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