1e1051a39Sopenharmony_ci/* 2e1051a39Sopenharmony_ci * Copyright 1995-2022 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 <stdio.h> 11e1051a39Sopenharmony_ci#include "internal/cryptlib.h" 12e1051a39Sopenharmony_ci#include <openssl/asn1.h> 13e1051a39Sopenharmony_ci#include <openssl/objects.h> 14e1051a39Sopenharmony_ci#include <openssl/x509.h> 15e1051a39Sopenharmony_ci#include <openssl/x509v3.h> 16e1051a39Sopenharmony_ci#include <openssl/core_names.h> 17e1051a39Sopenharmony_ci#include "crypto/x509.h" 18e1051a39Sopenharmony_ci 19e1051a39Sopenharmony_ciint X509_issuer_and_serial_cmp(const X509 *a, const X509 *b) 20e1051a39Sopenharmony_ci{ 21e1051a39Sopenharmony_ci int i; 22e1051a39Sopenharmony_ci const X509_CINF *ai, *bi; 23e1051a39Sopenharmony_ci 24e1051a39Sopenharmony_ci if (b == NULL) 25e1051a39Sopenharmony_ci return a != NULL; 26e1051a39Sopenharmony_ci if (a == NULL) 27e1051a39Sopenharmony_ci return -1; 28e1051a39Sopenharmony_ci ai = &a->cert_info; 29e1051a39Sopenharmony_ci bi = &b->cert_info; 30e1051a39Sopenharmony_ci i = ASN1_INTEGER_cmp(&ai->serialNumber, &bi->serialNumber); 31e1051a39Sopenharmony_ci if (i != 0) 32e1051a39Sopenharmony_ci return i < 0 ? -1 : 1; 33e1051a39Sopenharmony_ci return X509_NAME_cmp(ai->issuer, bi->issuer); 34e1051a39Sopenharmony_ci} 35e1051a39Sopenharmony_ci 36e1051a39Sopenharmony_ci#ifndef OPENSSL_NO_MD5 37e1051a39Sopenharmony_ciunsigned long X509_issuer_and_serial_hash(X509 *a) 38e1051a39Sopenharmony_ci{ 39e1051a39Sopenharmony_ci unsigned long ret = 0; 40e1051a39Sopenharmony_ci EVP_MD_CTX *ctx = EVP_MD_CTX_new(); 41e1051a39Sopenharmony_ci unsigned char md[16]; 42e1051a39Sopenharmony_ci char *f = NULL; 43e1051a39Sopenharmony_ci EVP_MD *digest = NULL; 44e1051a39Sopenharmony_ci 45e1051a39Sopenharmony_ci if (ctx == NULL) 46e1051a39Sopenharmony_ci goto err; 47e1051a39Sopenharmony_ci f = X509_NAME_oneline(a->cert_info.issuer, NULL, 0); 48e1051a39Sopenharmony_ci if (f == NULL) 49e1051a39Sopenharmony_ci goto err; 50e1051a39Sopenharmony_ci digest = EVP_MD_fetch(a->libctx, SN_md5, a->propq); 51e1051a39Sopenharmony_ci if (digest == NULL) 52e1051a39Sopenharmony_ci goto err; 53e1051a39Sopenharmony_ci 54e1051a39Sopenharmony_ci if (!EVP_DigestInit_ex(ctx, digest, NULL)) 55e1051a39Sopenharmony_ci goto err; 56e1051a39Sopenharmony_ci if (!EVP_DigestUpdate(ctx, (unsigned char *)f, strlen(f))) 57e1051a39Sopenharmony_ci goto err; 58e1051a39Sopenharmony_ci if (!EVP_DigestUpdate 59e1051a39Sopenharmony_ci (ctx, (unsigned char *)a->cert_info.serialNumber.data, 60e1051a39Sopenharmony_ci (unsigned long)a->cert_info.serialNumber.length)) 61e1051a39Sopenharmony_ci goto err; 62e1051a39Sopenharmony_ci if (!EVP_DigestFinal_ex(ctx, &(md[0]), NULL)) 63e1051a39Sopenharmony_ci goto err; 64e1051a39Sopenharmony_ci ret = (((unsigned long)md[0]) | ((unsigned long)md[1] << 8L) | 65e1051a39Sopenharmony_ci ((unsigned long)md[2] << 16L) | ((unsigned long)md[3] << 24L) 66e1051a39Sopenharmony_ci ) & 0xffffffffL; 67e1051a39Sopenharmony_ci err: 68e1051a39Sopenharmony_ci OPENSSL_free(f); 69e1051a39Sopenharmony_ci EVP_MD_free(digest); 70e1051a39Sopenharmony_ci EVP_MD_CTX_free(ctx); 71e1051a39Sopenharmony_ci return ret; 72e1051a39Sopenharmony_ci} 73e1051a39Sopenharmony_ci#endif 74e1051a39Sopenharmony_ci 75e1051a39Sopenharmony_ciint X509_issuer_name_cmp(const X509 *a, const X509 *b) 76e1051a39Sopenharmony_ci{ 77e1051a39Sopenharmony_ci return X509_NAME_cmp(a->cert_info.issuer, b->cert_info.issuer); 78e1051a39Sopenharmony_ci} 79e1051a39Sopenharmony_ci 80e1051a39Sopenharmony_ciint X509_subject_name_cmp(const X509 *a, const X509 *b) 81e1051a39Sopenharmony_ci{ 82e1051a39Sopenharmony_ci return X509_NAME_cmp(a->cert_info.subject, b->cert_info.subject); 83e1051a39Sopenharmony_ci} 84e1051a39Sopenharmony_ci 85e1051a39Sopenharmony_ciint X509_CRL_cmp(const X509_CRL *a, const X509_CRL *b) 86e1051a39Sopenharmony_ci{ 87e1051a39Sopenharmony_ci return X509_NAME_cmp(a->crl.issuer, b->crl.issuer); 88e1051a39Sopenharmony_ci} 89e1051a39Sopenharmony_ci 90e1051a39Sopenharmony_ciint X509_CRL_match(const X509_CRL *a, const X509_CRL *b) 91e1051a39Sopenharmony_ci{ 92e1051a39Sopenharmony_ci int rv; 93e1051a39Sopenharmony_ci 94e1051a39Sopenharmony_ci if ((a->flags & EXFLAG_NO_FINGERPRINT) == 0 95e1051a39Sopenharmony_ci && (b->flags & EXFLAG_NO_FINGERPRINT) == 0) 96e1051a39Sopenharmony_ci rv = memcmp(a->sha1_hash, b->sha1_hash, SHA_DIGEST_LENGTH); 97e1051a39Sopenharmony_ci else 98e1051a39Sopenharmony_ci return -2; 99e1051a39Sopenharmony_ci 100e1051a39Sopenharmony_ci return rv < 0 ? -1 : rv > 0; 101e1051a39Sopenharmony_ci} 102e1051a39Sopenharmony_ci 103e1051a39Sopenharmony_ciX509_NAME *X509_get_issuer_name(const X509 *a) 104e1051a39Sopenharmony_ci{ 105e1051a39Sopenharmony_ci return a->cert_info.issuer; 106e1051a39Sopenharmony_ci} 107e1051a39Sopenharmony_ci 108e1051a39Sopenharmony_ciunsigned long X509_issuer_name_hash(X509 *x) 109e1051a39Sopenharmony_ci{ 110e1051a39Sopenharmony_ci return X509_NAME_hash_ex(x->cert_info.issuer, NULL, NULL, NULL); 111e1051a39Sopenharmony_ci} 112e1051a39Sopenharmony_ci 113e1051a39Sopenharmony_ci#ifndef OPENSSL_NO_MD5 114e1051a39Sopenharmony_ciunsigned long X509_issuer_name_hash_old(X509 *x) 115e1051a39Sopenharmony_ci{ 116e1051a39Sopenharmony_ci return X509_NAME_hash_old(x->cert_info.issuer); 117e1051a39Sopenharmony_ci} 118e1051a39Sopenharmony_ci#endif 119e1051a39Sopenharmony_ci 120e1051a39Sopenharmony_ciX509_NAME *X509_get_subject_name(const X509 *a) 121e1051a39Sopenharmony_ci{ 122e1051a39Sopenharmony_ci return a->cert_info.subject; 123e1051a39Sopenharmony_ci} 124e1051a39Sopenharmony_ci 125e1051a39Sopenharmony_ciASN1_INTEGER *X509_get_serialNumber(X509 *a) 126e1051a39Sopenharmony_ci{ 127e1051a39Sopenharmony_ci return &a->cert_info.serialNumber; 128e1051a39Sopenharmony_ci} 129e1051a39Sopenharmony_ci 130e1051a39Sopenharmony_ciconst ASN1_INTEGER *X509_get0_serialNumber(const X509 *a) 131e1051a39Sopenharmony_ci{ 132e1051a39Sopenharmony_ci return &a->cert_info.serialNumber; 133e1051a39Sopenharmony_ci} 134e1051a39Sopenharmony_ci 135e1051a39Sopenharmony_ciunsigned long X509_subject_name_hash(X509 *x) 136e1051a39Sopenharmony_ci{ 137e1051a39Sopenharmony_ci return X509_NAME_hash_ex(x->cert_info.subject, NULL, NULL, NULL); 138e1051a39Sopenharmony_ci} 139e1051a39Sopenharmony_ci 140e1051a39Sopenharmony_ci#ifndef OPENSSL_NO_MD5 141e1051a39Sopenharmony_ciunsigned long X509_subject_name_hash_old(X509 *x) 142e1051a39Sopenharmony_ci{ 143e1051a39Sopenharmony_ci return X509_NAME_hash_old(x->cert_info.subject); 144e1051a39Sopenharmony_ci} 145e1051a39Sopenharmony_ci#endif 146e1051a39Sopenharmony_ci 147e1051a39Sopenharmony_ci/* 148e1051a39Sopenharmony_ci * Compare two certificates: they must be identical for this to work. NB: 149e1051a39Sopenharmony_ci * Although "cmp" operations are generally prototyped to take "const" 150e1051a39Sopenharmony_ci * arguments (eg. for use in STACKs), the way X509 handling is - these 151e1051a39Sopenharmony_ci * operations may involve ensuring the hashes are up-to-date and ensuring 152e1051a39Sopenharmony_ci * certain cert information is cached. So this is the point where the 153e1051a39Sopenharmony_ci * "depth-first" constification tree has to halt with an evil cast. 154e1051a39Sopenharmony_ci */ 155e1051a39Sopenharmony_ciint X509_cmp(const X509 *a, const X509 *b) 156e1051a39Sopenharmony_ci{ 157e1051a39Sopenharmony_ci int rv = 0; 158e1051a39Sopenharmony_ci 159e1051a39Sopenharmony_ci if (a == b) /* for efficiency */ 160e1051a39Sopenharmony_ci return 0; 161e1051a39Sopenharmony_ci 162e1051a39Sopenharmony_ci /* attempt to compute cert hash */ 163e1051a39Sopenharmony_ci (void)X509_check_purpose((X509 *)a, -1, 0); 164e1051a39Sopenharmony_ci (void)X509_check_purpose((X509 *)b, -1, 0); 165e1051a39Sopenharmony_ci 166e1051a39Sopenharmony_ci if ((a->ex_flags & EXFLAG_NO_FINGERPRINT) == 0 167e1051a39Sopenharmony_ci && (b->ex_flags & EXFLAG_NO_FINGERPRINT) == 0) 168e1051a39Sopenharmony_ci rv = memcmp(a->sha1_hash, b->sha1_hash, SHA_DIGEST_LENGTH); 169e1051a39Sopenharmony_ci if (rv != 0) 170e1051a39Sopenharmony_ci return rv < 0 ? -1 : 1; 171e1051a39Sopenharmony_ci 172e1051a39Sopenharmony_ci /* Check for match against stored encoding too */ 173e1051a39Sopenharmony_ci if (!a->cert_info.enc.modified && !b->cert_info.enc.modified) { 174e1051a39Sopenharmony_ci if (a->cert_info.enc.len < b->cert_info.enc.len) 175e1051a39Sopenharmony_ci return -1; 176e1051a39Sopenharmony_ci if (a->cert_info.enc.len > b->cert_info.enc.len) 177e1051a39Sopenharmony_ci return 1; 178e1051a39Sopenharmony_ci rv = memcmp(a->cert_info.enc.enc, 179e1051a39Sopenharmony_ci b->cert_info.enc.enc, a->cert_info.enc.len); 180e1051a39Sopenharmony_ci } 181e1051a39Sopenharmony_ci return rv < 0 ? -1 : rv > 0; 182e1051a39Sopenharmony_ci} 183e1051a39Sopenharmony_ci 184e1051a39Sopenharmony_ciint ossl_x509_add_cert_new(STACK_OF(X509) **p_sk, X509 *cert, int flags) 185e1051a39Sopenharmony_ci{ 186e1051a39Sopenharmony_ci if (*p_sk == NULL && (*p_sk = sk_X509_new_null()) == NULL) { 187e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_X509, ERR_R_MALLOC_FAILURE); 188e1051a39Sopenharmony_ci return 0; 189e1051a39Sopenharmony_ci } 190e1051a39Sopenharmony_ci return X509_add_cert(*p_sk, cert, flags); 191e1051a39Sopenharmony_ci} 192e1051a39Sopenharmony_ci 193e1051a39Sopenharmony_ciint X509_add_cert(STACK_OF(X509) *sk, X509 *cert, int flags) 194e1051a39Sopenharmony_ci{ 195e1051a39Sopenharmony_ci if (sk == NULL) { 196e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_X509, ERR_R_PASSED_NULL_PARAMETER); 197e1051a39Sopenharmony_ci return 0; 198e1051a39Sopenharmony_ci } 199e1051a39Sopenharmony_ci if ((flags & X509_ADD_FLAG_NO_DUP) != 0) { 200e1051a39Sopenharmony_ci /* 201e1051a39Sopenharmony_ci * not using sk_X509_set_cmp_func() and sk_X509_find() 202e1051a39Sopenharmony_ci * because this re-orders the certs on the stack 203e1051a39Sopenharmony_ci */ 204e1051a39Sopenharmony_ci int i; 205e1051a39Sopenharmony_ci 206e1051a39Sopenharmony_ci for (i = 0; i < sk_X509_num(sk); i++) { 207e1051a39Sopenharmony_ci if (X509_cmp(sk_X509_value(sk, i), cert) == 0) 208e1051a39Sopenharmony_ci return 1; 209e1051a39Sopenharmony_ci } 210e1051a39Sopenharmony_ci } 211e1051a39Sopenharmony_ci if ((flags & X509_ADD_FLAG_NO_SS) != 0) { 212e1051a39Sopenharmony_ci int ret = X509_self_signed(cert, 0); 213e1051a39Sopenharmony_ci 214e1051a39Sopenharmony_ci if (ret != 0) 215e1051a39Sopenharmony_ci return ret > 0 ? 1 : 0; 216e1051a39Sopenharmony_ci } 217e1051a39Sopenharmony_ci if (!sk_X509_insert(sk, cert, 218e1051a39Sopenharmony_ci (flags & X509_ADD_FLAG_PREPEND) != 0 ? 0 : -1)) { 219e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_X509, ERR_R_MALLOC_FAILURE); 220e1051a39Sopenharmony_ci return 0; 221e1051a39Sopenharmony_ci } 222e1051a39Sopenharmony_ci if ((flags & X509_ADD_FLAG_UP_REF) != 0) 223e1051a39Sopenharmony_ci (void)X509_up_ref(cert); 224e1051a39Sopenharmony_ci return 1; 225e1051a39Sopenharmony_ci} 226e1051a39Sopenharmony_ci 227e1051a39Sopenharmony_ciint X509_add_certs(STACK_OF(X509) *sk, STACK_OF(X509) *certs, int flags) 228e1051a39Sopenharmony_ci/* compiler would allow 'const' for the certs, yet they may get up-ref'ed */ 229e1051a39Sopenharmony_ci{ 230e1051a39Sopenharmony_ci if (sk == NULL) { 231e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_X509, ERR_R_PASSED_NULL_PARAMETER); 232e1051a39Sopenharmony_ci return 0; 233e1051a39Sopenharmony_ci } 234e1051a39Sopenharmony_ci return ossl_x509_add_certs_new(&sk, certs, flags); 235e1051a39Sopenharmony_ci} 236e1051a39Sopenharmony_ci 237e1051a39Sopenharmony_ciint ossl_x509_add_certs_new(STACK_OF(X509) **p_sk, STACK_OF(X509) *certs, 238e1051a39Sopenharmony_ci int flags) 239e1051a39Sopenharmony_ci/* compiler would allow 'const' for the certs, yet they may get up-ref'ed */ 240e1051a39Sopenharmony_ci{ 241e1051a39Sopenharmony_ci int n = sk_X509_num(certs /* may be NULL */); 242e1051a39Sopenharmony_ci int i; 243e1051a39Sopenharmony_ci 244e1051a39Sopenharmony_ci for (i = 0; i < n; i++) { 245e1051a39Sopenharmony_ci int j = (flags & X509_ADD_FLAG_PREPEND) == 0 ? i : n - 1 - i; 246e1051a39Sopenharmony_ci /* if prepend, add certs in reverse order to keep original order */ 247e1051a39Sopenharmony_ci 248e1051a39Sopenharmony_ci if (!ossl_x509_add_cert_new(p_sk, sk_X509_value(certs, j), flags)) 249e1051a39Sopenharmony_ci return 0; 250e1051a39Sopenharmony_ci } 251e1051a39Sopenharmony_ci return 1; 252e1051a39Sopenharmony_ci} 253e1051a39Sopenharmony_ci 254e1051a39Sopenharmony_ciint X509_NAME_cmp(const X509_NAME *a, const X509_NAME *b) 255e1051a39Sopenharmony_ci{ 256e1051a39Sopenharmony_ci int ret; 257e1051a39Sopenharmony_ci 258e1051a39Sopenharmony_ci if (b == NULL) 259e1051a39Sopenharmony_ci return a != NULL; 260e1051a39Sopenharmony_ci if (a == NULL) 261e1051a39Sopenharmony_ci return -1; 262e1051a39Sopenharmony_ci 263e1051a39Sopenharmony_ci /* Ensure canonical encoding is present and up to date */ 264e1051a39Sopenharmony_ci if (a->canon_enc == NULL || a->modified) { 265e1051a39Sopenharmony_ci ret = i2d_X509_NAME((X509_NAME *)a, NULL); 266e1051a39Sopenharmony_ci if (ret < 0) 267e1051a39Sopenharmony_ci return -2; 268e1051a39Sopenharmony_ci } 269e1051a39Sopenharmony_ci 270e1051a39Sopenharmony_ci if (b->canon_enc == NULL || b->modified) { 271e1051a39Sopenharmony_ci ret = i2d_X509_NAME((X509_NAME *)b, NULL); 272e1051a39Sopenharmony_ci if (ret < 0) 273e1051a39Sopenharmony_ci return -2; 274e1051a39Sopenharmony_ci } 275e1051a39Sopenharmony_ci 276e1051a39Sopenharmony_ci ret = a->canon_enclen - b->canon_enclen; 277e1051a39Sopenharmony_ci if (ret == 0 && a->canon_enclen == 0) 278e1051a39Sopenharmony_ci return 0; 279e1051a39Sopenharmony_ci 280e1051a39Sopenharmony_ci if (a->canon_enc == NULL || b->canon_enc == NULL) 281e1051a39Sopenharmony_ci return -2; 282e1051a39Sopenharmony_ci 283e1051a39Sopenharmony_ci if (ret == 0) 284e1051a39Sopenharmony_ci ret = memcmp(a->canon_enc, b->canon_enc, a->canon_enclen); 285e1051a39Sopenharmony_ci 286e1051a39Sopenharmony_ci return ret < 0 ? -1 : ret > 0; 287e1051a39Sopenharmony_ci} 288e1051a39Sopenharmony_ci 289e1051a39Sopenharmony_ciunsigned long X509_NAME_hash_ex(const X509_NAME *x, OSSL_LIB_CTX *libctx, 290e1051a39Sopenharmony_ci const char *propq, int *ok) 291e1051a39Sopenharmony_ci{ 292e1051a39Sopenharmony_ci unsigned long ret = 0; 293e1051a39Sopenharmony_ci unsigned char md[SHA_DIGEST_LENGTH]; 294e1051a39Sopenharmony_ci EVP_MD *sha1 = EVP_MD_fetch(libctx, "SHA1", propq); 295e1051a39Sopenharmony_ci 296e1051a39Sopenharmony_ci /* Make sure X509_NAME structure contains valid cached encoding */ 297e1051a39Sopenharmony_ci i2d_X509_NAME(x, NULL); 298e1051a39Sopenharmony_ci if (ok != NULL) 299e1051a39Sopenharmony_ci *ok = 0; 300e1051a39Sopenharmony_ci if (sha1 != NULL 301e1051a39Sopenharmony_ci && EVP_Digest(x->canon_enc, x->canon_enclen, md, NULL, sha1, NULL)) { 302e1051a39Sopenharmony_ci ret = (((unsigned long)md[0]) | ((unsigned long)md[1] << 8L) | 303e1051a39Sopenharmony_ci ((unsigned long)md[2] << 16L) | ((unsigned long)md[3] << 24L) 304e1051a39Sopenharmony_ci ) & 0xffffffffL; 305e1051a39Sopenharmony_ci if (ok != NULL) 306e1051a39Sopenharmony_ci *ok = 1; 307e1051a39Sopenharmony_ci } 308e1051a39Sopenharmony_ci EVP_MD_free(sha1); 309e1051a39Sopenharmony_ci return ret; 310e1051a39Sopenharmony_ci} 311e1051a39Sopenharmony_ci 312e1051a39Sopenharmony_ci#ifndef OPENSSL_NO_MD5 313e1051a39Sopenharmony_ci/* 314e1051a39Sopenharmony_ci * I now DER encode the name and hash it. Since I cache the DER encoding, 315e1051a39Sopenharmony_ci * this is reasonably efficient. 316e1051a39Sopenharmony_ci */ 317e1051a39Sopenharmony_ciunsigned long X509_NAME_hash_old(const X509_NAME *x) 318e1051a39Sopenharmony_ci{ 319e1051a39Sopenharmony_ci EVP_MD *md5 = EVP_MD_fetch(NULL, OSSL_DIGEST_NAME_MD5, "-fips"); 320e1051a39Sopenharmony_ci EVP_MD_CTX *md_ctx = EVP_MD_CTX_new(); 321e1051a39Sopenharmony_ci unsigned long ret = 0; 322e1051a39Sopenharmony_ci unsigned char md[16]; 323e1051a39Sopenharmony_ci 324e1051a39Sopenharmony_ci if (md5 == NULL || md_ctx == NULL) 325e1051a39Sopenharmony_ci goto end; 326e1051a39Sopenharmony_ci 327e1051a39Sopenharmony_ci /* Make sure X509_NAME structure contains valid cached encoding */ 328e1051a39Sopenharmony_ci i2d_X509_NAME(x, NULL); 329e1051a39Sopenharmony_ci if (EVP_DigestInit_ex(md_ctx, md5, NULL) 330e1051a39Sopenharmony_ci && EVP_DigestUpdate(md_ctx, x->bytes->data, x->bytes->length) 331e1051a39Sopenharmony_ci && EVP_DigestFinal_ex(md_ctx, md, NULL)) 332e1051a39Sopenharmony_ci ret = (((unsigned long)md[0]) | ((unsigned long)md[1] << 8L) | 333e1051a39Sopenharmony_ci ((unsigned long)md[2] << 16L) | ((unsigned long)md[3] << 24L) 334e1051a39Sopenharmony_ci ) & 0xffffffffL; 335e1051a39Sopenharmony_ci 336e1051a39Sopenharmony_ci end: 337e1051a39Sopenharmony_ci EVP_MD_CTX_free(md_ctx); 338e1051a39Sopenharmony_ci EVP_MD_free(md5); 339e1051a39Sopenharmony_ci 340e1051a39Sopenharmony_ci return ret; 341e1051a39Sopenharmony_ci} 342e1051a39Sopenharmony_ci#endif 343e1051a39Sopenharmony_ci 344e1051a39Sopenharmony_ci/* Search a stack of X509 for a match */ 345e1051a39Sopenharmony_ciX509 *X509_find_by_issuer_and_serial(STACK_OF(X509) *sk, const X509_NAME *name, 346e1051a39Sopenharmony_ci const ASN1_INTEGER *serial) 347e1051a39Sopenharmony_ci{ 348e1051a39Sopenharmony_ci int i; 349e1051a39Sopenharmony_ci X509 x, *x509 = NULL; 350e1051a39Sopenharmony_ci 351e1051a39Sopenharmony_ci if (!sk) 352e1051a39Sopenharmony_ci return NULL; 353e1051a39Sopenharmony_ci 354e1051a39Sopenharmony_ci x.cert_info.serialNumber = *serial; 355e1051a39Sopenharmony_ci x.cert_info.issuer = (X509_NAME *)name; /* won't modify it */ 356e1051a39Sopenharmony_ci 357e1051a39Sopenharmony_ci for (i = 0; i < sk_X509_num(sk); i++) { 358e1051a39Sopenharmony_ci x509 = sk_X509_value(sk, i); 359e1051a39Sopenharmony_ci if (X509_issuer_and_serial_cmp(x509, &x) == 0) 360e1051a39Sopenharmony_ci return x509; 361e1051a39Sopenharmony_ci } 362e1051a39Sopenharmony_ci return NULL; 363e1051a39Sopenharmony_ci} 364e1051a39Sopenharmony_ci 365e1051a39Sopenharmony_ciX509 *X509_find_by_subject(STACK_OF(X509) *sk, const X509_NAME *name) 366e1051a39Sopenharmony_ci{ 367e1051a39Sopenharmony_ci X509 *x509; 368e1051a39Sopenharmony_ci int i; 369e1051a39Sopenharmony_ci 370e1051a39Sopenharmony_ci for (i = 0; i < sk_X509_num(sk); i++) { 371e1051a39Sopenharmony_ci x509 = sk_X509_value(sk, i); 372e1051a39Sopenharmony_ci if (X509_NAME_cmp(X509_get_subject_name(x509), name) == 0) 373e1051a39Sopenharmony_ci return x509; 374e1051a39Sopenharmony_ci } 375e1051a39Sopenharmony_ci return NULL; 376e1051a39Sopenharmony_ci} 377e1051a39Sopenharmony_ci 378e1051a39Sopenharmony_ciEVP_PKEY *X509_get0_pubkey(const X509 *x) 379e1051a39Sopenharmony_ci{ 380e1051a39Sopenharmony_ci if (x == NULL) 381e1051a39Sopenharmony_ci return NULL; 382e1051a39Sopenharmony_ci return X509_PUBKEY_get0(x->cert_info.key); 383e1051a39Sopenharmony_ci} 384e1051a39Sopenharmony_ci 385e1051a39Sopenharmony_ciEVP_PKEY *X509_get_pubkey(X509 *x) 386e1051a39Sopenharmony_ci{ 387e1051a39Sopenharmony_ci if (x == NULL) 388e1051a39Sopenharmony_ci return NULL; 389e1051a39Sopenharmony_ci return X509_PUBKEY_get(x->cert_info.key); 390e1051a39Sopenharmony_ci} 391e1051a39Sopenharmony_ci 392e1051a39Sopenharmony_ciint X509_check_private_key(const X509 *x, const EVP_PKEY *k) 393e1051a39Sopenharmony_ci{ 394e1051a39Sopenharmony_ci const EVP_PKEY *xk; 395e1051a39Sopenharmony_ci int ret; 396e1051a39Sopenharmony_ci 397e1051a39Sopenharmony_ci xk = X509_get0_pubkey(x); 398e1051a39Sopenharmony_ci if (xk == NULL) { 399e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_X509, X509_R_UNABLE_TO_GET_CERTS_PUBLIC_KEY); 400e1051a39Sopenharmony_ci return 0; 401e1051a39Sopenharmony_ci } 402e1051a39Sopenharmony_ci 403e1051a39Sopenharmony_ci switch (ret = EVP_PKEY_eq(xk, k)) { 404e1051a39Sopenharmony_ci case 0: 405e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_X509, X509_R_KEY_VALUES_MISMATCH); 406e1051a39Sopenharmony_ci break; 407e1051a39Sopenharmony_ci case -1: 408e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_X509, X509_R_KEY_TYPE_MISMATCH); 409e1051a39Sopenharmony_ci break; 410e1051a39Sopenharmony_ci case -2: 411e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_X509, X509_R_UNKNOWN_KEY_TYPE); 412e1051a39Sopenharmony_ci break; 413e1051a39Sopenharmony_ci } 414e1051a39Sopenharmony_ci 415e1051a39Sopenharmony_ci return ret > 0; 416e1051a39Sopenharmony_ci} 417e1051a39Sopenharmony_ci 418e1051a39Sopenharmony_ci/* 419e1051a39Sopenharmony_ci * Check a suite B algorithm is permitted: pass in a public key and the NID 420e1051a39Sopenharmony_ci * of its signature (or 0 if no signature). The pflags is a pointer to a 421e1051a39Sopenharmony_ci * flags field which must contain the suite B verification flags. 422e1051a39Sopenharmony_ci */ 423e1051a39Sopenharmony_ci 424e1051a39Sopenharmony_ci#ifndef OPENSSL_NO_EC 425e1051a39Sopenharmony_ci 426e1051a39Sopenharmony_cistatic int check_suite_b(EVP_PKEY *pkey, int sign_nid, unsigned long *pflags) 427e1051a39Sopenharmony_ci{ 428e1051a39Sopenharmony_ci char curve_name[80]; 429e1051a39Sopenharmony_ci size_t curve_name_len; 430e1051a39Sopenharmony_ci int curve_nid; 431e1051a39Sopenharmony_ci 432e1051a39Sopenharmony_ci if (pkey == NULL || !EVP_PKEY_is_a(pkey, "EC")) 433e1051a39Sopenharmony_ci return X509_V_ERR_SUITE_B_INVALID_ALGORITHM; 434e1051a39Sopenharmony_ci 435e1051a39Sopenharmony_ci if (!EVP_PKEY_get_group_name(pkey, curve_name, sizeof(curve_name), 436e1051a39Sopenharmony_ci &curve_name_len)) 437e1051a39Sopenharmony_ci return X509_V_ERR_SUITE_B_INVALID_CURVE; 438e1051a39Sopenharmony_ci 439e1051a39Sopenharmony_ci curve_nid = OBJ_txt2nid(curve_name); 440e1051a39Sopenharmony_ci /* Check curve is consistent with LOS */ 441e1051a39Sopenharmony_ci if (curve_nid == NID_secp384r1) { /* P-384 */ 442e1051a39Sopenharmony_ci /* 443e1051a39Sopenharmony_ci * Check signature algorithm is consistent with curve. 444e1051a39Sopenharmony_ci */ 445e1051a39Sopenharmony_ci if (sign_nid != -1 && sign_nid != NID_ecdsa_with_SHA384) 446e1051a39Sopenharmony_ci return X509_V_ERR_SUITE_B_INVALID_SIGNATURE_ALGORITHM; 447e1051a39Sopenharmony_ci if (!(*pflags & X509_V_FLAG_SUITEB_192_LOS)) 448e1051a39Sopenharmony_ci return X509_V_ERR_SUITE_B_LOS_NOT_ALLOWED; 449e1051a39Sopenharmony_ci /* If we encounter P-384 we cannot use P-256 later */ 450e1051a39Sopenharmony_ci *pflags &= ~X509_V_FLAG_SUITEB_128_LOS_ONLY; 451e1051a39Sopenharmony_ci } else if (curve_nid == NID_X9_62_prime256v1) { /* P-256 */ 452e1051a39Sopenharmony_ci if (sign_nid != -1 && sign_nid != NID_ecdsa_with_SHA256) 453e1051a39Sopenharmony_ci return X509_V_ERR_SUITE_B_INVALID_SIGNATURE_ALGORITHM; 454e1051a39Sopenharmony_ci if (!(*pflags & X509_V_FLAG_SUITEB_128_LOS_ONLY)) 455e1051a39Sopenharmony_ci return X509_V_ERR_SUITE_B_LOS_NOT_ALLOWED; 456e1051a39Sopenharmony_ci } else { 457e1051a39Sopenharmony_ci return X509_V_ERR_SUITE_B_INVALID_CURVE; 458e1051a39Sopenharmony_ci } 459e1051a39Sopenharmony_ci return X509_V_OK; 460e1051a39Sopenharmony_ci} 461e1051a39Sopenharmony_ci 462e1051a39Sopenharmony_ciint X509_chain_check_suiteb(int *perror_depth, X509 *x, STACK_OF(X509) *chain, 463e1051a39Sopenharmony_ci unsigned long flags) 464e1051a39Sopenharmony_ci{ 465e1051a39Sopenharmony_ci int rv, i, sign_nid; 466e1051a39Sopenharmony_ci EVP_PKEY *pk; 467e1051a39Sopenharmony_ci unsigned long tflags = flags; 468e1051a39Sopenharmony_ci 469e1051a39Sopenharmony_ci if (!(flags & X509_V_FLAG_SUITEB_128_LOS)) 470e1051a39Sopenharmony_ci return X509_V_OK; 471e1051a39Sopenharmony_ci 472e1051a39Sopenharmony_ci /* If no EE certificate passed in must be first in chain */ 473e1051a39Sopenharmony_ci if (x == NULL) { 474e1051a39Sopenharmony_ci x = sk_X509_value(chain, 0); 475e1051a39Sopenharmony_ci i = 1; 476e1051a39Sopenharmony_ci } else { 477e1051a39Sopenharmony_ci i = 0; 478e1051a39Sopenharmony_ci } 479e1051a39Sopenharmony_ci pk = X509_get0_pubkey(x); 480e1051a39Sopenharmony_ci 481e1051a39Sopenharmony_ci /* 482e1051a39Sopenharmony_ci * With DANE-EE(3) success, or DANE-EE(3)/PKIX-EE(1) failure we don't build 483e1051a39Sopenharmony_ci * a chain all, just report trust success or failure, but must also report 484e1051a39Sopenharmony_ci * Suite-B errors if applicable. This is indicated via a NULL chain 485e1051a39Sopenharmony_ci * pointer. All we need to do is check the leaf key algorithm. 486e1051a39Sopenharmony_ci */ 487e1051a39Sopenharmony_ci if (chain == NULL) 488e1051a39Sopenharmony_ci return check_suite_b(pk, -1, &tflags); 489e1051a39Sopenharmony_ci 490e1051a39Sopenharmony_ci if (X509_get_version(x) != X509_VERSION_3) { 491e1051a39Sopenharmony_ci rv = X509_V_ERR_SUITE_B_INVALID_VERSION; 492e1051a39Sopenharmony_ci /* Correct error depth */ 493e1051a39Sopenharmony_ci i = 0; 494e1051a39Sopenharmony_ci goto end; 495e1051a39Sopenharmony_ci } 496e1051a39Sopenharmony_ci 497e1051a39Sopenharmony_ci /* Check EE key only */ 498e1051a39Sopenharmony_ci rv = check_suite_b(pk, -1, &tflags); 499e1051a39Sopenharmony_ci if (rv != X509_V_OK) { 500e1051a39Sopenharmony_ci /* Correct error depth */ 501e1051a39Sopenharmony_ci i = 0; 502e1051a39Sopenharmony_ci goto end; 503e1051a39Sopenharmony_ci } 504e1051a39Sopenharmony_ci for (; i < sk_X509_num(chain); i++) { 505e1051a39Sopenharmony_ci sign_nid = X509_get_signature_nid(x); 506e1051a39Sopenharmony_ci x = sk_X509_value(chain, i); 507e1051a39Sopenharmony_ci if (X509_get_version(x) != X509_VERSION_3) { 508e1051a39Sopenharmony_ci rv = X509_V_ERR_SUITE_B_INVALID_VERSION; 509e1051a39Sopenharmony_ci goto end; 510e1051a39Sopenharmony_ci } 511e1051a39Sopenharmony_ci pk = X509_get0_pubkey(x); 512e1051a39Sopenharmony_ci rv = check_suite_b(pk, sign_nid, &tflags); 513e1051a39Sopenharmony_ci if (rv != X509_V_OK) 514e1051a39Sopenharmony_ci goto end; 515e1051a39Sopenharmony_ci } 516e1051a39Sopenharmony_ci 517e1051a39Sopenharmony_ci /* Final check: root CA signature */ 518e1051a39Sopenharmony_ci rv = check_suite_b(pk, X509_get_signature_nid(x), &tflags); 519e1051a39Sopenharmony_ci end: 520e1051a39Sopenharmony_ci if (rv != X509_V_OK) { 521e1051a39Sopenharmony_ci /* Invalid signature or LOS errors are for previous cert */ 522e1051a39Sopenharmony_ci if ((rv == X509_V_ERR_SUITE_B_INVALID_SIGNATURE_ALGORITHM 523e1051a39Sopenharmony_ci || rv == X509_V_ERR_SUITE_B_LOS_NOT_ALLOWED) && i) 524e1051a39Sopenharmony_ci i--; 525e1051a39Sopenharmony_ci /* 526e1051a39Sopenharmony_ci * If we have LOS error and flags changed then we are signing P-384 527e1051a39Sopenharmony_ci * with P-256. Use more meaningful error. 528e1051a39Sopenharmony_ci */ 529e1051a39Sopenharmony_ci if (rv == X509_V_ERR_SUITE_B_LOS_NOT_ALLOWED && flags != tflags) 530e1051a39Sopenharmony_ci rv = X509_V_ERR_SUITE_B_CANNOT_SIGN_P_384_WITH_P_256; 531e1051a39Sopenharmony_ci if (perror_depth) 532e1051a39Sopenharmony_ci *perror_depth = i; 533e1051a39Sopenharmony_ci } 534e1051a39Sopenharmony_ci return rv; 535e1051a39Sopenharmony_ci} 536e1051a39Sopenharmony_ci 537e1051a39Sopenharmony_ciint X509_CRL_check_suiteb(X509_CRL *crl, EVP_PKEY *pk, unsigned long flags) 538e1051a39Sopenharmony_ci{ 539e1051a39Sopenharmony_ci int sign_nid; 540e1051a39Sopenharmony_ci if (!(flags & X509_V_FLAG_SUITEB_128_LOS)) 541e1051a39Sopenharmony_ci return X509_V_OK; 542e1051a39Sopenharmony_ci sign_nid = OBJ_obj2nid(crl->crl.sig_alg.algorithm); 543e1051a39Sopenharmony_ci return check_suite_b(pk, sign_nid, &flags); 544e1051a39Sopenharmony_ci} 545e1051a39Sopenharmony_ci 546e1051a39Sopenharmony_ci#else 547e1051a39Sopenharmony_ciint X509_chain_check_suiteb(int *perror_depth, X509 *x, STACK_OF(X509) *chain, 548e1051a39Sopenharmony_ci unsigned long flags) 549e1051a39Sopenharmony_ci{ 550e1051a39Sopenharmony_ci return 0; 551e1051a39Sopenharmony_ci} 552e1051a39Sopenharmony_ci 553e1051a39Sopenharmony_ciint X509_CRL_check_suiteb(X509_CRL *crl, EVP_PKEY *pk, unsigned long flags) 554e1051a39Sopenharmony_ci{ 555e1051a39Sopenharmony_ci return 0; 556e1051a39Sopenharmony_ci} 557e1051a39Sopenharmony_ci 558e1051a39Sopenharmony_ci#endif 559e1051a39Sopenharmony_ci 560e1051a39Sopenharmony_ci/* 561e1051a39Sopenharmony_ci * Not strictly speaking an "up_ref" as a STACK doesn't have a reference 562e1051a39Sopenharmony_ci * count but it has the same effect by duping the STACK and upping the ref of 563e1051a39Sopenharmony_ci * each X509 structure. 564e1051a39Sopenharmony_ci */ 565e1051a39Sopenharmony_ciSTACK_OF(X509) *X509_chain_up_ref(STACK_OF(X509) *chain) 566e1051a39Sopenharmony_ci{ 567e1051a39Sopenharmony_ci STACK_OF(X509) *ret = sk_X509_dup(chain); 568e1051a39Sopenharmony_ci int i; 569e1051a39Sopenharmony_ci 570e1051a39Sopenharmony_ci if (ret == NULL) 571e1051a39Sopenharmony_ci return NULL; 572e1051a39Sopenharmony_ci for (i = 0; i < sk_X509_num(ret); i++) { 573e1051a39Sopenharmony_ci X509 *x = sk_X509_value(ret, i); 574e1051a39Sopenharmony_ci 575e1051a39Sopenharmony_ci if (!X509_up_ref(x)) 576e1051a39Sopenharmony_ci goto err; 577e1051a39Sopenharmony_ci } 578e1051a39Sopenharmony_ci return ret; 579e1051a39Sopenharmony_ci 580e1051a39Sopenharmony_ci err: 581e1051a39Sopenharmony_ci while (i-- > 0) 582e1051a39Sopenharmony_ci X509_free(sk_X509_value(ret, i)); 583e1051a39Sopenharmony_ci sk_X509_free(ret); 584e1051a39Sopenharmony_ci return NULL; 585e1051a39Sopenharmony_ci} 586