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