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 <stdio.h> 16#include <stdlib.h> 17#include "hvb_footer.h" 18#include "hvb_crypto.h" 19#include "hvb_ops.h" 20#include "hvb_rvt.h" 21#include "hvb_cert.h" 22#include "hvb_sysdeps.h" 23#include "hvb_util.h" 24#include "hvb_cmdline.h" 25#include "hvb.h" 26 27struct hvb_verified_data *hvb_init_verified_data(void) 28{ 29 struct hvb_verified_data *vd = NULL; 30 31 vd = hvb_calloc(sizeof(*vd)); 32 if (!vd) { 33 hvb_print("malloc verified_data fail\n"); 34 return NULL; 35 } 36 37 vd->certs = hvb_calloc(sizeof(struct hvb_cert_data) * HVB_MAX_NUMBER_OF_LOADED_CERTS); 38 if (!vd->certs) { 39 hvb_print("malloc certs fail\n"); 40 goto fail; 41 } 42 43 vd->images = hvb_calloc(sizeof(struct hvb_image_data) * HVB_MAX_NUMBER_OF_LOADED_IMAGES); 44 if (!vd->images) { 45 hvb_print("malloc images fail\n"); 46 goto fail; 47 } 48 49 vd->num_loaded_certs = 0; 50 vd->num_loaded_images = 0; 51 52 vd->cmdline.buf = hvb_calloc(CMD_LINE_SIZE); 53 if (!vd->cmdline.buf) { 54 hvb_print("malloc cmdline fail\n"); 55 goto fail; 56 } 57 58 vd->cmdline.cur_pos = 0; 59 vd->cmdline.max_size = CMD_LINE_SIZE; 60 61 vd->key_len = 0; 62 63 return vd; 64 65fail: 66 hvb_chain_verify_data_free(vd); 67 hvb_free(vd); 68 vd = NULL; 69 return vd; 70} 71 72static enum hvb_errno hvb_rvt_verify_root(struct hvb_ops *ops, const char *ptn, 73 const char *const *ptn_list, 74 struct hvb_verified_data *vd) 75{ 76 enum hvb_errno ret = HVB_OK; 77 enum hvb_io_errno io_ret = HVB_IO_OK; 78 bool is_trusted = false; 79 struct hvb_buf cert_pubk = {0}; 80 81 ret = footer_init_desc(ops, ptn, ptn_list, &cert_pubk, vd); 82 if (ret != HVB_OK) { 83 hvb_printv("error verity partition: ", ptn, "\n", NULL); 84 goto fail; 85 } 86 87 io_ret = ops->valid_rvt_key(ops, cert_pubk.addr, cert_pubk.size, NULL, 0, &is_trusted); 88 if (io_ret != HVB_IO_OK) { 89 ret = HVB_ERROR_PUBLIC_KEY_REJECTED; 90 hvb_print("error, rvt public key invalid\n"); 91 goto fail; 92 } 93 94 if (is_trusted == false) { 95 ret = HVB_ERROR_PUBLIC_KEY_REJECTED; 96 hvb_print("error, rvt public key rejected\n"); 97 goto fail; 98 } 99 100fail: 101 return ret; 102} 103 104static struct hvb_buf *hvb_get_partition_image(struct hvb_verified_data *vd, const char *ptn) 105{ 106 struct hvb_image_data *p = vd->images; 107 struct hvb_image_data *end = p + vd->num_loaded_images; 108 size_t name_len = hvb_strnlen(ptn, HVB_MAX_PARTITION_NAME_LEN); 109 if (name_len >= HVB_MAX_PARTITION_NAME_LEN) { 110 hvb_print("invalid ptn name len\n"); 111 return NULL; 112 } 113 114 for (; p < end; p++) { 115 if (hvb_strnlen(p->partition_name, HVB_MAX_PARTITION_NAME_LEN) == name_len && 116 hvb_strncmp(ptn, p->partition_name, HVB_MAX_PARTITION_NAME_LEN) == 0) { 117 return &p->data; 118 } 119 } 120 121 return NULL; 122} 123 124static bool hvb_buf_equal(const struct hvb_buf *buf1, const struct hvb_buf *buf2) 125{ 126 return buf1->size == buf2->size && hvb_memcmp(buf1->addr, buf2->addr, buf1->size) == 0; 127} 128 129static enum hvb_errno hvb_walk_verify_nodes(struct hvb_ops *ops, const char *const *ptn_list, 130 struct hvb_buf *rvt, struct hvb_verified_data *vd) 131{ 132 enum hvb_errno ret = HVB_OK; 133 uint32_t i, nodes_num; 134 struct hvb_buf pubk_descs; 135 struct rvt_pubk_desc desc; 136 struct hvb_buf expected_pubk; 137 struct hvb_buf cert_pubk; 138 struct rvt_image_header header; 139 uint64_t desc_size; 140 141 desc_size = sizeof(desc) - (PUBKEY_LEN - vd->key_len); 142 ret = hvb_rvt_head_parser(rvt, &header, desc_size); 143 if (ret != HVB_OK) { 144 hvb_print("error, parse rvt header.\n"); 145 goto fail; 146 } 147 148 nodes_num = header.verity_num; 149 ret = hvb_rvt_get_pubk_desc(rvt, &pubk_descs); 150 if (ret != HVB_OK) { 151 hvb_print("error, pubk descs.\n"); 152 goto fail; 153 } 154 155 for (i = 0; i < nodes_num; i++) { 156 ret = hvb_rvt_pubk_desc_parser(&pubk_descs, &desc, desc_size); 157 if (ret != HVB_OK) { 158 hvb_print("errror, parser rvt k descs\n"); 159 goto fail; 160 } 161 162 ret = hvb_rvt_get_pubk_buf(&expected_pubk, rvt, &desc); 163 if (ret != HVB_OK) { 164 hvb_print("errror, get pubk buf\n"); 165 goto fail; 166 } 167 168 ret = footer_init_desc(ops, &desc.name[0], ptn_list, &cert_pubk, vd); 169 if (ret != HVB_OK) { 170 hvb_printv("error, verity partition: ", desc.name, "\n", NULL); 171 goto fail; 172 } 173 174 if (hvb_buf_equal(&expected_pubk, &cert_pubk) != true) { 175 ret = HVB_ERROR_PUBLIC_KEY_REJECTED; 176 hvb_printv("error, compare public key: ", desc.name, "\n", NULL); 177 goto fail; 178 } 179 180 pubk_descs.addr += desc_size; 181 } 182 183fail: 184 return ret; 185} 186 187static char const **hash_ptn_list_add_rvt(const char *const *hash_ptn_list, const char *rvt_ptn) 188{ 189 size_t n; 190 bool need_add_rvt = true; 191 char const **ptn = NULL; 192 size_t num_parttions = 0; 193 194 if (hash_ptn_list != NULL) { 195 while (hash_ptn_list[num_parttions] != NULL) { 196 num_parttions++; 197 } 198 } 199 200 num_parttions += REQUEST_LIST_LEN; 201 202 ptn = (char const **)hvb_calloc(num_parttions * sizeof(char *)); 203 if (ptn == NULL) { 204 hvb_print("error, alloc ptn\n"); 205 return NULL; 206 } 207 208 for (n = 0; n < num_parttions - REQUEST_LIST_LEN; n++) { 209 ptn[n] = hash_ptn_list[n]; 210 if (hvb_strncmp(ptn[n], rvt_ptn, HVB_MAX_PARTITION_NAME_LEN) == 0) { 211 need_add_rvt = false; 212 } 213 } 214 215 if (need_add_rvt) { 216 ptn[num_parttions - REQUEST_LIST_LEN] = rvt_ptn; 217 } 218 219 return ptn; 220} 221 222enum hvb_errno hvb_chain_verify(struct hvb_ops *ops, 223 const char *rvt_ptn, 224 const char *const *hash_ptn_list, 225 struct hvb_verified_data **out_vd) 226{ 227 enum hvb_errno ret = HVB_OK; 228 struct hvb_buf *rvt_image = NULL; 229 struct hvb_verified_data *vd = NULL; 230 char const **ptn_list = NULL; 231 232 hvb_return_hvb_err_if_null(ops); 233 hvb_return_hvb_err_if_null(rvt_ptn); 234 hvb_return_hvb_err_if_null(out_vd); 235 ret = check_hvb_ops(ops); 236 if (ret != HVB_OK) { 237 hvb_print("error, check ops\n"); 238 return HVB_ERROR_INVALID_ARGUMENT; 239 } 240 241 if (hvb_strnlen(rvt_ptn, HVB_MAX_PARTITION_NAME_LEN) >= HVB_MAX_PARTITION_NAME_LEN) { 242 hvb_print("error, check rvt partition name\n"); 243 return HVB_ERROR_INVALID_ARGUMENT; 244 } 245 246 ptn_list = hash_ptn_list_add_rvt(hash_ptn_list, rvt_ptn); 247 if (ptn_list == NULL) { 248 hvb_print("error, add rvt\n"); 249 return HVB_ERROR_OOM; 250 } 251 252 vd = hvb_init_verified_data(); 253 if (!vd) { 254 hvb_print("malloc verified_data fail\n"); 255 ret = HVB_ERROR_OOM; 256 goto fail; 257 } 258 259 /* verity rvt cert */ 260 ret = hvb_rvt_verify_root(ops, rvt_ptn, ptn_list, vd); 261 if (ret != HVB_OK) { 262 hvb_print("error, verity rvt partition.\n"); 263 goto fail; 264 } 265 266 /* get rvt image */ 267 rvt_image = hvb_get_partition_image(vd, rvt_ptn); 268 if (!rvt_image) { 269 hvb_print("error, get rvt ptn.\n"); 270 ret = HVB_ERROR_OOM; 271 goto fail; 272 } 273 274 /* walk verify all nodes from rvt */ 275 ret = hvb_walk_verify_nodes(ops, ptn_list, rvt_image, vd); 276 if (ret != HVB_OK) { 277 hvb_print("error, walk nodes.\n"); 278 goto fail; 279 } 280 281 /* creat cmdline info */ 282 ret = hvb_creat_cmdline(ops, vd); 283 if (ret != HVB_OK) { 284 hvb_print("error, create cmdline.\n"); 285 goto fail; 286 } 287 288 *out_vd = vd; 289 290fail: 291 if (vd != NULL && ret != HVB_OK) { 292 hvb_chain_verify_data_free(vd); 293 hvb_free(vd); 294 } 295 296 hvb_free(ptn_list); 297 298 return ret; 299} 300 301void hvb_chain_verify_data_free(struct hvb_verified_data *vd) 302{ 303 uint64_t n; 304 305 if (vd == NULL) { 306 hvb_print("vd is NULL, do nothing\n"); 307 return; 308 } 309 310 for (n = 0; n < vd->num_loaded_certs && vd->certs; n++) { 311 if (vd->certs[n].data.addr != NULL) 312 hvb_free(vd->certs[n].data.addr); 313 314 if (vd->certs[n].partition_name != NULL) { 315 hvb_free(vd->certs[n].partition_name); 316 } 317 } 318 319 if (vd->certs != NULL) { 320 hvb_free(vd->certs); 321 } 322 323 for (n = 0; n < vd->num_loaded_images && vd->images; n++) { 324 if (vd->images[n].data.addr != NULL) 325 hvb_free(vd->images[n].data.addr); 326 327 if (vd->images[n].partition_name != NULL) 328 hvb_free(vd->images[n].partition_name); 329 } 330 331 if (vd->images != NULL) { 332 hvb_free(vd->images); 333 } 334 335 if (vd->cmdline.buf != NULL) { 336 hvb_free(vd->cmdline.buf); 337 } 338 339 hvb_memset((uint8_t *)vd, 0, sizeof(*vd)); 340} 341