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 <stdio.h>
16 #include <stdlib.h>
17 #include "hvb_footer.h"
18 #include "hvb_crypto.h"
19 #include "hvb_ops.h"
20 #include "hvb_rvt.h"
21 #include "hvb_cert.h"
22 #include "hvb_sysdeps.h"
23 #include "hvb_util.h"
24 #include "hvb_cmdline.h"
25 #include "hvb.h"
26
hvb_init_verified_data(void)27 struct hvb_verified_data *hvb_init_verified_data(void)
28 {
29 struct hvb_verified_data *vd = NULL;
30
31 vd = hvb_calloc(sizeof(*vd));
32 if (!vd) {
33 hvb_print("malloc verified_data fail\n");
34 return NULL;
35 }
36
37 vd->certs = hvb_calloc(sizeof(struct hvb_cert_data) * HVB_MAX_NUMBER_OF_LOADED_CERTS);
38 if (!vd->certs) {
39 hvb_print("malloc certs fail\n");
40 goto fail;
41 }
42
43 vd->images = hvb_calloc(sizeof(struct hvb_image_data) * HVB_MAX_NUMBER_OF_LOADED_IMAGES);
44 if (!vd->images) {
45 hvb_print("malloc images fail\n");
46 goto fail;
47 }
48
49 vd->num_loaded_certs = 0;
50 vd->num_loaded_images = 0;
51
52 vd->cmdline.buf = hvb_calloc(CMD_LINE_SIZE);
53 if (!vd->cmdline.buf) {
54 hvb_print("malloc cmdline fail\n");
55 goto fail;
56 }
57
58 vd->cmdline.cur_pos = 0;
59 vd->cmdline.max_size = CMD_LINE_SIZE;
60
61 vd->key_len = 0;
62
63 return vd;
64
65 fail:
66 hvb_chain_verify_data_free(vd);
67 hvb_free(vd);
68 vd = NULL;
69 return vd;
70 }
71
hvb_rvt_verify_root(struct hvb_ops * ops,const char * ptn,const char * const * ptn_list,struct hvb_verified_data * vd)72 static enum hvb_errno hvb_rvt_verify_root(struct hvb_ops *ops, const char *ptn,
73 const char *const *ptn_list,
74 struct hvb_verified_data *vd)
75 {
76 enum hvb_errno ret = HVB_OK;
77 enum hvb_io_errno io_ret = HVB_IO_OK;
78 bool is_trusted = false;
79 struct hvb_buf cert_pubk = {0};
80
81 ret = footer_init_desc(ops, ptn, ptn_list, &cert_pubk, vd);
82 if (ret != HVB_OK) {
83 hvb_printv("error verity partition: ", ptn, "\n", NULL);
84 goto fail;
85 }
86
87 io_ret = ops->valid_rvt_key(ops, cert_pubk.addr, cert_pubk.size, NULL, 0, &is_trusted);
88 if (io_ret != HVB_IO_OK) {
89 ret = HVB_ERROR_PUBLIC_KEY_REJECTED;
90 hvb_print("error, rvt public key invalid\n");
91 goto fail;
92 }
93
94 if (is_trusted == false) {
95 ret = HVB_ERROR_PUBLIC_KEY_REJECTED;
96 hvb_print("error, rvt public key rejected\n");
97 goto fail;
98 }
99
100 fail:
101 return ret;
102 }
103
hvb_get_partition_image(struct hvb_verified_data * vd,const char * ptn)104 static struct hvb_buf *hvb_get_partition_image(struct hvb_verified_data *vd, const char *ptn)
105 {
106 struct hvb_image_data *p = vd->images;
107 struct hvb_image_data *end = p + vd->num_loaded_images;
108 size_t name_len = hvb_strnlen(ptn, HVB_MAX_PARTITION_NAME_LEN);
109 if (name_len >= HVB_MAX_PARTITION_NAME_LEN) {
110 hvb_print("invalid ptn name len\n");
111 return NULL;
112 }
113
114 for (; p < end; p++) {
115 if (hvb_strnlen(p->partition_name, HVB_MAX_PARTITION_NAME_LEN) == name_len &&
116 hvb_strncmp(ptn, p->partition_name, HVB_MAX_PARTITION_NAME_LEN) == 0) {
117 return &p->data;
118 }
119 }
120
121 return NULL;
122 }
123
hvb_buf_equal(const struct hvb_buf * buf1,const struct hvb_buf * buf2)124 static bool hvb_buf_equal(const struct hvb_buf *buf1, const struct hvb_buf *buf2)
125 {
126 return buf1->size == buf2->size && hvb_memcmp(buf1->addr, buf2->addr, buf1->size) == 0;
127 }
128
hvb_walk_verify_nodes(struct hvb_ops * ops,const char * const * ptn_list,struct hvb_buf * rvt,struct hvb_verified_data * vd)129 static enum hvb_errno hvb_walk_verify_nodes(struct hvb_ops *ops, const char *const *ptn_list,
130 struct hvb_buf *rvt, struct hvb_verified_data *vd)
131 {
132 enum hvb_errno ret = HVB_OK;
133 uint32_t i, nodes_num;
134 struct hvb_buf pubk_descs;
135 struct rvt_pubk_desc desc;
136 struct hvb_buf expected_pubk;
137 struct hvb_buf cert_pubk;
138 struct rvt_image_header header;
139 uint64_t desc_size;
140
141 desc_size = sizeof(desc) - (PUBKEY_LEN - vd->key_len);
142 ret = hvb_rvt_head_parser(rvt, &header, desc_size);
143 if (ret != HVB_OK) {
144 hvb_print("error, parse rvt header.\n");
145 goto fail;
146 }
147
148 nodes_num = header.verity_num;
149 ret = hvb_rvt_get_pubk_desc(rvt, &pubk_descs);
150 if (ret != HVB_OK) {
151 hvb_print("error, pubk descs.\n");
152 goto fail;
153 }
154
155 for (i = 0; i < nodes_num; i++) {
156 ret = hvb_rvt_pubk_desc_parser(&pubk_descs, &desc, desc_size);
157 if (ret != HVB_OK) {
158 hvb_print("errror, parser rvt k descs\n");
159 goto fail;
160 }
161
162 ret = hvb_rvt_get_pubk_buf(&expected_pubk, rvt, &desc);
163 if (ret != HVB_OK) {
164 hvb_print("errror, get pubk buf\n");
165 goto fail;
166 }
167
168 ret = footer_init_desc(ops, &desc.name[0], ptn_list, &cert_pubk, vd);
169 if (ret != HVB_OK) {
170 hvb_printv("error, verity partition: ", desc.name, "\n", NULL);
171 goto fail;
172 }
173
174 if (hvb_buf_equal(&expected_pubk, &cert_pubk) != true) {
175 ret = HVB_ERROR_PUBLIC_KEY_REJECTED;
176 hvb_printv("error, compare public key: ", desc.name, "\n", NULL);
177 goto fail;
178 }
179
180 pubk_descs.addr += desc_size;
181 }
182
183 fail:
184 return ret;
185 }
186
hash_ptn_list_add_rvt(const char * const * hash_ptn_list,const char * rvt_ptn)187 static char const **hash_ptn_list_add_rvt(const char *const *hash_ptn_list, const char *rvt_ptn)
188 {
189 size_t n;
190 bool need_add_rvt = true;
191 char const **ptn = NULL;
192 size_t num_parttions = 0;
193
194 if (hash_ptn_list != NULL) {
195 while (hash_ptn_list[num_parttions] != NULL) {
196 num_parttions++;
197 }
198 }
199
200 num_parttions += REQUEST_LIST_LEN;
201
202 ptn = (char const **)hvb_calloc(num_parttions * sizeof(char *));
203 if (ptn == NULL) {
204 hvb_print("error, alloc ptn\n");
205 return NULL;
206 }
207
208 for (n = 0; n < num_parttions - REQUEST_LIST_LEN; n++) {
209 ptn[n] = hash_ptn_list[n];
210 if (hvb_strcmp(ptn[n], rvt_ptn) == 0) {
211 need_add_rvt = false;
212 }
213 }
214
215 if (need_add_rvt) {
216 ptn[num_parttions - REQUEST_LIST_LEN] = rvt_ptn;
217 }
218
219 return ptn;
220 }
221
hvb_chain_verify(struct hvb_ops * ops,const char * rvt_ptn,const char * const * hash_ptn_list,struct hvb_verified_data ** out_vd)222 enum hvb_errno hvb_chain_verify(struct hvb_ops *ops,
223 const char *rvt_ptn,
224 const char *const *hash_ptn_list,
225 struct hvb_verified_data **out_vd)
226 {
227 enum hvb_errno ret = HVB_OK;
228 struct hvb_buf *rvt_image = NULL;
229 struct hvb_verified_data *vd = NULL;
230 char const **ptn_list = NULL;
231
232 hvb_return_hvb_err_if_null(ops);
233 hvb_return_hvb_err_if_null(rvt_ptn);
234 hvb_return_hvb_err_if_null(out_vd);
235
236 ptn_list = hash_ptn_list_add_rvt(hash_ptn_list, rvt_ptn);
237 if (ptn_list == NULL) {
238 hvb_print("error, add rvt\n");
239 return HVB_ERROR_OOM;
240 }
241
242 vd = hvb_init_verified_data();
243 if (!vd) {
244 hvb_print("malloc verified_data fail\n");
245 ret = HVB_ERROR_OOM;
246 goto fail;
247 }
248
249 /* verity rvt cert */
250 ret = hvb_rvt_verify_root(ops, rvt_ptn, ptn_list, vd);
251 if (ret != HVB_OK) {
252 hvb_print("error, verity rvt partition.\n");
253 goto fail;
254 }
255
256 /* get rvt image */
257 rvt_image = hvb_get_partition_image(vd, rvt_ptn);
258 if (!rvt_image) {
259 hvb_print("error, get rvt ptn.\n");
260 ret = HVB_ERROR_OOM;
261 goto fail;
262 }
263
264 /* walk verify all nodes from rvt */
265 ret = hvb_walk_verify_nodes(ops, ptn_list, rvt_image, vd);
266 if (ret != HVB_OK) {
267 hvb_print("error, walk nodes.\n");
268 goto fail;
269 }
270
271 /* creat cmdline info */
272 ret = hvb_creat_cmdline(ops, vd);
273 if (ret != HVB_OK) {
274 hvb_print("error, create cmdline.\n");
275 goto fail;
276 }
277
278 *out_vd = vd;
279
280 fail:
281 if (vd != NULL && ret != HVB_OK) {
282 hvb_chain_verify_data_free(vd);
283 hvb_free(vd);
284 }
285
286 hvb_free(ptn_list);
287
288 return ret;
289 }
290
hvb_chain_verify_data_free(struct hvb_verified_data * vd)291 void hvb_chain_verify_data_free(struct hvb_verified_data *vd)
292 {
293 uint64_t n;
294
295 if (vd == NULL) {
296 hvb_print("vd is NULL, do nothing\n");
297 return;
298 }
299
300 for (n = 0; n < vd->num_loaded_certs && vd->certs; n++) {
301 if (vd->certs[n].data.addr != NULL)
302 hvb_free(vd->certs[n].data.addr);
303
304 if (vd->certs[n].partition_name != NULL) {
305 hvb_free(vd->certs[n].partition_name);
306 }
307 }
308
309 if (vd->certs != NULL) {
310 hvb_free(vd->certs);
311 }
312
313 for (n = 0; n < vd->num_loaded_images && vd->images; n++) {
314 if (vd->images[n].data.addr != NULL)
315 hvb_free(vd->images[n].data.addr);
316
317 if (vd->images[n].partition_name != NULL)
318 hvb_free(vd->images[n].partition_name);
319 }
320
321 if (vd->images != NULL) {
322 hvb_free(vd->images);
323 }
324
325 if (vd->cmdline.buf != NULL) {
326 hvb_free(vd->cmdline.buf);
327 }
328
329 hvb_memset((uint8_t *)vd, 0, sizeof(*vd));
330 }
331