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 __FBSDID("$FreeBSD$"); 275fff9558SSimon J. Gerraty 285fff9558SSimon J. Gerraty /** 295fff9558SSimon J. Gerraty * @file vets.c - trust store 305fff9558SSimon J. Gerraty * @brief verify signatures 315fff9558SSimon J. Gerraty * 325fff9558SSimon J. Gerraty * We leverage code from BearSSL www.bearssl.org 335fff9558SSimon J. Gerraty */ 345fff9558SSimon J. Gerraty 355fff9558SSimon J. Gerraty #include <sys/time.h> 365fff9558SSimon J. Gerraty #include <stdarg.h> 375fff9558SSimon J. Gerraty #define NEED_BRSSL_H 385fff9558SSimon J. Gerraty #include "libsecureboot-priv.h" 395fff9558SSimon J. Gerraty #include <brssl.h> 405fff9558SSimon J. Gerraty #include <ta.h> 415fff9558SSimon J. Gerraty 425fff9558SSimon J. Gerraty #ifndef TRUST_ANCHOR_STR 435fff9558SSimon J. Gerraty # define TRUST_ANCHOR_STR ta_PEM 445fff9558SSimon J. Gerraty #endif 455fff9558SSimon J. Gerraty 4666655411SSimon J. Gerraty #define EPOCH_YEAR 1970 4766655411SSimon J. Gerraty #define AVG_SECONDS_PER_YEAR 31556952L 485fff9558SSimon J. Gerraty #define SECONDS_PER_DAY 86400 4953f151f9SSimon J. Gerraty #define SECONDS_PER_YEAR 365 * SECONDS_PER_DAY 5053f151f9SSimon J. Gerraty #ifndef VE_UTC_MAX_JUMP 5153f151f9SSimon J. Gerraty # define VE_UTC_MAX_JUMP 20 * SECONDS_PER_YEAR 5253f151f9SSimon J. Gerraty #endif 535fff9558SSimon J. Gerraty #define X509_DAYS_TO_UTC0 719528 545fff9558SSimon J. Gerraty 555fff9558SSimon J. Gerraty int DebugVe = 0; 565fff9558SSimon J. Gerraty 5766655411SSimon J. Gerraty #ifndef VE_VERIFY_FLAGS 5866655411SSimon J. Gerraty # define VE_VERIFY_FLAGS VEF_VERBOSE 5966655411SSimon J. Gerraty #endif 6066655411SSimon J. Gerraty int VerifyFlags = VE_VERIFY_FLAGS; 6166655411SSimon J. Gerraty 625fff9558SSimon J. Gerraty typedef VECTOR(br_x509_certificate) cert_list; 6313ea0450SMarcin Wojtas typedef VECTOR(hash_data) digest_list; 645fff9558SSimon J. Gerraty 655fff9558SSimon J. Gerraty static anchor_list trust_anchors = VEC_INIT; 6613ea0450SMarcin Wojtas static anchor_list forbidden_anchors = VEC_INIT; 6713ea0450SMarcin Wojtas static digest_list forbidden_digests = VEC_INIT; 685fff9558SSimon J. Gerraty 69f9510887SSimon J. Gerraty static int anchor_verbose = 0; 70f9510887SSimon J. Gerraty 71f9510887SSimon J. Gerraty void 72f9510887SSimon J. Gerraty ve_anchor_verbose_set(int n) 73f9510887SSimon J. Gerraty { 74f9510887SSimon J. Gerraty anchor_verbose = n; 75f9510887SSimon J. Gerraty } 76f9510887SSimon J. Gerraty 77f9510887SSimon J. Gerraty int 78f9510887SSimon J. Gerraty ve_anchor_verbose_get(void) 79f9510887SSimon J. Gerraty { 80f9510887SSimon J. Gerraty return (anchor_verbose); 81f9510887SSimon J. Gerraty } 82f9510887SSimon J. Gerraty 835fff9558SSimon J. Gerraty void 845fff9558SSimon J. Gerraty ve_debug_set(int n) 855fff9558SSimon J. Gerraty { 865fff9558SSimon J. Gerraty DebugVe = n; 875fff9558SSimon J. Gerraty } 885fff9558SSimon J. Gerraty 89*ab4f0a15SSimon J. Gerraty /* 90*ab4f0a15SSimon J. Gerraty * For embedded systems (and boot loaders) 91*ab4f0a15SSimon J. Gerraty * we do not want to enforce certificate validity post install. 92*ab4f0a15SSimon J. Gerraty * It is generally unacceptible for infrastructure to stop working 93*ab4f0a15SSimon J. Gerraty * just because it has not been updated recently. 94*ab4f0a15SSimon J. Gerraty */ 95*ab4f0a15SSimon J. Gerraty static int enforce_validity = 0; 96*ab4f0a15SSimon J. Gerraty 97*ab4f0a15SSimon J. Gerraty void 98*ab4f0a15SSimon J. Gerraty ve_enforce_validity_set(int i) 99*ab4f0a15SSimon J. Gerraty { 100*ab4f0a15SSimon J. Gerraty enforce_validity = i; 101*ab4f0a15SSimon J. Gerraty } 102*ab4f0a15SSimon J. Gerraty 1035fff9558SSimon J. Gerraty static char ebuf[512]; 1045fff9558SSimon J. Gerraty 1055fff9558SSimon J. Gerraty char * 1065fff9558SSimon J. Gerraty ve_error_get(void) 1075fff9558SSimon J. Gerraty { 1085fff9558SSimon J. Gerraty return (ebuf); 1095fff9558SSimon J. Gerraty } 1105fff9558SSimon J. Gerraty 1115fff9558SSimon J. Gerraty int 1125fff9558SSimon J. Gerraty ve_error_set(const char *fmt, ...) 1135fff9558SSimon J. Gerraty { 1145fff9558SSimon J. Gerraty int rc; 1155fff9558SSimon J. Gerraty va_list ap; 1165fff9558SSimon J. Gerraty 1175fff9558SSimon J. Gerraty va_start(ap, fmt); 1185fff9558SSimon J. Gerraty ebuf[0] = '\0'; 1195fff9558SSimon J. Gerraty rc = 0; 1205fff9558SSimon J. Gerraty if (fmt) { 1215fff9558SSimon J. Gerraty #ifdef STAND_H 1225fff9558SSimon J. Gerraty vsprintf(ebuf, fmt, ap); /* no vsnprintf in libstand */ 1235fff9558SSimon J. Gerraty ebuf[sizeof(ebuf) - 1] = '\0'; 1245fff9558SSimon J. Gerraty rc = strlen(ebuf); 1255fff9558SSimon J. Gerraty #else 1265fff9558SSimon J. Gerraty rc = vsnprintf(ebuf, sizeof(ebuf), fmt, ap); 1275fff9558SSimon J. Gerraty #endif 1285fff9558SSimon J. Gerraty } 1295fff9558SSimon J. Gerraty va_end(ap); 1305fff9558SSimon J. Gerraty return (rc); 1315fff9558SSimon J. Gerraty } 1325fff9558SSimon J. Gerraty 13366655411SSimon J. Gerraty #define isleap(y) (((y) % 4) == 0 && (((y) % 100) != 0 || ((y) % 400) == 0)) 13466655411SSimon J. Gerraty 13566655411SSimon J. Gerraty /* 13666655411SSimon J. Gerraty * The *approximate* date. 13766655411SSimon J. Gerraty * 13866655411SSimon J. Gerraty * When certificate verification fails for being 13966655411SSimon J. Gerraty * expired or not yet valid, it helps to indicate 14066655411SSimon J. Gerraty * our current date. 14166655411SSimon J. Gerraty * Since libsa lacks strftime and gmtime, 14266655411SSimon J. Gerraty * this simple implementation suffices. 14366655411SSimon J. Gerraty */ 14466655411SSimon J. Gerraty static const char * 14566655411SSimon J. Gerraty gdate(char *buf, size_t bufsz, time_t clock) 14666655411SSimon J. Gerraty { 14766655411SSimon J. Gerraty int days[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; 14866655411SSimon J. Gerraty int year, y, m, d; 14966655411SSimon J. Gerraty 15066655411SSimon J. Gerraty y = clock / AVG_SECONDS_PER_YEAR; 15166655411SSimon J. Gerraty year = EPOCH_YEAR + y; 15266655411SSimon J. Gerraty for (y = EPOCH_YEAR; y < year; y++) { 15366655411SSimon J. Gerraty clock -= SECONDS_PER_YEAR; 15466655411SSimon J. Gerraty if (isleap(y)) 15566655411SSimon J. Gerraty clock -= SECONDS_PER_DAY; 15666655411SSimon J. Gerraty } 15766655411SSimon J. Gerraty d = clock / SECONDS_PER_DAY; 15866655411SSimon J. Gerraty for (m = 0; d > 1 && m < 12; m++) { 15966655411SSimon J. Gerraty if (d > days[m]) { 16066655411SSimon J. Gerraty d -= days[m]; 16166655411SSimon J. Gerraty if (m == 1 && d > 0 && isleap(year)) 16266655411SSimon J. Gerraty d--; 16366655411SSimon J. Gerraty } else 16466655411SSimon J. Gerraty break; 16566655411SSimon J. Gerraty } 16666655411SSimon J. Gerraty d++; 16766655411SSimon J. Gerraty if (d > days[m]) { 16866655411SSimon J. Gerraty d = 1; 16966655411SSimon J. Gerraty m++; 17066655411SSimon J. Gerraty if (m >= 12) { 17166655411SSimon J. Gerraty year++; 17266655411SSimon J. Gerraty m = 0; 17366655411SSimon J. Gerraty } 17466655411SSimon J. Gerraty } 17566655411SSimon J. Gerraty (void)snprintf(buf, bufsz, "%04d-%02d-%02d", year, m+1, d); 17666655411SSimon J. Gerraty return(buf); 17766655411SSimon J. Gerraty } 17866655411SSimon J. Gerraty 1795fff9558SSimon J. Gerraty /* this is the time we use for verifying certs */ 18066655411SSimon J. Gerraty #ifdef UNIT_TEST 18166655411SSimon J. Gerraty extern time_t ve_utc; 18266655411SSimon J. Gerraty time_t ve_utc = 0; 18366655411SSimon J. Gerraty #else 1845fff9558SSimon J. Gerraty static time_t ve_utc = 0; 18566655411SSimon J. Gerraty #endif 1865fff9558SSimon J. Gerraty 1875fff9558SSimon J. Gerraty /** 1885fff9558SSimon J. Gerraty * @brief 1895fff9558SSimon J. Gerraty * set ve_utc used for certificate verification 1905fff9558SSimon J. Gerraty * 1915fff9558SSimon J. Gerraty * @param[in] utc 19253f151f9SSimon J. Gerraty * time - ignored unless greater than current value 19353f151f9SSimon J. Gerraty * and not a leap of 20 years or more. 1945fff9558SSimon J. Gerraty */ 1955fff9558SSimon J. Gerraty void 1965fff9558SSimon J. Gerraty ve_utc_set(time_t utc) 1975fff9558SSimon J. Gerraty { 19853f151f9SSimon J. Gerraty if (utc > ve_utc && 19953f151f9SSimon J. Gerraty (ve_utc == 0 || (utc - ve_utc) < VE_UTC_MAX_JUMP)) { 2005fff9558SSimon J. Gerraty DEBUG_PRINTF(2, ("Set ve_utc=%jd\n", (intmax_t)utc)); 2015fff9558SSimon J. Gerraty ve_utc = utc; 2025fff9558SSimon J. Gerraty } 2035fff9558SSimon J. Gerraty } 2045fff9558SSimon J. Gerraty 2055fff9558SSimon J. Gerraty static void 2065fff9558SSimon J. Gerraty free_cert_contents(br_x509_certificate *xc) 2075fff9558SSimon J. Gerraty { 2085fff9558SSimon J. Gerraty xfree(xc->data); 2095fff9558SSimon J. Gerraty } 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 * 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); 244f9510887SSimon J. Gerraty /* we don' actually care about cert status - just its name */ 245f9510887SSimon J. Gerraty err = mc.vtable->end_chain(&mc.vtable); 246f9510887SSimon J. Gerraty 247f9510887SSimon J. Gerraty if (!cn.status) 248f9510887SSimon J. Gerraty buf = NULL; 249f9510887SSimon J. Gerraty return (buf); 250f9510887SSimon J. Gerraty } 251f9510887SSimon J. Gerraty 25213ea0450SMarcin Wojtas /* ASN parsing related defines */ 25313ea0450SMarcin Wojtas #define ASN1_PRIMITIVE_TAG 0x1F 25413ea0450SMarcin Wojtas #define ASN1_INF_LENGTH 0x80 25513ea0450SMarcin Wojtas #define ASN1_LENGTH_MASK 0x7F 25613ea0450SMarcin Wojtas 25713ea0450SMarcin Wojtas /* 25813ea0450SMarcin Wojtas * Get TBS part of certificate. 25913ea0450SMarcin Wojtas * Since BearSSL doesn't provide any API to do this, 26013ea0450SMarcin Wojtas * it has to be implemented here. 2615fff9558SSimon J. Gerraty */ 26213ea0450SMarcin Wojtas static void* 26313ea0450SMarcin Wojtas X509_to_tbs(unsigned char* cert, size_t* output_size) 26413ea0450SMarcin Wojtas { 26513ea0450SMarcin Wojtas unsigned char *result; 26613ea0450SMarcin Wojtas size_t tbs_size; 26713ea0450SMarcin Wojtas int size, i; 26813ea0450SMarcin Wojtas 26913ea0450SMarcin Wojtas if (cert == NULL) 27013ea0450SMarcin Wojtas return (NULL); 27113ea0450SMarcin Wojtas 27213ea0450SMarcin Wojtas /* Strip two sequences to get to the TBS section */ 27313ea0450SMarcin Wojtas for (i = 0; i < 2; i++) { 27413ea0450SMarcin Wojtas /* 27513ea0450SMarcin Wojtas * XXX: We don't need to support extended tags since 27613ea0450SMarcin Wojtas * they should not be present in certificates. 27713ea0450SMarcin Wojtas */ 27813ea0450SMarcin Wojtas if ((*cert & ASN1_PRIMITIVE_TAG) == ASN1_PRIMITIVE_TAG) 27913ea0450SMarcin Wojtas return (NULL); 28013ea0450SMarcin Wojtas 28113ea0450SMarcin Wojtas cert++; 28213ea0450SMarcin Wojtas 28313ea0450SMarcin Wojtas if (*cert == ASN1_INF_LENGTH) 28413ea0450SMarcin Wojtas return (NULL); 28513ea0450SMarcin Wojtas 28613ea0450SMarcin Wojtas size = *cert & ASN1_LENGTH_MASK; 28713ea0450SMarcin Wojtas tbs_size = 0; 28813ea0450SMarcin Wojtas 28913ea0450SMarcin Wojtas /* Size can either be stored on a single or multiple bytes */ 29013ea0450SMarcin Wojtas if (*cert & (ASN1_LENGTH_MASK + 1)) { 29113ea0450SMarcin Wojtas cert++; 29213ea0450SMarcin Wojtas while (*cert == 0 && size > 0) { 29313ea0450SMarcin Wojtas cert++; 29413ea0450SMarcin Wojtas size--; 29513ea0450SMarcin Wojtas } 29613ea0450SMarcin Wojtas while (size-- > 0) { 29713ea0450SMarcin Wojtas tbs_size <<= 8; 29813ea0450SMarcin Wojtas tbs_size |= *(cert++); 29913ea0450SMarcin Wojtas } 30013ea0450SMarcin Wojtas } 30113ea0450SMarcin Wojtas if (i == 0) 30213ea0450SMarcin Wojtas result = cert; 30313ea0450SMarcin Wojtas } 30413ea0450SMarcin Wojtas tbs_size += (cert - result); 30513ea0450SMarcin Wojtas 30613ea0450SMarcin Wojtas if (output_size != NULL) 30713ea0450SMarcin Wojtas *output_size = tbs_size; 30813ea0450SMarcin Wojtas 30913ea0450SMarcin Wojtas return (result); 31013ea0450SMarcin Wojtas } 31113ea0450SMarcin Wojtas 31213ea0450SMarcin Wojtas void 31313ea0450SMarcin Wojtas ve_forbidden_digest_add(hash_data *digest, size_t num) 31413ea0450SMarcin Wojtas { 31513ea0450SMarcin Wojtas while (num--) 31613ea0450SMarcin Wojtas VEC_ADD(forbidden_digests, digest[num]); 31713ea0450SMarcin Wojtas } 31813ea0450SMarcin Wojtas 31913ea0450SMarcin Wojtas static size_t 320f9510887SSimon J. Gerraty ve_anchors_add(br_x509_certificate *xcs, size_t num, anchor_list *anchors, 32118e2fbc0SSimon J. Gerraty const char *anchors_name) 3225fff9558SSimon J. Gerraty { 3235fff9558SSimon J. Gerraty br_x509_trust_anchor ta; 3245fff9558SSimon J. Gerraty size_t u; 3255fff9558SSimon J. Gerraty 3265fff9558SSimon J. Gerraty for (u = 0; u < num; u++) { 3275fff9558SSimon J. Gerraty if (certificate_to_trust_anchor_inner(&ta, &xcs[u]) < 0) { 3285fff9558SSimon J. Gerraty break; 3295fff9558SSimon J. Gerraty } 33013ea0450SMarcin Wojtas VEC_ADD(*anchors, ta); 331f9510887SSimon J. Gerraty if (anchor_verbose && anchors_name) { 332f9510887SSimon J. Gerraty char buf[64]; 333f9510887SSimon J. Gerraty char *cp; 334f9510887SSimon J. Gerraty 335f9510887SSimon J. Gerraty cp = x509_cn_get(&xcs[u], buf, sizeof(buf)); 336f9510887SSimon J. Gerraty if (cp) { 337f9510887SSimon J. Gerraty printf("x509_anchor(%s) %s\n", cp, anchors_name); 338f9510887SSimon J. Gerraty } 339f9510887SSimon J. Gerraty } 3405fff9558SSimon J. Gerraty } 3415fff9558SSimon J. Gerraty return (u); 3425fff9558SSimon J. Gerraty } 3435fff9558SSimon J. Gerraty 3445fff9558SSimon J. Gerraty /** 3455fff9558SSimon J. Gerraty * @brief 34613ea0450SMarcin Wojtas * add certs to our trust store 34713ea0450SMarcin Wojtas */ 34813ea0450SMarcin Wojtas size_t 34913ea0450SMarcin Wojtas ve_trust_anchors_add(br_x509_certificate *xcs, size_t num) 35013ea0450SMarcin Wojtas { 351f9510887SSimon J. Gerraty return (ve_anchors_add(xcs, num, &trust_anchors, "trusted")); 35213ea0450SMarcin Wojtas } 35313ea0450SMarcin Wojtas 35413ea0450SMarcin Wojtas size_t 35513ea0450SMarcin Wojtas ve_forbidden_anchors_add(br_x509_certificate *xcs, size_t num) 35613ea0450SMarcin Wojtas { 357f9510887SSimon J. Gerraty return (ve_anchors_add(xcs, num, &forbidden_anchors, "forbidden")); 358f9510887SSimon J. Gerraty } 359f9510887SSimon J. Gerraty 360f9510887SSimon J. Gerraty 361f9510887SSimon J. Gerraty /** 362f9510887SSimon J. Gerraty * @brief add trust anchors in buf 363f9510887SSimon J. Gerraty * 364f9510887SSimon J. Gerraty * Assume buf contains x509 certificates, but if not and 365f9510887SSimon J. Gerraty * we support OpenPGP try adding as that. 366f9510887SSimon J. Gerraty * 367f9510887SSimon J. Gerraty * @return number of anchors added 368f9510887SSimon J. Gerraty */ 369f9510887SSimon J. Gerraty size_t 370f9510887SSimon J. Gerraty ve_trust_anchors_add_buf(unsigned char *buf, size_t len) 371f9510887SSimon J. Gerraty { 372f9510887SSimon J. Gerraty br_x509_certificate *xcs; 373f9510887SSimon J. Gerraty size_t num; 374f9510887SSimon J. Gerraty 375f9510887SSimon J. Gerraty num = 0; 376f9510887SSimon J. Gerraty xcs = parse_certificates(buf, len, &num); 377f9510887SSimon J. Gerraty if (xcs != NULL) { 378f9510887SSimon J. Gerraty num = ve_trust_anchors_add(xcs, num); 379f9510887SSimon J. Gerraty #ifdef VE_OPENPGP_SUPPORT 380f9510887SSimon J. Gerraty } else { 381f9510887SSimon J. Gerraty num = openpgp_trust_add_buf(buf, len); 382f9510887SSimon J. Gerraty #endif 383f9510887SSimon J. Gerraty } 384f9510887SSimon J. Gerraty return (num); 385f9510887SSimon J. Gerraty } 386f9510887SSimon J. Gerraty 387f9510887SSimon J. Gerraty /** 388f9510887SSimon J. Gerraty * @brief revoke trust anchors in buf 389f9510887SSimon J. Gerraty * 390f9510887SSimon J. Gerraty * Assume buf contains x509 certificates, but if not and 391f9510887SSimon J. Gerraty * we support OpenPGP try revoking keyId 392f9510887SSimon J. Gerraty * 393f9510887SSimon J. Gerraty * @return number of anchors revoked 394f9510887SSimon J. Gerraty */ 395f9510887SSimon J. Gerraty size_t 396f9510887SSimon J. Gerraty ve_trust_anchors_revoke(unsigned char *buf, size_t len) 397f9510887SSimon J. Gerraty { 398f9510887SSimon J. Gerraty br_x509_certificate *xcs; 399f9510887SSimon J. Gerraty size_t num; 400f9510887SSimon J. Gerraty 401f9510887SSimon J. Gerraty num = 0; 402f9510887SSimon J. Gerraty xcs = parse_certificates(buf, len, &num); 403f9510887SSimon J. Gerraty if (xcs != NULL) { 404f9510887SSimon J. Gerraty num = ve_forbidden_anchors_add(xcs, num); 405f9510887SSimon J. Gerraty #ifdef VE_OPENPGP_SUPPORT 406f9510887SSimon J. Gerraty } else { 407f9510887SSimon J. Gerraty if (buf[len - 1] == '\n') 408f9510887SSimon J. Gerraty buf[len - 1] = '\0'; 409f9510887SSimon J. Gerraty num = openpgp_trust_revoke((char *)buf); 410f9510887SSimon J. Gerraty #endif 411f9510887SSimon J. Gerraty } 412f9510887SSimon J. Gerraty return (num); 41313ea0450SMarcin Wojtas } 41413ea0450SMarcin Wojtas 41513ea0450SMarcin Wojtas /** 41613ea0450SMarcin Wojtas * @brief 4175fff9558SSimon J. Gerraty * initialize our trust_anchors from ta_PEM 4185fff9558SSimon J. Gerraty */ 4195fff9558SSimon J. Gerraty int 4205fff9558SSimon J. Gerraty ve_trust_init(void) 4215fff9558SSimon J. Gerraty { 4225fff9558SSimon J. Gerraty static int once = -1; 4235fff9558SSimon J. Gerraty 4245fff9558SSimon J. Gerraty if (once >= 0) 4255fff9558SSimon J. Gerraty return (once); 4263ae2a848SSimon J. Gerraty once = 0; /* to be sure */ 4275fff9558SSimon J. Gerraty #ifdef BUILD_UTC 42853f151f9SSimon J. Gerraty ve_utc_set(BUILD_UTC); /* ensure sanity */ 4295fff9558SSimon J. Gerraty #endif 43053f151f9SSimon J. Gerraty ve_utc_set(time(NULL)); 4315fff9558SSimon J. Gerraty ve_error_set(NULL); /* make sure it is empty */ 4325fff9558SSimon J. Gerraty #ifdef VE_PCR_SUPPORT 4335fff9558SSimon J. Gerraty ve_pcr_init(); 4345fff9558SSimon J. Gerraty #endif 4355fff9558SSimon J. Gerraty 4365fff9558SSimon J. Gerraty #ifdef TRUST_ANCHOR_STR 437e6ef5042SWojciech Macek if (TRUST_ANCHOR_STR != NULL && strlen(TRUST_ANCHOR_STR) != 0ul) 438e6ef5042SWojciech Macek ve_trust_anchors_add_buf(__DECONST(unsigned char *, 439e6ef5042SWojciech Macek TRUST_ANCHOR_STR), sizeof(TRUST_ANCHOR_STR)); 4405fff9558SSimon J. Gerraty #endif 44113ea0450SMarcin Wojtas once = (int) VEC_LEN(trust_anchors); 4429bee6a60SSimon J. Gerraty #ifdef VE_OPENPGP_SUPPORT 4439bee6a60SSimon J. Gerraty once += openpgp_trust_init(); 4449bee6a60SSimon J. Gerraty #endif 44513ea0450SMarcin Wojtas return (once); 4465fff9558SSimon J. Gerraty } 4475fff9558SSimon J. Gerraty 44866655411SSimon J. Gerraty #ifdef HAVE_BR_X509_TIME_CHECK 44966655411SSimon J. Gerraty static int 450cc9e6590SSimon J. Gerraty verify_time_cb(void *tctx __unused, 45166655411SSimon J. Gerraty uint32_t not_before_days, uint32_t not_before_seconds, 45266655411SSimon J. Gerraty uint32_t not_after_days, uint32_t not_after_seconds) 45366655411SSimon J. Gerraty { 45466655411SSimon J. Gerraty time_t not_before; 45566655411SSimon J. Gerraty time_t not_after; 45666655411SSimon J. Gerraty int rc; 45766655411SSimon J. Gerraty #ifdef UNIT_TEST 45866655411SSimon J. Gerraty char date[12], nb_date[12], na_date[12]; 45966655411SSimon J. Gerraty #endif 46066655411SSimon J. Gerraty 461*ab4f0a15SSimon J. Gerraty if (enforce_validity) { 46266655411SSimon J. Gerraty not_before = ((not_before_days - X509_DAYS_TO_UTC0) * SECONDS_PER_DAY) + not_before_seconds; 46366655411SSimon J. Gerraty not_after = ((not_after_days - X509_DAYS_TO_UTC0) * SECONDS_PER_DAY) + not_after_seconds; 46466655411SSimon J. Gerraty if (ve_utc < not_before) 46566655411SSimon J. Gerraty rc = -1; 46666655411SSimon J. Gerraty else if (ve_utc > not_after) 46766655411SSimon J. Gerraty rc = 1; 46866655411SSimon J. Gerraty else 46966655411SSimon J. Gerraty rc = 0; 47066655411SSimon J. Gerraty #ifdef UNIT_TEST 47166655411SSimon J. Gerraty printf("notBefore %s notAfter %s date %s rc %d\n", 47266655411SSimon J. Gerraty gdate(nb_date, sizeof(nb_date), not_before), 47366655411SSimon J. Gerraty gdate(na_date, sizeof(na_date), not_after), 47466655411SSimon J. Gerraty gdate(date, sizeof(date), ve_utc), rc); 47566655411SSimon J. Gerraty #endif 476*ab4f0a15SSimon J. Gerraty } else 47766655411SSimon J. Gerraty rc = 0; /* don't fail */ 47866655411SSimon J. Gerraty return rc; 47966655411SSimon J. Gerraty } 48066655411SSimon J. Gerraty #endif 48166655411SSimon J. Gerraty 4825fff9558SSimon J. Gerraty /** 4835fff9558SSimon J. Gerraty * if we can verify the certificate chain in "certs", 4845fff9558SSimon J. Gerraty * return the public key and if "xcp" is !NULL the associated 4855fff9558SSimon J. Gerraty * certificate 4865fff9558SSimon J. Gerraty */ 4875fff9558SSimon J. Gerraty static br_x509_pkey * 4885fff9558SSimon J. Gerraty verify_signer_xcs(br_x509_certificate *xcs, 4895fff9558SSimon J. Gerraty size_t num, 49013ea0450SMarcin Wojtas br_name_element *elts, size_t num_elts, 49113ea0450SMarcin Wojtas anchor_list *anchors) 4925fff9558SSimon J. Gerraty { 4935fff9558SSimon J. Gerraty br_x509_minimal_context mc; 4945fff9558SSimon J. Gerraty br_x509_certificate *xc; 4955fff9558SSimon J. Gerraty size_t u; 4965fff9558SSimon J. Gerraty cert_list chain = VEC_INIT; 4975fff9558SSimon J. Gerraty const br_x509_pkey *tpk; 4985fff9558SSimon J. Gerraty br_x509_pkey *pk; 4995fff9558SSimon J. Gerraty unsigned int usages; 5005fff9558SSimon J. Gerraty int err; 5015fff9558SSimon J. Gerraty 5025fff9558SSimon J. Gerraty DEBUG_PRINTF(5, ("verify_signer: %zu certs in chain\n", num)); 5035fff9558SSimon J. Gerraty VEC_ADDMANY(chain, xcs, num); 5045fff9558SSimon J. Gerraty if (VEC_LEN(chain) == 0) { 5055fff9558SSimon J. Gerraty ve_error_set("ERROR: no/invalid certificate chain\n"); 5065fff9558SSimon J. Gerraty return (NULL); 5075fff9558SSimon J. Gerraty } 5085fff9558SSimon J. Gerraty 5095fff9558SSimon J. Gerraty DEBUG_PRINTF(5, ("verify_signer: %zu trust anchors\n", 51013ea0450SMarcin Wojtas VEC_LEN(*anchors))); 5115fff9558SSimon J. Gerraty 5125fff9558SSimon J. Gerraty br_x509_minimal_init(&mc, &br_sha256_vtable, 51313ea0450SMarcin Wojtas &VEC_ELT(*anchors, 0), 51413ea0450SMarcin Wojtas VEC_LEN(*anchors)); 5155fff9558SSimon J. Gerraty #ifdef VE_ECDSA_SUPPORT 5165fff9558SSimon J. Gerraty br_x509_minimal_set_ecdsa(&mc, 5175fff9558SSimon J. Gerraty &br_ec_prime_i31, &br_ecdsa_i31_vrfy_asn1); 5185fff9558SSimon J. Gerraty #endif 5195fff9558SSimon J. Gerraty #ifdef VE_RSA_SUPPORT 5205fff9558SSimon J. Gerraty br_x509_minimal_set_rsa(&mc, &br_rsa_i31_pkcs1_vrfy); 5215fff9558SSimon J. Gerraty #endif 5225fff9558SSimon J. Gerraty #if defined(UNIT_TEST) && defined(VE_DEPRECATED_RSA_SHA1_SUPPORT) 5235fff9558SSimon J. Gerraty /* This is deprecated! do not enable unless you absoultely have to */ 5245fff9558SSimon J. Gerraty br_x509_minimal_set_hash(&mc, br_sha1_ID, &br_sha1_vtable); 5255fff9558SSimon J. Gerraty #endif 5265fff9558SSimon J. Gerraty br_x509_minimal_set_hash(&mc, br_sha256_ID, &br_sha256_vtable); 5275fff9558SSimon J. Gerraty #ifdef VE_SHA384_SUPPORT 5285fff9558SSimon J. Gerraty br_x509_minimal_set_hash(&mc, br_sha384_ID, &br_sha384_vtable); 5295fff9558SSimon J. Gerraty #endif 5305fff9558SSimon J. Gerraty #ifdef VE_SHA512_SUPPORT 5315fff9558SSimon J. Gerraty br_x509_minimal_set_hash(&mc, br_sha512_ID, &br_sha512_vtable); 5325fff9558SSimon J. Gerraty #endif 5335fff9558SSimon J. Gerraty br_x509_minimal_set_name_elements(&mc, elts, num_elts); 5345fff9558SSimon J. Gerraty 53566655411SSimon J. Gerraty #ifdef HAVE_BR_X509_TIME_CHECK 53666655411SSimon J. Gerraty br_x509_minimal_set_time_callback(&mc, NULL, verify_time_cb); 53766655411SSimon J. Gerraty #else 53866655411SSimon J. Gerraty #if defined(_STANDALONE) || defined(UNIT_TEST) 5395fff9558SSimon J. Gerraty /* 5405fff9558SSimon J. Gerraty * Clock is probably bogus so we use ve_utc. 5415fff9558SSimon J. Gerraty */ 5425fff9558SSimon J. Gerraty mc.days = (ve_utc / SECONDS_PER_DAY) + X509_DAYS_TO_UTC0; 5435fff9558SSimon J. Gerraty mc.seconds = (ve_utc % SECONDS_PER_DAY); 5445fff9558SSimon J. Gerraty #endif 54566655411SSimon J. Gerraty #endif 5465fff9558SSimon J. Gerraty mc.vtable->start_chain(&mc.vtable, NULL); 5475fff9558SSimon J. Gerraty for (u = 0; u < VEC_LEN(chain); u ++) { 5485fff9558SSimon J. Gerraty xc = &VEC_ELT(chain, u); 5495fff9558SSimon J. Gerraty mc.vtable->start_cert(&mc.vtable, xc->data_len); 5505fff9558SSimon J. Gerraty mc.vtable->append(&mc.vtable, xc->data, xc->data_len); 5515fff9558SSimon J. Gerraty mc.vtable->end_cert(&mc.vtable); 5525fff9558SSimon J. Gerraty switch (mc.err) { 5535fff9558SSimon J. Gerraty case 0: 5545fff9558SSimon J. Gerraty case BR_ERR_X509_OK: 5555fff9558SSimon J. Gerraty case BR_ERR_X509_EXPIRED: 5565fff9558SSimon J. Gerraty break; 5575fff9558SSimon J. Gerraty default: 5585fff9558SSimon J. Gerraty printf("u=%zu mc.err=%d\n", u, mc.err); 5595fff9558SSimon J. Gerraty break; 5605fff9558SSimon J. Gerraty } 5615fff9558SSimon J. Gerraty } 5625fff9558SSimon J. Gerraty err = mc.vtable->end_chain(&mc.vtable); 5635fff9558SSimon J. Gerraty pk = NULL; 5645fff9558SSimon J. Gerraty if (err) { 56566655411SSimon J. Gerraty char date[12]; 56666655411SSimon J. Gerraty 56766655411SSimon J. Gerraty switch (err) { 56866655411SSimon J. Gerraty case 54: 56966655411SSimon J. Gerraty ve_error_set("Validation failed, certificate not valid as of %s", 57066655411SSimon J. Gerraty gdate(date, sizeof(date), ve_utc)); 57166655411SSimon J. Gerraty break; 57266655411SSimon J. Gerraty default: 5735fff9558SSimon J. Gerraty ve_error_set("Validation failed, err = %d", err); 57466655411SSimon J. Gerraty break; 57566655411SSimon J. Gerraty } 5765fff9558SSimon J. Gerraty } else { 5775fff9558SSimon J. Gerraty tpk = mc.vtable->get_pkey(&mc.vtable, &usages); 5785fff9558SSimon J. Gerraty if (tpk != NULL) { 5795fff9558SSimon J. Gerraty pk = xpkeydup(tpk); 5805fff9558SSimon J. Gerraty } 5815fff9558SSimon J. Gerraty } 58213ea0450SMarcin Wojtas VEC_CLEAR(chain); 5835fff9558SSimon J. Gerraty return (pk); 5845fff9558SSimon J. Gerraty } 5855fff9558SSimon J. Gerraty 58613ea0450SMarcin Wojtas /* 58713ea0450SMarcin Wojtas * Check if digest of one of the certificates from verified chain 58813ea0450SMarcin Wojtas * is present in the forbidden database. 58913ea0450SMarcin Wojtas * Since UEFI allows to store three types of digests 59013ea0450SMarcin Wojtas * all of them have to be checked separately. 59113ea0450SMarcin Wojtas */ 59213ea0450SMarcin Wojtas static int 59313ea0450SMarcin Wojtas check_forbidden_digests(br_x509_certificate *xcs, size_t num) 59413ea0450SMarcin Wojtas { 59513ea0450SMarcin Wojtas unsigned char sha256_digest[br_sha256_SIZE]; 59613ea0450SMarcin Wojtas unsigned char sha384_digest[br_sha384_SIZE]; 59713ea0450SMarcin Wojtas unsigned char sha512_digest[br_sha512_SIZE]; 59813ea0450SMarcin Wojtas void *tbs; 59913ea0450SMarcin Wojtas hash_data *digest; 60013ea0450SMarcin Wojtas br_hash_compat_context ctx; 60113ea0450SMarcin Wojtas const br_hash_class *md; 60213ea0450SMarcin Wojtas size_t tbs_len, i; 60313ea0450SMarcin Wojtas int have_sha256, have_sha384, have_sha512; 60413ea0450SMarcin Wojtas 60513ea0450SMarcin Wojtas if (VEC_LEN(forbidden_digests) == 0) 60613ea0450SMarcin Wojtas return (0); 60713ea0450SMarcin Wojtas 60813ea0450SMarcin Wojtas /* 60913ea0450SMarcin Wojtas * Iterate through certificates, extract their To-Be-Signed section, 61013ea0450SMarcin Wojtas * and compare its digest against the ones in the forbidden database. 61113ea0450SMarcin Wojtas */ 61213ea0450SMarcin Wojtas while (num--) { 61313ea0450SMarcin Wojtas tbs = X509_to_tbs(xcs[num].data, &tbs_len); 61413ea0450SMarcin Wojtas if (tbs == NULL) { 61513ea0450SMarcin Wojtas printf("Failed to obtain TBS part of certificate\n"); 61613ea0450SMarcin Wojtas return (1); 61713ea0450SMarcin Wojtas } 61813ea0450SMarcin Wojtas have_sha256 = have_sha384 = have_sha512 = 0; 61913ea0450SMarcin Wojtas 62013ea0450SMarcin Wojtas for (i = 0; i < VEC_LEN(forbidden_digests); i++) { 62113ea0450SMarcin Wojtas digest = &VEC_ELT(forbidden_digests, i); 62213ea0450SMarcin Wojtas switch (digest->hash_size) { 62313ea0450SMarcin Wojtas case br_sha256_SIZE: 62413ea0450SMarcin Wojtas if (!have_sha256) { 62513ea0450SMarcin Wojtas have_sha256 = 1; 62613ea0450SMarcin Wojtas md = &br_sha256_vtable; 62713ea0450SMarcin Wojtas md->init(&ctx.vtable); 62813ea0450SMarcin Wojtas md->update(&ctx.vtable, tbs, tbs_len); 62913ea0450SMarcin Wojtas md->out(&ctx.vtable, sha256_digest); 63013ea0450SMarcin Wojtas } 63113ea0450SMarcin Wojtas if (!memcmp(sha256_digest, 63213ea0450SMarcin Wojtas digest->data, 63313ea0450SMarcin Wojtas br_sha256_SIZE)) 63413ea0450SMarcin Wojtas return (1); 63513ea0450SMarcin Wojtas 63613ea0450SMarcin Wojtas break; 63713ea0450SMarcin Wojtas case br_sha384_SIZE: 63813ea0450SMarcin Wojtas if (!have_sha384) { 63913ea0450SMarcin Wojtas have_sha384 = 1; 64013ea0450SMarcin Wojtas md = &br_sha384_vtable; 64113ea0450SMarcin Wojtas md->init(&ctx.vtable); 64213ea0450SMarcin Wojtas md->update(&ctx.vtable, tbs, tbs_len); 64313ea0450SMarcin Wojtas md->out(&ctx.vtable, sha384_digest); 64413ea0450SMarcin Wojtas } 64513ea0450SMarcin Wojtas if (!memcmp(sha384_digest, 64613ea0450SMarcin Wojtas digest->data, 64713ea0450SMarcin Wojtas br_sha384_SIZE)) 64813ea0450SMarcin Wojtas return (1); 64913ea0450SMarcin Wojtas 65013ea0450SMarcin Wojtas break; 65113ea0450SMarcin Wojtas case br_sha512_SIZE: 65213ea0450SMarcin Wojtas if (!have_sha512) { 65313ea0450SMarcin Wojtas have_sha512 = 1; 65413ea0450SMarcin Wojtas md = &br_sha512_vtable; 65513ea0450SMarcin Wojtas md->init(&ctx.vtable); 65613ea0450SMarcin Wojtas md->update(&ctx.vtable, tbs, tbs_len); 65713ea0450SMarcin Wojtas md->out(&ctx.vtable, sha512_digest); 65813ea0450SMarcin Wojtas } 65913ea0450SMarcin Wojtas if (!memcmp(sha512_digest, 66013ea0450SMarcin Wojtas digest->data, 66113ea0450SMarcin Wojtas br_sha512_SIZE)) 66213ea0450SMarcin Wojtas return (1); 66313ea0450SMarcin Wojtas 66413ea0450SMarcin Wojtas break; 66513ea0450SMarcin Wojtas } 66613ea0450SMarcin Wojtas } 66713ea0450SMarcin Wojtas } 66813ea0450SMarcin Wojtas 66913ea0450SMarcin Wojtas return (0); 67013ea0450SMarcin Wojtas } 67113ea0450SMarcin Wojtas 6725fff9558SSimon J. Gerraty static br_x509_pkey * 6735fff9558SSimon J. Gerraty verify_signer(const char *certs, 6745fff9558SSimon J. Gerraty br_name_element *elts, size_t num_elts) 6755fff9558SSimon J. Gerraty { 6765fff9558SSimon J. Gerraty br_x509_certificate *xcs; 6775fff9558SSimon J. Gerraty br_x509_pkey *pk; 6785fff9558SSimon J. Gerraty size_t num; 6795fff9558SSimon J. Gerraty 68013ea0450SMarcin Wojtas pk = NULL; 68113ea0450SMarcin Wojtas 6825fff9558SSimon J. Gerraty ve_trust_init(); 6835fff9558SSimon J. Gerraty xcs = read_certificates(certs, &num); 6845fff9558SSimon J. Gerraty if (xcs == NULL) { 6855fff9558SSimon J. Gerraty ve_error_set("cannot read certificates\n"); 6865fff9558SSimon J. Gerraty return (NULL); 6875fff9558SSimon J. Gerraty } 68813ea0450SMarcin Wojtas 68913ea0450SMarcin Wojtas /* 69013ea0450SMarcin Wojtas * Check if either 69113ea0450SMarcin Wojtas * 1. There is a direct match between cert from forbidden_anchors 69213ea0450SMarcin Wojtas * and a cert from chain. 69313ea0450SMarcin Wojtas * 2. CA that signed the chain is found in forbidden_anchors. 69413ea0450SMarcin Wojtas */ 69513ea0450SMarcin Wojtas if (VEC_LEN(forbidden_anchors) > 0) 69613ea0450SMarcin Wojtas pk = verify_signer_xcs(xcs, num, elts, num_elts, &forbidden_anchors); 69713ea0450SMarcin Wojtas if (pk != NULL) { 69813ea0450SMarcin Wojtas ve_error_set("Certificate is on forbidden list\n"); 69913ea0450SMarcin Wojtas xfreepkey(pk); 70013ea0450SMarcin Wojtas pk = NULL; 70113ea0450SMarcin Wojtas goto out; 70213ea0450SMarcin Wojtas } 70313ea0450SMarcin Wojtas 70413ea0450SMarcin Wojtas pk = verify_signer_xcs(xcs, num, elts, num_elts, &trust_anchors); 70513ea0450SMarcin Wojtas if (pk == NULL) 70613ea0450SMarcin Wojtas goto out; 70713ea0450SMarcin Wojtas 70813ea0450SMarcin Wojtas /* 70913ea0450SMarcin Wojtas * Check if hash of tbs part of any certificate in chain 71013ea0450SMarcin Wojtas * is on the forbidden list. 71113ea0450SMarcin Wojtas */ 71213ea0450SMarcin Wojtas if (check_forbidden_digests(xcs, num)) { 71313ea0450SMarcin Wojtas ve_error_set("Certificate hash is on forbidden list\n"); 71413ea0450SMarcin Wojtas xfreepkey(pk); 71513ea0450SMarcin Wojtas pk = NULL; 71613ea0450SMarcin Wojtas } 71713ea0450SMarcin Wojtas out: 71813ea0450SMarcin Wojtas free_certificates(xcs, num); 7195fff9558SSimon J. Gerraty return (pk); 7205fff9558SSimon J. Gerraty } 7215fff9558SSimon J. Gerraty 7225fff9558SSimon J. Gerraty /** 7235fff9558SSimon J. Gerraty * we need a hex digest including trailing newline below 7245fff9558SSimon J. Gerraty */ 7255fff9558SSimon J. Gerraty char * 7265fff9558SSimon J. Gerraty hexdigest(char *buf, size_t bufsz, unsigned char *foo, size_t foo_len) 7275fff9558SSimon J. Gerraty { 7285fff9558SSimon J. Gerraty char const hex2ascii[] = "0123456789abcdef"; 7295fff9558SSimon J. Gerraty size_t i; 7305fff9558SSimon J. Gerraty 7315fff9558SSimon J. Gerraty /* every binary byte is 2 chars in hex + newline + null */ 7325fff9558SSimon J. Gerraty if (bufsz < (2 * foo_len) + 2) 7335fff9558SSimon J. Gerraty return (NULL); 7345fff9558SSimon J. Gerraty 7355fff9558SSimon J. Gerraty for (i = 0; i < foo_len; i++) { 7365fff9558SSimon J. Gerraty buf[i * 2] = hex2ascii[foo[i] >> 4]; 7375fff9558SSimon J. Gerraty buf[i * 2 + 1] = hex2ascii[foo[i] & 0x0f]; 7385fff9558SSimon J. Gerraty } 7395fff9558SSimon J. Gerraty 7405fff9558SSimon J. Gerraty buf[i * 2] = 0x0A; /* we also want a newline */ 7415fff9558SSimon J. Gerraty buf[i * 2 + 1] = '\0'; 7425fff9558SSimon J. Gerraty 7435fff9558SSimon J. Gerraty return (buf); 7445fff9558SSimon J. Gerraty } 7455fff9558SSimon J. Gerraty 7465fff9558SSimon J. Gerraty /** 7475fff9558SSimon J. Gerraty * @brief 7485fff9558SSimon J. Gerraty * verify file against sigfile using pk 7495fff9558SSimon J. Gerraty * 7505fff9558SSimon J. Gerraty * When we generated the signature in sigfile, 7515fff9558SSimon J. Gerraty * we hashed (sha256) file, and sent that to signing server 7525fff9558SSimon J. Gerraty * which hashed (sha256) that hash. 7535fff9558SSimon J. Gerraty * 7545fff9558SSimon J. Gerraty * To verify we need to replicate that result. 7555fff9558SSimon J. Gerraty * 7565fff9558SSimon J. Gerraty * @param[in] pk 7575fff9558SSimon J. Gerraty * br_x509_pkey 7585fff9558SSimon J. Gerraty * 7595fff9558SSimon J. Gerraty * @paramp[in] file 7605fff9558SSimon J. Gerraty * file to be verified 7615fff9558SSimon J. Gerraty * 7625fff9558SSimon J. Gerraty * @param[in] sigfile 7635fff9558SSimon J. Gerraty * signature (PEM encoded) 7645fff9558SSimon J. Gerraty * 7655fff9558SSimon J. Gerraty * @return NULL on error, otherwise content of file. 7665fff9558SSimon J. Gerraty */ 7675fff9558SSimon J. Gerraty #ifdef VE_ECDSA_SUPPORT 7685fff9558SSimon J. Gerraty static unsigned char * 7695fff9558SSimon J. Gerraty verify_ec(br_x509_pkey *pk, const char *file, const char *sigfile) 7705fff9558SSimon J. Gerraty { 7710e47020fSSimon J. Gerraty #ifdef VE_ECDSA_HASH_AGAIN 7720e47020fSSimon J. Gerraty char *hex, hexbuf[br_sha512_SIZE * 2 + 2]; 7730e47020fSSimon J. Gerraty #endif 7745fff9558SSimon J. Gerraty unsigned char rhbuf[br_sha512_SIZE]; 7755fff9558SSimon J. Gerraty br_sha256_context ctx; 7765fff9558SSimon J. Gerraty unsigned char *fcp, *scp; 7775fff9558SSimon J. Gerraty size_t flen, slen, plen; 7785fff9558SSimon J. Gerraty pem_object *po; 7795fff9558SSimon J. Gerraty const br_ec_impl *ec; 7805fff9558SSimon J. Gerraty br_ecdsa_vrfy vrfy; 7815fff9558SSimon J. Gerraty 7825fff9558SSimon J. Gerraty if ((fcp = read_file(file, &flen)) == NULL) 7835fff9558SSimon J. Gerraty return (NULL); 7845fff9558SSimon J. Gerraty if ((scp = read_file(sigfile, &slen)) == NULL) { 7855fff9558SSimon J. Gerraty free(fcp); 7865fff9558SSimon J. Gerraty return (NULL); 7875fff9558SSimon J. Gerraty } 7885fff9558SSimon J. Gerraty if ((po = decode_pem(scp, slen, &plen)) == NULL) { 7895fff9558SSimon J. Gerraty free(fcp); 7905fff9558SSimon J. Gerraty free(scp); 7915fff9558SSimon J. Gerraty return (NULL); 7925fff9558SSimon J. Gerraty } 7935fff9558SSimon J. Gerraty br_sha256_init(&ctx); 7945fff9558SSimon J. Gerraty br_sha256_update(&ctx, fcp, flen); 7955fff9558SSimon J. Gerraty br_sha256_out(&ctx, rhbuf); 796f9510887SSimon J. Gerraty #ifdef VE_ECDSA_HASH_AGAIN 7975fff9558SSimon J. Gerraty hex = hexdigest(hexbuf, sizeof(hexbuf), rhbuf, br_sha256_SIZE); 7985fff9558SSimon J. Gerraty /* now hash that */ 7995fff9558SSimon J. Gerraty if (hex) { 8005fff9558SSimon J. Gerraty br_sha256_init(&ctx); 8015fff9558SSimon J. Gerraty br_sha256_update(&ctx, hex, strlen(hex)); 8025fff9558SSimon J. Gerraty br_sha256_out(&ctx, rhbuf); 8035fff9558SSimon J. Gerraty } 804f9510887SSimon J. Gerraty #endif 8055fff9558SSimon J. Gerraty ec = br_ec_get_default(); 8065fff9558SSimon J. Gerraty vrfy = br_ecdsa_vrfy_asn1_get_default(); 8075fff9558SSimon J. Gerraty if (!vrfy(ec, rhbuf, br_sha256_SIZE, &pk->key.ec, po->data, 8085fff9558SSimon J. Gerraty po->data_len)) { 8095fff9558SSimon J. Gerraty free(fcp); 8105fff9558SSimon J. Gerraty fcp = NULL; 8115fff9558SSimon J. Gerraty } 8125fff9558SSimon J. Gerraty free(scp); 8135fff9558SSimon J. Gerraty return (fcp); 8145fff9558SSimon J. Gerraty } 8155fff9558SSimon J. Gerraty #endif 8165fff9558SSimon J. Gerraty 8175fff9558SSimon J. Gerraty #if defined(VE_RSA_SUPPORT) || defined(VE_OPENPGP_SUPPORT) 8185fff9558SSimon J. Gerraty /** 8195fff9558SSimon J. Gerraty * @brief verify an rsa digest 8205fff9558SSimon J. Gerraty * 8215fff9558SSimon J. Gerraty * @return 0 on failure 8225fff9558SSimon J. Gerraty */ 8235fff9558SSimon J. Gerraty int 8245fff9558SSimon J. Gerraty verify_rsa_digest (br_rsa_public_key *pkey, 8255fff9558SSimon J. Gerraty const unsigned char *hash_oid, 8265fff9558SSimon J. Gerraty unsigned char *mdata, size_t mlen, 8275fff9558SSimon J. Gerraty unsigned char *sdata, size_t slen) 8285fff9558SSimon J. Gerraty { 8295fff9558SSimon J. Gerraty br_rsa_pkcs1_vrfy vrfy; 8305fff9558SSimon J. Gerraty unsigned char vhbuf[br_sha512_SIZE]; 8315fff9558SSimon J. Gerraty 8325fff9558SSimon J. Gerraty vrfy = br_rsa_pkcs1_vrfy_get_default(); 8335fff9558SSimon J. Gerraty 8345fff9558SSimon J. Gerraty if (!vrfy(sdata, slen, hash_oid, mlen, pkey, vhbuf) || 8355fff9558SSimon J. Gerraty memcmp(vhbuf, mdata, mlen) != 0) { 8365fff9558SSimon J. Gerraty return (0); /* fail */ 8375fff9558SSimon J. Gerraty } 8385fff9558SSimon J. Gerraty return (1); /* ok */ 8395fff9558SSimon J. Gerraty } 8405fff9558SSimon J. Gerraty #endif 8415fff9558SSimon J. Gerraty 8425fff9558SSimon J. Gerraty /** 8435fff9558SSimon J. Gerraty * @brief 8445fff9558SSimon J. Gerraty * verify file against sigfile using pk 8455fff9558SSimon J. Gerraty * 8465fff9558SSimon J. Gerraty * When we generated the signature in sigfile, 8475fff9558SSimon J. Gerraty * we hashed (sha256) file, and sent that to signing server 8485fff9558SSimon J. Gerraty * which hashed (sha256) that hash. 8495fff9558SSimon J. Gerraty * 8505fff9558SSimon J. Gerraty * Or (deprecated) we simply used sha1 hash directly. 8515fff9558SSimon J. Gerraty * 8525fff9558SSimon J. Gerraty * To verify we need to replicate that result. 8535fff9558SSimon J. Gerraty * 8545fff9558SSimon J. Gerraty * @param[in] pk 8555fff9558SSimon J. Gerraty * br_x509_pkey 8565fff9558SSimon J. Gerraty * 8575fff9558SSimon J. Gerraty * @paramp[in] file 8585fff9558SSimon J. Gerraty * file to be verified 8595fff9558SSimon J. Gerraty * 8605fff9558SSimon J. Gerraty * @param[in] sigfile 8615fff9558SSimon J. Gerraty * signature (PEM encoded) 8625fff9558SSimon J. Gerraty * 8635fff9558SSimon J. Gerraty * @return NULL on error, otherwise content of file. 8645fff9558SSimon J. Gerraty */ 8655fff9558SSimon J. Gerraty #ifdef VE_RSA_SUPPORT 8665fff9558SSimon J. Gerraty static unsigned char * 8675fff9558SSimon J. Gerraty verify_rsa(br_x509_pkey *pk, const char *file, const char *sigfile) 8685fff9558SSimon J. Gerraty { 8695fff9558SSimon J. Gerraty unsigned char rhbuf[br_sha512_SIZE]; 8705fff9558SSimon J. Gerraty const unsigned char *hash_oid; 8715fff9558SSimon J. Gerraty const br_hash_class *md; 8725fff9558SSimon J. Gerraty br_hash_compat_context mctx; 8735fff9558SSimon J. Gerraty unsigned char *fcp, *scp; 8745fff9558SSimon J. Gerraty size_t flen, slen, plen, hlen; 8755fff9558SSimon J. Gerraty pem_object *po; 8765fff9558SSimon J. Gerraty 8775fff9558SSimon J. Gerraty if ((fcp = read_file(file, &flen)) == NULL) 8785fff9558SSimon J. Gerraty return (NULL); 8795fff9558SSimon J. Gerraty if ((scp = read_file(sigfile, &slen)) == NULL) { 8805fff9558SSimon J. Gerraty free(fcp); 8815fff9558SSimon J. Gerraty return (NULL); 8825fff9558SSimon J. Gerraty } 8835fff9558SSimon J. Gerraty if ((po = decode_pem(scp, slen, &plen)) == NULL) { 8845fff9558SSimon J. Gerraty free(fcp); 8855fff9558SSimon J. Gerraty free(scp); 8865fff9558SSimon J. Gerraty return (NULL); 8875fff9558SSimon J. Gerraty } 8885fff9558SSimon J. Gerraty 8895fff9558SSimon J. Gerraty switch (po->data_len) { 8905fff9558SSimon J. Gerraty #if defined(UNIT_TEST) && defined(VE_DEPRECATED_RSA_SHA1_SUPPORT) 8915fff9558SSimon J. Gerraty case 256: 8925fff9558SSimon J. Gerraty // this is our old deprecated sig method 8935fff9558SSimon J. Gerraty md = &br_sha1_vtable; 8945fff9558SSimon J. Gerraty hlen = br_sha1_SIZE; 8955fff9558SSimon J. Gerraty hash_oid = BR_HASH_OID_SHA1; 8965fff9558SSimon J. Gerraty break; 8975fff9558SSimon J. Gerraty #endif 8985fff9558SSimon J. Gerraty default: 8995fff9558SSimon J. Gerraty md = &br_sha256_vtable; 9005fff9558SSimon J. Gerraty hlen = br_sha256_SIZE; 9015fff9558SSimon J. Gerraty hash_oid = BR_HASH_OID_SHA256; 9025fff9558SSimon J. Gerraty break; 9035fff9558SSimon J. Gerraty } 9045fff9558SSimon J. Gerraty md->init(&mctx.vtable); 9055fff9558SSimon J. Gerraty md->update(&mctx.vtable, fcp, flen); 9065fff9558SSimon J. Gerraty md->out(&mctx.vtable, rhbuf); 9075fff9558SSimon J. Gerraty if (!verify_rsa_digest(&pk->key.rsa, hash_oid, 9085fff9558SSimon J. Gerraty rhbuf, hlen, po->data, po->data_len)) { 9095fff9558SSimon J. Gerraty free(fcp); 9105fff9558SSimon J. Gerraty fcp = NULL; 9115fff9558SSimon J. Gerraty } 9125fff9558SSimon J. Gerraty free(scp); 9135fff9558SSimon J. Gerraty return (fcp); 9145fff9558SSimon J. Gerraty } 9155fff9558SSimon J. Gerraty #endif 9165fff9558SSimon J. Gerraty 9175fff9558SSimon J. Gerraty /** 9185fff9558SSimon J. Gerraty * @brief 9195fff9558SSimon J. Gerraty * verify a signature and return content of signed file 9205fff9558SSimon J. Gerraty * 9215fff9558SSimon J. Gerraty * @param[in] sigfile 9225fff9558SSimon J. Gerraty * file containing signature 9235fff9558SSimon J. Gerraty * we derrive path of signed file and certificate change from 9245fff9558SSimon J. Gerraty * this. 9255fff9558SSimon J. Gerraty * 9265fff9558SSimon J. Gerraty * @param[in] flags 9275fff9558SSimon J. Gerraty * only bit 1 significant so far 9285fff9558SSimon J. Gerraty * 9295fff9558SSimon J. Gerraty * @return NULL on error otherwise content of signed file 9305fff9558SSimon J. Gerraty */ 9315fff9558SSimon J. Gerraty unsigned char * 9325fff9558SSimon J. Gerraty verify_sig(const char *sigfile, int flags) 9335fff9558SSimon J. Gerraty { 9345fff9558SSimon J. Gerraty br_x509_pkey *pk; 9355fff9558SSimon J. Gerraty br_name_element cn; 9365fff9558SSimon J. Gerraty char cn_buf[80]; 9375fff9558SSimon J. Gerraty unsigned char cn_oid[4]; 9385fff9558SSimon J. Gerraty char pbuf[MAXPATHLEN]; 9395fff9558SSimon J. Gerraty char *cp; 9405fff9558SSimon J. Gerraty unsigned char *ucp; 9415fff9558SSimon J. Gerraty size_t n; 9425fff9558SSimon J. Gerraty 9435fff9558SSimon J. Gerraty DEBUG_PRINTF(5, ("verify_sig: %s\n", sigfile)); 9445fff9558SSimon J. Gerraty n = strlcpy(pbuf, sigfile, sizeof(pbuf)); 9455fff9558SSimon J. Gerraty if (n > (sizeof(pbuf) - 5) || strcmp(&sigfile[n - 3], "sig") != 0) 9465fff9558SSimon J. Gerraty return (NULL); 9475fff9558SSimon J. Gerraty cp = strcpy(&pbuf[n - 3], "certs"); 9485fff9558SSimon J. Gerraty /* 9495fff9558SSimon J. Gerraty * We want the commonName field 9505fff9558SSimon J. Gerraty * the OID we want is 2,5,4,3 - but DER encoded 9515fff9558SSimon J. Gerraty */ 9525fff9558SSimon J. Gerraty cn_oid[0] = 3; 9535fff9558SSimon J. Gerraty cn_oid[1] = 0x55; 9545fff9558SSimon J. Gerraty cn_oid[2] = 4; 9555fff9558SSimon J. Gerraty cn_oid[3] = 3; 9565fff9558SSimon J. Gerraty cn.oid = cn_oid; 9575fff9558SSimon J. Gerraty cn.buf = cn_buf; 9585fff9558SSimon J. Gerraty cn.len = sizeof(cn_buf); 9595fff9558SSimon J. Gerraty 9605fff9558SSimon J. Gerraty pk = verify_signer(pbuf, &cn, 1); 9615fff9558SSimon J. Gerraty if (!pk) { 9625fff9558SSimon J. Gerraty printf("cannot verify: %s: %s\n", pbuf, ve_error_get()); 9635fff9558SSimon J. Gerraty return (NULL); 9645fff9558SSimon J. Gerraty } 9655fff9558SSimon J. Gerraty for (; cp > pbuf; cp--) { 9665fff9558SSimon J. Gerraty if (*cp == '.') { 9675fff9558SSimon J. Gerraty *cp = '\0'; 9685fff9558SSimon J. Gerraty break; 9695fff9558SSimon J. Gerraty } 9705fff9558SSimon J. Gerraty } 9715fff9558SSimon J. Gerraty switch (pk->key_type) { 9725fff9558SSimon J. Gerraty #ifdef VE_ECDSA_SUPPORT 9735fff9558SSimon J. Gerraty case BR_KEYTYPE_EC: 9745fff9558SSimon J. Gerraty ucp = verify_ec(pk, pbuf, sigfile); 9755fff9558SSimon J. Gerraty break; 9765fff9558SSimon J. Gerraty #endif 9775fff9558SSimon J. Gerraty #ifdef VE_RSA_SUPPORT 9785fff9558SSimon J. Gerraty case BR_KEYTYPE_RSA: 9795fff9558SSimon J. Gerraty ucp = verify_rsa(pk, pbuf, sigfile); 9805fff9558SSimon J. Gerraty break; 9815fff9558SSimon J. Gerraty #endif 9825fff9558SSimon J. Gerraty default: 9835fff9558SSimon J. Gerraty ucp = NULL; /* not supported */ 9845fff9558SSimon J. Gerraty } 9855fff9558SSimon J. Gerraty xfreepkey(pk); 9865fff9558SSimon J. Gerraty if (!ucp) { 9875fff9558SSimon J. Gerraty printf("Unverified %s (%s)\n", pbuf, 9885fff9558SSimon J. Gerraty cn.status ? cn_buf : "unknown"); 98966655411SSimon J. Gerraty } else if ((flags & VEF_VERBOSE) != 0) { 9905fff9558SSimon J. Gerraty printf("Verified %s signed by %s\n", pbuf, 9915fff9558SSimon J. Gerraty cn.status ? cn_buf : "someone we trust"); 9925fff9558SSimon J. Gerraty } 9935fff9558SSimon J. Gerraty return (ucp); 9945fff9558SSimon J. Gerraty } 9955fff9558SSimon J. Gerraty 9965fff9558SSimon J. Gerraty 9975fff9558SSimon J. Gerraty /** 9985fff9558SSimon J. Gerraty * @brief verify hash matches 9995fff9558SSimon J. Gerraty * 10005fff9558SSimon J. Gerraty * We have finished hashing a file, 10015fff9558SSimon J. Gerraty * see if we got the desired result. 10025fff9558SSimon J. Gerraty * 10035fff9558SSimon J. Gerraty * @param[in] ctx 10045fff9558SSimon J. Gerraty * pointer to hash context 10055fff9558SSimon J. Gerraty * 10065fff9558SSimon J. Gerraty * @param[in] md 10075fff9558SSimon J. Gerraty * pointer to hash class 10085fff9558SSimon J. Gerraty * 10095fff9558SSimon J. Gerraty * @param[in] path 10105fff9558SSimon J. Gerraty * name of the file we are checking 10115fff9558SSimon J. Gerraty * 10125fff9558SSimon J. Gerraty * @param[in] want 10135fff9558SSimon J. Gerraty * the expected result 10145fff9558SSimon J. Gerraty * 10155fff9558SSimon J. Gerraty * @param[in] hlen 10165fff9558SSimon J. Gerraty * size of hash output 10175fff9558SSimon J. Gerraty * 10185fff9558SSimon J. Gerraty * @return 0 on success 10195fff9558SSimon J. Gerraty */ 10205fff9558SSimon J. Gerraty int 10215fff9558SSimon J. Gerraty ve_check_hash(br_hash_compat_context *ctx, const br_hash_class *md, 10225fff9558SSimon J. Gerraty const char *path, const char *want, size_t hlen) 10235fff9558SSimon J. Gerraty { 10245fff9558SSimon J. Gerraty char hexbuf[br_sha512_SIZE * 2 + 2]; 10255fff9558SSimon J. Gerraty unsigned char hbuf[br_sha512_SIZE]; 10265fff9558SSimon J. Gerraty char *hex; 10275fff9558SSimon J. Gerraty int rc; 10285fff9558SSimon J. Gerraty int n; 10295fff9558SSimon J. Gerraty 10305fff9558SSimon J. Gerraty md->out(&ctx->vtable, hbuf); 10315fff9558SSimon J. Gerraty #ifdef VE_PCR_SUPPORT 103253f151f9SSimon J. Gerraty ve_pcr_update(path, hbuf, hlen); 10335fff9558SSimon J. Gerraty #endif 10345fff9558SSimon J. Gerraty hex = hexdigest(hexbuf, sizeof(hexbuf), hbuf, hlen); 10355fff9558SSimon J. Gerraty if (!hex) 10365fff9558SSimon J. Gerraty return (VE_FINGERPRINT_WRONG); 10375fff9558SSimon J. Gerraty n = 2*hlen; 10385fff9558SSimon J. Gerraty if ((rc = strncmp(hex, want, n))) { 10395fff9558SSimon J. Gerraty ve_error_set("%s: %.*s != %.*s", path, n, hex, n, want); 10405fff9558SSimon J. Gerraty rc = VE_FINGERPRINT_WRONG; 10415fff9558SSimon J. Gerraty } 10425fff9558SSimon J. Gerraty return (rc ? rc : VE_FINGERPRINT_OK); 10435fff9558SSimon J. Gerraty } 10445fff9558SSimon J. Gerraty 10455fff9558SSimon J. Gerraty #ifdef VE_HASH_KAT_STR 10465fff9558SSimon J. Gerraty static int 10475fff9558SSimon J. Gerraty test_hash(const br_hash_class *md, size_t hlen, 10485fff9558SSimon J. Gerraty const char *hname, const char *s, size_t slen, const char *want) 10495fff9558SSimon J. Gerraty { 10505fff9558SSimon J. Gerraty br_hash_compat_context mctx; 10515fff9558SSimon J. Gerraty 10525fff9558SSimon J. Gerraty md->init(&mctx.vtable); 10535fff9558SSimon J. Gerraty md->update(&mctx.vtable, s, slen); 10545fff9558SSimon J. Gerraty return (ve_check_hash(&mctx, md, hname, want, hlen) != VE_FINGERPRINT_OK); 10555fff9558SSimon J. Gerraty } 10565fff9558SSimon J. Gerraty 10575fff9558SSimon J. Gerraty #endif 10585fff9558SSimon J. Gerraty 10595fff9558SSimon J. Gerraty #define ve_test_hash(n, N) \ 10605fff9558SSimon J. Gerraty printf("Testing hash: " #n "\t\t\t\t%s\n", \ 10615fff9558SSimon J. Gerraty test_hash(&br_ ## n ## _vtable, br_ ## n ## _SIZE, #n, \ 10629bee6a60SSimon J. Gerraty VE_HASH_KAT_STR, VE_HASH_KAT_STRLEN(VE_HASH_KAT_STR), \ 10635fff9558SSimon J. Gerraty vh_ ## N) ? "Failed" : "Passed") 10645fff9558SSimon J. Gerraty 10655fff9558SSimon J. Gerraty /** 10665fff9558SSimon J. Gerraty * @brief 10675fff9558SSimon J. Gerraty * run self tests on hash and signature verification 10685fff9558SSimon J. Gerraty * 10695fff9558SSimon J. Gerraty * Test that the hash methods (SHA1 and SHA256) work. 10705fff9558SSimon J. Gerraty * Test that we can verify a certificate for each supported 10715fff9558SSimon J. Gerraty * Root CA. 10725fff9558SSimon J. Gerraty * 10735fff9558SSimon J. Gerraty * @return cached result. 10745fff9558SSimon J. Gerraty */ 10755fff9558SSimon J. Gerraty int 10765fff9558SSimon J. Gerraty ve_self_tests(void) 10775fff9558SSimon J. Gerraty { 10785fff9558SSimon J. Gerraty static int once = -1; 10795fff9558SSimon J. Gerraty #ifdef VERIFY_CERTS_STR 10805fff9558SSimon J. Gerraty br_x509_certificate *xcs; 10815fff9558SSimon J. Gerraty br_x509_pkey *pk; 10825fff9558SSimon J. Gerraty br_name_element cn; 10835fff9558SSimon J. Gerraty char cn_buf[80]; 10845fff9558SSimon J. Gerraty unsigned char cn_oid[4]; 10855fff9558SSimon J. Gerraty size_t num; 10865fff9558SSimon J. Gerraty size_t u; 10875fff9558SSimon J. Gerraty #endif 10885fff9558SSimon J. Gerraty 10895fff9558SSimon J. Gerraty if (once >= 0) 10905fff9558SSimon J. Gerraty return (once); 10915fff9558SSimon J. Gerraty once = 0; 10925fff9558SSimon J. Gerraty 10935fff9558SSimon J. Gerraty DEBUG_PRINTF(5, ("Self tests...\n")); 10945fff9558SSimon J. Gerraty #ifdef VE_HASH_KAT_STR 10955fff9558SSimon J. Gerraty #ifdef VE_SHA1_SUPPORT 10965fff9558SSimon J. Gerraty ve_test_hash(sha1, SHA1); 10975fff9558SSimon J. Gerraty #endif 10985fff9558SSimon J. Gerraty #ifdef VE_SHA256_SUPPORT 10995fff9558SSimon J. Gerraty ve_test_hash(sha256, SHA256); 11005fff9558SSimon J. Gerraty #endif 11015fff9558SSimon J. Gerraty #ifdef VE_SHA384_SUPPORT 11025fff9558SSimon J. Gerraty ve_test_hash(sha384, SHA384); 11035fff9558SSimon J. Gerraty #endif 11045fff9558SSimon J. Gerraty #ifdef VE_SHA512_SUPPORT 11055fff9558SSimon J. Gerraty ve_test_hash(sha512, SHA512); 11065fff9558SSimon J. Gerraty #endif 11075fff9558SSimon J. Gerraty #endif 11085fff9558SSimon J. Gerraty #ifdef VERIFY_CERTS_STR 11095fff9558SSimon J. Gerraty xcs = parse_certificates(__DECONST(unsigned char *, VERIFY_CERTS_STR), 11105fff9558SSimon J. Gerraty sizeof(VERIFY_CERTS_STR), &num); 11119bee6a60SSimon J. Gerraty if (xcs != NULL) { 11125fff9558SSimon J. Gerraty /* 11135fff9558SSimon J. Gerraty * We want the commonName field 11145fff9558SSimon J. Gerraty * the OID we want is 2,5,4,3 - but DER encoded 11155fff9558SSimon J. Gerraty */ 11165fff9558SSimon J. Gerraty cn_oid[0] = 3; 11175fff9558SSimon J. Gerraty cn_oid[1] = 0x55; 11185fff9558SSimon J. Gerraty cn_oid[2] = 4; 11195fff9558SSimon J. Gerraty cn_oid[3] = 3; 11205fff9558SSimon J. Gerraty cn.oid = cn_oid; 11215fff9558SSimon J. Gerraty cn.buf = cn_buf; 11225fff9558SSimon J. Gerraty 11235fff9558SSimon J. Gerraty for (u = 0; u < num; u ++) { 11245fff9558SSimon J. Gerraty cn.len = sizeof(cn_buf); 112513ea0450SMarcin Wojtas if ((pk = verify_signer_xcs(&xcs[u], 1, &cn, 1, &trust_anchors)) != NULL) { 112613ea0450SMarcin Wojtas free_cert_contents(&xcs[u]); 11275fff9558SSimon J. Gerraty once++; 11285fff9558SSimon J. Gerraty printf("Testing verify certificate: %s\tPassed\n", 11295fff9558SSimon J. Gerraty cn.status ? cn_buf : ""); 11305fff9558SSimon J. Gerraty xfreepkey(pk); 11315fff9558SSimon J. Gerraty } 11325fff9558SSimon J. Gerraty } 11335fff9558SSimon J. Gerraty if (!once) 11345fff9558SSimon J. Gerraty printf("Testing verify certificate:\t\t\tFailed\n"); 11355fff9558SSimon J. Gerraty xfree(xcs); 11369bee6a60SSimon J. Gerraty } 11375fff9558SSimon J. Gerraty #endif /* VERIFY_CERTS_STR */ 11385fff9558SSimon J. Gerraty #ifdef VE_OPENPGP_SUPPORT 11395fff9558SSimon J. Gerraty if (!openpgp_self_tests()) 11405fff9558SSimon J. Gerraty once++; 11415fff9558SSimon J. Gerraty #endif 11425fff9558SSimon J. Gerraty return (once); 11435fff9558SSimon J. Gerraty } 1144