1
2
3
4
5
6
7#include <common.h>
8#include <charset.h>
9#include <efi_loader.h>
10#include <efi_variable.h>
11#include <image.h>
12#include <hexdump.h>
13#include <malloc.h>
14#include <crypto/pkcs7.h>
15#include <crypto/pkcs7_parser.h>
16#include <crypto/public_key.h>
17#include <linux/compat.h>
18#include <linux/oid_registry.h>
19#include <u-boot/hash-checksum.h>
20#include <u-boot/rsa.h>
21#include <u-boot/sha256.h>
22
23const efi_guid_t efi_guid_sha256 = EFI_CERT_SHA256_GUID;
24const efi_guid_t efi_guid_cert_rsa2048 = EFI_CERT_RSA2048_GUID;
25const efi_guid_t efi_guid_cert_x509 = EFI_CERT_X509_GUID;
26const efi_guid_t efi_guid_cert_x509_sha256 = EFI_CERT_X509_SHA256_GUID;
27const efi_guid_t efi_guid_cert_type_pkcs7 = EFI_CERT_TYPE_PKCS7_GUID;
28
29static u8 pkcs7_hdr[] = {
30
31 0x30, 0x82, 0x05, 0xc7,
32
33 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x02,
34
35 0xa0, 0x82, 0x05, 0xb8,
36};
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54struct pkcs7_message *efi_parse_pkcs7_header(const void *buf,
55 size_t buflen,
56 u8 **tmpbuf)
57{
58 u8 *ebuf;
59 size_t ebuflen, len;
60 struct pkcs7_message *msg;
61
62
63
64
65
66 if (buflen > sizeof(pkcs7_hdr) &&
67 !memcmp(&((u8 *)buf)[4], &pkcs7_hdr[4], 11)) {
68 msg = pkcs7_parse_message(buf, buflen);
69 if (IS_ERR(msg))
70 return NULL;
71 return msg;
72 }
73
74
75
76
77
78
79
80
81
82 EFI_PRINT("Makeshift prefix added to authentication data\n");
83 ebuflen = sizeof(pkcs7_hdr) + buflen;
84 if (ebuflen <= 0x7f) {
85 EFI_PRINT("Data is too short\n");
86 return NULL;
87 }
88
89 ebuf = malloc(ebuflen);
90 if (!ebuf) {
91 EFI_PRINT("Out of memory\n");
92 return NULL;
93 }
94
95 memcpy(ebuf, pkcs7_hdr, sizeof(pkcs7_hdr));
96 memcpy(ebuf + sizeof(pkcs7_hdr), buf, buflen);
97 len = ebuflen - 4;
98 ebuf[2] = (len >> 8) & 0xff;
99 ebuf[3] = len & 0xff;
100 len = ebuflen - 0x13;
101 ebuf[0x11] = (len >> 8) & 0xff;
102 ebuf[0x12] = len & 0xff;
103
104 msg = pkcs7_parse_message(ebuf, ebuflen);
105
106 if (IS_ERR(msg)) {
107 free(ebuf);
108 return NULL;
109 }
110
111 *tmpbuf = ebuf;
112 return msg;
113}
114
115
116
117
118
119
120
121
122
123
124
125
126static bool efi_hash_regions(struct image_region *regs, int count,
127 void **hash, size_t *size)
128{
129 if (!*hash) {
130 *hash = calloc(1, SHA256_SUM_LEN);
131 if (!*hash) {
132 EFI_PRINT("Out of memory\n");
133 return false;
134 }
135 }
136 if (size)
137 *size = SHA256_SUM_LEN;
138
139 hash_calculate("sha256", regs, count, *hash);
140#ifdef DEBUG
141 EFI_PRINT("hash calculated:\n");
142 print_hex_dump(" ", DUMP_PREFIX_OFFSET, 16, 1,
143 *hash, SHA256_SUM_LEN, false);
144#endif
145
146 return true;
147}
148
149
150
151
152
153
154
155
156
157
158
159
160bool efi_signature_lookup_digest(struct efi_image_regions *regs,
161 struct efi_signature_store *db)
162{
163 struct efi_signature_store *siglist;
164 struct efi_sig_data *sig_data;
165 void *hash = NULL;
166 size_t size = 0;
167 bool found = false;
168
169 EFI_PRINT("%s: Enter, %p, %p\n", __func__, regs, db);
170
171 if (!regs || !db || !db->sig_data_list)
172 goto out;
173
174 for (siglist = db; siglist; siglist = siglist->next) {
175
176 if (guidcmp(&siglist->sig_type, &efi_guid_sha256)) {
177 EFI_PRINT("Digest algorithm is not supported: %pUl\n",
178 &siglist->sig_type);
179 break;
180 }
181
182 if (!efi_hash_regions(regs->reg, regs->num, &hash, &size)) {
183 EFI_PRINT("Digesting an image failed\n");
184 break;
185 }
186
187 for (sig_data = siglist->sig_data_list; sig_data;
188 sig_data = sig_data->next) {
189#ifdef DEBUG
190 EFI_PRINT("Msg digest in database:\n");
191 print_hex_dump(" ", DUMP_PREFIX_OFFSET, 16, 1,
192 sig_data->data, sig_data->size, false);
193#endif
194 if (sig_data->size == size &&
195 !memcmp(sig_data->data, hash, size)) {
196 found = true;
197 free(hash);
198 goto out;
199 }
200 }
201
202 free(hash);
203 hash = NULL;
204 }
205
206out:
207 EFI_PRINT("%s: Exit, found: %d\n", __func__, found);
208 return found;
209}
210
211
212
213
214
215
216
217
218
219
220
221static bool efi_lookup_certificate(struct x509_certificate *cert,
222 struct efi_signature_store *db)
223{
224 struct efi_signature_store *siglist;
225 struct efi_sig_data *sig_data;
226 struct image_region reg[1];
227 void *hash = NULL, *hash_tmp = NULL;
228 size_t size = 0;
229 bool found = false;
230
231 EFI_PRINT("%s: Enter, %p, %p\n", __func__, cert, db);
232
233 if (!cert || !db || !db->sig_data_list)
234 goto out;
235
236
237
238
239
240
241 reg[0].data = cert->tbs;
242 reg[0].size = cert->tbs_size;
243 if (!efi_hash_regions(reg, 1, &hash, &size))
244 goto out;
245
246 EFI_PRINT("%s: searching for %s\n", __func__, cert->subject);
247 for (siglist = db; siglist; siglist = siglist->next) {
248
249 if (guidcmp(&siglist->sig_type, &efi_guid_cert_x509))
250 continue;
251
252 for (sig_data = siglist->sig_data_list; sig_data;
253 sig_data = sig_data->next) {
254 struct x509_certificate *cert_tmp;
255
256 cert_tmp = x509_cert_parse(sig_data->data,
257 sig_data->size);
258 if (IS_ERR_OR_NULL(cert_tmp))
259 continue;
260
261 EFI_PRINT("%s: against %s\n", __func__,
262 cert_tmp->subject);
263 reg[0].data = cert_tmp->tbs;
264 reg[0].size = cert_tmp->tbs_size;
265 if (!efi_hash_regions(reg, 1, &hash_tmp, NULL))
266 goto out;
267
268 x509_free_certificate(cert_tmp);
269
270 if (!memcmp(hash, hash_tmp, size)) {
271 found = true;
272 goto out;
273 }
274 }
275 }
276out:
277 free(hash);
278 free(hash_tmp);
279
280 EFI_PRINT("%s: Exit, found: %d\n", __func__, found);
281 return found;
282}
283
284
285
286
287
288
289
290
291
292
293
294
295static bool efi_verify_certificate(struct x509_certificate *signer,
296 struct efi_signature_store *db,
297 struct x509_certificate **root)
298{
299 struct efi_signature_store *siglist;
300 struct efi_sig_data *sig_data;
301 struct x509_certificate *cert;
302 bool verified = false;
303 int ret;
304
305 EFI_PRINT("%s: Enter, %p, %p\n", __func__, signer, db);
306
307 if (!signer || !db || !db->sig_data_list)
308 goto out;
309
310 for (siglist = db; siglist; siglist = siglist->next) {
311
312 if (guidcmp(&siglist->sig_type, &efi_guid_cert_x509))
313 continue;
314
315 for (sig_data = siglist->sig_data_list; sig_data;
316 sig_data = sig_data->next) {
317 cert = x509_cert_parse(sig_data->data, sig_data->size);
318 if (IS_ERR_OR_NULL(cert)) {
319 EFI_PRINT("Cannot parse x509 certificate\n");
320 continue;
321 }
322
323 ret = public_key_verify_signature(cert->pub,
324 signer->sig);
325 if (!ret) {
326 verified = true;
327 if (root)
328 *root = cert;
329 else
330 x509_free_certificate(cert);
331 goto out;
332 }
333 x509_free_certificate(cert);
334 }
335 }
336
337out:
338 EFI_PRINT("%s: Exit, verified: %d\n", __func__, verified);
339 return verified;
340}
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357static bool efi_signature_check_revocation(struct pkcs7_signed_info *sinfo,
358 struct x509_certificate *cert,
359 struct efi_signature_store *dbx)
360{
361 struct efi_signature_store *siglist;
362 struct efi_sig_data *sig_data;
363 struct image_region reg[1];
364 void *hash = NULL;
365 size_t size = 0;
366 time64_t revoc_time;
367 bool revoked = false;
368
369 EFI_PRINT("%s: Enter, %p, %p, %p\n", __func__, sinfo, cert, dbx);
370
371 if (!sinfo || !cert || !dbx || !dbx->sig_data_list)
372 goto out;
373
374 EFI_PRINT("Checking revocation against %s\n", cert->subject);
375 for (siglist = dbx; siglist; siglist = siglist->next) {
376 if (guidcmp(&siglist->sig_type, &efi_guid_cert_x509_sha256))
377 continue;
378
379
380 reg[0].data = cert->tbs;
381 reg[0].size = cert->tbs_size;
382 if (!efi_hash_regions(reg, 1, &hash, &size))
383 goto out;
384
385 for (sig_data = siglist->sig_data_list; sig_data;
386 sig_data = sig_data->next) {
387
388
389
390
391
392
393#ifdef DEBUG
394 if (sig_data->size >= size) {
395 EFI_PRINT("hash in db:\n");
396 print_hex_dump(" ", DUMP_PREFIX_OFFSET,
397 16, 1,
398 sig_data->data, size, false);
399 }
400#endif
401 if ((sig_data->size < size + sizeof(time64_t)) ||
402 memcmp(sig_data->data, hash, size))
403 continue;
404
405 memcpy(&revoc_time, sig_data->data + size,
406 sizeof(revoc_time));
407 EFI_PRINT("revocation time: 0x%llx\n", revoc_time);
408
409
410
411
412
413 revoked = true;
414 free(hash);
415 goto out;
416 }
417 free(hash);
418 hash = NULL;
419 }
420out:
421 EFI_PRINT("%s: Exit, revoked: %d\n", __func__, revoked);
422 return !revoked;
423}
424
425
426
427
428
429
430
431
432
433
434
435
436
437bool efi_signature_verify(struct efi_image_regions *regs,
438 struct pkcs7_message *msg,
439 struct efi_signature_store *db,
440 struct efi_signature_store *dbx)
441{
442 struct pkcs7_signed_info *sinfo;
443 struct x509_certificate *signer, *root;
444 bool verified = false;
445 int ret;
446
447 EFI_PRINT("%s: Enter, %p, %p, %p, %p\n", __func__, regs, msg, db, dbx);
448
449 if (!regs || !msg || !db || !db->sig_data_list)
450 goto out;
451
452 for (sinfo = msg->signed_infos; sinfo; sinfo = sinfo->next) {
453 EFI_PRINT("Signed Info: digest algo: %s, pkey algo: %s\n",
454 sinfo->sig->hash_algo, sinfo->sig->pkey_algo);
455
456
457
458
459
460
461
462
463 if (!msg->data &&
464 !efi_hash_regions(regs->reg, regs->num,
465 (void **)&sinfo->sig->digest, NULL)) {
466 EFI_PRINT("Digesting an image failed\n");
467 goto out;
468 }
469
470 EFI_PRINT("Verifying certificate chain\n");
471 signer = NULL;
472 ret = pkcs7_verify_one(msg, sinfo, &signer);
473 if (ret == -ENOPKG)
474 continue;
475
476 if (ret < 0 || !signer)
477 goto out;
478
479 if (sinfo->blacklisted)
480 goto out;
481
482 EFI_PRINT("Verifying last certificate in chain\n");
483 if (signer->self_signed) {
484 if (efi_lookup_certificate(signer, db))
485 if (efi_signature_check_revocation(sinfo,
486 signer, dbx))
487 break;
488 } else if (efi_verify_certificate(signer, db, &root)) {
489 bool check;
490
491 check = efi_signature_check_revocation(sinfo, root,
492 dbx);
493 x509_free_certificate(root);
494 if (check)
495 break;
496 }
497
498 EFI_PRINT("Certificate chain didn't reach trusted CA\n");
499 }
500 if (sinfo)
501 verified = true;
502out:
503 EFI_PRINT("%s: Exit, verified: %d\n", __func__, verified);
504 return verified;
505}
506
507
508
509
510
511
512
513
514
515
516
517bool efi_signature_check_signers(struct pkcs7_message *msg,
518 struct efi_signature_store *dbx)
519{
520 struct pkcs7_signed_info *sinfo;
521 bool revoked = false;
522
523 EFI_PRINT("%s: Enter, %p, %p\n", __func__, msg, dbx);
524
525 if (!msg || !dbx)
526 goto out;
527
528 for (sinfo = msg->signed_infos; sinfo; sinfo = sinfo->next) {
529 if (sinfo->signer &&
530 !efi_signature_check_revocation(sinfo, sinfo->signer,
531 dbx)) {
532 revoked = true;
533 break;
534 }
535 }
536out:
537 EFI_PRINT("%s: Exit, revoked: %d\n", __func__, revoked);
538 return !revoked;
539}
540
541
542
543
544
545
546
547
548void efi_sigstore_free(struct efi_signature_store *sigstore)
549{
550 struct efi_signature_store *sigstore_next;
551 struct efi_sig_data *sig_data, *sig_data_next;
552
553 while (sigstore) {
554 sigstore_next = sigstore->next;
555
556 sig_data = sigstore->sig_data_list;
557 while (sig_data) {
558 sig_data_next = sig_data->next;
559 free(sig_data->data);
560 free(sig_data);
561 sig_data = sig_data_next;
562 }
563
564 free(sigstore);
565 sigstore = sigstore_next;
566 }
567}
568
569
570
571
572
573
574
575
576
577
578
579static struct efi_signature_store *
580efi_sigstore_parse_siglist(struct efi_signature_list *esl)
581{
582 struct efi_signature_store *siglist = NULL;
583 struct efi_sig_data *sig_data, *sig_data_next;
584 struct efi_signature_data *esd;
585 size_t left;
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611 if (esl->signature_list_size
612 <= (sizeof(*esl) + esl->signature_header_size)) {
613 EFI_PRINT("Siglist in wrong format\n");
614 return NULL;
615 }
616
617
618 siglist = calloc(sizeof(*siglist), 1);
619 if (!siglist) {
620 EFI_PRINT("Out of memory\n");
621 goto err;
622 }
623 memcpy(&siglist->sig_type, &esl->signature_type, sizeof(efi_guid_t));
624
625
626 sig_data_next = NULL;
627 left = esl->signature_list_size
628 - (sizeof(*esl) + esl->signature_header_size);
629 esd = (struct efi_signature_data *)
630 ((u8 *)esl + sizeof(*esl) + esl->signature_header_size);
631
632 while (left > 0) {
633
634 if (left < esl->signature_size) {
635 EFI_PRINT("Certificate is too small\n");
636 goto err;
637 }
638
639 sig_data = calloc(esl->signature_size
640 - sizeof(esd->signature_owner), 1);
641 if (!sig_data) {
642 EFI_PRINT("Out of memory\n");
643 goto err;
644 }
645
646
647 memcpy(&sig_data->owner, &esd->signature_owner,
648 sizeof(efi_guid_t));
649 sig_data->size = esl->signature_size
650 - sizeof(esd->signature_owner);
651 sig_data->data = malloc(sig_data->size);
652 if (!sig_data->data) {
653 EFI_PRINT("Out of memory\n");
654 goto err;
655 }
656 memcpy(sig_data->data, esd->signature_data, sig_data->size);
657
658 sig_data->next = sig_data_next;
659 sig_data_next = sig_data;
660
661
662 esd = (struct efi_signature_data *)
663 ((u8 *)esd + esl->signature_size);
664 left -= esl->signature_size;
665 }
666 siglist->sig_data_list = sig_data_next;
667
668 return siglist;
669
670err:
671 efi_sigstore_free(siglist);
672
673 return NULL;
674}
675
676
677
678
679
680
681
682
683
684
685
686
687
688struct efi_signature_store *efi_build_signature_store(void *sig_list,
689 efi_uintn_t size)
690{
691 struct efi_signature_list *esl;
692 struct efi_signature_store *sigstore = NULL, *siglist;
693
694 esl = sig_list;
695 while (size > 0) {
696
697 if (size < sizeof(*esl)) {
698 EFI_PRINT("Signature list in wrong format\n");
699 goto err;
700 }
701
702 if (size < esl->signature_list_size) {
703 EFI_PRINT("Signature list in wrong format\n");
704 goto err;
705 }
706
707
708 siglist = efi_sigstore_parse_siglist(esl);
709 if (!siglist) {
710 EFI_PRINT("Parsing of signature list of failed\n");
711 goto err;
712 }
713
714
715 siglist->next = sigstore;
716 sigstore = siglist;
717
718
719 size -= esl->signature_list_size;
720 esl = (void *)esl + esl->signature_list_size;
721 }
722 free(sig_list);
723
724 return sigstore;
725
726err:
727 efi_sigstore_free(sigstore);
728 free(sig_list);
729
730 return NULL;
731}
732
733
734
735
736
737
738
739
740
741
742struct efi_signature_store *efi_sigstore_parse_sigdb(u16 *name)
743{
744 const efi_guid_t *vendor;
745 void *db;
746 efi_uintn_t db_size;
747
748 vendor = efi_auth_var_get_guid(name);
749 db = efi_get_var(name, vendor, &db_size);
750 if (!db) {
751 EFI_PRINT("variable, %ls, not found\n", name);
752 return calloc(sizeof(struct efi_signature_store), 1);
753 }
754
755 return efi_build_signature_store(db, db_size);
756}
757