]> git.ipfire.org Git - thirdparty/openssl.git/blob - crypto/ess/ess_lib.c
325acddb95a24493a593802012e3731f94de2ab0
[thirdparty/openssl.git] / crypto / ess / ess_lib.c
1 /*
2 * Copyright 2019-2020 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 *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 ESSerr(ESS_F_ESS_SIGNING_CERT_NEW_INIT, 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 (!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 ESSerr(ESS_F_ESS_CERT_ID_NEW_INIT, ERR_R_MALLOC_FAILURE);
96 return NULL;
97 }
98
99 ESS_SIGNING_CERT_V2 *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 ESSerr(ESS_F_ESS_SIGNING_CERT_V2_NEW_INIT, 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 ESSerr(ESS_F_ESS_CERT_ID_V2_NEW_INIT, ERR_R_MALLOC_FAILURE);
192 return NULL;
193 }
194
195 ESS_SIGNING_CERT *ESS_SIGNING_CERT_get(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 *ESS_SIGNING_CERT_V2_get(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 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 ESSerr(ESS_F_ESS_SIGNING_CERT_ADD, 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 ESSerr(ESS_F_ESS_SIGNING_CERT_ADD, 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 ESS_SIGNING_CERT_V2_add(PKCS7_SIGNER_INFO *si,
249 ESS_SIGNING_CERT_V2 *sc)
250 {
251 ASN1_STRING *seq = NULL;
252 unsigned char *p, *pp = NULL;
253 int len = i2d_ESS_SIGNING_CERT_V2(sc, NULL);
254
255 if ((pp = OPENSSL_malloc(len)) == NULL) {
256 ESSerr(ESS_F_ESS_SIGNING_CERT_V2_ADD, ERR_R_MALLOC_FAILURE);
257 goto err;
258 }
259
260 p = pp;
261 i2d_ESS_SIGNING_CERT_V2(sc, &p);
262 if ((seq = ASN1_STRING_new()) == NULL || !ASN1_STRING_set(seq, pp, len)) {
263 ESSerr(ESS_F_ESS_SIGNING_CERT_V2_ADD, ERR_R_MALLOC_FAILURE);
264 goto err;
265 }
266
267 OPENSSL_free(pp);
268 pp = NULL;
269 return PKCS7_add_signed_attribute(si,
270 NID_id_smime_aa_signingCertificateV2,
271 V_ASN1_SEQUENCE, seq);
272 err:
273 ASN1_STRING_free(seq);
274 OPENSSL_free(pp);
275 return 0;
276 }
277
278 static int ess_issuer_serial_cmp(const ESS_ISSUER_SERIAL *is, const X509 *cert)
279 {
280 GENERAL_NAME *issuer;
281
282 if (is == NULL || cert == NULL || sk_GENERAL_NAME_num(is->issuer) != 1)
283 return -1;
284
285 issuer = sk_GENERAL_NAME_value(is->issuer, 0);
286 if (issuer->type != GEN_DIRNAME
287 || X509_NAME_cmp(issuer->d.dirn, X509_get_issuer_name(cert)) != 0)
288 return -1;
289
290 return ASN1_INTEGER_cmp(is->serial, X509_get0_serialNumber(cert));
291 }
292
293 /* Returns < 0 if certificate is not found, certificate index otherwise. */
294 int ess_find_cert(const STACK_OF(ESS_CERT_ID) *cert_ids, X509 *cert)
295 {
296 int i;
297 unsigned char cert_sha1[SHA_DIGEST_LENGTH];
298
299 if (cert_ids == NULL || cert == NULL)
300 return -1;
301
302 /* Recompute SHA1 hash of certificate if necessary (side effect). */
303 if (!x509v3_cache_extensions(cert))
304 return -1;
305
306 /* TODO(3.0): fetch sha1 algorithm from providers */
307 if (!X509_digest(cert, EVP_sha1(), cert_sha1, NULL))
308 return -1;
309
310 /* Look for cert in the cert_ids vector. */
311 for (i = 0; i < sk_ESS_CERT_ID_num(cert_ids); ++i) {
312 const ESS_CERT_ID *cid = sk_ESS_CERT_ID_value(cert_ids, i);
313
314 if (cid->hash->length == SHA_DIGEST_LENGTH
315 && memcmp(cid->hash->data, cert_sha1, SHA_DIGEST_LENGTH) == 0) {
316 const ESS_ISSUER_SERIAL *is = cid->issuer_serial;
317
318 if (is == NULL || ess_issuer_serial_cmp(is, cert) == 0)
319 return i;
320 }
321 }
322
323 return -1;
324 }
325
326 /* Returns < 0 if certificate is not found, certificate index otherwise. */
327 int ess_find_cert_v2(const STACK_OF(ESS_CERT_ID_V2) *cert_ids, const X509 *cert)
328 {
329 int i;
330 unsigned char cert_digest[EVP_MAX_MD_SIZE];
331 unsigned int len;
332
333 /* Look for cert in the cert_ids vector. */
334 for (i = 0; i < sk_ESS_CERT_ID_V2_num(cert_ids); ++i) {
335 const ESS_CERT_ID_V2 *cid = sk_ESS_CERT_ID_V2_value(cert_ids, i);
336 const EVP_MD *md;
337
338 if (cid == NULL)
339 return -1;
340 if (cid->hash_alg != NULL)
341 md = EVP_get_digestbyobj(cid->hash_alg->algorithm);
342 else
343 md = EVP_sha256();
344
345 /* TODO(3.0): fetch sha1 algorithm from providers */
346 if (!X509_digest(cert, md, cert_digest, &len))
347 return -1;
348
349 if (cid->hash->length != (int)len)
350 return -1;
351
352 if (memcmp(cid->hash->data, cert_digest, cid->hash->length) == 0) {
353 const ESS_ISSUER_SERIAL *is = cid->issuer_serial;
354
355 if (is == NULL || ess_issuer_serial_cmp(is, cert) == 0)
356 return i;
357 }
358 }
359
360 return -1;
361 }