1 /*-
2 * Copyright (c) 2017-2018, Juniper Networks, Inc.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
14 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
15 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
16 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
17 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
18 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
19 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
21 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25 #include <sys/cdefs.h>
26 __FBSDID("$FreeBSD$");
27
28 /**
29 * @file vets.c - trust store
30 * @brief verify signatures
31 *
32 * We leverage code from BearSSL www.bearssl.org
33 */
34
35 #include <sys/time.h>
36 #include <stdarg.h>
37 #define NEED_BRSSL_H
38 #include "libsecureboot-priv.h"
39 #include <brssl.h>
40 #include <ta.h>
41
42 #ifndef TRUST_ANCHOR_STR
43 # define TRUST_ANCHOR_STR ta_PEM
44 #endif
45
46 #define SECONDS_PER_DAY 86400
47 #define X509_DAYS_TO_UTC0 719528
48
49 int DebugVe = 0;
50
51 typedef VECTOR(br_x509_certificate) cert_list;
52 typedef VECTOR(hash_data) digest_list;
53
54 static anchor_list trust_anchors = VEC_INIT;
55 static anchor_list forbidden_anchors = VEC_INIT;
56 static digest_list forbidden_digests = VEC_INIT;
57
58 static int anchor_verbose = 0;
59
60 void
ve_anchor_verbose_set(int n)61 ve_anchor_verbose_set(int n)
62 {
63 anchor_verbose = n;
64 }
65
66 int
ve_anchor_verbose_get(void)67 ve_anchor_verbose_get(void)
68 {
69 return (anchor_verbose);
70 }
71
72 void
ve_debug_set(int n)73 ve_debug_set(int n)
74 {
75 DebugVe = n;
76 }
77
78 static char ebuf[512];
79
80 char *
ve_error_get(void)81 ve_error_get(void)
82 {
83 return (ebuf);
84 }
85
86 int
ve_error_set(const char * fmt,...)87 ve_error_set(const char *fmt, ...)
88 {
89 int rc;
90 va_list ap;
91
92 va_start(ap, fmt);
93 ebuf[0] = '\0';
94 rc = 0;
95 if (fmt) {
96 #ifdef STAND_H
97 vsprintf(ebuf, fmt, ap); /* no vsnprintf in libstand */
98 ebuf[sizeof(ebuf) - 1] = '\0';
99 rc = strlen(ebuf);
100 #else
101 rc = vsnprintf(ebuf, sizeof(ebuf), fmt, ap);
102 #endif
103 }
104 va_end(ap);
105 return (rc);
106 }
107
108 /* this is the time we use for verifying certs */
109 static time_t ve_utc = 0;
110
111 /**
112 * @brief
113 * set ve_utc used for certificate verification
114 *
115 * @param[in] utc
116 * time - ignored unless greater than current value.
117 */
118 void
ve_utc_set(time_t utc)119 ve_utc_set(time_t utc)
120 {
121 if (utc > ve_utc) {
122 DEBUG_PRINTF(2, ("Set ve_utc=%jd\n", (intmax_t)utc));
123 ve_utc = utc;
124 }
125 }
126
127 static void
free_cert_contents(br_x509_certificate * xc)128 free_cert_contents(br_x509_certificate *xc)
129 {
130 xfree(xc->data);
131 }
132
133 /*
134 * a bit of a dance to get commonName from a certificate
135 */
136 static char *
x509_cn_get(br_x509_certificate * xc,char * buf,size_t len)137 x509_cn_get(br_x509_certificate *xc, char *buf, size_t len)
138 {
139 br_x509_minimal_context mc;
140 br_name_element cn;
141 unsigned char cn_oid[4];
142 int err;
143
144 if (buf == NULL)
145 return (buf);
146 /*
147 * We want the commonName field
148 * the OID we want is 2,5,4,3 - but DER encoded
149 */
150 cn_oid[0] = 3;
151 cn_oid[1] = 0x55;
152 cn_oid[2] = 4;
153 cn_oid[3] = 3;
154 cn.oid = cn_oid;
155 cn.buf = buf;
156 cn.len = len;
157 cn.buf[0] = '\0';
158
159 br_x509_minimal_init(&mc, &br_sha256_vtable, NULL, 0);
160 br_x509_minimal_set_name_elements(&mc, &cn, 1);
161 /* the below actually does the work - updates cn.status */
162 mc.vtable->start_chain(&mc.vtable, NULL);
163 mc.vtable->start_cert(&mc.vtable, xc->data_len);
164 mc.vtable->append(&mc.vtable, xc->data, xc->data_len);
165 mc.vtable->end_cert(&mc.vtable);
166 /* we don' actually care about cert status - just its name */
167 err = mc.vtable->end_chain(&mc.vtable);
168
169 if (!cn.status)
170 buf = NULL;
171 return (buf);
172 }
173
174 /* ASN parsing related defines */
175 #define ASN1_PRIMITIVE_TAG 0x1F
176 #define ASN1_INF_LENGTH 0x80
177 #define ASN1_LENGTH_MASK 0x7F
178
179 /*
180 * Get TBS part of certificate.
181 * Since BearSSL doesn't provide any API to do this,
182 * it has to be implemented here.
183 */
184 static void*
X509_to_tbs(unsigned char * cert,size_t * output_size)185 X509_to_tbs(unsigned char* cert, size_t* output_size)
186 {
187 unsigned char *result;
188 size_t tbs_size;
189 int size, i;
190
191 if (cert == NULL)
192 return (NULL);
193
194 /* Strip two sequences to get to the TBS section */
195 for (i = 0; i < 2; i++) {
196 /*
197 * XXX: We don't need to support extended tags since
198 * they should not be present in certificates.
199 */
200 if ((*cert & ASN1_PRIMITIVE_TAG) == ASN1_PRIMITIVE_TAG)
201 return (NULL);
202
203 cert++;
204
205 if (*cert == ASN1_INF_LENGTH)
206 return (NULL);
207
208 size = *cert & ASN1_LENGTH_MASK;
209 tbs_size = 0;
210
211 /* Size can either be stored on a single or multiple bytes */
212 if (*cert & (ASN1_LENGTH_MASK + 1)) {
213 cert++;
214 while (*cert == 0 && size > 0) {
215 cert++;
216 size--;
217 }
218 while (size-- > 0) {
219 tbs_size <<= 8;
220 tbs_size |= *(cert++);
221 }
222 }
223 if (i == 0)
224 result = cert;
225 }
226 tbs_size += (cert - result);
227
228 if (output_size != NULL)
229 *output_size = tbs_size;
230
231 return (result);
232 }
233
234 void
ve_forbidden_digest_add(hash_data * digest,size_t num)235 ve_forbidden_digest_add(hash_data *digest, size_t num)
236 {
237 while (num--)
238 VEC_ADD(forbidden_digests, digest[num]);
239 }
240
241 static size_t
ve_anchors_add(br_x509_certificate * xcs,size_t num,anchor_list * anchors,char * anchors_name)242 ve_anchors_add(br_x509_certificate *xcs, size_t num, anchor_list *anchors,
243 char *anchors_name)
244 {
245 br_x509_trust_anchor ta;
246 size_t u;
247
248 for (u = 0; u < num; u++) {
249 if (certificate_to_trust_anchor_inner(&ta, &xcs[u]) < 0) {
250 break;
251 }
252 VEC_ADD(*anchors, ta);
253 if (anchor_verbose && anchors_name) {
254 char buf[64];
255 char *cp;
256
257 cp = x509_cn_get(&xcs[u], buf, sizeof(buf));
258 if (cp) {
259 printf("x509_anchor(%s) %s\n", cp, anchors_name);
260 }
261 }
262 }
263 return (u);
264 }
265
266 /**
267 * @brief
268 * add certs to our trust store
269 */
270 size_t
ve_trust_anchors_add(br_x509_certificate * xcs,size_t num)271 ve_trust_anchors_add(br_x509_certificate *xcs, size_t num)
272 {
273 return (ve_anchors_add(xcs, num, &trust_anchors, "trusted"));
274 }
275
276 size_t
ve_forbidden_anchors_add(br_x509_certificate * xcs,size_t num)277 ve_forbidden_anchors_add(br_x509_certificate *xcs, size_t num)
278 {
279 return (ve_anchors_add(xcs, num, &forbidden_anchors, "forbidden"));
280 }
281
282
283 /**
284 * @brief add trust anchors in buf
285 *
286 * Assume buf contains x509 certificates, but if not and
287 * we support OpenPGP try adding as that.
288 *
289 * @return number of anchors added
290 */
291 size_t
ve_trust_anchors_add_buf(unsigned char * buf,size_t len)292 ve_trust_anchors_add_buf(unsigned char *buf, size_t len)
293 {
294 br_x509_certificate *xcs;
295 size_t num;
296
297 num = 0;
298 xcs = parse_certificates(buf, len, &num);
299 if (xcs != NULL) {
300 num = ve_trust_anchors_add(xcs, num);
301 #ifdef VE_OPENPGP_SUPPORT
302 } else {
303 num = openpgp_trust_add_buf(buf, len);
304 #endif
305 }
306 return (num);
307 }
308
309 /**
310 * @brief revoke trust anchors in buf
311 *
312 * Assume buf contains x509 certificates, but if not and
313 * we support OpenPGP try revoking keyId
314 *
315 * @return number of anchors revoked
316 */
317 size_t
ve_trust_anchors_revoke(unsigned char * buf,size_t len)318 ve_trust_anchors_revoke(unsigned char *buf, size_t len)
319 {
320 br_x509_certificate *xcs;
321 size_t num;
322
323 num = 0;
324 xcs = parse_certificates(buf, len, &num);
325 if (xcs != NULL) {
326 num = ve_forbidden_anchors_add(xcs, num);
327 #ifdef VE_OPENPGP_SUPPORT
328 } else {
329 if (buf[len - 1] == '\n')
330 buf[len - 1] = '\0';
331 num = openpgp_trust_revoke((char *)buf);
332 #endif
333 }
334 return (num);
335 }
336
337 /**
338 * @brief
339 * initialize our trust_anchors from ta_PEM
340 */
341 int
ve_trust_init(void)342 ve_trust_init(void)
343 {
344 static int once = -1;
345
346 if (once >= 0)
347 return (once);
348
349 ve_utc_set(time(NULL));
350 #ifdef BUILD_UTC
351 ve_utc_set(BUILD_UTC); /* just in case */
352 #endif
353 ve_error_set(NULL); /* make sure it is empty */
354 #ifdef VE_PCR_SUPPORT
355 ve_pcr_init();
356 #endif
357
358 #ifdef TRUST_ANCHOR_STR
359 ve_trust_anchors_add_buf(__DECONST(unsigned char *, TRUST_ANCHOR_STR),
360 sizeof(TRUST_ANCHOR_STR));
361 #endif
362 once = (int) VEC_LEN(trust_anchors);
363 #ifdef VE_OPENPGP_SUPPORT
364 once += openpgp_trust_init();
365 #endif
366 return (once);
367 }
368
369 /**
370 * if we can verify the certificate chain in "certs",
371 * return the public key and if "xcp" is !NULL the associated
372 * certificate
373 */
374 static br_x509_pkey *
verify_signer_xcs(br_x509_certificate * xcs,size_t num,br_name_element * elts,size_t num_elts,anchor_list * anchors)375 verify_signer_xcs(br_x509_certificate *xcs,
376 size_t num,
377 br_name_element *elts, size_t num_elts,
378 anchor_list *anchors)
379 {
380 br_x509_minimal_context mc;
381 br_x509_certificate *xc;
382 size_t u;
383 cert_list chain = VEC_INIT;
384 const br_x509_pkey *tpk;
385 br_x509_pkey *pk;
386 unsigned int usages;
387 int err;
388
389 DEBUG_PRINTF(5, ("verify_signer: %zu certs in chain\n", num));
390 VEC_ADDMANY(chain, xcs, num);
391 if (VEC_LEN(chain) == 0) {
392 ve_error_set("ERROR: no/invalid certificate chain\n");
393 return (NULL);
394 }
395
396 DEBUG_PRINTF(5, ("verify_signer: %zu trust anchors\n",
397 VEC_LEN(*anchors)));
398
399 br_x509_minimal_init(&mc, &br_sha256_vtable,
400 &VEC_ELT(*anchors, 0),
401 VEC_LEN(*anchors));
402 #ifdef VE_ECDSA_SUPPORT
403 br_x509_minimal_set_ecdsa(&mc,
404 &br_ec_prime_i31, &br_ecdsa_i31_vrfy_asn1);
405 #endif
406 #ifdef VE_RSA_SUPPORT
407 br_x509_minimal_set_rsa(&mc, &br_rsa_i31_pkcs1_vrfy);
408 #endif
409 #if defined(UNIT_TEST) && defined(VE_DEPRECATED_RSA_SHA1_SUPPORT)
410 /* This is deprecated! do not enable unless you absoultely have to */
411 br_x509_minimal_set_hash(&mc, br_sha1_ID, &br_sha1_vtable);
412 #endif
413 br_x509_minimal_set_hash(&mc, br_sha256_ID, &br_sha256_vtable);
414 #ifdef VE_SHA384_SUPPORT
415 br_x509_minimal_set_hash(&mc, br_sha384_ID, &br_sha384_vtable);
416 #endif
417 #ifdef VE_SHA512_SUPPORT
418 br_x509_minimal_set_hash(&mc, br_sha512_ID, &br_sha512_vtable);
419 #endif
420 br_x509_minimal_set_name_elements(&mc, elts, num_elts);
421
422 #ifdef _STANDALONE
423 /*
424 * Clock is probably bogus so we use ve_utc.
425 */
426 mc.days = (ve_utc / SECONDS_PER_DAY) + X509_DAYS_TO_UTC0;
427 mc.seconds = (ve_utc % SECONDS_PER_DAY);
428 #endif
429
430 mc.vtable->start_chain(&mc.vtable, NULL);
431 for (u = 0; u < VEC_LEN(chain); u ++) {
432 xc = &VEC_ELT(chain, u);
433 mc.vtable->start_cert(&mc.vtable, xc->data_len);
434 mc.vtable->append(&mc.vtable, xc->data, xc->data_len);
435 mc.vtable->end_cert(&mc.vtable);
436 switch (mc.err) {
437 case 0:
438 case BR_ERR_X509_OK:
439 case BR_ERR_X509_EXPIRED:
440 break;
441 default:
442 printf("u=%zu mc.err=%d\n", u, mc.err);
443 break;
444 }
445 }
446 err = mc.vtable->end_chain(&mc.vtable);
447 pk = NULL;
448 if (err) {
449 ve_error_set("Validation failed, err = %d", err);
450 } else {
451 tpk = mc.vtable->get_pkey(&mc.vtable, &usages);
452 if (tpk != NULL) {
453 pk = xpkeydup(tpk);
454 }
455 }
456 VEC_CLEAR(chain);
457 return (pk);
458 }
459
460 /*
461 * Check if digest of one of the certificates from verified chain
462 * is present in the forbidden database.
463 * Since UEFI allows to store three types of digests
464 * all of them have to be checked separately.
465 */
466 static int
check_forbidden_digests(br_x509_certificate * xcs,size_t num)467 check_forbidden_digests(br_x509_certificate *xcs, size_t num)
468 {
469 unsigned char sha256_digest[br_sha256_SIZE];
470 unsigned char sha384_digest[br_sha384_SIZE];
471 unsigned char sha512_digest[br_sha512_SIZE];
472 void *tbs;
473 hash_data *digest;
474 br_hash_compat_context ctx;
475 const br_hash_class *md;
476 size_t tbs_len, i;
477 int have_sha256, have_sha384, have_sha512;
478
479 if (VEC_LEN(forbidden_digests) == 0)
480 return (0);
481
482 /*
483 * Iterate through certificates, extract their To-Be-Signed section,
484 * and compare its digest against the ones in the forbidden database.
485 */
486 while (num--) {
487 tbs = X509_to_tbs(xcs[num].data, &tbs_len);
488 if (tbs == NULL) {
489 printf("Failed to obtain TBS part of certificate\n");
490 return (1);
491 }
492 have_sha256 = have_sha384 = have_sha512 = 0;
493
494 for (i = 0; i < VEC_LEN(forbidden_digests); i++) {
495 digest = &VEC_ELT(forbidden_digests, i);
496 switch (digest->hash_size) {
497 case br_sha256_SIZE:
498 if (!have_sha256) {
499 have_sha256 = 1;
500 md = &br_sha256_vtable;
501 md->init(&ctx.vtable);
502 md->update(&ctx.vtable, tbs, tbs_len);
503 md->out(&ctx.vtable, sha256_digest);
504 }
505 if (!memcmp(sha256_digest,
506 digest->data,
507 br_sha256_SIZE))
508 return (1);
509
510 break;
511 case br_sha384_SIZE:
512 if (!have_sha384) {
513 have_sha384 = 1;
514 md = &br_sha384_vtable;
515 md->init(&ctx.vtable);
516 md->update(&ctx.vtable, tbs, tbs_len);
517 md->out(&ctx.vtable, sha384_digest);
518 }
519 if (!memcmp(sha384_digest,
520 digest->data,
521 br_sha384_SIZE))
522 return (1);
523
524 break;
525 case br_sha512_SIZE:
526 if (!have_sha512) {
527 have_sha512 = 1;
528 md = &br_sha512_vtable;
529 md->init(&ctx.vtable);
530 md->update(&ctx.vtable, tbs, tbs_len);
531 md->out(&ctx.vtable, sha512_digest);
532 }
533 if (!memcmp(sha512_digest,
534 digest->data,
535 br_sha512_SIZE))
536 return (1);
537
538 break;
539 }
540 }
541 }
542
543 return (0);
544 }
545
546 static br_x509_pkey *
verify_signer(const char * certs,br_name_element * elts,size_t num_elts)547 verify_signer(const char *certs,
548 br_name_element *elts, size_t num_elts)
549 {
550 br_x509_certificate *xcs;
551 br_x509_pkey *pk;
552 size_t num;
553
554 pk = NULL;
555
556 ve_trust_init();
557 xcs = read_certificates(certs, &num);
558 if (xcs == NULL) {
559 ve_error_set("cannot read certificates\n");
560 return (NULL);
561 }
562
563 /*
564 * Check if either
565 * 1. There is a direct match between cert from forbidden_anchors
566 * and a cert from chain.
567 * 2. CA that signed the chain is found in forbidden_anchors.
568 */
569 if (VEC_LEN(forbidden_anchors) > 0)
570 pk = verify_signer_xcs(xcs, num, elts, num_elts, &forbidden_anchors);
571 if (pk != NULL) {
572 ve_error_set("Certificate is on forbidden list\n");
573 xfreepkey(pk);
574 pk = NULL;
575 goto out;
576 }
577
578 pk = verify_signer_xcs(xcs, num, elts, num_elts, &trust_anchors);
579 if (pk == NULL)
580 goto out;
581
582 /*
583 * Check if hash of tbs part of any certificate in chain
584 * is on the forbidden list.
585 */
586 if (check_forbidden_digests(xcs, num)) {
587 ve_error_set("Certificate hash is on forbidden list\n");
588 xfreepkey(pk);
589 pk = NULL;
590 }
591 out:
592 free_certificates(xcs, num);
593 return (pk);
594 }
595
596 /**
597 * we need a hex digest including trailing newline below
598 */
599 char *
hexdigest(char * buf,size_t bufsz,unsigned char * foo,size_t foo_len)600 hexdigest(char *buf, size_t bufsz, unsigned char *foo, size_t foo_len)
601 {
602 char const hex2ascii[] = "0123456789abcdef";
603 size_t i;
604
605 /* every binary byte is 2 chars in hex + newline + null */
606 if (bufsz < (2 * foo_len) + 2)
607 return (NULL);
608
609 for (i = 0; i < foo_len; i++) {
610 buf[i * 2] = hex2ascii[foo[i] >> 4];
611 buf[i * 2 + 1] = hex2ascii[foo[i] & 0x0f];
612 }
613
614 buf[i * 2] = 0x0A; /* we also want a newline */
615 buf[i * 2 + 1] = '\0';
616
617 return (buf);
618 }
619
620 /**
621 * @brief
622 * verify file against sigfile using pk
623 *
624 * When we generated the signature in sigfile,
625 * we hashed (sha256) file, and sent that to signing server
626 * which hashed (sha256) that hash.
627 *
628 * To verify we need to replicate that result.
629 *
630 * @param[in] pk
631 * br_x509_pkey
632 *
633 * @paramp[in] file
634 * file to be verified
635 *
636 * @param[in] sigfile
637 * signature (PEM encoded)
638 *
639 * @return NULL on error, otherwise content of file.
640 */
641 #ifdef VE_ECDSA_SUPPORT
642 static unsigned char *
verify_ec(br_x509_pkey * pk,const char * file,const char * sigfile)643 verify_ec(br_x509_pkey *pk, const char *file, const char *sigfile)
644 {
645 char hexbuf[br_sha512_SIZE * 2 + 2];
646 unsigned char rhbuf[br_sha512_SIZE];
647 char *hex;
648 br_sha256_context ctx;
649 unsigned char *fcp, *scp;
650 size_t flen, slen, plen;
651 pem_object *po;
652 const br_ec_impl *ec;
653 br_ecdsa_vrfy vrfy;
654
655 if ((fcp = read_file(file, &flen)) == NULL)
656 return (NULL);
657 if ((scp = read_file(sigfile, &slen)) == NULL) {
658 free(fcp);
659 return (NULL);
660 }
661 if ((po = decode_pem(scp, slen, &plen)) == NULL) {
662 free(fcp);
663 free(scp);
664 return (NULL);
665 }
666 br_sha256_init(&ctx);
667 br_sha256_update(&ctx, fcp, flen);
668 br_sha256_out(&ctx, rhbuf);
669 #ifdef VE_ECDSA_HASH_AGAIN
670 hex = hexdigest(hexbuf, sizeof(hexbuf), rhbuf, br_sha256_SIZE);
671 /* now hash that */
672 if (hex) {
673 br_sha256_init(&ctx);
674 br_sha256_update(&ctx, hex, strlen(hex));
675 br_sha256_out(&ctx, rhbuf);
676 }
677 #endif
678 ec = br_ec_get_default();
679 vrfy = br_ecdsa_vrfy_asn1_get_default();
680 if (!vrfy(ec, rhbuf, br_sha256_SIZE, &pk->key.ec, po->data,
681 po->data_len)) {
682 free(fcp);
683 fcp = NULL;
684 }
685 free(scp);
686 return (fcp);
687 }
688 #endif
689
690 #if defined(VE_RSA_SUPPORT) || defined(VE_OPENPGP_SUPPORT)
691 /**
692 * @brief verify an rsa digest
693 *
694 * @return 0 on failure
695 */
696 int
verify_rsa_digest(br_rsa_public_key * pkey,const unsigned char * hash_oid,unsigned char * mdata,size_t mlen,unsigned char * sdata,size_t slen)697 verify_rsa_digest (br_rsa_public_key *pkey,
698 const unsigned char *hash_oid,
699 unsigned char *mdata, size_t mlen,
700 unsigned char *sdata, size_t slen)
701 {
702 br_rsa_pkcs1_vrfy vrfy;
703 unsigned char vhbuf[br_sha512_SIZE];
704
705 vrfy = br_rsa_pkcs1_vrfy_get_default();
706
707 if (!vrfy(sdata, slen, hash_oid, mlen, pkey, vhbuf) ||
708 memcmp(vhbuf, mdata, mlen) != 0) {
709 return (0); /* fail */
710 }
711 return (1); /* ok */
712 }
713 #endif
714
715 /**
716 * @brief
717 * verify file against sigfile using pk
718 *
719 * When we generated the signature in sigfile,
720 * we hashed (sha256) file, and sent that to signing server
721 * which hashed (sha256) that hash.
722 *
723 * Or (deprecated) we simply used sha1 hash directly.
724 *
725 * To verify we need to replicate that result.
726 *
727 * @param[in] pk
728 * br_x509_pkey
729 *
730 * @paramp[in] file
731 * file to be verified
732 *
733 * @param[in] sigfile
734 * signature (PEM encoded)
735 *
736 * @return NULL on error, otherwise content of file.
737 */
738 #ifdef VE_RSA_SUPPORT
739 static unsigned char *
verify_rsa(br_x509_pkey * pk,const char * file,const char * sigfile)740 verify_rsa(br_x509_pkey *pk, const char *file, const char *sigfile)
741 {
742 unsigned char rhbuf[br_sha512_SIZE];
743 const unsigned char *hash_oid;
744 const br_hash_class *md;
745 br_hash_compat_context mctx;
746 unsigned char *fcp, *scp;
747 size_t flen, slen, plen, hlen;
748 pem_object *po;
749
750 if ((fcp = read_file(file, &flen)) == NULL)
751 return (NULL);
752 if ((scp = read_file(sigfile, &slen)) == NULL) {
753 free(fcp);
754 return (NULL);
755 }
756 if ((po = decode_pem(scp, slen, &plen)) == NULL) {
757 free(fcp);
758 free(scp);
759 return (NULL);
760 }
761
762 switch (po->data_len) {
763 #if defined(UNIT_TEST) && defined(VE_DEPRECATED_RSA_SHA1_SUPPORT)
764 case 256:
765 // this is our old deprecated sig method
766 md = &br_sha1_vtable;
767 hlen = br_sha1_SIZE;
768 hash_oid = BR_HASH_OID_SHA1;
769 break;
770 #endif
771 default:
772 md = &br_sha256_vtable;
773 hlen = br_sha256_SIZE;
774 hash_oid = BR_HASH_OID_SHA256;
775 break;
776 }
777 md->init(&mctx.vtable);
778 md->update(&mctx.vtable, fcp, flen);
779 md->out(&mctx.vtable, rhbuf);
780 if (!verify_rsa_digest(&pk->key.rsa, hash_oid,
781 rhbuf, hlen, po->data, po->data_len)) {
782 free(fcp);
783 fcp = NULL;
784 }
785 free(scp);
786 return (fcp);
787 }
788 #endif
789
790 /**
791 * @brief
792 * verify a signature and return content of signed file
793 *
794 * @param[in] sigfile
795 * file containing signature
796 * we derrive path of signed file and certificate change from
797 * this.
798 *
799 * @param[in] flags
800 * only bit 1 significant so far
801 *
802 * @return NULL on error otherwise content of signed file
803 */
804 unsigned char *
verify_sig(const char * sigfile,int flags)805 verify_sig(const char *sigfile, int flags)
806 {
807 br_x509_pkey *pk;
808 br_name_element cn;
809 char cn_buf[80];
810 unsigned char cn_oid[4];
811 char pbuf[MAXPATHLEN];
812 char *cp;
813 unsigned char *ucp;
814 size_t n;
815
816 DEBUG_PRINTF(5, ("verify_sig: %s\n", sigfile));
817 n = strlcpy(pbuf, sigfile, sizeof(pbuf));
818 if (n > (sizeof(pbuf) - 5) || strcmp(&sigfile[n - 3], "sig") != 0)
819 return (NULL);
820 cp = strcpy(&pbuf[n - 3], "certs");
821 /*
822 * We want the commonName field
823 * the OID we want is 2,5,4,3 - but DER encoded
824 */
825 cn_oid[0] = 3;
826 cn_oid[1] = 0x55;
827 cn_oid[2] = 4;
828 cn_oid[3] = 3;
829 cn.oid = cn_oid;
830 cn.buf = cn_buf;
831 cn.len = sizeof(cn_buf);
832
833 pk = verify_signer(pbuf, &cn, 1);
834 if (!pk) {
835 printf("cannot verify: %s: %s\n", pbuf, ve_error_get());
836 return (NULL);
837 }
838 for (; cp > pbuf; cp--) {
839 if (*cp == '.') {
840 *cp = '\0';
841 break;
842 }
843 }
844 switch (pk->key_type) {
845 #ifdef VE_ECDSA_SUPPORT
846 case BR_KEYTYPE_EC:
847 ucp = verify_ec(pk, pbuf, sigfile);
848 break;
849 #endif
850 #ifdef VE_RSA_SUPPORT
851 case BR_KEYTYPE_RSA:
852 ucp = verify_rsa(pk, pbuf, sigfile);
853 break;
854 #endif
855 default:
856 ucp = NULL; /* not supported */
857 }
858 xfreepkey(pk);
859 if (!ucp) {
860 printf("Unverified %s (%s)\n", pbuf,
861 cn.status ? cn_buf : "unknown");
862 } else if ((flags & 1) != 0) {
863 printf("Verified %s signed by %s\n", pbuf,
864 cn.status ? cn_buf : "someone we trust");
865 }
866 return (ucp);
867 }
868
869
870 /**
871 * @brief verify hash matches
872 *
873 * We have finished hashing a file,
874 * see if we got the desired result.
875 *
876 * @param[in] ctx
877 * pointer to hash context
878 *
879 * @param[in] md
880 * pointer to hash class
881 *
882 * @param[in] path
883 * name of the file we are checking
884 *
885 * @param[in] want
886 * the expected result
887 *
888 * @param[in] hlen
889 * size of hash output
890 *
891 * @return 0 on success
892 */
893 int
ve_check_hash(br_hash_compat_context * ctx,const br_hash_class * md,const char * path,const char * want,size_t hlen)894 ve_check_hash(br_hash_compat_context *ctx, const br_hash_class *md,
895 const char *path, const char *want, size_t hlen)
896 {
897 char hexbuf[br_sha512_SIZE * 2 + 2];
898 unsigned char hbuf[br_sha512_SIZE];
899 char *hex;
900 int rc;
901 int n;
902
903 md->out(&ctx->vtable, hbuf);
904 #ifdef VE_PCR_SUPPORT
905 ve_pcr_update(hbuf, hlen);
906 #endif
907 hex = hexdigest(hexbuf, sizeof(hexbuf), hbuf, hlen);
908 if (!hex)
909 return (VE_FINGERPRINT_WRONG);
910 n = 2*hlen;
911 if ((rc = strncmp(hex, want, n))) {
912 ve_error_set("%s: %.*s != %.*s", path, n, hex, n, want);
913 rc = VE_FINGERPRINT_WRONG;
914 }
915 return (rc ? rc : VE_FINGERPRINT_OK);
916 }
917
918 #ifdef VE_HASH_KAT_STR
919 static int
test_hash(const br_hash_class * md,size_t hlen,const char * hname,const char * s,size_t slen,const char * want)920 test_hash(const br_hash_class *md, size_t hlen,
921 const char *hname, const char *s, size_t slen, const char *want)
922 {
923 br_hash_compat_context mctx;
924
925 md->init(&mctx.vtable);
926 md->update(&mctx.vtable, s, slen);
927 return (ve_check_hash(&mctx, md, hname, want, hlen) != VE_FINGERPRINT_OK);
928 }
929
930 #endif
931
932 #define ve_test_hash(n, N) \
933 printf("Testing hash: " #n "\t\t\t\t%s\n", \
934 test_hash(&br_ ## n ## _vtable, br_ ## n ## _SIZE, #n, \
935 VE_HASH_KAT_STR, VE_HASH_KAT_STRLEN(VE_HASH_KAT_STR), \
936 vh_ ## N) ? "Failed" : "Passed")
937
938 /**
939 * @brief
940 * run self tests on hash and signature verification
941 *
942 * Test that the hash methods (SHA1 and SHA256) work.
943 * Test that we can verify a certificate for each supported
944 * Root CA.
945 *
946 * @return cached result.
947 */
948 int
ve_self_tests(void)949 ve_self_tests(void)
950 {
951 static int once = -1;
952 #ifdef VERIFY_CERTS_STR
953 br_x509_certificate *xcs;
954 br_x509_pkey *pk;
955 br_name_element cn;
956 char cn_buf[80];
957 unsigned char cn_oid[4];
958 size_t num;
959 size_t u;
960 #endif
961
962 if (once >= 0)
963 return (once);
964 once = 0;
965
966 DEBUG_PRINTF(5, ("Self tests...\n"));
967 #ifdef VE_HASH_KAT_STR
968 #ifdef VE_SHA1_SUPPORT
969 ve_test_hash(sha1, SHA1);
970 #endif
971 #ifdef VE_SHA256_SUPPORT
972 ve_test_hash(sha256, SHA256);
973 #endif
974 #ifdef VE_SHA384_SUPPORT
975 ve_test_hash(sha384, SHA384);
976 #endif
977 #ifdef VE_SHA512_SUPPORT
978 ve_test_hash(sha512, SHA512);
979 #endif
980 #endif
981 #ifdef VERIFY_CERTS_STR
982 xcs = parse_certificates(__DECONST(unsigned char *, VERIFY_CERTS_STR),
983 sizeof(VERIFY_CERTS_STR), &num);
984 if (xcs != NULL) {
985 /*
986 * We want the commonName field
987 * the OID we want is 2,5,4,3 - but DER encoded
988 */
989 cn_oid[0] = 3;
990 cn_oid[1] = 0x55;
991 cn_oid[2] = 4;
992 cn_oid[3] = 3;
993 cn.oid = cn_oid;
994 cn.buf = cn_buf;
995
996 for (u = 0; u < num; u ++) {
997 cn.len = sizeof(cn_buf);
998 if ((pk = verify_signer_xcs(&xcs[u], 1, &cn, 1, &trust_anchors)) != NULL) {
999 free_cert_contents(&xcs[u]);
1000 once++;
1001 printf("Testing verify certificate: %s\tPassed\n",
1002 cn.status ? cn_buf : "");
1003 xfreepkey(pk);
1004 }
1005 }
1006 if (!once)
1007 printf("Testing verify certificate:\t\t\tFailed\n");
1008 xfree(xcs);
1009 }
1010 #endif /* VERIFY_CERTS_STR */
1011 #ifdef VE_OPENPGP_SUPPORT
1012 if (!openpgp_self_tests())
1013 once++;
1014 #endif
1015 return (once);
1016 }
1017