1*b077aed3SPierre Pronchery /* 2*b077aed3SPierre Pronchery * Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved. 3*b077aed3SPierre Pronchery * 4*b077aed3SPierre Pronchery * Licensed under the Apache License 2.0 (the "License"). You may not use 5*b077aed3SPierre Pronchery * this file except in compliance with the License. You can obtain a copy 6*b077aed3SPierre Pronchery * in the file LICENSE in the source distribution or at 7*b077aed3SPierre Pronchery * https://www.openssl.org/source/license.html 8*b077aed3SPierre Pronchery */ 9*b077aed3SPierre Pronchery 10*b077aed3SPierre Pronchery #include <string.h> 11*b077aed3SPierre Pronchery #include <openssl/x509v3.h> 12*b077aed3SPierre Pronchery #include <openssl/err.h> 13*b077aed3SPierre Pronchery #include <openssl/ess.h> 14*b077aed3SPierre Pronchery #include "internal/sizes.h" 15*b077aed3SPierre Pronchery #include "crypto/ess.h" 16*b077aed3SPierre Pronchery #include "crypto/x509.h" 17*b077aed3SPierre Pronchery 18*b077aed3SPierre Pronchery static ESS_CERT_ID *ESS_CERT_ID_new_init(const X509 *cert, 19*b077aed3SPierre Pronchery int set_issuer_serial); 20*b077aed3SPierre Pronchery static ESS_CERT_ID_V2 *ESS_CERT_ID_V2_new_init(const EVP_MD *hash_alg, 21*b077aed3SPierre Pronchery const X509 *cert, 22*b077aed3SPierre Pronchery int set_issuer_serial); 23*b077aed3SPierre Pronchery 24*b077aed3SPierre Pronchery ESS_SIGNING_CERT *OSSL_ESS_signing_cert_new_init(const X509 *signcert, 25*b077aed3SPierre Pronchery const STACK_OF(X509) *certs, 26*b077aed3SPierre Pronchery int set_issuer_serial) 27*b077aed3SPierre Pronchery { 28*b077aed3SPierre Pronchery ESS_CERT_ID *cid = NULL; 29*b077aed3SPierre Pronchery ESS_SIGNING_CERT *sc; 30*b077aed3SPierre Pronchery int i; 31*b077aed3SPierre Pronchery 32*b077aed3SPierre Pronchery if ((sc = ESS_SIGNING_CERT_new()) == NULL) 33*b077aed3SPierre Pronchery goto err; 34*b077aed3SPierre Pronchery if (sc->cert_ids == NULL 35*b077aed3SPierre Pronchery && (sc->cert_ids = sk_ESS_CERT_ID_new_null()) == NULL) 36*b077aed3SPierre Pronchery goto err; 37*b077aed3SPierre Pronchery 38*b077aed3SPierre Pronchery if ((cid = ESS_CERT_ID_new_init(signcert, set_issuer_serial)) == NULL 39*b077aed3SPierre Pronchery || !sk_ESS_CERT_ID_push(sc->cert_ids, cid)) 40*b077aed3SPierre Pronchery goto err; 41*b077aed3SPierre Pronchery for (i = 0; i < sk_X509_num(certs); ++i) { 42*b077aed3SPierre Pronchery X509 *cert = sk_X509_value(certs, i); 43*b077aed3SPierre Pronchery 44*b077aed3SPierre Pronchery if ((cid = ESS_CERT_ID_new_init(cert, 1)) == NULL 45*b077aed3SPierre Pronchery || !sk_ESS_CERT_ID_push(sc->cert_ids, cid)) 46*b077aed3SPierre Pronchery goto err; 47*b077aed3SPierre Pronchery } 48*b077aed3SPierre Pronchery 49*b077aed3SPierre Pronchery return sc; 50*b077aed3SPierre Pronchery err: 51*b077aed3SPierre Pronchery ESS_SIGNING_CERT_free(sc); 52*b077aed3SPierre Pronchery ESS_CERT_ID_free(cid); 53*b077aed3SPierre Pronchery ERR_raise(ERR_LIB_ESS, ERR_R_MALLOC_FAILURE); 54*b077aed3SPierre Pronchery return NULL; 55*b077aed3SPierre Pronchery } 56*b077aed3SPierre Pronchery 57*b077aed3SPierre Pronchery static ESS_CERT_ID *ESS_CERT_ID_new_init(const X509 *cert, 58*b077aed3SPierre Pronchery int set_issuer_serial) 59*b077aed3SPierre Pronchery { 60*b077aed3SPierre Pronchery ESS_CERT_ID *cid = NULL; 61*b077aed3SPierre Pronchery GENERAL_NAME *name = NULL; 62*b077aed3SPierre Pronchery unsigned char cert_sha1[SHA_DIGEST_LENGTH]; 63*b077aed3SPierre Pronchery 64*b077aed3SPierre Pronchery if ((cid = ESS_CERT_ID_new()) == NULL) 65*b077aed3SPierre Pronchery goto err; 66*b077aed3SPierre Pronchery if (!X509_digest(cert, EVP_sha1(), cert_sha1, NULL)) 67*b077aed3SPierre Pronchery goto err; 68*b077aed3SPierre Pronchery if (!ASN1_OCTET_STRING_set(cid->hash, cert_sha1, SHA_DIGEST_LENGTH)) 69*b077aed3SPierre Pronchery goto err; 70*b077aed3SPierre Pronchery 71*b077aed3SPierre Pronchery /* Setting the issuer/serial if requested. */ 72*b077aed3SPierre Pronchery if (!set_issuer_serial) 73*b077aed3SPierre Pronchery return cid; 74*b077aed3SPierre Pronchery 75*b077aed3SPierre Pronchery if (cid->issuer_serial == NULL 76*b077aed3SPierre Pronchery && (cid->issuer_serial = ESS_ISSUER_SERIAL_new()) == NULL) 77*b077aed3SPierre Pronchery goto err; 78*b077aed3SPierre Pronchery if ((name = GENERAL_NAME_new()) == NULL) 79*b077aed3SPierre Pronchery goto err; 80*b077aed3SPierre Pronchery name->type = GEN_DIRNAME; 81*b077aed3SPierre Pronchery if ((name->d.dirn = X509_NAME_dup(X509_get_issuer_name(cert))) == NULL) 82*b077aed3SPierre Pronchery goto err; 83*b077aed3SPierre Pronchery if (!sk_GENERAL_NAME_push(cid->issuer_serial->issuer, name)) 84*b077aed3SPierre Pronchery goto err; 85*b077aed3SPierre Pronchery name = NULL; /* Ownership is lost. */ 86*b077aed3SPierre Pronchery ASN1_INTEGER_free(cid->issuer_serial->serial); 87*b077aed3SPierre Pronchery if ((cid->issuer_serial->serial = 88*b077aed3SPierre Pronchery ASN1_INTEGER_dup(X509_get0_serialNumber(cert))) == NULL) 89*b077aed3SPierre Pronchery goto err; 90*b077aed3SPierre Pronchery 91*b077aed3SPierre Pronchery return cid; 92*b077aed3SPierre Pronchery err: 93*b077aed3SPierre Pronchery GENERAL_NAME_free(name); 94*b077aed3SPierre Pronchery ESS_CERT_ID_free(cid); 95*b077aed3SPierre Pronchery ERR_raise(ERR_LIB_ESS, ERR_R_MALLOC_FAILURE); 96*b077aed3SPierre Pronchery return NULL; 97*b077aed3SPierre Pronchery } 98*b077aed3SPierre Pronchery 99*b077aed3SPierre Pronchery ESS_SIGNING_CERT_V2 *OSSL_ESS_signing_cert_v2_new_init(const EVP_MD *hash_alg, 100*b077aed3SPierre Pronchery const X509 *signcert, 101*b077aed3SPierre Pronchery const 102*b077aed3SPierre Pronchery STACK_OF(X509) *certs, 103*b077aed3SPierre Pronchery int set_issuer_serial) 104*b077aed3SPierre Pronchery { 105*b077aed3SPierre Pronchery ESS_CERT_ID_V2 *cid = NULL; 106*b077aed3SPierre Pronchery ESS_SIGNING_CERT_V2 *sc; 107*b077aed3SPierre Pronchery int i; 108*b077aed3SPierre Pronchery 109*b077aed3SPierre Pronchery if ((sc = ESS_SIGNING_CERT_V2_new()) == NULL) 110*b077aed3SPierre Pronchery goto err; 111*b077aed3SPierre Pronchery cid = ESS_CERT_ID_V2_new_init(hash_alg, signcert, set_issuer_serial); 112*b077aed3SPierre Pronchery if (cid == NULL) 113*b077aed3SPierre Pronchery goto err; 114*b077aed3SPierre Pronchery if (!sk_ESS_CERT_ID_V2_push(sc->cert_ids, cid)) 115*b077aed3SPierre Pronchery goto err; 116*b077aed3SPierre Pronchery cid = NULL; 117*b077aed3SPierre Pronchery 118*b077aed3SPierre Pronchery for (i = 0; i < sk_X509_num(certs); ++i) { 119*b077aed3SPierre Pronchery X509 *cert = sk_X509_value(certs, i); 120*b077aed3SPierre Pronchery 121*b077aed3SPierre Pronchery if ((cid = ESS_CERT_ID_V2_new_init(hash_alg, cert, 1)) == NULL) 122*b077aed3SPierre Pronchery goto err; 123*b077aed3SPierre Pronchery if (!sk_ESS_CERT_ID_V2_push(sc->cert_ids, cid)) 124*b077aed3SPierre Pronchery goto err; 125*b077aed3SPierre Pronchery cid = NULL; 126*b077aed3SPierre Pronchery } 127*b077aed3SPierre Pronchery 128*b077aed3SPierre Pronchery return sc; 129*b077aed3SPierre Pronchery err: 130*b077aed3SPierre Pronchery ESS_SIGNING_CERT_V2_free(sc); 131*b077aed3SPierre Pronchery ESS_CERT_ID_V2_free(cid); 132*b077aed3SPierre Pronchery ERR_raise(ERR_LIB_ESS, ERR_R_MALLOC_FAILURE); 133*b077aed3SPierre Pronchery return NULL; 134*b077aed3SPierre Pronchery } 135*b077aed3SPierre Pronchery 136*b077aed3SPierre Pronchery static ESS_CERT_ID_V2 *ESS_CERT_ID_V2_new_init(const EVP_MD *hash_alg, 137*b077aed3SPierre Pronchery const X509 *cert, 138*b077aed3SPierre Pronchery int set_issuer_serial) 139*b077aed3SPierre Pronchery { 140*b077aed3SPierre Pronchery ESS_CERT_ID_V2 *cid; 141*b077aed3SPierre Pronchery GENERAL_NAME *name = NULL; 142*b077aed3SPierre Pronchery unsigned char hash[EVP_MAX_MD_SIZE]; 143*b077aed3SPierre Pronchery unsigned int hash_len = sizeof(hash); 144*b077aed3SPierre Pronchery X509_ALGOR *alg = NULL; 145*b077aed3SPierre Pronchery 146*b077aed3SPierre Pronchery memset(hash, 0, sizeof(hash)); 147*b077aed3SPierre Pronchery 148*b077aed3SPierre Pronchery if ((cid = ESS_CERT_ID_V2_new()) == NULL) 149*b077aed3SPierre Pronchery goto err; 150*b077aed3SPierre Pronchery 151*b077aed3SPierre Pronchery if (!EVP_MD_is_a(hash_alg, SN_sha256)) { 152*b077aed3SPierre Pronchery alg = X509_ALGOR_new(); 153*b077aed3SPierre Pronchery if (alg == NULL) 154*b077aed3SPierre Pronchery goto err; 155*b077aed3SPierre Pronchery X509_ALGOR_set_md(alg, hash_alg); 156*b077aed3SPierre Pronchery if (alg->algorithm == NULL) 157*b077aed3SPierre Pronchery goto err; 158*b077aed3SPierre Pronchery cid->hash_alg = alg; 159*b077aed3SPierre Pronchery alg = NULL; 160*b077aed3SPierre Pronchery } else { 161*b077aed3SPierre Pronchery cid->hash_alg = NULL; 162*b077aed3SPierre Pronchery } 163*b077aed3SPierre Pronchery 164*b077aed3SPierre Pronchery if (!X509_digest(cert, hash_alg, hash, &hash_len)) 165*b077aed3SPierre Pronchery goto err; 166*b077aed3SPierre Pronchery 167*b077aed3SPierre Pronchery if (!ASN1_OCTET_STRING_set(cid->hash, hash, hash_len)) 168*b077aed3SPierre Pronchery goto err; 169*b077aed3SPierre Pronchery 170*b077aed3SPierre Pronchery if (!set_issuer_serial) 171*b077aed3SPierre Pronchery return cid; 172*b077aed3SPierre Pronchery 173*b077aed3SPierre Pronchery if ((cid->issuer_serial = ESS_ISSUER_SERIAL_new()) == NULL) 174*b077aed3SPierre Pronchery goto err; 175*b077aed3SPierre Pronchery if ((name = GENERAL_NAME_new()) == NULL) 176*b077aed3SPierre Pronchery goto err; 177*b077aed3SPierre Pronchery name->type = GEN_DIRNAME; 178*b077aed3SPierre Pronchery if ((name->d.dirn = X509_NAME_dup(X509_get_issuer_name(cert))) == NULL) 179*b077aed3SPierre Pronchery goto err; 180*b077aed3SPierre Pronchery if (!sk_GENERAL_NAME_push(cid->issuer_serial->issuer, name)) 181*b077aed3SPierre Pronchery goto err; 182*b077aed3SPierre Pronchery name = NULL; /* Ownership is lost. */ 183*b077aed3SPierre Pronchery ASN1_INTEGER_free(cid->issuer_serial->serial); 184*b077aed3SPierre Pronchery cid->issuer_serial->serial = ASN1_INTEGER_dup(X509_get0_serialNumber(cert)); 185*b077aed3SPierre Pronchery if (cid->issuer_serial->serial == NULL) 186*b077aed3SPierre Pronchery goto err; 187*b077aed3SPierre Pronchery 188*b077aed3SPierre Pronchery return cid; 189*b077aed3SPierre Pronchery err: 190*b077aed3SPierre Pronchery X509_ALGOR_free(alg); 191*b077aed3SPierre Pronchery GENERAL_NAME_free(name); 192*b077aed3SPierre Pronchery ESS_CERT_ID_V2_free(cid); 193*b077aed3SPierre Pronchery ERR_raise(ERR_LIB_ESS, ERR_R_MALLOC_FAILURE); 194*b077aed3SPierre Pronchery return NULL; 195*b077aed3SPierre Pronchery } 196*b077aed3SPierre Pronchery 197*b077aed3SPierre Pronchery static int ess_issuer_serial_cmp(const ESS_ISSUER_SERIAL *is, const X509 *cert) 198*b077aed3SPierre Pronchery { 199*b077aed3SPierre Pronchery GENERAL_NAME *issuer; 200*b077aed3SPierre Pronchery 201*b077aed3SPierre Pronchery if (is == NULL || cert == NULL || sk_GENERAL_NAME_num(is->issuer) != 1) 202*b077aed3SPierre Pronchery return -1; 203*b077aed3SPierre Pronchery 204*b077aed3SPierre Pronchery issuer = sk_GENERAL_NAME_value(is->issuer, 0); 205*b077aed3SPierre Pronchery if (issuer->type != GEN_DIRNAME 206*b077aed3SPierre Pronchery || X509_NAME_cmp(issuer->d.dirn, X509_get_issuer_name(cert)) != 0) 207*b077aed3SPierre Pronchery return -1; 208*b077aed3SPierre Pronchery 209*b077aed3SPierre Pronchery return ASN1_INTEGER_cmp(is->serial, X509_get0_serialNumber(cert)); 210*b077aed3SPierre Pronchery } 211*b077aed3SPierre Pronchery 212*b077aed3SPierre Pronchery /* 213*b077aed3SPierre Pronchery * Find the cert in |certs| referenced by |cid| if not NULL, else by |cid_v2|. 214*b077aed3SPierre Pronchery * The cert must be the first one in |certs| if and only if |index| is 0. 215*b077aed3SPierre Pronchery * Return 0 on not found, -1 on error, else 1 + the position in |certs|. 216*b077aed3SPierre Pronchery */ 217*b077aed3SPierre Pronchery static int find(const ESS_CERT_ID *cid, const ESS_CERT_ID_V2 *cid_v2, 218*b077aed3SPierre Pronchery int index, const STACK_OF(X509) *certs) 219*b077aed3SPierre Pronchery { 220*b077aed3SPierre Pronchery const X509 *cert; 221*b077aed3SPierre Pronchery EVP_MD *md = NULL; 222*b077aed3SPierre Pronchery char name[OSSL_MAX_NAME_SIZE]; 223*b077aed3SPierre Pronchery unsigned char cert_digest[EVP_MAX_MD_SIZE]; 224*b077aed3SPierre Pronchery unsigned int len, cid_hash_len; 225*b077aed3SPierre Pronchery const ESS_ISSUER_SERIAL *is; 226*b077aed3SPierre Pronchery int i; 227*b077aed3SPierre Pronchery int ret = -1; 228*b077aed3SPierre Pronchery 229*b077aed3SPierre Pronchery if (cid == NULL && cid_v2 == NULL) { 230*b077aed3SPierre Pronchery ERR_raise(ERR_LIB_ESS, ERR_R_PASSED_INVALID_ARGUMENT); 231*b077aed3SPierre Pronchery return -1; 232*b077aed3SPierre Pronchery } 233*b077aed3SPierre Pronchery 234*b077aed3SPierre Pronchery if (cid != NULL) 235*b077aed3SPierre Pronchery strcpy(name, "SHA1"); 236*b077aed3SPierre Pronchery else if (cid_v2->hash_alg == NULL) 237*b077aed3SPierre Pronchery strcpy(name, "SHA256"); 238*b077aed3SPierre Pronchery else 239*b077aed3SPierre Pronchery OBJ_obj2txt(name, sizeof(name), cid_v2->hash_alg->algorithm, 0); 240*b077aed3SPierre Pronchery 241*b077aed3SPierre Pronchery (void)ERR_set_mark(); 242*b077aed3SPierre Pronchery md = EVP_MD_fetch(NULL, name, NULL); 243*b077aed3SPierre Pronchery 244*b077aed3SPierre Pronchery if (md == NULL) 245*b077aed3SPierre Pronchery md = (EVP_MD *)EVP_get_digestbyname(name); 246*b077aed3SPierre Pronchery 247*b077aed3SPierre Pronchery if (md == NULL) { 248*b077aed3SPierre Pronchery (void)ERR_clear_last_mark(); 249*b077aed3SPierre Pronchery ERR_raise(ERR_LIB_ESS, ESS_R_ESS_DIGEST_ALG_UNKNOWN); 250*b077aed3SPierre Pronchery goto end; 251*b077aed3SPierre Pronchery } 252*b077aed3SPierre Pronchery (void)ERR_pop_to_mark(); 253*b077aed3SPierre Pronchery 254*b077aed3SPierre Pronchery for (i = 0; i < sk_X509_num(certs); ++i) { 255*b077aed3SPierre Pronchery cert = sk_X509_value(certs, i); 256*b077aed3SPierre Pronchery 257*b077aed3SPierre Pronchery cid_hash_len = cid != NULL ? cid->hash->length : cid_v2->hash->length; 258*b077aed3SPierre Pronchery if (!X509_digest(cert, md, cert_digest, &len) 259*b077aed3SPierre Pronchery || cid_hash_len != len) { 260*b077aed3SPierre Pronchery ERR_raise(ERR_LIB_ESS, ESS_R_ESS_CERT_DIGEST_ERROR); 261*b077aed3SPierre Pronchery goto end; 262*b077aed3SPierre Pronchery } 263*b077aed3SPierre Pronchery 264*b077aed3SPierre Pronchery if (memcmp(cid != NULL ? cid->hash->data : cid_v2->hash->data, 265*b077aed3SPierre Pronchery cert_digest, len) == 0) { 266*b077aed3SPierre Pronchery is = cid != NULL ? cid->issuer_serial : cid_v2->issuer_serial; 267*b077aed3SPierre Pronchery /* Well, it's not really required to match the serial numbers. */ 268*b077aed3SPierre Pronchery if (is == NULL || ess_issuer_serial_cmp(is, cert) == 0) { 269*b077aed3SPierre Pronchery if ((i == 0) == (index == 0)) { 270*b077aed3SPierre Pronchery ret = i + 1; 271*b077aed3SPierre Pronchery goto end; 272*b077aed3SPierre Pronchery } 273*b077aed3SPierre Pronchery ERR_raise(ERR_LIB_ESS, ESS_R_ESS_CERT_ID_WRONG_ORDER); 274*b077aed3SPierre Pronchery goto end; 275*b077aed3SPierre Pronchery } 276*b077aed3SPierre Pronchery } 277*b077aed3SPierre Pronchery } 278*b077aed3SPierre Pronchery 279*b077aed3SPierre Pronchery ret = 0; 280*b077aed3SPierre Pronchery ERR_raise(ERR_LIB_ESS, ESS_R_ESS_CERT_ID_NOT_FOUND); 281*b077aed3SPierre Pronchery end: 282*b077aed3SPierre Pronchery EVP_MD_free(md); 283*b077aed3SPierre Pronchery return ret; 284*b077aed3SPierre Pronchery } 285*b077aed3SPierre Pronchery 286*b077aed3SPierre Pronchery int OSSL_ESS_check_signing_certs(const ESS_SIGNING_CERT *ss, 287*b077aed3SPierre Pronchery const ESS_SIGNING_CERT_V2 *ssv2, 288*b077aed3SPierre Pronchery const STACK_OF(X509) *chain, 289*b077aed3SPierre Pronchery int require_signing_cert) 290*b077aed3SPierre Pronchery { 291*b077aed3SPierre Pronchery int n_v1 = ss == NULL ? -1 : sk_ESS_CERT_ID_num(ss->cert_ids); 292*b077aed3SPierre Pronchery int n_v2 = ssv2 == NULL ? -1 : sk_ESS_CERT_ID_V2_num(ssv2->cert_ids); 293*b077aed3SPierre Pronchery int i, ret; 294*b077aed3SPierre Pronchery 295*b077aed3SPierre Pronchery if (require_signing_cert && ss == NULL && ssv2 == NULL) { 296*b077aed3SPierre Pronchery ERR_raise(ERR_LIB_CMS, ESS_R_MISSING_SIGNING_CERTIFICATE_ATTRIBUTE); 297*b077aed3SPierre Pronchery return -1; 298*b077aed3SPierre Pronchery } 299*b077aed3SPierre Pronchery if (n_v1 == 0 || n_v2 == 0) { 300*b077aed3SPierre Pronchery ERR_raise(ERR_LIB_ESS, ESS_R_EMPTY_ESS_CERT_ID_LIST); 301*b077aed3SPierre Pronchery return -1; 302*b077aed3SPierre Pronchery } 303*b077aed3SPierre Pronchery /* If both ss and ssv2 exist, as required evaluate them independently. */ 304*b077aed3SPierre Pronchery for (i = 0; i < n_v1; i++) { 305*b077aed3SPierre Pronchery ret = find(sk_ESS_CERT_ID_value(ss->cert_ids, i), NULL, i, chain); 306*b077aed3SPierre Pronchery if (ret <= 0) 307*b077aed3SPierre Pronchery return ret; 308*b077aed3SPierre Pronchery } 309*b077aed3SPierre Pronchery for (i = 0; i < n_v2; i++) { 310*b077aed3SPierre Pronchery ret = find(NULL, sk_ESS_CERT_ID_V2_value(ssv2->cert_ids, i), i, chain); 311*b077aed3SPierre Pronchery if (ret <= 0) 312*b077aed3SPierre Pronchery return ret; 313*b077aed3SPierre Pronchery } 314*b077aed3SPierre Pronchery return 1; 315*b077aed3SPierre Pronchery } 316