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