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 vd->algorithm = 0;
61
62 return vd;
63
64 fail:
65 hvb_chain_verify_data_free(vd);
66 hvb_free(vd);
67 vd = NULL;
68 return vd;
69 }
70
hvb_rvt_verify_root(struct hvb_ops * ops,const char * ptn,const char * const * ptn_list,struct hvb_verified_data * vd)71 static enum hvb_errno hvb_rvt_verify_root(struct hvb_ops *ops, const char *ptn,
72 const char *const *ptn_list,
73 struct hvb_verified_data *vd)
74 {
75 enum hvb_errno ret = HVB_OK;
76 enum hvb_io_errno io_ret = HVB_IO_OK;
77 bool is_trusted = false;
78 struct hvb_buf cert_pubk = {0};
79
80 ret = footer_init_desc(ops, ptn, ptn_list, &cert_pubk, vd);
81 if (ret != HVB_OK) {
82 hvb_printv("error verity partition: ", ptn, "\n", NULL);
83 goto fail;
84 }
85
86 io_ret = ops->valid_rvt_key(ops, cert_pubk.addr, cert_pubk.size, NULL, 0, &is_trusted);
87 if (io_ret != HVB_IO_OK) {
88 ret = HVB_ERROR_PUBLIC_KEY_REJECTED;
89 hvb_print("error, rvt public key invalid\n");
90 goto fail;
91 }
92
93 if (is_trusted == false) {
94 ret = HVB_ERROR_PUBLIC_KEY_REJECTED;
95 hvb_print("error, rvt public key rejected\n");
96 goto fail;
97 }
98
99 fail:
100 return ret;
101 }
102
hvb_get_partition_image(struct hvb_verified_data * vd,const char * ptn)103 static struct hvb_buf *hvb_get_partition_image(struct hvb_verified_data *vd, const char *ptn)
104 {
105 struct hvb_image_data *p = vd->images;
106 struct hvb_image_data *end = p + vd->num_loaded_images;
107 size_t name_len = hvb_strnlen(ptn, HVB_MAX_PARTITION_NAME_LEN);
108 if (name_len >= HVB_MAX_PARTITION_NAME_LEN) {
109 hvb_print("invalid ptn name len\n");
110 return NULL;
111 }
112
113 for (; p < end; p++) {
114 if (hvb_strnlen(p->partition_name, HVB_MAX_PARTITION_NAME_LEN) == name_len &&
115 hvb_strncmp(ptn, p->partition_name, HVB_MAX_PARTITION_NAME_LEN) == 0) {
116 return &p->data;
117 }
118 }
119
120 return NULL;
121 }
122
hvb_buf_equal(const struct hvb_buf * buf1,const struct hvb_buf * buf2)123 static bool hvb_buf_equal(const struct hvb_buf *buf1, const struct hvb_buf *buf2)
124 {
125 return buf1->size == buf2->size && hvb_memcmp(buf1->addr, buf2->addr, buf1->size) == 0;
126 }
127
get_desc_size(uint32_t algo,uint32_t pubkey_num_per_ptn,uint64_t * desc_size)128 static enum hvb_errno get_desc_size(uint32_t algo, uint32_t pubkey_num_per_ptn, uint64_t *desc_size)
129 {
130 uint64_t key_len = 0;
131 switch (algo) {
132 case 1: { // SHA256_RSA4096
133 key_len = PUBKEY_LEN_4096;
134 break;
135 }
136 case 2: { // SHA256_RSA2048
137 key_len = PUBKEY_LEN_2048;
138 break;
139 }
140 case 3: { // SM3
141 key_len = PUBKEY_LEN_SM;
142 break;
143 }
144 default: {
145 hvb_print("hash algo dsnt support\n");
146 return HVB_ERROR_INVALID_ARGUMENT;
147 }
148 }
149
150 /* actual desc size is const part + pubkey payload part */
151 *desc_size = hvb_offsetof(struct rvt_pubk_desc, pubkey_payload) + key_len * pubkey_num_per_ptn;
152
153 return HVB_OK;
154 }
155
hvb_rvt_parser(const struct hvb_buf * rvt,const struct hvb_verified_data * vd,struct rvt_image_header * header,struct hvb_buf * pubk_descs,uint64_t * desc_size)156 static enum hvb_errno hvb_rvt_parser(const struct hvb_buf *rvt, const struct hvb_verified_data *vd,
157 struct rvt_image_header *header, struct hvb_buf *pubk_descs, uint64_t *desc_size)
158 {
159 enum hvb_errno ret;
160 uint64_t rvt_real_size;
161 uint32_t pubkey_num_per_ptn;
162
163 ret = hvb_rvt_head_parser(rvt, header);
164 if (ret != HVB_OK) {
165 hvb_print("error, parse rvt header.\n");
166 return ret;
167 }
168
169 if (header->pubkey_num_per_ptn == 0) {
170 hvb_print("old version rvt, use default pubkey num.\n");
171 pubkey_num_per_ptn = 1;
172 } else {
173 pubkey_num_per_ptn = header->pubkey_num_per_ptn;
174 }
175
176 ret = get_desc_size(vd->algorithm, pubkey_num_per_ptn, desc_size);
177 if (ret != HVB_OK) {
178 hvb_print("error, get desc size.\n");
179 return ret;
180 }
181
182 rvt_real_size = sizeof(*header) + header->verity_num * (*desc_size);
183 if (rvt_real_size > rvt->size || rvt_real_size < sizeof(*header)) {
184 hvb_print("error, rvt_real_size is invalid.\n");
185 return HVB_ERROR_INVALID_ARGUMENT;
186 }
187
188 ret = hvb_rvt_get_pubk_desc(rvt, pubk_descs);
189 if (ret != HVB_OK) {
190 hvb_print("error, pubk descs.\n");
191 return ret;
192 }
193
194 return HVB_OK;
195 }
196
hvb_pubkey_parser(const struct hvb_buf * rvt,uint32_t pubkey_num_per_ptn,struct rvt_pubk_desc * desc)197 static enum hvb_errno hvb_pubkey_parser(const struct hvb_buf *rvt, uint32_t pubkey_num_per_ptn,
198 struct rvt_pubk_desc *desc)
199 {
200 enum hvb_errno ret;
201
202 ret = hvb_rvt_get_pubk_buf(&desc->pubkey_payload, rvt, desc->pubkey_offset, desc->pubkey_len);
203 if (ret != HVB_OK) {
204 hvb_print("errror, get main pubk buf\n");
205 return ret;
206 }
207
208 if (pubkey_num_per_ptn == RVT_MAX_VALID_KEY_NUM) {
209 ret = hvb_rvt_get_pubk_buf(&desc->pubkey_payload_backup, rvt,
210 desc->pubkey_offset + desc->pubkey_len, desc->pubkey_len);
211 if (ret != HVB_OK) {
212 hvb_print("errror, get backup pubk buf\n");
213 return ret;
214 }
215 }
216
217 return HVB_OK;
218 }
219
hvb_walk_verify_nodes(struct hvb_ops * ops,const char * const * ptn_list,struct hvb_buf * rvt,struct hvb_verified_data * vd)220 static enum hvb_errno hvb_walk_verify_nodes(struct hvb_ops *ops, const char *const *ptn_list,
221 struct hvb_buf *rvt, struct hvb_verified_data *vd)
222 {
223 enum hvb_errno ret = HVB_OK;
224 uint32_t i;
225 struct hvb_buf pubk_descs = {0};
226 struct rvt_pubk_desc desc = {0};
227 struct hvb_buf cert_pubk = {0};
228 struct rvt_image_header header = {0};
229 uint64_t desc_size;
230 bool is_locked;
231
232 if (ops->read_lock_state(ops, &is_locked) != HVB_IO_OK) {
233 ret = HVB_ERROR_IO;
234 hvb_print("error, get lock state.\n");
235 goto fail;
236 }
237
238 ret = hvb_rvt_parser(rvt, vd, &header, &pubk_descs, &desc_size);
239 if (ret != HVB_OK) {
240 hvb_print("error, parse rvt.\n");
241 goto fail;
242 }
243
244 for (i = 0; i < header.verity_num; i++) {
245 ret = hvb_rvt_pubk_desc_parser(&pubk_descs, &desc);
246 if (ret != HVB_OK) {
247 hvb_print("errror, parser rvt pubkey descs\n");
248 goto fail;
249 }
250
251 ret = hvb_pubkey_parser(rvt, header.pubkey_num_per_ptn, &desc);
252 if (ret != HVB_OK) {
253 hvb_print("errror, parse pubkey\n");
254 goto fail;
255 }
256
257 ret = footer_init_desc(ops, &desc.name[0], ptn_list, &cert_pubk, vd);
258 if (ret != HVB_OK) {
259 hvb_printv("error, verity partition: ", desc.name, "\n", NULL);
260 goto fail;
261 }
262
263 if (hvb_buf_equal(&desc.pubkey_payload, &cert_pubk) != true) {
264 if (!is_locked && header.pubkey_num_per_ptn == RVT_MAX_VALID_KEY_NUM &&
265 hvb_buf_equal(&desc.pubkey_payload_backup, &cert_pubk)) {
266 hvb_printv(desc.name, "backup pubkey verified\n", NULL);
267 } else {
268 ret = HVB_ERROR_PUBLIC_KEY_REJECTED;
269 hvb_printv("error, compare public key: ", desc.name, "\n", NULL);
270 goto fail;
271 }
272 }
273
274 pubk_descs.addr += desc_size;
275 }
276
277 fail:
278 return ret;
279 }
280
hash_ptn_list_add_rvt(const char * const * hash_ptn_list,const char * rvt_ptn)281 static char const **hash_ptn_list_add_rvt(const char *const *hash_ptn_list, const char *rvt_ptn)
282 {
283 size_t n;
284 bool need_add_rvt = true;
285 char const **ptn = NULL;
286 size_t num_parttions = 0;
287
288 if (hash_ptn_list != NULL) {
289 while (hash_ptn_list[num_parttions] != NULL) {
290 num_parttions++;
291 }
292 }
293
294 num_parttions += REQUEST_LIST_LEN;
295
296 ptn = (char const **)hvb_calloc(num_parttions * sizeof(char *));
297 if (ptn == NULL) {
298 hvb_print("error, alloc ptn\n");
299 return NULL;
300 }
301
302 for (n = 0; n < num_parttions - REQUEST_LIST_LEN; n++) {
303 ptn[n] = hash_ptn_list[n];
304 if (hvb_strncmp(ptn[n], rvt_ptn, HVB_MAX_PARTITION_NAME_LEN) == 0) {
305 need_add_rvt = false;
306 }
307 }
308
309 if (need_add_rvt) {
310 ptn[num_parttions - REQUEST_LIST_LEN] = rvt_ptn;
311 }
312
313 return ptn;
314 }
315
hvb_chain_verify(struct hvb_ops * ops,const char * rvt_ptn,const char * const * hash_ptn_list,struct hvb_verified_data ** out_vd)316 enum hvb_errno hvb_chain_verify(struct hvb_ops *ops,
317 const char *rvt_ptn,
318 const char *const *hash_ptn_list,
319 struct hvb_verified_data **out_vd)
320 {
321 enum hvb_errno ret = HVB_OK;
322 struct hvb_buf *rvt_image = NULL;
323 struct hvb_verified_data *vd = NULL;
324 char const **ptn_list = NULL;
325
326 hvb_return_hvb_err_if_null(ops);
327 hvb_return_hvb_err_if_null(rvt_ptn);
328 hvb_return_hvb_err_if_null(out_vd);
329 ret = check_hvb_ops(ops);
330 if (ret != HVB_OK) {
331 hvb_print("error, check ops\n");
332 return HVB_ERROR_INVALID_ARGUMENT;
333 }
334
335 if (hvb_strnlen(rvt_ptn, HVB_MAX_PARTITION_NAME_LEN) >= HVB_MAX_PARTITION_NAME_LEN) {
336 hvb_print("error, check rvt partition name\n");
337 return HVB_ERROR_INVALID_ARGUMENT;
338 }
339
340 ptn_list = hash_ptn_list_add_rvt(hash_ptn_list, rvt_ptn);
341 if (ptn_list == NULL) {
342 hvb_print("error, add rvt\n");
343 return HVB_ERROR_OOM;
344 }
345
346 vd = hvb_init_verified_data();
347 if (!vd) {
348 hvb_print("malloc verified_data fail\n");
349 ret = HVB_ERROR_OOM;
350 goto fail;
351 }
352
353 /* verity rvt cert */
354 ret = hvb_rvt_verify_root(ops, rvt_ptn, ptn_list, vd);
355 if (ret != HVB_OK) {
356 hvb_print("error, verity rvt partition.\n");
357 goto fail;
358 }
359
360 /* get rvt image */
361 rvt_image = hvb_get_partition_image(vd, rvt_ptn);
362 if (!rvt_image) {
363 hvb_print("error, get rvt ptn.\n");
364 ret = HVB_ERROR_OOM;
365 goto fail;
366 }
367
368 /* walk verify all nodes from rvt */
369 ret = hvb_walk_verify_nodes(ops, ptn_list, rvt_image, vd);
370 if (ret != HVB_OK) {
371 hvb_print("error, walk nodes.\n");
372 goto fail;
373 }
374
375 hvb_print("hash algorithm is");
376 hvb_print_u64(vd->algorithm);
377
378 /* creat cmdline info */
379 ret = hvb_creat_cmdline(ops, vd);
380 if (ret != HVB_OK) {
381 hvb_print("error, create cmdline.\n");
382 goto fail;
383 }
384
385 *out_vd = vd;
386
387 fail:
388 if (vd != NULL && ret != HVB_OK) {
389 hvb_chain_verify_data_free(vd);
390 hvb_free(vd);
391 }
392
393 hvb_free(ptn_list);
394
395 return ret;
396 }
397
hvb_chain_verify_data_free(struct hvb_verified_data * vd)398 void hvb_chain_verify_data_free(struct hvb_verified_data *vd)
399 {
400 uint64_t n;
401
402 if (vd == NULL) {
403 hvb_print("vd is NULL, do nothing\n");
404 return;
405 }
406
407 for (n = 0; n < vd->num_loaded_certs && vd->certs; n++) {
408 if (vd->certs[n].data.addr != NULL)
409 hvb_free(vd->certs[n].data.addr);
410
411 if (vd->certs[n].partition_name != NULL) {
412 hvb_free(vd->certs[n].partition_name);
413 }
414 }
415
416 if (vd->certs != NULL) {
417 hvb_free(vd->certs);
418 }
419
420 for (n = 0; n < vd->num_loaded_images && vd->images; n++) {
421 if (vd->images[n].data.addr != NULL)
422 hvb_free(vd->images[n].data.addr);
423
424 if (vd->images[n].partition_name != NULL)
425 hvb_free(vd->images[n].partition_name);
426 }
427
428 if (vd->images != NULL) {
429 hvb_free(vd->images);
430 }
431
432 if (vd->cmdline.buf != NULL) {
433 hvb_free(vd->cmdline.buf);
434 }
435
436 hvb_memset((uint8_t *)vd, 0, sizeof(*vd));
437 }
438