1 | /* |
2 | * Copyright 2019 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 | |
16 | static ESS_CERT_ID *ESS_CERT_ID_new_init(X509 *cert, int issuer_needed); |
17 | static ESS_CERT_ID_V2 *ESS_CERT_ID_V2_new_init(const EVP_MD *hash_alg, |
18 | X509 *cert, int issuer_needed); |
19 | |
20 | ESS_SIGNING_CERT *ESS_SIGNING_CERT_new_init(X509 *signcert, |
21 | STACK_OF(X509) *certs, |
22 | int issuer_needed) |
23 | { |
24 | ESS_CERT_ID *cid = NULL; |
25 | ESS_SIGNING_CERT *sc; |
26 | int i; |
27 | |
28 | if ((sc = ESS_SIGNING_CERT_new()) == NULL) |
29 | goto err; |
30 | if (sc->cert_ids == NULL |
31 | && (sc->cert_ids = sk_ESS_CERT_ID_new_null()) == NULL) |
32 | goto err; |
33 | |
34 | if ((cid = ESS_CERT_ID_new_init(signcert, issuer_needed)) == NULL |
35 | || !sk_ESS_CERT_ID_push(sc->cert_ids, cid)) |
36 | goto err; |
37 | for (i = 0; i < sk_X509_num(certs); ++i) { |
38 | X509 *cert = sk_X509_value(certs, i); |
39 | if ((cid = ESS_CERT_ID_new_init(cert, 1)) == NULL |
40 | || !sk_ESS_CERT_ID_push(sc->cert_ids, cid)) |
41 | goto err; |
42 | } |
43 | |
44 | return sc; |
45 | err: |
46 | ESS_SIGNING_CERT_free(sc); |
47 | ESS_CERT_ID_free(cid); |
48 | ESSerr(ESS_F_ESS_SIGNING_CERT_NEW_INIT, ERR_R_MALLOC_FAILURE); |
49 | return NULL; |
50 | } |
51 | |
52 | static ESS_CERT_ID *ESS_CERT_ID_new_init(X509 *cert, int issuer_needed) |
53 | { |
54 | ESS_CERT_ID *cid = NULL; |
55 | GENERAL_NAME *name = NULL; |
56 | unsigned char cert_sha1[SHA_DIGEST_LENGTH]; |
57 | |
58 | /* Call for side-effect of computing hash and caching extensions */ |
59 | X509_check_purpose(cert, -1, 0); |
60 | if ((cid = ESS_CERT_ID_new()) == NULL) |
61 | goto err; |
62 | X509_digest(cert, EVP_sha1(), cert_sha1, NULL); |
63 | if (!ASN1_OCTET_STRING_set(cid->hash, cert_sha1, SHA_DIGEST_LENGTH)) |
64 | goto err; |
65 | |
66 | /* Setting the issuer/serial if requested. */ |
67 | if (!issuer_needed) |
68 | return cid; |
69 | |
70 | if (cid->issuer_serial == NULL |
71 | && (cid->issuer_serial = ESS_ISSUER_SERIAL_new()) == NULL) |
72 | goto err; |
73 | if ((name = GENERAL_NAME_new()) == NULL) |
74 | goto err; |
75 | name->type = GEN_DIRNAME; |
76 | if ((name->d.dirn = X509_NAME_dup(X509_get_issuer_name(cert))) == NULL) |
77 | goto err; |
78 | if (!sk_GENERAL_NAME_push(cid->issuer_serial->issuer, name)) |
79 | goto err; |
80 | name = NULL; /* Ownership is lost. */ |
81 | ASN1_INTEGER_free(cid->issuer_serial->serial); |
82 | if (!(cid->issuer_serial->serial = |
83 | ASN1_INTEGER_dup(X509_get_serialNumber(cert)))) |
84 | goto err; |
85 | |
86 | return cid; |
87 | err: |
88 | GENERAL_NAME_free(name); |
89 | ESS_CERT_ID_free(cid); |
90 | ESSerr(ESS_F_ESS_CERT_ID_NEW_INIT, ERR_R_MALLOC_FAILURE); |
91 | return NULL; |
92 | } |
93 | |
94 | ESS_SIGNING_CERT_V2 *ESS_SIGNING_CERT_V2_new_init(const EVP_MD *hash_alg, |
95 | X509 *signcert, |
96 | STACK_OF(X509) *certs, |
97 | int issuer_needed) |
98 | { |
99 | ESS_CERT_ID_V2 *cid = NULL; |
100 | ESS_SIGNING_CERT_V2 *sc; |
101 | int i; |
102 | |
103 | if ((sc = ESS_SIGNING_CERT_V2_new()) == NULL) |
104 | goto err; |
105 | if ((cid = ESS_CERT_ID_V2_new_init(hash_alg, signcert, issuer_needed)) == NULL) |
106 | goto err; |
107 | if (!sk_ESS_CERT_ID_V2_push(sc->cert_ids, cid)) |
108 | goto err; |
109 | cid = NULL; |
110 | |
111 | for (i = 0; i < sk_X509_num(certs); ++i) { |
112 | X509 *cert = sk_X509_value(certs, i); |
113 | |
114 | if ((cid = ESS_CERT_ID_V2_new_init(hash_alg, cert, 1)) == NULL) |
115 | goto err; |
116 | if (!sk_ESS_CERT_ID_V2_push(sc->cert_ids, cid)) |
117 | goto err; |
118 | cid = NULL; |
119 | } |
120 | |
121 | return sc; |
122 | err: |
123 | ESS_SIGNING_CERT_V2_free(sc); |
124 | ESS_CERT_ID_V2_free(cid); |
125 | ESSerr(ESS_F_ESS_SIGNING_CERT_V2_NEW_INIT, ERR_R_MALLOC_FAILURE); |
126 | return NULL; |
127 | } |
128 | |
129 | static ESS_CERT_ID_V2 *ESS_CERT_ID_V2_new_init(const EVP_MD *hash_alg, |
130 | X509 *cert, int issuer_needed) |
131 | { |
132 | ESS_CERT_ID_V2 *cid; |
133 | GENERAL_NAME *name = NULL; |
134 | unsigned char hash[EVP_MAX_MD_SIZE]; |
135 | unsigned int hash_len = sizeof(hash); |
136 | X509_ALGOR *alg = NULL; |
137 | |
138 | memset(hash, 0, sizeof(hash)); |
139 | |
140 | if ((cid = ESS_CERT_ID_V2_new()) == NULL) |
141 | goto err; |
142 | |
143 | if (hash_alg != EVP_sha256()) { |
144 | alg = X509_ALGOR_new(); |
145 | if (alg == NULL) |
146 | goto err; |
147 | X509_ALGOR_set_md(alg, hash_alg); |
148 | if (alg->algorithm == NULL) |
149 | goto err; |
150 | cid->hash_alg = alg; |
151 | alg = NULL; |
152 | } else { |
153 | cid->hash_alg = NULL; |
154 | } |
155 | |
156 | if (!X509_digest(cert, hash_alg, hash, &hash_len)) |
157 | goto err; |
158 | |
159 | if (!ASN1_OCTET_STRING_set(cid->hash, hash, hash_len)) |
160 | goto err; |
161 | |
162 | if (!issuer_needed) |
163 | return cid; |
164 | |
165 | if ((cid->issuer_serial = ESS_ISSUER_SERIAL_new()) == NULL) |
166 | goto err; |
167 | if ((name = GENERAL_NAME_new()) == NULL) |
168 | goto err; |
169 | name->type = GEN_DIRNAME; |
170 | if ((name->d.dirn = X509_NAME_dup(X509_get_issuer_name(cert))) == NULL) |
171 | goto err; |
172 | if (!sk_GENERAL_NAME_push(cid->issuer_serial->issuer, name)) |
173 | goto err; |
174 | name = NULL; /* Ownership is lost. */ |
175 | ASN1_INTEGER_free(cid->issuer_serial->serial); |
176 | cid->issuer_serial->serial = ASN1_INTEGER_dup(X509_get_serialNumber(cert)); |
177 | if (cid->issuer_serial->serial == NULL) |
178 | goto err; |
179 | |
180 | return cid; |
181 | err: |
182 | X509_ALGOR_free(alg); |
183 | GENERAL_NAME_free(name); |
184 | ESS_CERT_ID_V2_free(cid); |
185 | ESSerr(ESS_F_ESS_CERT_ID_V2_NEW_INIT, ERR_R_MALLOC_FAILURE); |
186 | return NULL; |
187 | } |
188 | |
189 | ESS_SIGNING_CERT *ESS_SIGNING_CERT_get(PKCS7_SIGNER_INFO *si) |
190 | { |
191 | ASN1_TYPE *attr; |
192 | const unsigned char *p; |
193 | attr = PKCS7_get_signed_attribute(si, NID_id_smime_aa_signingCertificate); |
194 | if (!attr) |
195 | return NULL; |
196 | p = attr->value.sequence->data; |
197 | return d2i_ESS_SIGNING_CERT(NULL, &p, attr->value.sequence->length); |
198 | } |
199 | |
200 | ESS_SIGNING_CERT_V2 *ESS_SIGNING_CERT_V2_get(PKCS7_SIGNER_INFO *si) |
201 | { |
202 | ASN1_TYPE *attr; |
203 | const unsigned char *p; |
204 | |
205 | attr = PKCS7_get_signed_attribute(si, NID_id_smime_aa_signingCertificateV2); |
206 | if (attr == NULL) |
207 | return NULL; |
208 | p = attr->value.sequence->data; |
209 | return d2i_ESS_SIGNING_CERT_V2(NULL, &p, attr->value.sequence->length); |
210 | } |
211 | |
212 | int ESS_SIGNING_CERT_add(PKCS7_SIGNER_INFO *si, ESS_SIGNING_CERT *sc) |
213 | { |
214 | ASN1_STRING *seq = NULL; |
215 | unsigned char *p, *pp = NULL; |
216 | int len; |
217 | |
218 | len = i2d_ESS_SIGNING_CERT(sc, NULL); |
219 | if ((pp = OPENSSL_malloc(len)) == NULL) { |
220 | ESSerr(ESS_F_ESS_SIGNING_CERT_ADD, ERR_R_MALLOC_FAILURE); |
221 | goto err; |
222 | } |
223 | p = pp; |
224 | i2d_ESS_SIGNING_CERT(sc, &p); |
225 | if ((seq = ASN1_STRING_new()) == NULL || !ASN1_STRING_set(seq, pp, len)) { |
226 | ESSerr(ESS_F_ESS_SIGNING_CERT_ADD, ERR_R_MALLOC_FAILURE); |
227 | goto err; |
228 | } |
229 | OPENSSL_free(pp); |
230 | pp = NULL; |
231 | return PKCS7_add_signed_attribute(si, |
232 | NID_id_smime_aa_signingCertificate, |
233 | V_ASN1_SEQUENCE, seq); |
234 | err: |
235 | ASN1_STRING_free(seq); |
236 | OPENSSL_free(pp); |
237 | |
238 | return 0; |
239 | } |
240 | |
241 | int ESS_SIGNING_CERT_V2_add(PKCS7_SIGNER_INFO *si, |
242 | ESS_SIGNING_CERT_V2 *sc) |
243 | { |
244 | ASN1_STRING *seq = NULL; |
245 | unsigned char *p, *pp = NULL; |
246 | int len = i2d_ESS_SIGNING_CERT_V2(sc, NULL); |
247 | |
248 | if ((pp = OPENSSL_malloc(len)) == NULL) { |
249 | ESSerr(ESS_F_ESS_SIGNING_CERT_V2_ADD, ERR_R_MALLOC_FAILURE); |
250 | goto err; |
251 | } |
252 | |
253 | p = pp; |
254 | i2d_ESS_SIGNING_CERT_V2(sc, &p); |
255 | if ((seq = ASN1_STRING_new()) == NULL || !ASN1_STRING_set(seq, pp, len)) { |
256 | ESSerr(ESS_F_ESS_SIGNING_CERT_V2_ADD, ERR_R_MALLOC_FAILURE); |
257 | goto err; |
258 | } |
259 | |
260 | OPENSSL_free(pp); |
261 | pp = NULL; |
262 | return PKCS7_add_signed_attribute(si, |
263 | NID_id_smime_aa_signingCertificateV2, |
264 | V_ASN1_SEQUENCE, seq); |
265 | err: |
266 | ASN1_STRING_free(seq); |
267 | OPENSSL_free(pp); |
268 | return 0; |
269 | } |
270 | |