]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - lib/libsecureboot/vets.c
Implement pci_enable_msi() and pci_disable_msi() in the LinuxKPI.
[FreeBSD/FreeBSD.git] / lib / libsecureboot / vets.c
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
61 ve_anchor_verbose_set(int n)
62 {
63         anchor_verbose = n;
64 }
65
66 int
67 ve_anchor_verbose_get(void)
68 {
69         return (anchor_verbose);
70 }
71
72 void
73 ve_debug_set(int n)
74 {
75         DebugVe = n;
76 }
77
78 static char ebuf[512];
79
80 char *
81 ve_error_get(void)
82 {
83         return (ebuf);
84 }
85
86 int
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
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
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 *
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*
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
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
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
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
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
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
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
342 ve_trust_init(void)
343 {
344         static int once = -1;
345
346         if (once >= 0)
347                 return (once);
348         once = 0;                       /* to be sure */
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 *
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
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 *
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 *
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 *
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
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 *
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 *
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
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
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
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 }