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