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