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
317 enum hvb_errno ret = HVB_OK;
318 struct hvb_buf buf;
319 uint8_t *p = cert_buf->addr;
320 uint8_t *end = p + cert_buf->size;
321 uint8_t *header = p;
322 size_t header_size = hvb_offsetof(struct hvb_cert, hash_payload);
323
324 /* parse header */
325 if (!_decode_octets(&buf, header_size, &p, end)) {
326 hvb_print("error, dc cert const.\n");
327 return HVB_ERROR_INVALID_CERT_FORMAT;
328 }
329 if (hvb_memcpy_s(cert, sizeof(*cert), buf.addr, buf.size) != 0) {
330 hvb_print("error, copy dc cert const.\n");
331 return HVB_ERROR_OOM;
332 }
333
334 if (cert->version_minor == 0) {
335 /* parse hash payload */
336 ret = _hvb_cert_payload_parser(cert, &p, end);
337 if (ret != HVB_OK) {
338 hvb_print("error, pr hash payload.\n");
339 return ret;
340 }
341
342 /* parse signature info */
343 ret = _hvb_cert_signature_parser(cert, &p, end);
344 if (ret != HVB_OK) {
345 hvb_print("error, pr sign.\n");
346 return ret;
347 }
348 } else if (cert->version_minor == 1) {
349 /* parse hash payload v2 */
350 ret = _hvb_cert_payload_parser_v2(cert, &p, end, header);
351 if (ret != HVB_OK) {
352 hvb_print("error, pr hash payload.\n");
353 return ret;
354 }
355
356 /* parse signature info v2 */
357 ret = _hvb_cert_signature_parser_v2(cert, &p, end, header);
358 if (ret != HVB_OK) {
359 hvb_print("error, pr sign.\n");
360 return ret;
361 }
362 } else {
363 hvb_print("error minor version\n");
364 return HVB_ERROR_INVALID_ARGUMENT;
365 }
366
367 return HVB_OK;
368 }
369
hvb_buftouint64(uint8_t * p)370 static uint64_t hvb_buftouint64(uint8_t *p)
371 {
372 uint32_t i;
373 uint64_t val = 0;
374
375 for (i = 0; i < 8; i++, p++) {
376 val |= (((uint64_t)(*p)) << (i * 8));
377 }
378
379 return val;
380 }
381
382 /*
383 * raw_pubk: |bit_length|n0|mod|p_rr|
384 */
hvb_cert_pubk_parser(struct hvb_rsa_pubkey * pubk,struct hvb_buf * raw_pubk)385 static enum hvb_errno hvb_cert_pubk_parser(struct hvb_rsa_pubkey *pubk, struct hvb_buf *raw_pubk)
386 {
387 uint64_t bit_length = 0;
388 uint64_t n0 = 0;
389 struct hvb_buf mod;
390 struct hvb_buf p_rr;
391 struct hvb_buf buf;
392
393 uint8_t *p = raw_pubk->addr;
394 uint8_t *end = p + raw_pubk->size;
395
396 if (!_decode_octets(&buf, sizeof(uint64_t), &p, end)) {
397 hvb_print("error, dc bit_length.\n");
398 return 1;
399 }
400 bit_length = hvb_buftouint64(buf.addr);
401 bit_length = hvb_be64toh(bit_length);
402
403 if (!_decode_octets(&buf, sizeof(uint64_t), &p, end)) {
404 hvb_print("error, dc n0.\n");
405 return 1;
406 }
407 n0 = hvb_buftouint64(buf.addr);
408 n0 = hvb_be64toh(n0);
409
410 if (!_decode_octets(&mod, bit_length / 8, &p, end)) {
411 hvb_print("error, dc mod.\n");
412 return 1;
413 }
414
415 if (!_decode_octets(&p_rr, bit_length / 8, &p, end)) {
416 hvb_print("error, dc p_rr\n");
417 return 1;
418 }
419
420 pubk->width = bit_length;
421 pubk->e = 65537;
422 pubk->pn = mod.addr;
423 pubk->nlen = mod.size;
424 pubk->p_rr = p_rr.addr;
425 pubk->rlen = p_rr.size;
426 pubk->n_n0_i = n0;
427
428 return 0;
429 }
430
hvb_verify_cert(struct hvb_buf * tbs,struct hvb_sign_info * sign_info,uint32_t salt_size)431 static enum hvb_errno hvb_verify_cert(struct hvb_buf *tbs, struct hvb_sign_info *sign_info, uint32_t salt_size)
432 {
433 int cry_err;
434 enum hvb_errno ret = HVB_OK;
435 uint32_t hash_len;
436 struct hvb_buf temp_buf;
437 uint8_t *hash = NULL;
438 struct hvb_rsa_pubkey pubk;
439
440 temp_buf = sign_info->pubk;
441 ret = hvb_cert_pubk_parser(&pubk, &temp_buf);
442 if (ret != HVB_OK) {
443 hvb_print("error, hvb cert pubk parser.\n");
444 return ret;
445 }
446
447 hash_len = get_hash_size(sign_info->algorithm);
448 hash = hvb_malloc(hash_len);
449 if (!hash) {
450 hvb_print("hash malloc error:");
451 return HVB_ERROR_OOM;
452 }
453
454 cry_err = hash_sha256_single(tbs->addr, tbs->size, hash, hash_len);
455 if (cry_err != 0) {
456 hvb_print("Error computed hash.\n");
457 return HVB_ERROR_INVALID_ARGUMENT;
458 }
459
460 cry_err = hvb_rsa_verify_pss(&pubk, hash, hash_len, sign_info->sign.addr, sign_info->sign.size, salt_size);
461 if (cry_err != VERIFY_OK) {
462 hvb_print("hvb_rsa_verify_pss result error, signature mismatch\n");
463 return HVB_ERROR_VERIFY_SIGN;
464 }
465
466 return HVB_OK;
467 }
468
_check_rollback_index(struct hvb_ops * ops,struct hvb_cert * cert,struct hvb_verified_data * vd)469 static enum hvb_errno _check_rollback_index(struct hvb_ops *ops, struct hvb_cert *cert, struct hvb_verified_data *vd)
470 {
471 enum hvb_io_errno io_ret = HVB_IO_OK;
472 uint64_t stored_rollback_index = 0;
473 uint64_t cert_rollback_index = cert->rollback_index;
474 uint64_t rollback_location = cert->rollback_location;
475
476 if (rollback_location >= HVB_MAX_NUMBER_OF_ROLLBACK_INDEX_LOCATIONS) {
477 hvb_print("error, rollback_location too big\n");
478 return HVB_ERROR_INVALID_CERT_FORMAT;
479 }
480
481 io_ret = ops->read_rollback(ops, rollback_location, &stored_rollback_index);
482 if (io_ret != HVB_IO_OK) {
483 hvb_print("error, read rollback idnex\n");
484 return HVB_ERROR_IO;
485 }
486
487 if (cert_rollback_index < stored_rollback_index) {
488 hvb_print("error, cert rollback index is less than the stored\n");
489 return HVB_ERROR_ROLLBACK_INDEX;
490 }
491
492 vd->rollback_indexes[rollback_location] = cert_rollback_index;
493
494 return HVB_OK;
495 }
496
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)497 enum hvb_errno cert_init_desc(struct hvb_ops *ops, const char *ptn, struct hvb_buf *cert_buf,
498 const char *const *hash_ptn_list, struct hvb_buf *out_pubk,
499 struct hvb_verified_data *vd)
500 {
501 hvb_return_hvb_err_if_null(ops);
502 hvb_return_hvb_err_if_null(ptn);
503 hvb_return_hvb_err_if_null(cert_buf);
504 hvb_return_hvb_err_if_null(out_pubk);
505 hvb_return_hvb_err_if_null(vd);
506
507 enum hvb_errno ret = HVB_OK;
508 struct hvb_cert cert = {0};
509 struct hvb_buf tbs = {0};
510 struct hvb_sign_info *sign_info = &cert.signature_info;
511
512 ret = hvb_cert_parser(&cert, cert_buf);
513 if (ret != HVB_OK) {
514 hvb_print("error, hvb cert parser.\n");
515 return ret;
516 }
517
518 tbs.addr = cert_buf->addr;
519 tbs.size = sign_info->sign.addr - cert_buf->addr;
520 ret = hvb_verify_cert(&tbs, sign_info, cert.salt_size);
521 if (ret != HVB_OK) {
522 hvb_print("error, verify cert.\n");
523 return ret;
524 }
525
526 ret = _check_rollback_index(ops, &cert, vd);
527 if (ret != HVB_OK) {
528 hvb_print("error, checkout index.\n");
529 return ret;
530 }
531
532 ret = hash_image_init_desc(ops, ptn, &cert, hash_ptn_list, vd);
533 if (ret != HVB_OK) {
534 hvb_print("hash_image_init_desc result error\n");
535 return ret;
536 }
537
538 *out_pubk = sign_info->pubk;
539 vd->key_len = out_pubk->size;
540
541 return ret;
542 }
543