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 "hvb_footer.h" 187310c0d0Sopenharmony_ci#include "hvb_crypto.h" 197310c0d0Sopenharmony_ci#include "hvb_ops.h" 207310c0d0Sopenharmony_ci#include "hvb_rvt.h" 217310c0d0Sopenharmony_ci#include "hvb_cert.h" 227310c0d0Sopenharmony_ci#include "hvb_sysdeps.h" 237310c0d0Sopenharmony_ci#include "hvb_util.h" 247310c0d0Sopenharmony_ci#include "hvb_cmdline.h" 257310c0d0Sopenharmony_ci#include "hvb.h" 267310c0d0Sopenharmony_ci 277310c0d0Sopenharmony_cistruct hvb_verified_data *hvb_init_verified_data(void) 287310c0d0Sopenharmony_ci{ 297310c0d0Sopenharmony_ci struct hvb_verified_data *vd = NULL; 307310c0d0Sopenharmony_ci 317310c0d0Sopenharmony_ci vd = hvb_calloc(sizeof(*vd)); 327310c0d0Sopenharmony_ci if (!vd) { 337310c0d0Sopenharmony_ci hvb_print("malloc verified_data fail\n"); 347310c0d0Sopenharmony_ci return NULL; 357310c0d0Sopenharmony_ci } 367310c0d0Sopenharmony_ci 377310c0d0Sopenharmony_ci vd->certs = hvb_calloc(sizeof(struct hvb_cert_data) * HVB_MAX_NUMBER_OF_LOADED_CERTS); 387310c0d0Sopenharmony_ci if (!vd->certs) { 397310c0d0Sopenharmony_ci hvb_print("malloc certs fail\n"); 407310c0d0Sopenharmony_ci goto fail; 417310c0d0Sopenharmony_ci } 427310c0d0Sopenharmony_ci 437310c0d0Sopenharmony_ci vd->images = hvb_calloc(sizeof(struct hvb_image_data) * HVB_MAX_NUMBER_OF_LOADED_IMAGES); 447310c0d0Sopenharmony_ci if (!vd->images) { 457310c0d0Sopenharmony_ci hvb_print("malloc images fail\n"); 467310c0d0Sopenharmony_ci goto fail; 477310c0d0Sopenharmony_ci } 487310c0d0Sopenharmony_ci 497310c0d0Sopenharmony_ci vd->num_loaded_certs = 0; 507310c0d0Sopenharmony_ci vd->num_loaded_images = 0; 517310c0d0Sopenharmony_ci 527310c0d0Sopenharmony_ci vd->cmdline.buf = hvb_calloc(CMD_LINE_SIZE); 537310c0d0Sopenharmony_ci if (!vd->cmdline.buf) { 547310c0d0Sopenharmony_ci hvb_print("malloc cmdline fail\n"); 557310c0d0Sopenharmony_ci goto fail; 567310c0d0Sopenharmony_ci } 577310c0d0Sopenharmony_ci 587310c0d0Sopenharmony_ci vd->cmdline.cur_pos = 0; 597310c0d0Sopenharmony_ci vd->cmdline.max_size = CMD_LINE_SIZE; 607310c0d0Sopenharmony_ci 617310c0d0Sopenharmony_ci vd->key_len = 0; 627310c0d0Sopenharmony_ci 637310c0d0Sopenharmony_ci return vd; 647310c0d0Sopenharmony_ci 657310c0d0Sopenharmony_cifail: 667310c0d0Sopenharmony_ci hvb_chain_verify_data_free(vd); 677310c0d0Sopenharmony_ci hvb_free(vd); 687310c0d0Sopenharmony_ci vd = NULL; 697310c0d0Sopenharmony_ci return vd; 707310c0d0Sopenharmony_ci} 717310c0d0Sopenharmony_ci 727310c0d0Sopenharmony_cistatic enum hvb_errno hvb_rvt_verify_root(struct hvb_ops *ops, const char *ptn, 737310c0d0Sopenharmony_ci const char *const *ptn_list, 747310c0d0Sopenharmony_ci struct hvb_verified_data *vd) 757310c0d0Sopenharmony_ci{ 767310c0d0Sopenharmony_ci enum hvb_errno ret = HVB_OK; 777310c0d0Sopenharmony_ci enum hvb_io_errno io_ret = HVB_IO_OK; 787310c0d0Sopenharmony_ci bool is_trusted = false; 797310c0d0Sopenharmony_ci struct hvb_buf cert_pubk = {0}; 807310c0d0Sopenharmony_ci 817310c0d0Sopenharmony_ci ret = footer_init_desc(ops, ptn, ptn_list, &cert_pubk, vd); 827310c0d0Sopenharmony_ci if (ret != HVB_OK) { 837310c0d0Sopenharmony_ci hvb_printv("error verity partition: ", ptn, "\n", NULL); 847310c0d0Sopenharmony_ci goto fail; 857310c0d0Sopenharmony_ci } 867310c0d0Sopenharmony_ci 877310c0d0Sopenharmony_ci io_ret = ops->valid_rvt_key(ops, cert_pubk.addr, cert_pubk.size, NULL, 0, &is_trusted); 887310c0d0Sopenharmony_ci if (io_ret != HVB_IO_OK) { 897310c0d0Sopenharmony_ci ret = HVB_ERROR_PUBLIC_KEY_REJECTED; 907310c0d0Sopenharmony_ci hvb_print("error, rvt public key invalid\n"); 917310c0d0Sopenharmony_ci goto fail; 927310c0d0Sopenharmony_ci } 937310c0d0Sopenharmony_ci 947310c0d0Sopenharmony_ci if (is_trusted == false) { 957310c0d0Sopenharmony_ci ret = HVB_ERROR_PUBLIC_KEY_REJECTED; 967310c0d0Sopenharmony_ci hvb_print("error, rvt public key rejected\n"); 977310c0d0Sopenharmony_ci goto fail; 987310c0d0Sopenharmony_ci } 997310c0d0Sopenharmony_ci 1007310c0d0Sopenharmony_cifail: 1017310c0d0Sopenharmony_ci return ret; 1027310c0d0Sopenharmony_ci} 1037310c0d0Sopenharmony_ci 1047310c0d0Sopenharmony_cistatic struct hvb_buf *hvb_get_partition_image(struct hvb_verified_data *vd, const char *ptn) 1057310c0d0Sopenharmony_ci{ 1067310c0d0Sopenharmony_ci struct hvb_image_data *p = vd->images; 1077310c0d0Sopenharmony_ci struct hvb_image_data *end = p + vd->num_loaded_images; 1087310c0d0Sopenharmony_ci size_t name_len = hvb_strnlen(ptn, HVB_MAX_PARTITION_NAME_LEN); 1097310c0d0Sopenharmony_ci if (name_len >= HVB_MAX_PARTITION_NAME_LEN) { 1107310c0d0Sopenharmony_ci hvb_print("invalid ptn name len\n"); 1117310c0d0Sopenharmony_ci return NULL; 1127310c0d0Sopenharmony_ci } 1137310c0d0Sopenharmony_ci 1147310c0d0Sopenharmony_ci for (; p < end; p++) { 1157310c0d0Sopenharmony_ci if (hvb_strnlen(p->partition_name, HVB_MAX_PARTITION_NAME_LEN) == name_len && 1167310c0d0Sopenharmony_ci hvb_strncmp(ptn, p->partition_name, HVB_MAX_PARTITION_NAME_LEN) == 0) { 1177310c0d0Sopenharmony_ci return &p->data; 1187310c0d0Sopenharmony_ci } 1197310c0d0Sopenharmony_ci } 1207310c0d0Sopenharmony_ci 1217310c0d0Sopenharmony_ci return NULL; 1227310c0d0Sopenharmony_ci} 1237310c0d0Sopenharmony_ci 1247310c0d0Sopenharmony_cistatic bool hvb_buf_equal(const struct hvb_buf *buf1, const struct hvb_buf *buf2) 1257310c0d0Sopenharmony_ci{ 1267310c0d0Sopenharmony_ci return buf1->size == buf2->size && hvb_memcmp(buf1->addr, buf2->addr, buf1->size) == 0; 1277310c0d0Sopenharmony_ci} 1287310c0d0Sopenharmony_ci 1297310c0d0Sopenharmony_cistatic enum hvb_errno hvb_walk_verify_nodes(struct hvb_ops *ops, const char *const *ptn_list, 1307310c0d0Sopenharmony_ci struct hvb_buf *rvt, struct hvb_verified_data *vd) 1317310c0d0Sopenharmony_ci{ 1327310c0d0Sopenharmony_ci enum hvb_errno ret = HVB_OK; 1337310c0d0Sopenharmony_ci uint32_t i, nodes_num; 1347310c0d0Sopenharmony_ci struct hvb_buf pubk_descs; 1357310c0d0Sopenharmony_ci struct rvt_pubk_desc desc; 1367310c0d0Sopenharmony_ci struct hvb_buf expected_pubk; 1377310c0d0Sopenharmony_ci struct hvb_buf cert_pubk; 1387310c0d0Sopenharmony_ci struct rvt_image_header header; 1397310c0d0Sopenharmony_ci uint64_t desc_size; 1407310c0d0Sopenharmony_ci 1417310c0d0Sopenharmony_ci desc_size = sizeof(desc) - (PUBKEY_LEN - vd->key_len); 1427310c0d0Sopenharmony_ci ret = hvb_rvt_head_parser(rvt, &header, desc_size); 1437310c0d0Sopenharmony_ci if (ret != HVB_OK) { 1447310c0d0Sopenharmony_ci hvb_print("error, parse rvt header.\n"); 1457310c0d0Sopenharmony_ci goto fail; 1467310c0d0Sopenharmony_ci } 1477310c0d0Sopenharmony_ci 1487310c0d0Sopenharmony_ci nodes_num = header.verity_num; 1497310c0d0Sopenharmony_ci ret = hvb_rvt_get_pubk_desc(rvt, &pubk_descs); 1507310c0d0Sopenharmony_ci if (ret != HVB_OK) { 1517310c0d0Sopenharmony_ci hvb_print("error, pubk descs.\n"); 1527310c0d0Sopenharmony_ci goto fail; 1537310c0d0Sopenharmony_ci } 1547310c0d0Sopenharmony_ci 1557310c0d0Sopenharmony_ci for (i = 0; i < nodes_num; i++) { 1567310c0d0Sopenharmony_ci ret = hvb_rvt_pubk_desc_parser(&pubk_descs, &desc, desc_size); 1577310c0d0Sopenharmony_ci if (ret != HVB_OK) { 1587310c0d0Sopenharmony_ci hvb_print("errror, parser rvt k descs\n"); 1597310c0d0Sopenharmony_ci goto fail; 1607310c0d0Sopenharmony_ci } 1617310c0d0Sopenharmony_ci 1627310c0d0Sopenharmony_ci ret = hvb_rvt_get_pubk_buf(&expected_pubk, rvt, &desc); 1637310c0d0Sopenharmony_ci if (ret != HVB_OK) { 1647310c0d0Sopenharmony_ci hvb_print("errror, get pubk buf\n"); 1657310c0d0Sopenharmony_ci goto fail; 1667310c0d0Sopenharmony_ci } 1677310c0d0Sopenharmony_ci 1687310c0d0Sopenharmony_ci ret = footer_init_desc(ops, &desc.name[0], ptn_list, &cert_pubk, vd); 1697310c0d0Sopenharmony_ci if (ret != HVB_OK) { 1707310c0d0Sopenharmony_ci hvb_printv("error, verity partition: ", desc.name, "\n", NULL); 1717310c0d0Sopenharmony_ci goto fail; 1727310c0d0Sopenharmony_ci } 1737310c0d0Sopenharmony_ci 1747310c0d0Sopenharmony_ci if (hvb_buf_equal(&expected_pubk, &cert_pubk) != true) { 1757310c0d0Sopenharmony_ci ret = HVB_ERROR_PUBLIC_KEY_REJECTED; 1767310c0d0Sopenharmony_ci hvb_printv("error, compare public key: ", desc.name, "\n", NULL); 1777310c0d0Sopenharmony_ci goto fail; 1787310c0d0Sopenharmony_ci } 1797310c0d0Sopenharmony_ci 1807310c0d0Sopenharmony_ci pubk_descs.addr += desc_size; 1817310c0d0Sopenharmony_ci } 1827310c0d0Sopenharmony_ci 1837310c0d0Sopenharmony_cifail: 1847310c0d0Sopenharmony_ci return ret; 1857310c0d0Sopenharmony_ci} 1867310c0d0Sopenharmony_ci 1877310c0d0Sopenharmony_cistatic char const **hash_ptn_list_add_rvt(const char *const *hash_ptn_list, const char *rvt_ptn) 1887310c0d0Sopenharmony_ci{ 1897310c0d0Sopenharmony_ci size_t n; 1907310c0d0Sopenharmony_ci bool need_add_rvt = true; 1917310c0d0Sopenharmony_ci char const **ptn = NULL; 1927310c0d0Sopenharmony_ci size_t num_parttions = 0; 1937310c0d0Sopenharmony_ci 1947310c0d0Sopenharmony_ci if (hash_ptn_list != NULL) { 1957310c0d0Sopenharmony_ci while (hash_ptn_list[num_parttions] != NULL) { 1967310c0d0Sopenharmony_ci num_parttions++; 1977310c0d0Sopenharmony_ci } 1987310c0d0Sopenharmony_ci } 1997310c0d0Sopenharmony_ci 2007310c0d0Sopenharmony_ci num_parttions += REQUEST_LIST_LEN; 2017310c0d0Sopenharmony_ci 2027310c0d0Sopenharmony_ci ptn = (char const **)hvb_calloc(num_parttions * sizeof(char *)); 2037310c0d0Sopenharmony_ci if (ptn == NULL) { 2047310c0d0Sopenharmony_ci hvb_print("error, alloc ptn\n"); 2057310c0d0Sopenharmony_ci return NULL; 2067310c0d0Sopenharmony_ci } 2077310c0d0Sopenharmony_ci 2087310c0d0Sopenharmony_ci for (n = 0; n < num_parttions - REQUEST_LIST_LEN; n++) { 2097310c0d0Sopenharmony_ci ptn[n] = hash_ptn_list[n]; 2107310c0d0Sopenharmony_ci if (hvb_strncmp(ptn[n], rvt_ptn, HVB_MAX_PARTITION_NAME_LEN) == 0) { 2117310c0d0Sopenharmony_ci need_add_rvt = false; 2127310c0d0Sopenharmony_ci } 2137310c0d0Sopenharmony_ci } 2147310c0d0Sopenharmony_ci 2157310c0d0Sopenharmony_ci if (need_add_rvt) { 2167310c0d0Sopenharmony_ci ptn[num_parttions - REQUEST_LIST_LEN] = rvt_ptn; 2177310c0d0Sopenharmony_ci } 2187310c0d0Sopenharmony_ci 2197310c0d0Sopenharmony_ci return ptn; 2207310c0d0Sopenharmony_ci} 2217310c0d0Sopenharmony_ci 2227310c0d0Sopenharmony_cienum hvb_errno hvb_chain_verify(struct hvb_ops *ops, 2237310c0d0Sopenharmony_ci const char *rvt_ptn, 2247310c0d0Sopenharmony_ci const char *const *hash_ptn_list, 2257310c0d0Sopenharmony_ci struct hvb_verified_data **out_vd) 2267310c0d0Sopenharmony_ci{ 2277310c0d0Sopenharmony_ci enum hvb_errno ret = HVB_OK; 2287310c0d0Sopenharmony_ci struct hvb_buf *rvt_image = NULL; 2297310c0d0Sopenharmony_ci struct hvb_verified_data *vd = NULL; 2307310c0d0Sopenharmony_ci char const **ptn_list = NULL; 2317310c0d0Sopenharmony_ci 2327310c0d0Sopenharmony_ci hvb_return_hvb_err_if_null(ops); 2337310c0d0Sopenharmony_ci hvb_return_hvb_err_if_null(rvt_ptn); 2347310c0d0Sopenharmony_ci hvb_return_hvb_err_if_null(out_vd); 2357310c0d0Sopenharmony_ci ret = check_hvb_ops(ops); 2367310c0d0Sopenharmony_ci if (ret != HVB_OK) { 2377310c0d0Sopenharmony_ci hvb_print("error, check ops\n"); 2387310c0d0Sopenharmony_ci return HVB_ERROR_INVALID_ARGUMENT; 2397310c0d0Sopenharmony_ci } 2407310c0d0Sopenharmony_ci 2417310c0d0Sopenharmony_ci if (hvb_strnlen(rvt_ptn, HVB_MAX_PARTITION_NAME_LEN) >= HVB_MAX_PARTITION_NAME_LEN) { 2427310c0d0Sopenharmony_ci hvb_print("error, check rvt partition name\n"); 2437310c0d0Sopenharmony_ci return HVB_ERROR_INVALID_ARGUMENT; 2447310c0d0Sopenharmony_ci } 2457310c0d0Sopenharmony_ci 2467310c0d0Sopenharmony_ci ptn_list = hash_ptn_list_add_rvt(hash_ptn_list, rvt_ptn); 2477310c0d0Sopenharmony_ci if (ptn_list == NULL) { 2487310c0d0Sopenharmony_ci hvb_print("error, add rvt\n"); 2497310c0d0Sopenharmony_ci return HVB_ERROR_OOM; 2507310c0d0Sopenharmony_ci } 2517310c0d0Sopenharmony_ci 2527310c0d0Sopenharmony_ci vd = hvb_init_verified_data(); 2537310c0d0Sopenharmony_ci if (!vd) { 2547310c0d0Sopenharmony_ci hvb_print("malloc verified_data fail\n"); 2557310c0d0Sopenharmony_ci ret = HVB_ERROR_OOM; 2567310c0d0Sopenharmony_ci goto fail; 2577310c0d0Sopenharmony_ci } 2587310c0d0Sopenharmony_ci 2597310c0d0Sopenharmony_ci /* verity rvt cert */ 2607310c0d0Sopenharmony_ci ret = hvb_rvt_verify_root(ops, rvt_ptn, ptn_list, vd); 2617310c0d0Sopenharmony_ci if (ret != HVB_OK) { 2627310c0d0Sopenharmony_ci hvb_print("error, verity rvt partition.\n"); 2637310c0d0Sopenharmony_ci goto fail; 2647310c0d0Sopenharmony_ci } 2657310c0d0Sopenharmony_ci 2667310c0d0Sopenharmony_ci /* get rvt image */ 2677310c0d0Sopenharmony_ci rvt_image = hvb_get_partition_image(vd, rvt_ptn); 2687310c0d0Sopenharmony_ci if (!rvt_image) { 2697310c0d0Sopenharmony_ci hvb_print("error, get rvt ptn.\n"); 2707310c0d0Sopenharmony_ci ret = HVB_ERROR_OOM; 2717310c0d0Sopenharmony_ci goto fail; 2727310c0d0Sopenharmony_ci } 2737310c0d0Sopenharmony_ci 2747310c0d0Sopenharmony_ci /* walk verify all nodes from rvt */ 2757310c0d0Sopenharmony_ci ret = hvb_walk_verify_nodes(ops, ptn_list, rvt_image, vd); 2767310c0d0Sopenharmony_ci if (ret != HVB_OK) { 2777310c0d0Sopenharmony_ci hvb_print("error, walk nodes.\n"); 2787310c0d0Sopenharmony_ci goto fail; 2797310c0d0Sopenharmony_ci } 2807310c0d0Sopenharmony_ci 2817310c0d0Sopenharmony_ci /* creat cmdline info */ 2827310c0d0Sopenharmony_ci ret = hvb_creat_cmdline(ops, vd); 2837310c0d0Sopenharmony_ci if (ret != HVB_OK) { 2847310c0d0Sopenharmony_ci hvb_print("error, create cmdline.\n"); 2857310c0d0Sopenharmony_ci goto fail; 2867310c0d0Sopenharmony_ci } 2877310c0d0Sopenharmony_ci 2887310c0d0Sopenharmony_ci *out_vd = vd; 2897310c0d0Sopenharmony_ci 2907310c0d0Sopenharmony_cifail: 2917310c0d0Sopenharmony_ci if (vd != NULL && ret != HVB_OK) { 2927310c0d0Sopenharmony_ci hvb_chain_verify_data_free(vd); 2937310c0d0Sopenharmony_ci hvb_free(vd); 2947310c0d0Sopenharmony_ci } 2957310c0d0Sopenharmony_ci 2967310c0d0Sopenharmony_ci hvb_free(ptn_list); 2977310c0d0Sopenharmony_ci 2987310c0d0Sopenharmony_ci return ret; 2997310c0d0Sopenharmony_ci} 3007310c0d0Sopenharmony_ci 3017310c0d0Sopenharmony_civoid hvb_chain_verify_data_free(struct hvb_verified_data *vd) 3027310c0d0Sopenharmony_ci{ 3037310c0d0Sopenharmony_ci uint64_t n; 3047310c0d0Sopenharmony_ci 3057310c0d0Sopenharmony_ci if (vd == NULL) { 3067310c0d0Sopenharmony_ci hvb_print("vd is NULL, do nothing\n"); 3077310c0d0Sopenharmony_ci return; 3087310c0d0Sopenharmony_ci } 3097310c0d0Sopenharmony_ci 3107310c0d0Sopenharmony_ci for (n = 0; n < vd->num_loaded_certs && vd->certs; n++) { 3117310c0d0Sopenharmony_ci if (vd->certs[n].data.addr != NULL) 3127310c0d0Sopenharmony_ci hvb_free(vd->certs[n].data.addr); 3137310c0d0Sopenharmony_ci 3147310c0d0Sopenharmony_ci if (vd->certs[n].partition_name != NULL) { 3157310c0d0Sopenharmony_ci hvb_free(vd->certs[n].partition_name); 3167310c0d0Sopenharmony_ci } 3177310c0d0Sopenharmony_ci } 3187310c0d0Sopenharmony_ci 3197310c0d0Sopenharmony_ci if (vd->certs != NULL) { 3207310c0d0Sopenharmony_ci hvb_free(vd->certs); 3217310c0d0Sopenharmony_ci } 3227310c0d0Sopenharmony_ci 3237310c0d0Sopenharmony_ci for (n = 0; n < vd->num_loaded_images && vd->images; n++) { 3247310c0d0Sopenharmony_ci if (vd->images[n].data.addr != NULL) 3257310c0d0Sopenharmony_ci hvb_free(vd->images[n].data.addr); 3267310c0d0Sopenharmony_ci 3277310c0d0Sopenharmony_ci if (vd->images[n].partition_name != NULL) 3287310c0d0Sopenharmony_ci hvb_free(vd->images[n].partition_name); 3297310c0d0Sopenharmony_ci } 3307310c0d0Sopenharmony_ci 3317310c0d0Sopenharmony_ci if (vd->images != NULL) { 3327310c0d0Sopenharmony_ci hvb_free(vd->images); 3337310c0d0Sopenharmony_ci } 3347310c0d0Sopenharmony_ci 3357310c0d0Sopenharmony_ci if (vd->cmdline.buf != NULL) { 3367310c0d0Sopenharmony_ci hvb_free(vd->cmdline.buf); 3377310c0d0Sopenharmony_ci } 3387310c0d0Sopenharmony_ci 3397310c0d0Sopenharmony_ci hvb_memset((uint8_t *)vd, 0, sizeof(*vd)); 3407310c0d0Sopenharmony_ci} 341