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