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