]> git.ipfire.org Git - thirdparty/openssl.git/blame - crypto/ess/ess_lib.c
Update copyright year
[thirdparty/openssl.git] / crypto / ess / ess_lib.c
CommitLineData
e85d19c6 1/*
8020d79b 2 * Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
e85d19c6
AI
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>
25f2138b 14#include "crypto/ess.h"
6725682d 15#include "crypto/x509.h"
e85d19c6
AI
16
17static ESS_CERT_ID *ESS_CERT_ID_new_init(X509 *cert, int issuer_needed);
18static ESS_CERT_ID_V2 *ESS_CERT_ID_V2_new_init(const EVP_MD *hash_alg,
19 X509 *cert, int issuer_needed);
20
53155f1c
SL
21ESS_SIGNING_CERT *ossl_ess_signing_cert_new_init(X509 *signcert,
22 STACK_OF(X509) *certs,
23 int issuer_needed)
e85d19c6
AI
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);
9311d0c4 49 ERR_raise(ERR_LIB_ESS, ERR_R_MALLOC_FAILURE);
e85d19c6
AI
50 return NULL;
51}
52
53static 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 */
6725682d 60 if (!x509v3_cache_extensions(cert))
9e3c510b
F
61 return NULL;
62
e85d19c6
AI
63 if ((cid = ESS_CERT_ID_new()) == NULL)
64 goto err;
9e3c510b 65 /* TODO(3.0): fetch sha1 algorithm from providers */
7e06a675
BE
66 if (!X509_digest(cert, EVP_sha1(), cert_sha1, NULL))
67 goto err;
e85d19c6
AI
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);
9e3c510b 87 if ((cid->issuer_serial->serial =
1337a3a9 88 ASN1_INTEGER_dup(X509_get0_serialNumber(cert))) == NULL)
e85d19c6
AI
89 goto err;
90
91 return cid;
92 err:
93 GENERAL_NAME_free(name);
94 ESS_CERT_ID_free(cid);
9311d0c4 95 ERR_raise(ERR_LIB_ESS, ERR_R_MALLOC_FAILURE);
e85d19c6
AI
96 return NULL;
97}
98
53155f1c
SL
99ESS_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)
e85d19c6
AI
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);
9311d0c4 130 ERR_raise(ERR_LIB_ESS, ERR_R_MALLOC_FAILURE);
e85d19c6
AI
131 return NULL;
132}
133
134static 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
9e3c510b 161 /* TODO(3.0): fetch sha1 algorithm from providers */
e85d19c6
AI
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);
1337a3a9 182 cid->issuer_serial->serial = ASN1_INTEGER_dup(X509_get0_serialNumber(cert));
e85d19c6
AI
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);
9311d0c4 191 ERR_raise(ERR_LIB_ESS, ERR_R_MALLOC_FAILURE);
e85d19c6
AI
192 return NULL;
193}
194
53155f1c 195ESS_SIGNING_CERT *ossl_ess_signing_cert_get(PKCS7_SIGNER_INFO *si)
e85d19c6
AI
196{
197 ASN1_TYPE *attr;
198 const unsigned char *p;
9e3c510b 199
e85d19c6 200 attr = PKCS7_get_signed_attribute(si, NID_id_smime_aa_signingCertificate);
9e3c510b 201 if (attr == NULL)
e85d19c6
AI
202 return NULL;
203 p = attr->value.sequence->data;
204 return d2i_ESS_SIGNING_CERT(NULL, &p, attr->value.sequence->length);
205}
206
53155f1c 207ESS_SIGNING_CERT_V2 *ossl_ess_signing_cert_v2_get(PKCS7_SIGNER_INFO *si)
e85d19c6
AI
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
53155f1c 219int ossl_ess_signing_cert_add(PKCS7_SIGNER_INFO *si, ESS_SIGNING_CERT *sc)
e85d19c6
AI
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) {
9311d0c4 227 ERR_raise(ERR_LIB_ESS, ERR_R_MALLOC_FAILURE);
e85d19c6
AI
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)) {
9311d0c4 233 ERR_raise(ERR_LIB_ESS, ERR_R_MALLOC_FAILURE);
e85d19c6
AI
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
53155f1c 248int ossl_ess_signing_cert_v2_add(PKCS7_SIGNER_INFO *si, ESS_SIGNING_CERT_V2 *sc)
e85d19c6
AI
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) {
9311d0c4 255 ERR_raise(ERR_LIB_ESS, ERR_R_MALLOC_FAILURE);
e85d19c6
AI
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)) {
9311d0c4 262 ERR_raise(ERR_LIB_ESS, ERR_R_MALLOC_FAILURE);
e85d19c6
AI
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}
9e3c510b
F
276
277static 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/* Returns < 0 if certificate is not found, certificate index otherwise. */
53155f1c 293int ossl_ess_find_cert(const STACK_OF(ESS_CERT_ID) *cert_ids, X509 *cert)
9e3c510b
F
294{
295 int i;
296 unsigned char cert_sha1[SHA_DIGEST_LENGTH];
297
298 if (cert_ids == NULL || cert == NULL)
299 return -1;
300
301 /* Recompute SHA1 hash of certificate if necessary (side effect). */
6725682d 302 if (!x509v3_cache_extensions(cert))
9e3c510b
F
303 return -1;
304
305 /* TODO(3.0): fetch sha1 algorithm from providers */
306 if (!X509_digest(cert, EVP_sha1(), cert_sha1, NULL))
307 return -1;
308
309 /* Look for cert in the cert_ids vector. */
310 for (i = 0; i < sk_ESS_CERT_ID_num(cert_ids); ++i) {
311 const ESS_CERT_ID *cid = sk_ESS_CERT_ID_value(cert_ids, i);
312
313 if (cid->hash->length == SHA_DIGEST_LENGTH
314 && memcmp(cid->hash->data, cert_sha1, SHA_DIGEST_LENGTH) == 0) {
315 const ESS_ISSUER_SERIAL *is = cid->issuer_serial;
316
317 if (is == NULL || ess_issuer_serial_cmp(is, cert) == 0)
318 return i;
319 }
320 }
321
322 return -1;
323}
324
325/* Returns < 0 if certificate is not found, certificate index otherwise. */
53155f1c
SL
326int ossl_ess_find_cert_v2(const STACK_OF(ESS_CERT_ID_V2) *cert_ids,
327 const X509 *cert)
9e3c510b
F
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
5999d20e
SL
338 if (cid == NULL)
339 return -1;
340 if (cid->hash_alg != NULL)
9e3c510b
F
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}