xref: /third_party/openssl/crypto/ess/ess_lib.c (revision e1051a39)
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