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 <string.h> 18#include "hvb.h" 19#include "hvb_util.h" 20#include "hvb_crypto.h" 21#include "hvb_sysdeps.h" 22#include "hvb_cert.h" 23 24 25static bool hvb_need_verify_hash(const char *const *hash_ptn_list, const char *ptn) 26{ 27 size_t n; 28 size_t ptn_len = hvb_strnlen(ptn, HVB_MAX_PARTITION_NAME_LEN); 29 if (ptn_len >= HVB_MAX_PARTITION_NAME_LEN) { 30 hvb_print("invalid ptn name len\n"); 31 return false; 32 } 33 34 if (hash_ptn_list == NULL) 35 return false; 36 37 for (n = 0; hash_ptn_list[n] != NULL; n++) { 38 if (hvb_strnlen(hash_ptn_list[n], HVB_MAX_PARTITION_NAME_LEN) == ptn_len && 39 hvb_strncmp(hash_ptn_list[n], ptn, HVB_MAX_PARTITION_NAME_LEN) == 0) { 40 return true; 41 } 42 } 43 44 return false; 45} 46 47static uint64_t get_hash_size(uint32_t algo) 48{ 49 switch (algo) { 50 case 0: // SHA256_RSA3072 51 case 1: // SHA256_RSA4096 52 case 2: // SHA256_RSA2048 53 return 32; 54 default: 55 return 0; 56 } 57 58 return 0; 59} 60 61static enum hvb_errno hvb_compare_hash(struct hvb_buf *digest_buf, struct hvb_buf *msg_buf, 62 struct hvb_buf *salt_buf, uint32_t hash_algo) 63{ 64 int hash_err; 65 struct hash_ctx_t ctx = {0}; 66 uint8_t computed_hash[HVB_HASH_MAX_BYTES] = {0}; 67 68 uint32_t computed_hash_size = get_hash_size(hash_algo); 69 if (computed_hash_size != digest_buf->size) { 70 hvb_print("computed_hash_size error\n"); 71 return HVB_ERROR_INVALID_ARGUMENT; 72 } 73 74 hash_err = hash_ctx_init(&ctx, hash_algo); 75 if (hash_err != HASH_OK) { 76 hvb_print("hash init error\n"); 77 return HVB_ERROR_VERIFY_HASH; 78 } 79 80 hash_err = hash_calc_update(&ctx, salt_buf->addr, salt_buf->size); 81 if (hash_err != HASH_OK) { 82 hvb_print("hash updata salt error\n"); 83 return HVB_ERROR_VERIFY_HASH; 84 } 85 86 hash_err = hash_calc_do_final(&ctx, msg_buf->addr, msg_buf->size, &computed_hash[0], digest_buf->size); 87 if (hash_err != HASH_OK) { 88 hvb_print("hash updata msg error\n"); 89 return HVB_ERROR_VERIFY_HASH; 90 } 91 92 if (hvb_memcmp(&computed_hash[0], digest_buf->addr, computed_hash_size) != 0) { 93 hvb_print("compare fail\n"); 94 return HVB_ERROR_VERIFY_HASH; 95 } 96 97 return HVB_OK; 98} 99 100static enum hvb_errno hash_image_init_desc(struct hvb_ops *ops, const char *ptn, 101 struct hvb_cert *cert, const char *const *hash_ptn_list, 102 struct hvb_verified_data *vd) 103{ 104 enum hvb_io_errno io_ret = HVB_IO_OK; 105 enum hvb_errno ret = HVB_OK; 106 struct hvb_buf image_buf = {NULL, 0}; 107 struct hvb_buf salt_buf = {cert->hash_payload.salt, cert->salt_size}; 108 struct hvb_buf digest_buf = {cert->hash_payload.digest, cert->digest_size}; 109 uint64_t read_bytes = 0; 110 struct hvb_image_data *image = NULL; 111 enum hvb_image_type image_type = (enum hvb_image_type)cert->verity_type; 112 113 if (image_type != HVB_IMAGE_TYPE_HASH || !hvb_need_verify_hash(hash_ptn_list, ptn)) { 114 hvb_printv(ptn, ": no need verify hash image.\n", NULL); 115 return HVB_OK; 116 } 117 118 image_buf.size = cert->image_original_len; 119 image_buf.addr = hvb_malloc(image_buf.size); 120 if (image_buf.addr == NULL) { 121 hvb_print("malloc image_buf fail\n"); 122 return HVB_ERROR_OOM; 123 } 124 125 io_ret = ops->read_partition(ops, ptn, 0, image_buf.size, image_buf.addr, &read_bytes); 126 if (io_ret != HVB_IO_OK) { 127 hvb_printv(ptn, ": Error loading data.\n", NULL); 128 ret = HVB_ERROR_IO; 129 goto out; 130 } 131 if (read_bytes != image_buf.size) { 132 hvb_printv(ptn, ": Read incorrect number of bytes from.\n", NULL); 133 ret = HVB_ERROR_IO; 134 goto out; 135 } 136 137 ret = hvb_compare_hash(&digest_buf, &image_buf, &salt_buf, cert->hash_algo); 138 if (ret != HVB_OK) { 139 hvb_printv(ptn, ": compare hash error.\n", NULL); 140 goto out; 141 } 142 143 if (vd->num_loaded_images >= HVB_MAX_NUMBER_OF_LOADED_IMAGES) { 144 hvb_print("error, too many images\n"); 145 ret = HVB_ERROR_OOM; 146 goto out; 147 } 148 149 image = &vd->images[vd->num_loaded_images++]; 150 image->partition_name = hvb_strdup(ptn); 151 image->data = image_buf; 152 image->preloaded = true; 153 154 return HVB_OK; 155 156out: 157 if (image_buf.addr != NULL) 158 hvb_free(image_buf.addr); 159 160 return ret; 161} 162 163static bool _decode_octets(struct hvb_buf *buf, size_t size, uint8_t **p, uint8_t *end) 164{ 165 /* check range */ 166 if (*p + size > end || *p + size < *p) 167 return false; 168 169 buf->addr = *p; 170 buf->size = size; 171 172 /* forward move */ 173 *p += size; 174 175 return true; 176} 177 178static enum hvb_errno _hvb_cert_payload_parser(struct hvb_cert *cert, uint8_t **p, uint8_t *end) 179{ 180 struct hvb_buf buf; 181 struct hash_payload *payload = &cert->hash_payload; 182 183 if (!_decode_octets(&buf, cert->salt_size, p, end)) { 184 hvb_print("error, dc salt.\n"); 185 return HVB_ERROR_INVALID_CERT_FORMAT; 186 } 187 payload->salt = buf.addr; 188 189 if (!_decode_octets(&buf, cert->digest_size, p, end)) { 190 hvb_print("error, dc digest.\n"); 191 return HVB_ERROR_INVALID_CERT_FORMAT; 192 } 193 payload->digest = buf.addr; 194 195 return HVB_OK; 196} 197 198static enum hvb_errno _hvb_cert_payload_parser_v2(struct hvb_cert *cert, uint8_t **p, uint8_t *end, uint8_t *header) 199{ 200 struct hash_payload *payload = &cert->hash_payload; 201 uint8_t *cur_header; 202 203 if (header + cert->salt_offset > end || header + cert->salt_offset <= header) { 204 hvb_print("error, illegal salt offset.\n"); 205 return HVB_ERROR_INVALID_CERT_FORMAT; 206 } 207 cur_header = header + cert->salt_offset; 208 209 if (cur_header + cert->salt_size > end || cur_header + cert->salt_size <= cur_header) { 210 hvb_print("error, dc salt.\n"); 211 return HVB_ERROR_INVALID_CERT_FORMAT; 212 } 213 payload->salt = cur_header; 214 215 if (header + cert->digest_offset > end || header + cert->digest_offset <= header) { 216 hvb_print("error, illegal digest offset.\n"); 217 return HVB_ERROR_INVALID_CERT_FORMAT; 218 } 219 cur_header = header + cert->digest_offset; 220 221 if (cur_header + cert->digest_size > end || cur_header + cert->digest_size <= cur_header) { 222 hvb_print("error, dc digest.\n"); 223 return HVB_ERROR_INVALID_CERT_FORMAT; 224 } 225 payload->digest = cur_header; 226 *p = cur_header + cert->digest_size; 227 228 return HVB_OK; 229} 230 231static enum hvb_errno _hvb_cert_signature_parser(struct hvb_cert *cert, uint8_t **p, uint8_t *end) 232{ 233 struct hvb_buf buf; 234 struct hvb_sign_info *sign_info = &cert->signature_info; 235 size_t cp_size = hvb_offsetof(struct hvb_sign_info, pubk); 236 237 if (!_decode_octets(&buf, cp_size, p, end)) { 238 hvb_print("error, dc sign info const.\n"); 239 return HVB_ERROR_INVALID_CERT_FORMAT; 240 } 241 if (hvb_memcpy_s(&cert->signature_info, sizeof(cert->signature_info), buf.addr, cp_size) != 0) { 242 hvb_print("error, copy dc sign info const.\n"); 243 return HVB_ERROR_OOM; 244 } 245 246 if (!_decode_octets(&buf, sign_info->pubkey_len, p, end)) { 247 hvb_print("error, dc pubk.\n"); 248 return HVB_ERROR_INVALID_CERT_FORMAT; 249 } 250 if (hvb_memcpy_s(&sign_info->pubk, sizeof(sign_info->pubk), &buf, sizeof(buf)) != 0) { 251 hvb_print("error, copy dc pubk.\n"); 252 return HVB_ERROR_OOM; 253 } 254 255 if (!_decode_octets(&buf, sign_info->signature_len, p, end)) { 256 hvb_print("error, dc sign.\n"); 257 return HVB_ERROR_INVALID_CERT_FORMAT; 258 } 259 if (hvb_memcpy_s(&sign_info->sign, sizeof(sign_info->sign), &buf, sizeof(buf)) != 0) { 260 hvb_print("error, copy dc sign.\n"); 261 return HVB_ERROR_OOM; 262 } 263 264 return HVB_OK; 265} 266 267static enum hvb_errno _hvb_cert_signature_parser_v2(struct hvb_cert *cert, uint8_t **p, uint8_t *end, uint8_t *header) 268{ 269 struct hvb_buf buf; 270 struct hvb_sign_info *sign_info = &cert->signature_info; 271 size_t cp_size = hvb_offsetof(struct hvb_sign_info, pubk); 272 uint8_t *cur_header; 273 274 if (!_decode_octets(&buf, cp_size, p, end)) { 275 hvb_print("error, dc sign info const.\n"); 276 return HVB_ERROR_INVALID_CERT_FORMAT; 277 } 278 if (hvb_memcpy_s(&cert->signature_info, sizeof(cert->signature_info), buf.addr, cp_size) != 0) { 279 hvb_print("error, copy dc sign info const.\n"); 280 return HVB_ERROR_OOM; 281 } 282 283 if (header + sign_info->pubkey_offset > end || header + sign_info->pubkey_offset <= header) { 284 hvb_print("error, illegal pubkey offset.\n"); 285 return HVB_ERROR_INVALID_CERT_FORMAT; 286 } 287 cur_header = header + sign_info->pubkey_offset; 288 289 if (cur_header + sign_info->pubkey_len > end || cur_header + sign_info->pubkey_len <= cur_header) { 290 hvb_print("error, dc pubkey.\n"); 291 return HVB_ERROR_INVALID_CERT_FORMAT; 292 } 293 sign_info->pubk.addr = cur_header; 294 sign_info->pubk.size = sign_info->pubkey_len; 295 296 if (header + sign_info->signature_offset > end || header + sign_info->signature_offset <= header) { 297 hvb_print("error, illegal signature offset.\n"); 298 return HVB_ERROR_INVALID_CERT_FORMAT; 299 } 300 cur_header = header + sign_info->signature_offset; 301 302 if (cur_header + sign_info->signature_len > end || cur_header + sign_info->signature_len <= cur_header) { 303 hvb_print("error, dc pubkey.\n"); 304 return HVB_ERROR_INVALID_CERT_FORMAT; 305 } 306 sign_info->sign.addr = cur_header; 307 sign_info->sign.size = sign_info->signature_len; 308 309 return HVB_OK; 310} 311 312enum hvb_errno hvb_cert_parser(struct hvb_cert *cert, struct hvb_buf *cert_buf) 313{ 314 hvb_return_hvb_err_if_null(cert); 315 hvb_return_hvb_err_if_null(cert_buf); 316 hvb_return_hvb_err_if_null(cert_buf->addr); 317 318 if (cert_buf->size > HVB_CERT_MAX_SIZE) { 319 hvb_print("invalid cert size.\n"); 320 return HVB_ERROR_INVALID_ARGUMENT; 321 } 322 323 enum hvb_errno ret = HVB_OK; 324 struct hvb_buf buf; 325 uint8_t *p = cert_buf->addr; 326 uint8_t *end = p + cert_buf->size; 327 uint8_t *header = p; 328 size_t header_size = hvb_offsetof(struct hvb_cert, hash_payload); 329 330 /* parse header */ 331 if (!_decode_octets(&buf, header_size, &p, end)) { 332 hvb_print("error, dc cert const.\n"); 333 return HVB_ERROR_INVALID_CERT_FORMAT; 334 } 335 if (hvb_memcpy_s(cert, sizeof(*cert), buf.addr, buf.size) != 0) { 336 hvb_print("error, copy dc cert const.\n"); 337 return HVB_ERROR_OOM; 338 } 339 340 if (cert->version_minor == 0) { 341 /* parse hash payload */ 342 ret = _hvb_cert_payload_parser(cert, &p, end); 343 if (ret != HVB_OK) { 344 hvb_print("error, pr hash payload.\n"); 345 return ret; 346 } 347 348 /* parse signature info */ 349 ret = _hvb_cert_signature_parser(cert, &p, end); 350 if (ret != HVB_OK) { 351 hvb_print("error, pr sign.\n"); 352 return ret; 353 } 354 } else if (cert->version_minor == 1) { 355 /* parse hash payload v2 */ 356 ret = _hvb_cert_payload_parser_v2(cert, &p, end, header); 357 if (ret != HVB_OK) { 358 hvb_print("error, pr hash payload.\n"); 359 return ret; 360 } 361 362 /* parse signature info v2 */ 363 ret = _hvb_cert_signature_parser_v2(cert, &p, end, header); 364 if (ret != HVB_OK) { 365 hvb_print("error, pr sign.\n"); 366 return ret; 367 } 368 } else { 369 hvb_print("error minor version\n"); 370 return HVB_ERROR_INVALID_ARGUMENT; 371 } 372 373 return HVB_OK; 374} 375 376static uint64_t hvb_buftouint64(uint8_t *p) 377{ 378 uint32_t i; 379 uint64_t val = 0; 380 381 for (i = 0; i < 8; i++, p++) { 382 val |= (((uint64_t)(*p)) << (i * 8)); 383 } 384 385 return val; 386} 387 388/* 389 * raw_pubk: |bit_length|n0|mod|p_rr| 390 */ 391static enum hvb_errno hvb_cert_pubk_parser(struct hvb_rsa_pubkey *pubk, struct hvb_buf *raw_pubk) 392{ 393 uint64_t bit_length = 0; 394 uint64_t n0 = 0; 395 struct hvb_buf mod; 396 struct hvb_buf p_rr; 397 struct hvb_buf buf; 398 399 uint8_t *p = raw_pubk->addr; 400 uint8_t *end = p + raw_pubk->size; 401 402 if (!_decode_octets(&buf, sizeof(uint64_t), &p, end)) { 403 hvb_print("error, dc bit_length.\n"); 404 return 1; 405 } 406 bit_length = hvb_buftouint64(buf.addr); 407 bit_length = hvb_be64toh(bit_length); 408 409 if (!_decode_octets(&buf, sizeof(uint64_t), &p, end)) { 410 hvb_print("error, dc n0.\n"); 411 return 1; 412 } 413 n0 = hvb_buftouint64(buf.addr); 414 n0 = hvb_be64toh(n0); 415 416 if (!_decode_octets(&mod, bit_length / 8, &p, end)) { 417 hvb_print("error, dc mod.\n"); 418 return 1; 419 } 420 421 if (!_decode_octets(&p_rr, bit_length / 8, &p, end)) { 422 hvb_print("error, dc p_rr\n"); 423 return 1; 424 } 425 426 pubk->width = bit_length; 427 pubk->e = 65537; 428 pubk->pn = mod.addr; 429 pubk->nlen = mod.size; 430 pubk->p_rr = p_rr.addr; 431 pubk->rlen = p_rr.size; 432 pubk->n_n0_i = n0; 433 434 return 0; 435} 436 437static enum hvb_errno hvb_verify_cert(struct hvb_buf *tbs, struct hvb_sign_info *sign_info, uint32_t salt_size) 438{ 439 int cry_err; 440 enum hvb_errno ret = HVB_OK; 441 uint32_t hash_len; 442 struct hvb_buf temp_buf; 443 uint8_t *hash = NULL; 444 struct hvb_rsa_pubkey pubk; 445 446 temp_buf = sign_info->pubk; 447 ret = hvb_cert_pubk_parser(&pubk, &temp_buf); 448 if (ret != HVB_OK) { 449 hvb_print("error, hvb cert pubk parser.\n"); 450 return ret; 451 } 452 453 hash_len = get_hash_size(sign_info->algorithm); 454 hash = hvb_malloc(hash_len); 455 if (!hash) { 456 hvb_print("hash malloc error:"); 457 return HVB_ERROR_OOM; 458 } 459 460 cry_err = hash_sha256_single(tbs->addr, tbs->size, hash, hash_len); 461 if (cry_err != 0) { 462 hvb_print("Error computed hash.\n"); 463 return HVB_ERROR_INVALID_ARGUMENT; 464 } 465 466 cry_err = hvb_rsa_verify_pss(&pubk, hash, hash_len, sign_info->sign.addr, sign_info->sign.size, salt_size); 467 if (cry_err != VERIFY_OK) { 468 hvb_print("hvb_rsa_verify_pss result error, signature mismatch\n"); 469 return HVB_ERROR_VERIFY_SIGN; 470 } 471 472 return HVB_OK; 473} 474 475static enum hvb_errno _check_rollback_index(struct hvb_ops *ops, struct hvb_cert *cert, struct hvb_verified_data *vd) 476{ 477 enum hvb_io_errno io_ret = HVB_IO_OK; 478 uint64_t stored_rollback_index = 0; 479 uint64_t cert_rollback_index = cert->rollback_index; 480 uint64_t rollback_location = cert->rollback_location; 481 482 if (rollback_location >= HVB_MAX_NUMBER_OF_ROLLBACK_INDEX_LOCATIONS) { 483 hvb_print("error, rollback_location too big\n"); 484 return HVB_ERROR_INVALID_CERT_FORMAT; 485 } 486 487 io_ret = ops->read_rollback(ops, rollback_location, &stored_rollback_index); 488 if (io_ret != HVB_IO_OK) { 489 hvb_print("error, read rollback idnex\n"); 490 return HVB_ERROR_IO; 491 } 492 493 if (cert_rollback_index < stored_rollback_index) { 494 hvb_print("error, cert rollback index is less than the stored\n"); 495 return HVB_ERROR_ROLLBACK_INDEX; 496 } 497 498 vd->rollback_indexes[rollback_location] = cert_rollback_index; 499 500 return HVB_OK; 501} 502 503enum hvb_errno cert_init_desc(struct hvb_ops *ops, const char *ptn, struct hvb_buf *cert_buf, 504 const char *const *hash_ptn_list, struct hvb_buf *out_pubk, 505 struct hvb_verified_data *vd) 506{ 507 hvb_return_hvb_err_if_null(ops); 508 hvb_return_hvb_err_if_null(ptn); 509 hvb_return_hvb_err_if_null(cert_buf); 510 hvb_return_hvb_err_if_null(cert_buf->addr); 511 hvb_return_hvb_err_if_null(out_pubk); 512 hvb_return_hvb_err_if_null(vd); 513 514 enum hvb_errno ret = HVB_OK; 515 ret = check_hvb_ops(ops); 516 if (ret != HVB_OK) { 517 hvb_print("error, check ops\n"); 518 return HVB_ERROR_INVALID_ARGUMENT; 519 } 520 if (hvb_strnlen(ptn, HVB_MAX_PARTITION_NAME_LEN) >= HVB_MAX_PARTITION_NAME_LEN) { 521 hvb_print("error, check partition name\n"); 522 return HVB_ERROR_INVALID_ARGUMENT; 523 } 524 525 struct hvb_cert cert = {0}; 526 struct hvb_buf tbs = {0}; 527 struct hvb_sign_info *sign_info = &cert.signature_info; 528 529 ret = hvb_cert_parser(&cert, cert_buf); 530 if (ret != HVB_OK) { 531 hvb_print("error, hvb cert parser.\n"); 532 return ret; 533 } 534 535 tbs.addr = cert_buf->addr; 536 tbs.size = sign_info->sign.addr - cert_buf->addr; 537 ret = hvb_verify_cert(&tbs, sign_info, cert.salt_size); 538 if (ret != HVB_OK) { 539 hvb_print("error, verify cert.\n"); 540 return ret; 541 } 542 543 ret = _check_rollback_index(ops, &cert, vd); 544 if (ret != HVB_OK) { 545 hvb_print("error, checkout index.\n"); 546 return ret; 547 } 548 549 ret = hash_image_init_desc(ops, ptn, &cert, hash_ptn_list, vd); 550 if (ret != HVB_OK) { 551 hvb_print("hash_image_init_desc result error\n"); 552 return ret; 553 } 554 555 *out_pubk = sign_info->pubk; 556 vd->key_len = out_pubk->size; 557 558 return ret; 559} 560