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 <string.h>
18 #include "hvb.h"
19 #include "hvb_util.h"
20 #include "hvb_crypto.h"
21 #include "hvb_sysdeps.h"
22 #include "hvb_cert.h"
23 
24 
hvb_need_verify_hash(const char *const *hash_ptn_list, const char *ptn)25 static bool hvb_need_verify_hash(const char *const *hash_ptn_list, const char *ptn)
26 {
27     size_t n;
28     size_t ptn_len = hvb_strnlen(ptn, HVB_MAX_PARTITION_NAME_LEN);
29     if (ptn_len >= HVB_MAX_PARTITION_NAME_LEN) {
30         hvb_print("invalid ptn name len\n");
31         return false;
32     }
33 
34     if (hash_ptn_list == NULL)
35         return false;
36 
37     for (n = 0; hash_ptn_list[n] != NULL; n++) {
38         if (hvb_strnlen(hash_ptn_list[n], HVB_MAX_PARTITION_NAME_LEN) == ptn_len &&
39             hvb_strncmp(hash_ptn_list[n], ptn, HVB_MAX_PARTITION_NAME_LEN) == 0) {
40             return true;
41         }
42     }
43 
44     return false;
45 }
46 
get_hash_size(uint32_t algo)47 static uint64_t get_hash_size(uint32_t algo)
48 {
49     switch (algo) {
50         case 0: // SHA256_RSA3072
51         case 1: // SHA256_RSA4096
52         case 2: // SHA256_RSA2048
53             return 32;
54         default:
55             return 0;
56     }
57 
58     return 0;
59 }
60 
hvb_compare_hash(struct hvb_buf *digest_buf, struct hvb_buf *msg_buf, struct hvb_buf *salt_buf, uint32_t hash_algo)61 static enum hvb_errno hvb_compare_hash(struct hvb_buf *digest_buf, struct hvb_buf *msg_buf,
62                                        struct hvb_buf *salt_buf, uint32_t hash_algo)
63 {
64     int hash_err;
65     struct hash_ctx_t ctx = {0};
66     uint8_t computed_hash[HVB_HASH_MAX_BYTES] = {0};
67 
68     uint32_t computed_hash_size = get_hash_size(hash_algo);
69     if (computed_hash_size != digest_buf->size) {
70         hvb_print("computed_hash_size error\n");
71         return HVB_ERROR_INVALID_ARGUMENT;
72     }
73 
74     hash_err = hash_ctx_init(&ctx, hash_algo);
75     if (hash_err != HASH_OK) {
76         hvb_print("hash init error\n");
77         return HVB_ERROR_VERIFY_HASH;
78     }
79 
80     hash_err = hash_calc_update(&ctx, salt_buf->addr, salt_buf->size);
81     if (hash_err != HASH_OK) {
82         hvb_print("hash updata salt error\n");
83         return HVB_ERROR_VERIFY_HASH;
84     }
85 
86     hash_err = hash_calc_do_final(&ctx, msg_buf->addr, msg_buf->size, &computed_hash[0], digest_buf->size);
87     if (hash_err != HASH_OK) {
88         hvb_print("hash updata msg error\n");
89         return HVB_ERROR_VERIFY_HASH;
90     }
91 
92     if (hvb_memcmp(&computed_hash[0], digest_buf->addr, computed_hash_size) != 0) {
93         hvb_print("compare fail\n");
94         return HVB_ERROR_VERIFY_HASH;
95     }
96 
97     return HVB_OK;
98 }
99 
hash_image_init_desc(struct hvb_ops *ops, const char *ptn, struct hvb_cert *cert, const char *const *hash_ptn_list, struct hvb_verified_data *vd)100 static enum hvb_errno hash_image_init_desc(struct hvb_ops *ops, const char *ptn,
101                                            struct hvb_cert *cert, const char *const *hash_ptn_list,
102                                            struct hvb_verified_data *vd)
103 {
104     enum hvb_io_errno io_ret = HVB_IO_OK;
105     enum hvb_errno ret = HVB_OK;
106     struct hvb_buf image_buf = {NULL, 0};
107     struct hvb_buf salt_buf = {cert->hash_payload.salt, cert->salt_size};
108     struct hvb_buf digest_buf = {cert->hash_payload.digest, cert->digest_size};
109     uint64_t read_bytes = 0;
110     struct hvb_image_data *image = NULL;
111     enum hvb_image_type image_type = (enum hvb_image_type)cert->verity_type;
112 
113     if (image_type != HVB_IMAGE_TYPE_HASH || !hvb_need_verify_hash(hash_ptn_list, ptn)) {
114         hvb_printv(ptn, ": no need verify hash image.\n", NULL);
115         return HVB_OK;
116     }
117 
118     image_buf.size = cert->image_original_len;
119     image_buf.addr = hvb_malloc(image_buf.size);
120     if (image_buf.addr == NULL) {
121         hvb_print("malloc image_buf fail\n");
122         return HVB_ERROR_OOM;
123     }
124 
125     io_ret = ops->read_partition(ops, ptn, 0, image_buf.size, image_buf.addr, &read_bytes);
126     if (io_ret != HVB_IO_OK) {
127         hvb_printv(ptn, ": Error loading data.\n", NULL);
128         ret = HVB_ERROR_IO;
129         goto out;
130     }
131     if (read_bytes != image_buf.size) {
132         hvb_printv(ptn, ": Read incorrect number of bytes from.\n", NULL);
133         ret = HVB_ERROR_IO;
134         goto out;
135     }
136 
137     ret = hvb_compare_hash(&digest_buf, &image_buf, &salt_buf, cert->hash_algo);
138     if (ret != HVB_OK) {
139         hvb_printv(ptn, ": compare hash error.\n", NULL);
140         goto out;
141     }
142 
143     if (vd->num_loaded_images >= HVB_MAX_NUMBER_OF_LOADED_IMAGES) {
144         hvb_print("error, too many images\n");
145         ret = HVB_ERROR_OOM;
146         goto out;
147     }
148 
149     image = &vd->images[vd->num_loaded_images++];
150     image->partition_name = hvb_strdup(ptn);
151     image->data = image_buf;
152     image->preloaded = true;
153 
154     return HVB_OK;
155 
156 out:
157     if (image_buf.addr != NULL)
158         hvb_free(image_buf.addr);
159 
160     return ret;
161 }
162 
_decode_octets(struct hvb_buf *buf, size_t size, uint8_t **p, uint8_t *end)163 static bool _decode_octets(struct hvb_buf *buf, size_t size, uint8_t **p, uint8_t *end)
164 {
165     /* check range */
166     if (*p + size > end || *p + size < *p)
167         return false;
168 
169     buf->addr = *p;
170     buf->size = size;
171 
172     /* forward move */
173     *p += size;
174 
175     return true;
176 }
177 
_hvb_cert_payload_parser(struct hvb_cert *cert, uint8_t **p, uint8_t *end)178 static enum hvb_errno _hvb_cert_payload_parser(struct hvb_cert *cert, uint8_t **p, uint8_t *end)
179 {
180     struct hvb_buf buf;
181     struct hash_payload *payload = &cert->hash_payload;
182 
183     if (!_decode_octets(&buf, cert->salt_size, p, end)) {
184         hvb_print("error, dc salt.\n");
185         return HVB_ERROR_INVALID_CERT_FORMAT;
186     }
187     payload->salt = buf.addr;
188 
189     if (!_decode_octets(&buf, cert->digest_size, p, end)) {
190         hvb_print("error, dc digest.\n");
191         return HVB_ERROR_INVALID_CERT_FORMAT;
192     }
193     payload->digest = buf.addr;
194 
195     return HVB_OK;
196 }
197 
_hvb_cert_payload_parser_v2(struct hvb_cert *cert, uint8_t **p, uint8_t *end, uint8_t *header)198 static enum hvb_errno _hvb_cert_payload_parser_v2(struct hvb_cert *cert, uint8_t **p, uint8_t *end, uint8_t *header)
199 {
200     struct hash_payload *payload = &cert->hash_payload;
201     uint8_t *cur_header;
202 
203     if (header + cert->salt_offset > end || header + cert->salt_offset <= header) {
204         hvb_print("error, illegal salt offset.\n");
205         return HVB_ERROR_INVALID_CERT_FORMAT;
206     }
207     cur_header = header + cert->salt_offset;
208 
209     if (cur_header + cert->salt_size > end || cur_header + cert->salt_size <= cur_header) {
210         hvb_print("error, dc salt.\n");
211         return HVB_ERROR_INVALID_CERT_FORMAT;
212     }
213     payload->salt = cur_header;
214 
215     if (header + cert->digest_offset > end || header + cert->digest_offset <= header) {
216         hvb_print("error, illegal digest offset.\n");
217         return HVB_ERROR_INVALID_CERT_FORMAT;
218     }
219     cur_header = header + cert->digest_offset;
220 
221     if (cur_header + cert->digest_size > end || cur_header + cert->digest_size <= cur_header) {
222         hvb_print("error, dc digest.\n");
223         return HVB_ERROR_INVALID_CERT_FORMAT;
224     }
225     payload->digest = cur_header;
226     *p = cur_header + cert->digest_size;
227 
228     return HVB_OK;
229 }
230 
_hvb_cert_signature_parser(struct hvb_cert *cert, uint8_t **p, uint8_t *end)231 static enum hvb_errno _hvb_cert_signature_parser(struct hvb_cert *cert, uint8_t **p, uint8_t *end)
232 {
233     struct hvb_buf buf;
234     struct hvb_sign_info *sign_info = &cert->signature_info;
235     size_t cp_size = hvb_offsetof(struct hvb_sign_info, pubk);
236 
237     if (!_decode_octets(&buf, cp_size, p, end)) {
238         hvb_print("error, dc sign info const.\n");
239         return HVB_ERROR_INVALID_CERT_FORMAT;
240     }
241     if (hvb_memcpy_s(&cert->signature_info, sizeof(cert->signature_info), buf.addr, cp_size) != 0) {
242         hvb_print("error, copy dc sign info const.\n");
243         return HVB_ERROR_OOM;
244     }
245 
246     if (!_decode_octets(&buf, sign_info->pubkey_len, p, end)) {
247         hvb_print("error, dc pubk.\n");
248         return HVB_ERROR_INVALID_CERT_FORMAT;
249     }
250     if (hvb_memcpy_s(&sign_info->pubk, sizeof(sign_info->pubk), &buf, sizeof(buf)) != 0) {
251         hvb_print("error, copy dc pubk.\n");
252         return HVB_ERROR_OOM;
253     }
254 
255     if (!_decode_octets(&buf, sign_info->signature_len, p, end)) {
256         hvb_print("error, dc sign.\n");
257         return HVB_ERROR_INVALID_CERT_FORMAT;
258     }
259     if (hvb_memcpy_s(&sign_info->sign, sizeof(sign_info->sign), &buf, sizeof(buf)) != 0) {
260         hvb_print("error, copy dc sign.\n");
261         return HVB_ERROR_OOM;
262     }
263 
264     return HVB_OK;
265 }
266 
_hvb_cert_signature_parser_v2(struct hvb_cert *cert, uint8_t **p, uint8_t *end, uint8_t *header)267 static enum hvb_errno _hvb_cert_signature_parser_v2(struct hvb_cert *cert, uint8_t **p, uint8_t *end, uint8_t *header)
268 {
269     struct hvb_buf buf;
270     struct hvb_sign_info *sign_info = &cert->signature_info;
271     size_t cp_size = hvb_offsetof(struct hvb_sign_info, pubk);
272     uint8_t *cur_header;
273 
274     if (!_decode_octets(&buf, cp_size, p, end)) {
275         hvb_print("error, dc sign info const.\n");
276         return HVB_ERROR_INVALID_CERT_FORMAT;
277     }
278     if (hvb_memcpy_s(&cert->signature_info, sizeof(cert->signature_info), buf.addr, cp_size) != 0) {
279         hvb_print("error, copy dc sign info const.\n");
280         return HVB_ERROR_OOM;
281     }
282 
283     if (header + sign_info->pubkey_offset > end || header + sign_info->pubkey_offset <= header) {
284         hvb_print("error, illegal pubkey offset.\n");
285         return HVB_ERROR_INVALID_CERT_FORMAT;
286     }
287     cur_header = header + sign_info->pubkey_offset;
288 
289     if (cur_header + sign_info->pubkey_len > end || cur_header + sign_info->pubkey_len <= cur_header) {
290         hvb_print("error, dc pubkey.\n");
291         return HVB_ERROR_INVALID_CERT_FORMAT;
292     }
293     sign_info->pubk.addr = cur_header;
294     sign_info->pubk.size = sign_info->pubkey_len;
295 
296     if (header + sign_info->signature_offset > end || header + sign_info->signature_offset <= header) {
297         hvb_print("error, illegal signature offset.\n");
298         return HVB_ERROR_INVALID_CERT_FORMAT;
299     }
300     cur_header = header + sign_info->signature_offset;
301 
302     if (cur_header + sign_info->signature_len > end || cur_header + sign_info->signature_len <= cur_header) {
303         hvb_print("error, dc pubkey.\n");
304         return HVB_ERROR_INVALID_CERT_FORMAT;
305     }
306     sign_info->sign.addr = cur_header;
307     sign_info->sign.size = sign_info->signature_len;
308 
309     return HVB_OK;
310 }
311 
hvb_cert_parser(struct hvb_cert *cert, struct hvb_buf *cert_buf)312 enum hvb_errno hvb_cert_parser(struct hvb_cert *cert, struct hvb_buf *cert_buf)
313 {
314     hvb_return_hvb_err_if_null(cert);
315     hvb_return_hvb_err_if_null(cert_buf);
316     hvb_return_hvb_err_if_null(cert_buf->addr);
317 
318     if (cert_buf->size > HVB_CERT_MAX_SIZE) {
319         hvb_print("invalid cert size.\n");
320         return HVB_ERROR_INVALID_ARGUMENT;
321     }
322 
323     enum hvb_errno ret = HVB_OK;
324     struct hvb_buf buf;
325     uint8_t *p = cert_buf->addr;
326     uint8_t *end = p + cert_buf->size;
327     uint8_t *header = p;
328     size_t header_size = hvb_offsetof(struct hvb_cert, hash_payload);
329 
330     /* parse header */
331     if (!_decode_octets(&buf, header_size, &p, end)) {
332         hvb_print("error, dc cert const.\n");
333         return HVB_ERROR_INVALID_CERT_FORMAT;
334     }
335     if (hvb_memcpy_s(cert, sizeof(*cert), buf.addr, buf.size) != 0) {
336         hvb_print("error, copy dc cert const.\n");
337         return HVB_ERROR_OOM;
338     }
339 
340     if (cert->version_minor == 0) {
341         /* parse hash payload */
342         ret = _hvb_cert_payload_parser(cert, &p, end);
343         if (ret != HVB_OK) {
344             hvb_print("error, pr hash payload.\n");
345             return ret;
346         }
347 
348         /* parse signature info */
349         ret = _hvb_cert_signature_parser(cert, &p, end);
350         if (ret != HVB_OK) {
351             hvb_print("error, pr sign.\n");
352             return ret;
353         }
354     } else if (cert->version_minor == 1) {
355         /* parse hash payload v2 */
356         ret = _hvb_cert_payload_parser_v2(cert, &p, end, header);
357         if (ret != HVB_OK) {
358             hvb_print("error, pr hash payload.\n");
359             return ret;
360         }
361 
362         /* parse signature info v2 */
363         ret = _hvb_cert_signature_parser_v2(cert, &p, end, header);
364         if (ret != HVB_OK) {
365             hvb_print("error, pr sign.\n");
366             return ret;
367         }
368     } else {
369         hvb_print("error minor version\n");
370         return HVB_ERROR_INVALID_ARGUMENT;
371     }
372 
373     return HVB_OK;
374 }
375 
hvb_buftouint64(uint8_t *p)376 static uint64_t hvb_buftouint64(uint8_t *p)
377 {
378     uint32_t i;
379     uint64_t val = 0;
380 
381     for (i = 0; i < 8; i++, p++) {
382         val |= (((uint64_t)(*p)) << (i * 8));
383     }
384 
385     return val;
386 }
387 
388 /*
389  * raw_pubk: |bit_length|n0|mod|p_rr|
390  */
hvb_cert_pubk_parser(struct hvb_rsa_pubkey *pubk, struct hvb_buf *raw_pubk)391 static enum hvb_errno hvb_cert_pubk_parser(struct hvb_rsa_pubkey *pubk, struct hvb_buf *raw_pubk)
392 {
393     uint64_t bit_length = 0;
394     uint64_t n0 = 0;
395     struct hvb_buf mod;
396     struct hvb_buf p_rr;
397     struct hvb_buf buf;
398 
399     uint8_t *p = raw_pubk->addr;
400     uint8_t *end = p + raw_pubk->size;
401 
402     if (!_decode_octets(&buf, sizeof(uint64_t), &p, end)) {
403         hvb_print("error, dc bit_length.\n");
404         return 1;
405     }
406     bit_length = hvb_buftouint64(buf.addr);
407     bit_length = hvb_be64toh(bit_length);
408 
409     if (!_decode_octets(&buf, sizeof(uint64_t), &p, end)) {
410         hvb_print("error, dc n0.\n");
411         return 1;
412     }
413     n0 = hvb_buftouint64(buf.addr);
414     n0 = hvb_be64toh(n0);
415 
416     if (!_decode_octets(&mod, bit_length / 8, &p, end)) {
417         hvb_print("error, dc mod.\n");
418         return 1;
419     }
420 
421     if (!_decode_octets(&p_rr, bit_length / 8, &p, end)) {
422         hvb_print("error, dc p_rr\n");
423         return 1;
424     }
425 
426     pubk->width = bit_length;
427     pubk->e = 65537;
428     pubk->pn = mod.addr;
429     pubk->nlen = mod.size;
430     pubk->p_rr = p_rr.addr;
431     pubk->rlen = p_rr.size;
432     pubk->n_n0_i = n0;
433 
434     return 0;
435 }
436 
hvb_verify_cert(struct hvb_buf *tbs, struct hvb_sign_info *sign_info, uint32_t salt_size)437 static enum hvb_errno hvb_verify_cert(struct hvb_buf *tbs, struct hvb_sign_info *sign_info, uint32_t salt_size)
438 {
439     int cry_err;
440     enum hvb_errno ret = HVB_OK;
441     uint32_t hash_len;
442     struct hvb_buf temp_buf;
443     uint8_t *hash = NULL;
444     struct hvb_rsa_pubkey pubk;
445 
446     temp_buf = sign_info->pubk;
447     ret = hvb_cert_pubk_parser(&pubk, &temp_buf);
448     if (ret != HVB_OK) {
449         hvb_print("error, hvb cert pubk parser.\n");
450         return ret;
451     }
452 
453     hash_len = get_hash_size(sign_info->algorithm);
454     hash = hvb_malloc(hash_len);
455     if (!hash) {
456         hvb_print("hash malloc error:");
457         return HVB_ERROR_OOM;
458     }
459 
460     cry_err = hash_sha256_single(tbs->addr, tbs->size, hash, hash_len);
461     if (cry_err != 0) {
462         hvb_print("Error computed hash.\n");
463         return HVB_ERROR_INVALID_ARGUMENT;
464     }
465 
466     cry_err = hvb_rsa_verify_pss(&pubk, hash, hash_len, sign_info->sign.addr, sign_info->sign.size, salt_size);
467     if (cry_err != VERIFY_OK) {
468         hvb_print("hvb_rsa_verify_pss result error, signature mismatch\n");
469         return HVB_ERROR_VERIFY_SIGN;
470     }
471 
472     return HVB_OK;
473 }
474 
_check_rollback_index(struct hvb_ops *ops, struct hvb_cert *cert, struct hvb_verified_data *vd)475 static enum hvb_errno _check_rollback_index(struct hvb_ops *ops, struct hvb_cert *cert, struct hvb_verified_data *vd)
476 {
477     enum hvb_io_errno io_ret = HVB_IO_OK;
478     uint64_t stored_rollback_index = 0;
479     uint64_t cert_rollback_index = cert->rollback_index;
480     uint64_t rollback_location = cert->rollback_location;
481 
482     if (rollback_location >= HVB_MAX_NUMBER_OF_ROLLBACK_INDEX_LOCATIONS) {
483         hvb_print("error, rollback_location too big\n");
484         return HVB_ERROR_INVALID_CERT_FORMAT;
485     }
486 
487     io_ret = ops->read_rollback(ops, rollback_location, &stored_rollback_index);
488     if (io_ret != HVB_IO_OK) {
489         hvb_print("error, read rollback idnex\n");
490         return HVB_ERROR_IO;
491     }
492 
493     if (cert_rollback_index < stored_rollback_index) {
494         hvb_print("error, cert rollback index is less than the stored\n");
495         return HVB_ERROR_ROLLBACK_INDEX;
496     }
497 
498     vd->rollback_indexes[rollback_location] = cert_rollback_index;
499 
500     return HVB_OK;
501 }
502 
cert_init_desc(struct hvb_ops *ops, const char *ptn, struct hvb_buf *cert_buf, const char *const *hash_ptn_list, struct hvb_buf *out_pubk, struct hvb_verified_data *vd)503 enum hvb_errno cert_init_desc(struct hvb_ops *ops, const char *ptn, struct hvb_buf *cert_buf,
504                               const char *const *hash_ptn_list, struct hvb_buf *out_pubk,
505                               struct hvb_verified_data *vd)
506 {
507     hvb_return_hvb_err_if_null(ops);
508     hvb_return_hvb_err_if_null(ptn);
509     hvb_return_hvb_err_if_null(cert_buf);
510     hvb_return_hvb_err_if_null(cert_buf->addr);
511     hvb_return_hvb_err_if_null(out_pubk);
512     hvb_return_hvb_err_if_null(vd);
513 
514     enum hvb_errno ret = HVB_OK;
515     ret = check_hvb_ops(ops);
516     if (ret != HVB_OK) {
517         hvb_print("error, check ops\n");
518         return HVB_ERROR_INVALID_ARGUMENT;
519     }
520     if (hvb_strnlen(ptn, HVB_MAX_PARTITION_NAME_LEN) >= HVB_MAX_PARTITION_NAME_LEN) {
521         hvb_print("error, check partition name\n");
522         return HVB_ERROR_INVALID_ARGUMENT;
523     }
524 
525     struct hvb_cert cert = {0};
526     struct hvb_buf tbs = {0};
527     struct hvb_sign_info *sign_info = &cert.signature_info;
528 
529     ret = hvb_cert_parser(&cert, cert_buf);
530     if (ret != HVB_OK) {
531         hvb_print("error, hvb cert parser.\n");
532         return ret;
533     }
534 
535     tbs.addr = cert_buf->addr;
536     tbs.size = sign_info->sign.addr - cert_buf->addr;
537     ret = hvb_verify_cert(&tbs, sign_info, cert.salt_size);
538     if (ret != HVB_OK) {
539         hvb_print("error, verify cert.\n");
540         return ret;
541     }
542 
543     ret = _check_rollback_index(ops, &cert, vd);
544     if (ret != HVB_OK) {
545         hvb_print("error, checkout index.\n");
546         return ret;
547     }
548 
549     ret = hash_image_init_desc(ops, ptn, &cert, hash_ptn_list, vd);
550     if (ret != HVB_OK) {
551         hvb_print("hash_image_init_desc result error\n");
552         return ret;
553     }
554 
555     *out_pubk = sign_info->pubk;
556     vd->key_len = out_pubk->size;
557 
558     return ret;
559 }
560