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 <stdio.h> 167310c0d0Sopenharmony_ci#include <stdlib.h> 177310c0d0Sopenharmony_ci#include <string.h> 187310c0d0Sopenharmony_ci#include "hvb.h" 197310c0d0Sopenharmony_ci#include "hvb_util.h" 207310c0d0Sopenharmony_ci#include "hvb_crypto.h" 217310c0d0Sopenharmony_ci#include "hvb_sysdeps.h" 227310c0d0Sopenharmony_ci#include "hvb_cert.h" 237310c0d0Sopenharmony_ci 247310c0d0Sopenharmony_ci 257310c0d0Sopenharmony_cistatic bool hvb_need_verify_hash(const char *const *hash_ptn_list, const char *ptn) 267310c0d0Sopenharmony_ci{ 277310c0d0Sopenharmony_ci size_t n; 287310c0d0Sopenharmony_ci size_t ptn_len = hvb_strnlen(ptn, HVB_MAX_PARTITION_NAME_LEN); 297310c0d0Sopenharmony_ci if (ptn_len >= HVB_MAX_PARTITION_NAME_LEN) { 307310c0d0Sopenharmony_ci hvb_print("invalid ptn name len\n"); 317310c0d0Sopenharmony_ci return false; 327310c0d0Sopenharmony_ci } 337310c0d0Sopenharmony_ci 347310c0d0Sopenharmony_ci if (hash_ptn_list == NULL) 357310c0d0Sopenharmony_ci return false; 367310c0d0Sopenharmony_ci 377310c0d0Sopenharmony_ci for (n = 0; hash_ptn_list[n] != NULL; n++) { 387310c0d0Sopenharmony_ci if (hvb_strnlen(hash_ptn_list[n], HVB_MAX_PARTITION_NAME_LEN) == ptn_len && 397310c0d0Sopenharmony_ci hvb_strncmp(hash_ptn_list[n], ptn, HVB_MAX_PARTITION_NAME_LEN) == 0) { 407310c0d0Sopenharmony_ci return true; 417310c0d0Sopenharmony_ci } 427310c0d0Sopenharmony_ci } 437310c0d0Sopenharmony_ci 447310c0d0Sopenharmony_ci return false; 457310c0d0Sopenharmony_ci} 467310c0d0Sopenharmony_ci 477310c0d0Sopenharmony_cistatic uint64_t get_hash_size(uint32_t algo) 487310c0d0Sopenharmony_ci{ 497310c0d0Sopenharmony_ci switch (algo) { 507310c0d0Sopenharmony_ci case 0: // SHA256_RSA3072 517310c0d0Sopenharmony_ci case 1: // SHA256_RSA4096 527310c0d0Sopenharmony_ci case 2: // SHA256_RSA2048 537310c0d0Sopenharmony_ci return 32; 547310c0d0Sopenharmony_ci default: 557310c0d0Sopenharmony_ci return 0; 567310c0d0Sopenharmony_ci } 577310c0d0Sopenharmony_ci 587310c0d0Sopenharmony_ci return 0; 597310c0d0Sopenharmony_ci} 607310c0d0Sopenharmony_ci 617310c0d0Sopenharmony_cistatic enum hvb_errno hvb_compare_hash(struct hvb_buf *digest_buf, struct hvb_buf *msg_buf, 627310c0d0Sopenharmony_ci struct hvb_buf *salt_buf, uint32_t hash_algo) 637310c0d0Sopenharmony_ci{ 647310c0d0Sopenharmony_ci int hash_err; 657310c0d0Sopenharmony_ci struct hash_ctx_t ctx = {0}; 667310c0d0Sopenharmony_ci uint8_t computed_hash[HVB_HASH_MAX_BYTES] = {0}; 677310c0d0Sopenharmony_ci 687310c0d0Sopenharmony_ci uint32_t computed_hash_size = get_hash_size(hash_algo); 697310c0d0Sopenharmony_ci if (computed_hash_size != digest_buf->size) { 707310c0d0Sopenharmony_ci hvb_print("computed_hash_size error\n"); 717310c0d0Sopenharmony_ci return HVB_ERROR_INVALID_ARGUMENT; 727310c0d0Sopenharmony_ci } 737310c0d0Sopenharmony_ci 747310c0d0Sopenharmony_ci hash_err = hash_ctx_init(&ctx, hash_algo); 757310c0d0Sopenharmony_ci if (hash_err != HASH_OK) { 767310c0d0Sopenharmony_ci hvb_print("hash init error\n"); 777310c0d0Sopenharmony_ci return HVB_ERROR_VERIFY_HASH; 787310c0d0Sopenharmony_ci } 797310c0d0Sopenharmony_ci 807310c0d0Sopenharmony_ci hash_err = hash_calc_update(&ctx, salt_buf->addr, salt_buf->size); 817310c0d0Sopenharmony_ci if (hash_err != HASH_OK) { 827310c0d0Sopenharmony_ci hvb_print("hash updata salt error\n"); 837310c0d0Sopenharmony_ci return HVB_ERROR_VERIFY_HASH; 847310c0d0Sopenharmony_ci } 857310c0d0Sopenharmony_ci 867310c0d0Sopenharmony_ci hash_err = hash_calc_do_final(&ctx, msg_buf->addr, msg_buf->size, &computed_hash[0], digest_buf->size); 877310c0d0Sopenharmony_ci if (hash_err != HASH_OK) { 887310c0d0Sopenharmony_ci hvb_print("hash updata msg error\n"); 897310c0d0Sopenharmony_ci return HVB_ERROR_VERIFY_HASH; 907310c0d0Sopenharmony_ci } 917310c0d0Sopenharmony_ci 927310c0d0Sopenharmony_ci if (hvb_memcmp(&computed_hash[0], digest_buf->addr, computed_hash_size) != 0) { 937310c0d0Sopenharmony_ci hvb_print("compare fail\n"); 947310c0d0Sopenharmony_ci return HVB_ERROR_VERIFY_HASH; 957310c0d0Sopenharmony_ci } 967310c0d0Sopenharmony_ci 977310c0d0Sopenharmony_ci return HVB_OK; 987310c0d0Sopenharmony_ci} 997310c0d0Sopenharmony_ci 1007310c0d0Sopenharmony_cistatic enum hvb_errno hash_image_init_desc(struct hvb_ops *ops, const char *ptn, 1017310c0d0Sopenharmony_ci struct hvb_cert *cert, const char *const *hash_ptn_list, 1027310c0d0Sopenharmony_ci struct hvb_verified_data *vd) 1037310c0d0Sopenharmony_ci{ 1047310c0d0Sopenharmony_ci enum hvb_io_errno io_ret = HVB_IO_OK; 1057310c0d0Sopenharmony_ci enum hvb_errno ret = HVB_OK; 1067310c0d0Sopenharmony_ci struct hvb_buf image_buf = {NULL, 0}; 1077310c0d0Sopenharmony_ci struct hvb_buf salt_buf = {cert->hash_payload.salt, cert->salt_size}; 1087310c0d0Sopenharmony_ci struct hvb_buf digest_buf = {cert->hash_payload.digest, cert->digest_size}; 1097310c0d0Sopenharmony_ci uint64_t read_bytes = 0; 1107310c0d0Sopenharmony_ci struct hvb_image_data *image = NULL; 1117310c0d0Sopenharmony_ci enum hvb_image_type image_type = (enum hvb_image_type)cert->verity_type; 1127310c0d0Sopenharmony_ci 1137310c0d0Sopenharmony_ci if (image_type != HVB_IMAGE_TYPE_HASH || !hvb_need_verify_hash(hash_ptn_list, ptn)) { 1147310c0d0Sopenharmony_ci hvb_printv(ptn, ": no need verify hash image.\n", NULL); 1157310c0d0Sopenharmony_ci return HVB_OK; 1167310c0d0Sopenharmony_ci } 1177310c0d0Sopenharmony_ci 1187310c0d0Sopenharmony_ci image_buf.size = cert->image_original_len; 1197310c0d0Sopenharmony_ci image_buf.addr = hvb_malloc(image_buf.size); 1207310c0d0Sopenharmony_ci if (image_buf.addr == NULL) { 1217310c0d0Sopenharmony_ci hvb_print("malloc image_buf fail\n"); 1227310c0d0Sopenharmony_ci return HVB_ERROR_OOM; 1237310c0d0Sopenharmony_ci } 1247310c0d0Sopenharmony_ci 1257310c0d0Sopenharmony_ci io_ret = ops->read_partition(ops, ptn, 0, image_buf.size, image_buf.addr, &read_bytes); 1267310c0d0Sopenharmony_ci if (io_ret != HVB_IO_OK) { 1277310c0d0Sopenharmony_ci hvb_printv(ptn, ": Error loading data.\n", NULL); 1287310c0d0Sopenharmony_ci ret = HVB_ERROR_IO; 1297310c0d0Sopenharmony_ci goto out; 1307310c0d0Sopenharmony_ci } 1317310c0d0Sopenharmony_ci if (read_bytes != image_buf.size) { 1327310c0d0Sopenharmony_ci hvb_printv(ptn, ": Read incorrect number of bytes from.\n", NULL); 1337310c0d0Sopenharmony_ci ret = HVB_ERROR_IO; 1347310c0d0Sopenharmony_ci goto out; 1357310c0d0Sopenharmony_ci } 1367310c0d0Sopenharmony_ci 1377310c0d0Sopenharmony_ci ret = hvb_compare_hash(&digest_buf, &image_buf, &salt_buf, cert->hash_algo); 1387310c0d0Sopenharmony_ci if (ret != HVB_OK) { 1397310c0d0Sopenharmony_ci hvb_printv(ptn, ": compare hash error.\n", NULL); 1407310c0d0Sopenharmony_ci goto out; 1417310c0d0Sopenharmony_ci } 1427310c0d0Sopenharmony_ci 1437310c0d0Sopenharmony_ci if (vd->num_loaded_images >= HVB_MAX_NUMBER_OF_LOADED_IMAGES) { 1447310c0d0Sopenharmony_ci hvb_print("error, too many images\n"); 1457310c0d0Sopenharmony_ci ret = HVB_ERROR_OOM; 1467310c0d0Sopenharmony_ci goto out; 1477310c0d0Sopenharmony_ci } 1487310c0d0Sopenharmony_ci 1497310c0d0Sopenharmony_ci image = &vd->images[vd->num_loaded_images++]; 1507310c0d0Sopenharmony_ci image->partition_name = hvb_strdup(ptn); 1517310c0d0Sopenharmony_ci image->data = image_buf; 1527310c0d0Sopenharmony_ci image->preloaded = true; 1537310c0d0Sopenharmony_ci 1547310c0d0Sopenharmony_ci return HVB_OK; 1557310c0d0Sopenharmony_ci 1567310c0d0Sopenharmony_ciout: 1577310c0d0Sopenharmony_ci if (image_buf.addr != NULL) 1587310c0d0Sopenharmony_ci hvb_free(image_buf.addr); 1597310c0d0Sopenharmony_ci 1607310c0d0Sopenharmony_ci return ret; 1617310c0d0Sopenharmony_ci} 1627310c0d0Sopenharmony_ci 1637310c0d0Sopenharmony_cistatic bool _decode_octets(struct hvb_buf *buf, size_t size, uint8_t **p, uint8_t *end) 1647310c0d0Sopenharmony_ci{ 1657310c0d0Sopenharmony_ci /* check range */ 1667310c0d0Sopenharmony_ci if (*p + size > end || *p + size < *p) 1677310c0d0Sopenharmony_ci return false; 1687310c0d0Sopenharmony_ci 1697310c0d0Sopenharmony_ci buf->addr = *p; 1707310c0d0Sopenharmony_ci buf->size = size; 1717310c0d0Sopenharmony_ci 1727310c0d0Sopenharmony_ci /* forward move */ 1737310c0d0Sopenharmony_ci *p += size; 1747310c0d0Sopenharmony_ci 1757310c0d0Sopenharmony_ci return true; 1767310c0d0Sopenharmony_ci} 1777310c0d0Sopenharmony_ci 1787310c0d0Sopenharmony_cistatic enum hvb_errno _hvb_cert_payload_parser(struct hvb_cert *cert, uint8_t **p, uint8_t *end) 1797310c0d0Sopenharmony_ci{ 1807310c0d0Sopenharmony_ci struct hvb_buf buf; 1817310c0d0Sopenharmony_ci struct hash_payload *payload = &cert->hash_payload; 1827310c0d0Sopenharmony_ci 1837310c0d0Sopenharmony_ci if (!_decode_octets(&buf, cert->salt_size, p, end)) { 1847310c0d0Sopenharmony_ci hvb_print("error, dc salt.\n"); 1857310c0d0Sopenharmony_ci return HVB_ERROR_INVALID_CERT_FORMAT; 1867310c0d0Sopenharmony_ci } 1877310c0d0Sopenharmony_ci payload->salt = buf.addr; 1887310c0d0Sopenharmony_ci 1897310c0d0Sopenharmony_ci if (!_decode_octets(&buf, cert->digest_size, p, end)) { 1907310c0d0Sopenharmony_ci hvb_print("error, dc digest.\n"); 1917310c0d0Sopenharmony_ci return HVB_ERROR_INVALID_CERT_FORMAT; 1927310c0d0Sopenharmony_ci } 1937310c0d0Sopenharmony_ci payload->digest = buf.addr; 1947310c0d0Sopenharmony_ci 1957310c0d0Sopenharmony_ci return HVB_OK; 1967310c0d0Sopenharmony_ci} 1977310c0d0Sopenharmony_ci 1987310c0d0Sopenharmony_cistatic enum hvb_errno _hvb_cert_payload_parser_v2(struct hvb_cert *cert, uint8_t **p, uint8_t *end, uint8_t *header) 1997310c0d0Sopenharmony_ci{ 2007310c0d0Sopenharmony_ci struct hash_payload *payload = &cert->hash_payload; 2017310c0d0Sopenharmony_ci uint8_t *cur_header; 2027310c0d0Sopenharmony_ci 2037310c0d0Sopenharmony_ci if (header + cert->salt_offset > end || header + cert->salt_offset <= header) { 2047310c0d0Sopenharmony_ci hvb_print("error, illegal salt offset.\n"); 2057310c0d0Sopenharmony_ci return HVB_ERROR_INVALID_CERT_FORMAT; 2067310c0d0Sopenharmony_ci } 2077310c0d0Sopenharmony_ci cur_header = header + cert->salt_offset; 2087310c0d0Sopenharmony_ci 2097310c0d0Sopenharmony_ci if (cur_header + cert->salt_size > end || cur_header + cert->salt_size <= cur_header) { 2107310c0d0Sopenharmony_ci hvb_print("error, dc salt.\n"); 2117310c0d0Sopenharmony_ci return HVB_ERROR_INVALID_CERT_FORMAT; 2127310c0d0Sopenharmony_ci } 2137310c0d0Sopenharmony_ci payload->salt = cur_header; 2147310c0d0Sopenharmony_ci 2157310c0d0Sopenharmony_ci if (header + cert->digest_offset > end || header + cert->digest_offset <= header) { 2167310c0d0Sopenharmony_ci hvb_print("error, illegal digest offset.\n"); 2177310c0d0Sopenharmony_ci return HVB_ERROR_INVALID_CERT_FORMAT; 2187310c0d0Sopenharmony_ci } 2197310c0d0Sopenharmony_ci cur_header = header + cert->digest_offset; 2207310c0d0Sopenharmony_ci 2217310c0d0Sopenharmony_ci if (cur_header + cert->digest_size > end || cur_header + cert->digest_size <= cur_header) { 2227310c0d0Sopenharmony_ci hvb_print("error, dc digest.\n"); 2237310c0d0Sopenharmony_ci return HVB_ERROR_INVALID_CERT_FORMAT; 2247310c0d0Sopenharmony_ci } 2257310c0d0Sopenharmony_ci payload->digest = cur_header; 2267310c0d0Sopenharmony_ci *p = cur_header + cert->digest_size; 2277310c0d0Sopenharmony_ci 2287310c0d0Sopenharmony_ci return HVB_OK; 2297310c0d0Sopenharmony_ci} 2307310c0d0Sopenharmony_ci 2317310c0d0Sopenharmony_cistatic enum hvb_errno _hvb_cert_signature_parser(struct hvb_cert *cert, uint8_t **p, uint8_t *end) 2327310c0d0Sopenharmony_ci{ 2337310c0d0Sopenharmony_ci struct hvb_buf buf; 2347310c0d0Sopenharmony_ci struct hvb_sign_info *sign_info = &cert->signature_info; 2357310c0d0Sopenharmony_ci size_t cp_size = hvb_offsetof(struct hvb_sign_info, pubk); 2367310c0d0Sopenharmony_ci 2377310c0d0Sopenharmony_ci if (!_decode_octets(&buf, cp_size, p, end)) { 2387310c0d0Sopenharmony_ci hvb_print("error, dc sign info const.\n"); 2397310c0d0Sopenharmony_ci return HVB_ERROR_INVALID_CERT_FORMAT; 2407310c0d0Sopenharmony_ci } 2417310c0d0Sopenharmony_ci if (hvb_memcpy_s(&cert->signature_info, sizeof(cert->signature_info), buf.addr, cp_size) != 0) { 2427310c0d0Sopenharmony_ci hvb_print("error, copy dc sign info const.\n"); 2437310c0d0Sopenharmony_ci return HVB_ERROR_OOM; 2447310c0d0Sopenharmony_ci } 2457310c0d0Sopenharmony_ci 2467310c0d0Sopenharmony_ci if (!_decode_octets(&buf, sign_info->pubkey_len, p, end)) { 2477310c0d0Sopenharmony_ci hvb_print("error, dc pubk.\n"); 2487310c0d0Sopenharmony_ci return HVB_ERROR_INVALID_CERT_FORMAT; 2497310c0d0Sopenharmony_ci } 2507310c0d0Sopenharmony_ci if (hvb_memcpy_s(&sign_info->pubk, sizeof(sign_info->pubk), &buf, sizeof(buf)) != 0) { 2517310c0d0Sopenharmony_ci hvb_print("error, copy dc pubk.\n"); 2527310c0d0Sopenharmony_ci return HVB_ERROR_OOM; 2537310c0d0Sopenharmony_ci } 2547310c0d0Sopenharmony_ci 2557310c0d0Sopenharmony_ci if (!_decode_octets(&buf, sign_info->signature_len, p, end)) { 2567310c0d0Sopenharmony_ci hvb_print("error, dc sign.\n"); 2577310c0d0Sopenharmony_ci return HVB_ERROR_INVALID_CERT_FORMAT; 2587310c0d0Sopenharmony_ci } 2597310c0d0Sopenharmony_ci if (hvb_memcpy_s(&sign_info->sign, sizeof(sign_info->sign), &buf, sizeof(buf)) != 0) { 2607310c0d0Sopenharmony_ci hvb_print("error, copy dc sign.\n"); 2617310c0d0Sopenharmony_ci return HVB_ERROR_OOM; 2627310c0d0Sopenharmony_ci } 2637310c0d0Sopenharmony_ci 2647310c0d0Sopenharmony_ci return HVB_OK; 2657310c0d0Sopenharmony_ci} 2667310c0d0Sopenharmony_ci 2677310c0d0Sopenharmony_cistatic enum hvb_errno _hvb_cert_signature_parser_v2(struct hvb_cert *cert, uint8_t **p, uint8_t *end, uint8_t *header) 2687310c0d0Sopenharmony_ci{ 2697310c0d0Sopenharmony_ci struct hvb_buf buf; 2707310c0d0Sopenharmony_ci struct hvb_sign_info *sign_info = &cert->signature_info; 2717310c0d0Sopenharmony_ci size_t cp_size = hvb_offsetof(struct hvb_sign_info, pubk); 2727310c0d0Sopenharmony_ci uint8_t *cur_header; 2737310c0d0Sopenharmony_ci 2747310c0d0Sopenharmony_ci if (!_decode_octets(&buf, cp_size, p, end)) { 2757310c0d0Sopenharmony_ci hvb_print("error, dc sign info const.\n"); 2767310c0d0Sopenharmony_ci return HVB_ERROR_INVALID_CERT_FORMAT; 2777310c0d0Sopenharmony_ci } 2787310c0d0Sopenharmony_ci if (hvb_memcpy_s(&cert->signature_info, sizeof(cert->signature_info), buf.addr, cp_size) != 0) { 2797310c0d0Sopenharmony_ci hvb_print("error, copy dc sign info const.\n"); 2807310c0d0Sopenharmony_ci return HVB_ERROR_OOM; 2817310c0d0Sopenharmony_ci } 2827310c0d0Sopenharmony_ci 2837310c0d0Sopenharmony_ci if (header + sign_info->pubkey_offset > end || header + sign_info->pubkey_offset <= header) { 2847310c0d0Sopenharmony_ci hvb_print("error, illegal pubkey offset.\n"); 2857310c0d0Sopenharmony_ci return HVB_ERROR_INVALID_CERT_FORMAT; 2867310c0d0Sopenharmony_ci } 2877310c0d0Sopenharmony_ci cur_header = header + sign_info->pubkey_offset; 2887310c0d0Sopenharmony_ci 2897310c0d0Sopenharmony_ci if (cur_header + sign_info->pubkey_len > end || cur_header + sign_info->pubkey_len <= cur_header) { 2907310c0d0Sopenharmony_ci hvb_print("error, dc pubkey.\n"); 2917310c0d0Sopenharmony_ci return HVB_ERROR_INVALID_CERT_FORMAT; 2927310c0d0Sopenharmony_ci } 2937310c0d0Sopenharmony_ci sign_info->pubk.addr = cur_header; 2947310c0d0Sopenharmony_ci sign_info->pubk.size = sign_info->pubkey_len; 2957310c0d0Sopenharmony_ci 2967310c0d0Sopenharmony_ci if (header + sign_info->signature_offset > end || header + sign_info->signature_offset <= header) { 2977310c0d0Sopenharmony_ci hvb_print("error, illegal signature offset.\n"); 2987310c0d0Sopenharmony_ci return HVB_ERROR_INVALID_CERT_FORMAT; 2997310c0d0Sopenharmony_ci } 3007310c0d0Sopenharmony_ci cur_header = header + sign_info->signature_offset; 3017310c0d0Sopenharmony_ci 3027310c0d0Sopenharmony_ci if (cur_header + sign_info->signature_len > end || cur_header + sign_info->signature_len <= cur_header) { 3037310c0d0Sopenharmony_ci hvb_print("error, dc pubkey.\n"); 3047310c0d0Sopenharmony_ci return HVB_ERROR_INVALID_CERT_FORMAT; 3057310c0d0Sopenharmony_ci } 3067310c0d0Sopenharmony_ci sign_info->sign.addr = cur_header; 3077310c0d0Sopenharmony_ci sign_info->sign.size = sign_info->signature_len; 3087310c0d0Sopenharmony_ci 3097310c0d0Sopenharmony_ci return HVB_OK; 3107310c0d0Sopenharmony_ci} 3117310c0d0Sopenharmony_ci 3127310c0d0Sopenharmony_cienum hvb_errno hvb_cert_parser(struct hvb_cert *cert, struct hvb_buf *cert_buf) 3137310c0d0Sopenharmony_ci{ 3147310c0d0Sopenharmony_ci hvb_return_hvb_err_if_null(cert); 3157310c0d0Sopenharmony_ci hvb_return_hvb_err_if_null(cert_buf); 3167310c0d0Sopenharmony_ci hvb_return_hvb_err_if_null(cert_buf->addr); 3177310c0d0Sopenharmony_ci 3187310c0d0Sopenharmony_ci if (cert_buf->size > HVB_CERT_MAX_SIZE) { 3197310c0d0Sopenharmony_ci hvb_print("invalid cert size.\n"); 3207310c0d0Sopenharmony_ci return HVB_ERROR_INVALID_ARGUMENT; 3217310c0d0Sopenharmony_ci } 3227310c0d0Sopenharmony_ci 3237310c0d0Sopenharmony_ci enum hvb_errno ret = HVB_OK; 3247310c0d0Sopenharmony_ci struct hvb_buf buf; 3257310c0d0Sopenharmony_ci uint8_t *p = cert_buf->addr; 3267310c0d0Sopenharmony_ci uint8_t *end = p + cert_buf->size; 3277310c0d0Sopenharmony_ci uint8_t *header = p; 3287310c0d0Sopenharmony_ci size_t header_size = hvb_offsetof(struct hvb_cert, hash_payload); 3297310c0d0Sopenharmony_ci 3307310c0d0Sopenharmony_ci /* parse header */ 3317310c0d0Sopenharmony_ci if (!_decode_octets(&buf, header_size, &p, end)) { 3327310c0d0Sopenharmony_ci hvb_print("error, dc cert const.\n"); 3337310c0d0Sopenharmony_ci return HVB_ERROR_INVALID_CERT_FORMAT; 3347310c0d0Sopenharmony_ci } 3357310c0d0Sopenharmony_ci if (hvb_memcpy_s(cert, sizeof(*cert), buf.addr, buf.size) != 0) { 3367310c0d0Sopenharmony_ci hvb_print("error, copy dc cert const.\n"); 3377310c0d0Sopenharmony_ci return HVB_ERROR_OOM; 3387310c0d0Sopenharmony_ci } 3397310c0d0Sopenharmony_ci 3407310c0d0Sopenharmony_ci if (cert->version_minor == 0) { 3417310c0d0Sopenharmony_ci /* parse hash payload */ 3427310c0d0Sopenharmony_ci ret = _hvb_cert_payload_parser(cert, &p, end); 3437310c0d0Sopenharmony_ci if (ret != HVB_OK) { 3447310c0d0Sopenharmony_ci hvb_print("error, pr hash payload.\n"); 3457310c0d0Sopenharmony_ci return ret; 3467310c0d0Sopenharmony_ci } 3477310c0d0Sopenharmony_ci 3487310c0d0Sopenharmony_ci /* parse signature info */ 3497310c0d0Sopenharmony_ci ret = _hvb_cert_signature_parser(cert, &p, end); 3507310c0d0Sopenharmony_ci if (ret != HVB_OK) { 3517310c0d0Sopenharmony_ci hvb_print("error, pr sign.\n"); 3527310c0d0Sopenharmony_ci return ret; 3537310c0d0Sopenharmony_ci } 3547310c0d0Sopenharmony_ci } else if (cert->version_minor == 1) { 3557310c0d0Sopenharmony_ci /* parse hash payload v2 */ 3567310c0d0Sopenharmony_ci ret = _hvb_cert_payload_parser_v2(cert, &p, end, header); 3577310c0d0Sopenharmony_ci if (ret != HVB_OK) { 3587310c0d0Sopenharmony_ci hvb_print("error, pr hash payload.\n"); 3597310c0d0Sopenharmony_ci return ret; 3607310c0d0Sopenharmony_ci } 3617310c0d0Sopenharmony_ci 3627310c0d0Sopenharmony_ci /* parse signature info v2 */ 3637310c0d0Sopenharmony_ci ret = _hvb_cert_signature_parser_v2(cert, &p, end, header); 3647310c0d0Sopenharmony_ci if (ret != HVB_OK) { 3657310c0d0Sopenharmony_ci hvb_print("error, pr sign.\n"); 3667310c0d0Sopenharmony_ci return ret; 3677310c0d0Sopenharmony_ci } 3687310c0d0Sopenharmony_ci } else { 3697310c0d0Sopenharmony_ci hvb_print("error minor version\n"); 3707310c0d0Sopenharmony_ci return HVB_ERROR_INVALID_ARGUMENT; 3717310c0d0Sopenharmony_ci } 3727310c0d0Sopenharmony_ci 3737310c0d0Sopenharmony_ci return HVB_OK; 3747310c0d0Sopenharmony_ci} 3757310c0d0Sopenharmony_ci 3767310c0d0Sopenharmony_cistatic uint64_t hvb_buftouint64(uint8_t *p) 3777310c0d0Sopenharmony_ci{ 3787310c0d0Sopenharmony_ci uint32_t i; 3797310c0d0Sopenharmony_ci uint64_t val = 0; 3807310c0d0Sopenharmony_ci 3817310c0d0Sopenharmony_ci for (i = 0; i < 8; i++, p++) { 3827310c0d0Sopenharmony_ci val |= (((uint64_t)(*p)) << (i * 8)); 3837310c0d0Sopenharmony_ci } 3847310c0d0Sopenharmony_ci 3857310c0d0Sopenharmony_ci return val; 3867310c0d0Sopenharmony_ci} 3877310c0d0Sopenharmony_ci 3887310c0d0Sopenharmony_ci/* 3897310c0d0Sopenharmony_ci * raw_pubk: |bit_length|n0|mod|p_rr| 3907310c0d0Sopenharmony_ci */ 3917310c0d0Sopenharmony_cistatic enum hvb_errno hvb_cert_pubk_parser(struct hvb_rsa_pubkey *pubk, struct hvb_buf *raw_pubk) 3927310c0d0Sopenharmony_ci{ 3937310c0d0Sopenharmony_ci uint64_t bit_length = 0; 3947310c0d0Sopenharmony_ci uint64_t n0 = 0; 3957310c0d0Sopenharmony_ci struct hvb_buf mod; 3967310c0d0Sopenharmony_ci struct hvb_buf p_rr; 3977310c0d0Sopenharmony_ci struct hvb_buf buf; 3987310c0d0Sopenharmony_ci 3997310c0d0Sopenharmony_ci uint8_t *p = raw_pubk->addr; 4007310c0d0Sopenharmony_ci uint8_t *end = p + raw_pubk->size; 4017310c0d0Sopenharmony_ci 4027310c0d0Sopenharmony_ci if (!_decode_octets(&buf, sizeof(uint64_t), &p, end)) { 4037310c0d0Sopenharmony_ci hvb_print("error, dc bit_length.\n"); 4047310c0d0Sopenharmony_ci return 1; 4057310c0d0Sopenharmony_ci } 4067310c0d0Sopenharmony_ci bit_length = hvb_buftouint64(buf.addr); 4077310c0d0Sopenharmony_ci bit_length = hvb_be64toh(bit_length); 4087310c0d0Sopenharmony_ci 4097310c0d0Sopenharmony_ci if (!_decode_octets(&buf, sizeof(uint64_t), &p, end)) { 4107310c0d0Sopenharmony_ci hvb_print("error, dc n0.\n"); 4117310c0d0Sopenharmony_ci return 1; 4127310c0d0Sopenharmony_ci } 4137310c0d0Sopenharmony_ci n0 = hvb_buftouint64(buf.addr); 4147310c0d0Sopenharmony_ci n0 = hvb_be64toh(n0); 4157310c0d0Sopenharmony_ci 4167310c0d0Sopenharmony_ci if (!_decode_octets(&mod, bit_length / 8, &p, end)) { 4177310c0d0Sopenharmony_ci hvb_print("error, dc mod.\n"); 4187310c0d0Sopenharmony_ci return 1; 4197310c0d0Sopenharmony_ci } 4207310c0d0Sopenharmony_ci 4217310c0d0Sopenharmony_ci if (!_decode_octets(&p_rr, bit_length / 8, &p, end)) { 4227310c0d0Sopenharmony_ci hvb_print("error, dc p_rr\n"); 4237310c0d0Sopenharmony_ci return 1; 4247310c0d0Sopenharmony_ci } 4257310c0d0Sopenharmony_ci 4267310c0d0Sopenharmony_ci pubk->width = bit_length; 4277310c0d0Sopenharmony_ci pubk->e = 65537; 4287310c0d0Sopenharmony_ci pubk->pn = mod.addr; 4297310c0d0Sopenharmony_ci pubk->nlen = mod.size; 4307310c0d0Sopenharmony_ci pubk->p_rr = p_rr.addr; 4317310c0d0Sopenharmony_ci pubk->rlen = p_rr.size; 4327310c0d0Sopenharmony_ci pubk->n_n0_i = n0; 4337310c0d0Sopenharmony_ci 4347310c0d0Sopenharmony_ci return 0; 4357310c0d0Sopenharmony_ci} 4367310c0d0Sopenharmony_ci 4377310c0d0Sopenharmony_cistatic enum hvb_errno hvb_verify_cert(struct hvb_buf *tbs, struct hvb_sign_info *sign_info, uint32_t salt_size) 4387310c0d0Sopenharmony_ci{ 4397310c0d0Sopenharmony_ci int cry_err; 4407310c0d0Sopenharmony_ci enum hvb_errno ret = HVB_OK; 4417310c0d0Sopenharmony_ci uint32_t hash_len; 4427310c0d0Sopenharmony_ci struct hvb_buf temp_buf; 4437310c0d0Sopenharmony_ci uint8_t *hash = NULL; 4447310c0d0Sopenharmony_ci struct hvb_rsa_pubkey pubk; 4457310c0d0Sopenharmony_ci 4467310c0d0Sopenharmony_ci temp_buf = sign_info->pubk; 4477310c0d0Sopenharmony_ci ret = hvb_cert_pubk_parser(&pubk, &temp_buf); 4487310c0d0Sopenharmony_ci if (ret != HVB_OK) { 4497310c0d0Sopenharmony_ci hvb_print("error, hvb cert pubk parser.\n"); 4507310c0d0Sopenharmony_ci return ret; 4517310c0d0Sopenharmony_ci } 4527310c0d0Sopenharmony_ci 4537310c0d0Sopenharmony_ci hash_len = get_hash_size(sign_info->algorithm); 4547310c0d0Sopenharmony_ci hash = hvb_malloc(hash_len); 4557310c0d0Sopenharmony_ci if (!hash) { 4567310c0d0Sopenharmony_ci hvb_print("hash malloc error:"); 4577310c0d0Sopenharmony_ci return HVB_ERROR_OOM; 4587310c0d0Sopenharmony_ci } 4597310c0d0Sopenharmony_ci 4607310c0d0Sopenharmony_ci cry_err = hash_sha256_single(tbs->addr, tbs->size, hash, hash_len); 4617310c0d0Sopenharmony_ci if (cry_err != 0) { 4627310c0d0Sopenharmony_ci hvb_print("Error computed hash.\n"); 4637310c0d0Sopenharmony_ci return HVB_ERROR_INVALID_ARGUMENT; 4647310c0d0Sopenharmony_ci } 4657310c0d0Sopenharmony_ci 4667310c0d0Sopenharmony_ci cry_err = hvb_rsa_verify_pss(&pubk, hash, hash_len, sign_info->sign.addr, sign_info->sign.size, salt_size); 4677310c0d0Sopenharmony_ci if (cry_err != VERIFY_OK) { 4687310c0d0Sopenharmony_ci hvb_print("hvb_rsa_verify_pss result error, signature mismatch\n"); 4697310c0d0Sopenharmony_ci return HVB_ERROR_VERIFY_SIGN; 4707310c0d0Sopenharmony_ci } 4717310c0d0Sopenharmony_ci 4727310c0d0Sopenharmony_ci return HVB_OK; 4737310c0d0Sopenharmony_ci} 4747310c0d0Sopenharmony_ci 4757310c0d0Sopenharmony_cistatic enum hvb_errno _check_rollback_index(struct hvb_ops *ops, struct hvb_cert *cert, struct hvb_verified_data *vd) 4767310c0d0Sopenharmony_ci{ 4777310c0d0Sopenharmony_ci enum hvb_io_errno io_ret = HVB_IO_OK; 4787310c0d0Sopenharmony_ci uint64_t stored_rollback_index = 0; 4797310c0d0Sopenharmony_ci uint64_t cert_rollback_index = cert->rollback_index; 4807310c0d0Sopenharmony_ci uint64_t rollback_location = cert->rollback_location; 4817310c0d0Sopenharmony_ci 4827310c0d0Sopenharmony_ci if (rollback_location >= HVB_MAX_NUMBER_OF_ROLLBACK_INDEX_LOCATIONS) { 4837310c0d0Sopenharmony_ci hvb_print("error, rollback_location too big\n"); 4847310c0d0Sopenharmony_ci return HVB_ERROR_INVALID_CERT_FORMAT; 4857310c0d0Sopenharmony_ci } 4867310c0d0Sopenharmony_ci 4877310c0d0Sopenharmony_ci io_ret = ops->read_rollback(ops, rollback_location, &stored_rollback_index); 4887310c0d0Sopenharmony_ci if (io_ret != HVB_IO_OK) { 4897310c0d0Sopenharmony_ci hvb_print("error, read rollback idnex\n"); 4907310c0d0Sopenharmony_ci return HVB_ERROR_IO; 4917310c0d0Sopenharmony_ci } 4927310c0d0Sopenharmony_ci 4937310c0d0Sopenharmony_ci if (cert_rollback_index < stored_rollback_index) { 4947310c0d0Sopenharmony_ci hvb_print("error, cert rollback index is less than the stored\n"); 4957310c0d0Sopenharmony_ci return HVB_ERROR_ROLLBACK_INDEX; 4967310c0d0Sopenharmony_ci } 4977310c0d0Sopenharmony_ci 4987310c0d0Sopenharmony_ci vd->rollback_indexes[rollback_location] = cert_rollback_index; 4997310c0d0Sopenharmony_ci 5007310c0d0Sopenharmony_ci return HVB_OK; 5017310c0d0Sopenharmony_ci} 5027310c0d0Sopenharmony_ci 5037310c0d0Sopenharmony_cienum hvb_errno cert_init_desc(struct hvb_ops *ops, const char *ptn, struct hvb_buf *cert_buf, 5047310c0d0Sopenharmony_ci const char *const *hash_ptn_list, struct hvb_buf *out_pubk, 5057310c0d0Sopenharmony_ci struct hvb_verified_data *vd) 5067310c0d0Sopenharmony_ci{ 5077310c0d0Sopenharmony_ci hvb_return_hvb_err_if_null(ops); 5087310c0d0Sopenharmony_ci hvb_return_hvb_err_if_null(ptn); 5097310c0d0Sopenharmony_ci hvb_return_hvb_err_if_null(cert_buf); 5107310c0d0Sopenharmony_ci hvb_return_hvb_err_if_null(cert_buf->addr); 5117310c0d0Sopenharmony_ci hvb_return_hvb_err_if_null(out_pubk); 5127310c0d0Sopenharmony_ci hvb_return_hvb_err_if_null(vd); 5137310c0d0Sopenharmony_ci 5147310c0d0Sopenharmony_ci enum hvb_errno ret = HVB_OK; 5157310c0d0Sopenharmony_ci ret = check_hvb_ops(ops); 5167310c0d0Sopenharmony_ci if (ret != HVB_OK) { 5177310c0d0Sopenharmony_ci hvb_print("error, check ops\n"); 5187310c0d0Sopenharmony_ci return HVB_ERROR_INVALID_ARGUMENT; 5197310c0d0Sopenharmony_ci } 5207310c0d0Sopenharmony_ci if (hvb_strnlen(ptn, HVB_MAX_PARTITION_NAME_LEN) >= HVB_MAX_PARTITION_NAME_LEN) { 5217310c0d0Sopenharmony_ci hvb_print("error, check partition name\n"); 5227310c0d0Sopenharmony_ci return HVB_ERROR_INVALID_ARGUMENT; 5237310c0d0Sopenharmony_ci } 5247310c0d0Sopenharmony_ci 5257310c0d0Sopenharmony_ci struct hvb_cert cert = {0}; 5267310c0d0Sopenharmony_ci struct hvb_buf tbs = {0}; 5277310c0d0Sopenharmony_ci struct hvb_sign_info *sign_info = &cert.signature_info; 5287310c0d0Sopenharmony_ci 5297310c0d0Sopenharmony_ci ret = hvb_cert_parser(&cert, cert_buf); 5307310c0d0Sopenharmony_ci if (ret != HVB_OK) { 5317310c0d0Sopenharmony_ci hvb_print("error, hvb cert parser.\n"); 5327310c0d0Sopenharmony_ci return ret; 5337310c0d0Sopenharmony_ci } 5347310c0d0Sopenharmony_ci 5357310c0d0Sopenharmony_ci tbs.addr = cert_buf->addr; 5367310c0d0Sopenharmony_ci tbs.size = sign_info->sign.addr - cert_buf->addr; 5377310c0d0Sopenharmony_ci ret = hvb_verify_cert(&tbs, sign_info, cert.salt_size); 5387310c0d0Sopenharmony_ci if (ret != HVB_OK) { 5397310c0d0Sopenharmony_ci hvb_print("error, verify cert.\n"); 5407310c0d0Sopenharmony_ci return ret; 5417310c0d0Sopenharmony_ci } 5427310c0d0Sopenharmony_ci 5437310c0d0Sopenharmony_ci ret = _check_rollback_index(ops, &cert, vd); 5447310c0d0Sopenharmony_ci if (ret != HVB_OK) { 5457310c0d0Sopenharmony_ci hvb_print("error, checkout index.\n"); 5467310c0d0Sopenharmony_ci return ret; 5477310c0d0Sopenharmony_ci } 5487310c0d0Sopenharmony_ci 5497310c0d0Sopenharmony_ci ret = hash_image_init_desc(ops, ptn, &cert, hash_ptn_list, vd); 5507310c0d0Sopenharmony_ci if (ret != HVB_OK) { 5517310c0d0Sopenharmony_ci hvb_print("hash_image_init_desc result error\n"); 5527310c0d0Sopenharmony_ci return ret; 5537310c0d0Sopenharmony_ci } 5547310c0d0Sopenharmony_ci 5557310c0d0Sopenharmony_ci *out_pubk = sign_info->pubk; 5567310c0d0Sopenharmony_ci vd->key_len = out_pubk->size; 5577310c0d0Sopenharmony_ci 5587310c0d0Sopenharmony_ci return ret; 5597310c0d0Sopenharmony_ci} 560