• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "hvb_footer.h"
16 #include "hvb_util.h"
17 #include "hvb_cert.h"
18 #include "hvb_sysdeps.h"
19 
_footer_parser(struct hvb_footer * footer,struct hvb_buf * footer_buf)20 static enum hvb_errno _footer_parser(struct hvb_footer *footer, struct hvb_buf *footer_buf)
21 {
22     uint64_t size;
23 
24     if (footer_buf->size < sizeof(*footer)) {
25         hvb_print("footer src size error.\n");
26         return HVB_ERROR_INVALID_FOOTER_FORMAT;
27     }
28 
29     hvb_memcpy((uint8_t *)footer, footer_buf->addr, sizeof(*footer));
30 
31     /* Check that magic is correct. */
32     if (hvb_memcmp(footer->magic, HVB_FOOTER_MAGIC, sizeof(footer->magic)) != 0) {
33         hvb_print("Footer magic is incorrect.\n");
34         return HVB_ERROR_INVALID_FOOTER_FORMAT;
35     }
36 
37     /* check these size is correct */
38     size = footer->image_size + footer->cert_size + footer_buf->size;
39     if (size < footer->image_size || size > footer->partition_size) {
40         hvb_print("Invalid image_size in footer.\n");
41         return HVB_ERROR_INVALID_FOOTER_FORMAT;
42     }
43 
44     return HVB_OK;
45 }
46 
_load_and_parse_footer(struct hvb_ops * ops,struct hvb_footer * footer,const char * ptn)47 static enum hvb_errno _load_and_parse_footer(struct hvb_ops *ops, struct hvb_footer *footer, const char *ptn)
48 {
49     enum hvb_errno ret = HVB_OK;
50     uint64_t read_bytes = 0;
51     enum hvb_io_errno io_ret = HVB_IO_OK;
52     uint8_t buf[HVB_FOOTER_SIZE] = {0};
53     struct hvb_buf footer_buf = {&buf[0], sizeof(buf)};
54 
55     io_ret = ops->read_partition(ops, ptn, -HVB_FOOTER_SIZE, HVB_FOOTER_SIZE, footer_buf.addr, &read_bytes);
56     if (io_ret != HVB_IO_OK) {
57         hvb_printv(ptn, ": error, loading data.\n", NULL);
58         return HVB_ERROR_IO;
59     }
60 
61     if (read_bytes != footer_buf.size) {
62         hvb_printv(ptn, ": Read incorrect number of bytes.\n", NULL);
63         return HVB_ERROR_IO;
64     }
65 
66     ret = _footer_parser(footer, &footer_buf);
67     if (ret != HVB_OK) {
68         hvb_printv(ptn, ": No footer detected,.\n", NULL);
69         return ret;
70     }
71 
72     return HVB_OK;
73 }
74 
_load_cert(struct hvb_ops * ops,struct hvb_buf * cert,const char * ptn,struct hvb_footer * footer)75 static enum hvb_errno _load_cert(struct hvb_ops *ops, struct hvb_buf *cert, const char *ptn, struct hvb_footer *footer)
76 {
77     enum hvb_io_errno io_ret = HVB_IO_OK;
78     uint64_t read_bytes = 0;
79     uint64_t offset = footer->cert_offset;
80 
81     io_ret = ops->read_partition(ops, ptn, offset, cert->size, cert->addr, &read_bytes);
82     if (io_ret != HVB_IO_OK) {
83         hvb_printv(ptn, ": error loading signature data.\n", NULL);
84         return HVB_ERROR_IO;
85     }
86 
87     if (cert->size != read_bytes) {
88         hvb_printv(ptn, ": Read incorrect number of bytes from.\n", NULL);
89         return HVB_ERROR_IO;
90     }
91 
92     return HVB_OK;
93 }
94 
footer_init_desc(struct hvb_ops * ops,const char * ptn,const char * const * hash_ptn_list,struct hvb_buf * out_pubk,struct hvb_verified_data * vd)95 enum hvb_errno footer_init_desc(struct hvb_ops *ops, const char *ptn, const char *const *hash_ptn_list,
96                                 struct hvb_buf *out_pubk, struct hvb_verified_data *vd)
97 {
98     enum hvb_errno ret = HVB_OK;
99     struct hvb_buf cert_buf = {NULL, 0};
100     struct hvb_footer footer = {0};
101     struct hvb_cert_data *cert_info = NULL;
102 
103     ret = _load_and_parse_footer(ops, &footer, ptn);
104     if (ret != HVB_OK)
105         return ret;
106 
107     cert_buf.size = footer.cert_size;
108     cert_buf.addr = hvb_malloc(cert_buf.size);
109     if (!cert_buf.addr) {
110         hvb_print("error, alloc cert buf\n");
111         return HVB_ERROR_OOM;
112     }
113 
114     ret = _load_cert(ops, &cert_buf, ptn, &footer);
115     if (ret != HVB_OK)
116         goto out;
117 
118     ret = cert_init_desc(ops, ptn, &cert_buf, hash_ptn_list, out_pubk, vd);
119     if (ret != HVB_OK)
120         goto out;
121 
122     if (vd->num_loaded_certs >= HVB_MAX_NUMBER_OF_LOADED_CERTS) {
123         hvb_print("error, too many certs\n");
124         ret = HVB_ERROR_OOM;
125         goto out;
126     }
127 
128     cert_info = &vd->certs[vd->num_loaded_certs++];
129     cert_info->partition_name = hvb_strdup(ptn);
130     cert_info->data = cert_buf;
131     cert_info->verify_result = ret;
132 
133     return ret;
134 
135 out:
136     if (cert_buf.addr != NULL)
137         hvb_free(cert_buf.addr);
138 
139     return ret;
140 }
141