]> git.ipfire.org Git - thirdparty/openssl.git/blob - crypto/ess/ess_lib.c
Add ossl_ x509 symbols
[thirdparty/openssl.git] / crypto / ess / ess_lib.c
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 "crypto/ess.h"
15 #include "crypto/x509.h"
16
17 static ESS_CERT_ID *ESS_CERT_ID_new_init(X509 *cert, int issuer_needed);
18 static ESS_CERT_ID_V2 *ESS_CERT_ID_V2_new_init(const EVP_MD *hash_alg,
19 X509 *cert, int issuer_needed);
20
21 ESS_SIGNING_CERT *ossl_ess_signing_cert_new_init(X509 *signcert,
22 STACK_OF(X509) *certs,
23 int issuer_needed)
24 {
25 ESS_CERT_ID *cid = NULL;
26 ESS_SIGNING_CERT *sc;
27 int i;
28
29 if ((sc = ESS_SIGNING_CERT_new()) == NULL)
30 goto err;
31 if (sc->cert_ids == NULL
32 && (sc->cert_ids = sk_ESS_CERT_ID_new_null()) == NULL)
33 goto err;
34
35 if ((cid = ESS_CERT_ID_new_init(signcert, issuer_needed)) == NULL
36 || !sk_ESS_CERT_ID_push(sc->cert_ids, cid))
37 goto err;
38 for (i = 0; i < sk_X509_num(certs); ++i) {
39 X509 *cert = sk_X509_value(certs, i);
40 if ((cid = ESS_CERT_ID_new_init(cert, 1)) == NULL
41 || !sk_ESS_CERT_ID_push(sc->cert_ids, cid))
42 goto err;
43 }
44
45 return sc;
46 err:
47 ESS_SIGNING_CERT_free(sc);
48 ESS_CERT_ID_free(cid);
49 ERR_raise(ERR_LIB_ESS, ERR_R_MALLOC_FAILURE);
50 return NULL;
51 }
52
53 static ESS_CERT_ID *ESS_CERT_ID_new_init(X509 *cert, int issuer_needed)
54 {
55 ESS_CERT_ID *cid = NULL;
56 GENERAL_NAME *name = NULL;
57 unsigned char cert_sha1[SHA_DIGEST_LENGTH];
58
59 /* Call for side-effect of computing hash and caching extensions */
60 if (!ossl_x509v3_cache_extensions(cert))
61 return NULL;
62
63 if ((cid = ESS_CERT_ID_new()) == NULL)
64 goto err;
65 /* TODO(3.0): fetch sha1 algorithm from providers */
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 (!issuer_needed)
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
99 ESS_SIGNING_CERT_V2 *ossl_ess_signing_cert_v2_new_init(const EVP_MD *hash_alg,
100 X509 *signcert,
101 STACK_OF(X509) *certs,
102 int issuer_needed)
103 {
104 ESS_CERT_ID_V2 *cid = NULL;
105 ESS_SIGNING_CERT_V2 *sc;
106 int i;
107
108 if ((sc = ESS_SIGNING_CERT_V2_new()) == NULL)
109 goto err;
110 if ((cid = ESS_CERT_ID_V2_new_init(hash_alg, signcert, issuer_needed)) == NULL)
111 goto err;
112 if (!sk_ESS_CERT_ID_V2_push(sc->cert_ids, cid))
113 goto err;
114 cid = NULL;
115
116 for (i = 0; i < sk_X509_num(certs); ++i) {
117 X509 *cert = sk_X509_value(certs, i);
118
119 if ((cid = ESS_CERT_ID_V2_new_init(hash_alg, cert, 1)) == NULL)
120 goto err;
121 if (!sk_ESS_CERT_ID_V2_push(sc->cert_ids, cid))
122 goto err;
123 cid = NULL;
124 }
125
126 return sc;
127 err:
128 ESS_SIGNING_CERT_V2_free(sc);
129 ESS_CERT_ID_V2_free(cid);
130 ERR_raise(ERR_LIB_ESS, ERR_R_MALLOC_FAILURE);
131 return NULL;
132 }
133
134 static ESS_CERT_ID_V2 *ESS_CERT_ID_V2_new_init(const EVP_MD *hash_alg,
135 X509 *cert, int issuer_needed)
136 {
137 ESS_CERT_ID_V2 *cid;
138 GENERAL_NAME *name = NULL;
139 unsigned char hash[EVP_MAX_MD_SIZE];
140 unsigned int hash_len = sizeof(hash);
141 X509_ALGOR *alg = NULL;
142
143 memset(hash, 0, sizeof(hash));
144
145 if ((cid = ESS_CERT_ID_V2_new()) == NULL)
146 goto err;
147
148 if (hash_alg != EVP_sha256()) {
149 alg = X509_ALGOR_new();
150 if (alg == NULL)
151 goto err;
152 X509_ALGOR_set_md(alg, hash_alg);
153 if (alg->algorithm == NULL)
154 goto err;
155 cid->hash_alg = alg;
156 alg = NULL;
157 } else {
158 cid->hash_alg = NULL;
159 }
160
161 /* TODO(3.0): fetch sha1 algorithm from providers */
162 if (!X509_digest(cert, hash_alg, hash, &hash_len))
163 goto err;
164
165 if (!ASN1_OCTET_STRING_set(cid->hash, hash, hash_len))
166 goto err;
167
168 if (!issuer_needed)
169 return cid;
170
171 if ((cid->issuer_serial = ESS_ISSUER_SERIAL_new()) == NULL)
172 goto err;
173 if ((name = GENERAL_NAME_new()) == NULL)
174 goto err;
175 name->type = GEN_DIRNAME;
176 if ((name->d.dirn = X509_NAME_dup(X509_get_issuer_name(cert))) == NULL)
177 goto err;
178 if (!sk_GENERAL_NAME_push(cid->issuer_serial->issuer, name))
179 goto err;
180 name = NULL; /* Ownership is lost. */
181 ASN1_INTEGER_free(cid->issuer_serial->serial);
182 cid->issuer_serial->serial = ASN1_INTEGER_dup(X509_get0_serialNumber(cert));
183 if (cid->issuer_serial->serial == NULL)
184 goto err;
185
186 return cid;
187 err:
188 X509_ALGOR_free(alg);
189 GENERAL_NAME_free(name);
190 ESS_CERT_ID_V2_free(cid);
191 ERR_raise(ERR_LIB_ESS, ERR_R_MALLOC_FAILURE);
192 return NULL;
193 }
194
195 ESS_SIGNING_CERT *ossl_ess_get_signing_cert(const PKCS7_SIGNER_INFO *si)
196 {
197 ASN1_TYPE *attr;
198 const unsigned char *p;
199
200 attr = PKCS7_get_signed_attribute(si, NID_id_smime_aa_signingCertificate);
201 if (attr == NULL)
202 return NULL;
203 p = attr->value.sequence->data;
204 return d2i_ESS_SIGNING_CERT(NULL, &p, attr->value.sequence->length);
205 }
206
207 ESS_SIGNING_CERT_V2 *ossl_ess_get_signing_cert_v2(const PKCS7_SIGNER_INFO *si)
208 {
209 ASN1_TYPE *attr;
210 const unsigned char *p;
211
212 attr = PKCS7_get_signed_attribute(si, NID_id_smime_aa_signingCertificateV2);
213 if (attr == NULL)
214 return NULL;
215 p = attr->value.sequence->data;
216 return d2i_ESS_SIGNING_CERT_V2(NULL, &p, attr->value.sequence->length);
217 }
218
219 int ossl_ess_signing_cert_add(PKCS7_SIGNER_INFO *si, ESS_SIGNING_CERT *sc)
220 {
221 ASN1_STRING *seq = NULL;
222 unsigned char *p, *pp = NULL;
223 int len;
224
225 len = i2d_ESS_SIGNING_CERT(sc, NULL);
226 if ((pp = OPENSSL_malloc(len)) == NULL) {
227 ERR_raise(ERR_LIB_ESS, ERR_R_MALLOC_FAILURE);
228 goto err;
229 }
230 p = pp;
231 i2d_ESS_SIGNING_CERT(sc, &p);
232 if ((seq = ASN1_STRING_new()) == NULL || !ASN1_STRING_set(seq, pp, len)) {
233 ERR_raise(ERR_LIB_ESS, ERR_R_MALLOC_FAILURE);
234 goto err;
235 }
236 OPENSSL_free(pp);
237 pp = NULL;
238 return PKCS7_add_signed_attribute(si,
239 NID_id_smime_aa_signingCertificate,
240 V_ASN1_SEQUENCE, seq);
241 err:
242 ASN1_STRING_free(seq);
243 OPENSSL_free(pp);
244
245 return 0;
246 }
247
248 int ossl_ess_signing_cert_v2_add(PKCS7_SIGNER_INFO *si, ESS_SIGNING_CERT_V2 *sc)
249 {
250 ASN1_STRING *seq = NULL;
251 unsigned char *p, *pp = NULL;
252 int len = i2d_ESS_SIGNING_CERT_V2(sc, NULL);
253
254 if ((pp = OPENSSL_malloc(len)) == NULL) {
255 ERR_raise(ERR_LIB_ESS, ERR_R_MALLOC_FAILURE);
256 goto err;
257 }
258
259 p = pp;
260 i2d_ESS_SIGNING_CERT_V2(sc, &p);
261 if ((seq = ASN1_STRING_new()) == NULL || !ASN1_STRING_set(seq, pp, len)) {
262 ERR_raise(ERR_LIB_ESS, ERR_R_MALLOC_FAILURE);
263 goto err;
264 }
265
266 OPENSSL_free(pp);
267 pp = NULL;
268 return PKCS7_add_signed_attribute(si,
269 NID_id_smime_aa_signingCertificateV2,
270 V_ASN1_SEQUENCE, seq);
271 err:
272 ASN1_STRING_free(seq);
273 OPENSSL_free(pp);
274 return 0;
275 }
276
277 static int ess_issuer_serial_cmp(const ESS_ISSUER_SERIAL *is, const X509 *cert)
278 {
279 GENERAL_NAME *issuer;
280
281 if (is == NULL || cert == NULL || sk_GENERAL_NAME_num(is->issuer) != 1)
282 return -1;
283
284 issuer = sk_GENERAL_NAME_value(is->issuer, 0);
285 if (issuer->type != GEN_DIRNAME
286 || X509_NAME_cmp(issuer->d.dirn, X509_get_issuer_name(cert)) != 0)
287 return -1;
288
289 return ASN1_INTEGER_cmp(is->serial, X509_get0_serialNumber(cert));
290 }
291
292 /*
293 * Find cert referenced by |cid| (if not NULL, else |cidv2|) in |certs|.
294 * If the cid{,v2} index is 0, the cert must be in the first in |certs| list.
295 * Return 0 on not found, -1 on error, else 1 + the position in |certs|.
296 */
297 static int find(const ESS_CERT_ID *cid, const ESS_CERT_ID_V2 *cid_v2,
298 int index, const STACK_OF(X509) *certs)
299 {
300 const X509 *cert;
301 const EVP_MD *md;
302 unsigned char cert_digest[EVP_MAX_MD_SIZE];
303 unsigned int len, cid_hash_len;
304 const ESS_ISSUER_SERIAL *is;
305 int i;
306
307 if (cid == NULL && cid_v2 == NULL) {
308 ERR_raise(ERR_LIB_ESS, ERR_R_PASSED_INVALID_ARGUMENT);
309 return -1;
310 }
311
312 /* Look for cert with cid in the certs. */
313 for (i = 0; i < sk_X509_num(certs); ++i) {
314 cert = sk_X509_value(certs, i);
315
316 if (cid != NULL)
317 md = EVP_sha1();
318 else
319 md = cid_v2->hash_alg == NULL ? EVP_sha256() :
320 EVP_get_digestbyobj(cid_v2->hash_alg->algorithm);
321 if (md == NULL) {
322 ERR_raise(ERR_LIB_ESS, ESS_R_ESS_DIGEST_ALG_UNKNOWN);
323 return -1;
324 }
325
326 cid_hash_len = cid != NULL ? cid->hash->length : cid_v2->hash->length;
327 if (!X509_digest(cert, md, cert_digest, &len)
328 || cid_hash_len != len) {
329 ERR_raise(ERR_LIB_ESS, ESS_R_ESS_CERT_DIGEST_ERROR);
330 return -1;
331 }
332
333 if (memcmp(cid != NULL ? cid->hash->data : cid_v2->hash->data,
334 cert_digest, len) == 0) {
335 is = cid != NULL ? cid->issuer_serial : cid_v2->issuer_serial;
336 /* Well, it's not really required to match the serial numbers. */
337 if (is == NULL || ess_issuer_serial_cmp(is, cert) == 0) {
338 if ((i == 0) == (index == 0))
339 return i + 1;
340 ERR_raise(ERR_LIB_ESS, ESS_R_ESS_CERT_ID_WRONG_ORDER);
341 return -1;
342 }
343 }
344 }
345
346 ERR_raise(ERR_LIB_ESS, ESS_R_ESS_CERT_ID_NOT_FOUND);
347 return 0;
348 }
349
350 /*
351 * If ESSCertID and/or ESSCertIDv2 exist, which must be non-empty if given,
352 * check if their first ID entry matches the signer cert first in chain
353 * and each further ID entry matches any further cert in the chain.
354 */
355 int ossl_ess_check_signing_certs(const ESS_SIGNING_CERT *ss,
356 const ESS_SIGNING_CERT_V2 *ssv2,
357 const STACK_OF(X509) *chain,
358 int require_signing_cert)
359 {
360 int n_v1 = ss == NULL ? -1 : sk_ESS_CERT_ID_num(ss->cert_ids);
361 int n_v2 = ssv2 == NULL ? -1 : sk_ESS_CERT_ID_V2_num(ssv2->cert_ids);
362 int i;
363
364 if (require_signing_cert && ss == NULL && ssv2 == NULL) {
365 ERR_raise(ERR_LIB_CMS, ESS_R_MISSING_SIGNING_CERTIFICATE_ATTRIBUTE);
366 return 0;
367 }
368 if (n_v1 == 0 || n_v2 == 0) {
369 ERR_raise(ERR_LIB_ESS, ESS_R_EMPTY_ESS_CERT_ID_LIST);
370 return 0;
371 }
372 /* If both ss and ssv2 exist, as required evaluate them independently. */
373 for (i = 0; i < n_v1; i++)
374 if (find(sk_ESS_CERT_ID_value(ss->cert_ids, i), NULL, i, chain) <= 0)
375 return 0;
376 for (i = 0; i < n_v2; i++)
377 if (find(NULL, sk_ESS_CERT_ID_V2_value(ssv2->cert_ids, i), i, chain) <= 0)
378 return 0;
379 return 1;
380 }