17310c0d0Sopenharmony_ci/* 27310c0d0Sopenharmony_ci * Copyright (c) 2022-2023 Huawei Device Co., Ltd. 37310c0d0Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 47310c0d0Sopenharmony_ci * you may not use this file except in compliance with the License. 57310c0d0Sopenharmony_ci * You may obtain a copy of the License at 67310c0d0Sopenharmony_ci * 77310c0d0Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 87310c0d0Sopenharmony_ci * 97310c0d0Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 107310c0d0Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 117310c0d0Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 127310c0d0Sopenharmony_ci * See the License for the specific language governing permissions and 137310c0d0Sopenharmony_ci * limitations under the License. 147310c0d0Sopenharmony_ci */ 157310c0d0Sopenharmony_ci#include "hvb_cmdline.h" 167310c0d0Sopenharmony_ci#include "hvb_util.h" 177310c0d0Sopenharmony_ci#include "hvb_cert.h" 187310c0d0Sopenharmony_ci#include "hvb_rvt.h" 197310c0d0Sopenharmony_ci#include "hvb_ops.h" 207310c0d0Sopenharmony_ci#include "hvb.h" 217310c0d0Sopenharmony_ci#include "hvb_sysdeps.h" 227310c0d0Sopenharmony_ci#include "hvb_crypto.h" 237310c0d0Sopenharmony_ci 247310c0d0Sopenharmony_cistatic int cmdline_append_option(struct hvb_verified_data *vd, const char *key, const char *value) 257310c0d0Sopenharmony_ci{ 267310c0d0Sopenharmony_ci uint64_t option_len = 0; 277310c0d0Sopenharmony_ci uint64_t key_len, value_len; 287310c0d0Sopenharmony_ci struct hvb_cmdline_data *cmdline = NULL; 297310c0d0Sopenharmony_ci 307310c0d0Sopenharmony_ci if (vd == NULL || vd->cmdline.buf == NULL) 317310c0d0Sopenharmony_ci return 0; 327310c0d0Sopenharmony_ci 337310c0d0Sopenharmony_ci cmdline = &vd->cmdline; 347310c0d0Sopenharmony_ci 357310c0d0Sopenharmony_ci key_len = hvb_strlen(key); 367310c0d0Sopenharmony_ci value_len = hvb_strlen(value); 377310c0d0Sopenharmony_ci /* 2 for blank space and = */ 387310c0d0Sopenharmony_ci option_len = key_len + value_len + 2; 397310c0d0Sopenharmony_ci if (option_len > cmdline->max_size - cmdline->cur_pos - 1) 407310c0d0Sopenharmony_ci return 0; 417310c0d0Sopenharmony_ci 427310c0d0Sopenharmony_ci /* append blank space */ 437310c0d0Sopenharmony_ci cmdline->buf[cmdline->cur_pos] = ' '; 447310c0d0Sopenharmony_ci cmdline->cur_pos++; 457310c0d0Sopenharmony_ci /* append key */ 467310c0d0Sopenharmony_ci hvb_memcpy(cmdline->buf + cmdline->cur_pos, key, key_len); 477310c0d0Sopenharmony_ci cmdline->cur_pos += key_len; 487310c0d0Sopenharmony_ci /* append = */ 497310c0d0Sopenharmony_ci cmdline->buf[cmdline->cur_pos] = '='; 507310c0d0Sopenharmony_ci cmdline->cur_pos++; 517310c0d0Sopenharmony_ci /* append value */ 527310c0d0Sopenharmony_ci hvb_memcpy(cmdline->buf + cmdline->cur_pos, value, value_len); 537310c0d0Sopenharmony_ci cmdline->cur_pos += value_len; 547310c0d0Sopenharmony_ci 557310c0d0Sopenharmony_ci return 1; 567310c0d0Sopenharmony_ci} 577310c0d0Sopenharmony_ci 587310c0d0Sopenharmony_cistatic int hvb_append_version_cmdline(struct hvb_verified_data *vd, const char *key_value, 597310c0d0Sopenharmony_ci uint64_t version_major, uint64_t version_minor) 607310c0d0Sopenharmony_ci{ 617310c0d0Sopenharmony_ci char major_digits[HVB_MAX_DIGITS_UINT64]; 627310c0d0Sopenharmony_ci char minor_digits[HVB_MAX_DIGITS_UINT64]; 637310c0d0Sopenharmony_ci char combined[HVB_MAX_DIGITS_UINT64 * 2 + 1]; 647310c0d0Sopenharmony_ci uint64_t num_major_digits, num_minor_digits; 657310c0d0Sopenharmony_ci 667310c0d0Sopenharmony_ci num_major_digits = hvb_uint64_to_base10(version_major, major_digits); 677310c0d0Sopenharmony_ci num_minor_digits = hvb_uint64_to_base10(version_minor, minor_digits); 687310c0d0Sopenharmony_ci 697310c0d0Sopenharmony_ci hvb_memcpy(combined, major_digits, num_major_digits); 707310c0d0Sopenharmony_ci combined[num_major_digits] = '.'; 717310c0d0Sopenharmony_ci hvb_memcpy(combined + num_major_digits + 1, minor_digits, num_minor_digits); 727310c0d0Sopenharmony_ci combined[num_major_digits + 1 + num_minor_digits] = '\0'; 737310c0d0Sopenharmony_ci 747310c0d0Sopenharmony_ci return cmdline_append_option(vd, key_value, combined); 757310c0d0Sopenharmony_ci} 767310c0d0Sopenharmony_ci 777310c0d0Sopenharmony_cistatic int cmdline_append_uint64_base10(struct hvb_verified_data *vd, const char *key, uint64_t value) 787310c0d0Sopenharmony_ci{ 797310c0d0Sopenharmony_ci char digits[HVB_MAX_DIGITS_UINT64]; 807310c0d0Sopenharmony_ci 817310c0d0Sopenharmony_ci hvb_uint64_to_base10(value, digits); 827310c0d0Sopenharmony_ci 837310c0d0Sopenharmony_ci return cmdline_append_option(vd, key, digits); 847310c0d0Sopenharmony_ci} 857310c0d0Sopenharmony_ci 867310c0d0Sopenharmony_cistatic int cmdline_append_hex(struct hvb_verified_data *vd, const char* key, 877310c0d0Sopenharmony_ci const uint8_t *data, uint64_t data_len) 887310c0d0Sopenharmony_ci{ 897310c0d0Sopenharmony_ci int ret; 907310c0d0Sopenharmony_ci char *hex_data = hvb_bin2hex(data, data_len); 917310c0d0Sopenharmony_ci 927310c0d0Sopenharmony_ci if (hex_data == NULL) { 937310c0d0Sopenharmony_ci return 0; 947310c0d0Sopenharmony_ci } 957310c0d0Sopenharmony_ci 967310c0d0Sopenharmony_ci ret = cmdline_append_option(vd, key, hex_data); 977310c0d0Sopenharmony_ci hvb_free(hex_data); 987310c0d0Sopenharmony_ci 997310c0d0Sopenharmony_ci return ret; 1007310c0d0Sopenharmony_ci} 1017310c0d0Sopenharmony_ci 1027310c0d0Sopenharmony_cienum hvb_errno hvb_creat_cmdline(struct hvb_ops *ops, struct hvb_verified_data *vd) 1037310c0d0Sopenharmony_ci{ 1047310c0d0Sopenharmony_ci hvb_return_hvb_err_if_null(ops); 1057310c0d0Sopenharmony_ci hvb_return_hvb_err_if_null(vd); 1067310c0d0Sopenharmony_ci 1077310c0d0Sopenharmony_ci enum hvb_errno ret = HVB_OK; 1087310c0d0Sopenharmony_ci enum hvb_io_errno io_ret = HVB_IO_OK; 1097310c0d0Sopenharmony_ci bool device_locked = false; 1107310c0d0Sopenharmony_ci ret = check_hvb_ops(ops); 1117310c0d0Sopenharmony_ci if (ret != HVB_OK) { 1127310c0d0Sopenharmony_ci hvb_print("error, check ops\n"); 1137310c0d0Sopenharmony_ci return HVB_ERROR_INVALID_ARGUMENT; 1147310c0d0Sopenharmony_ci } 1157310c0d0Sopenharmony_ci 1167310c0d0Sopenharmony_ci /* set ohos.boot.hvb.version. */ 1177310c0d0Sopenharmony_ci if (!hvb_append_version_cmdline(vd, HVB_CMDLINE_VERSION, 1187310c0d0Sopenharmony_ci HVB_VERSION_MAJOR, HVB_VERSION_MINOR)) { 1197310c0d0Sopenharmony_ci ret = HVB_ERROR_OOM; 1207310c0d0Sopenharmony_ci goto fail; 1217310c0d0Sopenharmony_ci } 1227310c0d0Sopenharmony_ci 1237310c0d0Sopenharmony_ci /* set ohos.boot.device_state to "locked" or "unlocked". */ 1247310c0d0Sopenharmony_ci io_ret = ops->read_lock_state(ops, &device_locked); 1257310c0d0Sopenharmony_ci if (io_ret == HVB_IO_ERROR_OOM) { 1267310c0d0Sopenharmony_ci ret = HVB_ERROR_OOM; 1277310c0d0Sopenharmony_ci goto fail; 1287310c0d0Sopenharmony_ci } else if (io_ret != HVB_IO_OK) { 1297310c0d0Sopenharmony_ci hvb_print("Error getting device state.\n"); 1307310c0d0Sopenharmony_ci ret = HVB_ERROR_IO; 1317310c0d0Sopenharmony_ci goto fail; 1327310c0d0Sopenharmony_ci } 1337310c0d0Sopenharmony_ci 1347310c0d0Sopenharmony_ci if (!cmdline_append_option(vd, HVB_CMDLINE_DEV_STATE, 1357310c0d0Sopenharmony_ci device_locked ? "locked" : "unlocked")) { 1367310c0d0Sopenharmony_ci ret = HVB_ERROR_OOM; 1377310c0d0Sopenharmony_ci goto fail; 1387310c0d0Sopenharmony_ci } 1397310c0d0Sopenharmony_ci 1407310c0d0Sopenharmony_ci /* 1417310c0d0Sopenharmony_ci * set ohos.boot.hvb.{hash_algo, size, digest} - use same hash 1427310c0d0Sopenharmony_ci * function as is used to sign rvt. 1437310c0d0Sopenharmony_ci */ 1447310c0d0Sopenharmony_ci uint8_t rvt_digest[HVB_SHA256_DIGEST_BYTES] = {0}; 1457310c0d0Sopenharmony_ci uint64_t rvt_size = 0; 1467310c0d0Sopenharmony_ci for (uint64_t n = 0; n < vd->num_loaded_certs; n++) { 1477310c0d0Sopenharmony_ci rvt_size += vd->certs[n].data.size; 1487310c0d0Sopenharmony_ci } 1497310c0d0Sopenharmony_ci 1507310c0d0Sopenharmony_ci if (hvb_calculate_certs_digest(vd, rvt_digest) != HVB_OK) { 1517310c0d0Sopenharmony_ci hvb_print("Error calculate rvt digest.\n"); 1527310c0d0Sopenharmony_ci ret = HVB_ERROR_OOM; 1537310c0d0Sopenharmony_ci goto fail; 1547310c0d0Sopenharmony_ci } 1557310c0d0Sopenharmony_ci 1567310c0d0Sopenharmony_ci if (!cmdline_append_option(vd, HVB_CMDLINE_HASH_ALG, "sha256") || 1577310c0d0Sopenharmony_ci !cmdline_append_uint64_base10(vd, HVB_CMDLINE_RVT_SIZE, rvt_size) || 1587310c0d0Sopenharmony_ci !cmdline_append_hex(vd, HVB_CMDLINE_CERT_DIGEST, rvt_digest, HVB_SHA256_DIGEST_BYTES)) { 1597310c0d0Sopenharmony_ci ret = HVB_ERROR_OOM; 1607310c0d0Sopenharmony_ci goto fail; 1617310c0d0Sopenharmony_ci } 1627310c0d0Sopenharmony_ci 1637310c0d0Sopenharmony_cifail: 1647310c0d0Sopenharmony_ci return ret; 1657310c0d0Sopenharmony_ci} 166