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
16static ESS_CERT_ID *ESS_CERT_ID_new_init(X509 *cert, int issuer_needed);
17static ESS_CERT_ID_V2 *ESS_CERT_ID_V2_new_init(const EVP_MD *hash_alg,
18 X509 *cert, int issuer_needed);
19
20ESS_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
52static 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
94ESS_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
129static 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
189ESS_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
200ESS_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
212int 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
241int 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