1/* 2 * Copyright (c) 2022-2023 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15#include "hvb_cmdline.h" 16#include "hvb_util.h" 17#include "hvb_cert.h" 18#include "hvb_rvt.h" 19#include "hvb_ops.h" 20#include "hvb.h" 21#include "hvb_sysdeps.h" 22#include "hvb_crypto.h" 23 24static int cmdline_append_option(struct hvb_verified_data *vd, const char *key, const char *value) 25{ 26 uint64_t option_len = 0; 27 uint64_t key_len, value_len; 28 struct hvb_cmdline_data *cmdline = NULL; 29 30 if (vd == NULL || vd->cmdline.buf == NULL) 31 return 0; 32 33 cmdline = &vd->cmdline; 34 35 key_len = hvb_strlen(key); 36 value_len = hvb_strlen(value); 37 /* 2 for blank space and = */ 38 option_len = key_len + value_len + 2; 39 if (option_len > cmdline->max_size - cmdline->cur_pos - 1) 40 return 0; 41 42 /* append blank space */ 43 cmdline->buf[cmdline->cur_pos] = ' '; 44 cmdline->cur_pos++; 45 /* append key */ 46 hvb_memcpy(cmdline->buf + cmdline->cur_pos, key, key_len); 47 cmdline->cur_pos += key_len; 48 /* append = */ 49 cmdline->buf[cmdline->cur_pos] = '='; 50 cmdline->cur_pos++; 51 /* append value */ 52 hvb_memcpy(cmdline->buf + cmdline->cur_pos, value, value_len); 53 cmdline->cur_pos += value_len; 54 55 return 1; 56} 57 58static int hvb_append_version_cmdline(struct hvb_verified_data *vd, const char *key_value, 59 uint64_t version_major, uint64_t version_minor) 60{ 61 char major_digits[HVB_MAX_DIGITS_UINT64]; 62 char minor_digits[HVB_MAX_DIGITS_UINT64]; 63 char combined[HVB_MAX_DIGITS_UINT64 * 2 + 1]; 64 uint64_t num_major_digits, num_minor_digits; 65 66 num_major_digits = hvb_uint64_to_base10(version_major, major_digits); 67 num_minor_digits = hvb_uint64_to_base10(version_minor, minor_digits); 68 69 hvb_memcpy(combined, major_digits, num_major_digits); 70 combined[num_major_digits] = '.'; 71 hvb_memcpy(combined + num_major_digits + 1, minor_digits, num_minor_digits); 72 combined[num_major_digits + 1 + num_minor_digits] = '\0'; 73 74 return cmdline_append_option(vd, key_value, combined); 75} 76 77static int cmdline_append_uint64_base10(struct hvb_verified_data *vd, const char *key, uint64_t value) 78{ 79 char digits[HVB_MAX_DIGITS_UINT64]; 80 81 hvb_uint64_to_base10(value, digits); 82 83 return cmdline_append_option(vd, key, digits); 84} 85 86static int cmdline_append_hex(struct hvb_verified_data *vd, const char* key, 87 const uint8_t *data, uint64_t data_len) 88{ 89 int ret; 90 char *hex_data = hvb_bin2hex(data, data_len); 91 92 if (hex_data == NULL) { 93 return 0; 94 } 95 96 ret = cmdline_append_option(vd, key, hex_data); 97 hvb_free(hex_data); 98 99 return ret; 100} 101 102enum hvb_errno hvb_creat_cmdline(struct hvb_ops *ops, struct hvb_verified_data *vd) 103{ 104 hvb_return_hvb_err_if_null(ops); 105 hvb_return_hvb_err_if_null(vd); 106 107 enum hvb_errno ret = HVB_OK; 108 enum hvb_io_errno io_ret = HVB_IO_OK; 109 bool device_locked = false; 110 ret = check_hvb_ops(ops); 111 if (ret != HVB_OK) { 112 hvb_print("error, check ops\n"); 113 return HVB_ERROR_INVALID_ARGUMENT; 114 } 115 116 /* set ohos.boot.hvb.version. */ 117 if (!hvb_append_version_cmdline(vd, HVB_CMDLINE_VERSION, 118 HVB_VERSION_MAJOR, HVB_VERSION_MINOR)) { 119 ret = HVB_ERROR_OOM; 120 goto fail; 121 } 122 123 /* set ohos.boot.device_state to "locked" or "unlocked". */ 124 io_ret = ops->read_lock_state(ops, &device_locked); 125 if (io_ret == HVB_IO_ERROR_OOM) { 126 ret = HVB_ERROR_OOM; 127 goto fail; 128 } else if (io_ret != HVB_IO_OK) { 129 hvb_print("Error getting device state.\n"); 130 ret = HVB_ERROR_IO; 131 goto fail; 132 } 133 134 if (!cmdline_append_option(vd, HVB_CMDLINE_DEV_STATE, 135 device_locked ? "locked" : "unlocked")) { 136 ret = HVB_ERROR_OOM; 137 goto fail; 138 } 139 140 /* 141 * set ohos.boot.hvb.{hash_algo, size, digest} - use same hash 142 * function as is used to sign rvt. 143 */ 144 uint8_t rvt_digest[HVB_SHA256_DIGEST_BYTES] = {0}; 145 uint64_t rvt_size = 0; 146 for (uint64_t n = 0; n < vd->num_loaded_certs; n++) { 147 rvt_size += vd->certs[n].data.size; 148 } 149 150 if (hvb_calculate_certs_digest(vd, rvt_digest) != HVB_OK) { 151 hvb_print("Error calculate rvt digest.\n"); 152 ret = HVB_ERROR_OOM; 153 goto fail; 154 } 155 156 if (!cmdline_append_option(vd, HVB_CMDLINE_HASH_ALG, "sha256") || 157 !cmdline_append_uint64_base10(vd, HVB_CMDLINE_RVT_SIZE, rvt_size) || 158 !cmdline_append_hex(vd, HVB_CMDLINE_CERT_DIGEST, rvt_digest, HVB_SHA256_DIGEST_BYTES)) { 159 ret = HVB_ERROR_OOM; 160 goto fail; 161 } 162 163fail: 164 return ret; 165} 166