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 "hvb_footer.h" 167310c0d0Sopenharmony_ci#include "hvb_util.h" 177310c0d0Sopenharmony_ci#include "hvb_cert.h" 187310c0d0Sopenharmony_ci#include "hvb_sysdeps.h" 197310c0d0Sopenharmony_ci 207310c0d0Sopenharmony_cistatic enum hvb_errno _footer_parser(struct hvb_footer *footer, struct hvb_buf *footer_buf) 217310c0d0Sopenharmony_ci{ 227310c0d0Sopenharmony_ci uint64_t size; 237310c0d0Sopenharmony_ci 247310c0d0Sopenharmony_ci if (footer_buf->size < sizeof(*footer)) { 257310c0d0Sopenharmony_ci hvb_print("footer src size error.\n"); 267310c0d0Sopenharmony_ci return HVB_ERROR_INVALID_FOOTER_FORMAT; 277310c0d0Sopenharmony_ci } 287310c0d0Sopenharmony_ci if (hvb_memcpy_s(footer, sizeof(*footer), footer_buf->addr, sizeof(*footer)) != 0) { 297310c0d0Sopenharmony_ci hvb_print("error, copy footer.\n"); 307310c0d0Sopenharmony_ci return HVB_ERROR_OOM; 317310c0d0Sopenharmony_ci } 327310c0d0Sopenharmony_ci 337310c0d0Sopenharmony_ci /* Check that magic is correct. */ 347310c0d0Sopenharmony_ci if (hvb_memcmp(footer->magic, HVB_FOOTER_MAGIC, sizeof(footer->magic)) != 0) { 357310c0d0Sopenharmony_ci hvb_print("Footer magic is incorrect.\n"); 367310c0d0Sopenharmony_ci return HVB_ERROR_INVALID_FOOTER_FORMAT; 377310c0d0Sopenharmony_ci } 387310c0d0Sopenharmony_ci 397310c0d0Sopenharmony_ci /* check these size is correct */ 407310c0d0Sopenharmony_ci if (footer->partition_size > HVB_MAX_PARTITION_SIZE || 417310c0d0Sopenharmony_ci footer->partition_size < HVB_MIN_PARTITION_SIZE) { 427310c0d0Sopenharmony_ci hvb_print("Invalid partition_size in footer.\n"); 437310c0d0Sopenharmony_ci return HVB_ERROR_INVALID_FOOTER_FORMAT; 447310c0d0Sopenharmony_ci } 457310c0d0Sopenharmony_ci 467310c0d0Sopenharmony_ci size = footer->image_size + footer->cert_size + HVB_FOOTER_SIZE; 477310c0d0Sopenharmony_ci if (footer->image_size >= footer->partition_size || 487310c0d0Sopenharmony_ci size < footer->image_size + HVB_FOOTER_SIZE || 497310c0d0Sopenharmony_ci size > footer->partition_size) { 507310c0d0Sopenharmony_ci hvb_print("Invalid image_size in footer.\n"); 517310c0d0Sopenharmony_ci return HVB_ERROR_INVALID_FOOTER_FORMAT; 527310c0d0Sopenharmony_ci } 537310c0d0Sopenharmony_ci 547310c0d0Sopenharmony_ci size = footer->cert_offset + footer->cert_size + HVB_FOOTER_SIZE; 557310c0d0Sopenharmony_ci if (footer->cert_offset < footer->image_size || 567310c0d0Sopenharmony_ci size < footer->cert_offset + HVB_FOOTER_SIZE || 577310c0d0Sopenharmony_ci size > footer->partition_size) { 587310c0d0Sopenharmony_ci hvb_print("Invalid cert info in footer.\n"); 597310c0d0Sopenharmony_ci return HVB_ERROR_INVALID_FOOTER_FORMAT; 607310c0d0Sopenharmony_ci } 617310c0d0Sopenharmony_ci 627310c0d0Sopenharmony_ci return HVB_OK; 637310c0d0Sopenharmony_ci} 647310c0d0Sopenharmony_ci 657310c0d0Sopenharmony_cistatic enum hvb_errno _load_and_parse_footer(struct hvb_ops *ops, struct hvb_footer *footer, const char *ptn) 667310c0d0Sopenharmony_ci{ 677310c0d0Sopenharmony_ci enum hvb_errno ret = HVB_OK; 687310c0d0Sopenharmony_ci uint64_t read_bytes = 0; 697310c0d0Sopenharmony_ci enum hvb_io_errno io_ret = HVB_IO_OK; 707310c0d0Sopenharmony_ci uint8_t buf[HVB_FOOTER_SIZE] = {0}; 717310c0d0Sopenharmony_ci struct hvb_buf footer_buf = {&buf[0], sizeof(buf)}; 727310c0d0Sopenharmony_ci 737310c0d0Sopenharmony_ci io_ret = ops->read_partition(ops, ptn, -HVB_FOOTER_SIZE, HVB_FOOTER_SIZE, footer_buf.addr, &read_bytes); 747310c0d0Sopenharmony_ci if (io_ret != HVB_IO_OK) { 757310c0d0Sopenharmony_ci hvb_printv(ptn, ": error, loading data.\n", NULL); 767310c0d0Sopenharmony_ci return HVB_ERROR_IO; 777310c0d0Sopenharmony_ci } 787310c0d0Sopenharmony_ci 797310c0d0Sopenharmony_ci if (read_bytes != footer_buf.size) { 807310c0d0Sopenharmony_ci hvb_printv(ptn, ": Read incorrect number of bytes.\n", NULL); 817310c0d0Sopenharmony_ci return HVB_ERROR_IO; 827310c0d0Sopenharmony_ci } 837310c0d0Sopenharmony_ci 847310c0d0Sopenharmony_ci ret = _footer_parser(footer, &footer_buf); 857310c0d0Sopenharmony_ci if (ret != HVB_OK) { 867310c0d0Sopenharmony_ci hvb_printv(ptn, ": No footer detected,.\n", NULL); 877310c0d0Sopenharmony_ci return ret; 887310c0d0Sopenharmony_ci } 897310c0d0Sopenharmony_ci 907310c0d0Sopenharmony_ci return HVB_OK; 917310c0d0Sopenharmony_ci} 927310c0d0Sopenharmony_ci 937310c0d0Sopenharmony_cistatic enum hvb_errno _load_cert(struct hvb_ops *ops, struct hvb_buf *cert, const char *ptn, struct hvb_footer *footer) 947310c0d0Sopenharmony_ci{ 957310c0d0Sopenharmony_ci enum hvb_io_errno io_ret = HVB_IO_OK; 967310c0d0Sopenharmony_ci uint64_t read_bytes = 0; 977310c0d0Sopenharmony_ci uint64_t offset = footer->cert_offset; 987310c0d0Sopenharmony_ci 997310c0d0Sopenharmony_ci io_ret = ops->read_partition(ops, ptn, offset, cert->size, cert->addr, &read_bytes); 1007310c0d0Sopenharmony_ci if (io_ret != HVB_IO_OK) { 1017310c0d0Sopenharmony_ci hvb_printv(ptn, ": error loading signature data.\n", NULL); 1027310c0d0Sopenharmony_ci return HVB_ERROR_IO; 1037310c0d0Sopenharmony_ci } 1047310c0d0Sopenharmony_ci 1057310c0d0Sopenharmony_ci if (cert->size != read_bytes) { 1067310c0d0Sopenharmony_ci hvb_printv(ptn, ": Read incorrect number of bytes from.\n", NULL); 1077310c0d0Sopenharmony_ci return HVB_ERROR_IO; 1087310c0d0Sopenharmony_ci } 1097310c0d0Sopenharmony_ci 1107310c0d0Sopenharmony_ci return HVB_OK; 1117310c0d0Sopenharmony_ci} 1127310c0d0Sopenharmony_ci 1137310c0d0Sopenharmony_cienum hvb_errno footer_init_desc(struct hvb_ops *ops, const char *ptn, const char *const *hash_ptn_list, 1147310c0d0Sopenharmony_ci struct hvb_buf *out_pubk, struct hvb_verified_data *vd) 1157310c0d0Sopenharmony_ci{ 1167310c0d0Sopenharmony_ci hvb_return_hvb_err_if_null(ops); 1177310c0d0Sopenharmony_ci hvb_return_hvb_err_if_null(ptn); 1187310c0d0Sopenharmony_ci hvb_return_hvb_err_if_null(out_pubk); 1197310c0d0Sopenharmony_ci hvb_return_hvb_err_if_null(vd); 1207310c0d0Sopenharmony_ci 1217310c0d0Sopenharmony_ci enum hvb_errno ret = HVB_OK; 1227310c0d0Sopenharmony_ci struct hvb_buf cert_buf = {NULL, 0}; 1237310c0d0Sopenharmony_ci struct hvb_footer footer = {0}; 1247310c0d0Sopenharmony_ci struct hvb_cert_data *cert_info = NULL; 1257310c0d0Sopenharmony_ci 1267310c0d0Sopenharmony_ci ret = check_hvb_ops(ops); 1277310c0d0Sopenharmony_ci if (ret != HVB_OK) { 1287310c0d0Sopenharmony_ci hvb_print("error, check ops\n"); 1297310c0d0Sopenharmony_ci return HVB_ERROR_INVALID_ARGUMENT; 1307310c0d0Sopenharmony_ci } 1317310c0d0Sopenharmony_ci if (hvb_strnlen(ptn, HVB_MAX_PARTITION_NAME_LEN) >= HVB_MAX_PARTITION_NAME_LEN) { 1327310c0d0Sopenharmony_ci hvb_print("error, check partition name\n"); 1337310c0d0Sopenharmony_ci return HVB_ERROR_INVALID_ARGUMENT; 1347310c0d0Sopenharmony_ci } 1357310c0d0Sopenharmony_ci 1367310c0d0Sopenharmony_ci ret = _load_and_parse_footer(ops, &footer, ptn); 1377310c0d0Sopenharmony_ci if (ret != HVB_OK) 1387310c0d0Sopenharmony_ci return ret; 1397310c0d0Sopenharmony_ci 1407310c0d0Sopenharmony_ci cert_buf.size = footer.cert_size; 1417310c0d0Sopenharmony_ci cert_buf.addr = hvb_malloc(cert_buf.size); 1427310c0d0Sopenharmony_ci if (!cert_buf.addr) { 1437310c0d0Sopenharmony_ci hvb_print("error, alloc cert buf\n"); 1447310c0d0Sopenharmony_ci return HVB_ERROR_OOM; 1457310c0d0Sopenharmony_ci } 1467310c0d0Sopenharmony_ci 1477310c0d0Sopenharmony_ci ret = _load_cert(ops, &cert_buf, ptn, &footer); 1487310c0d0Sopenharmony_ci if (ret != HVB_OK) 1497310c0d0Sopenharmony_ci goto out; 1507310c0d0Sopenharmony_ci 1517310c0d0Sopenharmony_ci ret = cert_init_desc(ops, ptn, &cert_buf, hash_ptn_list, out_pubk, vd); 1527310c0d0Sopenharmony_ci if (ret != HVB_OK) 1537310c0d0Sopenharmony_ci goto out; 1547310c0d0Sopenharmony_ci 1557310c0d0Sopenharmony_ci if (vd->num_loaded_certs >= HVB_MAX_NUMBER_OF_LOADED_CERTS) { 1567310c0d0Sopenharmony_ci hvb_print("error, too many certs\n"); 1577310c0d0Sopenharmony_ci ret = HVB_ERROR_OOM; 1587310c0d0Sopenharmony_ci goto out; 1597310c0d0Sopenharmony_ci } 1607310c0d0Sopenharmony_ci 1617310c0d0Sopenharmony_ci cert_info = &vd->certs[vd->num_loaded_certs++]; 1627310c0d0Sopenharmony_ci cert_info->partition_name = hvb_strdup(ptn); 1637310c0d0Sopenharmony_ci cert_info->data = cert_buf; 1647310c0d0Sopenharmony_ci cert_info->verify_result = ret; 1657310c0d0Sopenharmony_ci 1667310c0d0Sopenharmony_ci return ret; 1677310c0d0Sopenharmony_ci 1687310c0d0Sopenharmony_ciout: 1697310c0d0Sopenharmony_ci if (cert_buf.addr != NULL) 1707310c0d0Sopenharmony_ci hvb_free(cert_buf.addr); 1717310c0d0Sopenharmony_ci 1727310c0d0Sopenharmony_ci return ret; 1737310c0d0Sopenharmony_ci} 174