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 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 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 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 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 * 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 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 * 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 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 2035fff9558SSimon J. Gerraty static void 2045fff9558SSimon J. Gerraty free_cert_contents(br_x509_certificate *xc) 2055fff9558SSimon J. Gerraty { 2065fff9558SSimon J. Gerraty xfree(xc->data); 2075fff9558SSimon J. Gerraty } 2085fff9558SSimon J. Gerraty 209f9510887SSimon J. Gerraty /* 210f9510887SSimon J. Gerraty * a bit of a dance to get commonName from a certificate 211f9510887SSimon J. Gerraty */ 212f9510887SSimon J. Gerraty static char * 213f9510887SSimon J. Gerraty x509_cn_get(br_x509_certificate *xc, char *buf, size_t len) 214f9510887SSimon J. Gerraty { 215f9510887SSimon J. Gerraty br_x509_minimal_context mc; 216f9510887SSimon J. Gerraty br_name_element cn; 217f9510887SSimon J. Gerraty unsigned char cn_oid[4]; 218f9510887SSimon J. Gerraty int err; 219f9510887SSimon J. Gerraty 220f9510887SSimon J. Gerraty if (buf == NULL) 221f9510887SSimon J. Gerraty return (buf); 222f9510887SSimon J. Gerraty /* 223f9510887SSimon J. Gerraty * We want the commonName field 224f9510887SSimon J. Gerraty * the OID we want is 2,5,4,3 - but DER encoded 225f9510887SSimon J. Gerraty */ 226f9510887SSimon J. Gerraty cn_oid[0] = 3; 227f9510887SSimon J. Gerraty cn_oid[1] = 0x55; 228f9510887SSimon J. Gerraty cn_oid[2] = 4; 229f9510887SSimon J. Gerraty cn_oid[3] = 3; 230f9510887SSimon J. Gerraty cn.oid = cn_oid; 231f9510887SSimon J. Gerraty cn.buf = buf; 232f9510887SSimon J. Gerraty cn.len = len; 233f9510887SSimon J. Gerraty cn.buf[0] = '\0'; 234f9510887SSimon J. Gerraty 235f9510887SSimon J. Gerraty br_x509_minimal_init(&mc, &br_sha256_vtable, NULL, 0); 236f9510887SSimon J. Gerraty br_x509_minimal_set_name_elements(&mc, &cn, 1); 237f9510887SSimon J. Gerraty /* the below actually does the work - updates cn.status */ 238f9510887SSimon J. Gerraty mc.vtable->start_chain(&mc.vtable, NULL); 239f9510887SSimon J. Gerraty mc.vtable->start_cert(&mc.vtable, xc->data_len); 240f9510887SSimon J. Gerraty mc.vtable->append(&mc.vtable, xc->data, xc->data_len); 241f9510887SSimon J. Gerraty mc.vtable->end_cert(&mc.vtable); 24256f3f2d2SSimon J. Gerraty /* we don't actually care about cert status - just its name */ 243f9510887SSimon J. Gerraty err = mc.vtable->end_chain(&mc.vtable); 2449c3478cbSSimon J. Gerraty (void)err; /* keep compiler quiet */ 245f9510887SSimon J. Gerraty 2469c3478cbSSimon J. Gerraty if (cn.status <= 0) 247f9510887SSimon J. Gerraty buf = NULL; 248f9510887SSimon J. Gerraty return (buf); 249f9510887SSimon J. Gerraty } 250f9510887SSimon J. Gerraty 25113ea0450SMarcin Wojtas /* ASN parsing related defines */ 25213ea0450SMarcin Wojtas #define ASN1_PRIMITIVE_TAG 0x1F 25313ea0450SMarcin Wojtas #define ASN1_INF_LENGTH 0x80 25413ea0450SMarcin Wojtas #define ASN1_LENGTH_MASK 0x7F 25513ea0450SMarcin Wojtas 25613ea0450SMarcin Wojtas /* 25713ea0450SMarcin Wojtas * Get TBS part of certificate. 25813ea0450SMarcin Wojtas * Since BearSSL doesn't provide any API to do this, 25913ea0450SMarcin Wojtas * it has to be implemented here. 2605fff9558SSimon J. Gerraty */ 26113ea0450SMarcin Wojtas static void* 26213ea0450SMarcin Wojtas X509_to_tbs(unsigned char* cert, size_t* output_size) 26313ea0450SMarcin Wojtas { 26413ea0450SMarcin Wojtas unsigned char *result; 26513ea0450SMarcin Wojtas size_t tbs_size; 26613ea0450SMarcin Wojtas int size, i; 26713ea0450SMarcin Wojtas 26813ea0450SMarcin Wojtas if (cert == NULL) 26913ea0450SMarcin Wojtas return (NULL); 27013ea0450SMarcin Wojtas 27113ea0450SMarcin Wojtas /* Strip two sequences to get to the TBS section */ 27213ea0450SMarcin Wojtas for (i = 0; i < 2; i++) { 27313ea0450SMarcin Wojtas /* 27413ea0450SMarcin Wojtas * XXX: We don't need to support extended tags since 27513ea0450SMarcin Wojtas * they should not be present in certificates. 27613ea0450SMarcin Wojtas */ 27713ea0450SMarcin Wojtas if ((*cert & ASN1_PRIMITIVE_TAG) == ASN1_PRIMITIVE_TAG) 27813ea0450SMarcin Wojtas return (NULL); 27913ea0450SMarcin Wojtas 28013ea0450SMarcin Wojtas cert++; 28113ea0450SMarcin Wojtas 28213ea0450SMarcin Wojtas if (*cert == ASN1_INF_LENGTH) 28313ea0450SMarcin Wojtas return (NULL); 28413ea0450SMarcin Wojtas 28513ea0450SMarcin Wojtas size = *cert & ASN1_LENGTH_MASK; 28613ea0450SMarcin Wojtas tbs_size = 0; 28713ea0450SMarcin Wojtas 28813ea0450SMarcin Wojtas /* Size can either be stored on a single or multiple bytes */ 28913ea0450SMarcin Wojtas if (*cert & (ASN1_LENGTH_MASK + 1)) { 29013ea0450SMarcin Wojtas cert++; 29113ea0450SMarcin Wojtas while (*cert == 0 && size > 0) { 29213ea0450SMarcin Wojtas cert++; 29313ea0450SMarcin Wojtas size--; 29413ea0450SMarcin Wojtas } 29513ea0450SMarcin Wojtas while (size-- > 0) { 29613ea0450SMarcin Wojtas tbs_size <<= 8; 29713ea0450SMarcin Wojtas tbs_size |= *(cert++); 29813ea0450SMarcin Wojtas } 29913ea0450SMarcin Wojtas } 30013ea0450SMarcin Wojtas if (i == 0) 30113ea0450SMarcin Wojtas result = cert; 30213ea0450SMarcin Wojtas } 30313ea0450SMarcin Wojtas tbs_size += (cert - result); 30413ea0450SMarcin Wojtas 30513ea0450SMarcin Wojtas if (output_size != NULL) 30613ea0450SMarcin Wojtas *output_size = tbs_size; 30713ea0450SMarcin Wojtas 30813ea0450SMarcin Wojtas return (result); 30913ea0450SMarcin Wojtas } 31013ea0450SMarcin Wojtas 31113ea0450SMarcin Wojtas void 31213ea0450SMarcin Wojtas ve_forbidden_digest_add(hash_data *digest, size_t num) 31313ea0450SMarcin Wojtas { 31413ea0450SMarcin Wojtas while (num--) 31513ea0450SMarcin Wojtas VEC_ADD(forbidden_digests, digest[num]); 31613ea0450SMarcin Wojtas } 31713ea0450SMarcin Wojtas 31813ea0450SMarcin Wojtas static size_t 319f9510887SSimon J. Gerraty ve_anchors_add(br_x509_certificate *xcs, size_t num, anchor_list *anchors, 32018e2fbc0SSimon J. Gerraty const char *anchors_name) 3215fff9558SSimon J. Gerraty { 3225fff9558SSimon J. Gerraty br_x509_trust_anchor ta; 3235fff9558SSimon J. Gerraty size_t u; 3245fff9558SSimon J. Gerraty 3255fff9558SSimon J. Gerraty for (u = 0; u < num; u++) { 3265fff9558SSimon J. Gerraty if (certificate_to_trust_anchor_inner(&ta, &xcs[u]) < 0) { 3275fff9558SSimon J. Gerraty break; 3285fff9558SSimon J. Gerraty } 32913ea0450SMarcin Wojtas VEC_ADD(*anchors, ta); 330f9510887SSimon J. Gerraty if (anchor_verbose && anchors_name) { 331f9510887SSimon J. Gerraty char buf[64]; 332f9510887SSimon J. Gerraty char *cp; 333f9510887SSimon J. Gerraty 334f9510887SSimon J. Gerraty cp = x509_cn_get(&xcs[u], buf, sizeof(buf)); 335f9510887SSimon J. Gerraty if (cp) { 336f9510887SSimon J. Gerraty printf("x509_anchor(%s) %s\n", cp, anchors_name); 337f9510887SSimon J. Gerraty } 338f9510887SSimon J. Gerraty } 3395fff9558SSimon J. Gerraty } 3405fff9558SSimon J. Gerraty return (u); 3415fff9558SSimon J. Gerraty } 3425fff9558SSimon J. Gerraty 3435fff9558SSimon J. Gerraty /** 3445fff9558SSimon J. Gerraty * @brief 34513ea0450SMarcin Wojtas * add certs to our trust store 34613ea0450SMarcin Wojtas */ 34713ea0450SMarcin Wojtas size_t 34813ea0450SMarcin Wojtas ve_trust_anchors_add(br_x509_certificate *xcs, size_t num) 34913ea0450SMarcin Wojtas { 350f9510887SSimon J. Gerraty return (ve_anchors_add(xcs, num, &trust_anchors, "trusted")); 35113ea0450SMarcin Wojtas } 35213ea0450SMarcin Wojtas 35313ea0450SMarcin Wojtas size_t 35413ea0450SMarcin Wojtas ve_forbidden_anchors_add(br_x509_certificate *xcs, size_t num) 35513ea0450SMarcin Wojtas { 356f9510887SSimon J. Gerraty return (ve_anchors_add(xcs, num, &forbidden_anchors, "forbidden")); 357f9510887SSimon J. Gerraty } 358f9510887SSimon J. Gerraty 359f9510887SSimon J. Gerraty 360f9510887SSimon J. Gerraty /** 361f9510887SSimon J. Gerraty * @brief add trust anchors in buf 362f9510887SSimon J. Gerraty * 363f9510887SSimon J. Gerraty * Assume buf contains x509 certificates, but if not and 364f9510887SSimon J. Gerraty * we support OpenPGP try adding as that. 365f9510887SSimon J. Gerraty * 366f9510887SSimon J. Gerraty * @return number of anchors added 367f9510887SSimon J. Gerraty */ 368f9510887SSimon J. Gerraty size_t 369f9510887SSimon J. Gerraty ve_trust_anchors_add_buf(unsigned char *buf, size_t len) 370f9510887SSimon J. Gerraty { 371f9510887SSimon J. Gerraty br_x509_certificate *xcs; 372f9510887SSimon J. Gerraty size_t num; 373f9510887SSimon J. Gerraty 374f9510887SSimon J. Gerraty num = 0; 375f9510887SSimon J. Gerraty xcs = parse_certificates(buf, len, &num); 376f9510887SSimon J. Gerraty if (xcs != NULL) { 377f9510887SSimon J. Gerraty num = ve_trust_anchors_add(xcs, num); 378f9510887SSimon J. Gerraty #ifdef VE_OPENPGP_SUPPORT 379f9510887SSimon J. Gerraty } else { 380f9510887SSimon J. Gerraty num = openpgp_trust_add_buf(buf, len); 381f9510887SSimon J. Gerraty #endif 382f9510887SSimon J. Gerraty } 383f9510887SSimon J. Gerraty return (num); 384f9510887SSimon J. Gerraty } 385f9510887SSimon J. Gerraty 386f9510887SSimon J. Gerraty /** 387f9510887SSimon J. Gerraty * @brief revoke trust anchors in buf 388f9510887SSimon J. Gerraty * 389f9510887SSimon J. Gerraty * Assume buf contains x509 certificates, but if not and 390f9510887SSimon J. Gerraty * we support OpenPGP try revoking keyId 391f9510887SSimon J. Gerraty * 392f9510887SSimon J. Gerraty * @return number of anchors revoked 393f9510887SSimon J. Gerraty */ 394f9510887SSimon J. Gerraty size_t 395f9510887SSimon J. Gerraty ve_trust_anchors_revoke(unsigned char *buf, size_t len) 396f9510887SSimon J. Gerraty { 397f9510887SSimon J. Gerraty br_x509_certificate *xcs; 398f9510887SSimon J. Gerraty size_t num; 399f9510887SSimon J. Gerraty 400f9510887SSimon J. Gerraty num = 0; 401f9510887SSimon J. Gerraty xcs = parse_certificates(buf, len, &num); 402f9510887SSimon J. Gerraty if (xcs != NULL) { 403f9510887SSimon J. Gerraty num = ve_forbidden_anchors_add(xcs, num); 404f9510887SSimon J. Gerraty #ifdef VE_OPENPGP_SUPPORT 405f9510887SSimon J. Gerraty } else { 406f9510887SSimon J. Gerraty if (buf[len - 1] == '\n') 407f9510887SSimon J. Gerraty buf[len - 1] = '\0'; 408f9510887SSimon J. Gerraty num = openpgp_trust_revoke((char *)buf); 409f9510887SSimon J. Gerraty #endif 410f9510887SSimon J. Gerraty } 411f9510887SSimon J. Gerraty return (num); 41213ea0450SMarcin Wojtas } 41313ea0450SMarcin Wojtas 41413ea0450SMarcin Wojtas /** 41513ea0450SMarcin Wojtas * @brief 4165fff9558SSimon J. Gerraty * initialize our trust_anchors from ta_PEM 4175fff9558SSimon J. Gerraty */ 4185fff9558SSimon J. Gerraty int 4195fff9558SSimon J. Gerraty ve_trust_init(void) 4205fff9558SSimon J. Gerraty { 4215fff9558SSimon J. Gerraty static int once = -1; 4225fff9558SSimon J. Gerraty 4235fff9558SSimon J. Gerraty if (once >= 0) 4245fff9558SSimon J. Gerraty return (once); 4253ae2a848SSimon J. Gerraty once = 0; /* to be sure */ 4265fff9558SSimon J. Gerraty #ifdef BUILD_UTC 42753f151f9SSimon J. Gerraty ve_utc_set(BUILD_UTC); /* ensure sanity */ 4285fff9558SSimon J. Gerraty #endif 42953f151f9SSimon J. Gerraty ve_utc_set(time(NULL)); 4305fff9558SSimon J. Gerraty ve_error_set(NULL); /* make sure it is empty */ 4315fff9558SSimon J. Gerraty #ifdef VE_PCR_SUPPORT 4325fff9558SSimon J. Gerraty ve_pcr_init(); 4335fff9558SSimon J. Gerraty #endif 4345fff9558SSimon J. Gerraty 4355fff9558SSimon J. Gerraty #ifdef TRUST_ANCHOR_STR 436e6ef5042SWojciech Macek if (TRUST_ANCHOR_STR != NULL && strlen(TRUST_ANCHOR_STR) != 0ul) 437e6ef5042SWojciech Macek ve_trust_anchors_add_buf(__DECONST(unsigned char *, 438e6ef5042SWojciech Macek TRUST_ANCHOR_STR), sizeof(TRUST_ANCHOR_STR)); 4395fff9558SSimon J. Gerraty #endif 44013ea0450SMarcin Wojtas once = (int) VEC_LEN(trust_anchors); 4419bee6a60SSimon J. Gerraty #ifdef VE_OPENPGP_SUPPORT 4429bee6a60SSimon J. Gerraty once += openpgp_trust_init(); 4439bee6a60SSimon J. Gerraty #endif 44413ea0450SMarcin Wojtas return (once); 4455fff9558SSimon J. Gerraty } 4465fff9558SSimon J. Gerraty 44766655411SSimon J. Gerraty #ifdef HAVE_BR_X509_TIME_CHECK 44866655411SSimon J. Gerraty static int 449cc9e6590SSimon J. Gerraty verify_time_cb(void *tctx __unused, 45066655411SSimon J. Gerraty uint32_t not_before_days, uint32_t not_before_seconds, 45166655411SSimon J. Gerraty uint32_t not_after_days, uint32_t not_after_seconds) 45266655411SSimon J. Gerraty { 45366655411SSimon J. Gerraty time_t not_before; 45466655411SSimon J. Gerraty time_t not_after; 45566655411SSimon J. Gerraty int rc; 45666655411SSimon J. Gerraty #ifdef UNIT_TEST 45766655411SSimon J. Gerraty char date[12], nb_date[12], na_date[12]; 45866655411SSimon J. Gerraty #endif 45966655411SSimon J. Gerraty 460ab4f0a15SSimon J. Gerraty if (enforce_validity) { 46166655411SSimon J. Gerraty not_before = ((not_before_days - X509_DAYS_TO_UTC0) * SECONDS_PER_DAY) + not_before_seconds; 46266655411SSimon J. Gerraty not_after = ((not_after_days - X509_DAYS_TO_UTC0) * SECONDS_PER_DAY) + not_after_seconds; 46366655411SSimon J. Gerraty if (ve_utc < not_before) 46466655411SSimon J. Gerraty rc = -1; 46566655411SSimon J. Gerraty else if (ve_utc > not_after) 46666655411SSimon J. Gerraty rc = 1; 46766655411SSimon J. Gerraty else 46866655411SSimon J. Gerraty rc = 0; 46966655411SSimon J. Gerraty #ifdef UNIT_TEST 47066655411SSimon J. Gerraty printf("notBefore %s notAfter %s date %s rc %d\n", 47166655411SSimon J. Gerraty gdate(nb_date, sizeof(nb_date), not_before), 47266655411SSimon J. Gerraty gdate(na_date, sizeof(na_date), not_after), 47366655411SSimon J. Gerraty gdate(date, sizeof(date), ve_utc), rc); 47466655411SSimon J. Gerraty #endif 475ab4f0a15SSimon J. Gerraty } else 47666655411SSimon J. Gerraty rc = 0; /* don't fail */ 47766655411SSimon J. Gerraty return rc; 47866655411SSimon J. Gerraty } 47966655411SSimon J. Gerraty #endif 48066655411SSimon J. Gerraty 4815fff9558SSimon J. Gerraty /** 4825fff9558SSimon J. Gerraty * if we can verify the certificate chain in "certs", 4835fff9558SSimon J. Gerraty * return the public key and if "xcp" is !NULL the associated 4845fff9558SSimon J. Gerraty * certificate 4855fff9558SSimon J. Gerraty */ 4865fff9558SSimon J. Gerraty static br_x509_pkey * 4875fff9558SSimon J. Gerraty verify_signer_xcs(br_x509_certificate *xcs, 4885fff9558SSimon J. Gerraty size_t num, 48913ea0450SMarcin Wojtas br_name_element *elts, size_t num_elts, 49013ea0450SMarcin Wojtas anchor_list *anchors) 4915fff9558SSimon J. Gerraty { 4925fff9558SSimon J. Gerraty br_x509_minimal_context mc; 4935fff9558SSimon J. Gerraty br_x509_certificate *xc; 4945fff9558SSimon J. Gerraty size_t u; 4955fff9558SSimon J. Gerraty cert_list chain = VEC_INIT; 4965fff9558SSimon J. Gerraty const br_x509_pkey *tpk; 4975fff9558SSimon J. Gerraty br_x509_pkey *pk; 4985fff9558SSimon J. Gerraty unsigned int usages; 4995fff9558SSimon J. Gerraty int err; 5005fff9558SSimon J. Gerraty 5015fff9558SSimon J. Gerraty DEBUG_PRINTF(5, ("verify_signer: %zu certs in chain\n", num)); 5025fff9558SSimon J. Gerraty VEC_ADDMANY(chain, xcs, num); 5035fff9558SSimon J. Gerraty if (VEC_LEN(chain) == 0) { 5045fff9558SSimon J. Gerraty ve_error_set("ERROR: no/invalid certificate chain\n"); 5055fff9558SSimon J. Gerraty return (NULL); 5065fff9558SSimon J. Gerraty } 5075fff9558SSimon J. Gerraty 5085fff9558SSimon J. Gerraty DEBUG_PRINTF(5, ("verify_signer: %zu trust anchors\n", 50913ea0450SMarcin Wojtas VEC_LEN(*anchors))); 5105fff9558SSimon J. Gerraty 5115fff9558SSimon J. Gerraty br_x509_minimal_init(&mc, &br_sha256_vtable, 51213ea0450SMarcin Wojtas &VEC_ELT(*anchors, 0), 51313ea0450SMarcin Wojtas VEC_LEN(*anchors)); 5145fff9558SSimon J. Gerraty #ifdef VE_ECDSA_SUPPORT 5155fff9558SSimon J. Gerraty br_x509_minimal_set_ecdsa(&mc, 5165fff9558SSimon J. Gerraty &br_ec_prime_i31, &br_ecdsa_i31_vrfy_asn1); 5175fff9558SSimon J. Gerraty #endif 5185fff9558SSimon J. Gerraty #ifdef VE_RSA_SUPPORT 5195fff9558SSimon J. Gerraty br_x509_minimal_set_rsa(&mc, &br_rsa_i31_pkcs1_vrfy); 5205fff9558SSimon J. Gerraty #endif 5215fff9558SSimon J. Gerraty #if defined(UNIT_TEST) && defined(VE_DEPRECATED_RSA_SHA1_SUPPORT) 522cb25444cSElyes HAOUAS /* This is deprecated! do not enable unless you absolutely have to */ 5235fff9558SSimon J. Gerraty br_x509_minimal_set_hash(&mc, br_sha1_ID, &br_sha1_vtable); 5245fff9558SSimon J. Gerraty #endif 5255fff9558SSimon J. Gerraty br_x509_minimal_set_hash(&mc, br_sha256_ID, &br_sha256_vtable); 5265fff9558SSimon J. Gerraty #ifdef VE_SHA384_SUPPORT 5275fff9558SSimon J. Gerraty br_x509_minimal_set_hash(&mc, br_sha384_ID, &br_sha384_vtable); 5285fff9558SSimon J. Gerraty #endif 5295fff9558SSimon J. Gerraty #ifdef VE_SHA512_SUPPORT 5305fff9558SSimon J. Gerraty br_x509_minimal_set_hash(&mc, br_sha512_ID, &br_sha512_vtable); 5315fff9558SSimon J. Gerraty #endif 5325fff9558SSimon J. Gerraty br_x509_minimal_set_name_elements(&mc, elts, num_elts); 5335fff9558SSimon J. Gerraty 53466655411SSimon J. Gerraty #ifdef HAVE_BR_X509_TIME_CHECK 53566655411SSimon J. Gerraty br_x509_minimal_set_time_callback(&mc, NULL, verify_time_cb); 53666655411SSimon J. Gerraty #else 53766655411SSimon J. Gerraty #if defined(_STANDALONE) || defined(UNIT_TEST) 5385fff9558SSimon J. Gerraty /* 5395fff9558SSimon J. Gerraty * Clock is probably bogus so we use ve_utc. 5405fff9558SSimon J. Gerraty */ 5415fff9558SSimon J. Gerraty mc.days = (ve_utc / SECONDS_PER_DAY) + X509_DAYS_TO_UTC0; 5425fff9558SSimon J. Gerraty mc.seconds = (ve_utc % SECONDS_PER_DAY); 5435fff9558SSimon J. Gerraty #endif 54466655411SSimon J. Gerraty #endif 5455fff9558SSimon J. Gerraty mc.vtable->start_chain(&mc.vtable, NULL); 5465fff9558SSimon J. Gerraty for (u = 0; u < VEC_LEN(chain); u ++) { 5475fff9558SSimon J. Gerraty xc = &VEC_ELT(chain, u); 5485fff9558SSimon J. Gerraty mc.vtable->start_cert(&mc.vtable, xc->data_len); 5495fff9558SSimon J. Gerraty mc.vtable->append(&mc.vtable, xc->data, xc->data_len); 5505fff9558SSimon J. Gerraty mc.vtable->end_cert(&mc.vtable); 5515fff9558SSimon J. Gerraty switch (mc.err) { 5525fff9558SSimon J. Gerraty case 0: 5535fff9558SSimon J. Gerraty case BR_ERR_X509_OK: 5545fff9558SSimon J. Gerraty case BR_ERR_X509_EXPIRED: 5555fff9558SSimon J. Gerraty break; 5565fff9558SSimon J. Gerraty default: 5575fff9558SSimon J. Gerraty printf("u=%zu mc.err=%d\n", u, mc.err); 5585fff9558SSimon J. Gerraty break; 5595fff9558SSimon J. Gerraty } 5605fff9558SSimon J. Gerraty } 5615fff9558SSimon J. Gerraty err = mc.vtable->end_chain(&mc.vtable); 5625fff9558SSimon J. Gerraty pk = NULL; 5635fff9558SSimon J. Gerraty if (err) { 56466655411SSimon J. Gerraty char date[12]; 56566655411SSimon J. Gerraty 56666655411SSimon J. Gerraty switch (err) { 56766655411SSimon J. Gerraty case 54: 56866655411SSimon J. Gerraty ve_error_set("Validation failed, certificate not valid as of %s", 56966655411SSimon J. Gerraty gdate(date, sizeof(date), ve_utc)); 57066655411SSimon J. Gerraty break; 571*4b9d6057SStéphane Rochoy default: { 572*4b9d6057SStéphane Rochoy const char *err_desc = NULL; 573*4b9d6057SStéphane Rochoy const char *err_name = find_error_name(err, &err_desc); 574*4b9d6057SStéphane Rochoy 575*4b9d6057SStéphane Rochoy if (err_name == NULL) 576*4b9d6057SStéphane Rochoy ve_error_set("Validation failed, err = %d", 577*4b9d6057SStéphane Rochoy err); 578*4b9d6057SStéphane Rochoy else 579*4b9d6057SStéphane Rochoy ve_error_set("Validation failed, %s (%s)", 580*4b9d6057SStéphane Rochoy err_desc, err_name); 581*4b9d6057SStéphane Rochoy break; } 58266655411SSimon J. Gerraty } 5835fff9558SSimon J. Gerraty } else { 5845fff9558SSimon J. Gerraty tpk = mc.vtable->get_pkey(&mc.vtable, &usages); 5855fff9558SSimon J. Gerraty if (tpk != NULL) { 5865fff9558SSimon J. Gerraty pk = xpkeydup(tpk); 5875fff9558SSimon J. Gerraty } 5885fff9558SSimon J. Gerraty } 58913ea0450SMarcin Wojtas VEC_CLEAR(chain); 5905fff9558SSimon J. Gerraty return (pk); 5915fff9558SSimon J. Gerraty } 5925fff9558SSimon J. Gerraty 59313ea0450SMarcin Wojtas /* 59413ea0450SMarcin Wojtas * Check if digest of one of the certificates from verified chain 59513ea0450SMarcin Wojtas * is present in the forbidden database. 59613ea0450SMarcin Wojtas * Since UEFI allows to store three types of digests 59713ea0450SMarcin Wojtas * all of them have to be checked separately. 59813ea0450SMarcin Wojtas */ 59913ea0450SMarcin Wojtas static int 60013ea0450SMarcin Wojtas check_forbidden_digests(br_x509_certificate *xcs, size_t num) 60113ea0450SMarcin Wojtas { 60213ea0450SMarcin Wojtas unsigned char sha256_digest[br_sha256_SIZE]; 60313ea0450SMarcin Wojtas unsigned char sha384_digest[br_sha384_SIZE]; 60413ea0450SMarcin Wojtas unsigned char sha512_digest[br_sha512_SIZE]; 60513ea0450SMarcin Wojtas void *tbs; 60613ea0450SMarcin Wojtas hash_data *digest; 60713ea0450SMarcin Wojtas br_hash_compat_context ctx; 60813ea0450SMarcin Wojtas const br_hash_class *md; 60913ea0450SMarcin Wojtas size_t tbs_len, i; 61013ea0450SMarcin Wojtas int have_sha256, have_sha384, have_sha512; 61113ea0450SMarcin Wojtas 61213ea0450SMarcin Wojtas if (VEC_LEN(forbidden_digests) == 0) 61313ea0450SMarcin Wojtas return (0); 61413ea0450SMarcin Wojtas 61513ea0450SMarcin Wojtas /* 61613ea0450SMarcin Wojtas * Iterate through certificates, extract their To-Be-Signed section, 61713ea0450SMarcin Wojtas * and compare its digest against the ones in the forbidden database. 61813ea0450SMarcin Wojtas */ 61913ea0450SMarcin Wojtas while (num--) { 62013ea0450SMarcin Wojtas tbs = X509_to_tbs(xcs[num].data, &tbs_len); 62113ea0450SMarcin Wojtas if (tbs == NULL) { 62213ea0450SMarcin Wojtas printf("Failed to obtain TBS part of certificate\n"); 62313ea0450SMarcin Wojtas return (1); 62413ea0450SMarcin Wojtas } 62513ea0450SMarcin Wojtas have_sha256 = have_sha384 = have_sha512 = 0; 62613ea0450SMarcin Wojtas 62713ea0450SMarcin Wojtas for (i = 0; i < VEC_LEN(forbidden_digests); i++) { 62813ea0450SMarcin Wojtas digest = &VEC_ELT(forbidden_digests, i); 62913ea0450SMarcin Wojtas switch (digest->hash_size) { 63013ea0450SMarcin Wojtas case br_sha256_SIZE: 63113ea0450SMarcin Wojtas if (!have_sha256) { 63213ea0450SMarcin Wojtas have_sha256 = 1; 63313ea0450SMarcin Wojtas md = &br_sha256_vtable; 63413ea0450SMarcin Wojtas md->init(&ctx.vtable); 63513ea0450SMarcin Wojtas md->update(&ctx.vtable, tbs, tbs_len); 63613ea0450SMarcin Wojtas md->out(&ctx.vtable, sha256_digest); 63713ea0450SMarcin Wojtas } 63813ea0450SMarcin Wojtas if (!memcmp(sha256_digest, 63913ea0450SMarcin Wojtas digest->data, 64013ea0450SMarcin Wojtas br_sha256_SIZE)) 64113ea0450SMarcin Wojtas return (1); 64213ea0450SMarcin Wojtas 64313ea0450SMarcin Wojtas break; 64413ea0450SMarcin Wojtas case br_sha384_SIZE: 64513ea0450SMarcin Wojtas if (!have_sha384) { 64613ea0450SMarcin Wojtas have_sha384 = 1; 64713ea0450SMarcin Wojtas md = &br_sha384_vtable; 64813ea0450SMarcin Wojtas md->init(&ctx.vtable); 64913ea0450SMarcin Wojtas md->update(&ctx.vtable, tbs, tbs_len); 65013ea0450SMarcin Wojtas md->out(&ctx.vtable, sha384_digest); 65113ea0450SMarcin Wojtas } 65213ea0450SMarcin Wojtas if (!memcmp(sha384_digest, 65313ea0450SMarcin Wojtas digest->data, 65413ea0450SMarcin Wojtas br_sha384_SIZE)) 65513ea0450SMarcin Wojtas return (1); 65613ea0450SMarcin Wojtas 65713ea0450SMarcin Wojtas break; 65813ea0450SMarcin Wojtas case br_sha512_SIZE: 65913ea0450SMarcin Wojtas if (!have_sha512) { 66013ea0450SMarcin Wojtas have_sha512 = 1; 66113ea0450SMarcin Wojtas md = &br_sha512_vtable; 66213ea0450SMarcin Wojtas md->init(&ctx.vtable); 66313ea0450SMarcin Wojtas md->update(&ctx.vtable, tbs, tbs_len); 66413ea0450SMarcin Wojtas md->out(&ctx.vtable, sha512_digest); 66513ea0450SMarcin Wojtas } 66613ea0450SMarcin Wojtas if (!memcmp(sha512_digest, 66713ea0450SMarcin Wojtas digest->data, 66813ea0450SMarcin Wojtas br_sha512_SIZE)) 66913ea0450SMarcin Wojtas return (1); 67013ea0450SMarcin Wojtas 67113ea0450SMarcin Wojtas break; 67213ea0450SMarcin Wojtas } 67313ea0450SMarcin Wojtas } 67413ea0450SMarcin Wojtas } 67513ea0450SMarcin Wojtas 67613ea0450SMarcin Wojtas return (0); 67713ea0450SMarcin Wojtas } 67813ea0450SMarcin Wojtas 6795fff9558SSimon J. Gerraty static br_x509_pkey * 6805fff9558SSimon J. Gerraty verify_signer(const char *certs, 6815fff9558SSimon J. Gerraty br_name_element *elts, size_t num_elts) 6825fff9558SSimon J. Gerraty { 6835fff9558SSimon J. Gerraty br_x509_certificate *xcs; 6845fff9558SSimon J. Gerraty br_x509_pkey *pk; 6855fff9558SSimon J. Gerraty size_t num; 6865fff9558SSimon J. Gerraty 68713ea0450SMarcin Wojtas pk = NULL; 68813ea0450SMarcin Wojtas 6895fff9558SSimon J. Gerraty ve_trust_init(); 6905fff9558SSimon J. Gerraty xcs = read_certificates(certs, &num); 6915fff9558SSimon J. Gerraty if (xcs == NULL) { 6925fff9558SSimon J. Gerraty ve_error_set("cannot read certificates\n"); 6935fff9558SSimon J. Gerraty return (NULL); 6945fff9558SSimon J. Gerraty } 69513ea0450SMarcin Wojtas 69613ea0450SMarcin Wojtas /* 69713ea0450SMarcin Wojtas * Check if either 69813ea0450SMarcin Wojtas * 1. There is a direct match between cert from forbidden_anchors 69913ea0450SMarcin Wojtas * and a cert from chain. 70013ea0450SMarcin Wojtas * 2. CA that signed the chain is found in forbidden_anchors. 70113ea0450SMarcin Wojtas */ 70213ea0450SMarcin Wojtas if (VEC_LEN(forbidden_anchors) > 0) 70313ea0450SMarcin Wojtas pk = verify_signer_xcs(xcs, num, elts, num_elts, &forbidden_anchors); 70413ea0450SMarcin Wojtas if (pk != NULL) { 70513ea0450SMarcin Wojtas ve_error_set("Certificate is on forbidden list\n"); 70613ea0450SMarcin Wojtas xfreepkey(pk); 70713ea0450SMarcin Wojtas pk = NULL; 70813ea0450SMarcin Wojtas goto out; 70913ea0450SMarcin Wojtas } 71013ea0450SMarcin Wojtas 71113ea0450SMarcin Wojtas pk = verify_signer_xcs(xcs, num, elts, num_elts, &trust_anchors); 71213ea0450SMarcin Wojtas if (pk == NULL) 71313ea0450SMarcin Wojtas goto out; 71413ea0450SMarcin Wojtas 71513ea0450SMarcin Wojtas /* 71613ea0450SMarcin Wojtas * Check if hash of tbs part of any certificate in chain 71713ea0450SMarcin Wojtas * is on the forbidden list. 71813ea0450SMarcin Wojtas */ 71913ea0450SMarcin Wojtas if (check_forbidden_digests(xcs, num)) { 72013ea0450SMarcin Wojtas ve_error_set("Certificate hash is on forbidden list\n"); 72113ea0450SMarcin Wojtas xfreepkey(pk); 72213ea0450SMarcin Wojtas pk = NULL; 72313ea0450SMarcin Wojtas } 72413ea0450SMarcin Wojtas out: 72513ea0450SMarcin Wojtas free_certificates(xcs, num); 7265fff9558SSimon J. Gerraty return (pk); 7275fff9558SSimon J. Gerraty } 7285fff9558SSimon J. Gerraty 7295fff9558SSimon J. Gerraty /** 7305fff9558SSimon J. Gerraty * we need a hex digest including trailing newline below 7315fff9558SSimon J. Gerraty */ 7325fff9558SSimon J. Gerraty char * 7335fff9558SSimon J. Gerraty hexdigest(char *buf, size_t bufsz, unsigned char *foo, size_t foo_len) 7345fff9558SSimon J. Gerraty { 7355fff9558SSimon J. Gerraty char const hex2ascii[] = "0123456789abcdef"; 7365fff9558SSimon J. Gerraty size_t i; 7375fff9558SSimon J. Gerraty 7385fff9558SSimon J. Gerraty /* every binary byte is 2 chars in hex + newline + null */ 7395fff9558SSimon J. Gerraty if (bufsz < (2 * foo_len) + 2) 7405fff9558SSimon J. Gerraty return (NULL); 7415fff9558SSimon J. Gerraty 7425fff9558SSimon J. Gerraty for (i = 0; i < foo_len; i++) { 7435fff9558SSimon J. Gerraty buf[i * 2] = hex2ascii[foo[i] >> 4]; 7445fff9558SSimon J. Gerraty buf[i * 2 + 1] = hex2ascii[foo[i] & 0x0f]; 7455fff9558SSimon J. Gerraty } 7465fff9558SSimon J. Gerraty 7475fff9558SSimon J. Gerraty buf[i * 2] = 0x0A; /* we also want a newline */ 7485fff9558SSimon J. Gerraty buf[i * 2 + 1] = '\0'; 7495fff9558SSimon J. Gerraty 7505fff9558SSimon J. Gerraty return (buf); 7515fff9558SSimon J. Gerraty } 7525fff9558SSimon J. Gerraty 7535fff9558SSimon J. Gerraty /** 7545fff9558SSimon J. Gerraty * @brief 7555fff9558SSimon J. Gerraty * verify file against sigfile using pk 7565fff9558SSimon J. Gerraty * 7575fff9558SSimon J. Gerraty * When we generated the signature in sigfile, 7585fff9558SSimon J. Gerraty * we hashed (sha256) file, and sent that to signing server 7595fff9558SSimon J. Gerraty * which hashed (sha256) that hash. 7605fff9558SSimon J. Gerraty * 7615fff9558SSimon J. Gerraty * To verify we need to replicate that result. 7625fff9558SSimon J. Gerraty * 7635fff9558SSimon J. Gerraty * @param[in] pk 7645fff9558SSimon J. Gerraty * br_x509_pkey 7655fff9558SSimon J. Gerraty * 7665fff9558SSimon J. Gerraty * @paramp[in] file 7675fff9558SSimon J. Gerraty * file to be verified 7685fff9558SSimon J. Gerraty * 7695fff9558SSimon J. Gerraty * @param[in] sigfile 7705fff9558SSimon J. Gerraty * signature (PEM encoded) 7715fff9558SSimon J. Gerraty * 7725fff9558SSimon J. Gerraty * @return NULL on error, otherwise content of file. 7735fff9558SSimon J. Gerraty */ 7745fff9558SSimon J. Gerraty #ifdef VE_ECDSA_SUPPORT 7755fff9558SSimon J. Gerraty static unsigned char * 7765fff9558SSimon J. Gerraty verify_ec(br_x509_pkey *pk, const char *file, const char *sigfile) 7775fff9558SSimon J. Gerraty { 7780e47020fSSimon J. Gerraty #ifdef VE_ECDSA_HASH_AGAIN 7790e47020fSSimon J. Gerraty char *hex, hexbuf[br_sha512_SIZE * 2 + 2]; 7800e47020fSSimon J. Gerraty #endif 7815fff9558SSimon J. Gerraty unsigned char rhbuf[br_sha512_SIZE]; 7825fff9558SSimon J. Gerraty br_sha256_context ctx; 7835fff9558SSimon J. Gerraty unsigned char *fcp, *scp; 7845fff9558SSimon J. Gerraty size_t flen, slen, plen; 7855fff9558SSimon J. Gerraty pem_object *po; 7865fff9558SSimon J. Gerraty const br_ec_impl *ec; 7875fff9558SSimon J. Gerraty br_ecdsa_vrfy vrfy; 7885fff9558SSimon J. Gerraty 7895fff9558SSimon J. Gerraty if ((fcp = read_file(file, &flen)) == NULL) 7905fff9558SSimon J. Gerraty return (NULL); 7915fff9558SSimon J. Gerraty if ((scp = read_file(sigfile, &slen)) == NULL) { 7925fff9558SSimon J. Gerraty free(fcp); 7935fff9558SSimon J. Gerraty return (NULL); 7945fff9558SSimon J. Gerraty } 7955fff9558SSimon J. Gerraty if ((po = decode_pem(scp, slen, &plen)) == NULL) { 7965fff9558SSimon J. Gerraty free(fcp); 7975fff9558SSimon J. Gerraty free(scp); 7985fff9558SSimon J. Gerraty return (NULL); 7995fff9558SSimon J. Gerraty } 8005fff9558SSimon J. Gerraty br_sha256_init(&ctx); 8015fff9558SSimon J. Gerraty br_sha256_update(&ctx, fcp, flen); 8025fff9558SSimon J. Gerraty br_sha256_out(&ctx, rhbuf); 803f9510887SSimon J. Gerraty #ifdef VE_ECDSA_HASH_AGAIN 8045fff9558SSimon J. Gerraty hex = hexdigest(hexbuf, sizeof(hexbuf), rhbuf, br_sha256_SIZE); 8055fff9558SSimon J. Gerraty /* now hash that */ 8065fff9558SSimon J. Gerraty if (hex) { 8075fff9558SSimon J. Gerraty br_sha256_init(&ctx); 8085fff9558SSimon J. Gerraty br_sha256_update(&ctx, hex, strlen(hex)); 8095fff9558SSimon J. Gerraty br_sha256_out(&ctx, rhbuf); 8105fff9558SSimon J. Gerraty } 811f9510887SSimon J. Gerraty #endif 8125fff9558SSimon J. Gerraty ec = br_ec_get_default(); 8135fff9558SSimon J. Gerraty vrfy = br_ecdsa_vrfy_asn1_get_default(); 8145fff9558SSimon J. Gerraty if (!vrfy(ec, rhbuf, br_sha256_SIZE, &pk->key.ec, po->data, 8155fff9558SSimon J. Gerraty po->data_len)) { 8165fff9558SSimon J. Gerraty free(fcp); 8175fff9558SSimon J. Gerraty fcp = NULL; 8185fff9558SSimon J. Gerraty } 8195fff9558SSimon J. Gerraty free(scp); 8205fff9558SSimon J. Gerraty return (fcp); 8215fff9558SSimon J. Gerraty } 8225fff9558SSimon J. Gerraty #endif 8235fff9558SSimon J. Gerraty 8245fff9558SSimon J. Gerraty #if defined(VE_RSA_SUPPORT) || defined(VE_OPENPGP_SUPPORT) 8255fff9558SSimon J. Gerraty /** 8265fff9558SSimon J. Gerraty * @brief verify an rsa digest 8275fff9558SSimon J. Gerraty * 8285fff9558SSimon J. Gerraty * @return 0 on failure 8295fff9558SSimon J. Gerraty */ 8305fff9558SSimon J. Gerraty int 8315fff9558SSimon J. Gerraty verify_rsa_digest (br_rsa_public_key *pkey, 8325fff9558SSimon J. Gerraty const unsigned char *hash_oid, 8335fff9558SSimon J. Gerraty unsigned char *mdata, size_t mlen, 8345fff9558SSimon J. Gerraty unsigned char *sdata, size_t slen) 8355fff9558SSimon J. Gerraty { 8365fff9558SSimon J. Gerraty br_rsa_pkcs1_vrfy vrfy; 8375fff9558SSimon J. Gerraty unsigned char vhbuf[br_sha512_SIZE]; 8385fff9558SSimon J. Gerraty 8395fff9558SSimon J. Gerraty vrfy = br_rsa_pkcs1_vrfy_get_default(); 8405fff9558SSimon J. Gerraty 8415fff9558SSimon J. Gerraty if (!vrfy(sdata, slen, hash_oid, mlen, pkey, vhbuf) || 8425fff9558SSimon J. Gerraty memcmp(vhbuf, mdata, mlen) != 0) { 8435fff9558SSimon J. Gerraty return (0); /* fail */ 8445fff9558SSimon J. Gerraty } 8455fff9558SSimon J. Gerraty return (1); /* ok */ 8465fff9558SSimon J. Gerraty } 8475fff9558SSimon J. Gerraty #endif 8485fff9558SSimon J. Gerraty 8495fff9558SSimon J. Gerraty /** 8505fff9558SSimon J. Gerraty * @brief 8515fff9558SSimon J. Gerraty * verify file against sigfile using pk 8525fff9558SSimon J. Gerraty * 8535fff9558SSimon J. Gerraty * When we generated the signature in sigfile, 8545fff9558SSimon J. Gerraty * we hashed (sha256) file, and sent that to signing server 8555fff9558SSimon J. Gerraty * which hashed (sha256) that hash. 8565fff9558SSimon J. Gerraty * 8575fff9558SSimon J. Gerraty * Or (deprecated) we simply used sha1 hash directly. 8585fff9558SSimon J. Gerraty * 8595fff9558SSimon J. Gerraty * To verify we need to replicate that result. 8605fff9558SSimon J. Gerraty * 8615fff9558SSimon J. Gerraty * @param[in] pk 8625fff9558SSimon J. Gerraty * br_x509_pkey 8635fff9558SSimon J. Gerraty * 8645fff9558SSimon J. Gerraty * @paramp[in] file 8655fff9558SSimon J. Gerraty * file to be verified 8665fff9558SSimon J. Gerraty * 8675fff9558SSimon J. Gerraty * @param[in] sigfile 8685fff9558SSimon J. Gerraty * signature (PEM encoded) 8695fff9558SSimon J. Gerraty * 8705fff9558SSimon J. Gerraty * @return NULL on error, otherwise content of file. 8715fff9558SSimon J. Gerraty */ 8725fff9558SSimon J. Gerraty #ifdef VE_RSA_SUPPORT 8735fff9558SSimon J. Gerraty static unsigned char * 8745fff9558SSimon J. Gerraty verify_rsa(br_x509_pkey *pk, const char *file, const char *sigfile) 8755fff9558SSimon J. Gerraty { 8765fff9558SSimon J. Gerraty unsigned char rhbuf[br_sha512_SIZE]; 8775fff9558SSimon J. Gerraty const unsigned char *hash_oid; 8785fff9558SSimon J. Gerraty const br_hash_class *md; 8795fff9558SSimon J. Gerraty br_hash_compat_context mctx; 8805fff9558SSimon J. Gerraty unsigned char *fcp, *scp; 8815fff9558SSimon J. Gerraty size_t flen, slen, plen, hlen; 8825fff9558SSimon J. Gerraty pem_object *po; 8835fff9558SSimon J. Gerraty 8845fff9558SSimon J. Gerraty if ((fcp = read_file(file, &flen)) == NULL) 8855fff9558SSimon J. Gerraty return (NULL); 8865fff9558SSimon J. Gerraty if ((scp = read_file(sigfile, &slen)) == NULL) { 8875fff9558SSimon J. Gerraty free(fcp); 8885fff9558SSimon J. Gerraty return (NULL); 8895fff9558SSimon J. Gerraty } 8905fff9558SSimon J. Gerraty if ((po = decode_pem(scp, slen, &plen)) == NULL) { 8915fff9558SSimon J. Gerraty free(fcp); 8925fff9558SSimon J. Gerraty free(scp); 8935fff9558SSimon J. Gerraty return (NULL); 8945fff9558SSimon J. Gerraty } 8955fff9558SSimon J. Gerraty 8965fff9558SSimon J. Gerraty switch (po->data_len) { 8975fff9558SSimon J. Gerraty #if defined(UNIT_TEST) && defined(VE_DEPRECATED_RSA_SHA1_SUPPORT) 8985fff9558SSimon J. Gerraty case 256: 8995fff9558SSimon J. Gerraty // this is our old deprecated sig method 9005fff9558SSimon J. Gerraty md = &br_sha1_vtable; 9015fff9558SSimon J. Gerraty hlen = br_sha1_SIZE; 9025fff9558SSimon J. Gerraty hash_oid = BR_HASH_OID_SHA1; 9035fff9558SSimon J. Gerraty break; 9045fff9558SSimon J. Gerraty #endif 9055fff9558SSimon J. Gerraty default: 9065fff9558SSimon J. Gerraty md = &br_sha256_vtable; 9075fff9558SSimon J. Gerraty hlen = br_sha256_SIZE; 9085fff9558SSimon J. Gerraty hash_oid = BR_HASH_OID_SHA256; 9095fff9558SSimon J. Gerraty break; 9105fff9558SSimon J. Gerraty } 9115fff9558SSimon J. Gerraty md->init(&mctx.vtable); 9125fff9558SSimon J. Gerraty md->update(&mctx.vtable, fcp, flen); 9135fff9558SSimon J. Gerraty md->out(&mctx.vtable, rhbuf); 9145fff9558SSimon J. Gerraty if (!verify_rsa_digest(&pk->key.rsa, hash_oid, 9155fff9558SSimon J. Gerraty rhbuf, hlen, po->data, po->data_len)) { 9165fff9558SSimon J. Gerraty free(fcp); 9175fff9558SSimon J. Gerraty fcp = NULL; 9185fff9558SSimon J. Gerraty } 9195fff9558SSimon J. Gerraty free(scp); 9205fff9558SSimon J. Gerraty return (fcp); 9215fff9558SSimon J. Gerraty } 9225fff9558SSimon J. Gerraty #endif 9235fff9558SSimon J. Gerraty 9245fff9558SSimon J. Gerraty /** 9255fff9558SSimon J. Gerraty * @brief 9265fff9558SSimon J. Gerraty * verify a signature and return content of signed file 9275fff9558SSimon J. Gerraty * 9285fff9558SSimon J. Gerraty * @param[in] sigfile 9295fff9558SSimon J. Gerraty * file containing signature 9305fff9558SSimon J. Gerraty * we derrive path of signed file and certificate change from 9315fff9558SSimon J. Gerraty * this. 9325fff9558SSimon J. Gerraty * 9335fff9558SSimon J. Gerraty * @param[in] flags 9345fff9558SSimon J. Gerraty * only bit 1 significant so far 9355fff9558SSimon J. Gerraty * 9365fff9558SSimon J. Gerraty * @return NULL on error otherwise content of signed file 9375fff9558SSimon J. Gerraty */ 9385fff9558SSimon J. Gerraty unsigned char * 9395fff9558SSimon J. Gerraty verify_sig(const char *sigfile, int flags) 9405fff9558SSimon J. Gerraty { 9415fff9558SSimon J. Gerraty br_x509_pkey *pk; 9425fff9558SSimon J. Gerraty br_name_element cn; 9435fff9558SSimon J. Gerraty char cn_buf[80]; 9445fff9558SSimon J. Gerraty unsigned char cn_oid[4]; 9455fff9558SSimon J. Gerraty char pbuf[MAXPATHLEN]; 9465fff9558SSimon J. Gerraty char *cp; 9475fff9558SSimon J. Gerraty unsigned char *ucp; 9485fff9558SSimon J. Gerraty size_t n; 9495fff9558SSimon J. Gerraty 9505fff9558SSimon J. Gerraty DEBUG_PRINTF(5, ("verify_sig: %s\n", sigfile)); 9515fff9558SSimon J. Gerraty n = strlcpy(pbuf, sigfile, sizeof(pbuf)); 9525fff9558SSimon J. Gerraty if (n > (sizeof(pbuf) - 5) || strcmp(&sigfile[n - 3], "sig") != 0) 9535fff9558SSimon J. Gerraty return (NULL); 9545fff9558SSimon J. Gerraty cp = strcpy(&pbuf[n - 3], "certs"); 9555fff9558SSimon J. Gerraty /* 9565fff9558SSimon J. Gerraty * We want the commonName field 9575fff9558SSimon J. Gerraty * the OID we want is 2,5,4,3 - but DER encoded 9585fff9558SSimon J. Gerraty */ 9595fff9558SSimon J. Gerraty cn_oid[0] = 3; 9605fff9558SSimon J. Gerraty cn_oid[1] = 0x55; 9615fff9558SSimon J. Gerraty cn_oid[2] = 4; 9625fff9558SSimon J. Gerraty cn_oid[3] = 3; 9635fff9558SSimon J. Gerraty cn.oid = cn_oid; 9645fff9558SSimon J. Gerraty cn.buf = cn_buf; 9655fff9558SSimon J. Gerraty cn.len = sizeof(cn_buf); 9665fff9558SSimon J. Gerraty 9675fff9558SSimon J. Gerraty pk = verify_signer(pbuf, &cn, 1); 9685fff9558SSimon J. Gerraty if (!pk) { 9695fff9558SSimon J. Gerraty printf("cannot verify: %s: %s\n", pbuf, ve_error_get()); 9705fff9558SSimon J. Gerraty return (NULL); 9715fff9558SSimon J. Gerraty } 9725fff9558SSimon J. Gerraty for (; cp > pbuf; cp--) { 9735fff9558SSimon J. Gerraty if (*cp == '.') { 9745fff9558SSimon J. Gerraty *cp = '\0'; 9755fff9558SSimon J. Gerraty break; 9765fff9558SSimon J. Gerraty } 9775fff9558SSimon J. Gerraty } 9785fff9558SSimon J. Gerraty switch (pk->key_type) { 9795fff9558SSimon J. Gerraty #ifdef VE_ECDSA_SUPPORT 9805fff9558SSimon J. Gerraty case BR_KEYTYPE_EC: 9815fff9558SSimon J. Gerraty ucp = verify_ec(pk, pbuf, sigfile); 9825fff9558SSimon J. Gerraty break; 9835fff9558SSimon J. Gerraty #endif 9845fff9558SSimon J. Gerraty #ifdef VE_RSA_SUPPORT 9855fff9558SSimon J. Gerraty case BR_KEYTYPE_RSA: 9865fff9558SSimon J. Gerraty ucp = verify_rsa(pk, pbuf, sigfile); 9875fff9558SSimon J. Gerraty break; 9885fff9558SSimon J. Gerraty #endif 9895fff9558SSimon J. Gerraty default: 9905fff9558SSimon J. Gerraty ucp = NULL; /* not supported */ 9915fff9558SSimon J. Gerraty } 9925fff9558SSimon J. Gerraty xfreepkey(pk); 9935fff9558SSimon J. Gerraty if (!ucp) { 9945fff9558SSimon J. Gerraty printf("Unverified %s (%s)\n", pbuf, 9955fff9558SSimon J. Gerraty cn.status ? cn_buf : "unknown"); 99666655411SSimon J. Gerraty } else if ((flags & VEF_VERBOSE) != 0) { 9975fff9558SSimon J. Gerraty printf("Verified %s signed by %s\n", pbuf, 9985fff9558SSimon J. Gerraty cn.status ? cn_buf : "someone we trust"); 9995fff9558SSimon J. Gerraty } 10005fff9558SSimon J. Gerraty return (ucp); 10015fff9558SSimon J. Gerraty } 10025fff9558SSimon J. Gerraty 10035fff9558SSimon J. Gerraty 10045fff9558SSimon J. Gerraty /** 10055fff9558SSimon J. Gerraty * @brief verify hash matches 10065fff9558SSimon J. Gerraty * 10075fff9558SSimon J. Gerraty * We have finished hashing a file, 10085fff9558SSimon J. Gerraty * see if we got the desired result. 10095fff9558SSimon J. Gerraty * 10105fff9558SSimon J. Gerraty * @param[in] ctx 10115fff9558SSimon J. Gerraty * pointer to hash context 10125fff9558SSimon J. Gerraty * 10135fff9558SSimon J. Gerraty * @param[in] md 10145fff9558SSimon J. Gerraty * pointer to hash class 10155fff9558SSimon J. Gerraty * 10165fff9558SSimon J. Gerraty * @param[in] path 10175fff9558SSimon J. Gerraty * name of the file we are checking 10185fff9558SSimon J. Gerraty * 10195fff9558SSimon J. Gerraty * @param[in] want 10205fff9558SSimon J. Gerraty * the expected result 10215fff9558SSimon J. Gerraty * 10225fff9558SSimon J. Gerraty * @param[in] hlen 10235fff9558SSimon J. Gerraty * size of hash output 10245fff9558SSimon J. Gerraty * 10255fff9558SSimon J. Gerraty * @return 0 on success 10265fff9558SSimon J. Gerraty */ 10275fff9558SSimon J. Gerraty int 10285fff9558SSimon J. Gerraty ve_check_hash(br_hash_compat_context *ctx, const br_hash_class *md, 10295fff9558SSimon J. Gerraty const char *path, const char *want, size_t hlen) 10305fff9558SSimon J. Gerraty { 10315fff9558SSimon J. Gerraty char hexbuf[br_sha512_SIZE * 2 + 2]; 10325fff9558SSimon J. Gerraty unsigned char hbuf[br_sha512_SIZE]; 10335fff9558SSimon J. Gerraty char *hex; 10345fff9558SSimon J. Gerraty int rc; 10355fff9558SSimon J. Gerraty int n; 10365fff9558SSimon J. Gerraty 10375fff9558SSimon J. Gerraty md->out(&ctx->vtable, hbuf); 10385fff9558SSimon J. Gerraty #ifdef VE_PCR_SUPPORT 103953f151f9SSimon J. Gerraty ve_pcr_update(path, hbuf, hlen); 10405fff9558SSimon J. Gerraty #endif 10415fff9558SSimon J. Gerraty hex = hexdigest(hexbuf, sizeof(hexbuf), hbuf, hlen); 10425fff9558SSimon J. Gerraty if (!hex) 10435fff9558SSimon J. Gerraty return (VE_FINGERPRINT_WRONG); 10445fff9558SSimon J. Gerraty n = 2*hlen; 10455fff9558SSimon J. Gerraty if ((rc = strncmp(hex, want, n))) { 10465fff9558SSimon J. Gerraty ve_error_set("%s: %.*s != %.*s", path, n, hex, n, want); 10475fff9558SSimon J. Gerraty rc = VE_FINGERPRINT_WRONG; 10485fff9558SSimon J. Gerraty } 10495fff9558SSimon J. Gerraty return (rc ? rc : VE_FINGERPRINT_OK); 10505fff9558SSimon J. Gerraty } 10515fff9558SSimon J. Gerraty 10525fff9558SSimon J. Gerraty #ifdef VE_HASH_KAT_STR 10535fff9558SSimon J. Gerraty static int 10545fff9558SSimon J. Gerraty test_hash(const br_hash_class *md, size_t hlen, 10555fff9558SSimon J. Gerraty const char *hname, const char *s, size_t slen, const char *want) 10565fff9558SSimon J. Gerraty { 10575fff9558SSimon J. Gerraty br_hash_compat_context mctx; 10585fff9558SSimon J. Gerraty 10595fff9558SSimon J. Gerraty md->init(&mctx.vtable); 10605fff9558SSimon J. Gerraty md->update(&mctx.vtable, s, slen); 10615fff9558SSimon J. Gerraty return (ve_check_hash(&mctx, md, hname, want, hlen) != VE_FINGERPRINT_OK); 10625fff9558SSimon J. Gerraty } 10635fff9558SSimon J. Gerraty 10645fff9558SSimon J. Gerraty #endif 10655fff9558SSimon J. Gerraty 10665fff9558SSimon J. Gerraty #define ve_test_hash(n, N) \ 10675fff9558SSimon J. Gerraty printf("Testing hash: " #n "\t\t\t\t%s\n", \ 10685fff9558SSimon J. Gerraty test_hash(&br_ ## n ## _vtable, br_ ## n ## _SIZE, #n, \ 10699bee6a60SSimon J. Gerraty VE_HASH_KAT_STR, VE_HASH_KAT_STRLEN(VE_HASH_KAT_STR), \ 10705fff9558SSimon J. Gerraty vh_ ## N) ? "Failed" : "Passed") 10715fff9558SSimon J. Gerraty 10725fff9558SSimon J. Gerraty /** 10735fff9558SSimon J. Gerraty * @brief 10745fff9558SSimon J. Gerraty * run self tests on hash and signature verification 10755fff9558SSimon J. Gerraty * 10765fff9558SSimon J. Gerraty * Test that the hash methods (SHA1 and SHA256) work. 10775fff9558SSimon J. Gerraty * Test that we can verify a certificate for each supported 10785fff9558SSimon J. Gerraty * Root CA. 10795fff9558SSimon J. Gerraty * 10805fff9558SSimon J. Gerraty * @return cached result. 10815fff9558SSimon J. Gerraty */ 10825fff9558SSimon J. Gerraty int 10835fff9558SSimon J. Gerraty ve_self_tests(void) 10845fff9558SSimon J. Gerraty { 10855fff9558SSimon J. Gerraty static int once = -1; 10865fff9558SSimon J. Gerraty #ifdef VERIFY_CERTS_STR 10875fff9558SSimon J. Gerraty br_x509_certificate *xcs; 10885fff9558SSimon J. Gerraty br_x509_pkey *pk; 10895fff9558SSimon J. Gerraty br_name_element cn; 10905fff9558SSimon J. Gerraty char cn_buf[80]; 10915fff9558SSimon J. Gerraty unsigned char cn_oid[4]; 10925fff9558SSimon J. Gerraty size_t num; 10935fff9558SSimon J. Gerraty size_t u; 10945fff9558SSimon J. Gerraty #endif 10955fff9558SSimon J. Gerraty 10965fff9558SSimon J. Gerraty if (once >= 0) 10975fff9558SSimon J. Gerraty return (once); 10985fff9558SSimon J. Gerraty once = 0; 10995fff9558SSimon J. Gerraty 11005fff9558SSimon J. Gerraty DEBUG_PRINTF(5, ("Self tests...\n")); 11015fff9558SSimon J. Gerraty #ifdef VE_HASH_KAT_STR 11025fff9558SSimon J. Gerraty #ifdef VE_SHA1_SUPPORT 11035fff9558SSimon J. Gerraty ve_test_hash(sha1, SHA1); 11045fff9558SSimon J. Gerraty #endif 11055fff9558SSimon J. Gerraty #ifdef VE_SHA256_SUPPORT 11065fff9558SSimon J. Gerraty ve_test_hash(sha256, SHA256); 11075fff9558SSimon J. Gerraty #endif 11085fff9558SSimon J. Gerraty #ifdef VE_SHA384_SUPPORT 11095fff9558SSimon J. Gerraty ve_test_hash(sha384, SHA384); 11105fff9558SSimon J. Gerraty #endif 11115fff9558SSimon J. Gerraty #ifdef VE_SHA512_SUPPORT 11125fff9558SSimon J. Gerraty ve_test_hash(sha512, SHA512); 11135fff9558SSimon J. Gerraty #endif 11145fff9558SSimon J. Gerraty #endif 11155fff9558SSimon J. Gerraty #ifdef VERIFY_CERTS_STR 11165fff9558SSimon J. Gerraty xcs = parse_certificates(__DECONST(unsigned char *, VERIFY_CERTS_STR), 11175fff9558SSimon J. Gerraty sizeof(VERIFY_CERTS_STR), &num); 11189bee6a60SSimon J. Gerraty if (xcs != NULL) { 11195fff9558SSimon J. Gerraty /* 11205fff9558SSimon J. Gerraty * We want the commonName field 11215fff9558SSimon J. Gerraty * the OID we want is 2,5,4,3 - but DER encoded 11225fff9558SSimon J. Gerraty */ 11235fff9558SSimon J. Gerraty cn_oid[0] = 3; 11245fff9558SSimon J. Gerraty cn_oid[1] = 0x55; 11255fff9558SSimon J. Gerraty cn_oid[2] = 4; 11265fff9558SSimon J. Gerraty cn_oid[3] = 3; 11275fff9558SSimon J. Gerraty cn.oid = cn_oid; 11285fff9558SSimon J. Gerraty cn.buf = cn_buf; 11295fff9558SSimon J. Gerraty 11305fff9558SSimon J. Gerraty for (u = 0; u < num; u ++) { 11315fff9558SSimon J. Gerraty cn.len = sizeof(cn_buf); 113213ea0450SMarcin Wojtas if ((pk = verify_signer_xcs(&xcs[u], 1, &cn, 1, &trust_anchors)) != NULL) { 113313ea0450SMarcin Wojtas free_cert_contents(&xcs[u]); 11345fff9558SSimon J. Gerraty once++; 11355fff9558SSimon J. Gerraty printf("Testing verify certificate: %s\tPassed\n", 11365fff9558SSimon J. Gerraty cn.status ? cn_buf : ""); 11375fff9558SSimon J. Gerraty xfreepkey(pk); 11385fff9558SSimon J. Gerraty } 11395fff9558SSimon J. Gerraty } 11405fff9558SSimon J. Gerraty if (!once) 11415fff9558SSimon J. Gerraty printf("Testing verify certificate:\t\t\tFailed\n"); 11425fff9558SSimon J. Gerraty xfree(xcs); 11439bee6a60SSimon J. Gerraty } 11445fff9558SSimon J. Gerraty #endif /* VERIFY_CERTS_STR */ 11455fff9558SSimon J. Gerraty #ifdef VE_OPENPGP_SUPPORT 11465fff9558SSimon J. Gerraty if (!openpgp_self_tests()) 11475fff9558SSimon J. Gerraty once++; 11485fff9558SSimon J. Gerraty #endif 11495fff9558SSimon J. Gerraty return (once); 11505fff9558SSimon J. Gerraty } 1151