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 465fff9558SSimon J. Gerraty #define SECONDS_PER_DAY 86400 475fff9558SSimon J. Gerraty #define X509_DAYS_TO_UTC0 719528 485fff9558SSimon J. Gerraty 495fff9558SSimon J. Gerraty int DebugVe = 0; 505fff9558SSimon J. Gerraty 515fff9558SSimon J. Gerraty typedef VECTOR(br_x509_certificate) cert_list; 52*13ea0450SMarcin Wojtas typedef VECTOR(hash_data) digest_list; 535fff9558SSimon J. Gerraty 545fff9558SSimon J. Gerraty static anchor_list trust_anchors = VEC_INIT; 55*13ea0450SMarcin Wojtas static anchor_list forbidden_anchors = VEC_INIT; 56*13ea0450SMarcin Wojtas static digest_list forbidden_digests = VEC_INIT; 575fff9558SSimon J. Gerraty 585fff9558SSimon J. Gerraty void 595fff9558SSimon J. Gerraty ve_debug_set(int n) 605fff9558SSimon J. Gerraty { 615fff9558SSimon J. Gerraty DebugVe = n; 625fff9558SSimon J. Gerraty } 635fff9558SSimon J. Gerraty 645fff9558SSimon J. Gerraty static char ebuf[512]; 655fff9558SSimon J. Gerraty 665fff9558SSimon J. Gerraty char * 675fff9558SSimon J. Gerraty ve_error_get(void) 685fff9558SSimon J. Gerraty { 695fff9558SSimon J. Gerraty return (ebuf); 705fff9558SSimon J. Gerraty } 715fff9558SSimon J. Gerraty 725fff9558SSimon J. Gerraty int 735fff9558SSimon J. Gerraty ve_error_set(const char *fmt, ...) 745fff9558SSimon J. Gerraty { 755fff9558SSimon J. Gerraty int rc; 765fff9558SSimon J. Gerraty va_list ap; 775fff9558SSimon J. Gerraty 785fff9558SSimon J. Gerraty va_start(ap, fmt); 795fff9558SSimon J. Gerraty ebuf[0] = '\0'; 805fff9558SSimon J. Gerraty rc = 0; 815fff9558SSimon J. Gerraty if (fmt) { 825fff9558SSimon J. Gerraty #ifdef STAND_H 835fff9558SSimon J. Gerraty vsprintf(ebuf, fmt, ap); /* no vsnprintf in libstand */ 845fff9558SSimon J. Gerraty ebuf[sizeof(ebuf) - 1] = '\0'; 855fff9558SSimon J. Gerraty rc = strlen(ebuf); 865fff9558SSimon J. Gerraty #else 875fff9558SSimon J. Gerraty rc = vsnprintf(ebuf, sizeof(ebuf), fmt, ap); 885fff9558SSimon J. Gerraty #endif 895fff9558SSimon J. Gerraty } 905fff9558SSimon J. Gerraty va_end(ap); 915fff9558SSimon J. Gerraty return (rc); 925fff9558SSimon J. Gerraty } 935fff9558SSimon J. Gerraty 945fff9558SSimon J. Gerraty /* this is the time we use for verifying certs */ 955fff9558SSimon J. Gerraty static time_t ve_utc = 0; 965fff9558SSimon J. Gerraty 975fff9558SSimon J. Gerraty /** 985fff9558SSimon J. Gerraty * @brief 995fff9558SSimon J. Gerraty * set ve_utc used for certificate verification 1005fff9558SSimon J. Gerraty * 1015fff9558SSimon J. Gerraty * @param[in] utc 1025fff9558SSimon J. Gerraty * time - ignored unless greater than current value. 1035fff9558SSimon J. Gerraty */ 1045fff9558SSimon J. Gerraty void 1055fff9558SSimon J. Gerraty ve_utc_set(time_t utc) 1065fff9558SSimon J. Gerraty { 1075fff9558SSimon J. Gerraty if (utc > ve_utc) { 1085fff9558SSimon J. Gerraty DEBUG_PRINTF(2, ("Set ve_utc=%jd\n", (intmax_t)utc)); 1095fff9558SSimon J. Gerraty ve_utc = utc; 1105fff9558SSimon J. Gerraty } 1115fff9558SSimon J. Gerraty } 1125fff9558SSimon J. Gerraty 1135fff9558SSimon J. Gerraty static void 1145fff9558SSimon J. Gerraty free_cert_contents(br_x509_certificate *xc) 1155fff9558SSimon J. Gerraty { 1165fff9558SSimon J. Gerraty xfree(xc->data); 1175fff9558SSimon J. Gerraty } 1185fff9558SSimon J. Gerraty 119*13ea0450SMarcin Wojtas /* ASN parsing related defines */ 120*13ea0450SMarcin Wojtas #define ASN1_PRIMITIVE_TAG 0x1F 121*13ea0450SMarcin Wojtas #define ASN1_INF_LENGTH 0x80 122*13ea0450SMarcin Wojtas #define ASN1_LENGTH_MASK 0x7F 123*13ea0450SMarcin Wojtas 124*13ea0450SMarcin Wojtas /* 125*13ea0450SMarcin Wojtas * Get TBS part of certificate. 126*13ea0450SMarcin Wojtas * Since BearSSL doesn't provide any API to do this, 127*13ea0450SMarcin Wojtas * it has to be implemented here. 1285fff9558SSimon J. Gerraty */ 129*13ea0450SMarcin Wojtas static void* 130*13ea0450SMarcin Wojtas X509_to_tbs(unsigned char* cert, size_t* output_size) 131*13ea0450SMarcin Wojtas { 132*13ea0450SMarcin Wojtas unsigned char *result; 133*13ea0450SMarcin Wojtas size_t tbs_size; 134*13ea0450SMarcin Wojtas int size, i; 135*13ea0450SMarcin Wojtas 136*13ea0450SMarcin Wojtas if (cert == NULL) 137*13ea0450SMarcin Wojtas return (NULL); 138*13ea0450SMarcin Wojtas 139*13ea0450SMarcin Wojtas /* Strip two sequences to get to the TBS section */ 140*13ea0450SMarcin Wojtas for (i = 0; i < 2; i++) { 141*13ea0450SMarcin Wojtas /* 142*13ea0450SMarcin Wojtas * XXX: We don't need to support extended tags since 143*13ea0450SMarcin Wojtas * they should not be present in certificates. 144*13ea0450SMarcin Wojtas */ 145*13ea0450SMarcin Wojtas if ((*cert & ASN1_PRIMITIVE_TAG) == ASN1_PRIMITIVE_TAG) 146*13ea0450SMarcin Wojtas return (NULL); 147*13ea0450SMarcin Wojtas 148*13ea0450SMarcin Wojtas cert++; 149*13ea0450SMarcin Wojtas 150*13ea0450SMarcin Wojtas if (*cert == ASN1_INF_LENGTH) 151*13ea0450SMarcin Wojtas return (NULL); 152*13ea0450SMarcin Wojtas 153*13ea0450SMarcin Wojtas size = *cert & ASN1_LENGTH_MASK; 154*13ea0450SMarcin Wojtas tbs_size = 0; 155*13ea0450SMarcin Wojtas 156*13ea0450SMarcin Wojtas /* Size can either be stored on a single or multiple bytes */ 157*13ea0450SMarcin Wojtas if (*cert & (ASN1_LENGTH_MASK + 1)) { 158*13ea0450SMarcin Wojtas cert++; 159*13ea0450SMarcin Wojtas while (*cert == 0 && size > 0) { 160*13ea0450SMarcin Wojtas cert++; 161*13ea0450SMarcin Wojtas size--; 162*13ea0450SMarcin Wojtas } 163*13ea0450SMarcin Wojtas while (size-- > 0) { 164*13ea0450SMarcin Wojtas tbs_size <<= 8; 165*13ea0450SMarcin Wojtas tbs_size |= *(cert++); 166*13ea0450SMarcin Wojtas } 167*13ea0450SMarcin Wojtas } 168*13ea0450SMarcin Wojtas if (i == 0) 169*13ea0450SMarcin Wojtas result = cert; 170*13ea0450SMarcin Wojtas } 171*13ea0450SMarcin Wojtas tbs_size += (cert - result); 172*13ea0450SMarcin Wojtas 173*13ea0450SMarcin Wojtas if (output_size != NULL) 174*13ea0450SMarcin Wojtas *output_size = tbs_size; 175*13ea0450SMarcin Wojtas 176*13ea0450SMarcin Wojtas return (result); 177*13ea0450SMarcin Wojtas } 178*13ea0450SMarcin Wojtas 179*13ea0450SMarcin Wojtas void 180*13ea0450SMarcin Wojtas ve_forbidden_digest_add(hash_data *digest, size_t num) 181*13ea0450SMarcin Wojtas { 182*13ea0450SMarcin Wojtas while (num--) 183*13ea0450SMarcin Wojtas VEC_ADD(forbidden_digests, digest[num]); 184*13ea0450SMarcin Wojtas } 185*13ea0450SMarcin Wojtas 186*13ea0450SMarcin Wojtas static size_t 187*13ea0450SMarcin Wojtas ve_anchors_add(br_x509_certificate *xcs, size_t num, anchor_list *anchors) 1885fff9558SSimon J. Gerraty { 1895fff9558SSimon J. Gerraty br_x509_trust_anchor ta; 1905fff9558SSimon J. Gerraty size_t u; 1915fff9558SSimon J. Gerraty 1925fff9558SSimon J. Gerraty for (u = 0; u < num; u++) { 1935fff9558SSimon J. Gerraty if (certificate_to_trust_anchor_inner(&ta, &xcs[u]) < 0) { 1945fff9558SSimon J. Gerraty break; 1955fff9558SSimon J. Gerraty } 196*13ea0450SMarcin Wojtas VEC_ADD(*anchors, ta); 1975fff9558SSimon J. Gerraty } 1985fff9558SSimon J. Gerraty return (u); 1995fff9558SSimon J. Gerraty } 2005fff9558SSimon J. Gerraty 2015fff9558SSimon J. Gerraty /** 2025fff9558SSimon J. Gerraty * @brief 203*13ea0450SMarcin Wojtas * add certs to our trust store 204*13ea0450SMarcin Wojtas */ 205*13ea0450SMarcin Wojtas size_t 206*13ea0450SMarcin Wojtas ve_trust_anchors_add(br_x509_certificate *xcs, size_t num) 207*13ea0450SMarcin Wojtas { 208*13ea0450SMarcin Wojtas return (ve_anchors_add(xcs, num, &trust_anchors)); 209*13ea0450SMarcin Wojtas } 210*13ea0450SMarcin Wojtas 211*13ea0450SMarcin Wojtas size_t 212*13ea0450SMarcin Wojtas ve_forbidden_anchors_add(br_x509_certificate *xcs, size_t num) 213*13ea0450SMarcin Wojtas { 214*13ea0450SMarcin Wojtas return (ve_anchors_add(xcs, num, &forbidden_anchors)); 215*13ea0450SMarcin Wojtas } 216*13ea0450SMarcin Wojtas 217*13ea0450SMarcin Wojtas /** 218*13ea0450SMarcin Wojtas * @brief 2195fff9558SSimon J. Gerraty * initialize our trust_anchors from ta_PEM 2205fff9558SSimon J. Gerraty */ 2215fff9558SSimon J. Gerraty int 2225fff9558SSimon J. Gerraty ve_trust_init(void) 2235fff9558SSimon J. Gerraty { 224*13ea0450SMarcin Wojtas #ifdef TRUST_ANCHOR_STR 2255fff9558SSimon J. Gerraty br_x509_certificate *xcs; 226*13ea0450SMarcin Wojtas #endif 2275fff9558SSimon J. Gerraty static int once = -1; 2285fff9558SSimon J. Gerraty size_t num; 2295fff9558SSimon J. Gerraty 2305fff9558SSimon J. Gerraty if (once >= 0) 2315fff9558SSimon J. Gerraty return (once); 2325fff9558SSimon J. Gerraty 2335fff9558SSimon J. Gerraty ve_utc_set(time(NULL)); 2345fff9558SSimon J. Gerraty #ifdef BUILD_UTC 2355fff9558SSimon J. Gerraty ve_utc_set(BUILD_UTC); /* just in case */ 2365fff9558SSimon J. Gerraty #endif 2375fff9558SSimon J. Gerraty ve_error_set(NULL); /* make sure it is empty */ 2385fff9558SSimon J. Gerraty #ifdef VE_PCR_SUPPORT 2395fff9558SSimon J. Gerraty ve_pcr_init(); 2405fff9558SSimon J. Gerraty #endif 2415fff9558SSimon J. Gerraty 2425fff9558SSimon J. Gerraty #ifdef TRUST_ANCHOR_STR 2435fff9558SSimon J. Gerraty xcs = parse_certificates(__DECONST(unsigned char *, TRUST_ANCHOR_STR), 2445fff9558SSimon J. Gerraty sizeof(TRUST_ANCHOR_STR), &num); 245*13ea0450SMarcin Wojtas if (xcs != NULL) 2465fff9558SSimon J. Gerraty num = ve_trust_anchors_add(xcs, num); 2475fff9558SSimon J. Gerraty #endif 248*13ea0450SMarcin Wojtas once = (int) VEC_LEN(trust_anchors); 249*13ea0450SMarcin Wojtas 250*13ea0450SMarcin Wojtas return (once); 2515fff9558SSimon J. Gerraty } 2525fff9558SSimon J. Gerraty 2535fff9558SSimon J. Gerraty /** 2545fff9558SSimon J. Gerraty * if we can verify the certificate chain in "certs", 2555fff9558SSimon J. Gerraty * return the public key and if "xcp" is !NULL the associated 2565fff9558SSimon J. Gerraty * certificate 2575fff9558SSimon J. Gerraty */ 2585fff9558SSimon J. Gerraty static br_x509_pkey * 2595fff9558SSimon J. Gerraty verify_signer_xcs(br_x509_certificate *xcs, 2605fff9558SSimon J. Gerraty size_t num, 261*13ea0450SMarcin Wojtas br_name_element *elts, size_t num_elts, 262*13ea0450SMarcin Wojtas anchor_list *anchors) 2635fff9558SSimon J. Gerraty { 2645fff9558SSimon J. Gerraty br_x509_minimal_context mc; 2655fff9558SSimon J. Gerraty br_x509_certificate *xc; 2665fff9558SSimon J. Gerraty size_t u; 2675fff9558SSimon J. Gerraty cert_list chain = VEC_INIT; 2685fff9558SSimon J. Gerraty const br_x509_pkey *tpk; 2695fff9558SSimon J. Gerraty br_x509_pkey *pk; 2705fff9558SSimon J. Gerraty unsigned int usages; 2715fff9558SSimon J. Gerraty int err; 2725fff9558SSimon J. Gerraty 2735fff9558SSimon J. Gerraty DEBUG_PRINTF(5, ("verify_signer: %zu certs in chain\n", num)); 2745fff9558SSimon J. Gerraty VEC_ADDMANY(chain, xcs, num); 2755fff9558SSimon J. Gerraty if (VEC_LEN(chain) == 0) { 2765fff9558SSimon J. Gerraty ve_error_set("ERROR: no/invalid certificate chain\n"); 2775fff9558SSimon J. Gerraty return (NULL); 2785fff9558SSimon J. Gerraty } 2795fff9558SSimon J. Gerraty 2805fff9558SSimon J. Gerraty DEBUG_PRINTF(5, ("verify_signer: %zu trust anchors\n", 281*13ea0450SMarcin Wojtas VEC_LEN(*anchors))); 2825fff9558SSimon J. Gerraty 2835fff9558SSimon J. Gerraty br_x509_minimal_init(&mc, &br_sha256_vtable, 284*13ea0450SMarcin Wojtas &VEC_ELT(*anchors, 0), 285*13ea0450SMarcin Wojtas VEC_LEN(*anchors)); 2865fff9558SSimon J. Gerraty #ifdef VE_ECDSA_SUPPORT 2875fff9558SSimon J. Gerraty br_x509_minimal_set_ecdsa(&mc, 2885fff9558SSimon J. Gerraty &br_ec_prime_i31, &br_ecdsa_i31_vrfy_asn1); 2895fff9558SSimon J. Gerraty #endif 2905fff9558SSimon J. Gerraty #ifdef VE_RSA_SUPPORT 2915fff9558SSimon J. Gerraty br_x509_minimal_set_rsa(&mc, &br_rsa_i31_pkcs1_vrfy); 2925fff9558SSimon J. Gerraty #endif 2935fff9558SSimon J. Gerraty #if defined(UNIT_TEST) && defined(VE_DEPRECATED_RSA_SHA1_SUPPORT) 2945fff9558SSimon J. Gerraty /* This is deprecated! do not enable unless you absoultely have to */ 2955fff9558SSimon J. Gerraty br_x509_minimal_set_hash(&mc, br_sha1_ID, &br_sha1_vtable); 2965fff9558SSimon J. Gerraty #endif 2975fff9558SSimon J. Gerraty br_x509_minimal_set_hash(&mc, br_sha256_ID, &br_sha256_vtable); 2985fff9558SSimon J. Gerraty #ifdef VE_SHA384_SUPPORT 2995fff9558SSimon J. Gerraty br_x509_minimal_set_hash(&mc, br_sha384_ID, &br_sha384_vtable); 3005fff9558SSimon J. Gerraty #endif 3015fff9558SSimon J. Gerraty #ifdef VE_SHA512_SUPPORT 3025fff9558SSimon J. Gerraty br_x509_minimal_set_hash(&mc, br_sha512_ID, &br_sha512_vtable); 3035fff9558SSimon J. Gerraty #endif 3045fff9558SSimon J. Gerraty br_x509_minimal_set_name_elements(&mc, elts, num_elts); 3055fff9558SSimon J. Gerraty 3065fff9558SSimon J. Gerraty #ifdef _STANDALONE 3075fff9558SSimon J. Gerraty /* 3085fff9558SSimon J. Gerraty * Clock is probably bogus so we use ve_utc. 3095fff9558SSimon J. Gerraty */ 3105fff9558SSimon J. Gerraty mc.days = (ve_utc / SECONDS_PER_DAY) + X509_DAYS_TO_UTC0; 3115fff9558SSimon J. Gerraty mc.seconds = (ve_utc % SECONDS_PER_DAY); 3125fff9558SSimon J. Gerraty #endif 3135fff9558SSimon J. Gerraty 3145fff9558SSimon J. Gerraty mc.vtable->start_chain(&mc.vtable, NULL); 3155fff9558SSimon J. Gerraty for (u = 0; u < VEC_LEN(chain); u ++) { 3165fff9558SSimon J. Gerraty xc = &VEC_ELT(chain, u); 3175fff9558SSimon J. Gerraty mc.vtable->start_cert(&mc.vtable, xc->data_len); 3185fff9558SSimon J. Gerraty mc.vtable->append(&mc.vtable, xc->data, xc->data_len); 3195fff9558SSimon J. Gerraty mc.vtable->end_cert(&mc.vtable); 3205fff9558SSimon J. Gerraty switch (mc.err) { 3215fff9558SSimon J. Gerraty case 0: 3225fff9558SSimon J. Gerraty case BR_ERR_X509_OK: 3235fff9558SSimon J. Gerraty case BR_ERR_X509_EXPIRED: 3245fff9558SSimon J. Gerraty break; 3255fff9558SSimon J. Gerraty default: 3265fff9558SSimon J. Gerraty printf("u=%zu mc.err=%d\n", u, mc.err); 3275fff9558SSimon J. Gerraty break; 3285fff9558SSimon J. Gerraty } 3295fff9558SSimon J. Gerraty } 3305fff9558SSimon J. Gerraty err = mc.vtable->end_chain(&mc.vtable); 3315fff9558SSimon J. Gerraty pk = NULL; 3325fff9558SSimon J. Gerraty if (err) { 3335fff9558SSimon J. Gerraty ve_error_set("Validation failed, err = %d", err); 3345fff9558SSimon J. Gerraty } else { 3355fff9558SSimon J. Gerraty tpk = mc.vtable->get_pkey(&mc.vtable, &usages); 3365fff9558SSimon J. Gerraty if (tpk != NULL) { 3375fff9558SSimon J. Gerraty pk = xpkeydup(tpk); 3385fff9558SSimon J. Gerraty } 3395fff9558SSimon J. Gerraty } 340*13ea0450SMarcin Wojtas VEC_CLEAR(chain); 3415fff9558SSimon J. Gerraty return (pk); 3425fff9558SSimon J. Gerraty } 3435fff9558SSimon J. Gerraty 344*13ea0450SMarcin Wojtas /* 345*13ea0450SMarcin Wojtas * Check if digest of one of the certificates from verified chain 346*13ea0450SMarcin Wojtas * is present in the forbidden database. 347*13ea0450SMarcin Wojtas * Since UEFI allows to store three types of digests 348*13ea0450SMarcin Wojtas * all of them have to be checked separately. 349*13ea0450SMarcin Wojtas */ 350*13ea0450SMarcin Wojtas static int 351*13ea0450SMarcin Wojtas check_forbidden_digests(br_x509_certificate *xcs, size_t num) 352*13ea0450SMarcin Wojtas { 353*13ea0450SMarcin Wojtas unsigned char sha256_digest[br_sha256_SIZE]; 354*13ea0450SMarcin Wojtas unsigned char sha384_digest[br_sha384_SIZE]; 355*13ea0450SMarcin Wojtas unsigned char sha512_digest[br_sha512_SIZE]; 356*13ea0450SMarcin Wojtas void *tbs; 357*13ea0450SMarcin Wojtas hash_data *digest; 358*13ea0450SMarcin Wojtas br_hash_compat_context ctx; 359*13ea0450SMarcin Wojtas const br_hash_class *md; 360*13ea0450SMarcin Wojtas size_t tbs_len, i; 361*13ea0450SMarcin Wojtas int have_sha256, have_sha384, have_sha512; 362*13ea0450SMarcin Wojtas 363*13ea0450SMarcin Wojtas if (VEC_LEN(forbidden_digests) == 0) 364*13ea0450SMarcin Wojtas return (0); 365*13ea0450SMarcin Wojtas 366*13ea0450SMarcin Wojtas /* 367*13ea0450SMarcin Wojtas * Iterate through certificates, extract their To-Be-Signed section, 368*13ea0450SMarcin Wojtas * and compare its digest against the ones in the forbidden database. 369*13ea0450SMarcin Wojtas */ 370*13ea0450SMarcin Wojtas while (num--) { 371*13ea0450SMarcin Wojtas tbs = X509_to_tbs(xcs[num].data, &tbs_len); 372*13ea0450SMarcin Wojtas if (tbs == NULL) { 373*13ea0450SMarcin Wojtas printf("Failed to obtain TBS part of certificate\n"); 374*13ea0450SMarcin Wojtas return (1); 375*13ea0450SMarcin Wojtas } 376*13ea0450SMarcin Wojtas have_sha256 = have_sha384 = have_sha512 = 0; 377*13ea0450SMarcin Wojtas 378*13ea0450SMarcin Wojtas for (i = 0; i < VEC_LEN(forbidden_digests); i++) { 379*13ea0450SMarcin Wojtas digest = &VEC_ELT(forbidden_digests, i); 380*13ea0450SMarcin Wojtas switch (digest->hash_size) { 381*13ea0450SMarcin Wojtas case br_sha256_SIZE: 382*13ea0450SMarcin Wojtas if (!have_sha256) { 383*13ea0450SMarcin Wojtas have_sha256 = 1; 384*13ea0450SMarcin Wojtas md = &br_sha256_vtable; 385*13ea0450SMarcin Wojtas md->init(&ctx.vtable); 386*13ea0450SMarcin Wojtas md->update(&ctx.vtable, tbs, tbs_len); 387*13ea0450SMarcin Wojtas md->out(&ctx.vtable, sha256_digest); 388*13ea0450SMarcin Wojtas } 389*13ea0450SMarcin Wojtas if (!memcmp(sha256_digest, 390*13ea0450SMarcin Wojtas digest->data, 391*13ea0450SMarcin Wojtas br_sha256_SIZE)) 392*13ea0450SMarcin Wojtas return (1); 393*13ea0450SMarcin Wojtas 394*13ea0450SMarcin Wojtas break; 395*13ea0450SMarcin Wojtas case br_sha384_SIZE: 396*13ea0450SMarcin Wojtas if (!have_sha384) { 397*13ea0450SMarcin Wojtas have_sha384 = 1; 398*13ea0450SMarcin Wojtas md = &br_sha384_vtable; 399*13ea0450SMarcin Wojtas md->init(&ctx.vtable); 400*13ea0450SMarcin Wojtas md->update(&ctx.vtable, tbs, tbs_len); 401*13ea0450SMarcin Wojtas md->out(&ctx.vtable, sha384_digest); 402*13ea0450SMarcin Wojtas } 403*13ea0450SMarcin Wojtas if (!memcmp(sha384_digest, 404*13ea0450SMarcin Wojtas digest->data, 405*13ea0450SMarcin Wojtas br_sha384_SIZE)) 406*13ea0450SMarcin Wojtas return (1); 407*13ea0450SMarcin Wojtas 408*13ea0450SMarcin Wojtas break; 409*13ea0450SMarcin Wojtas case br_sha512_SIZE: 410*13ea0450SMarcin Wojtas if (!have_sha512) { 411*13ea0450SMarcin Wojtas have_sha512 = 1; 412*13ea0450SMarcin Wojtas md = &br_sha512_vtable; 413*13ea0450SMarcin Wojtas md->init(&ctx.vtable); 414*13ea0450SMarcin Wojtas md->update(&ctx.vtable, tbs, tbs_len); 415*13ea0450SMarcin Wojtas md->out(&ctx.vtable, sha512_digest); 416*13ea0450SMarcin Wojtas } 417*13ea0450SMarcin Wojtas if (!memcmp(sha512_digest, 418*13ea0450SMarcin Wojtas digest->data, 419*13ea0450SMarcin Wojtas br_sha512_SIZE)) 420*13ea0450SMarcin Wojtas return (1); 421*13ea0450SMarcin Wojtas 422*13ea0450SMarcin Wojtas break; 423*13ea0450SMarcin Wojtas } 424*13ea0450SMarcin Wojtas } 425*13ea0450SMarcin Wojtas } 426*13ea0450SMarcin Wojtas 427*13ea0450SMarcin Wojtas return (0); 428*13ea0450SMarcin Wojtas } 429*13ea0450SMarcin Wojtas 4305fff9558SSimon J. Gerraty static br_x509_pkey * 4315fff9558SSimon J. Gerraty verify_signer(const char *certs, 4325fff9558SSimon J. Gerraty br_name_element *elts, size_t num_elts) 4335fff9558SSimon J. Gerraty { 4345fff9558SSimon J. Gerraty br_x509_certificate *xcs; 4355fff9558SSimon J. Gerraty br_x509_pkey *pk; 4365fff9558SSimon J. Gerraty size_t num; 4375fff9558SSimon J. Gerraty 438*13ea0450SMarcin Wojtas pk = NULL; 439*13ea0450SMarcin Wojtas 4405fff9558SSimon J. Gerraty ve_trust_init(); 4415fff9558SSimon J. Gerraty xcs = read_certificates(certs, &num); 4425fff9558SSimon J. Gerraty if (xcs == NULL) { 4435fff9558SSimon J. Gerraty ve_error_set("cannot read certificates\n"); 4445fff9558SSimon J. Gerraty return (NULL); 4455fff9558SSimon J. Gerraty } 446*13ea0450SMarcin Wojtas 447*13ea0450SMarcin Wojtas /* 448*13ea0450SMarcin Wojtas * Check if either 449*13ea0450SMarcin Wojtas * 1. There is a direct match between cert from forbidden_anchors 450*13ea0450SMarcin Wojtas * and a cert from chain. 451*13ea0450SMarcin Wojtas * 2. CA that signed the chain is found in forbidden_anchors. 452*13ea0450SMarcin Wojtas */ 453*13ea0450SMarcin Wojtas if (VEC_LEN(forbidden_anchors) > 0) 454*13ea0450SMarcin Wojtas pk = verify_signer_xcs(xcs, num, elts, num_elts, &forbidden_anchors); 455*13ea0450SMarcin Wojtas if (pk != NULL) { 456*13ea0450SMarcin Wojtas ve_error_set("Certificate is on forbidden list\n"); 457*13ea0450SMarcin Wojtas xfreepkey(pk); 458*13ea0450SMarcin Wojtas pk = NULL; 459*13ea0450SMarcin Wojtas goto out; 460*13ea0450SMarcin Wojtas } 461*13ea0450SMarcin Wojtas 462*13ea0450SMarcin Wojtas pk = verify_signer_xcs(xcs, num, elts, num_elts, &trust_anchors); 463*13ea0450SMarcin Wojtas if (pk == NULL) 464*13ea0450SMarcin Wojtas goto out; 465*13ea0450SMarcin Wojtas 466*13ea0450SMarcin Wojtas /* 467*13ea0450SMarcin Wojtas * Check if hash of tbs part of any certificate in chain 468*13ea0450SMarcin Wojtas * is on the forbidden list. 469*13ea0450SMarcin Wojtas */ 470*13ea0450SMarcin Wojtas if (check_forbidden_digests(xcs, num)) { 471*13ea0450SMarcin Wojtas ve_error_set("Certificate hash is on forbidden list\n"); 472*13ea0450SMarcin Wojtas xfreepkey(pk); 473*13ea0450SMarcin Wojtas pk = NULL; 474*13ea0450SMarcin Wojtas } 475*13ea0450SMarcin Wojtas out: 476*13ea0450SMarcin Wojtas free_certificates(xcs, num); 4775fff9558SSimon J. Gerraty return (pk); 4785fff9558SSimon J. Gerraty } 4795fff9558SSimon J. Gerraty 4805fff9558SSimon J. Gerraty /** 4815fff9558SSimon J. Gerraty * we need a hex digest including trailing newline below 4825fff9558SSimon J. Gerraty */ 4835fff9558SSimon J. Gerraty char * 4845fff9558SSimon J. Gerraty hexdigest(char *buf, size_t bufsz, unsigned char *foo, size_t foo_len) 4855fff9558SSimon J. Gerraty { 4865fff9558SSimon J. Gerraty char const hex2ascii[] = "0123456789abcdef"; 4875fff9558SSimon J. Gerraty size_t i; 4885fff9558SSimon J. Gerraty 4895fff9558SSimon J. Gerraty /* every binary byte is 2 chars in hex + newline + null */ 4905fff9558SSimon J. Gerraty if (bufsz < (2 * foo_len) + 2) 4915fff9558SSimon J. Gerraty return (NULL); 4925fff9558SSimon J. Gerraty 4935fff9558SSimon J. Gerraty for (i = 0; i < foo_len; i++) { 4945fff9558SSimon J. Gerraty buf[i * 2] = hex2ascii[foo[i] >> 4]; 4955fff9558SSimon J. Gerraty buf[i * 2 + 1] = hex2ascii[foo[i] & 0x0f]; 4965fff9558SSimon J. Gerraty } 4975fff9558SSimon J. Gerraty 4985fff9558SSimon J. Gerraty buf[i * 2] = 0x0A; /* we also want a newline */ 4995fff9558SSimon J. Gerraty buf[i * 2 + 1] = '\0'; 5005fff9558SSimon J. Gerraty 5015fff9558SSimon J. Gerraty return (buf); 5025fff9558SSimon J. Gerraty } 5035fff9558SSimon J. Gerraty 5045fff9558SSimon J. Gerraty /** 5055fff9558SSimon J. Gerraty * @brief 5065fff9558SSimon J. Gerraty * verify file against sigfile using pk 5075fff9558SSimon J. Gerraty * 5085fff9558SSimon J. Gerraty * When we generated the signature in sigfile, 5095fff9558SSimon J. Gerraty * we hashed (sha256) file, and sent that to signing server 5105fff9558SSimon J. Gerraty * which hashed (sha256) that hash. 5115fff9558SSimon J. Gerraty * 5125fff9558SSimon J. Gerraty * To verify we need to replicate that result. 5135fff9558SSimon J. Gerraty * 5145fff9558SSimon J. Gerraty * @param[in] pk 5155fff9558SSimon J. Gerraty * br_x509_pkey 5165fff9558SSimon J. Gerraty * 5175fff9558SSimon J. Gerraty * @paramp[in] file 5185fff9558SSimon J. Gerraty * file to be verified 5195fff9558SSimon J. Gerraty * 5205fff9558SSimon J. Gerraty * @param[in] sigfile 5215fff9558SSimon J. Gerraty * signature (PEM encoded) 5225fff9558SSimon J. Gerraty * 5235fff9558SSimon J. Gerraty * @return NULL on error, otherwise content of file. 5245fff9558SSimon J. Gerraty */ 5255fff9558SSimon J. Gerraty #ifdef VE_ECDSA_SUPPORT 5265fff9558SSimon J. Gerraty static unsigned char * 5275fff9558SSimon J. Gerraty verify_ec(br_x509_pkey *pk, const char *file, const char *sigfile) 5285fff9558SSimon J. Gerraty { 5295fff9558SSimon J. Gerraty char hexbuf[br_sha512_SIZE * 2 + 2]; 5305fff9558SSimon J. Gerraty unsigned char rhbuf[br_sha512_SIZE]; 5315fff9558SSimon J. Gerraty char *hex; 5325fff9558SSimon J. Gerraty br_sha256_context ctx; 5335fff9558SSimon J. Gerraty unsigned char *fcp, *scp; 5345fff9558SSimon J. Gerraty size_t flen, slen, plen; 5355fff9558SSimon J. Gerraty pem_object *po; 5365fff9558SSimon J. Gerraty const br_ec_impl *ec; 5375fff9558SSimon J. Gerraty br_ecdsa_vrfy vrfy; 5385fff9558SSimon J. Gerraty 5395fff9558SSimon J. Gerraty if ((fcp = read_file(file, &flen)) == NULL) 5405fff9558SSimon J. Gerraty return (NULL); 5415fff9558SSimon J. Gerraty if ((scp = read_file(sigfile, &slen)) == NULL) { 5425fff9558SSimon J. Gerraty free(fcp); 5435fff9558SSimon J. Gerraty return (NULL); 5445fff9558SSimon J. Gerraty } 5455fff9558SSimon J. Gerraty if ((po = decode_pem(scp, slen, &plen)) == NULL) { 5465fff9558SSimon J. Gerraty free(fcp); 5475fff9558SSimon J. Gerraty free(scp); 5485fff9558SSimon J. Gerraty return (NULL); 5495fff9558SSimon J. Gerraty } 5505fff9558SSimon J. Gerraty br_sha256_init(&ctx); 5515fff9558SSimon J. Gerraty br_sha256_update(&ctx, fcp, flen); 5525fff9558SSimon J. Gerraty br_sha256_out(&ctx, rhbuf); 5535fff9558SSimon J. Gerraty hex = hexdigest(hexbuf, sizeof(hexbuf), rhbuf, br_sha256_SIZE); 5545fff9558SSimon J. Gerraty /* now hash that */ 5555fff9558SSimon J. Gerraty if (hex) { 5565fff9558SSimon J. Gerraty br_sha256_init(&ctx); 5575fff9558SSimon J. Gerraty br_sha256_update(&ctx, hex, strlen(hex)); 5585fff9558SSimon J. Gerraty br_sha256_out(&ctx, rhbuf); 5595fff9558SSimon J. Gerraty } 5605fff9558SSimon J. Gerraty ec = br_ec_get_default(); 5615fff9558SSimon J. Gerraty vrfy = br_ecdsa_vrfy_asn1_get_default(); 5625fff9558SSimon J. Gerraty if (!vrfy(ec, rhbuf, br_sha256_SIZE, &pk->key.ec, po->data, 5635fff9558SSimon J. Gerraty po->data_len)) { 5645fff9558SSimon J. Gerraty free(fcp); 5655fff9558SSimon J. Gerraty fcp = NULL; 5665fff9558SSimon J. Gerraty } 5675fff9558SSimon J. Gerraty free(scp); 5685fff9558SSimon J. Gerraty return (fcp); 5695fff9558SSimon J. Gerraty } 5705fff9558SSimon J. Gerraty #endif 5715fff9558SSimon J. Gerraty 5725fff9558SSimon J. Gerraty #if defined(VE_RSA_SUPPORT) || defined(VE_OPENPGP_SUPPORT) 5735fff9558SSimon J. Gerraty /** 5745fff9558SSimon J. Gerraty * @brief verify an rsa digest 5755fff9558SSimon J. Gerraty * 5765fff9558SSimon J. Gerraty * @return 0 on failure 5775fff9558SSimon J. Gerraty */ 5785fff9558SSimon J. Gerraty int 5795fff9558SSimon J. Gerraty verify_rsa_digest (br_rsa_public_key *pkey, 5805fff9558SSimon J. Gerraty const unsigned char *hash_oid, 5815fff9558SSimon J. Gerraty unsigned char *mdata, size_t mlen, 5825fff9558SSimon J. Gerraty unsigned char *sdata, size_t slen) 5835fff9558SSimon J. Gerraty { 5845fff9558SSimon J. Gerraty br_rsa_pkcs1_vrfy vrfy; 5855fff9558SSimon J. Gerraty unsigned char vhbuf[br_sha512_SIZE]; 5865fff9558SSimon J. Gerraty 5875fff9558SSimon J. Gerraty vrfy = br_rsa_pkcs1_vrfy_get_default(); 5885fff9558SSimon J. Gerraty 5895fff9558SSimon J. Gerraty if (!vrfy(sdata, slen, hash_oid, mlen, pkey, vhbuf) || 5905fff9558SSimon J. Gerraty memcmp(vhbuf, mdata, mlen) != 0) { 5915fff9558SSimon J. Gerraty return (0); /* fail */ 5925fff9558SSimon J. Gerraty } 5935fff9558SSimon J. Gerraty return (1); /* ok */ 5945fff9558SSimon J. Gerraty } 5955fff9558SSimon J. Gerraty #endif 5965fff9558SSimon J. Gerraty 5975fff9558SSimon J. Gerraty /** 5985fff9558SSimon J. Gerraty * @brief 5995fff9558SSimon J. Gerraty * verify file against sigfile using pk 6005fff9558SSimon J. Gerraty * 6015fff9558SSimon J. Gerraty * When we generated the signature in sigfile, 6025fff9558SSimon J. Gerraty * we hashed (sha256) file, and sent that to signing server 6035fff9558SSimon J. Gerraty * which hashed (sha256) that hash. 6045fff9558SSimon J. Gerraty * 6055fff9558SSimon J. Gerraty * Or (deprecated) we simply used sha1 hash directly. 6065fff9558SSimon J. Gerraty * 6075fff9558SSimon J. Gerraty * To verify we need to replicate that result. 6085fff9558SSimon J. Gerraty * 6095fff9558SSimon J. Gerraty * @param[in] pk 6105fff9558SSimon J. Gerraty * br_x509_pkey 6115fff9558SSimon J. Gerraty * 6125fff9558SSimon J. Gerraty * @paramp[in] file 6135fff9558SSimon J. Gerraty * file to be verified 6145fff9558SSimon J. Gerraty * 6155fff9558SSimon J. Gerraty * @param[in] sigfile 6165fff9558SSimon J. Gerraty * signature (PEM encoded) 6175fff9558SSimon J. Gerraty * 6185fff9558SSimon J. Gerraty * @return NULL on error, otherwise content of file. 6195fff9558SSimon J. Gerraty */ 6205fff9558SSimon J. Gerraty #ifdef VE_RSA_SUPPORT 6215fff9558SSimon J. Gerraty static unsigned char * 6225fff9558SSimon J. Gerraty verify_rsa(br_x509_pkey *pk, const char *file, const char *sigfile) 6235fff9558SSimon J. Gerraty { 6245fff9558SSimon J. Gerraty unsigned char rhbuf[br_sha512_SIZE]; 6255fff9558SSimon J. Gerraty const unsigned char *hash_oid; 6265fff9558SSimon J. Gerraty const br_hash_class *md; 6275fff9558SSimon J. Gerraty br_hash_compat_context mctx; 6285fff9558SSimon J. Gerraty unsigned char *fcp, *scp; 6295fff9558SSimon J. Gerraty size_t flen, slen, plen, hlen; 6305fff9558SSimon J. Gerraty pem_object *po; 6315fff9558SSimon J. Gerraty 6325fff9558SSimon J. Gerraty if ((fcp = read_file(file, &flen)) == NULL) 6335fff9558SSimon J. Gerraty return (NULL); 6345fff9558SSimon J. Gerraty if ((scp = read_file(sigfile, &slen)) == NULL) { 6355fff9558SSimon J. Gerraty free(fcp); 6365fff9558SSimon J. Gerraty return (NULL); 6375fff9558SSimon J. Gerraty } 6385fff9558SSimon J. Gerraty if ((po = decode_pem(scp, slen, &plen)) == NULL) { 6395fff9558SSimon J. Gerraty free(fcp); 6405fff9558SSimon J. Gerraty free(scp); 6415fff9558SSimon J. Gerraty return (NULL); 6425fff9558SSimon J. Gerraty } 6435fff9558SSimon J. Gerraty 6445fff9558SSimon J. Gerraty switch (po->data_len) { 6455fff9558SSimon J. Gerraty #if defined(UNIT_TEST) && defined(VE_DEPRECATED_RSA_SHA1_SUPPORT) 6465fff9558SSimon J. Gerraty case 256: 6475fff9558SSimon J. Gerraty // this is our old deprecated sig method 6485fff9558SSimon J. Gerraty md = &br_sha1_vtable; 6495fff9558SSimon J. Gerraty hlen = br_sha1_SIZE; 6505fff9558SSimon J. Gerraty hash_oid = BR_HASH_OID_SHA1; 6515fff9558SSimon J. Gerraty break; 6525fff9558SSimon J. Gerraty #endif 6535fff9558SSimon J. Gerraty default: 6545fff9558SSimon J. Gerraty md = &br_sha256_vtable; 6555fff9558SSimon J. Gerraty hlen = br_sha256_SIZE; 6565fff9558SSimon J. Gerraty hash_oid = BR_HASH_OID_SHA256; 6575fff9558SSimon J. Gerraty break; 6585fff9558SSimon J. Gerraty } 6595fff9558SSimon J. Gerraty md->init(&mctx.vtable); 6605fff9558SSimon J. Gerraty md->update(&mctx.vtable, fcp, flen); 6615fff9558SSimon J. Gerraty md->out(&mctx.vtable, rhbuf); 6625fff9558SSimon J. Gerraty if (!verify_rsa_digest(&pk->key.rsa, hash_oid, 6635fff9558SSimon J. Gerraty rhbuf, hlen, po->data, po->data_len)) { 6645fff9558SSimon J. Gerraty free(fcp); 6655fff9558SSimon J. Gerraty fcp = NULL; 6665fff9558SSimon J. Gerraty } 6675fff9558SSimon J. Gerraty free(scp); 6685fff9558SSimon J. Gerraty return (fcp); 6695fff9558SSimon J. Gerraty } 6705fff9558SSimon J. Gerraty #endif 6715fff9558SSimon J. Gerraty 6725fff9558SSimon J. Gerraty /** 6735fff9558SSimon J. Gerraty * @brief 6745fff9558SSimon J. Gerraty * verify a signature and return content of signed file 6755fff9558SSimon J. Gerraty * 6765fff9558SSimon J. Gerraty * @param[in] sigfile 6775fff9558SSimon J. Gerraty * file containing signature 6785fff9558SSimon J. Gerraty * we derrive path of signed file and certificate change from 6795fff9558SSimon J. Gerraty * this. 6805fff9558SSimon J. Gerraty * 6815fff9558SSimon J. Gerraty * @param[in] flags 6825fff9558SSimon J. Gerraty * only bit 1 significant so far 6835fff9558SSimon J. Gerraty * 6845fff9558SSimon J. Gerraty * @return NULL on error otherwise content of signed file 6855fff9558SSimon J. Gerraty */ 6865fff9558SSimon J. Gerraty unsigned char * 6875fff9558SSimon J. Gerraty verify_sig(const char *sigfile, int flags) 6885fff9558SSimon J. Gerraty { 6895fff9558SSimon J. Gerraty br_x509_pkey *pk; 6905fff9558SSimon J. Gerraty br_name_element cn; 6915fff9558SSimon J. Gerraty char cn_buf[80]; 6925fff9558SSimon J. Gerraty unsigned char cn_oid[4]; 6935fff9558SSimon J. Gerraty char pbuf[MAXPATHLEN]; 6945fff9558SSimon J. Gerraty char *cp; 6955fff9558SSimon J. Gerraty unsigned char *ucp; 6965fff9558SSimon J. Gerraty size_t n; 6975fff9558SSimon J. Gerraty 6985fff9558SSimon J. Gerraty DEBUG_PRINTF(5, ("verify_sig: %s\n", sigfile)); 6995fff9558SSimon J. Gerraty n = strlcpy(pbuf, sigfile, sizeof(pbuf)); 7005fff9558SSimon J. Gerraty if (n > (sizeof(pbuf) - 5) || strcmp(&sigfile[n - 3], "sig") != 0) 7015fff9558SSimon J. Gerraty return (NULL); 7025fff9558SSimon J. Gerraty cp = strcpy(&pbuf[n - 3], "certs"); 7035fff9558SSimon J. Gerraty /* 7045fff9558SSimon J. Gerraty * We want the commonName field 7055fff9558SSimon J. Gerraty * the OID we want is 2,5,4,3 - but DER encoded 7065fff9558SSimon J. Gerraty */ 7075fff9558SSimon J. Gerraty cn_oid[0] = 3; 7085fff9558SSimon J. Gerraty cn_oid[1] = 0x55; 7095fff9558SSimon J. Gerraty cn_oid[2] = 4; 7105fff9558SSimon J. Gerraty cn_oid[3] = 3; 7115fff9558SSimon J. Gerraty cn.oid = cn_oid; 7125fff9558SSimon J. Gerraty cn.buf = cn_buf; 7135fff9558SSimon J. Gerraty cn.len = sizeof(cn_buf); 7145fff9558SSimon J. Gerraty 7155fff9558SSimon J. Gerraty pk = verify_signer(pbuf, &cn, 1); 7165fff9558SSimon J. Gerraty if (!pk) { 7175fff9558SSimon J. Gerraty printf("cannot verify: %s: %s\n", pbuf, ve_error_get()); 7185fff9558SSimon J. Gerraty return (NULL); 7195fff9558SSimon J. Gerraty } 7205fff9558SSimon J. Gerraty for (; cp > pbuf; cp--) { 7215fff9558SSimon J. Gerraty if (*cp == '.') { 7225fff9558SSimon J. Gerraty *cp = '\0'; 7235fff9558SSimon J. Gerraty break; 7245fff9558SSimon J. Gerraty } 7255fff9558SSimon J. Gerraty } 7265fff9558SSimon J. Gerraty switch (pk->key_type) { 7275fff9558SSimon J. Gerraty #ifdef VE_ECDSA_SUPPORT 7285fff9558SSimon J. Gerraty case BR_KEYTYPE_EC: 7295fff9558SSimon J. Gerraty ucp = verify_ec(pk, pbuf, sigfile); 7305fff9558SSimon J. Gerraty break; 7315fff9558SSimon J. Gerraty #endif 7325fff9558SSimon J. Gerraty #ifdef VE_RSA_SUPPORT 7335fff9558SSimon J. Gerraty case BR_KEYTYPE_RSA: 7345fff9558SSimon J. Gerraty ucp = verify_rsa(pk, pbuf, sigfile); 7355fff9558SSimon J. Gerraty break; 7365fff9558SSimon J. Gerraty #endif 7375fff9558SSimon J. Gerraty default: 7385fff9558SSimon J. Gerraty ucp = NULL; /* not supported */ 7395fff9558SSimon J. Gerraty } 7405fff9558SSimon J. Gerraty xfreepkey(pk); 7415fff9558SSimon J. Gerraty if (!ucp) { 7425fff9558SSimon J. Gerraty printf("Unverified %s (%s)\n", pbuf, 7435fff9558SSimon J. Gerraty cn.status ? cn_buf : "unknown"); 7445fff9558SSimon J. Gerraty } else if ((flags & 1) != 0) { 7455fff9558SSimon J. Gerraty printf("Verified %s signed by %s\n", pbuf, 7465fff9558SSimon J. Gerraty cn.status ? cn_buf : "someone we trust"); 7475fff9558SSimon J. Gerraty } 7485fff9558SSimon J. Gerraty return (ucp); 7495fff9558SSimon J. Gerraty } 7505fff9558SSimon J. Gerraty 7515fff9558SSimon J. Gerraty 7525fff9558SSimon J. Gerraty /** 7535fff9558SSimon J. Gerraty * @brief verify hash matches 7545fff9558SSimon J. Gerraty * 7555fff9558SSimon J. Gerraty * We have finished hashing a file, 7565fff9558SSimon J. Gerraty * see if we got the desired result. 7575fff9558SSimon J. Gerraty * 7585fff9558SSimon J. Gerraty * @param[in] ctx 7595fff9558SSimon J. Gerraty * pointer to hash context 7605fff9558SSimon J. Gerraty * 7615fff9558SSimon J. Gerraty * @param[in] md 7625fff9558SSimon J. Gerraty * pointer to hash class 7635fff9558SSimon J. Gerraty * 7645fff9558SSimon J. Gerraty * @param[in] path 7655fff9558SSimon J. Gerraty * name of the file we are checking 7665fff9558SSimon J. Gerraty * 7675fff9558SSimon J. Gerraty * @param[in] want 7685fff9558SSimon J. Gerraty * the expected result 7695fff9558SSimon J. Gerraty * 7705fff9558SSimon J. Gerraty * @param[in] hlen 7715fff9558SSimon J. Gerraty * size of hash output 7725fff9558SSimon J. Gerraty * 7735fff9558SSimon J. Gerraty * @return 0 on success 7745fff9558SSimon J. Gerraty */ 7755fff9558SSimon J. Gerraty int 7765fff9558SSimon J. Gerraty ve_check_hash(br_hash_compat_context *ctx, const br_hash_class *md, 7775fff9558SSimon J. Gerraty const char *path, const char *want, size_t hlen) 7785fff9558SSimon J. Gerraty { 7795fff9558SSimon J. Gerraty char hexbuf[br_sha512_SIZE * 2 + 2]; 7805fff9558SSimon J. Gerraty unsigned char hbuf[br_sha512_SIZE]; 7815fff9558SSimon J. Gerraty char *hex; 7825fff9558SSimon J. Gerraty int rc; 7835fff9558SSimon J. Gerraty int n; 7845fff9558SSimon J. Gerraty 7855fff9558SSimon J. Gerraty md->out(&ctx->vtable, hbuf); 7865fff9558SSimon J. Gerraty #ifdef VE_PCR_SUPPORT 7875fff9558SSimon J. Gerraty ve_pcr_update(hbuf, hlen); 7885fff9558SSimon J. Gerraty #endif 7895fff9558SSimon J. Gerraty hex = hexdigest(hexbuf, sizeof(hexbuf), hbuf, hlen); 7905fff9558SSimon J. Gerraty if (!hex) 7915fff9558SSimon J. Gerraty return (VE_FINGERPRINT_WRONG); 7925fff9558SSimon J. Gerraty n = 2*hlen; 7935fff9558SSimon J. Gerraty if ((rc = strncmp(hex, want, n))) { 7945fff9558SSimon J. Gerraty ve_error_set("%s: %.*s != %.*s", path, n, hex, n, want); 7955fff9558SSimon J. Gerraty rc = VE_FINGERPRINT_WRONG; 7965fff9558SSimon J. Gerraty } 7975fff9558SSimon J. Gerraty return (rc ? rc : VE_FINGERPRINT_OK); 7985fff9558SSimon J. Gerraty } 7995fff9558SSimon J. Gerraty 8005fff9558SSimon J. Gerraty #ifdef VE_HASH_KAT_STR 8015fff9558SSimon J. Gerraty static int 8025fff9558SSimon J. Gerraty test_hash(const br_hash_class *md, size_t hlen, 8035fff9558SSimon J. Gerraty const char *hname, const char *s, size_t slen, const char *want) 8045fff9558SSimon J. Gerraty { 8055fff9558SSimon J. Gerraty br_hash_compat_context mctx; 8065fff9558SSimon J. Gerraty 8075fff9558SSimon J. Gerraty md->init(&mctx.vtable); 8085fff9558SSimon J. Gerraty md->update(&mctx.vtable, s, slen); 8095fff9558SSimon J. Gerraty return (ve_check_hash(&mctx, md, hname, want, hlen) != VE_FINGERPRINT_OK); 8105fff9558SSimon J. Gerraty } 8115fff9558SSimon J. Gerraty 8125fff9558SSimon J. Gerraty #endif 8135fff9558SSimon J. Gerraty 8145fff9558SSimon J. Gerraty #define ve_test_hash(n, N) \ 8155fff9558SSimon J. Gerraty printf("Testing hash: " #n "\t\t\t\t%s\n", \ 8165fff9558SSimon J. Gerraty test_hash(&br_ ## n ## _vtable, br_ ## n ## _SIZE, #n, \ 8175fff9558SSimon J. Gerraty VE_HASH_KAT_STR, sizeof(VE_HASH_KAT_STR), \ 8185fff9558SSimon J. Gerraty vh_ ## N) ? "Failed" : "Passed") 8195fff9558SSimon J. Gerraty 8205fff9558SSimon J. Gerraty /** 8215fff9558SSimon J. Gerraty * @brief 8225fff9558SSimon J. Gerraty * run self tests on hash and signature verification 8235fff9558SSimon J. Gerraty * 8245fff9558SSimon J. Gerraty * Test that the hash methods (SHA1 and SHA256) work. 8255fff9558SSimon J. Gerraty * Test that we can verify a certificate for each supported 8265fff9558SSimon J. Gerraty * Root CA. 8275fff9558SSimon J. Gerraty * 8285fff9558SSimon J. Gerraty * @return cached result. 8295fff9558SSimon J. Gerraty */ 8305fff9558SSimon J. Gerraty int 8315fff9558SSimon J. Gerraty ve_self_tests(void) 8325fff9558SSimon J. Gerraty { 8335fff9558SSimon J. Gerraty static int once = -1; 8345fff9558SSimon J. Gerraty #ifdef VERIFY_CERTS_STR 8355fff9558SSimon J. Gerraty br_x509_certificate *xcs; 8365fff9558SSimon J. Gerraty br_x509_pkey *pk; 8375fff9558SSimon J. Gerraty br_name_element cn; 8385fff9558SSimon J. Gerraty char cn_buf[80]; 8395fff9558SSimon J. Gerraty unsigned char cn_oid[4]; 8405fff9558SSimon J. Gerraty size_t num; 8415fff9558SSimon J. Gerraty size_t u; 8425fff9558SSimon J. Gerraty #endif 8435fff9558SSimon J. Gerraty 8445fff9558SSimon J. Gerraty if (once >= 0) 8455fff9558SSimon J. Gerraty return (once); 8465fff9558SSimon J. Gerraty once = 0; 8475fff9558SSimon J. Gerraty 8485fff9558SSimon J. Gerraty DEBUG_PRINTF(5, ("Self tests...\n")); 8495fff9558SSimon J. Gerraty #ifdef VE_HASH_KAT_STR 8505fff9558SSimon J. Gerraty #ifdef VE_SHA1_SUPPORT 8515fff9558SSimon J. Gerraty ve_test_hash(sha1, SHA1); 8525fff9558SSimon J. Gerraty #endif 8535fff9558SSimon J. Gerraty #ifdef VE_SHA256_SUPPORT 8545fff9558SSimon J. Gerraty ve_test_hash(sha256, SHA256); 8555fff9558SSimon J. Gerraty #endif 8565fff9558SSimon J. Gerraty #ifdef VE_SHA384_SUPPORT 8575fff9558SSimon J. Gerraty ve_test_hash(sha384, SHA384); 8585fff9558SSimon J. Gerraty #endif 8595fff9558SSimon J. Gerraty #ifdef VE_SHA512_SUPPORT 8605fff9558SSimon J. Gerraty ve_test_hash(sha512, SHA512); 8615fff9558SSimon J. Gerraty #endif 8625fff9558SSimon J. Gerraty #endif 8635fff9558SSimon J. Gerraty #ifdef VERIFY_CERTS_STR 8645fff9558SSimon J. Gerraty xcs = parse_certificates(__DECONST(unsigned char *, VERIFY_CERTS_STR), 8655fff9558SSimon J. Gerraty sizeof(VERIFY_CERTS_STR), &num); 8665fff9558SSimon J. Gerraty if (xcs == NULL) 8675fff9558SSimon J. Gerraty return (0); 8685fff9558SSimon J. Gerraty /* 8695fff9558SSimon J. Gerraty * We want the commonName field 8705fff9558SSimon J. Gerraty * the OID we want is 2,5,4,3 - but DER encoded 8715fff9558SSimon J. Gerraty */ 8725fff9558SSimon J. Gerraty cn_oid[0] = 3; 8735fff9558SSimon J. Gerraty cn_oid[1] = 0x55; 8745fff9558SSimon J. Gerraty cn_oid[2] = 4; 8755fff9558SSimon J. Gerraty cn_oid[3] = 3; 8765fff9558SSimon J. Gerraty cn.oid = cn_oid; 8775fff9558SSimon J. Gerraty cn.buf = cn_buf; 8785fff9558SSimon J. Gerraty 8795fff9558SSimon J. Gerraty for (u = 0; u < num; u ++) { 8805fff9558SSimon J. Gerraty cn.len = sizeof(cn_buf); 881*13ea0450SMarcin Wojtas if ((pk = verify_signer_xcs(&xcs[u], 1, &cn, 1, &trust_anchors)) != NULL) { 882*13ea0450SMarcin Wojtas free_cert_contents(&xcs[u]); 8835fff9558SSimon J. Gerraty once++; 8845fff9558SSimon J. Gerraty printf("Testing verify certificate: %s\tPassed\n", 8855fff9558SSimon J. Gerraty cn.status ? cn_buf : ""); 8865fff9558SSimon J. Gerraty xfreepkey(pk); 8875fff9558SSimon J. Gerraty } 8885fff9558SSimon J. Gerraty } 8895fff9558SSimon J. Gerraty if (!once) 8905fff9558SSimon J. Gerraty printf("Testing verify certificate:\t\t\tFailed\n"); 8915fff9558SSimon J. Gerraty xfree(xcs); 8925fff9558SSimon J. Gerraty #else 8935fff9558SSimon J. Gerraty printf("No X.509 self tests\n"); 8945fff9558SSimon J. Gerraty #endif /* VERIFY_CERTS_STR */ 8955fff9558SSimon J. Gerraty #ifdef VE_OPENPGP_SUPPORT 8965fff9558SSimon J. Gerraty if (!openpgp_self_tests()) 8975fff9558SSimon J. Gerraty once++; 8985fff9558SSimon J. Gerraty #endif 8995fff9558SSimon J. Gerraty return (once); 9005fff9558SSimon J. Gerraty } 901