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