15fff9558SSimon J. Gerraty /*-
25fff9558SSimon J. Gerraty * Copyright (c) 2017-2018, Juniper Networks, Inc.
35fff9558SSimon J. Gerraty *
45fff9558SSimon J. Gerraty * Redistribution and use in source and binary forms, with or without
55fff9558SSimon J. Gerraty * modification, are permitted provided that the following conditions
65fff9558SSimon J. Gerraty * are met:
75fff9558SSimon J. Gerraty * 1. Redistributions of source code must retain the above copyright
85fff9558SSimon J. Gerraty * notice, this list of conditions and the following disclaimer.
95fff9558SSimon J. Gerraty * 2. Redistributions in binary form must reproduce the above copyright
105fff9558SSimon J. Gerraty * notice, this list of conditions and the following disclaimer in the
115fff9558SSimon J. Gerraty * documentation and/or other materials provided with the distribution.
125fff9558SSimon J. Gerraty *
135fff9558SSimon J. Gerraty * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
145fff9558SSimon J. Gerraty * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
155fff9558SSimon J. Gerraty * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
165fff9558SSimon J. Gerraty * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
175fff9558SSimon J. Gerraty * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
185fff9558SSimon J. Gerraty * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
195fff9558SSimon J. Gerraty * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
205fff9558SSimon J. Gerraty * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
215fff9558SSimon J. Gerraty * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
225fff9558SSimon J. Gerraty * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
235fff9558SSimon J. Gerraty * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
245fff9558SSimon J. Gerraty */
255fff9558SSimon J. Gerraty #include <sys/cdefs.h>
265fff9558SSimon J. Gerraty /**
275fff9558SSimon J. Gerraty * @file vets.c - trust store
285fff9558SSimon J. Gerraty * @brief verify signatures
295fff9558SSimon J. Gerraty *
305fff9558SSimon J. Gerraty * We leverage code from BearSSL www.bearssl.org
315fff9558SSimon J. Gerraty */
325fff9558SSimon J. Gerraty
335fff9558SSimon J. Gerraty #include <sys/time.h>
345fff9558SSimon J. Gerraty #include <stdarg.h>
355fff9558SSimon J. Gerraty #define NEED_BRSSL_H
365fff9558SSimon J. Gerraty #include "libsecureboot-priv.h"
375fff9558SSimon J. Gerraty #include <brssl.h>
385fff9558SSimon J. Gerraty #include <ta.h>
395fff9558SSimon J. Gerraty
405fff9558SSimon J. Gerraty #ifndef TRUST_ANCHOR_STR
415fff9558SSimon J. Gerraty # define TRUST_ANCHOR_STR ta_PEM
425fff9558SSimon J. Gerraty #endif
435fff9558SSimon J. Gerraty
4466655411SSimon J. Gerraty #define EPOCH_YEAR 1970
4566655411SSimon J. Gerraty #define AVG_SECONDS_PER_YEAR 31556952L
465fff9558SSimon J. Gerraty #define SECONDS_PER_DAY 86400
4753f151f9SSimon J. Gerraty #define SECONDS_PER_YEAR 365 * SECONDS_PER_DAY
4853f151f9SSimon J. Gerraty #ifndef VE_UTC_MAX_JUMP
4953f151f9SSimon J. Gerraty # define VE_UTC_MAX_JUMP 20 * SECONDS_PER_YEAR
5053f151f9SSimon J. Gerraty #endif
515fff9558SSimon J. Gerraty #define X509_DAYS_TO_UTC0 719528
525fff9558SSimon J. Gerraty
535fff9558SSimon J. Gerraty int DebugVe = 0;
545fff9558SSimon J. Gerraty
5566655411SSimon J. Gerraty #ifndef VE_VERIFY_FLAGS
5666655411SSimon J. Gerraty # define VE_VERIFY_FLAGS VEF_VERBOSE
5766655411SSimon J. Gerraty #endif
5866655411SSimon J. Gerraty int VerifyFlags = VE_VERIFY_FLAGS;
5966655411SSimon J. Gerraty
605fff9558SSimon J. Gerraty typedef VECTOR(br_x509_certificate) cert_list;
6113ea0450SMarcin Wojtas typedef VECTOR(hash_data) digest_list;
625fff9558SSimon J. Gerraty
635fff9558SSimon J. Gerraty static anchor_list trust_anchors = VEC_INIT;
6413ea0450SMarcin Wojtas static anchor_list forbidden_anchors = VEC_INIT;
6513ea0450SMarcin Wojtas static digest_list forbidden_digests = VEC_INIT;
665fff9558SSimon J. Gerraty
67f9510887SSimon J. Gerraty static int anchor_verbose = 0;
68f9510887SSimon J. Gerraty
69f9510887SSimon J. Gerraty void
ve_anchor_verbose_set(int n)70f9510887SSimon J. Gerraty ve_anchor_verbose_set(int n)
71f9510887SSimon J. Gerraty {
72f9510887SSimon J. Gerraty anchor_verbose = n;
73f9510887SSimon J. Gerraty }
74f9510887SSimon J. Gerraty
75f9510887SSimon J. Gerraty int
ve_anchor_verbose_get(void)76f9510887SSimon J. Gerraty ve_anchor_verbose_get(void)
77f9510887SSimon J. Gerraty {
78f9510887SSimon J. Gerraty return (anchor_verbose);
79f9510887SSimon J. Gerraty }
80f9510887SSimon J. Gerraty
815fff9558SSimon J. Gerraty void
ve_debug_set(int n)825fff9558SSimon J. Gerraty ve_debug_set(int n)
835fff9558SSimon J. Gerraty {
845fff9558SSimon J. Gerraty DebugVe = n;
855fff9558SSimon J. Gerraty }
865fff9558SSimon J. Gerraty
87ab4f0a15SSimon J. Gerraty /*
88ab4f0a15SSimon J. Gerraty * For embedded systems (and boot loaders)
89ab4f0a15SSimon J. Gerraty * we do not want to enforce certificate validity post install.
90ab4f0a15SSimon J. Gerraty * It is generally unacceptible for infrastructure to stop working
91ab4f0a15SSimon J. Gerraty * just because it has not been updated recently.
92ab4f0a15SSimon J. Gerraty */
93ab4f0a15SSimon J. Gerraty static int enforce_validity = 0;
94ab4f0a15SSimon J. Gerraty
95ab4f0a15SSimon J. Gerraty void
ve_enforce_validity_set(int i)96ab4f0a15SSimon J. Gerraty ve_enforce_validity_set(int i)
97ab4f0a15SSimon J. Gerraty {
98ab4f0a15SSimon J. Gerraty enforce_validity = i;
99ab4f0a15SSimon J. Gerraty }
100ab4f0a15SSimon J. Gerraty
1015fff9558SSimon J. Gerraty static char ebuf[512];
1025fff9558SSimon J. Gerraty
1035fff9558SSimon J. Gerraty char *
ve_error_get(void)1045fff9558SSimon J. Gerraty ve_error_get(void)
1055fff9558SSimon J. Gerraty {
1065fff9558SSimon J. Gerraty return (ebuf);
1075fff9558SSimon J. Gerraty }
1085fff9558SSimon J. Gerraty
1095fff9558SSimon J. Gerraty int
ve_error_set(const char * fmt,...)1105fff9558SSimon J. Gerraty ve_error_set(const char *fmt, ...)
1115fff9558SSimon J. Gerraty {
1125fff9558SSimon J. Gerraty int rc;
1135fff9558SSimon J. Gerraty va_list ap;
1145fff9558SSimon J. Gerraty
1155fff9558SSimon J. Gerraty va_start(ap, fmt);
1165fff9558SSimon J. Gerraty ebuf[0] = '\0';
1175fff9558SSimon J. Gerraty rc = 0;
1185fff9558SSimon J. Gerraty if (fmt) {
1195fff9558SSimon J. Gerraty #ifdef STAND_H
1205fff9558SSimon J. Gerraty vsprintf(ebuf, fmt, ap); /* no vsnprintf in libstand */
1215fff9558SSimon J. Gerraty ebuf[sizeof(ebuf) - 1] = '\0';
1225fff9558SSimon J. Gerraty rc = strlen(ebuf);
1235fff9558SSimon J. Gerraty #else
1245fff9558SSimon J. Gerraty rc = vsnprintf(ebuf, sizeof(ebuf), fmt, ap);
1255fff9558SSimon J. Gerraty #endif
1265fff9558SSimon J. Gerraty }
1275fff9558SSimon J. Gerraty va_end(ap);
1285fff9558SSimon J. Gerraty return (rc);
1295fff9558SSimon J. Gerraty }
1305fff9558SSimon J. Gerraty
13166655411SSimon J. Gerraty #define isleap(y) (((y) % 4) == 0 && (((y) % 100) != 0 || ((y) % 400) == 0))
13266655411SSimon J. Gerraty
13366655411SSimon J. Gerraty /*
13466655411SSimon J. Gerraty * The *approximate* date.
13566655411SSimon J. Gerraty *
13666655411SSimon J. Gerraty * When certificate verification fails for being
13766655411SSimon J. Gerraty * expired or not yet valid, it helps to indicate
13866655411SSimon J. Gerraty * our current date.
13966655411SSimon J. Gerraty * Since libsa lacks strftime and gmtime,
14066655411SSimon J. Gerraty * this simple implementation suffices.
14166655411SSimon J. Gerraty */
14266655411SSimon J. Gerraty static const char *
gdate(char * buf,size_t bufsz,time_t clock)14366655411SSimon J. Gerraty gdate(char *buf, size_t bufsz, time_t clock)
14466655411SSimon J. Gerraty {
14566655411SSimon J. Gerraty int days[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
14666655411SSimon J. Gerraty int year, y, m, d;
14766655411SSimon J. Gerraty
14866655411SSimon J. Gerraty y = clock / AVG_SECONDS_PER_YEAR;
14966655411SSimon J. Gerraty year = EPOCH_YEAR + y;
15066655411SSimon J. Gerraty for (y = EPOCH_YEAR; y < year; y++) {
15166655411SSimon J. Gerraty clock -= SECONDS_PER_YEAR;
15266655411SSimon J. Gerraty if (isleap(y))
15366655411SSimon J. Gerraty clock -= SECONDS_PER_DAY;
15466655411SSimon J. Gerraty }
15566655411SSimon J. Gerraty d = clock / SECONDS_PER_DAY;
15666655411SSimon J. Gerraty for (m = 0; d > 1 && m < 12; m++) {
15766655411SSimon J. Gerraty if (d > days[m]) {
15866655411SSimon J. Gerraty d -= days[m];
15966655411SSimon J. Gerraty if (m == 1 && d > 0 && isleap(year))
16066655411SSimon J. Gerraty d--;
16166655411SSimon J. Gerraty } else
16266655411SSimon J. Gerraty break;
16366655411SSimon J. Gerraty }
16466655411SSimon J. Gerraty d++;
16566655411SSimon J. Gerraty if (d > days[m]) {
16666655411SSimon J. Gerraty d = 1;
16766655411SSimon J. Gerraty m++;
16866655411SSimon J. Gerraty if (m >= 12) {
16966655411SSimon J. Gerraty year++;
17066655411SSimon J. Gerraty m = 0;
17166655411SSimon J. Gerraty }
17266655411SSimon J. Gerraty }
17366655411SSimon J. Gerraty (void)snprintf(buf, bufsz, "%04d-%02d-%02d", year, m+1, d);
17466655411SSimon J. Gerraty return(buf);
17566655411SSimon J. Gerraty }
17666655411SSimon J. Gerraty
1775fff9558SSimon J. Gerraty /* this is the time we use for verifying certs */
17866655411SSimon J. Gerraty #ifdef UNIT_TEST
17966655411SSimon J. Gerraty extern time_t ve_utc;
18066655411SSimon J. Gerraty time_t ve_utc = 0;
18166655411SSimon J. Gerraty #else
1825fff9558SSimon J. Gerraty static time_t ve_utc = 0;
18366655411SSimon J. Gerraty #endif
1845fff9558SSimon J. Gerraty
1855fff9558SSimon J. Gerraty /**
1865fff9558SSimon J. Gerraty * @brief
1875fff9558SSimon J. Gerraty * set ve_utc used for certificate verification
1885fff9558SSimon J. Gerraty *
1895fff9558SSimon J. Gerraty * @param[in] utc
19053f151f9SSimon J. Gerraty * time - ignored unless greater than current value
19153f151f9SSimon J. Gerraty * and not a leap of 20 years or more.
1925fff9558SSimon J. Gerraty */
1935fff9558SSimon J. Gerraty void
ve_utc_set(time_t utc)1945fff9558SSimon J. Gerraty ve_utc_set(time_t utc)
1955fff9558SSimon J. Gerraty {
19653f151f9SSimon J. Gerraty if (utc > ve_utc &&
19753f151f9SSimon J. Gerraty (ve_utc == 0 || (utc - ve_utc) < VE_UTC_MAX_JUMP)) {
1985fff9558SSimon J. Gerraty DEBUG_PRINTF(2, ("Set ve_utc=%jd\n", (intmax_t)utc));
1995fff9558SSimon J. Gerraty ve_utc = utc;
2005fff9558SSimon J. Gerraty }
2015fff9558SSimon J. Gerraty }
2025fff9558SSimon J. Gerraty
203*dae4eb62SSimon J. Gerraty #ifdef VERIFY_CERTS_STR
2045fff9558SSimon J. Gerraty static void
free_cert_contents(br_x509_certificate * xc)2055fff9558SSimon J. Gerraty free_cert_contents(br_x509_certificate *xc)
2065fff9558SSimon J. Gerraty {
2075fff9558SSimon J. Gerraty xfree(xc->data);
2085fff9558SSimon J. Gerraty }
209*dae4eb62SSimon J. Gerraty #endif
2105fff9558SSimon J. Gerraty
211f9510887SSimon J. Gerraty /*
212f9510887SSimon J. Gerraty * a bit of a dance to get commonName from a certificate
213f9510887SSimon J. Gerraty */
214f9510887SSimon J. Gerraty static char *
x509_cn_get(br_x509_certificate * xc,char * buf,size_t len)215f9510887SSimon J. Gerraty x509_cn_get(br_x509_certificate *xc, char *buf, size_t len)
216f9510887SSimon J. Gerraty {
217f9510887SSimon J. Gerraty br_x509_minimal_context mc;
218f9510887SSimon J. Gerraty br_name_element cn;
219f9510887SSimon J. Gerraty unsigned char cn_oid[4];
220f9510887SSimon J. Gerraty int err;
221f9510887SSimon J. Gerraty
222f9510887SSimon J. Gerraty if (buf == NULL)
223f9510887SSimon J. Gerraty return (buf);
224f9510887SSimon J. Gerraty /*
225f9510887SSimon J. Gerraty * We want the commonName field
226f9510887SSimon J. Gerraty * the OID we want is 2,5,4,3 - but DER encoded
227f9510887SSimon J. Gerraty */
228f9510887SSimon J. Gerraty cn_oid[0] = 3;
229f9510887SSimon J. Gerraty cn_oid[1] = 0x55;
230f9510887SSimon J. Gerraty cn_oid[2] = 4;
231f9510887SSimon J. Gerraty cn_oid[3] = 3;
232f9510887SSimon J. Gerraty cn.oid = cn_oid;
233f9510887SSimon J. Gerraty cn.buf = buf;
234f9510887SSimon J. Gerraty cn.len = len;
235f9510887SSimon J. Gerraty cn.buf[0] = '\0';
236f9510887SSimon J. Gerraty
237f9510887SSimon J. Gerraty br_x509_minimal_init(&mc, &br_sha256_vtable, NULL, 0);
238f9510887SSimon J. Gerraty br_x509_minimal_set_name_elements(&mc, &cn, 1);
239f9510887SSimon J. Gerraty /* the below actually does the work - updates cn.status */
240f9510887SSimon J. Gerraty mc.vtable->start_chain(&mc.vtable, NULL);
241f9510887SSimon J. Gerraty mc.vtable->start_cert(&mc.vtable, xc->data_len);
242f9510887SSimon J. Gerraty mc.vtable->append(&mc.vtable, xc->data, xc->data_len);
243f9510887SSimon J. Gerraty mc.vtable->end_cert(&mc.vtable);
24456f3f2d2SSimon J. Gerraty /* we don't actually care about cert status - just its name */
245f9510887SSimon J. Gerraty err = mc.vtable->end_chain(&mc.vtable);
2469c3478cbSSimon J. Gerraty (void)err; /* keep compiler quiet */
247f9510887SSimon J. Gerraty
2489c3478cbSSimon J. Gerraty if (cn.status <= 0)
249f9510887SSimon J. Gerraty buf = NULL;
250f9510887SSimon J. Gerraty return (buf);
251f9510887SSimon J. Gerraty }
252f9510887SSimon J. Gerraty
25313ea0450SMarcin Wojtas /* ASN parsing related defines */
25413ea0450SMarcin Wojtas #define ASN1_PRIMITIVE_TAG 0x1F
25513ea0450SMarcin Wojtas #define ASN1_INF_LENGTH 0x80
25613ea0450SMarcin Wojtas #define ASN1_LENGTH_MASK 0x7F
25713ea0450SMarcin Wojtas
25813ea0450SMarcin Wojtas /*
25913ea0450SMarcin Wojtas * Get TBS part of certificate.
26013ea0450SMarcin Wojtas * Since BearSSL doesn't provide any API to do this,
26113ea0450SMarcin Wojtas * it has to be implemented here.
2625fff9558SSimon J. Gerraty */
26313ea0450SMarcin Wojtas static void*
X509_to_tbs(unsigned char * cert,size_t * output_size)26413ea0450SMarcin Wojtas X509_to_tbs(unsigned char* cert, size_t* output_size)
26513ea0450SMarcin Wojtas {
26613ea0450SMarcin Wojtas unsigned char *result;
26713ea0450SMarcin Wojtas size_t tbs_size;
26813ea0450SMarcin Wojtas int size, i;
26913ea0450SMarcin Wojtas
27013ea0450SMarcin Wojtas if (cert == NULL)
27113ea0450SMarcin Wojtas return (NULL);
27213ea0450SMarcin Wojtas
27313ea0450SMarcin Wojtas /* Strip two sequences to get to the TBS section */
27413ea0450SMarcin Wojtas for (i = 0; i < 2; i++) {
27513ea0450SMarcin Wojtas /*
27613ea0450SMarcin Wojtas * XXX: We don't need to support extended tags since
27713ea0450SMarcin Wojtas * they should not be present in certificates.
27813ea0450SMarcin Wojtas */
27913ea0450SMarcin Wojtas if ((*cert & ASN1_PRIMITIVE_TAG) == ASN1_PRIMITIVE_TAG)
28013ea0450SMarcin Wojtas return (NULL);
28113ea0450SMarcin Wojtas
28213ea0450SMarcin Wojtas cert++;
28313ea0450SMarcin Wojtas
28413ea0450SMarcin Wojtas if (*cert == ASN1_INF_LENGTH)
28513ea0450SMarcin Wojtas return (NULL);
28613ea0450SMarcin Wojtas
28713ea0450SMarcin Wojtas size = *cert & ASN1_LENGTH_MASK;
28813ea0450SMarcin Wojtas tbs_size = 0;
28913ea0450SMarcin Wojtas
29013ea0450SMarcin Wojtas /* Size can either be stored on a single or multiple bytes */
29113ea0450SMarcin Wojtas if (*cert & (ASN1_LENGTH_MASK + 1)) {
29213ea0450SMarcin Wojtas cert++;
29313ea0450SMarcin Wojtas while (*cert == 0 && size > 0) {
29413ea0450SMarcin Wojtas cert++;
29513ea0450SMarcin Wojtas size--;
29613ea0450SMarcin Wojtas }
29713ea0450SMarcin Wojtas while (size-- > 0) {
29813ea0450SMarcin Wojtas tbs_size <<= 8;
29913ea0450SMarcin Wojtas tbs_size |= *(cert++);
30013ea0450SMarcin Wojtas }
30113ea0450SMarcin Wojtas }
30213ea0450SMarcin Wojtas if (i == 0)
30313ea0450SMarcin Wojtas result = cert;
30413ea0450SMarcin Wojtas }
30513ea0450SMarcin Wojtas tbs_size += (cert - result);
30613ea0450SMarcin Wojtas
30713ea0450SMarcin Wojtas if (output_size != NULL)
30813ea0450SMarcin Wojtas *output_size = tbs_size;
30913ea0450SMarcin Wojtas
31013ea0450SMarcin Wojtas return (result);
31113ea0450SMarcin Wojtas }
31213ea0450SMarcin Wojtas
31313ea0450SMarcin Wojtas void
ve_forbidden_digest_add(hash_data * digest,size_t num)31413ea0450SMarcin Wojtas ve_forbidden_digest_add(hash_data *digest, size_t num)
31513ea0450SMarcin Wojtas {
31613ea0450SMarcin Wojtas while (num--)
31713ea0450SMarcin Wojtas VEC_ADD(forbidden_digests, digest[num]);
31813ea0450SMarcin Wojtas }
31913ea0450SMarcin Wojtas
32013ea0450SMarcin Wojtas static size_t
ve_anchors_add(br_x509_certificate * xcs,size_t num,anchor_list * anchors,const char * anchors_name)321f9510887SSimon J. Gerraty ve_anchors_add(br_x509_certificate *xcs, size_t num, anchor_list *anchors,
32218e2fbc0SSimon J. Gerraty const char *anchors_name)
3235fff9558SSimon J. Gerraty {
3245fff9558SSimon J. Gerraty br_x509_trust_anchor ta;
3255fff9558SSimon J. Gerraty size_t u;
3265fff9558SSimon J. Gerraty
3275fff9558SSimon J. Gerraty for (u = 0; u < num; u++) {
3285fff9558SSimon J. Gerraty if (certificate_to_trust_anchor_inner(&ta, &xcs[u]) < 0) {
3295fff9558SSimon J. Gerraty break;
3305fff9558SSimon J. Gerraty }
33113ea0450SMarcin Wojtas VEC_ADD(*anchors, ta);
332f9510887SSimon J. Gerraty if (anchor_verbose && anchors_name) {
333f9510887SSimon J. Gerraty char buf[64];
334f9510887SSimon J. Gerraty char *cp;
335f9510887SSimon J. Gerraty
336f9510887SSimon J. Gerraty cp = x509_cn_get(&xcs[u], buf, sizeof(buf));
337f9510887SSimon J. Gerraty if (cp) {
338f9510887SSimon J. Gerraty printf("x509_anchor(%s) %s\n", cp, anchors_name);
339f9510887SSimon J. Gerraty }
340f9510887SSimon J. Gerraty }
3415fff9558SSimon J. Gerraty }
3425fff9558SSimon J. Gerraty return (u);
3435fff9558SSimon J. Gerraty }
3445fff9558SSimon J. Gerraty
3455fff9558SSimon J. Gerraty /**
3465fff9558SSimon J. Gerraty * @brief
34713ea0450SMarcin Wojtas * add certs to our trust store
34813ea0450SMarcin Wojtas */
34913ea0450SMarcin Wojtas size_t
ve_trust_anchors_add(br_x509_certificate * xcs,size_t num)35013ea0450SMarcin Wojtas ve_trust_anchors_add(br_x509_certificate *xcs, size_t num)
35113ea0450SMarcin Wojtas {
352f9510887SSimon J. Gerraty return (ve_anchors_add(xcs, num, &trust_anchors, "trusted"));
35313ea0450SMarcin Wojtas }
35413ea0450SMarcin Wojtas
35513ea0450SMarcin Wojtas size_t
ve_forbidden_anchors_add(br_x509_certificate * xcs,size_t num)35613ea0450SMarcin Wojtas ve_forbidden_anchors_add(br_x509_certificate *xcs, size_t num)
35713ea0450SMarcin Wojtas {
358f9510887SSimon J. Gerraty return (ve_anchors_add(xcs, num, &forbidden_anchors, "forbidden"));
359f9510887SSimon J. Gerraty }
360f9510887SSimon J. Gerraty
361f9510887SSimon J. Gerraty
362f9510887SSimon J. Gerraty /**
363f9510887SSimon J. Gerraty * @brief add trust anchors in buf
364f9510887SSimon J. Gerraty *
365f9510887SSimon J. Gerraty * Assume buf contains x509 certificates, but if not and
366f9510887SSimon J. Gerraty * we support OpenPGP try adding as that.
367f9510887SSimon J. Gerraty *
368f9510887SSimon J. Gerraty * @return number of anchors added
369f9510887SSimon J. Gerraty */
370f9510887SSimon J. Gerraty size_t
ve_trust_anchors_add_buf(unsigned char * buf,size_t len)371f9510887SSimon J. Gerraty ve_trust_anchors_add_buf(unsigned char *buf, size_t len)
372f9510887SSimon J. Gerraty {
373f9510887SSimon J. Gerraty br_x509_certificate *xcs;
374f9510887SSimon J. Gerraty size_t num;
375f9510887SSimon J. Gerraty
376f9510887SSimon J. Gerraty num = 0;
377*dae4eb62SSimon J. Gerraty if (len > 0) {
378f9510887SSimon J. Gerraty xcs = parse_certificates(buf, len, &num);
379f9510887SSimon J. Gerraty if (xcs != NULL) {
380f9510887SSimon J. Gerraty num = ve_trust_anchors_add(xcs, num);
381f9510887SSimon J. Gerraty #ifdef VE_OPENPGP_SUPPORT
382f9510887SSimon J. Gerraty } else {
383f9510887SSimon J. Gerraty num = openpgp_trust_add_buf(buf, len);
384f9510887SSimon J. Gerraty #endif
385f9510887SSimon J. Gerraty }
386*dae4eb62SSimon J. Gerraty }
387f9510887SSimon J. Gerraty return (num);
388f9510887SSimon J. Gerraty }
389f9510887SSimon J. Gerraty
390f9510887SSimon J. Gerraty /**
391f9510887SSimon J. Gerraty * @brief revoke trust anchors in buf
392f9510887SSimon J. Gerraty *
393f9510887SSimon J. Gerraty * Assume buf contains x509 certificates, but if not and
394f9510887SSimon J. Gerraty * we support OpenPGP try revoking keyId
395f9510887SSimon J. Gerraty *
396f9510887SSimon J. Gerraty * @return number of anchors revoked
397f9510887SSimon J. Gerraty */
398f9510887SSimon J. Gerraty size_t
ve_trust_anchors_revoke(unsigned char * buf,size_t len)399f9510887SSimon J. Gerraty ve_trust_anchors_revoke(unsigned char *buf, size_t len)
400f9510887SSimon J. Gerraty {
401f9510887SSimon J. Gerraty br_x509_certificate *xcs;
402f9510887SSimon J. Gerraty size_t num;
403f9510887SSimon J. Gerraty
404f9510887SSimon J. Gerraty num = 0;
405*dae4eb62SSimon J. Gerraty if (len > 0) {
406f9510887SSimon J. Gerraty xcs = parse_certificates(buf, len, &num);
407f9510887SSimon J. Gerraty if (xcs != NULL) {
408f9510887SSimon J. Gerraty num = ve_forbidden_anchors_add(xcs, num);
409f9510887SSimon J. Gerraty #ifdef VE_OPENPGP_SUPPORT
410f9510887SSimon J. Gerraty } else {
411f9510887SSimon J. Gerraty if (buf[len - 1] == '\n')
412f9510887SSimon J. Gerraty buf[len - 1] = '\0';
413f9510887SSimon J. Gerraty num = openpgp_trust_revoke((char *)buf);
414f9510887SSimon J. Gerraty #endif
415f9510887SSimon J. Gerraty }
416*dae4eb62SSimon J. Gerraty }
417f9510887SSimon J. Gerraty return (num);
41813ea0450SMarcin Wojtas }
41913ea0450SMarcin Wojtas
42013ea0450SMarcin Wojtas /**
42113ea0450SMarcin Wojtas * @brief
4225fff9558SSimon J. Gerraty * initialize our trust_anchors from ta_PEM
4235fff9558SSimon J. Gerraty */
4245fff9558SSimon J. Gerraty int
ve_trust_init(void)4255fff9558SSimon J. Gerraty ve_trust_init(void)
4265fff9558SSimon J. Gerraty {
4275fff9558SSimon J. Gerraty static int once = -1;
4285fff9558SSimon J. Gerraty
4295fff9558SSimon J. Gerraty if (once >= 0)
4305fff9558SSimon J. Gerraty return (once);
4313ae2a848SSimon J. Gerraty once = 0; /* to be sure */
4325fff9558SSimon J. Gerraty #ifdef BUILD_UTC
43353f151f9SSimon J. Gerraty ve_utc_set(BUILD_UTC); /* ensure sanity */
4345fff9558SSimon J. Gerraty #endif
43553f151f9SSimon J. Gerraty ve_utc_set(time(NULL));
4365fff9558SSimon J. Gerraty ve_error_set(NULL); /* make sure it is empty */
4375fff9558SSimon J. Gerraty #ifdef VE_PCR_SUPPORT
4385fff9558SSimon J. Gerraty ve_pcr_init();
4395fff9558SSimon J. Gerraty #endif
4405fff9558SSimon J. Gerraty
4415fff9558SSimon J. Gerraty #ifdef TRUST_ANCHOR_STR
442e6ef5042SWojciech Macek if (TRUST_ANCHOR_STR != NULL && strlen(TRUST_ANCHOR_STR) != 0ul)
443e6ef5042SWojciech Macek ve_trust_anchors_add_buf(__DECONST(unsigned char *,
444e6ef5042SWojciech Macek TRUST_ANCHOR_STR), sizeof(TRUST_ANCHOR_STR));
4455fff9558SSimon J. Gerraty #endif
44613ea0450SMarcin Wojtas once = (int) VEC_LEN(trust_anchors);
4479bee6a60SSimon J. Gerraty #ifdef VE_OPENPGP_SUPPORT
4489bee6a60SSimon J. Gerraty once += openpgp_trust_init();
4499bee6a60SSimon J. Gerraty #endif
45013ea0450SMarcin Wojtas return (once);
4515fff9558SSimon J. Gerraty }
4525fff9558SSimon J. Gerraty
45366655411SSimon J. Gerraty #ifdef HAVE_BR_X509_TIME_CHECK
45466655411SSimon J. Gerraty static int
verify_time_cb(void * tctx __unused,uint32_t not_before_days,uint32_t not_before_seconds,uint32_t not_after_days,uint32_t not_after_seconds)455cc9e6590SSimon J. Gerraty verify_time_cb(void *tctx __unused,
45666655411SSimon J. Gerraty uint32_t not_before_days, uint32_t not_before_seconds,
45766655411SSimon J. Gerraty uint32_t not_after_days, uint32_t not_after_seconds)
45866655411SSimon J. Gerraty {
45966655411SSimon J. Gerraty time_t not_before;
46066655411SSimon J. Gerraty time_t not_after;
46166655411SSimon J. Gerraty int rc;
46266655411SSimon J. Gerraty #ifdef UNIT_TEST
46366655411SSimon J. Gerraty char date[12], nb_date[12], na_date[12];
46466655411SSimon J. Gerraty #endif
46566655411SSimon J. Gerraty
466ab4f0a15SSimon J. Gerraty if (enforce_validity) {
46766655411SSimon J. Gerraty not_before = ((not_before_days - X509_DAYS_TO_UTC0) * SECONDS_PER_DAY) + not_before_seconds;
46866655411SSimon J. Gerraty not_after = ((not_after_days - X509_DAYS_TO_UTC0) * SECONDS_PER_DAY) + not_after_seconds;
46966655411SSimon J. Gerraty if (ve_utc < not_before)
47066655411SSimon J. Gerraty rc = -1;
47166655411SSimon J. Gerraty else if (ve_utc > not_after)
47266655411SSimon J. Gerraty rc = 1;
47366655411SSimon J. Gerraty else
47466655411SSimon J. Gerraty rc = 0;
47566655411SSimon J. Gerraty #ifdef UNIT_TEST
47666655411SSimon J. Gerraty printf("notBefore %s notAfter %s date %s rc %d\n",
47766655411SSimon J. Gerraty gdate(nb_date, sizeof(nb_date), not_before),
47866655411SSimon J. Gerraty gdate(na_date, sizeof(na_date), not_after),
47966655411SSimon J. Gerraty gdate(date, sizeof(date), ve_utc), rc);
48066655411SSimon J. Gerraty #endif
481ab4f0a15SSimon J. Gerraty } else
48266655411SSimon J. Gerraty rc = 0; /* don't fail */
48366655411SSimon J. Gerraty return rc;
48466655411SSimon J. Gerraty }
48566655411SSimon J. Gerraty #endif
48666655411SSimon J. Gerraty
4875fff9558SSimon J. Gerraty /**
4885fff9558SSimon J. Gerraty * if we can verify the certificate chain in "certs",
4895fff9558SSimon J. Gerraty * return the public key and if "xcp" is !NULL the associated
4905fff9558SSimon J. Gerraty * certificate
4915fff9558SSimon J. Gerraty */
4925fff9558SSimon J. Gerraty 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)4935fff9558SSimon J. Gerraty verify_signer_xcs(br_x509_certificate *xcs,
4945fff9558SSimon J. Gerraty size_t num,
49513ea0450SMarcin Wojtas br_name_element *elts, size_t num_elts,
49613ea0450SMarcin Wojtas anchor_list *anchors)
4975fff9558SSimon J. Gerraty {
4985fff9558SSimon J. Gerraty br_x509_minimal_context mc;
4995fff9558SSimon J. Gerraty br_x509_certificate *xc;
5005fff9558SSimon J. Gerraty size_t u;
5015fff9558SSimon J. Gerraty cert_list chain = VEC_INIT;
5025fff9558SSimon J. Gerraty const br_x509_pkey *tpk;
5035fff9558SSimon J. Gerraty br_x509_pkey *pk;
5045fff9558SSimon J. Gerraty unsigned int usages;
5055fff9558SSimon J. Gerraty int err;
5065fff9558SSimon J. Gerraty
5075fff9558SSimon J. Gerraty DEBUG_PRINTF(5, ("verify_signer: %zu certs in chain\n", num));
5085fff9558SSimon J. Gerraty VEC_ADDMANY(chain, xcs, num);
5095fff9558SSimon J. Gerraty if (VEC_LEN(chain) == 0) {
5105fff9558SSimon J. Gerraty ve_error_set("ERROR: no/invalid certificate chain\n");
5115fff9558SSimon J. Gerraty return (NULL);
5125fff9558SSimon J. Gerraty }
5135fff9558SSimon J. Gerraty
5145fff9558SSimon J. Gerraty DEBUG_PRINTF(5, ("verify_signer: %zu trust anchors\n",
51513ea0450SMarcin Wojtas VEC_LEN(*anchors)));
5165fff9558SSimon J. Gerraty
5175fff9558SSimon J. Gerraty br_x509_minimal_init(&mc, &br_sha256_vtable,
51813ea0450SMarcin Wojtas &VEC_ELT(*anchors, 0),
51913ea0450SMarcin Wojtas VEC_LEN(*anchors));
5205fff9558SSimon J. Gerraty #ifdef VE_ECDSA_SUPPORT
5215fff9558SSimon J. Gerraty br_x509_minimal_set_ecdsa(&mc,
5225fff9558SSimon J. Gerraty &br_ec_prime_i31, &br_ecdsa_i31_vrfy_asn1);
5235fff9558SSimon J. Gerraty #endif
5245fff9558SSimon J. Gerraty #ifdef VE_RSA_SUPPORT
5255fff9558SSimon J. Gerraty br_x509_minimal_set_rsa(&mc, &br_rsa_i31_pkcs1_vrfy);
5265fff9558SSimon J. Gerraty #endif
5275fff9558SSimon J. Gerraty #if defined(UNIT_TEST) && defined(VE_DEPRECATED_RSA_SHA1_SUPPORT)
528cb25444cSElyes HAOUAS /* This is deprecated! do not enable unless you absolutely have to */
5295fff9558SSimon J. Gerraty br_x509_minimal_set_hash(&mc, br_sha1_ID, &br_sha1_vtable);
5305fff9558SSimon J. Gerraty #endif
5315fff9558SSimon J. Gerraty br_x509_minimal_set_hash(&mc, br_sha256_ID, &br_sha256_vtable);
5325fff9558SSimon J. Gerraty #ifdef VE_SHA384_SUPPORT
5335fff9558SSimon J. Gerraty br_x509_minimal_set_hash(&mc, br_sha384_ID, &br_sha384_vtable);
5345fff9558SSimon J. Gerraty #endif
5355fff9558SSimon J. Gerraty #ifdef VE_SHA512_SUPPORT
5365fff9558SSimon J. Gerraty br_x509_minimal_set_hash(&mc, br_sha512_ID, &br_sha512_vtable);
5375fff9558SSimon J. Gerraty #endif
5385fff9558SSimon J. Gerraty br_x509_minimal_set_name_elements(&mc, elts, num_elts);
5395fff9558SSimon J. Gerraty
54066655411SSimon J. Gerraty #ifdef HAVE_BR_X509_TIME_CHECK
54166655411SSimon J. Gerraty br_x509_minimal_set_time_callback(&mc, NULL, verify_time_cb);
54266655411SSimon J. Gerraty #else
54366655411SSimon J. Gerraty #if defined(_STANDALONE) || defined(UNIT_TEST)
5445fff9558SSimon J. Gerraty /*
5455fff9558SSimon J. Gerraty * Clock is probably bogus so we use ve_utc.
5465fff9558SSimon J. Gerraty */
5475fff9558SSimon J. Gerraty mc.days = (ve_utc / SECONDS_PER_DAY) + X509_DAYS_TO_UTC0;
5485fff9558SSimon J. Gerraty mc.seconds = (ve_utc % SECONDS_PER_DAY);
5495fff9558SSimon J. Gerraty #endif
55066655411SSimon J. Gerraty #endif
5515fff9558SSimon J. Gerraty mc.vtable->start_chain(&mc.vtable, NULL);
5525fff9558SSimon J. Gerraty for (u = 0; u < VEC_LEN(chain); u ++) {
5535fff9558SSimon J. Gerraty xc = &VEC_ELT(chain, u);
5545fff9558SSimon J. Gerraty mc.vtable->start_cert(&mc.vtable, xc->data_len);
5555fff9558SSimon J. Gerraty mc.vtable->append(&mc.vtable, xc->data, xc->data_len);
5565fff9558SSimon J. Gerraty mc.vtable->end_cert(&mc.vtable);
5575fff9558SSimon J. Gerraty switch (mc.err) {
5585fff9558SSimon J. Gerraty case 0:
5595fff9558SSimon J. Gerraty case BR_ERR_X509_OK:
5605fff9558SSimon J. Gerraty case BR_ERR_X509_EXPIRED:
5615fff9558SSimon J. Gerraty break;
5625fff9558SSimon J. Gerraty default:
5635fff9558SSimon J. Gerraty printf("u=%zu mc.err=%d\n", u, mc.err);
5645fff9558SSimon J. Gerraty break;
5655fff9558SSimon J. Gerraty }
5665fff9558SSimon J. Gerraty }
5675fff9558SSimon J. Gerraty err = mc.vtable->end_chain(&mc.vtable);
5685fff9558SSimon J. Gerraty pk = NULL;
5695fff9558SSimon J. Gerraty if (err) {
57066655411SSimon J. Gerraty char date[12];
57166655411SSimon J. Gerraty
57266655411SSimon J. Gerraty switch (err) {
57366655411SSimon J. Gerraty case 54:
57466655411SSimon J. Gerraty ve_error_set("Validation failed, certificate not valid as of %s",
57566655411SSimon J. Gerraty gdate(date, sizeof(date), ve_utc));
57666655411SSimon J. Gerraty break;
5774b9d6057SStéphane Rochoy default: {
5784b9d6057SStéphane Rochoy const char *err_desc = NULL;
5794b9d6057SStéphane Rochoy const char *err_name = find_error_name(err, &err_desc);
5804b9d6057SStéphane Rochoy
5814b9d6057SStéphane Rochoy if (err_name == NULL)
5824b9d6057SStéphane Rochoy ve_error_set("Validation failed, err = %d",
5834b9d6057SStéphane Rochoy err);
5844b9d6057SStéphane Rochoy else
5854b9d6057SStéphane Rochoy ve_error_set("Validation failed, %s (%s)",
5864b9d6057SStéphane Rochoy err_desc, err_name);
5874b9d6057SStéphane Rochoy break; }
58866655411SSimon J. Gerraty }
5895fff9558SSimon J. Gerraty } else {
5905fff9558SSimon J. Gerraty tpk = mc.vtable->get_pkey(&mc.vtable, &usages);
5915fff9558SSimon J. Gerraty if (tpk != NULL) {
5925fff9558SSimon J. Gerraty pk = xpkeydup(tpk);
5935fff9558SSimon J. Gerraty }
5945fff9558SSimon J. Gerraty }
59513ea0450SMarcin Wojtas VEC_CLEAR(chain);
5965fff9558SSimon J. Gerraty return (pk);
5975fff9558SSimon J. Gerraty }
5985fff9558SSimon J. Gerraty
59913ea0450SMarcin Wojtas /*
60013ea0450SMarcin Wojtas * Check if digest of one of the certificates from verified chain
60113ea0450SMarcin Wojtas * is present in the forbidden database.
60213ea0450SMarcin Wojtas * Since UEFI allows to store three types of digests
60313ea0450SMarcin Wojtas * all of them have to be checked separately.
60413ea0450SMarcin Wojtas */
60513ea0450SMarcin Wojtas static int
check_forbidden_digests(br_x509_certificate * xcs,size_t num)60613ea0450SMarcin Wojtas check_forbidden_digests(br_x509_certificate *xcs, size_t num)
60713ea0450SMarcin Wojtas {
60813ea0450SMarcin Wojtas unsigned char sha256_digest[br_sha256_SIZE];
60913ea0450SMarcin Wojtas unsigned char sha384_digest[br_sha384_SIZE];
61013ea0450SMarcin Wojtas unsigned char sha512_digest[br_sha512_SIZE];
61113ea0450SMarcin Wojtas void *tbs;
61213ea0450SMarcin Wojtas hash_data *digest;
61313ea0450SMarcin Wojtas br_hash_compat_context ctx;
61413ea0450SMarcin Wojtas const br_hash_class *md;
61513ea0450SMarcin Wojtas size_t tbs_len, i;
61613ea0450SMarcin Wojtas int have_sha256, have_sha384, have_sha512;
61713ea0450SMarcin Wojtas
61813ea0450SMarcin Wojtas if (VEC_LEN(forbidden_digests) == 0)
61913ea0450SMarcin Wojtas return (0);
62013ea0450SMarcin Wojtas
62113ea0450SMarcin Wojtas /*
62213ea0450SMarcin Wojtas * Iterate through certificates, extract their To-Be-Signed section,
62313ea0450SMarcin Wojtas * and compare its digest against the ones in the forbidden database.
62413ea0450SMarcin Wojtas */
62513ea0450SMarcin Wojtas while (num--) {
62613ea0450SMarcin Wojtas tbs = X509_to_tbs(xcs[num].data, &tbs_len);
62713ea0450SMarcin Wojtas if (tbs == NULL) {
62813ea0450SMarcin Wojtas printf("Failed to obtain TBS part of certificate\n");
62913ea0450SMarcin Wojtas return (1);
63013ea0450SMarcin Wojtas }
63113ea0450SMarcin Wojtas have_sha256 = have_sha384 = have_sha512 = 0;
63213ea0450SMarcin Wojtas
63313ea0450SMarcin Wojtas for (i = 0; i < VEC_LEN(forbidden_digests); i++) {
63413ea0450SMarcin Wojtas digest = &VEC_ELT(forbidden_digests, i);
63513ea0450SMarcin Wojtas switch (digest->hash_size) {
63613ea0450SMarcin Wojtas case br_sha256_SIZE:
63713ea0450SMarcin Wojtas if (!have_sha256) {
63813ea0450SMarcin Wojtas have_sha256 = 1;
63913ea0450SMarcin Wojtas md = &br_sha256_vtable;
64013ea0450SMarcin Wojtas md->init(&ctx.vtable);
64113ea0450SMarcin Wojtas md->update(&ctx.vtable, tbs, tbs_len);
64213ea0450SMarcin Wojtas md->out(&ctx.vtable, sha256_digest);
64313ea0450SMarcin Wojtas }
64413ea0450SMarcin Wojtas if (!memcmp(sha256_digest,
64513ea0450SMarcin Wojtas digest->data,
64613ea0450SMarcin Wojtas br_sha256_SIZE))
64713ea0450SMarcin Wojtas return (1);
64813ea0450SMarcin Wojtas
64913ea0450SMarcin Wojtas break;
65013ea0450SMarcin Wojtas case br_sha384_SIZE:
65113ea0450SMarcin Wojtas if (!have_sha384) {
65213ea0450SMarcin Wojtas have_sha384 = 1;
65313ea0450SMarcin Wojtas md = &br_sha384_vtable;
65413ea0450SMarcin Wojtas md->init(&ctx.vtable);
65513ea0450SMarcin Wojtas md->update(&ctx.vtable, tbs, tbs_len);
65613ea0450SMarcin Wojtas md->out(&ctx.vtable, sha384_digest);
65713ea0450SMarcin Wojtas }
65813ea0450SMarcin Wojtas if (!memcmp(sha384_digest,
65913ea0450SMarcin Wojtas digest->data,
66013ea0450SMarcin Wojtas br_sha384_SIZE))
66113ea0450SMarcin Wojtas return (1);
66213ea0450SMarcin Wojtas
66313ea0450SMarcin Wojtas break;
66413ea0450SMarcin Wojtas case br_sha512_SIZE:
66513ea0450SMarcin Wojtas if (!have_sha512) {
66613ea0450SMarcin Wojtas have_sha512 = 1;
66713ea0450SMarcin Wojtas md = &br_sha512_vtable;
66813ea0450SMarcin Wojtas md->init(&ctx.vtable);
66913ea0450SMarcin Wojtas md->update(&ctx.vtable, tbs, tbs_len);
67013ea0450SMarcin Wojtas md->out(&ctx.vtable, sha512_digest);
67113ea0450SMarcin Wojtas }
67213ea0450SMarcin Wojtas if (!memcmp(sha512_digest,
67313ea0450SMarcin Wojtas digest->data,
67413ea0450SMarcin Wojtas br_sha512_SIZE))
67513ea0450SMarcin Wojtas return (1);
67613ea0450SMarcin Wojtas
67713ea0450SMarcin Wojtas break;
67813ea0450SMarcin Wojtas }
67913ea0450SMarcin Wojtas }
68013ea0450SMarcin Wojtas }
68113ea0450SMarcin Wojtas
68213ea0450SMarcin Wojtas return (0);
68313ea0450SMarcin Wojtas }
68413ea0450SMarcin Wojtas
6855fff9558SSimon J. Gerraty static br_x509_pkey *
verify_signer(const char * certs,br_name_element * elts,size_t num_elts)6865fff9558SSimon J. Gerraty verify_signer(const char *certs,
6875fff9558SSimon J. Gerraty br_name_element *elts, size_t num_elts)
6885fff9558SSimon J. Gerraty {
6895fff9558SSimon J. Gerraty br_x509_certificate *xcs;
6905fff9558SSimon J. Gerraty br_x509_pkey *pk;
6915fff9558SSimon J. Gerraty size_t num;
6925fff9558SSimon J. Gerraty
69313ea0450SMarcin Wojtas pk = NULL;
69413ea0450SMarcin Wojtas
6955fff9558SSimon J. Gerraty ve_trust_init();
6965fff9558SSimon J. Gerraty xcs = read_certificates(certs, &num);
6975fff9558SSimon J. Gerraty if (xcs == NULL) {
6985fff9558SSimon J. Gerraty ve_error_set("cannot read certificates\n");
6995fff9558SSimon J. Gerraty return (NULL);
7005fff9558SSimon J. Gerraty }
70113ea0450SMarcin Wojtas
70213ea0450SMarcin Wojtas /*
70313ea0450SMarcin Wojtas * Check if either
70413ea0450SMarcin Wojtas * 1. There is a direct match between cert from forbidden_anchors
70513ea0450SMarcin Wojtas * and a cert from chain.
70613ea0450SMarcin Wojtas * 2. CA that signed the chain is found in forbidden_anchors.
70713ea0450SMarcin Wojtas */
70813ea0450SMarcin Wojtas if (VEC_LEN(forbidden_anchors) > 0)
70913ea0450SMarcin Wojtas pk = verify_signer_xcs(xcs, num, elts, num_elts, &forbidden_anchors);
71013ea0450SMarcin Wojtas if (pk != NULL) {
71113ea0450SMarcin Wojtas ve_error_set("Certificate is on forbidden list\n");
71213ea0450SMarcin Wojtas xfreepkey(pk);
71313ea0450SMarcin Wojtas pk = NULL;
71413ea0450SMarcin Wojtas goto out;
71513ea0450SMarcin Wojtas }
71613ea0450SMarcin Wojtas
71713ea0450SMarcin Wojtas pk = verify_signer_xcs(xcs, num, elts, num_elts, &trust_anchors);
71813ea0450SMarcin Wojtas if (pk == NULL)
71913ea0450SMarcin Wojtas goto out;
72013ea0450SMarcin Wojtas
72113ea0450SMarcin Wojtas /*
72213ea0450SMarcin Wojtas * Check if hash of tbs part of any certificate in chain
72313ea0450SMarcin Wojtas * is on the forbidden list.
72413ea0450SMarcin Wojtas */
72513ea0450SMarcin Wojtas if (check_forbidden_digests(xcs, num)) {
72613ea0450SMarcin Wojtas ve_error_set("Certificate hash is on forbidden list\n");
72713ea0450SMarcin Wojtas xfreepkey(pk);
72813ea0450SMarcin Wojtas pk = NULL;
72913ea0450SMarcin Wojtas }
73013ea0450SMarcin Wojtas out:
73113ea0450SMarcin Wojtas free_certificates(xcs, num);
7325fff9558SSimon J. Gerraty return (pk);
7335fff9558SSimon J. Gerraty }
7345fff9558SSimon J. Gerraty
7355fff9558SSimon J. Gerraty /**
7365fff9558SSimon J. Gerraty * we need a hex digest including trailing newline below
7375fff9558SSimon J. Gerraty */
7385fff9558SSimon J. Gerraty char *
hexdigest(char * buf,size_t bufsz,unsigned char * foo,size_t foo_len)7395fff9558SSimon J. Gerraty hexdigest(char *buf, size_t bufsz, unsigned char *foo, size_t foo_len)
7405fff9558SSimon J. Gerraty {
7415fff9558SSimon J. Gerraty char const hex2ascii[] = "0123456789abcdef";
7425fff9558SSimon J. Gerraty size_t i;
7435fff9558SSimon J. Gerraty
7445fff9558SSimon J. Gerraty /* every binary byte is 2 chars in hex + newline + null */
7455fff9558SSimon J. Gerraty if (bufsz < (2 * foo_len) + 2)
7465fff9558SSimon J. Gerraty return (NULL);
7475fff9558SSimon J. Gerraty
7485fff9558SSimon J. Gerraty for (i = 0; i < foo_len; i++) {
7495fff9558SSimon J. Gerraty buf[i * 2] = hex2ascii[foo[i] >> 4];
7505fff9558SSimon J. Gerraty buf[i * 2 + 1] = hex2ascii[foo[i] & 0x0f];
7515fff9558SSimon J. Gerraty }
7525fff9558SSimon J. Gerraty
7535fff9558SSimon J. Gerraty buf[i * 2] = 0x0A; /* we also want a newline */
7545fff9558SSimon J. Gerraty buf[i * 2 + 1] = '\0';
7555fff9558SSimon J. Gerraty
7565fff9558SSimon J. Gerraty return (buf);
7575fff9558SSimon J. Gerraty }
7585fff9558SSimon J. Gerraty
7595fff9558SSimon J. Gerraty /**
7605fff9558SSimon J. Gerraty * @brief
7615fff9558SSimon J. Gerraty * verify file against sigfile using pk
7625fff9558SSimon J. Gerraty *
7635fff9558SSimon J. Gerraty * When we generated the signature in sigfile,
7645fff9558SSimon J. Gerraty * we hashed (sha256) file, and sent that to signing server
7655fff9558SSimon J. Gerraty * which hashed (sha256) that hash.
7665fff9558SSimon J. Gerraty *
7675fff9558SSimon J. Gerraty * To verify we need to replicate that result.
7685fff9558SSimon J. Gerraty *
7695fff9558SSimon J. Gerraty * @param[in] pk
7705fff9558SSimon J. Gerraty * br_x509_pkey
7715fff9558SSimon J. Gerraty *
7725fff9558SSimon J. Gerraty * @paramp[in] file
7735fff9558SSimon J. Gerraty * file to be verified
7745fff9558SSimon J. Gerraty *
7755fff9558SSimon J. Gerraty * @param[in] sigfile
7765fff9558SSimon J. Gerraty * signature (PEM encoded)
7775fff9558SSimon J. Gerraty *
7785fff9558SSimon J. Gerraty * @return NULL on error, otherwise content of file.
7795fff9558SSimon J. Gerraty */
7805fff9558SSimon J. Gerraty #ifdef VE_ECDSA_SUPPORT
7815fff9558SSimon J. Gerraty static unsigned char *
verify_ec(br_x509_pkey * pk,const char * file,const char * sigfile)7825fff9558SSimon J. Gerraty verify_ec(br_x509_pkey *pk, const char *file, const char *sigfile)
7835fff9558SSimon J. Gerraty {
7840e47020fSSimon J. Gerraty #ifdef VE_ECDSA_HASH_AGAIN
7850e47020fSSimon J. Gerraty char *hex, hexbuf[br_sha512_SIZE * 2 + 2];
7860e47020fSSimon J. Gerraty #endif
7875fff9558SSimon J. Gerraty unsigned char rhbuf[br_sha512_SIZE];
7885fff9558SSimon J. Gerraty br_sha256_context ctx;
7895fff9558SSimon J. Gerraty unsigned char *fcp, *scp;
7905fff9558SSimon J. Gerraty size_t flen, slen, plen;
7915fff9558SSimon J. Gerraty pem_object *po;
7925fff9558SSimon J. Gerraty const br_ec_impl *ec;
7935fff9558SSimon J. Gerraty br_ecdsa_vrfy vrfy;
7945fff9558SSimon J. Gerraty
7955fff9558SSimon J. Gerraty if ((fcp = read_file(file, &flen)) == NULL)
7965fff9558SSimon J. Gerraty return (NULL);
7975fff9558SSimon J. Gerraty if ((scp = read_file(sigfile, &slen)) == NULL) {
7985fff9558SSimon J. Gerraty free(fcp);
7995fff9558SSimon J. Gerraty return (NULL);
8005fff9558SSimon J. Gerraty }
8015fff9558SSimon J. Gerraty if ((po = decode_pem(scp, slen, &plen)) == NULL) {
8025fff9558SSimon J. Gerraty free(fcp);
8035fff9558SSimon J. Gerraty free(scp);
8045fff9558SSimon J. Gerraty return (NULL);
8055fff9558SSimon J. Gerraty }
8065fff9558SSimon J. Gerraty br_sha256_init(&ctx);
8075fff9558SSimon J. Gerraty br_sha256_update(&ctx, fcp, flen);
8085fff9558SSimon J. Gerraty br_sha256_out(&ctx, rhbuf);
809f9510887SSimon J. Gerraty #ifdef VE_ECDSA_HASH_AGAIN
8105fff9558SSimon J. Gerraty hex = hexdigest(hexbuf, sizeof(hexbuf), rhbuf, br_sha256_SIZE);
8115fff9558SSimon J. Gerraty /* now hash that */
8125fff9558SSimon J. Gerraty if (hex) {
8135fff9558SSimon J. Gerraty br_sha256_init(&ctx);
8145fff9558SSimon J. Gerraty br_sha256_update(&ctx, hex, strlen(hex));
8155fff9558SSimon J. Gerraty br_sha256_out(&ctx, rhbuf);
8165fff9558SSimon J. Gerraty }
817f9510887SSimon J. Gerraty #endif
8185fff9558SSimon J. Gerraty ec = br_ec_get_default();
8195fff9558SSimon J. Gerraty vrfy = br_ecdsa_vrfy_asn1_get_default();
8205fff9558SSimon J. Gerraty if (!vrfy(ec, rhbuf, br_sha256_SIZE, &pk->key.ec, po->data,
8215fff9558SSimon J. Gerraty po->data_len)) {
8225fff9558SSimon J. Gerraty free(fcp);
8235fff9558SSimon J. Gerraty fcp = NULL;
8245fff9558SSimon J. Gerraty }
8255fff9558SSimon J. Gerraty free(scp);
8265fff9558SSimon J. Gerraty return (fcp);
8275fff9558SSimon J. Gerraty }
8285fff9558SSimon J. Gerraty #endif
8295fff9558SSimon J. Gerraty
8305fff9558SSimon J. Gerraty #if defined(VE_RSA_SUPPORT) || defined(VE_OPENPGP_SUPPORT)
8315fff9558SSimon J. Gerraty /**
8325fff9558SSimon J. Gerraty * @brief verify an rsa digest
8335fff9558SSimon J. Gerraty *
8345fff9558SSimon J. Gerraty * @return 0 on failure
8355fff9558SSimon J. Gerraty */
8365fff9558SSimon J. Gerraty 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)8375fff9558SSimon J. Gerraty verify_rsa_digest (br_rsa_public_key *pkey,
8385fff9558SSimon J. Gerraty const unsigned char *hash_oid,
8395fff9558SSimon J. Gerraty unsigned char *mdata, size_t mlen,
8405fff9558SSimon J. Gerraty unsigned char *sdata, size_t slen)
8415fff9558SSimon J. Gerraty {
8425fff9558SSimon J. Gerraty br_rsa_pkcs1_vrfy vrfy;
8435fff9558SSimon J. Gerraty unsigned char vhbuf[br_sha512_SIZE];
8445fff9558SSimon J. Gerraty
8455fff9558SSimon J. Gerraty vrfy = br_rsa_pkcs1_vrfy_get_default();
8465fff9558SSimon J. Gerraty
8475fff9558SSimon J. Gerraty if (!vrfy(sdata, slen, hash_oid, mlen, pkey, vhbuf) ||
8485fff9558SSimon J. Gerraty memcmp(vhbuf, mdata, mlen) != 0) {
8495fff9558SSimon J. Gerraty return (0); /* fail */
8505fff9558SSimon J. Gerraty }
8515fff9558SSimon J. Gerraty return (1); /* ok */
8525fff9558SSimon J. Gerraty }
8535fff9558SSimon J. Gerraty #endif
8545fff9558SSimon J. Gerraty
8555fff9558SSimon J. Gerraty /**
8565fff9558SSimon J. Gerraty * @brief
8575fff9558SSimon J. Gerraty * verify file against sigfile using pk
8585fff9558SSimon J. Gerraty *
8595fff9558SSimon J. Gerraty * When we generated the signature in sigfile,
8605fff9558SSimon J. Gerraty * we hashed (sha256) file, and sent that to signing server
8615fff9558SSimon J. Gerraty * which hashed (sha256) that hash.
8625fff9558SSimon J. Gerraty *
8635fff9558SSimon J. Gerraty * Or (deprecated) we simply used sha1 hash directly.
8645fff9558SSimon J. Gerraty *
8655fff9558SSimon J. Gerraty * To verify we need to replicate that result.
8665fff9558SSimon J. Gerraty *
8675fff9558SSimon J. Gerraty * @param[in] pk
8685fff9558SSimon J. Gerraty * br_x509_pkey
8695fff9558SSimon J. Gerraty *
8705fff9558SSimon J. Gerraty * @paramp[in] file
8715fff9558SSimon J. Gerraty * file to be verified
8725fff9558SSimon J. Gerraty *
8735fff9558SSimon J. Gerraty * @param[in] sigfile
8745fff9558SSimon J. Gerraty * signature (PEM encoded)
8755fff9558SSimon J. Gerraty *
8765fff9558SSimon J. Gerraty * @return NULL on error, otherwise content of file.
8775fff9558SSimon J. Gerraty */
8785fff9558SSimon J. Gerraty #ifdef VE_RSA_SUPPORT
8795fff9558SSimon J. Gerraty static unsigned char *
verify_rsa(br_x509_pkey * pk,const char * file,const char * sigfile)8805fff9558SSimon J. Gerraty verify_rsa(br_x509_pkey *pk, const char *file, const char *sigfile)
8815fff9558SSimon J. Gerraty {
8825fff9558SSimon J. Gerraty unsigned char rhbuf[br_sha512_SIZE];
8835fff9558SSimon J. Gerraty const unsigned char *hash_oid;
8845fff9558SSimon J. Gerraty const br_hash_class *md;
8855fff9558SSimon J. Gerraty br_hash_compat_context mctx;
8865fff9558SSimon J. Gerraty unsigned char *fcp, *scp;
8875fff9558SSimon J. Gerraty size_t flen, slen, plen, hlen;
8885fff9558SSimon J. Gerraty pem_object *po;
8895fff9558SSimon J. Gerraty
8905fff9558SSimon J. Gerraty if ((fcp = read_file(file, &flen)) == NULL)
8915fff9558SSimon J. Gerraty return (NULL);
8925fff9558SSimon J. Gerraty if ((scp = read_file(sigfile, &slen)) == NULL) {
8935fff9558SSimon J. Gerraty free(fcp);
8945fff9558SSimon J. Gerraty return (NULL);
8955fff9558SSimon J. Gerraty }
8965fff9558SSimon J. Gerraty if ((po = decode_pem(scp, slen, &plen)) == NULL) {
8975fff9558SSimon J. Gerraty free(fcp);
8985fff9558SSimon J. Gerraty free(scp);
8995fff9558SSimon J. Gerraty return (NULL);
9005fff9558SSimon J. Gerraty }
9015fff9558SSimon J. Gerraty
9025fff9558SSimon J. Gerraty switch (po->data_len) {
9035fff9558SSimon J. Gerraty #if defined(UNIT_TEST) && defined(VE_DEPRECATED_RSA_SHA1_SUPPORT)
9045fff9558SSimon J. Gerraty case 256:
9055fff9558SSimon J. Gerraty // this is our old deprecated sig method
9065fff9558SSimon J. Gerraty md = &br_sha1_vtable;
9075fff9558SSimon J. Gerraty hlen = br_sha1_SIZE;
9085fff9558SSimon J. Gerraty hash_oid = BR_HASH_OID_SHA1;
9095fff9558SSimon J. Gerraty break;
9105fff9558SSimon J. Gerraty #endif
9115fff9558SSimon J. Gerraty default:
9125fff9558SSimon J. Gerraty md = &br_sha256_vtable;
9135fff9558SSimon J. Gerraty hlen = br_sha256_SIZE;
9145fff9558SSimon J. Gerraty hash_oid = BR_HASH_OID_SHA256;
9155fff9558SSimon J. Gerraty break;
9165fff9558SSimon J. Gerraty }
9175fff9558SSimon J. Gerraty md->init(&mctx.vtable);
9185fff9558SSimon J. Gerraty md->update(&mctx.vtable, fcp, flen);
9195fff9558SSimon J. Gerraty md->out(&mctx.vtable, rhbuf);
9205fff9558SSimon J. Gerraty if (!verify_rsa_digest(&pk->key.rsa, hash_oid,
9215fff9558SSimon J. Gerraty rhbuf, hlen, po->data, po->data_len)) {
9225fff9558SSimon J. Gerraty free(fcp);
9235fff9558SSimon J. Gerraty fcp = NULL;
9245fff9558SSimon J. Gerraty }
9255fff9558SSimon J. Gerraty free(scp);
9265fff9558SSimon J. Gerraty return (fcp);
9275fff9558SSimon J. Gerraty }
9285fff9558SSimon J. Gerraty #endif
9295fff9558SSimon J. Gerraty
9305fff9558SSimon J. Gerraty /**
9315fff9558SSimon J. Gerraty * @brief
9325fff9558SSimon J. Gerraty * verify a signature and return content of signed file
9335fff9558SSimon J. Gerraty *
9345fff9558SSimon J. Gerraty * @param[in] sigfile
9355fff9558SSimon J. Gerraty * file containing signature
9365fff9558SSimon J. Gerraty * we derrive path of signed file and certificate change from
9375fff9558SSimon J. Gerraty * this.
9385fff9558SSimon J. Gerraty *
9395fff9558SSimon J. Gerraty * @param[in] flags
9405fff9558SSimon J. Gerraty * only bit 1 significant so far
9415fff9558SSimon J. Gerraty *
9425fff9558SSimon J. Gerraty * @return NULL on error otherwise content of signed file
9435fff9558SSimon J. Gerraty */
9445fff9558SSimon J. Gerraty unsigned char *
verify_sig(const char * sigfile,int flags)9455fff9558SSimon J. Gerraty verify_sig(const char *sigfile, int flags)
9465fff9558SSimon J. Gerraty {
9475fff9558SSimon J. Gerraty br_x509_pkey *pk;
9485fff9558SSimon J. Gerraty br_name_element cn;
9495fff9558SSimon J. Gerraty char cn_buf[80];
9505fff9558SSimon J. Gerraty unsigned char cn_oid[4];
9515fff9558SSimon J. Gerraty char pbuf[MAXPATHLEN];
9525fff9558SSimon J. Gerraty char *cp;
9535fff9558SSimon J. Gerraty unsigned char *ucp;
9545fff9558SSimon J. Gerraty size_t n;
9555fff9558SSimon J. Gerraty
9565fff9558SSimon J. Gerraty DEBUG_PRINTF(5, ("verify_sig: %s\n", sigfile));
9575fff9558SSimon J. Gerraty n = strlcpy(pbuf, sigfile, sizeof(pbuf));
9585fff9558SSimon J. Gerraty if (n > (sizeof(pbuf) - 5) || strcmp(&sigfile[n - 3], "sig") != 0)
9595fff9558SSimon J. Gerraty return (NULL);
9605fff9558SSimon J. Gerraty cp = strcpy(&pbuf[n - 3], "certs");
9615fff9558SSimon J. Gerraty /*
9625fff9558SSimon J. Gerraty * We want the commonName field
9635fff9558SSimon J. Gerraty * the OID we want is 2,5,4,3 - but DER encoded
9645fff9558SSimon J. Gerraty */
9655fff9558SSimon J. Gerraty cn_oid[0] = 3;
9665fff9558SSimon J. Gerraty cn_oid[1] = 0x55;
9675fff9558SSimon J. Gerraty cn_oid[2] = 4;
9685fff9558SSimon J. Gerraty cn_oid[3] = 3;
9695fff9558SSimon J. Gerraty cn.oid = cn_oid;
9705fff9558SSimon J. Gerraty cn.buf = cn_buf;
9715fff9558SSimon J. Gerraty cn.len = sizeof(cn_buf);
9725fff9558SSimon J. Gerraty
9735fff9558SSimon J. Gerraty pk = verify_signer(pbuf, &cn, 1);
9745fff9558SSimon J. Gerraty if (!pk) {
9755fff9558SSimon J. Gerraty printf("cannot verify: %s: %s\n", pbuf, ve_error_get());
9765fff9558SSimon J. Gerraty return (NULL);
9775fff9558SSimon J. Gerraty }
9785fff9558SSimon J. Gerraty for (; cp > pbuf; cp--) {
9795fff9558SSimon J. Gerraty if (*cp == '.') {
9805fff9558SSimon J. Gerraty *cp = '\0';
9815fff9558SSimon J. Gerraty break;
9825fff9558SSimon J. Gerraty }
9835fff9558SSimon J. Gerraty }
9845fff9558SSimon J. Gerraty switch (pk->key_type) {
9855fff9558SSimon J. Gerraty #ifdef VE_ECDSA_SUPPORT
9865fff9558SSimon J. Gerraty case BR_KEYTYPE_EC:
9875fff9558SSimon J. Gerraty ucp = verify_ec(pk, pbuf, sigfile);
9885fff9558SSimon J. Gerraty break;
9895fff9558SSimon J. Gerraty #endif
9905fff9558SSimon J. Gerraty #ifdef VE_RSA_SUPPORT
9915fff9558SSimon J. Gerraty case BR_KEYTYPE_RSA:
9925fff9558SSimon J. Gerraty ucp = verify_rsa(pk, pbuf, sigfile);
9935fff9558SSimon J. Gerraty break;
9945fff9558SSimon J. Gerraty #endif
9955fff9558SSimon J. Gerraty default:
9965fff9558SSimon J. Gerraty ucp = NULL; /* not supported */
9975fff9558SSimon J. Gerraty }
9985fff9558SSimon J. Gerraty xfreepkey(pk);
9995fff9558SSimon J. Gerraty if (!ucp) {
10005fff9558SSimon J. Gerraty printf("Unverified %s (%s)\n", pbuf,
10015fff9558SSimon J. Gerraty cn.status ? cn_buf : "unknown");
100266655411SSimon J. Gerraty } else if ((flags & VEF_VERBOSE) != 0) {
10035fff9558SSimon J. Gerraty printf("Verified %s signed by %s\n", pbuf,
10045fff9558SSimon J. Gerraty cn.status ? cn_buf : "someone we trust");
10055fff9558SSimon J. Gerraty }
10065fff9558SSimon J. Gerraty return (ucp);
10075fff9558SSimon J. Gerraty }
10085fff9558SSimon J. Gerraty
10095fff9558SSimon J. Gerraty
10105fff9558SSimon J. Gerraty /**
10115fff9558SSimon J. Gerraty * @brief verify hash matches
10125fff9558SSimon J. Gerraty *
10135fff9558SSimon J. Gerraty * We have finished hashing a file,
10145fff9558SSimon J. Gerraty * see if we got the desired result.
10155fff9558SSimon J. Gerraty *
10165fff9558SSimon J. Gerraty * @param[in] ctx
10175fff9558SSimon J. Gerraty * pointer to hash context
10185fff9558SSimon J. Gerraty *
10195fff9558SSimon J. Gerraty * @param[in] md
10205fff9558SSimon J. Gerraty * pointer to hash class
10215fff9558SSimon J. Gerraty *
10225fff9558SSimon J. Gerraty * @param[in] path
10235fff9558SSimon J. Gerraty * name of the file we are checking
10245fff9558SSimon J. Gerraty *
10255fff9558SSimon J. Gerraty * @param[in] want
10265fff9558SSimon J. Gerraty * the expected result
10275fff9558SSimon J. Gerraty *
10285fff9558SSimon J. Gerraty * @param[in] hlen
10295fff9558SSimon J. Gerraty * size of hash output
10305fff9558SSimon J. Gerraty *
10315fff9558SSimon J. Gerraty * @return 0 on success
10325fff9558SSimon J. Gerraty */
10335fff9558SSimon J. Gerraty int
ve_check_hash(br_hash_compat_context * ctx,const br_hash_class * md,const char * path,const char * want,size_t hlen)10345fff9558SSimon J. Gerraty ve_check_hash(br_hash_compat_context *ctx, const br_hash_class *md,
10355fff9558SSimon J. Gerraty const char *path, const char *want, size_t hlen)
10365fff9558SSimon J. Gerraty {
10375fff9558SSimon J. Gerraty char hexbuf[br_sha512_SIZE * 2 + 2];
10385fff9558SSimon J. Gerraty unsigned char hbuf[br_sha512_SIZE];
10395fff9558SSimon J. Gerraty char *hex;
10405fff9558SSimon J. Gerraty int rc;
10415fff9558SSimon J. Gerraty int n;
10425fff9558SSimon J. Gerraty
10435fff9558SSimon J. Gerraty md->out(&ctx->vtable, hbuf);
10445fff9558SSimon J. Gerraty #ifdef VE_PCR_SUPPORT
104553f151f9SSimon J. Gerraty ve_pcr_update(path, hbuf, hlen);
10465fff9558SSimon J. Gerraty #endif
10475fff9558SSimon J. Gerraty hex = hexdigest(hexbuf, sizeof(hexbuf), hbuf, hlen);
10485fff9558SSimon J. Gerraty if (!hex)
10495fff9558SSimon J. Gerraty return (VE_FINGERPRINT_WRONG);
10505fff9558SSimon J. Gerraty n = 2*hlen;
10515fff9558SSimon J. Gerraty if ((rc = strncmp(hex, want, n))) {
10525fff9558SSimon J. Gerraty ve_error_set("%s: %.*s != %.*s", path, n, hex, n, want);
10535fff9558SSimon J. Gerraty rc = VE_FINGERPRINT_WRONG;
10545fff9558SSimon J. Gerraty }
10555fff9558SSimon J. Gerraty return (rc ? rc : VE_FINGERPRINT_OK);
10565fff9558SSimon J. Gerraty }
10575fff9558SSimon J. Gerraty
10585fff9558SSimon J. Gerraty #ifdef VE_HASH_KAT_STR
10595fff9558SSimon J. Gerraty static int
test_hash(const br_hash_class * md,size_t hlen,const char * hname,const char * s,size_t slen,const char * want)10605fff9558SSimon J. Gerraty test_hash(const br_hash_class *md, size_t hlen,
10615fff9558SSimon J. Gerraty const char *hname, const char *s, size_t slen, const char *want)
10625fff9558SSimon J. Gerraty {
10635fff9558SSimon J. Gerraty br_hash_compat_context mctx;
10645fff9558SSimon J. Gerraty
10655fff9558SSimon J. Gerraty md->init(&mctx.vtable);
10665fff9558SSimon J. Gerraty md->update(&mctx.vtable, s, slen);
10675fff9558SSimon J. Gerraty return (ve_check_hash(&mctx, md, hname, want, hlen) != VE_FINGERPRINT_OK);
10685fff9558SSimon J. Gerraty }
10695fff9558SSimon J. Gerraty
10705fff9558SSimon J. Gerraty #endif
10715fff9558SSimon J. Gerraty
10725fff9558SSimon J. Gerraty #define ve_test_hash(n, N) \
10735fff9558SSimon J. Gerraty printf("Testing hash: " #n "\t\t\t\t%s\n", \
10745fff9558SSimon J. Gerraty test_hash(&br_ ## n ## _vtable, br_ ## n ## _SIZE, #n, \
10759bee6a60SSimon J. Gerraty VE_HASH_KAT_STR, VE_HASH_KAT_STRLEN(VE_HASH_KAT_STR), \
10765fff9558SSimon J. Gerraty vh_ ## N) ? "Failed" : "Passed")
10775fff9558SSimon J. Gerraty
10785fff9558SSimon J. Gerraty /**
10795fff9558SSimon J. Gerraty * @brief
10805fff9558SSimon J. Gerraty * run self tests on hash and signature verification
10815fff9558SSimon J. Gerraty *
10825fff9558SSimon J. Gerraty * Test that the hash methods (SHA1 and SHA256) work.
10835fff9558SSimon J. Gerraty * Test that we can verify a certificate for each supported
10845fff9558SSimon J. Gerraty * Root CA.
10855fff9558SSimon J. Gerraty *
10865fff9558SSimon J. Gerraty * @return cached result.
10875fff9558SSimon J. Gerraty */
10885fff9558SSimon J. Gerraty int
ve_self_tests(void)10895fff9558SSimon J. Gerraty ve_self_tests(void)
10905fff9558SSimon J. Gerraty {
10915fff9558SSimon J. Gerraty static int once = -1;
10925fff9558SSimon J. Gerraty #ifdef VERIFY_CERTS_STR
10935fff9558SSimon J. Gerraty br_x509_certificate *xcs;
10945fff9558SSimon J. Gerraty br_x509_pkey *pk;
10955fff9558SSimon J. Gerraty br_name_element cn;
10965fff9558SSimon J. Gerraty char cn_buf[80];
10975fff9558SSimon J. Gerraty unsigned char cn_oid[4];
10985fff9558SSimon J. Gerraty size_t num;
10995fff9558SSimon J. Gerraty size_t u;
11005fff9558SSimon J. Gerraty #endif
11015fff9558SSimon J. Gerraty
11025fff9558SSimon J. Gerraty if (once >= 0)
11035fff9558SSimon J. Gerraty return (once);
11045fff9558SSimon J. Gerraty once = 0;
11055fff9558SSimon J. Gerraty
11065fff9558SSimon J. Gerraty DEBUG_PRINTF(5, ("Self tests...\n"));
11075fff9558SSimon J. Gerraty #ifdef VE_HASH_KAT_STR
11085fff9558SSimon J. Gerraty #ifdef VE_SHA1_SUPPORT
11095fff9558SSimon J. Gerraty ve_test_hash(sha1, SHA1);
11105fff9558SSimon J. Gerraty #endif
11115fff9558SSimon J. Gerraty #ifdef VE_SHA256_SUPPORT
11125fff9558SSimon J. Gerraty ve_test_hash(sha256, SHA256);
11135fff9558SSimon J. Gerraty #endif
11145fff9558SSimon J. Gerraty #ifdef VE_SHA384_SUPPORT
11155fff9558SSimon J. Gerraty ve_test_hash(sha384, SHA384);
11165fff9558SSimon J. Gerraty #endif
11175fff9558SSimon J. Gerraty #ifdef VE_SHA512_SUPPORT
11185fff9558SSimon J. Gerraty ve_test_hash(sha512, SHA512);
11195fff9558SSimon J. Gerraty #endif
11205fff9558SSimon J. Gerraty #endif
11215fff9558SSimon J. Gerraty #ifdef VERIFY_CERTS_STR
11225fff9558SSimon J. Gerraty xcs = parse_certificates(__DECONST(unsigned char *, VERIFY_CERTS_STR),
11235fff9558SSimon J. Gerraty sizeof(VERIFY_CERTS_STR), &num);
11249bee6a60SSimon J. Gerraty if (xcs != NULL) {
11255fff9558SSimon J. Gerraty /*
11265fff9558SSimon J. Gerraty * We want the commonName field
11275fff9558SSimon J. Gerraty * the OID we want is 2,5,4,3 - but DER encoded
11285fff9558SSimon J. Gerraty */
11295fff9558SSimon J. Gerraty cn_oid[0] = 3;
11305fff9558SSimon J. Gerraty cn_oid[1] = 0x55;
11315fff9558SSimon J. Gerraty cn_oid[2] = 4;
11325fff9558SSimon J. Gerraty cn_oid[3] = 3;
11335fff9558SSimon J. Gerraty cn.oid = cn_oid;
11345fff9558SSimon J. Gerraty cn.buf = cn_buf;
11355fff9558SSimon J. Gerraty
11365fff9558SSimon J. Gerraty for (u = 0; u < num; u ++) {
11375fff9558SSimon J. Gerraty cn.len = sizeof(cn_buf);
113813ea0450SMarcin Wojtas if ((pk = verify_signer_xcs(&xcs[u], 1, &cn, 1, &trust_anchors)) != NULL) {
113913ea0450SMarcin Wojtas free_cert_contents(&xcs[u]);
11405fff9558SSimon J. Gerraty once++;
11415fff9558SSimon J. Gerraty printf("Testing verify certificate: %s\tPassed\n",
11425fff9558SSimon J. Gerraty cn.status ? cn_buf : "");
11435fff9558SSimon J. Gerraty xfreepkey(pk);
11445fff9558SSimon J. Gerraty }
11455fff9558SSimon J. Gerraty }
11465fff9558SSimon J. Gerraty if (!once)
11475fff9558SSimon J. Gerraty printf("Testing verify certificate:\t\t\tFailed\n");
11485fff9558SSimon J. Gerraty xfree(xcs);
11499bee6a60SSimon J. Gerraty }
11505fff9558SSimon J. Gerraty #endif /* VERIFY_CERTS_STR */
11515fff9558SSimon J. Gerraty #ifdef VE_OPENPGP_SUPPORT
11525fff9558SSimon J. Gerraty if (!openpgp_self_tests())
11535fff9558SSimon J. Gerraty once++;
11545fff9558SSimon J. Gerraty #endif
11555fff9558SSimon J. Gerraty return (once);
11565fff9558SSimon J. Gerraty }
1157