1*5fff9558SSimon J. Gerraty /*- 2*5fff9558SSimon J. Gerraty * Copyright (c) 2017-2018, Juniper Networks, Inc. 3*5fff9558SSimon J. Gerraty * 4*5fff9558SSimon J. Gerraty * Redistribution and use in source and binary forms, with or without 5*5fff9558SSimon J. Gerraty * modification, are permitted provided that the following conditions 6*5fff9558SSimon J. Gerraty * are met: 7*5fff9558SSimon J. Gerraty * 1. Redistributions of source code must retain the above copyright 8*5fff9558SSimon J. Gerraty * notice, this list of conditions and the following disclaimer. 9*5fff9558SSimon J. Gerraty * 2. Redistributions in binary form must reproduce the above copyright 10*5fff9558SSimon J. Gerraty * notice, this list of conditions and the following disclaimer in the 11*5fff9558SSimon J. Gerraty * documentation and/or other materials provided with the distribution. 12*5fff9558SSimon J. Gerraty * 13*5fff9558SSimon J. Gerraty * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 14*5fff9558SSimon J. Gerraty * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 15*5fff9558SSimon J. Gerraty * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 16*5fff9558SSimon J. Gerraty * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 17*5fff9558SSimon J. Gerraty * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 18*5fff9558SSimon J. Gerraty * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 19*5fff9558SSimon J. Gerraty * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 20*5fff9558SSimon J. Gerraty * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 21*5fff9558SSimon J. Gerraty * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22*5fff9558SSimon J. Gerraty * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 23*5fff9558SSimon J. Gerraty * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24*5fff9558SSimon J. Gerraty */ 25*5fff9558SSimon J. Gerraty #include <sys/cdefs.h> 26*5fff9558SSimon J. Gerraty __FBSDID("$FreeBSD$"); 27*5fff9558SSimon J. Gerraty 28*5fff9558SSimon J. Gerraty /** 29*5fff9558SSimon J. Gerraty * @file vets.c - trust store 30*5fff9558SSimon J. Gerraty * @brief verify signatures 31*5fff9558SSimon J. Gerraty * 32*5fff9558SSimon J. Gerraty * We leverage code from BearSSL www.bearssl.org 33*5fff9558SSimon J. Gerraty */ 34*5fff9558SSimon J. Gerraty 35*5fff9558SSimon J. Gerraty #include <sys/time.h> 36*5fff9558SSimon J. Gerraty #include <stdarg.h> 37*5fff9558SSimon J. Gerraty #define NEED_BRSSL_H 38*5fff9558SSimon J. Gerraty #include "libsecureboot-priv.h" 39*5fff9558SSimon J. Gerraty #include <brssl.h> 40*5fff9558SSimon J. Gerraty #include <ta.h> 41*5fff9558SSimon J. Gerraty 42*5fff9558SSimon J. Gerraty #ifndef TRUST_ANCHOR_STR 43*5fff9558SSimon J. Gerraty # define TRUST_ANCHOR_STR ta_PEM 44*5fff9558SSimon J. Gerraty #endif 45*5fff9558SSimon J. Gerraty 46*5fff9558SSimon J. Gerraty #define SECONDS_PER_DAY 86400 47*5fff9558SSimon J. Gerraty #define X509_DAYS_TO_UTC0 719528 48*5fff9558SSimon J. Gerraty 49*5fff9558SSimon J. Gerraty int DebugVe = 0; 50*5fff9558SSimon J. Gerraty 51*5fff9558SSimon J. Gerraty typedef VECTOR(br_x509_certificate) cert_list; 52*5fff9558SSimon J. Gerraty 53*5fff9558SSimon J. Gerraty static anchor_list trust_anchors = VEC_INIT; 54*5fff9558SSimon J. Gerraty 55*5fff9558SSimon J. Gerraty void 56*5fff9558SSimon J. Gerraty ve_debug_set(int n) 57*5fff9558SSimon J. Gerraty { 58*5fff9558SSimon J. Gerraty DebugVe = n; 59*5fff9558SSimon J. Gerraty } 60*5fff9558SSimon J. Gerraty 61*5fff9558SSimon J. Gerraty static char ebuf[512]; 62*5fff9558SSimon J. Gerraty 63*5fff9558SSimon J. Gerraty char * 64*5fff9558SSimon J. Gerraty ve_error_get(void) 65*5fff9558SSimon J. Gerraty { 66*5fff9558SSimon J. Gerraty return (ebuf); 67*5fff9558SSimon J. Gerraty } 68*5fff9558SSimon J. Gerraty 69*5fff9558SSimon J. Gerraty int 70*5fff9558SSimon J. Gerraty ve_error_set(const char *fmt, ...) 71*5fff9558SSimon J. Gerraty { 72*5fff9558SSimon J. Gerraty int rc; 73*5fff9558SSimon J. Gerraty va_list ap; 74*5fff9558SSimon J. Gerraty 75*5fff9558SSimon J. Gerraty va_start(ap, fmt); 76*5fff9558SSimon J. Gerraty ebuf[0] = '\0'; 77*5fff9558SSimon J. Gerraty rc = 0; 78*5fff9558SSimon J. Gerraty if (fmt) { 79*5fff9558SSimon J. Gerraty #ifdef STAND_H 80*5fff9558SSimon J. Gerraty vsprintf(ebuf, fmt, ap); /* no vsnprintf in libstand */ 81*5fff9558SSimon J. Gerraty ebuf[sizeof(ebuf) - 1] = '\0'; 82*5fff9558SSimon J. Gerraty rc = strlen(ebuf); 83*5fff9558SSimon J. Gerraty #else 84*5fff9558SSimon J. Gerraty rc = vsnprintf(ebuf, sizeof(ebuf), fmt, ap); 85*5fff9558SSimon J. Gerraty #endif 86*5fff9558SSimon J. Gerraty } 87*5fff9558SSimon J. Gerraty va_end(ap); 88*5fff9558SSimon J. Gerraty return (rc); 89*5fff9558SSimon J. Gerraty } 90*5fff9558SSimon J. Gerraty 91*5fff9558SSimon J. Gerraty /* this is the time we use for verifying certs */ 92*5fff9558SSimon J. Gerraty static time_t ve_utc = 0; 93*5fff9558SSimon J. Gerraty 94*5fff9558SSimon J. Gerraty /** 95*5fff9558SSimon J. Gerraty * @brief 96*5fff9558SSimon J. Gerraty * set ve_utc used for certificate verification 97*5fff9558SSimon J. Gerraty * 98*5fff9558SSimon J. Gerraty * @param[in] utc 99*5fff9558SSimon J. Gerraty * time - ignored unless greater than current value. 100*5fff9558SSimon J. Gerraty */ 101*5fff9558SSimon J. Gerraty void 102*5fff9558SSimon J. Gerraty ve_utc_set(time_t utc) 103*5fff9558SSimon J. Gerraty { 104*5fff9558SSimon J. Gerraty if (utc > ve_utc) { 105*5fff9558SSimon J. Gerraty DEBUG_PRINTF(2, ("Set ve_utc=%jd\n", (intmax_t)utc)); 106*5fff9558SSimon J. Gerraty ve_utc = utc; 107*5fff9558SSimon J. Gerraty } 108*5fff9558SSimon J. Gerraty } 109*5fff9558SSimon J. Gerraty 110*5fff9558SSimon J. Gerraty static void 111*5fff9558SSimon J. Gerraty free_cert_contents(br_x509_certificate *xc) 112*5fff9558SSimon J. Gerraty { 113*5fff9558SSimon J. Gerraty xfree(xc->data); 114*5fff9558SSimon J. Gerraty } 115*5fff9558SSimon J. Gerraty 116*5fff9558SSimon J. Gerraty /** 117*5fff9558SSimon J. Gerraty * @brief 118*5fff9558SSimon J. Gerraty * add certs to our trust store 119*5fff9558SSimon J. Gerraty */ 120*5fff9558SSimon J. Gerraty size_t 121*5fff9558SSimon J. Gerraty ve_trust_anchors_add(br_x509_certificate *xcs, size_t num) 122*5fff9558SSimon J. Gerraty { 123*5fff9558SSimon J. Gerraty br_x509_trust_anchor ta; 124*5fff9558SSimon J. Gerraty size_t u; 125*5fff9558SSimon J. Gerraty 126*5fff9558SSimon J. Gerraty for (u = 0; u < num; u++) { 127*5fff9558SSimon J. Gerraty if (certificate_to_trust_anchor_inner(&ta, &xcs[u]) < 0) { 128*5fff9558SSimon J. Gerraty break; 129*5fff9558SSimon J. Gerraty } 130*5fff9558SSimon J. Gerraty VEC_ADD(trust_anchors, ta); 131*5fff9558SSimon J. Gerraty } 132*5fff9558SSimon J. Gerraty return (u); 133*5fff9558SSimon J. Gerraty } 134*5fff9558SSimon J. Gerraty 135*5fff9558SSimon J. Gerraty /** 136*5fff9558SSimon J. Gerraty * @brief 137*5fff9558SSimon J. Gerraty * initialize our trust_anchors from ta_PEM 138*5fff9558SSimon J. Gerraty */ 139*5fff9558SSimon J. Gerraty int 140*5fff9558SSimon J. Gerraty ve_trust_init(void) 141*5fff9558SSimon J. Gerraty { 142*5fff9558SSimon J. Gerraty br_x509_certificate *xcs; 143*5fff9558SSimon J. Gerraty static int once = -1; 144*5fff9558SSimon J. Gerraty size_t num; 145*5fff9558SSimon J. Gerraty 146*5fff9558SSimon J. Gerraty if (once >= 0) 147*5fff9558SSimon J. Gerraty return (once); 148*5fff9558SSimon J. Gerraty once = 0; 149*5fff9558SSimon J. Gerraty 150*5fff9558SSimon J. Gerraty ve_utc_set(time(NULL)); 151*5fff9558SSimon J. Gerraty #ifdef BUILD_UTC 152*5fff9558SSimon J. Gerraty ve_utc_set(BUILD_UTC); /* just in case */ 153*5fff9558SSimon J. Gerraty #endif 154*5fff9558SSimon J. Gerraty ve_error_set(NULL); /* make sure it is empty */ 155*5fff9558SSimon J. Gerraty #ifdef VE_PCR_SUPPORT 156*5fff9558SSimon J. Gerraty ve_pcr_init(); 157*5fff9558SSimon J. Gerraty #endif 158*5fff9558SSimon J. Gerraty 159*5fff9558SSimon J. Gerraty #ifdef TRUST_ANCHOR_STR 160*5fff9558SSimon J. Gerraty xcs = parse_certificates(__DECONST(unsigned char *, TRUST_ANCHOR_STR), 161*5fff9558SSimon J. Gerraty sizeof(TRUST_ANCHOR_STR), &num); 162*5fff9558SSimon J. Gerraty if (xcs == NULL) 163*5fff9558SSimon J. Gerraty return (0); 164*5fff9558SSimon J. Gerraty num = ve_trust_anchors_add(xcs, num); 165*5fff9558SSimon J. Gerraty once = (int) num; 166*5fff9558SSimon J. Gerraty #else 167*5fff9558SSimon J. Gerraty num = 0; 168*5fff9558SSimon J. Gerraty #endif 169*5fff9558SSimon J. Gerraty return (num); 170*5fff9558SSimon J. Gerraty } 171*5fff9558SSimon J. Gerraty 172*5fff9558SSimon J. Gerraty /** 173*5fff9558SSimon J. Gerraty * if we can verify the certificate chain in "certs", 174*5fff9558SSimon J. Gerraty * return the public key and if "xcp" is !NULL the associated 175*5fff9558SSimon J. Gerraty * certificate 176*5fff9558SSimon J. Gerraty */ 177*5fff9558SSimon J. Gerraty static br_x509_pkey * 178*5fff9558SSimon J. Gerraty verify_signer_xcs(br_x509_certificate *xcs, 179*5fff9558SSimon J. Gerraty size_t num, 180*5fff9558SSimon J. Gerraty br_name_element *elts, size_t num_elts) 181*5fff9558SSimon J. Gerraty { 182*5fff9558SSimon J. Gerraty br_x509_minimal_context mc; 183*5fff9558SSimon J. Gerraty br_x509_certificate *xc; 184*5fff9558SSimon J. Gerraty size_t u; 185*5fff9558SSimon J. Gerraty cert_list chain = VEC_INIT; 186*5fff9558SSimon J. Gerraty const br_x509_pkey *tpk; 187*5fff9558SSimon J. Gerraty br_x509_pkey *pk; 188*5fff9558SSimon J. Gerraty unsigned int usages; 189*5fff9558SSimon J. Gerraty int err; 190*5fff9558SSimon J. Gerraty 191*5fff9558SSimon J. Gerraty DEBUG_PRINTF(5, ("verify_signer: %zu certs in chain\n", num)); 192*5fff9558SSimon J. Gerraty VEC_ADDMANY(chain, xcs, num); 193*5fff9558SSimon J. Gerraty if (VEC_LEN(chain) == 0) { 194*5fff9558SSimon J. Gerraty ve_error_set("ERROR: no/invalid certificate chain\n"); 195*5fff9558SSimon J. Gerraty return (NULL); 196*5fff9558SSimon J. Gerraty } 197*5fff9558SSimon J. Gerraty 198*5fff9558SSimon J. Gerraty DEBUG_PRINTF(5, ("verify_signer: %zu trust anchors\n", 199*5fff9558SSimon J. Gerraty VEC_LEN(trust_anchors))); 200*5fff9558SSimon J. Gerraty 201*5fff9558SSimon J. Gerraty br_x509_minimal_init(&mc, &br_sha256_vtable, 202*5fff9558SSimon J. Gerraty &VEC_ELT(trust_anchors, 0), 203*5fff9558SSimon J. Gerraty VEC_LEN(trust_anchors)); 204*5fff9558SSimon J. Gerraty #ifdef VE_ECDSA_SUPPORT 205*5fff9558SSimon J. Gerraty br_x509_minimal_set_ecdsa(&mc, 206*5fff9558SSimon J. Gerraty &br_ec_prime_i31, &br_ecdsa_i31_vrfy_asn1); 207*5fff9558SSimon J. Gerraty #endif 208*5fff9558SSimon J. Gerraty #ifdef VE_RSA_SUPPORT 209*5fff9558SSimon J. Gerraty br_x509_minimal_set_rsa(&mc, &br_rsa_i31_pkcs1_vrfy); 210*5fff9558SSimon J. Gerraty #endif 211*5fff9558SSimon J. Gerraty #if defined(UNIT_TEST) && defined(VE_DEPRECATED_RSA_SHA1_SUPPORT) 212*5fff9558SSimon J. Gerraty /* This is deprecated! do not enable unless you absoultely have to */ 213*5fff9558SSimon J. Gerraty br_x509_minimal_set_hash(&mc, br_sha1_ID, &br_sha1_vtable); 214*5fff9558SSimon J. Gerraty #endif 215*5fff9558SSimon J. Gerraty br_x509_minimal_set_hash(&mc, br_sha256_ID, &br_sha256_vtable); 216*5fff9558SSimon J. Gerraty #ifdef VE_SHA384_SUPPORT 217*5fff9558SSimon J. Gerraty br_x509_minimal_set_hash(&mc, br_sha384_ID, &br_sha384_vtable); 218*5fff9558SSimon J. Gerraty #endif 219*5fff9558SSimon J. Gerraty #ifdef VE_SHA512_SUPPORT 220*5fff9558SSimon J. Gerraty br_x509_minimal_set_hash(&mc, br_sha512_ID, &br_sha512_vtable); 221*5fff9558SSimon J. Gerraty #endif 222*5fff9558SSimon J. Gerraty br_x509_minimal_set_name_elements(&mc, elts, num_elts); 223*5fff9558SSimon J. Gerraty 224*5fff9558SSimon J. Gerraty #ifdef _STANDALONE 225*5fff9558SSimon J. Gerraty /* 226*5fff9558SSimon J. Gerraty * Clock is probably bogus so we use ve_utc. 227*5fff9558SSimon J. Gerraty */ 228*5fff9558SSimon J. Gerraty mc.days = (ve_utc / SECONDS_PER_DAY) + X509_DAYS_TO_UTC0; 229*5fff9558SSimon J. Gerraty mc.seconds = (ve_utc % SECONDS_PER_DAY); 230*5fff9558SSimon J. Gerraty #endif 231*5fff9558SSimon J. Gerraty 232*5fff9558SSimon J. Gerraty mc.vtable->start_chain(&mc.vtable, NULL); 233*5fff9558SSimon J. Gerraty for (u = 0; u < VEC_LEN(chain); u ++) { 234*5fff9558SSimon J. Gerraty xc = &VEC_ELT(chain, u); 235*5fff9558SSimon J. Gerraty mc.vtable->start_cert(&mc.vtable, xc->data_len); 236*5fff9558SSimon J. Gerraty mc.vtable->append(&mc.vtable, xc->data, xc->data_len); 237*5fff9558SSimon J. Gerraty mc.vtable->end_cert(&mc.vtable); 238*5fff9558SSimon J. Gerraty switch (mc.err) { 239*5fff9558SSimon J. Gerraty case 0: 240*5fff9558SSimon J. Gerraty case BR_ERR_X509_OK: 241*5fff9558SSimon J. Gerraty case BR_ERR_X509_EXPIRED: 242*5fff9558SSimon J. Gerraty break; 243*5fff9558SSimon J. Gerraty default: 244*5fff9558SSimon J. Gerraty printf("u=%zu mc.err=%d\n", u, mc.err); 245*5fff9558SSimon J. Gerraty break; 246*5fff9558SSimon J. Gerraty } 247*5fff9558SSimon J. Gerraty } 248*5fff9558SSimon J. Gerraty err = mc.vtable->end_chain(&mc.vtable); 249*5fff9558SSimon J. Gerraty pk = NULL; 250*5fff9558SSimon J. Gerraty if (err) { 251*5fff9558SSimon J. Gerraty ve_error_set("Validation failed, err = %d", err); 252*5fff9558SSimon J. Gerraty } else { 253*5fff9558SSimon J. Gerraty tpk = mc.vtable->get_pkey(&mc.vtable, &usages); 254*5fff9558SSimon J. Gerraty if (tpk != NULL) { 255*5fff9558SSimon J. Gerraty pk = xpkeydup(tpk); 256*5fff9558SSimon J. Gerraty } 257*5fff9558SSimon J. Gerraty } 258*5fff9558SSimon J. Gerraty VEC_CLEAREXT(chain, &free_cert_contents); 259*5fff9558SSimon J. Gerraty return (pk); 260*5fff9558SSimon J. Gerraty } 261*5fff9558SSimon J. Gerraty 262*5fff9558SSimon J. Gerraty static br_x509_pkey * 263*5fff9558SSimon J. Gerraty verify_signer(const char *certs, 264*5fff9558SSimon J. Gerraty br_name_element *elts, size_t num_elts) 265*5fff9558SSimon J. Gerraty { 266*5fff9558SSimon J. Gerraty br_x509_certificate *xcs; 267*5fff9558SSimon J. Gerraty br_x509_pkey *pk; 268*5fff9558SSimon J. Gerraty size_t num; 269*5fff9558SSimon J. Gerraty 270*5fff9558SSimon J. Gerraty ve_trust_init(); 271*5fff9558SSimon J. Gerraty xcs = read_certificates(certs, &num); 272*5fff9558SSimon J. Gerraty if (xcs == NULL) { 273*5fff9558SSimon J. Gerraty ve_error_set("cannot read certificates\n"); 274*5fff9558SSimon J. Gerraty return (NULL); 275*5fff9558SSimon J. Gerraty } 276*5fff9558SSimon J. Gerraty pk = verify_signer_xcs(xcs, num, elts, num_elts); 277*5fff9558SSimon J. Gerraty xfree(xcs); 278*5fff9558SSimon J. Gerraty return (pk); 279*5fff9558SSimon J. Gerraty } 280*5fff9558SSimon J. Gerraty 281*5fff9558SSimon J. Gerraty /** 282*5fff9558SSimon J. Gerraty * we need a hex digest including trailing newline below 283*5fff9558SSimon J. Gerraty */ 284*5fff9558SSimon J. Gerraty char * 285*5fff9558SSimon J. Gerraty hexdigest(char *buf, size_t bufsz, unsigned char *foo, size_t foo_len) 286*5fff9558SSimon J. Gerraty { 287*5fff9558SSimon J. Gerraty char const hex2ascii[] = "0123456789abcdef"; 288*5fff9558SSimon J. Gerraty size_t i; 289*5fff9558SSimon J. Gerraty 290*5fff9558SSimon J. Gerraty /* every binary byte is 2 chars in hex + newline + null */ 291*5fff9558SSimon J. Gerraty if (bufsz < (2 * foo_len) + 2) 292*5fff9558SSimon J. Gerraty return (NULL); 293*5fff9558SSimon J. Gerraty 294*5fff9558SSimon J. Gerraty for (i = 0; i < foo_len; i++) { 295*5fff9558SSimon J. Gerraty buf[i * 2] = hex2ascii[foo[i] >> 4]; 296*5fff9558SSimon J. Gerraty buf[i * 2 + 1] = hex2ascii[foo[i] & 0x0f]; 297*5fff9558SSimon J. Gerraty } 298*5fff9558SSimon J. Gerraty 299*5fff9558SSimon J. Gerraty buf[i * 2] = 0x0A; /* we also want a newline */ 300*5fff9558SSimon J. Gerraty buf[i * 2 + 1] = '\0'; 301*5fff9558SSimon J. Gerraty 302*5fff9558SSimon J. Gerraty return (buf); 303*5fff9558SSimon J. Gerraty } 304*5fff9558SSimon J. Gerraty 305*5fff9558SSimon J. Gerraty /** 306*5fff9558SSimon J. Gerraty * @brief 307*5fff9558SSimon J. Gerraty * verify file against sigfile using pk 308*5fff9558SSimon J. Gerraty * 309*5fff9558SSimon J. Gerraty * When we generated the signature in sigfile, 310*5fff9558SSimon J. Gerraty * we hashed (sha256) file, and sent that to signing server 311*5fff9558SSimon J. Gerraty * which hashed (sha256) that hash. 312*5fff9558SSimon J. Gerraty * 313*5fff9558SSimon J. Gerraty * To verify we need to replicate that result. 314*5fff9558SSimon J. Gerraty * 315*5fff9558SSimon J. Gerraty * @param[in] pk 316*5fff9558SSimon J. Gerraty * br_x509_pkey 317*5fff9558SSimon J. Gerraty * 318*5fff9558SSimon J. Gerraty * @paramp[in] file 319*5fff9558SSimon J. Gerraty * file to be verified 320*5fff9558SSimon J. Gerraty * 321*5fff9558SSimon J. Gerraty * @param[in] sigfile 322*5fff9558SSimon J. Gerraty * signature (PEM encoded) 323*5fff9558SSimon J. Gerraty * 324*5fff9558SSimon J. Gerraty * @return NULL on error, otherwise content of file. 325*5fff9558SSimon J. Gerraty */ 326*5fff9558SSimon J. Gerraty #ifdef VE_ECDSA_SUPPORT 327*5fff9558SSimon J. Gerraty static unsigned char * 328*5fff9558SSimon J. Gerraty verify_ec(br_x509_pkey *pk, const char *file, const char *sigfile) 329*5fff9558SSimon J. Gerraty { 330*5fff9558SSimon J. Gerraty char hexbuf[br_sha512_SIZE * 2 + 2]; 331*5fff9558SSimon J. Gerraty unsigned char rhbuf[br_sha512_SIZE]; 332*5fff9558SSimon J. Gerraty char *hex; 333*5fff9558SSimon J. Gerraty br_sha256_context ctx; 334*5fff9558SSimon J. Gerraty unsigned char *fcp, *scp; 335*5fff9558SSimon J. Gerraty size_t flen, slen, plen; 336*5fff9558SSimon J. Gerraty pem_object *po; 337*5fff9558SSimon J. Gerraty const br_ec_impl *ec; 338*5fff9558SSimon J. Gerraty br_ecdsa_vrfy vrfy; 339*5fff9558SSimon J. Gerraty 340*5fff9558SSimon J. Gerraty if ((fcp = read_file(file, &flen)) == NULL) 341*5fff9558SSimon J. Gerraty return (NULL); 342*5fff9558SSimon J. Gerraty if ((scp = read_file(sigfile, &slen)) == NULL) { 343*5fff9558SSimon J. Gerraty free(fcp); 344*5fff9558SSimon J. Gerraty return (NULL); 345*5fff9558SSimon J. Gerraty } 346*5fff9558SSimon J. Gerraty if ((po = decode_pem(scp, slen, &plen)) == NULL) { 347*5fff9558SSimon J. Gerraty free(fcp); 348*5fff9558SSimon J. Gerraty free(scp); 349*5fff9558SSimon J. Gerraty return (NULL); 350*5fff9558SSimon J. Gerraty } 351*5fff9558SSimon J. Gerraty br_sha256_init(&ctx); 352*5fff9558SSimon J. Gerraty br_sha256_update(&ctx, fcp, flen); 353*5fff9558SSimon J. Gerraty br_sha256_out(&ctx, rhbuf); 354*5fff9558SSimon J. Gerraty hex = hexdigest(hexbuf, sizeof(hexbuf), rhbuf, br_sha256_SIZE); 355*5fff9558SSimon J. Gerraty /* now hash that */ 356*5fff9558SSimon J. Gerraty if (hex) { 357*5fff9558SSimon J. Gerraty br_sha256_init(&ctx); 358*5fff9558SSimon J. Gerraty br_sha256_update(&ctx, hex, strlen(hex)); 359*5fff9558SSimon J. Gerraty br_sha256_out(&ctx, rhbuf); 360*5fff9558SSimon J. Gerraty } 361*5fff9558SSimon J. Gerraty ec = br_ec_get_default(); 362*5fff9558SSimon J. Gerraty vrfy = br_ecdsa_vrfy_asn1_get_default(); 363*5fff9558SSimon J. Gerraty if (!vrfy(ec, rhbuf, br_sha256_SIZE, &pk->key.ec, po->data, 364*5fff9558SSimon J. Gerraty po->data_len)) { 365*5fff9558SSimon J. Gerraty free(fcp); 366*5fff9558SSimon J. Gerraty fcp = NULL; 367*5fff9558SSimon J. Gerraty } 368*5fff9558SSimon J. Gerraty free(scp); 369*5fff9558SSimon J. Gerraty return (fcp); 370*5fff9558SSimon J. Gerraty } 371*5fff9558SSimon J. Gerraty #endif 372*5fff9558SSimon J. Gerraty 373*5fff9558SSimon J. Gerraty #if defined(VE_RSA_SUPPORT) || defined(VE_OPENPGP_SUPPORT) 374*5fff9558SSimon J. Gerraty /** 375*5fff9558SSimon J. Gerraty * @brief verify an rsa digest 376*5fff9558SSimon J. Gerraty * 377*5fff9558SSimon J. Gerraty * @return 0 on failure 378*5fff9558SSimon J. Gerraty */ 379*5fff9558SSimon J. Gerraty int 380*5fff9558SSimon J. Gerraty verify_rsa_digest (br_rsa_public_key *pkey, 381*5fff9558SSimon J. Gerraty const unsigned char *hash_oid, 382*5fff9558SSimon J. Gerraty unsigned char *mdata, size_t mlen, 383*5fff9558SSimon J. Gerraty unsigned char *sdata, size_t slen) 384*5fff9558SSimon J. Gerraty { 385*5fff9558SSimon J. Gerraty br_rsa_pkcs1_vrfy vrfy; 386*5fff9558SSimon J. Gerraty unsigned char vhbuf[br_sha512_SIZE]; 387*5fff9558SSimon J. Gerraty 388*5fff9558SSimon J. Gerraty vrfy = br_rsa_pkcs1_vrfy_get_default(); 389*5fff9558SSimon J. Gerraty 390*5fff9558SSimon J. Gerraty if (!vrfy(sdata, slen, hash_oid, mlen, pkey, vhbuf) || 391*5fff9558SSimon J. Gerraty memcmp(vhbuf, mdata, mlen) != 0) { 392*5fff9558SSimon J. Gerraty return (0); /* fail */ 393*5fff9558SSimon J. Gerraty } 394*5fff9558SSimon J. Gerraty return (1); /* ok */ 395*5fff9558SSimon J. Gerraty } 396*5fff9558SSimon J. Gerraty #endif 397*5fff9558SSimon J. Gerraty 398*5fff9558SSimon J. Gerraty /** 399*5fff9558SSimon J. Gerraty * @brief 400*5fff9558SSimon J. Gerraty * verify file against sigfile using pk 401*5fff9558SSimon J. Gerraty * 402*5fff9558SSimon J. Gerraty * When we generated the signature in sigfile, 403*5fff9558SSimon J. Gerraty * we hashed (sha256) file, and sent that to signing server 404*5fff9558SSimon J. Gerraty * which hashed (sha256) that hash. 405*5fff9558SSimon J. Gerraty * 406*5fff9558SSimon J. Gerraty * Or (deprecated) we simply used sha1 hash directly. 407*5fff9558SSimon J. Gerraty * 408*5fff9558SSimon J. Gerraty * To verify we need to replicate that result. 409*5fff9558SSimon J. Gerraty * 410*5fff9558SSimon J. Gerraty * @param[in] pk 411*5fff9558SSimon J. Gerraty * br_x509_pkey 412*5fff9558SSimon J. Gerraty * 413*5fff9558SSimon J. Gerraty * @paramp[in] file 414*5fff9558SSimon J. Gerraty * file to be verified 415*5fff9558SSimon J. Gerraty * 416*5fff9558SSimon J. Gerraty * @param[in] sigfile 417*5fff9558SSimon J. Gerraty * signature (PEM encoded) 418*5fff9558SSimon J. Gerraty * 419*5fff9558SSimon J. Gerraty * @return NULL on error, otherwise content of file. 420*5fff9558SSimon J. Gerraty */ 421*5fff9558SSimon J. Gerraty #ifdef VE_RSA_SUPPORT 422*5fff9558SSimon J. Gerraty static unsigned char * 423*5fff9558SSimon J. Gerraty verify_rsa(br_x509_pkey *pk, const char *file, const char *sigfile) 424*5fff9558SSimon J. Gerraty { 425*5fff9558SSimon J. Gerraty unsigned char rhbuf[br_sha512_SIZE]; 426*5fff9558SSimon J. Gerraty const unsigned char *hash_oid; 427*5fff9558SSimon J. Gerraty const br_hash_class *md; 428*5fff9558SSimon J. Gerraty br_hash_compat_context mctx; 429*5fff9558SSimon J. Gerraty unsigned char *fcp, *scp; 430*5fff9558SSimon J. Gerraty size_t flen, slen, plen, hlen; 431*5fff9558SSimon J. Gerraty pem_object *po; 432*5fff9558SSimon J. Gerraty 433*5fff9558SSimon J. Gerraty if ((fcp = read_file(file, &flen)) == NULL) 434*5fff9558SSimon J. Gerraty return (NULL); 435*5fff9558SSimon J. Gerraty if ((scp = read_file(sigfile, &slen)) == NULL) { 436*5fff9558SSimon J. Gerraty free(fcp); 437*5fff9558SSimon J. Gerraty return (NULL); 438*5fff9558SSimon J. Gerraty } 439*5fff9558SSimon J. Gerraty if ((po = decode_pem(scp, slen, &plen)) == NULL) { 440*5fff9558SSimon J. Gerraty free(fcp); 441*5fff9558SSimon J. Gerraty free(scp); 442*5fff9558SSimon J. Gerraty return (NULL); 443*5fff9558SSimon J. Gerraty } 444*5fff9558SSimon J. Gerraty 445*5fff9558SSimon J. Gerraty switch (po->data_len) { 446*5fff9558SSimon J. Gerraty #if defined(UNIT_TEST) && defined(VE_DEPRECATED_RSA_SHA1_SUPPORT) 447*5fff9558SSimon J. Gerraty case 256: 448*5fff9558SSimon J. Gerraty // this is our old deprecated sig method 449*5fff9558SSimon J. Gerraty md = &br_sha1_vtable; 450*5fff9558SSimon J. Gerraty hlen = br_sha1_SIZE; 451*5fff9558SSimon J. Gerraty hash_oid = BR_HASH_OID_SHA1; 452*5fff9558SSimon J. Gerraty break; 453*5fff9558SSimon J. Gerraty #endif 454*5fff9558SSimon J. Gerraty default: 455*5fff9558SSimon J. Gerraty md = &br_sha256_vtable; 456*5fff9558SSimon J. Gerraty hlen = br_sha256_SIZE; 457*5fff9558SSimon J. Gerraty hash_oid = BR_HASH_OID_SHA256; 458*5fff9558SSimon J. Gerraty break; 459*5fff9558SSimon J. Gerraty } 460*5fff9558SSimon J. Gerraty md->init(&mctx.vtable); 461*5fff9558SSimon J. Gerraty md->update(&mctx.vtable, fcp, flen); 462*5fff9558SSimon J. Gerraty md->out(&mctx.vtable, rhbuf); 463*5fff9558SSimon J. Gerraty if (!verify_rsa_digest(&pk->key.rsa, hash_oid, 464*5fff9558SSimon J. Gerraty rhbuf, hlen, po->data, po->data_len)) { 465*5fff9558SSimon J. Gerraty free(fcp); 466*5fff9558SSimon J. Gerraty fcp = NULL; 467*5fff9558SSimon J. Gerraty } 468*5fff9558SSimon J. Gerraty free(scp); 469*5fff9558SSimon J. Gerraty return (fcp); 470*5fff9558SSimon J. Gerraty } 471*5fff9558SSimon J. Gerraty #endif 472*5fff9558SSimon J. Gerraty 473*5fff9558SSimon J. Gerraty /** 474*5fff9558SSimon J. Gerraty * @brief 475*5fff9558SSimon J. Gerraty * verify a signature and return content of signed file 476*5fff9558SSimon J. Gerraty * 477*5fff9558SSimon J. Gerraty * @param[in] sigfile 478*5fff9558SSimon J. Gerraty * file containing signature 479*5fff9558SSimon J. Gerraty * we derrive path of signed file and certificate change from 480*5fff9558SSimon J. Gerraty * this. 481*5fff9558SSimon J. Gerraty * 482*5fff9558SSimon J. Gerraty * @param[in] flags 483*5fff9558SSimon J. Gerraty * only bit 1 significant so far 484*5fff9558SSimon J. Gerraty * 485*5fff9558SSimon J. Gerraty * @return NULL on error otherwise content of signed file 486*5fff9558SSimon J. Gerraty */ 487*5fff9558SSimon J. Gerraty unsigned char * 488*5fff9558SSimon J. Gerraty verify_sig(const char *sigfile, int flags) 489*5fff9558SSimon J. Gerraty { 490*5fff9558SSimon J. Gerraty br_x509_pkey *pk; 491*5fff9558SSimon J. Gerraty br_name_element cn; 492*5fff9558SSimon J. Gerraty char cn_buf[80]; 493*5fff9558SSimon J. Gerraty unsigned char cn_oid[4]; 494*5fff9558SSimon J. Gerraty char pbuf[MAXPATHLEN]; 495*5fff9558SSimon J. Gerraty char *cp; 496*5fff9558SSimon J. Gerraty unsigned char *ucp; 497*5fff9558SSimon J. Gerraty size_t n; 498*5fff9558SSimon J. Gerraty 499*5fff9558SSimon J. Gerraty DEBUG_PRINTF(5, ("verify_sig: %s\n", sigfile)); 500*5fff9558SSimon J. Gerraty n = strlcpy(pbuf, sigfile, sizeof(pbuf)); 501*5fff9558SSimon J. Gerraty if (n > (sizeof(pbuf) - 5) || strcmp(&sigfile[n - 3], "sig") != 0) 502*5fff9558SSimon J. Gerraty return (NULL); 503*5fff9558SSimon J. Gerraty cp = strcpy(&pbuf[n - 3], "certs"); 504*5fff9558SSimon J. Gerraty /* 505*5fff9558SSimon J. Gerraty * We want the commonName field 506*5fff9558SSimon J. Gerraty * the OID we want is 2,5,4,3 - but DER encoded 507*5fff9558SSimon J. Gerraty */ 508*5fff9558SSimon J. Gerraty cn_oid[0] = 3; 509*5fff9558SSimon J. Gerraty cn_oid[1] = 0x55; 510*5fff9558SSimon J. Gerraty cn_oid[2] = 4; 511*5fff9558SSimon J. Gerraty cn_oid[3] = 3; 512*5fff9558SSimon J. Gerraty cn.oid = cn_oid; 513*5fff9558SSimon J. Gerraty cn.buf = cn_buf; 514*5fff9558SSimon J. Gerraty cn.len = sizeof(cn_buf); 515*5fff9558SSimon J. Gerraty 516*5fff9558SSimon J. Gerraty pk = verify_signer(pbuf, &cn, 1); 517*5fff9558SSimon J. Gerraty if (!pk) { 518*5fff9558SSimon J. Gerraty printf("cannot verify: %s: %s\n", pbuf, ve_error_get()); 519*5fff9558SSimon J. Gerraty return (NULL); 520*5fff9558SSimon J. Gerraty } 521*5fff9558SSimon J. Gerraty for (; cp > pbuf; cp--) { 522*5fff9558SSimon J. Gerraty if (*cp == '.') { 523*5fff9558SSimon J. Gerraty *cp = '\0'; 524*5fff9558SSimon J. Gerraty break; 525*5fff9558SSimon J. Gerraty } 526*5fff9558SSimon J. Gerraty } 527*5fff9558SSimon J. Gerraty switch (pk->key_type) { 528*5fff9558SSimon J. Gerraty #ifdef VE_ECDSA_SUPPORT 529*5fff9558SSimon J. Gerraty case BR_KEYTYPE_EC: 530*5fff9558SSimon J. Gerraty ucp = verify_ec(pk, pbuf, sigfile); 531*5fff9558SSimon J. Gerraty break; 532*5fff9558SSimon J. Gerraty #endif 533*5fff9558SSimon J. Gerraty #ifdef VE_RSA_SUPPORT 534*5fff9558SSimon J. Gerraty case BR_KEYTYPE_RSA: 535*5fff9558SSimon J. Gerraty ucp = verify_rsa(pk, pbuf, sigfile); 536*5fff9558SSimon J. Gerraty break; 537*5fff9558SSimon J. Gerraty #endif 538*5fff9558SSimon J. Gerraty default: 539*5fff9558SSimon J. Gerraty ucp = NULL; /* not supported */ 540*5fff9558SSimon J. Gerraty } 541*5fff9558SSimon J. Gerraty xfreepkey(pk); 542*5fff9558SSimon J. Gerraty if (!ucp) { 543*5fff9558SSimon J. Gerraty printf("Unverified %s (%s)\n", pbuf, 544*5fff9558SSimon J. Gerraty cn.status ? cn_buf : "unknown"); 545*5fff9558SSimon J. Gerraty } else if ((flags & 1) != 0) { 546*5fff9558SSimon J. Gerraty printf("Verified %s signed by %s\n", pbuf, 547*5fff9558SSimon J. Gerraty cn.status ? cn_buf : "someone we trust"); 548*5fff9558SSimon J. Gerraty } 549*5fff9558SSimon J. Gerraty return (ucp); 550*5fff9558SSimon J. Gerraty } 551*5fff9558SSimon J. Gerraty 552*5fff9558SSimon J. Gerraty 553*5fff9558SSimon J. Gerraty /** 554*5fff9558SSimon J. Gerraty * @brief verify hash matches 555*5fff9558SSimon J. Gerraty * 556*5fff9558SSimon J. Gerraty * We have finished hashing a file, 557*5fff9558SSimon J. Gerraty * see if we got the desired result. 558*5fff9558SSimon J. Gerraty * 559*5fff9558SSimon J. Gerraty * @param[in] ctx 560*5fff9558SSimon J. Gerraty * pointer to hash context 561*5fff9558SSimon J. Gerraty * 562*5fff9558SSimon J. Gerraty * @param[in] md 563*5fff9558SSimon J. Gerraty * pointer to hash class 564*5fff9558SSimon J. Gerraty * 565*5fff9558SSimon J. Gerraty * @param[in] path 566*5fff9558SSimon J. Gerraty * name of the file we are checking 567*5fff9558SSimon J. Gerraty * 568*5fff9558SSimon J. Gerraty * @param[in] want 569*5fff9558SSimon J. Gerraty * the expected result 570*5fff9558SSimon J. Gerraty * 571*5fff9558SSimon J. Gerraty * @param[in] hlen 572*5fff9558SSimon J. Gerraty * size of hash output 573*5fff9558SSimon J. Gerraty * 574*5fff9558SSimon J. Gerraty * @return 0 on success 575*5fff9558SSimon J. Gerraty */ 576*5fff9558SSimon J. Gerraty int 577*5fff9558SSimon J. Gerraty ve_check_hash(br_hash_compat_context *ctx, const br_hash_class *md, 578*5fff9558SSimon J. Gerraty const char *path, const char *want, size_t hlen) 579*5fff9558SSimon J. Gerraty { 580*5fff9558SSimon J. Gerraty char hexbuf[br_sha512_SIZE * 2 + 2]; 581*5fff9558SSimon J. Gerraty unsigned char hbuf[br_sha512_SIZE]; 582*5fff9558SSimon J. Gerraty char *hex; 583*5fff9558SSimon J. Gerraty int rc; 584*5fff9558SSimon J. Gerraty int n; 585*5fff9558SSimon J. Gerraty 586*5fff9558SSimon J. Gerraty md->out(&ctx->vtable, hbuf); 587*5fff9558SSimon J. Gerraty #ifdef VE_PCR_SUPPORT 588*5fff9558SSimon J. Gerraty ve_pcr_update(hbuf, hlen); 589*5fff9558SSimon J. Gerraty #endif 590*5fff9558SSimon J. Gerraty hex = hexdigest(hexbuf, sizeof(hexbuf), hbuf, hlen); 591*5fff9558SSimon J. Gerraty if (!hex) 592*5fff9558SSimon J. Gerraty return (VE_FINGERPRINT_WRONG); 593*5fff9558SSimon J. Gerraty n = 2*hlen; 594*5fff9558SSimon J. Gerraty if ((rc = strncmp(hex, want, n))) { 595*5fff9558SSimon J. Gerraty ve_error_set("%s: %.*s != %.*s", path, n, hex, n, want); 596*5fff9558SSimon J. Gerraty rc = VE_FINGERPRINT_WRONG; 597*5fff9558SSimon J. Gerraty } 598*5fff9558SSimon J. Gerraty return (rc ? rc : VE_FINGERPRINT_OK); 599*5fff9558SSimon J. Gerraty } 600*5fff9558SSimon J. Gerraty 601*5fff9558SSimon J. Gerraty #ifdef VE_HASH_KAT_STR 602*5fff9558SSimon J. Gerraty static int 603*5fff9558SSimon J. Gerraty test_hash(const br_hash_class *md, size_t hlen, 604*5fff9558SSimon J. Gerraty const char *hname, const char *s, size_t slen, const char *want) 605*5fff9558SSimon J. Gerraty { 606*5fff9558SSimon J. Gerraty br_hash_compat_context mctx; 607*5fff9558SSimon J. Gerraty 608*5fff9558SSimon J. Gerraty md->init(&mctx.vtable); 609*5fff9558SSimon J. Gerraty md->update(&mctx.vtable, s, slen); 610*5fff9558SSimon J. Gerraty return (ve_check_hash(&mctx, md, hname, want, hlen) != VE_FINGERPRINT_OK); 611*5fff9558SSimon J. Gerraty } 612*5fff9558SSimon J. Gerraty 613*5fff9558SSimon J. Gerraty #endif 614*5fff9558SSimon J. Gerraty 615*5fff9558SSimon J. Gerraty #define ve_test_hash(n, N) \ 616*5fff9558SSimon J. Gerraty printf("Testing hash: " #n "\t\t\t\t%s\n", \ 617*5fff9558SSimon J. Gerraty test_hash(&br_ ## n ## _vtable, br_ ## n ## _SIZE, #n, \ 618*5fff9558SSimon J. Gerraty VE_HASH_KAT_STR, sizeof(VE_HASH_KAT_STR), \ 619*5fff9558SSimon J. Gerraty vh_ ## N) ? "Failed" : "Passed") 620*5fff9558SSimon J. Gerraty 621*5fff9558SSimon J. Gerraty /** 622*5fff9558SSimon J. Gerraty * @brief 623*5fff9558SSimon J. Gerraty * run self tests on hash and signature verification 624*5fff9558SSimon J. Gerraty * 625*5fff9558SSimon J. Gerraty * Test that the hash methods (SHA1 and SHA256) work. 626*5fff9558SSimon J. Gerraty * Test that we can verify a certificate for each supported 627*5fff9558SSimon J. Gerraty * Root CA. 628*5fff9558SSimon J. Gerraty * 629*5fff9558SSimon J. Gerraty * @return cached result. 630*5fff9558SSimon J. Gerraty */ 631*5fff9558SSimon J. Gerraty int 632*5fff9558SSimon J. Gerraty ve_self_tests(void) 633*5fff9558SSimon J. Gerraty { 634*5fff9558SSimon J. Gerraty static int once = -1; 635*5fff9558SSimon J. Gerraty #ifdef VERIFY_CERTS_STR 636*5fff9558SSimon J. Gerraty br_x509_certificate *xcs; 637*5fff9558SSimon J. Gerraty br_x509_pkey *pk; 638*5fff9558SSimon J. Gerraty br_name_element cn; 639*5fff9558SSimon J. Gerraty char cn_buf[80]; 640*5fff9558SSimon J. Gerraty unsigned char cn_oid[4]; 641*5fff9558SSimon J. Gerraty size_t num; 642*5fff9558SSimon J. Gerraty size_t u; 643*5fff9558SSimon J. Gerraty #endif 644*5fff9558SSimon J. Gerraty 645*5fff9558SSimon J. Gerraty if (once >= 0) 646*5fff9558SSimon J. Gerraty return (once); 647*5fff9558SSimon J. Gerraty once = 0; 648*5fff9558SSimon J. Gerraty 649*5fff9558SSimon J. Gerraty DEBUG_PRINTF(5, ("Self tests...\n")); 650*5fff9558SSimon J. Gerraty #ifdef VE_HASH_KAT_STR 651*5fff9558SSimon J. Gerraty #ifdef VE_SHA1_SUPPORT 652*5fff9558SSimon J. Gerraty ve_test_hash(sha1, SHA1); 653*5fff9558SSimon J. Gerraty #endif 654*5fff9558SSimon J. Gerraty #ifdef VE_SHA256_SUPPORT 655*5fff9558SSimon J. Gerraty ve_test_hash(sha256, SHA256); 656*5fff9558SSimon J. Gerraty #endif 657*5fff9558SSimon J. Gerraty #ifdef VE_SHA384_SUPPORT 658*5fff9558SSimon J. Gerraty ve_test_hash(sha384, SHA384); 659*5fff9558SSimon J. Gerraty #endif 660*5fff9558SSimon J. Gerraty #ifdef VE_SHA512_SUPPORT 661*5fff9558SSimon J. Gerraty ve_test_hash(sha512, SHA512); 662*5fff9558SSimon J. Gerraty #endif 663*5fff9558SSimon J. Gerraty #endif 664*5fff9558SSimon J. Gerraty #ifdef VERIFY_CERTS_STR 665*5fff9558SSimon J. Gerraty xcs = parse_certificates(__DECONST(unsigned char *, VERIFY_CERTS_STR), 666*5fff9558SSimon J. Gerraty sizeof(VERIFY_CERTS_STR), &num); 667*5fff9558SSimon J. Gerraty if (xcs == NULL) 668*5fff9558SSimon J. Gerraty return (0); 669*5fff9558SSimon J. Gerraty /* 670*5fff9558SSimon J. Gerraty * We want the commonName field 671*5fff9558SSimon J. Gerraty * the OID we want is 2,5,4,3 - but DER encoded 672*5fff9558SSimon J. Gerraty */ 673*5fff9558SSimon J. Gerraty cn_oid[0] = 3; 674*5fff9558SSimon J. Gerraty cn_oid[1] = 0x55; 675*5fff9558SSimon J. Gerraty cn_oid[2] = 4; 676*5fff9558SSimon J. Gerraty cn_oid[3] = 3; 677*5fff9558SSimon J. Gerraty cn.oid = cn_oid; 678*5fff9558SSimon J. Gerraty cn.buf = cn_buf; 679*5fff9558SSimon J. Gerraty 680*5fff9558SSimon J. Gerraty for (u = 0; u < num; u ++) { 681*5fff9558SSimon J. Gerraty cn.len = sizeof(cn_buf); 682*5fff9558SSimon J. Gerraty if ((pk = verify_signer_xcs(&xcs[u], 1, &cn, 1)) != NULL) { 683*5fff9558SSimon J. Gerraty once++; 684*5fff9558SSimon J. Gerraty printf("Testing verify certificate: %s\tPassed\n", 685*5fff9558SSimon J. Gerraty cn.status ? cn_buf : ""); 686*5fff9558SSimon J. Gerraty xfreepkey(pk); 687*5fff9558SSimon J. Gerraty } 688*5fff9558SSimon J. Gerraty } 689*5fff9558SSimon J. Gerraty if (!once) 690*5fff9558SSimon J. Gerraty printf("Testing verify certificate:\t\t\tFailed\n"); 691*5fff9558SSimon J. Gerraty xfree(xcs); 692*5fff9558SSimon J. Gerraty #else 693*5fff9558SSimon J. Gerraty printf("No X.509 self tests\n"); 694*5fff9558SSimon J. Gerraty #endif /* VERIFY_CERTS_STR */ 695*5fff9558SSimon J. Gerraty #ifdef VE_OPENPGP_SUPPORT 696*5fff9558SSimon J. Gerraty if (!openpgp_self_tests()) 697*5fff9558SSimon J. Gerraty once++; 698*5fff9558SSimon J. Gerraty #endif 699*5fff9558SSimon J. Gerraty return (once); 700*5fff9558SSimon J. Gerraty } 701