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