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_strncmp(ptn[n], rvt_ptn, HVB_MAX_PARTITION_NAME_LEN) == 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     ret = check_hvb_ops(ops);
236     if (ret != HVB_OK) {
237         hvb_print("error, check ops\n");
238         return HVB_ERROR_INVALID_ARGUMENT;
239     }
240 
241     if (hvb_strnlen(rvt_ptn, HVB_MAX_PARTITION_NAME_LEN) >= HVB_MAX_PARTITION_NAME_LEN) {
242         hvb_print("error, check rvt partition name\n");
243         return HVB_ERROR_INVALID_ARGUMENT;
244     }
245 
246     ptn_list = hash_ptn_list_add_rvt(hash_ptn_list, rvt_ptn);
247     if (ptn_list == NULL) {
248         hvb_print("error, add rvt\n");
249         return HVB_ERROR_OOM;
250     }
251 
252     vd = hvb_init_verified_data();
253     if (!vd) {
254         hvb_print("malloc verified_data fail\n");
255         ret = HVB_ERROR_OOM;
256         goto fail;
257     }
258 
259     /* verity rvt cert */
260     ret = hvb_rvt_verify_root(ops, rvt_ptn, ptn_list, vd);
261     if (ret != HVB_OK) {
262         hvb_print("error, verity rvt partition.\n");
263         goto fail;
264     }
265 
266     /* get rvt image */
267     rvt_image = hvb_get_partition_image(vd, rvt_ptn);
268     if (!rvt_image) {
269         hvb_print("error, get rvt ptn.\n");
270         ret = HVB_ERROR_OOM;
271         goto fail;
272     }
273 
274     /* walk verify all nodes from rvt */
275     ret = hvb_walk_verify_nodes(ops, ptn_list, rvt_image, vd);
276     if (ret != HVB_OK) {
277         hvb_print("error, walk nodes.\n");
278         goto fail;
279     }
280 
281     /* creat cmdline info */
282     ret = hvb_creat_cmdline(ops, vd);
283     if (ret != HVB_OK) {
284         hvb_print("error, create cmdline.\n");
285         goto fail;
286     }
287 
288     *out_vd = vd;
289 
290 fail:
291     if (vd != NULL && ret != HVB_OK) {
292         hvb_chain_verify_data_free(vd);
293         hvb_free(vd);
294     }
295 
296     hvb_free(ptn_list);
297 
298     return ret;
299 }
300 
hvb_chain_verify_data_free(struct hvb_verified_data *vd)301 void hvb_chain_verify_data_free(struct hvb_verified_data *vd)
302 {
303     uint64_t n;
304 
305     if (vd == NULL) {
306         hvb_print("vd is NULL, do nothing\n");
307         return;
308     }
309 
310     for (n = 0; n < vd->num_loaded_certs && vd->certs; n++) {
311         if (vd->certs[n].data.addr != NULL)
312             hvb_free(vd->certs[n].data.addr);
313 
314         if (vd->certs[n].partition_name != NULL) {
315             hvb_free(vd->certs[n].partition_name);
316         }
317     }
318 
319     if (vd->certs != NULL) {
320         hvb_free(vd->certs);
321     }
322 
323     for (n = 0; n < vd->num_loaded_images && vd->images; n++) {
324         if (vd->images[n].data.addr != NULL)
325             hvb_free(vd->images[n].data.addr);
326 
327         if (vd->images[n].partition_name != NULL)
328             hvb_free(vd->images[n].partition_name);
329     }
330 
331     if (vd->images != NULL) {
332         hvb_free(vd->images);
333     }
334 
335     if (vd->cmdline.buf != NULL) {
336         hvb_free(vd->cmdline.buf);
337     }
338 
339     hvb_memset((uint8_t *)vd, 0, sizeof(*vd));
340 }
341