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 46*66655411SSimon J. Gerraty #define EPOCH_YEAR 1970 47*66655411SSimon 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 57*66655411SSimon J. Gerraty #ifndef VE_VERIFY_FLAGS 58*66655411SSimon J. Gerraty # define VE_VERIFY_FLAGS VEF_VERBOSE 59*66655411SSimon J. Gerraty #endif 60*66655411SSimon J. Gerraty int VerifyFlags = VE_VERIFY_FLAGS; 61*66655411SSimon 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 895fff9558SSimon J. Gerraty static char ebuf[512]; 905fff9558SSimon J. Gerraty 915fff9558SSimon J. Gerraty char * 925fff9558SSimon J. Gerraty ve_error_get(void) 935fff9558SSimon J. Gerraty { 945fff9558SSimon J. Gerraty return (ebuf); 955fff9558SSimon J. Gerraty } 965fff9558SSimon J. Gerraty 975fff9558SSimon J. Gerraty int 985fff9558SSimon J. Gerraty ve_error_set(const char *fmt, ...) 995fff9558SSimon J. Gerraty { 1005fff9558SSimon J. Gerraty int rc; 1015fff9558SSimon J. Gerraty va_list ap; 1025fff9558SSimon J. Gerraty 1035fff9558SSimon J. Gerraty va_start(ap, fmt); 1045fff9558SSimon J. Gerraty ebuf[0] = '\0'; 1055fff9558SSimon J. Gerraty rc = 0; 1065fff9558SSimon J. Gerraty if (fmt) { 1075fff9558SSimon J. Gerraty #ifdef STAND_H 1085fff9558SSimon J. Gerraty vsprintf(ebuf, fmt, ap); /* no vsnprintf in libstand */ 1095fff9558SSimon J. Gerraty ebuf[sizeof(ebuf) - 1] = '\0'; 1105fff9558SSimon J. Gerraty rc = strlen(ebuf); 1115fff9558SSimon J. Gerraty #else 1125fff9558SSimon J. Gerraty rc = vsnprintf(ebuf, sizeof(ebuf), fmt, ap); 1135fff9558SSimon J. Gerraty #endif 1145fff9558SSimon J. Gerraty } 1155fff9558SSimon J. Gerraty va_end(ap); 1165fff9558SSimon J. Gerraty return (rc); 1175fff9558SSimon J. Gerraty } 1185fff9558SSimon J. Gerraty 119*66655411SSimon J. Gerraty #define isleap(y) (((y) % 4) == 0 && (((y) % 100) != 0 || ((y) % 400) == 0)) 120*66655411SSimon J. Gerraty 121*66655411SSimon J. Gerraty /* 122*66655411SSimon J. Gerraty * The *approximate* date. 123*66655411SSimon J. Gerraty * 124*66655411SSimon J. Gerraty * When certificate verification fails for being 125*66655411SSimon J. Gerraty * expired or not yet valid, it helps to indicate 126*66655411SSimon J. Gerraty * our current date. 127*66655411SSimon J. Gerraty * Since libsa lacks strftime and gmtime, 128*66655411SSimon J. Gerraty * this simple implementation suffices. 129*66655411SSimon J. Gerraty */ 130*66655411SSimon J. Gerraty static const char * 131*66655411SSimon J. Gerraty gdate(char *buf, size_t bufsz, time_t clock) 132*66655411SSimon J. Gerraty { 133*66655411SSimon J. Gerraty int days[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; 134*66655411SSimon J. Gerraty int year, y, m, d; 135*66655411SSimon J. Gerraty 136*66655411SSimon J. Gerraty y = clock / AVG_SECONDS_PER_YEAR; 137*66655411SSimon J. Gerraty year = EPOCH_YEAR + y; 138*66655411SSimon J. Gerraty for (y = EPOCH_YEAR; y < year; y++) { 139*66655411SSimon J. Gerraty clock -= SECONDS_PER_YEAR; 140*66655411SSimon J. Gerraty if (isleap(y)) 141*66655411SSimon J. Gerraty clock -= SECONDS_PER_DAY; 142*66655411SSimon J. Gerraty } 143*66655411SSimon J. Gerraty d = clock / SECONDS_PER_DAY; 144*66655411SSimon J. Gerraty for (m = 0; d > 1 && m < 12; m++) { 145*66655411SSimon J. Gerraty if (d > days[m]) { 146*66655411SSimon J. Gerraty d -= days[m]; 147*66655411SSimon J. Gerraty if (m == 1 && d > 0 && isleap(year)) 148*66655411SSimon J. Gerraty d--; 149*66655411SSimon J. Gerraty } else 150*66655411SSimon J. Gerraty break; 151*66655411SSimon J. Gerraty } 152*66655411SSimon J. Gerraty d++; 153*66655411SSimon J. Gerraty if (d > days[m]) { 154*66655411SSimon J. Gerraty d = 1; 155*66655411SSimon J. Gerraty m++; 156*66655411SSimon J. Gerraty if (m >= 12) { 157*66655411SSimon J. Gerraty year++; 158*66655411SSimon J. Gerraty m = 0; 159*66655411SSimon J. Gerraty } 160*66655411SSimon J. Gerraty } 161*66655411SSimon J. Gerraty (void)snprintf(buf, bufsz, "%04d-%02d-%02d", year, m+1, d); 162*66655411SSimon J. Gerraty return(buf); 163*66655411SSimon J. Gerraty } 164*66655411SSimon J. Gerraty 1655fff9558SSimon J. Gerraty /* this is the time we use for verifying certs */ 166*66655411SSimon J. Gerraty #ifdef UNIT_TEST 167*66655411SSimon J. Gerraty extern time_t ve_utc; 168*66655411SSimon J. Gerraty time_t ve_utc = 0; 169*66655411SSimon J. Gerraty #else 1705fff9558SSimon J. Gerraty static time_t ve_utc = 0; 171*66655411SSimon J. Gerraty #endif 1725fff9558SSimon J. Gerraty 1735fff9558SSimon J. Gerraty /** 1745fff9558SSimon J. Gerraty * @brief 1755fff9558SSimon J. Gerraty * set ve_utc used for certificate verification 1765fff9558SSimon J. Gerraty * 1775fff9558SSimon J. Gerraty * @param[in] utc 17853f151f9SSimon J. Gerraty * time - ignored unless greater than current value 17953f151f9SSimon J. Gerraty * and not a leap of 20 years or more. 1805fff9558SSimon J. Gerraty */ 1815fff9558SSimon J. Gerraty void 1825fff9558SSimon J. Gerraty ve_utc_set(time_t utc) 1835fff9558SSimon J. Gerraty { 18453f151f9SSimon J. Gerraty if (utc > ve_utc && 18553f151f9SSimon J. Gerraty (ve_utc == 0 || (utc - ve_utc) < VE_UTC_MAX_JUMP)) { 1865fff9558SSimon J. Gerraty DEBUG_PRINTF(2, ("Set ve_utc=%jd\n", (intmax_t)utc)); 1875fff9558SSimon J. Gerraty ve_utc = utc; 1885fff9558SSimon J. Gerraty } 1895fff9558SSimon J. Gerraty } 1905fff9558SSimon J. Gerraty 1915fff9558SSimon J. Gerraty static void 1925fff9558SSimon J. Gerraty free_cert_contents(br_x509_certificate *xc) 1935fff9558SSimon J. Gerraty { 1945fff9558SSimon J. Gerraty xfree(xc->data); 1955fff9558SSimon J. Gerraty } 1965fff9558SSimon J. Gerraty 197f9510887SSimon J. Gerraty /* 198f9510887SSimon J. Gerraty * a bit of a dance to get commonName from a certificate 199f9510887SSimon J. Gerraty */ 200f9510887SSimon J. Gerraty static char * 201f9510887SSimon J. Gerraty x509_cn_get(br_x509_certificate *xc, char *buf, size_t len) 202f9510887SSimon J. Gerraty { 203f9510887SSimon J. Gerraty br_x509_minimal_context mc; 204f9510887SSimon J. Gerraty br_name_element cn; 205f9510887SSimon J. Gerraty unsigned char cn_oid[4]; 206f9510887SSimon J. Gerraty int err; 207f9510887SSimon J. Gerraty 208f9510887SSimon J. Gerraty if (buf == NULL) 209f9510887SSimon J. Gerraty return (buf); 210f9510887SSimon J. Gerraty /* 211f9510887SSimon J. Gerraty * We want the commonName field 212f9510887SSimon J. Gerraty * the OID we want is 2,5,4,3 - but DER encoded 213f9510887SSimon J. Gerraty */ 214f9510887SSimon J. Gerraty cn_oid[0] = 3; 215f9510887SSimon J. Gerraty cn_oid[1] = 0x55; 216f9510887SSimon J. Gerraty cn_oid[2] = 4; 217f9510887SSimon J. Gerraty cn_oid[3] = 3; 218f9510887SSimon J. Gerraty cn.oid = cn_oid; 219f9510887SSimon J. Gerraty cn.buf = buf; 220f9510887SSimon J. Gerraty cn.len = len; 221f9510887SSimon J. Gerraty cn.buf[0] = '\0'; 222f9510887SSimon J. Gerraty 223f9510887SSimon J. Gerraty br_x509_minimal_init(&mc, &br_sha256_vtable, NULL, 0); 224f9510887SSimon J. Gerraty br_x509_minimal_set_name_elements(&mc, &cn, 1); 225f9510887SSimon J. Gerraty /* the below actually does the work - updates cn.status */ 226f9510887SSimon J. Gerraty mc.vtable->start_chain(&mc.vtable, NULL); 227f9510887SSimon J. Gerraty mc.vtable->start_cert(&mc.vtable, xc->data_len); 228f9510887SSimon J. Gerraty mc.vtable->append(&mc.vtable, xc->data, xc->data_len); 229f9510887SSimon J. Gerraty mc.vtable->end_cert(&mc.vtable); 230f9510887SSimon J. Gerraty /* we don' actually care about cert status - just its name */ 231f9510887SSimon J. Gerraty err = mc.vtable->end_chain(&mc.vtable); 232f9510887SSimon J. Gerraty 233f9510887SSimon J. Gerraty if (!cn.status) 234f9510887SSimon J. Gerraty buf = NULL; 235f9510887SSimon J. Gerraty return (buf); 236f9510887SSimon J. Gerraty } 237f9510887SSimon J. Gerraty 23813ea0450SMarcin Wojtas /* ASN parsing related defines */ 23913ea0450SMarcin Wojtas #define ASN1_PRIMITIVE_TAG 0x1F 24013ea0450SMarcin Wojtas #define ASN1_INF_LENGTH 0x80 24113ea0450SMarcin Wojtas #define ASN1_LENGTH_MASK 0x7F 24213ea0450SMarcin Wojtas 24313ea0450SMarcin Wojtas /* 24413ea0450SMarcin Wojtas * Get TBS part of certificate. 24513ea0450SMarcin Wojtas * Since BearSSL doesn't provide any API to do this, 24613ea0450SMarcin Wojtas * it has to be implemented here. 2475fff9558SSimon J. Gerraty */ 24813ea0450SMarcin Wojtas static void* 24913ea0450SMarcin Wojtas X509_to_tbs(unsigned char* cert, size_t* output_size) 25013ea0450SMarcin Wojtas { 25113ea0450SMarcin Wojtas unsigned char *result; 25213ea0450SMarcin Wojtas size_t tbs_size; 25313ea0450SMarcin Wojtas int size, i; 25413ea0450SMarcin Wojtas 25513ea0450SMarcin Wojtas if (cert == NULL) 25613ea0450SMarcin Wojtas return (NULL); 25713ea0450SMarcin Wojtas 25813ea0450SMarcin Wojtas /* Strip two sequences to get to the TBS section */ 25913ea0450SMarcin Wojtas for (i = 0; i < 2; i++) { 26013ea0450SMarcin Wojtas /* 26113ea0450SMarcin Wojtas * XXX: We don't need to support extended tags since 26213ea0450SMarcin Wojtas * they should not be present in certificates. 26313ea0450SMarcin Wojtas */ 26413ea0450SMarcin Wojtas if ((*cert & ASN1_PRIMITIVE_TAG) == ASN1_PRIMITIVE_TAG) 26513ea0450SMarcin Wojtas return (NULL); 26613ea0450SMarcin Wojtas 26713ea0450SMarcin Wojtas cert++; 26813ea0450SMarcin Wojtas 26913ea0450SMarcin Wojtas if (*cert == ASN1_INF_LENGTH) 27013ea0450SMarcin Wojtas return (NULL); 27113ea0450SMarcin Wojtas 27213ea0450SMarcin Wojtas size = *cert & ASN1_LENGTH_MASK; 27313ea0450SMarcin Wojtas tbs_size = 0; 27413ea0450SMarcin Wojtas 27513ea0450SMarcin Wojtas /* Size can either be stored on a single or multiple bytes */ 27613ea0450SMarcin Wojtas if (*cert & (ASN1_LENGTH_MASK + 1)) { 27713ea0450SMarcin Wojtas cert++; 27813ea0450SMarcin Wojtas while (*cert == 0 && size > 0) { 27913ea0450SMarcin Wojtas cert++; 28013ea0450SMarcin Wojtas size--; 28113ea0450SMarcin Wojtas } 28213ea0450SMarcin Wojtas while (size-- > 0) { 28313ea0450SMarcin Wojtas tbs_size <<= 8; 28413ea0450SMarcin Wojtas tbs_size |= *(cert++); 28513ea0450SMarcin Wojtas } 28613ea0450SMarcin Wojtas } 28713ea0450SMarcin Wojtas if (i == 0) 28813ea0450SMarcin Wojtas result = cert; 28913ea0450SMarcin Wojtas } 29013ea0450SMarcin Wojtas tbs_size += (cert - result); 29113ea0450SMarcin Wojtas 29213ea0450SMarcin Wojtas if (output_size != NULL) 29313ea0450SMarcin Wojtas *output_size = tbs_size; 29413ea0450SMarcin Wojtas 29513ea0450SMarcin Wojtas return (result); 29613ea0450SMarcin Wojtas } 29713ea0450SMarcin Wojtas 29813ea0450SMarcin Wojtas void 29913ea0450SMarcin Wojtas ve_forbidden_digest_add(hash_data *digest, size_t num) 30013ea0450SMarcin Wojtas { 30113ea0450SMarcin Wojtas while (num--) 30213ea0450SMarcin Wojtas VEC_ADD(forbidden_digests, digest[num]); 30313ea0450SMarcin Wojtas } 30413ea0450SMarcin Wojtas 30513ea0450SMarcin Wojtas static size_t 306f9510887SSimon J. Gerraty ve_anchors_add(br_x509_certificate *xcs, size_t num, anchor_list *anchors, 30718e2fbc0SSimon J. Gerraty const char *anchors_name) 3085fff9558SSimon J. Gerraty { 3095fff9558SSimon J. Gerraty br_x509_trust_anchor ta; 3105fff9558SSimon J. Gerraty size_t u; 3115fff9558SSimon J. Gerraty 3125fff9558SSimon J. Gerraty for (u = 0; u < num; u++) { 3135fff9558SSimon J. Gerraty if (certificate_to_trust_anchor_inner(&ta, &xcs[u]) < 0) { 3145fff9558SSimon J. Gerraty break; 3155fff9558SSimon J. Gerraty } 31613ea0450SMarcin Wojtas VEC_ADD(*anchors, ta); 317f9510887SSimon J. Gerraty if (anchor_verbose && anchors_name) { 318f9510887SSimon J. Gerraty char buf[64]; 319f9510887SSimon J. Gerraty char *cp; 320f9510887SSimon J. Gerraty 321f9510887SSimon J. Gerraty cp = x509_cn_get(&xcs[u], buf, sizeof(buf)); 322f9510887SSimon J. Gerraty if (cp) { 323f9510887SSimon J. Gerraty printf("x509_anchor(%s) %s\n", cp, anchors_name); 324f9510887SSimon J. Gerraty } 325f9510887SSimon J. Gerraty } 3265fff9558SSimon J. Gerraty } 3275fff9558SSimon J. Gerraty return (u); 3285fff9558SSimon J. Gerraty } 3295fff9558SSimon J. Gerraty 3305fff9558SSimon J. Gerraty /** 3315fff9558SSimon J. Gerraty * @brief 33213ea0450SMarcin Wojtas * add certs to our trust store 33313ea0450SMarcin Wojtas */ 33413ea0450SMarcin Wojtas size_t 33513ea0450SMarcin Wojtas ve_trust_anchors_add(br_x509_certificate *xcs, size_t num) 33613ea0450SMarcin Wojtas { 337f9510887SSimon J. Gerraty return (ve_anchors_add(xcs, num, &trust_anchors, "trusted")); 33813ea0450SMarcin Wojtas } 33913ea0450SMarcin Wojtas 34013ea0450SMarcin Wojtas size_t 34113ea0450SMarcin Wojtas ve_forbidden_anchors_add(br_x509_certificate *xcs, size_t num) 34213ea0450SMarcin Wojtas { 343f9510887SSimon J. Gerraty return (ve_anchors_add(xcs, num, &forbidden_anchors, "forbidden")); 344f9510887SSimon J. Gerraty } 345f9510887SSimon J. Gerraty 346f9510887SSimon J. Gerraty 347f9510887SSimon J. Gerraty /** 348f9510887SSimon J. Gerraty * @brief add trust anchors in buf 349f9510887SSimon J. Gerraty * 350f9510887SSimon J. Gerraty * Assume buf contains x509 certificates, but if not and 351f9510887SSimon J. Gerraty * we support OpenPGP try adding as that. 352f9510887SSimon J. Gerraty * 353f9510887SSimon J. Gerraty * @return number of anchors added 354f9510887SSimon J. Gerraty */ 355f9510887SSimon J. Gerraty size_t 356f9510887SSimon J. Gerraty ve_trust_anchors_add_buf(unsigned char *buf, size_t len) 357f9510887SSimon J. Gerraty { 358f9510887SSimon J. Gerraty br_x509_certificate *xcs; 359f9510887SSimon J. Gerraty size_t num; 360f9510887SSimon J. Gerraty 361f9510887SSimon J. Gerraty num = 0; 362f9510887SSimon J. Gerraty xcs = parse_certificates(buf, len, &num); 363f9510887SSimon J. Gerraty if (xcs != NULL) { 364f9510887SSimon J. Gerraty num = ve_trust_anchors_add(xcs, num); 365f9510887SSimon J. Gerraty #ifdef VE_OPENPGP_SUPPORT 366f9510887SSimon J. Gerraty } else { 367f9510887SSimon J. Gerraty num = openpgp_trust_add_buf(buf, len); 368f9510887SSimon J. Gerraty #endif 369f9510887SSimon J. Gerraty } 370f9510887SSimon J. Gerraty return (num); 371f9510887SSimon J. Gerraty } 372f9510887SSimon J. Gerraty 373f9510887SSimon J. Gerraty /** 374f9510887SSimon J. Gerraty * @brief revoke trust anchors in buf 375f9510887SSimon J. Gerraty * 376f9510887SSimon J. Gerraty * Assume buf contains x509 certificates, but if not and 377f9510887SSimon J. Gerraty * we support OpenPGP try revoking keyId 378f9510887SSimon J. Gerraty * 379f9510887SSimon J. Gerraty * @return number of anchors revoked 380f9510887SSimon J. Gerraty */ 381f9510887SSimon J. Gerraty size_t 382f9510887SSimon J. Gerraty ve_trust_anchors_revoke(unsigned char *buf, size_t len) 383f9510887SSimon J. Gerraty { 384f9510887SSimon J. Gerraty br_x509_certificate *xcs; 385f9510887SSimon J. Gerraty size_t num; 386f9510887SSimon J. Gerraty 387f9510887SSimon J. Gerraty num = 0; 388f9510887SSimon J. Gerraty xcs = parse_certificates(buf, len, &num); 389f9510887SSimon J. Gerraty if (xcs != NULL) { 390f9510887SSimon J. Gerraty num = ve_forbidden_anchors_add(xcs, num); 391f9510887SSimon J. Gerraty #ifdef VE_OPENPGP_SUPPORT 392f9510887SSimon J. Gerraty } else { 393f9510887SSimon J. Gerraty if (buf[len - 1] == '\n') 394f9510887SSimon J. Gerraty buf[len - 1] = '\0'; 395f9510887SSimon J. Gerraty num = openpgp_trust_revoke((char *)buf); 396f9510887SSimon J. Gerraty #endif 397f9510887SSimon J. Gerraty } 398f9510887SSimon J. Gerraty return (num); 39913ea0450SMarcin Wojtas } 40013ea0450SMarcin Wojtas 40113ea0450SMarcin Wojtas /** 40213ea0450SMarcin Wojtas * @brief 4035fff9558SSimon J. Gerraty * initialize our trust_anchors from ta_PEM 4045fff9558SSimon J. Gerraty */ 4055fff9558SSimon J. Gerraty int 4065fff9558SSimon J. Gerraty ve_trust_init(void) 4075fff9558SSimon J. Gerraty { 4085fff9558SSimon J. Gerraty static int once = -1; 4095fff9558SSimon J. Gerraty 4105fff9558SSimon J. Gerraty if (once >= 0) 4115fff9558SSimon J. Gerraty return (once); 4123ae2a848SSimon J. Gerraty once = 0; /* to be sure */ 4135fff9558SSimon J. Gerraty #ifdef BUILD_UTC 41453f151f9SSimon J. Gerraty ve_utc_set(BUILD_UTC); /* ensure sanity */ 4155fff9558SSimon J. Gerraty #endif 41653f151f9SSimon J. Gerraty ve_utc_set(time(NULL)); 4175fff9558SSimon J. Gerraty ve_error_set(NULL); /* make sure it is empty */ 4185fff9558SSimon J. Gerraty #ifdef VE_PCR_SUPPORT 4195fff9558SSimon J. Gerraty ve_pcr_init(); 4205fff9558SSimon J. Gerraty #endif 4215fff9558SSimon J. Gerraty 4225fff9558SSimon J. Gerraty #ifdef TRUST_ANCHOR_STR 423f9510887SSimon J. Gerraty ve_trust_anchors_add_buf(__DECONST(unsigned char *, TRUST_ANCHOR_STR), 424f9510887SSimon J. Gerraty sizeof(TRUST_ANCHOR_STR)); 4255fff9558SSimon J. Gerraty #endif 42613ea0450SMarcin Wojtas once = (int) VEC_LEN(trust_anchors); 4279bee6a60SSimon J. Gerraty #ifdef VE_OPENPGP_SUPPORT 4289bee6a60SSimon J. Gerraty once += openpgp_trust_init(); 4299bee6a60SSimon J. Gerraty #endif 43013ea0450SMarcin Wojtas return (once); 4315fff9558SSimon J. Gerraty } 4325fff9558SSimon J. Gerraty 433*66655411SSimon J. Gerraty #ifdef HAVE_BR_X509_TIME_CHECK 434*66655411SSimon J. Gerraty static int 435*66655411SSimon J. Gerraty verify_time_cb(void *tctx, 436*66655411SSimon J. Gerraty uint32_t not_before_days, uint32_t not_before_seconds, 437*66655411SSimon J. Gerraty uint32_t not_after_days, uint32_t not_after_seconds) 438*66655411SSimon J. Gerraty { 439*66655411SSimon J. Gerraty time_t not_before; 440*66655411SSimon J. Gerraty time_t not_after; 441*66655411SSimon J. Gerraty int rc; 442*66655411SSimon J. Gerraty #ifdef UNIT_TEST 443*66655411SSimon J. Gerraty char date[12], nb_date[12], na_date[12]; 444*66655411SSimon J. Gerraty #endif 445*66655411SSimon J. Gerraty 446*66655411SSimon J. Gerraty not_before = ((not_before_days - X509_DAYS_TO_UTC0) * SECONDS_PER_DAY) + not_before_seconds; 447*66655411SSimon J. Gerraty not_after = ((not_after_days - X509_DAYS_TO_UTC0) * SECONDS_PER_DAY) + not_after_seconds; 448*66655411SSimon J. Gerraty if (ve_utc < not_before) 449*66655411SSimon J. Gerraty rc = -1; 450*66655411SSimon J. Gerraty else if (ve_utc > not_after) 451*66655411SSimon J. Gerraty rc = 1; 452*66655411SSimon J. Gerraty else 453*66655411SSimon J. Gerraty rc = 0; 454*66655411SSimon J. Gerraty #ifdef UNIT_TEST 455*66655411SSimon J. Gerraty printf("notBefore %s notAfter %s date %s rc %d\n", 456*66655411SSimon J. Gerraty gdate(nb_date, sizeof(nb_date), not_before), 457*66655411SSimon J. Gerraty gdate(na_date, sizeof(na_date), not_after), 458*66655411SSimon J. Gerraty gdate(date, sizeof(date), ve_utc), rc); 459*66655411SSimon J. Gerraty #endif 460*66655411SSimon J. Gerraty #if defined(_STANDALONE) 461*66655411SSimon J. Gerraty rc = 0; /* don't fail */ 462*66655411SSimon J. Gerraty #endif 463*66655411SSimon J. Gerraty return rc; 464*66655411SSimon J. Gerraty } 465*66655411SSimon J. Gerraty #endif 466*66655411SSimon J. Gerraty 4675fff9558SSimon J. Gerraty /** 4685fff9558SSimon J. Gerraty * if we can verify the certificate chain in "certs", 4695fff9558SSimon J. Gerraty * return the public key and if "xcp" is !NULL the associated 4705fff9558SSimon J. Gerraty * certificate 4715fff9558SSimon J. Gerraty */ 4725fff9558SSimon J. Gerraty static br_x509_pkey * 4735fff9558SSimon J. Gerraty verify_signer_xcs(br_x509_certificate *xcs, 4745fff9558SSimon J. Gerraty size_t num, 47513ea0450SMarcin Wojtas br_name_element *elts, size_t num_elts, 47613ea0450SMarcin Wojtas anchor_list *anchors) 4775fff9558SSimon J. Gerraty { 4785fff9558SSimon J. Gerraty br_x509_minimal_context mc; 4795fff9558SSimon J. Gerraty br_x509_certificate *xc; 4805fff9558SSimon J. Gerraty size_t u; 4815fff9558SSimon J. Gerraty cert_list chain = VEC_INIT; 4825fff9558SSimon J. Gerraty const br_x509_pkey *tpk; 4835fff9558SSimon J. Gerraty br_x509_pkey *pk; 4845fff9558SSimon J. Gerraty unsigned int usages; 4855fff9558SSimon J. Gerraty int err; 4865fff9558SSimon J. Gerraty 4875fff9558SSimon J. Gerraty DEBUG_PRINTF(5, ("verify_signer: %zu certs in chain\n", num)); 4885fff9558SSimon J. Gerraty VEC_ADDMANY(chain, xcs, num); 4895fff9558SSimon J. Gerraty if (VEC_LEN(chain) == 0) { 4905fff9558SSimon J. Gerraty ve_error_set("ERROR: no/invalid certificate chain\n"); 4915fff9558SSimon J. Gerraty return (NULL); 4925fff9558SSimon J. Gerraty } 4935fff9558SSimon J. Gerraty 4945fff9558SSimon J. Gerraty DEBUG_PRINTF(5, ("verify_signer: %zu trust anchors\n", 49513ea0450SMarcin Wojtas VEC_LEN(*anchors))); 4965fff9558SSimon J. Gerraty 4975fff9558SSimon J. Gerraty br_x509_minimal_init(&mc, &br_sha256_vtable, 49813ea0450SMarcin Wojtas &VEC_ELT(*anchors, 0), 49913ea0450SMarcin Wojtas VEC_LEN(*anchors)); 5005fff9558SSimon J. Gerraty #ifdef VE_ECDSA_SUPPORT 5015fff9558SSimon J. Gerraty br_x509_minimal_set_ecdsa(&mc, 5025fff9558SSimon J. Gerraty &br_ec_prime_i31, &br_ecdsa_i31_vrfy_asn1); 5035fff9558SSimon J. Gerraty #endif 5045fff9558SSimon J. Gerraty #ifdef VE_RSA_SUPPORT 5055fff9558SSimon J. Gerraty br_x509_minimal_set_rsa(&mc, &br_rsa_i31_pkcs1_vrfy); 5065fff9558SSimon J. Gerraty #endif 5075fff9558SSimon J. Gerraty #if defined(UNIT_TEST) && defined(VE_DEPRECATED_RSA_SHA1_SUPPORT) 5085fff9558SSimon J. Gerraty /* This is deprecated! do not enable unless you absoultely have to */ 5095fff9558SSimon J. Gerraty br_x509_minimal_set_hash(&mc, br_sha1_ID, &br_sha1_vtable); 5105fff9558SSimon J. Gerraty #endif 5115fff9558SSimon J. Gerraty br_x509_minimal_set_hash(&mc, br_sha256_ID, &br_sha256_vtable); 5125fff9558SSimon J. Gerraty #ifdef VE_SHA384_SUPPORT 5135fff9558SSimon J. Gerraty br_x509_minimal_set_hash(&mc, br_sha384_ID, &br_sha384_vtable); 5145fff9558SSimon J. Gerraty #endif 5155fff9558SSimon J. Gerraty #ifdef VE_SHA512_SUPPORT 5165fff9558SSimon J. Gerraty br_x509_minimal_set_hash(&mc, br_sha512_ID, &br_sha512_vtable); 5175fff9558SSimon J. Gerraty #endif 5185fff9558SSimon J. Gerraty br_x509_minimal_set_name_elements(&mc, elts, num_elts); 5195fff9558SSimon J. Gerraty 520*66655411SSimon J. Gerraty #ifdef HAVE_BR_X509_TIME_CHECK 521*66655411SSimon J. Gerraty br_x509_minimal_set_time_callback(&mc, NULL, verify_time_cb); 522*66655411SSimon J. Gerraty #else 523*66655411SSimon J. Gerraty #if defined(_STANDALONE) || defined(UNIT_TEST) 5245fff9558SSimon J. Gerraty /* 5255fff9558SSimon J. Gerraty * Clock is probably bogus so we use ve_utc. 5265fff9558SSimon J. Gerraty */ 5275fff9558SSimon J. Gerraty mc.days = (ve_utc / SECONDS_PER_DAY) + X509_DAYS_TO_UTC0; 5285fff9558SSimon J. Gerraty mc.seconds = (ve_utc % SECONDS_PER_DAY); 5295fff9558SSimon J. Gerraty #endif 530*66655411SSimon J. Gerraty #endif 5315fff9558SSimon J. Gerraty mc.vtable->start_chain(&mc.vtable, NULL); 5325fff9558SSimon J. Gerraty for (u = 0; u < VEC_LEN(chain); u ++) { 5335fff9558SSimon J. Gerraty xc = &VEC_ELT(chain, u); 5345fff9558SSimon J. Gerraty mc.vtable->start_cert(&mc.vtable, xc->data_len); 5355fff9558SSimon J. Gerraty mc.vtable->append(&mc.vtable, xc->data, xc->data_len); 5365fff9558SSimon J. Gerraty mc.vtable->end_cert(&mc.vtable); 5375fff9558SSimon J. Gerraty switch (mc.err) { 5385fff9558SSimon J. Gerraty case 0: 5395fff9558SSimon J. Gerraty case BR_ERR_X509_OK: 5405fff9558SSimon J. Gerraty case BR_ERR_X509_EXPIRED: 5415fff9558SSimon J. Gerraty break; 5425fff9558SSimon J. Gerraty default: 5435fff9558SSimon J. Gerraty printf("u=%zu mc.err=%d\n", u, mc.err); 5445fff9558SSimon J. Gerraty break; 5455fff9558SSimon J. Gerraty } 5465fff9558SSimon J. Gerraty } 5475fff9558SSimon J. Gerraty err = mc.vtable->end_chain(&mc.vtable); 5485fff9558SSimon J. Gerraty pk = NULL; 5495fff9558SSimon J. Gerraty if (err) { 550*66655411SSimon J. Gerraty char date[12]; 551*66655411SSimon J. Gerraty 552*66655411SSimon J. Gerraty switch (err) { 553*66655411SSimon J. Gerraty case 54: 554*66655411SSimon J. Gerraty ve_error_set("Validation failed, certificate not valid as of %s", 555*66655411SSimon J. Gerraty gdate(date, sizeof(date), ve_utc)); 556*66655411SSimon J. Gerraty break; 557*66655411SSimon J. Gerraty default: 5585fff9558SSimon J. Gerraty ve_error_set("Validation failed, err = %d", err); 559*66655411SSimon J. Gerraty break; 560*66655411SSimon J. Gerraty } 5615fff9558SSimon J. Gerraty } else { 5625fff9558SSimon J. Gerraty tpk = mc.vtable->get_pkey(&mc.vtable, &usages); 5635fff9558SSimon J. Gerraty if (tpk != NULL) { 5645fff9558SSimon J. Gerraty pk = xpkeydup(tpk); 5655fff9558SSimon J. Gerraty } 5665fff9558SSimon J. Gerraty } 56713ea0450SMarcin Wojtas VEC_CLEAR(chain); 5685fff9558SSimon J. Gerraty return (pk); 5695fff9558SSimon J. Gerraty } 5705fff9558SSimon J. Gerraty 57113ea0450SMarcin Wojtas /* 57213ea0450SMarcin Wojtas * Check if digest of one of the certificates from verified chain 57313ea0450SMarcin Wojtas * is present in the forbidden database. 57413ea0450SMarcin Wojtas * Since UEFI allows to store three types of digests 57513ea0450SMarcin Wojtas * all of them have to be checked separately. 57613ea0450SMarcin Wojtas */ 57713ea0450SMarcin Wojtas static int 57813ea0450SMarcin Wojtas check_forbidden_digests(br_x509_certificate *xcs, size_t num) 57913ea0450SMarcin Wojtas { 58013ea0450SMarcin Wojtas unsigned char sha256_digest[br_sha256_SIZE]; 58113ea0450SMarcin Wojtas unsigned char sha384_digest[br_sha384_SIZE]; 58213ea0450SMarcin Wojtas unsigned char sha512_digest[br_sha512_SIZE]; 58313ea0450SMarcin Wojtas void *tbs; 58413ea0450SMarcin Wojtas hash_data *digest; 58513ea0450SMarcin Wojtas br_hash_compat_context ctx; 58613ea0450SMarcin Wojtas const br_hash_class *md; 58713ea0450SMarcin Wojtas size_t tbs_len, i; 58813ea0450SMarcin Wojtas int have_sha256, have_sha384, have_sha512; 58913ea0450SMarcin Wojtas 59013ea0450SMarcin Wojtas if (VEC_LEN(forbidden_digests) == 0) 59113ea0450SMarcin Wojtas return (0); 59213ea0450SMarcin Wojtas 59313ea0450SMarcin Wojtas /* 59413ea0450SMarcin Wojtas * Iterate through certificates, extract their To-Be-Signed section, 59513ea0450SMarcin Wojtas * and compare its digest against the ones in the forbidden database. 59613ea0450SMarcin Wojtas */ 59713ea0450SMarcin Wojtas while (num--) { 59813ea0450SMarcin Wojtas tbs = X509_to_tbs(xcs[num].data, &tbs_len); 59913ea0450SMarcin Wojtas if (tbs == NULL) { 60013ea0450SMarcin Wojtas printf("Failed to obtain TBS part of certificate\n"); 60113ea0450SMarcin Wojtas return (1); 60213ea0450SMarcin Wojtas } 60313ea0450SMarcin Wojtas have_sha256 = have_sha384 = have_sha512 = 0; 60413ea0450SMarcin Wojtas 60513ea0450SMarcin Wojtas for (i = 0; i < VEC_LEN(forbidden_digests); i++) { 60613ea0450SMarcin Wojtas digest = &VEC_ELT(forbidden_digests, i); 60713ea0450SMarcin Wojtas switch (digest->hash_size) { 60813ea0450SMarcin Wojtas case br_sha256_SIZE: 60913ea0450SMarcin Wojtas if (!have_sha256) { 61013ea0450SMarcin Wojtas have_sha256 = 1; 61113ea0450SMarcin Wojtas md = &br_sha256_vtable; 61213ea0450SMarcin Wojtas md->init(&ctx.vtable); 61313ea0450SMarcin Wojtas md->update(&ctx.vtable, tbs, tbs_len); 61413ea0450SMarcin Wojtas md->out(&ctx.vtable, sha256_digest); 61513ea0450SMarcin Wojtas } 61613ea0450SMarcin Wojtas if (!memcmp(sha256_digest, 61713ea0450SMarcin Wojtas digest->data, 61813ea0450SMarcin Wojtas br_sha256_SIZE)) 61913ea0450SMarcin Wojtas return (1); 62013ea0450SMarcin Wojtas 62113ea0450SMarcin Wojtas break; 62213ea0450SMarcin Wojtas case br_sha384_SIZE: 62313ea0450SMarcin Wojtas if (!have_sha384) { 62413ea0450SMarcin Wojtas have_sha384 = 1; 62513ea0450SMarcin Wojtas md = &br_sha384_vtable; 62613ea0450SMarcin Wojtas md->init(&ctx.vtable); 62713ea0450SMarcin Wojtas md->update(&ctx.vtable, tbs, tbs_len); 62813ea0450SMarcin Wojtas md->out(&ctx.vtable, sha384_digest); 62913ea0450SMarcin Wojtas } 63013ea0450SMarcin Wojtas if (!memcmp(sha384_digest, 63113ea0450SMarcin Wojtas digest->data, 63213ea0450SMarcin Wojtas br_sha384_SIZE)) 63313ea0450SMarcin Wojtas return (1); 63413ea0450SMarcin Wojtas 63513ea0450SMarcin Wojtas break; 63613ea0450SMarcin Wojtas case br_sha512_SIZE: 63713ea0450SMarcin Wojtas if (!have_sha512) { 63813ea0450SMarcin Wojtas have_sha512 = 1; 63913ea0450SMarcin Wojtas md = &br_sha512_vtable; 64013ea0450SMarcin Wojtas md->init(&ctx.vtable); 64113ea0450SMarcin Wojtas md->update(&ctx.vtable, tbs, tbs_len); 64213ea0450SMarcin Wojtas md->out(&ctx.vtable, sha512_digest); 64313ea0450SMarcin Wojtas } 64413ea0450SMarcin Wojtas if (!memcmp(sha512_digest, 64513ea0450SMarcin Wojtas digest->data, 64613ea0450SMarcin Wojtas br_sha512_SIZE)) 64713ea0450SMarcin Wojtas return (1); 64813ea0450SMarcin Wojtas 64913ea0450SMarcin Wojtas break; 65013ea0450SMarcin Wojtas } 65113ea0450SMarcin Wojtas } 65213ea0450SMarcin Wojtas } 65313ea0450SMarcin Wojtas 65413ea0450SMarcin Wojtas return (0); 65513ea0450SMarcin Wojtas } 65613ea0450SMarcin Wojtas 6575fff9558SSimon J. Gerraty static br_x509_pkey * 6585fff9558SSimon J. Gerraty verify_signer(const char *certs, 6595fff9558SSimon J. Gerraty br_name_element *elts, size_t num_elts) 6605fff9558SSimon J. Gerraty { 6615fff9558SSimon J. Gerraty br_x509_certificate *xcs; 6625fff9558SSimon J. Gerraty br_x509_pkey *pk; 6635fff9558SSimon J. Gerraty size_t num; 6645fff9558SSimon J. Gerraty 66513ea0450SMarcin Wojtas pk = NULL; 66613ea0450SMarcin Wojtas 6675fff9558SSimon J. Gerraty ve_trust_init(); 6685fff9558SSimon J. Gerraty xcs = read_certificates(certs, &num); 6695fff9558SSimon J. Gerraty if (xcs == NULL) { 6705fff9558SSimon J. Gerraty ve_error_set("cannot read certificates\n"); 6715fff9558SSimon J. Gerraty return (NULL); 6725fff9558SSimon J. Gerraty } 67313ea0450SMarcin Wojtas 67413ea0450SMarcin Wojtas /* 67513ea0450SMarcin Wojtas * Check if either 67613ea0450SMarcin Wojtas * 1. There is a direct match between cert from forbidden_anchors 67713ea0450SMarcin Wojtas * and a cert from chain. 67813ea0450SMarcin Wojtas * 2. CA that signed the chain is found in forbidden_anchors. 67913ea0450SMarcin Wojtas */ 68013ea0450SMarcin Wojtas if (VEC_LEN(forbidden_anchors) > 0) 68113ea0450SMarcin Wojtas pk = verify_signer_xcs(xcs, num, elts, num_elts, &forbidden_anchors); 68213ea0450SMarcin Wojtas if (pk != NULL) { 68313ea0450SMarcin Wojtas ve_error_set("Certificate is on forbidden list\n"); 68413ea0450SMarcin Wojtas xfreepkey(pk); 68513ea0450SMarcin Wojtas pk = NULL; 68613ea0450SMarcin Wojtas goto out; 68713ea0450SMarcin Wojtas } 68813ea0450SMarcin Wojtas 68913ea0450SMarcin Wojtas pk = verify_signer_xcs(xcs, num, elts, num_elts, &trust_anchors); 69013ea0450SMarcin Wojtas if (pk == NULL) 69113ea0450SMarcin Wojtas goto out; 69213ea0450SMarcin Wojtas 69313ea0450SMarcin Wojtas /* 69413ea0450SMarcin Wojtas * Check if hash of tbs part of any certificate in chain 69513ea0450SMarcin Wojtas * is on the forbidden list. 69613ea0450SMarcin Wojtas */ 69713ea0450SMarcin Wojtas if (check_forbidden_digests(xcs, num)) { 69813ea0450SMarcin Wojtas ve_error_set("Certificate hash is on forbidden list\n"); 69913ea0450SMarcin Wojtas xfreepkey(pk); 70013ea0450SMarcin Wojtas pk = NULL; 70113ea0450SMarcin Wojtas } 70213ea0450SMarcin Wojtas out: 70313ea0450SMarcin Wojtas free_certificates(xcs, num); 7045fff9558SSimon J. Gerraty return (pk); 7055fff9558SSimon J. Gerraty } 7065fff9558SSimon J. Gerraty 7075fff9558SSimon J. Gerraty /** 7085fff9558SSimon J. Gerraty * we need a hex digest including trailing newline below 7095fff9558SSimon J. Gerraty */ 7105fff9558SSimon J. Gerraty char * 7115fff9558SSimon J. Gerraty hexdigest(char *buf, size_t bufsz, unsigned char *foo, size_t foo_len) 7125fff9558SSimon J. Gerraty { 7135fff9558SSimon J. Gerraty char const hex2ascii[] = "0123456789abcdef"; 7145fff9558SSimon J. Gerraty size_t i; 7155fff9558SSimon J. Gerraty 7165fff9558SSimon J. Gerraty /* every binary byte is 2 chars in hex + newline + null */ 7175fff9558SSimon J. Gerraty if (bufsz < (2 * foo_len) + 2) 7185fff9558SSimon J. Gerraty return (NULL); 7195fff9558SSimon J. Gerraty 7205fff9558SSimon J. Gerraty for (i = 0; i < foo_len; i++) { 7215fff9558SSimon J. Gerraty buf[i * 2] = hex2ascii[foo[i] >> 4]; 7225fff9558SSimon J. Gerraty buf[i * 2 + 1] = hex2ascii[foo[i] & 0x0f]; 7235fff9558SSimon J. Gerraty } 7245fff9558SSimon J. Gerraty 7255fff9558SSimon J. Gerraty buf[i * 2] = 0x0A; /* we also want a newline */ 7265fff9558SSimon J. Gerraty buf[i * 2 + 1] = '\0'; 7275fff9558SSimon J. Gerraty 7285fff9558SSimon J. Gerraty return (buf); 7295fff9558SSimon J. Gerraty } 7305fff9558SSimon J. Gerraty 7315fff9558SSimon J. Gerraty /** 7325fff9558SSimon J. Gerraty * @brief 7335fff9558SSimon J. Gerraty * verify file against sigfile using pk 7345fff9558SSimon J. Gerraty * 7355fff9558SSimon J. Gerraty * When we generated the signature in sigfile, 7365fff9558SSimon J. Gerraty * we hashed (sha256) file, and sent that to signing server 7375fff9558SSimon J. Gerraty * which hashed (sha256) that hash. 7385fff9558SSimon J. Gerraty * 7395fff9558SSimon J. Gerraty * To verify we need to replicate that result. 7405fff9558SSimon J. Gerraty * 7415fff9558SSimon J. Gerraty * @param[in] pk 7425fff9558SSimon J. Gerraty * br_x509_pkey 7435fff9558SSimon J. Gerraty * 7445fff9558SSimon J. Gerraty * @paramp[in] file 7455fff9558SSimon J. Gerraty * file to be verified 7465fff9558SSimon J. Gerraty * 7475fff9558SSimon J. Gerraty * @param[in] sigfile 7485fff9558SSimon J. Gerraty * signature (PEM encoded) 7495fff9558SSimon J. Gerraty * 7505fff9558SSimon J. Gerraty * @return NULL on error, otherwise content of file. 7515fff9558SSimon J. Gerraty */ 7525fff9558SSimon J. Gerraty #ifdef VE_ECDSA_SUPPORT 7535fff9558SSimon J. Gerraty static unsigned char * 7545fff9558SSimon J. Gerraty verify_ec(br_x509_pkey *pk, const char *file, const char *sigfile) 7555fff9558SSimon J. Gerraty { 7560e47020fSSimon J. Gerraty #ifdef VE_ECDSA_HASH_AGAIN 7570e47020fSSimon J. Gerraty char *hex, hexbuf[br_sha512_SIZE * 2 + 2]; 7580e47020fSSimon J. Gerraty #endif 7595fff9558SSimon J. Gerraty unsigned char rhbuf[br_sha512_SIZE]; 7605fff9558SSimon J. Gerraty br_sha256_context ctx; 7615fff9558SSimon J. Gerraty unsigned char *fcp, *scp; 7625fff9558SSimon J. Gerraty size_t flen, slen, plen; 7635fff9558SSimon J. Gerraty pem_object *po; 7645fff9558SSimon J. Gerraty const br_ec_impl *ec; 7655fff9558SSimon J. Gerraty br_ecdsa_vrfy vrfy; 7665fff9558SSimon J. Gerraty 7675fff9558SSimon J. Gerraty if ((fcp = read_file(file, &flen)) == NULL) 7685fff9558SSimon J. Gerraty return (NULL); 7695fff9558SSimon J. Gerraty if ((scp = read_file(sigfile, &slen)) == NULL) { 7705fff9558SSimon J. Gerraty free(fcp); 7715fff9558SSimon J. Gerraty return (NULL); 7725fff9558SSimon J. Gerraty } 7735fff9558SSimon J. Gerraty if ((po = decode_pem(scp, slen, &plen)) == NULL) { 7745fff9558SSimon J. Gerraty free(fcp); 7755fff9558SSimon J. Gerraty free(scp); 7765fff9558SSimon J. Gerraty return (NULL); 7775fff9558SSimon J. Gerraty } 7785fff9558SSimon J. Gerraty br_sha256_init(&ctx); 7795fff9558SSimon J. Gerraty br_sha256_update(&ctx, fcp, flen); 7805fff9558SSimon J. Gerraty br_sha256_out(&ctx, rhbuf); 781f9510887SSimon J. Gerraty #ifdef VE_ECDSA_HASH_AGAIN 7825fff9558SSimon J. Gerraty hex = hexdigest(hexbuf, sizeof(hexbuf), rhbuf, br_sha256_SIZE); 7835fff9558SSimon J. Gerraty /* now hash that */ 7845fff9558SSimon J. Gerraty if (hex) { 7855fff9558SSimon J. Gerraty br_sha256_init(&ctx); 7865fff9558SSimon J. Gerraty br_sha256_update(&ctx, hex, strlen(hex)); 7875fff9558SSimon J. Gerraty br_sha256_out(&ctx, rhbuf); 7885fff9558SSimon J. Gerraty } 789f9510887SSimon J. Gerraty #endif 7905fff9558SSimon J. Gerraty ec = br_ec_get_default(); 7915fff9558SSimon J. Gerraty vrfy = br_ecdsa_vrfy_asn1_get_default(); 7925fff9558SSimon J. Gerraty if (!vrfy(ec, rhbuf, br_sha256_SIZE, &pk->key.ec, po->data, 7935fff9558SSimon J. Gerraty po->data_len)) { 7945fff9558SSimon J. Gerraty free(fcp); 7955fff9558SSimon J. Gerraty fcp = NULL; 7965fff9558SSimon J. Gerraty } 7975fff9558SSimon J. Gerraty free(scp); 7985fff9558SSimon J. Gerraty return (fcp); 7995fff9558SSimon J. Gerraty } 8005fff9558SSimon J. Gerraty #endif 8015fff9558SSimon J. Gerraty 8025fff9558SSimon J. Gerraty #if defined(VE_RSA_SUPPORT) || defined(VE_OPENPGP_SUPPORT) 8035fff9558SSimon J. Gerraty /** 8045fff9558SSimon J. Gerraty * @brief verify an rsa digest 8055fff9558SSimon J. Gerraty * 8065fff9558SSimon J. Gerraty * @return 0 on failure 8075fff9558SSimon J. Gerraty */ 8085fff9558SSimon J. Gerraty int 8095fff9558SSimon J. Gerraty verify_rsa_digest (br_rsa_public_key *pkey, 8105fff9558SSimon J. Gerraty const unsigned char *hash_oid, 8115fff9558SSimon J. Gerraty unsigned char *mdata, size_t mlen, 8125fff9558SSimon J. Gerraty unsigned char *sdata, size_t slen) 8135fff9558SSimon J. Gerraty { 8145fff9558SSimon J. Gerraty br_rsa_pkcs1_vrfy vrfy; 8155fff9558SSimon J. Gerraty unsigned char vhbuf[br_sha512_SIZE]; 8165fff9558SSimon J. Gerraty 8175fff9558SSimon J. Gerraty vrfy = br_rsa_pkcs1_vrfy_get_default(); 8185fff9558SSimon J. Gerraty 8195fff9558SSimon J. Gerraty if (!vrfy(sdata, slen, hash_oid, mlen, pkey, vhbuf) || 8205fff9558SSimon J. Gerraty memcmp(vhbuf, mdata, mlen) != 0) { 8215fff9558SSimon J. Gerraty return (0); /* fail */ 8225fff9558SSimon J. Gerraty } 8235fff9558SSimon J. Gerraty return (1); /* ok */ 8245fff9558SSimon J. Gerraty } 8255fff9558SSimon J. Gerraty #endif 8265fff9558SSimon J. Gerraty 8275fff9558SSimon J. Gerraty /** 8285fff9558SSimon J. Gerraty * @brief 8295fff9558SSimon J. Gerraty * verify file against sigfile using pk 8305fff9558SSimon J. Gerraty * 8315fff9558SSimon J. Gerraty * When we generated the signature in sigfile, 8325fff9558SSimon J. Gerraty * we hashed (sha256) file, and sent that to signing server 8335fff9558SSimon J. Gerraty * which hashed (sha256) that hash. 8345fff9558SSimon J. Gerraty * 8355fff9558SSimon J. Gerraty * Or (deprecated) we simply used sha1 hash directly. 8365fff9558SSimon J. Gerraty * 8375fff9558SSimon J. Gerraty * To verify we need to replicate that result. 8385fff9558SSimon J. Gerraty * 8395fff9558SSimon J. Gerraty * @param[in] pk 8405fff9558SSimon J. Gerraty * br_x509_pkey 8415fff9558SSimon J. Gerraty * 8425fff9558SSimon J. Gerraty * @paramp[in] file 8435fff9558SSimon J. Gerraty * file to be verified 8445fff9558SSimon J. Gerraty * 8455fff9558SSimon J. Gerraty * @param[in] sigfile 8465fff9558SSimon J. Gerraty * signature (PEM encoded) 8475fff9558SSimon J. Gerraty * 8485fff9558SSimon J. Gerraty * @return NULL on error, otherwise content of file. 8495fff9558SSimon J. Gerraty */ 8505fff9558SSimon J. Gerraty #ifdef VE_RSA_SUPPORT 8515fff9558SSimon J. Gerraty static unsigned char * 8525fff9558SSimon J. Gerraty verify_rsa(br_x509_pkey *pk, const char *file, const char *sigfile) 8535fff9558SSimon J. Gerraty { 8545fff9558SSimon J. Gerraty unsigned char rhbuf[br_sha512_SIZE]; 8555fff9558SSimon J. Gerraty const unsigned char *hash_oid; 8565fff9558SSimon J. Gerraty const br_hash_class *md; 8575fff9558SSimon J. Gerraty br_hash_compat_context mctx; 8585fff9558SSimon J. Gerraty unsigned char *fcp, *scp; 8595fff9558SSimon J. Gerraty size_t flen, slen, plen, hlen; 8605fff9558SSimon J. Gerraty pem_object *po; 8615fff9558SSimon J. Gerraty 8625fff9558SSimon J. Gerraty if ((fcp = read_file(file, &flen)) == NULL) 8635fff9558SSimon J. Gerraty return (NULL); 8645fff9558SSimon J. Gerraty if ((scp = read_file(sigfile, &slen)) == NULL) { 8655fff9558SSimon J. Gerraty free(fcp); 8665fff9558SSimon J. Gerraty return (NULL); 8675fff9558SSimon J. Gerraty } 8685fff9558SSimon J. Gerraty if ((po = decode_pem(scp, slen, &plen)) == NULL) { 8695fff9558SSimon J. Gerraty free(fcp); 8705fff9558SSimon J. Gerraty free(scp); 8715fff9558SSimon J. Gerraty return (NULL); 8725fff9558SSimon J. Gerraty } 8735fff9558SSimon J. Gerraty 8745fff9558SSimon J. Gerraty switch (po->data_len) { 8755fff9558SSimon J. Gerraty #if defined(UNIT_TEST) && defined(VE_DEPRECATED_RSA_SHA1_SUPPORT) 8765fff9558SSimon J. Gerraty case 256: 8775fff9558SSimon J. Gerraty // this is our old deprecated sig method 8785fff9558SSimon J. Gerraty md = &br_sha1_vtable; 8795fff9558SSimon J. Gerraty hlen = br_sha1_SIZE; 8805fff9558SSimon J. Gerraty hash_oid = BR_HASH_OID_SHA1; 8815fff9558SSimon J. Gerraty break; 8825fff9558SSimon J. Gerraty #endif 8835fff9558SSimon J. Gerraty default: 8845fff9558SSimon J. Gerraty md = &br_sha256_vtable; 8855fff9558SSimon J. Gerraty hlen = br_sha256_SIZE; 8865fff9558SSimon J. Gerraty hash_oid = BR_HASH_OID_SHA256; 8875fff9558SSimon J. Gerraty break; 8885fff9558SSimon J. Gerraty } 8895fff9558SSimon J. Gerraty md->init(&mctx.vtable); 8905fff9558SSimon J. Gerraty md->update(&mctx.vtable, fcp, flen); 8915fff9558SSimon J. Gerraty md->out(&mctx.vtable, rhbuf); 8925fff9558SSimon J. Gerraty if (!verify_rsa_digest(&pk->key.rsa, hash_oid, 8935fff9558SSimon J. Gerraty rhbuf, hlen, po->data, po->data_len)) { 8945fff9558SSimon J. Gerraty free(fcp); 8955fff9558SSimon J. Gerraty fcp = NULL; 8965fff9558SSimon J. Gerraty } 8975fff9558SSimon J. Gerraty free(scp); 8985fff9558SSimon J. Gerraty return (fcp); 8995fff9558SSimon J. Gerraty } 9005fff9558SSimon J. Gerraty #endif 9015fff9558SSimon J. Gerraty 9025fff9558SSimon J. Gerraty /** 9035fff9558SSimon J. Gerraty * @brief 9045fff9558SSimon J. Gerraty * verify a signature and return content of signed file 9055fff9558SSimon J. Gerraty * 9065fff9558SSimon J. Gerraty * @param[in] sigfile 9075fff9558SSimon J. Gerraty * file containing signature 9085fff9558SSimon J. Gerraty * we derrive path of signed file and certificate change from 9095fff9558SSimon J. Gerraty * this. 9105fff9558SSimon J. Gerraty * 9115fff9558SSimon J. Gerraty * @param[in] flags 9125fff9558SSimon J. Gerraty * only bit 1 significant so far 9135fff9558SSimon J. Gerraty * 9145fff9558SSimon J. Gerraty * @return NULL on error otherwise content of signed file 9155fff9558SSimon J. Gerraty */ 9165fff9558SSimon J. Gerraty unsigned char * 9175fff9558SSimon J. Gerraty verify_sig(const char *sigfile, int flags) 9185fff9558SSimon J. Gerraty { 9195fff9558SSimon J. Gerraty br_x509_pkey *pk; 9205fff9558SSimon J. Gerraty br_name_element cn; 9215fff9558SSimon J. Gerraty char cn_buf[80]; 9225fff9558SSimon J. Gerraty unsigned char cn_oid[4]; 9235fff9558SSimon J. Gerraty char pbuf[MAXPATHLEN]; 9245fff9558SSimon J. Gerraty char *cp; 9255fff9558SSimon J. Gerraty unsigned char *ucp; 9265fff9558SSimon J. Gerraty size_t n; 9275fff9558SSimon J. Gerraty 9285fff9558SSimon J. Gerraty DEBUG_PRINTF(5, ("verify_sig: %s\n", sigfile)); 9295fff9558SSimon J. Gerraty n = strlcpy(pbuf, sigfile, sizeof(pbuf)); 9305fff9558SSimon J. Gerraty if (n > (sizeof(pbuf) - 5) || strcmp(&sigfile[n - 3], "sig") != 0) 9315fff9558SSimon J. Gerraty return (NULL); 9325fff9558SSimon J. Gerraty cp = strcpy(&pbuf[n - 3], "certs"); 9335fff9558SSimon J. Gerraty /* 9345fff9558SSimon J. Gerraty * We want the commonName field 9355fff9558SSimon J. Gerraty * the OID we want is 2,5,4,3 - but DER encoded 9365fff9558SSimon J. Gerraty */ 9375fff9558SSimon J. Gerraty cn_oid[0] = 3; 9385fff9558SSimon J. Gerraty cn_oid[1] = 0x55; 9395fff9558SSimon J. Gerraty cn_oid[2] = 4; 9405fff9558SSimon J. Gerraty cn_oid[3] = 3; 9415fff9558SSimon J. Gerraty cn.oid = cn_oid; 9425fff9558SSimon J. Gerraty cn.buf = cn_buf; 9435fff9558SSimon J. Gerraty cn.len = sizeof(cn_buf); 9445fff9558SSimon J. Gerraty 9455fff9558SSimon J. Gerraty pk = verify_signer(pbuf, &cn, 1); 9465fff9558SSimon J. Gerraty if (!pk) { 9475fff9558SSimon J. Gerraty printf("cannot verify: %s: %s\n", pbuf, ve_error_get()); 9485fff9558SSimon J. Gerraty return (NULL); 9495fff9558SSimon J. Gerraty } 9505fff9558SSimon J. Gerraty for (; cp > pbuf; cp--) { 9515fff9558SSimon J. Gerraty if (*cp == '.') { 9525fff9558SSimon J. Gerraty *cp = '\0'; 9535fff9558SSimon J. Gerraty break; 9545fff9558SSimon J. Gerraty } 9555fff9558SSimon J. Gerraty } 9565fff9558SSimon J. Gerraty switch (pk->key_type) { 9575fff9558SSimon J. Gerraty #ifdef VE_ECDSA_SUPPORT 9585fff9558SSimon J. Gerraty case BR_KEYTYPE_EC: 9595fff9558SSimon J. Gerraty ucp = verify_ec(pk, pbuf, sigfile); 9605fff9558SSimon J. Gerraty break; 9615fff9558SSimon J. Gerraty #endif 9625fff9558SSimon J. Gerraty #ifdef VE_RSA_SUPPORT 9635fff9558SSimon J. Gerraty case BR_KEYTYPE_RSA: 9645fff9558SSimon J. Gerraty ucp = verify_rsa(pk, pbuf, sigfile); 9655fff9558SSimon J. Gerraty break; 9665fff9558SSimon J. Gerraty #endif 9675fff9558SSimon J. Gerraty default: 9685fff9558SSimon J. Gerraty ucp = NULL; /* not supported */ 9695fff9558SSimon J. Gerraty } 9705fff9558SSimon J. Gerraty xfreepkey(pk); 9715fff9558SSimon J. Gerraty if (!ucp) { 9725fff9558SSimon J. Gerraty printf("Unverified %s (%s)\n", pbuf, 9735fff9558SSimon J. Gerraty cn.status ? cn_buf : "unknown"); 974*66655411SSimon J. Gerraty } else if ((flags & VEF_VERBOSE) != 0) { 9755fff9558SSimon J. Gerraty printf("Verified %s signed by %s\n", pbuf, 9765fff9558SSimon J. Gerraty cn.status ? cn_buf : "someone we trust"); 9775fff9558SSimon J. Gerraty } 9785fff9558SSimon J. Gerraty return (ucp); 9795fff9558SSimon J. Gerraty } 9805fff9558SSimon J. Gerraty 9815fff9558SSimon J. Gerraty 9825fff9558SSimon J. Gerraty /** 9835fff9558SSimon J. Gerraty * @brief verify hash matches 9845fff9558SSimon J. Gerraty * 9855fff9558SSimon J. Gerraty * We have finished hashing a file, 9865fff9558SSimon J. Gerraty * see if we got the desired result. 9875fff9558SSimon J. Gerraty * 9885fff9558SSimon J. Gerraty * @param[in] ctx 9895fff9558SSimon J. Gerraty * pointer to hash context 9905fff9558SSimon J. Gerraty * 9915fff9558SSimon J. Gerraty * @param[in] md 9925fff9558SSimon J. Gerraty * pointer to hash class 9935fff9558SSimon J. Gerraty * 9945fff9558SSimon J. Gerraty * @param[in] path 9955fff9558SSimon J. Gerraty * name of the file we are checking 9965fff9558SSimon J. Gerraty * 9975fff9558SSimon J. Gerraty * @param[in] want 9985fff9558SSimon J. Gerraty * the expected result 9995fff9558SSimon J. Gerraty * 10005fff9558SSimon J. Gerraty * @param[in] hlen 10015fff9558SSimon J. Gerraty * size of hash output 10025fff9558SSimon J. Gerraty * 10035fff9558SSimon J. Gerraty * @return 0 on success 10045fff9558SSimon J. Gerraty */ 10055fff9558SSimon J. Gerraty int 10065fff9558SSimon J. Gerraty ve_check_hash(br_hash_compat_context *ctx, const br_hash_class *md, 10075fff9558SSimon J. Gerraty const char *path, const char *want, size_t hlen) 10085fff9558SSimon J. Gerraty { 10095fff9558SSimon J. Gerraty char hexbuf[br_sha512_SIZE * 2 + 2]; 10105fff9558SSimon J. Gerraty unsigned char hbuf[br_sha512_SIZE]; 10115fff9558SSimon J. Gerraty char *hex; 10125fff9558SSimon J. Gerraty int rc; 10135fff9558SSimon J. Gerraty int n; 10145fff9558SSimon J. Gerraty 10155fff9558SSimon J. Gerraty md->out(&ctx->vtable, hbuf); 10165fff9558SSimon J. Gerraty #ifdef VE_PCR_SUPPORT 101753f151f9SSimon J. Gerraty ve_pcr_update(path, hbuf, hlen); 10185fff9558SSimon J. Gerraty #endif 10195fff9558SSimon J. Gerraty hex = hexdigest(hexbuf, sizeof(hexbuf), hbuf, hlen); 10205fff9558SSimon J. Gerraty if (!hex) 10215fff9558SSimon J. Gerraty return (VE_FINGERPRINT_WRONG); 10225fff9558SSimon J. Gerraty n = 2*hlen; 10235fff9558SSimon J. Gerraty if ((rc = strncmp(hex, want, n))) { 10245fff9558SSimon J. Gerraty ve_error_set("%s: %.*s != %.*s", path, n, hex, n, want); 10255fff9558SSimon J. Gerraty rc = VE_FINGERPRINT_WRONG; 10265fff9558SSimon J. Gerraty } 10275fff9558SSimon J. Gerraty return (rc ? rc : VE_FINGERPRINT_OK); 10285fff9558SSimon J. Gerraty } 10295fff9558SSimon J. Gerraty 10305fff9558SSimon J. Gerraty #ifdef VE_HASH_KAT_STR 10315fff9558SSimon J. Gerraty static int 10325fff9558SSimon J. Gerraty test_hash(const br_hash_class *md, size_t hlen, 10335fff9558SSimon J. Gerraty const char *hname, const char *s, size_t slen, const char *want) 10345fff9558SSimon J. Gerraty { 10355fff9558SSimon J. Gerraty br_hash_compat_context mctx; 10365fff9558SSimon J. Gerraty 10375fff9558SSimon J. Gerraty md->init(&mctx.vtable); 10385fff9558SSimon J. Gerraty md->update(&mctx.vtable, s, slen); 10395fff9558SSimon J. Gerraty return (ve_check_hash(&mctx, md, hname, want, hlen) != VE_FINGERPRINT_OK); 10405fff9558SSimon J. Gerraty } 10415fff9558SSimon J. Gerraty 10425fff9558SSimon J. Gerraty #endif 10435fff9558SSimon J. Gerraty 10445fff9558SSimon J. Gerraty #define ve_test_hash(n, N) \ 10455fff9558SSimon J. Gerraty printf("Testing hash: " #n "\t\t\t\t%s\n", \ 10465fff9558SSimon J. Gerraty test_hash(&br_ ## n ## _vtable, br_ ## n ## _SIZE, #n, \ 10479bee6a60SSimon J. Gerraty VE_HASH_KAT_STR, VE_HASH_KAT_STRLEN(VE_HASH_KAT_STR), \ 10485fff9558SSimon J. Gerraty vh_ ## N) ? "Failed" : "Passed") 10495fff9558SSimon J. Gerraty 10505fff9558SSimon J. Gerraty /** 10515fff9558SSimon J. Gerraty * @brief 10525fff9558SSimon J. Gerraty * run self tests on hash and signature verification 10535fff9558SSimon J. Gerraty * 10545fff9558SSimon J. Gerraty * Test that the hash methods (SHA1 and SHA256) work. 10555fff9558SSimon J. Gerraty * Test that we can verify a certificate for each supported 10565fff9558SSimon J. Gerraty * Root CA. 10575fff9558SSimon J. Gerraty * 10585fff9558SSimon J. Gerraty * @return cached result. 10595fff9558SSimon J. Gerraty */ 10605fff9558SSimon J. Gerraty int 10615fff9558SSimon J. Gerraty ve_self_tests(void) 10625fff9558SSimon J. Gerraty { 10635fff9558SSimon J. Gerraty static int once = -1; 10645fff9558SSimon J. Gerraty #ifdef VERIFY_CERTS_STR 10655fff9558SSimon J. Gerraty br_x509_certificate *xcs; 10665fff9558SSimon J. Gerraty br_x509_pkey *pk; 10675fff9558SSimon J. Gerraty br_name_element cn; 10685fff9558SSimon J. Gerraty char cn_buf[80]; 10695fff9558SSimon J. Gerraty unsigned char cn_oid[4]; 10705fff9558SSimon J. Gerraty size_t num; 10715fff9558SSimon J. Gerraty size_t u; 10725fff9558SSimon J. Gerraty #endif 10735fff9558SSimon J. Gerraty 10745fff9558SSimon J. Gerraty if (once >= 0) 10755fff9558SSimon J. Gerraty return (once); 10765fff9558SSimon J. Gerraty once = 0; 10775fff9558SSimon J. Gerraty 10785fff9558SSimon J. Gerraty DEBUG_PRINTF(5, ("Self tests...\n")); 10795fff9558SSimon J. Gerraty #ifdef VE_HASH_KAT_STR 10805fff9558SSimon J. Gerraty #ifdef VE_SHA1_SUPPORT 10815fff9558SSimon J. Gerraty ve_test_hash(sha1, SHA1); 10825fff9558SSimon J. Gerraty #endif 10835fff9558SSimon J. Gerraty #ifdef VE_SHA256_SUPPORT 10845fff9558SSimon J. Gerraty ve_test_hash(sha256, SHA256); 10855fff9558SSimon J. Gerraty #endif 10865fff9558SSimon J. Gerraty #ifdef VE_SHA384_SUPPORT 10875fff9558SSimon J. Gerraty ve_test_hash(sha384, SHA384); 10885fff9558SSimon J. Gerraty #endif 10895fff9558SSimon J. Gerraty #ifdef VE_SHA512_SUPPORT 10905fff9558SSimon J. Gerraty ve_test_hash(sha512, SHA512); 10915fff9558SSimon J. Gerraty #endif 10925fff9558SSimon J. Gerraty #endif 10935fff9558SSimon J. Gerraty #ifdef VERIFY_CERTS_STR 10945fff9558SSimon J. Gerraty xcs = parse_certificates(__DECONST(unsigned char *, VERIFY_CERTS_STR), 10955fff9558SSimon J. Gerraty sizeof(VERIFY_CERTS_STR), &num); 10969bee6a60SSimon J. Gerraty if (xcs != NULL) { 10975fff9558SSimon J. Gerraty /* 10985fff9558SSimon J. Gerraty * We want the commonName field 10995fff9558SSimon J. Gerraty * the OID we want is 2,5,4,3 - but DER encoded 11005fff9558SSimon J. Gerraty */ 11015fff9558SSimon J. Gerraty cn_oid[0] = 3; 11025fff9558SSimon J. Gerraty cn_oid[1] = 0x55; 11035fff9558SSimon J. Gerraty cn_oid[2] = 4; 11045fff9558SSimon J. Gerraty cn_oid[3] = 3; 11055fff9558SSimon J. Gerraty cn.oid = cn_oid; 11065fff9558SSimon J. Gerraty cn.buf = cn_buf; 11075fff9558SSimon J. Gerraty 11085fff9558SSimon J. Gerraty for (u = 0; u < num; u ++) { 11095fff9558SSimon J. Gerraty cn.len = sizeof(cn_buf); 111013ea0450SMarcin Wojtas if ((pk = verify_signer_xcs(&xcs[u], 1, &cn, 1, &trust_anchors)) != NULL) { 111113ea0450SMarcin Wojtas free_cert_contents(&xcs[u]); 11125fff9558SSimon J. Gerraty once++; 11135fff9558SSimon J. Gerraty printf("Testing verify certificate: %s\tPassed\n", 11145fff9558SSimon J. Gerraty cn.status ? cn_buf : ""); 11155fff9558SSimon J. Gerraty xfreepkey(pk); 11165fff9558SSimon J. Gerraty } 11175fff9558SSimon J. Gerraty } 11185fff9558SSimon J. Gerraty if (!once) 11195fff9558SSimon J. Gerraty printf("Testing verify certificate:\t\t\tFailed\n"); 11205fff9558SSimon J. Gerraty xfree(xcs); 11219bee6a60SSimon J. Gerraty } 11225fff9558SSimon J. Gerraty #endif /* VERIFY_CERTS_STR */ 11235fff9558SSimon J. Gerraty #ifdef VE_OPENPGP_SUPPORT 11245fff9558SSimon J. Gerraty if (!openpgp_self_tests()) 11255fff9558SSimon J. Gerraty once++; 11265fff9558SSimon J. Gerraty #endif 11275fff9558SSimon J. Gerraty return (once); 11285fff9558SSimon J. Gerraty } 1129