]>
Commit | Line | Data |
---|---|---|
0f113f3e | 1 | /* |
33388b44 | 2 | * Copyright 2008-2020 The OpenSSL Project Authors. All Rights Reserved. |
8931b30d | 3 | * |
08ddd302 | 4 | * Licensed under the Apache License 2.0 (the "License"). You may not use |
b1322259 RS |
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 | |
8931b30d DSH |
8 | */ |
9 | ||
10 | #include <openssl/asn1t.h> | |
17c2764d | 11 | #include <openssl/x509v3.h> |
8931b30d DSH |
12 | #include <openssl/err.h> |
13 | #include <openssl/pem.h> | |
14 | #include <openssl/bio.h> | |
15 | #include <openssl/asn1.h> | |
e52a3c3d | 16 | #include <openssl/cms.h> |
c1669f41 SL |
17 | #include <openssl/cms.h> |
18 | #include "crypto/x509.h" | |
706457b7 | 19 | #include "cms_local.h" |
8931b30d | 20 | |
c1669f41 SL |
21 | static STACK_OF(CMS_CertificateChoices) |
22 | **cms_get0_certificate_choices(CMS_ContentInfo *cms); | |
23 | ||
8931b30d DSH |
24 | IMPLEMENT_ASN1_PRINT_FUNCTION(CMS_ContentInfo) |
25 | ||
c1669f41 SL |
26 | CMS_ContentInfo *d2i_CMS_ContentInfo(CMS_ContentInfo **a, |
27 | const unsigned char **in, long len) | |
28 | { | |
29 | CMS_ContentInfo *ci; | |
30 | ||
31 | ci = (CMS_ContentInfo *)ASN1_item_d2i((ASN1_VALUE **)a, in, len, | |
32 | (CMS_ContentInfo_it())); | |
33 | if (ci != NULL && a != NULL) | |
34 | cms_resolve_libctx(ci); | |
35 | return ci; | |
36 | } | |
37 | ||
38 | int i2d_CMS_ContentInfo(const CMS_ContentInfo *a, unsigned char **out) | |
39 | { | |
40 | return ASN1_item_i2d((const ASN1_VALUE *)a, out, (CMS_ContentInfo_it())); | |
41 | } | |
42 | ||
b4250010 | 43 | CMS_ContentInfo *CMS_ContentInfo_new_ex(OSSL_LIB_CTX *libctx, const char *propq) |
c1669f41 SL |
44 | { |
45 | CMS_ContentInfo *ci; | |
46 | ||
47 | ci = (CMS_ContentInfo *)ASN1_item_new(ASN1_ITEM_rptr(CMS_ContentInfo)); | |
48 | if (ci != NULL) { | |
49 | ci->ctx.libctx = libctx; | |
50 | ci->ctx.propq = NULL; | |
51 | if (propq != NULL) { | |
52 | ci->ctx.propq = OPENSSL_strdup(propq); | |
53 | if (ci->ctx.propq == NULL) { | |
54 | CMS_ContentInfo_free(ci); | |
55 | ci = NULL; | |
56 | ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); | |
57 | } | |
58 | } | |
59 | } | |
60 | return ci; | |
61 | } | |
62 | ||
63 | CMS_ContentInfo *CMS_ContentInfo_new(void) | |
64 | { | |
d8652be0 | 65 | return CMS_ContentInfo_new_ex(NULL, NULL); |
c1669f41 SL |
66 | } |
67 | ||
68 | void CMS_ContentInfo_free(CMS_ContentInfo *cms) | |
69 | { | |
70 | if (cms != NULL) { | |
71 | OPENSSL_free(cms->ctx.propq); | |
72 | ASN1_item_free((ASN1_VALUE *)cms, ASN1_ITEM_rptr(CMS_ContentInfo)); | |
73 | } | |
74 | } | |
75 | ||
76 | const CMS_CTX *cms_get0_cmsctx(const CMS_ContentInfo *cms) | |
77 | { | |
78 | return cms != NULL ? &cms->ctx : NULL; | |
79 | } | |
80 | ||
b4250010 | 81 | OSSL_LIB_CTX *cms_ctx_get0_libctx(const CMS_CTX *ctx) |
c1669f41 SL |
82 | { |
83 | return ctx->libctx; | |
84 | } | |
85 | ||
86 | const char *cms_ctx_get0_propq(const CMS_CTX *ctx) | |
87 | { | |
88 | return ctx->propq; | |
89 | } | |
90 | ||
91 | void cms_resolve_libctx(CMS_ContentInfo *ci) | |
92 | { | |
93 | int i; | |
94 | CMS_CertificateChoices *cch; | |
95 | STACK_OF(CMS_CertificateChoices) **pcerts; | |
96 | const CMS_CTX *ctx; | |
97 | ||
98 | if (ci == NULL) | |
99 | return; | |
100 | ||
101 | ctx = cms_get0_cmsctx(ci); | |
102 | cms_SignerInfos_set_cmsctx(ci); | |
103 | cms_RecipientInfos_set_cmsctx(ci); | |
104 | ||
105 | pcerts = cms_get0_certificate_choices(ci); | |
106 | if (pcerts != NULL) { | |
107 | for (i = 0; i < sk_CMS_CertificateChoices_num(*pcerts); i++) { | |
108 | cch = sk_CMS_CertificateChoices_value(*pcerts, i); | |
109 | if (cch->type == CMS_CERTCHOICE_CERT) | |
110 | x509_set0_libctx(cch->d.certificate, ctx->libctx, ctx->propq); | |
111 | } | |
112 | } | |
113 | } | |
114 | ||
dc423f89 | 115 | const ASN1_OBJECT *CMS_get0_type(const CMS_ContentInfo *cms) |
0f113f3e MC |
116 | { |
117 | return cms->contentType; | |
118 | } | |
8931b30d | 119 | |
b4250010 | 120 | CMS_ContentInfo *cms_Data_create(OSSL_LIB_CTX *libctx, const char *propq) |
0f113f3e | 121 | { |
d8652be0 | 122 | CMS_ContentInfo *cms = CMS_ContentInfo_new_ex(libctx, propq); |
c1669f41 | 123 | |
90945fa3 | 124 | if (cms != NULL) { |
0f113f3e MC |
125 | cms->contentType = OBJ_nid2obj(NID_pkcs7_data); |
126 | /* Never detached */ | |
127 | CMS_set_detached(cms, 0); | |
128 | } | |
129 | return cms; | |
130 | } | |
8931b30d DSH |
131 | |
132 | BIO *cms_content_bio(CMS_ContentInfo *cms) | |
0f113f3e MC |
133 | { |
134 | ASN1_OCTET_STRING **pos = CMS_get0_content(cms); | |
12a765a5 RS |
135 | |
136 | if (pos == NULL) | |
0f113f3e MC |
137 | return NULL; |
138 | /* If content detached data goes nowhere: create NULL BIO */ | |
12a765a5 | 139 | if (*pos == NULL) |
0f113f3e MC |
140 | return BIO_new(BIO_s_null()); |
141 | /* | |
142 | * If content not detached and created return memory BIO | |
143 | */ | |
12a765a5 | 144 | if (*pos == NULL || ((*pos)->flags == ASN1_STRING_FLAG_CONT)) |
0f113f3e MC |
145 | return BIO_new(BIO_s_mem()); |
146 | /* Else content was read in: return read only BIO for it */ | |
147 | return BIO_new_mem_buf((*pos)->data, (*pos)->length); | |
148 | } | |
8931b30d DSH |
149 | |
150 | BIO *CMS_dataInit(CMS_ContentInfo *cms, BIO *icont) | |
0f113f3e MC |
151 | { |
152 | BIO *cmsbio, *cont; | |
153 | if (icont) | |
154 | cont = icont; | |
155 | else | |
156 | cont = cms_content_bio(cms); | |
157 | if (!cont) { | |
9311d0c4 | 158 | ERR_raise(ERR_LIB_CMS, CMS_R_NO_CONTENT); |
0f113f3e MC |
159 | return NULL; |
160 | } | |
161 | switch (OBJ_obj2nid(cms->contentType)) { | |
162 | ||
163 | case NID_pkcs7_data: | |
164 | return cont; | |
165 | ||
166 | case NID_pkcs7_signed: | |
167 | cmsbio = cms_SignedData_init_bio(cms); | |
168 | break; | |
169 | ||
170 | case NID_pkcs7_digest: | |
171 | cmsbio = cms_DigestedData_init_bio(cms); | |
172 | break; | |
8931b30d | 173 | #ifdef ZLIB |
0f113f3e MC |
174 | case NID_id_smime_ct_compressedData: |
175 | cmsbio = cms_CompressedData_init_bio(cms); | |
176 | break; | |
8931b30d DSH |
177 | #endif |
178 | ||
0f113f3e MC |
179 | case NID_pkcs7_encrypted: |
180 | cmsbio = cms_EncryptedData_init_bio(cms); | |
181 | break; | |
b820455c | 182 | |
0f113f3e MC |
183 | case NID_pkcs7_enveloped: |
184 | cmsbio = cms_EnvelopedData_init_bio(cms); | |
185 | break; | |
4f1aa191 | 186 | |
924663c3 JZ |
187 | case NID_id_smime_ct_authEnvelopedData: |
188 | cmsbio = cms_AuthEnvelopedData_init_bio(cms); | |
189 | break; | |
190 | ||
0f113f3e | 191 | default: |
9311d0c4 | 192 | ERR_raise(ERR_LIB_CMS, CMS_R_UNSUPPORTED_TYPE); |
19b4e6f8 | 193 | goto err; |
0f113f3e | 194 | } |
8931b30d | 195 | |
0f113f3e MC |
196 | if (cmsbio) |
197 | return BIO_push(cmsbio, cont); | |
19b4e6f8 | 198 | err: |
0f113f3e MC |
199 | if (!icont) |
200 | BIO_free(cont); | |
201 | return NULL; | |
8931b30d | 202 | |
0f113f3e | 203 | } |
b820455c | 204 | |
9fdcc21f | 205 | /* unfortunately cannot constify SMIME_write_ASN1() due to this function */ |
8931b30d | 206 | int CMS_dataFinal(CMS_ContentInfo *cms, BIO *cmsbio) |
0f113f3e MC |
207 | { |
208 | ASN1_OCTET_STRING **pos = CMS_get0_content(cms); | |
12a765a5 RS |
209 | |
210 | if (pos == NULL) | |
0f113f3e | 211 | return 0; |
0d4fb843 | 212 | /* If embedded content find memory BIO and set content */ |
0f113f3e MC |
213 | if (*pos && ((*pos)->flags & ASN1_STRING_FLAG_CONT)) { |
214 | BIO *mbio; | |
215 | unsigned char *cont; | |
216 | long contlen; | |
217 | mbio = BIO_find_type(cmsbio, BIO_TYPE_MEM); | |
218 | if (!mbio) { | |
9311d0c4 | 219 | ERR_raise(ERR_LIB_CMS, CMS_R_CONTENT_NOT_FOUND); |
0f113f3e MC |
220 | return 0; |
221 | } | |
222 | contlen = BIO_get_mem_data(mbio, &cont); | |
223 | /* Set bio as read only so its content can't be clobbered */ | |
224 | BIO_set_flags(mbio, BIO_FLAGS_MEM_RDONLY); | |
225 | BIO_set_mem_eof_return(mbio, 0); | |
226 | ASN1_STRING_set0(*pos, cont, contlen); | |
227 | (*pos)->flags &= ~ASN1_STRING_FLAG_CONT; | |
228 | } | |
229 | ||
230 | switch (OBJ_obj2nid(cms->contentType)) { | |
231 | ||
232 | case NID_pkcs7_data: | |
0f113f3e MC |
233 | case NID_pkcs7_encrypted: |
234 | case NID_id_smime_ct_compressedData: | |
235 | /* Nothing to do */ | |
236 | return 1; | |
237 | ||
71434aed DB |
238 | case NID_pkcs7_enveloped: |
239 | return cms_EnvelopedData_final(cms, cmsbio); | |
240 | ||
924663c3 JZ |
241 | case NID_id_smime_ct_authEnvelopedData: |
242 | return cms_AuthEnvelopedData_final(cms, cmsbio); | |
243 | ||
0f113f3e MC |
244 | case NID_pkcs7_signed: |
245 | return cms_SignedData_final(cms, cmsbio); | |
246 | ||
247 | case NID_pkcs7_digest: | |
248 | return cms_DigestedData_do_final(cms, cmsbio, 0); | |
249 | ||
250 | default: | |
9311d0c4 | 251 | ERR_raise(ERR_LIB_CMS, CMS_R_UNSUPPORTED_TYPE); |
0f113f3e MC |
252 | return 0; |
253 | } | |
254 | } | |
255 | ||
256 | /* | |
257 | * Return an OCTET STRING pointer to content. This allows it to be accessed | |
258 | * or set later. | |
8931b30d DSH |
259 | */ |
260 | ||
261 | ASN1_OCTET_STRING **CMS_get0_content(CMS_ContentInfo *cms) | |
0f113f3e MC |
262 | { |
263 | switch (OBJ_obj2nid(cms->contentType)) { | |
8931b30d | 264 | |
0f113f3e MC |
265 | case NID_pkcs7_data: |
266 | return &cms->d.data; | |
8931b30d | 267 | |
0f113f3e MC |
268 | case NID_pkcs7_signed: |
269 | return &cms->d.signedData->encapContentInfo->eContent; | |
8931b30d | 270 | |
0f113f3e MC |
271 | case NID_pkcs7_enveloped: |
272 | return &cms->d.envelopedData->encryptedContentInfo->encryptedContent; | |
8931b30d | 273 | |
0f113f3e MC |
274 | case NID_pkcs7_digest: |
275 | return &cms->d.digestedData->encapContentInfo->eContent; | |
8931b30d | 276 | |
0f113f3e MC |
277 | case NID_pkcs7_encrypted: |
278 | return &cms->d.encryptedData->encryptedContentInfo->encryptedContent; | |
8931b30d | 279 | |
924663c3 JZ |
280 | case NID_id_smime_ct_authEnvelopedData: |
281 | return &cms->d.authEnvelopedData->authEncryptedContentInfo | |
282 | ->encryptedContent; | |
283 | ||
0f113f3e MC |
284 | case NID_id_smime_ct_authData: |
285 | return &cms->d.authenticatedData->encapContentInfo->eContent; | |
8931b30d | 286 | |
0f113f3e MC |
287 | case NID_id_smime_ct_compressedData: |
288 | return &cms->d.compressedData->encapContentInfo->eContent; | |
8931b30d | 289 | |
0f113f3e MC |
290 | default: |
291 | if (cms->d.other->type == V_ASN1_OCTET_STRING) | |
292 | return &cms->d.other->value.octet_string; | |
9311d0c4 | 293 | ERR_raise(ERR_LIB_CMS, CMS_R_UNSUPPORTED_CONTENT_TYPE); |
0f113f3e | 294 | return NULL; |
8931b30d | 295 | |
0f113f3e MC |
296 | } |
297 | } | |
8931b30d | 298 | |
0f113f3e MC |
299 | /* |
300 | * Return an ASN1_OBJECT pointer to content type. This allows it to be | |
301 | * accessed or set later. | |
8931b30d DSH |
302 | */ |
303 | ||
304 | static ASN1_OBJECT **cms_get0_econtent_type(CMS_ContentInfo *cms) | |
0f113f3e MC |
305 | { |
306 | switch (OBJ_obj2nid(cms->contentType)) { | |
8931b30d | 307 | |
0f113f3e MC |
308 | case NID_pkcs7_signed: |
309 | return &cms->d.signedData->encapContentInfo->eContentType; | |
8931b30d | 310 | |
0f113f3e MC |
311 | case NID_pkcs7_enveloped: |
312 | return &cms->d.envelopedData->encryptedContentInfo->contentType; | |
8931b30d | 313 | |
0f113f3e MC |
314 | case NID_pkcs7_digest: |
315 | return &cms->d.digestedData->encapContentInfo->eContentType; | |
8931b30d | 316 | |
0f113f3e MC |
317 | case NID_pkcs7_encrypted: |
318 | return &cms->d.encryptedData->encryptedContentInfo->contentType; | |
8931b30d | 319 | |
924663c3 JZ |
320 | case NID_id_smime_ct_authEnvelopedData: |
321 | return &cms->d.authEnvelopedData->authEncryptedContentInfo | |
322 | ->contentType; | |
0f113f3e MC |
323 | case NID_id_smime_ct_authData: |
324 | return &cms->d.authenticatedData->encapContentInfo->eContentType; | |
8931b30d | 325 | |
0f113f3e MC |
326 | case NID_id_smime_ct_compressedData: |
327 | return &cms->d.compressedData->encapContentInfo->eContentType; | |
8931b30d | 328 | |
0f113f3e | 329 | default: |
9311d0c4 | 330 | ERR_raise(ERR_LIB_CMS, CMS_R_UNSUPPORTED_CONTENT_TYPE); |
0f113f3e | 331 | return NULL; |
8931b30d | 332 | |
0f113f3e MC |
333 | } |
334 | } | |
8931b30d DSH |
335 | |
336 | const ASN1_OBJECT *CMS_get0_eContentType(CMS_ContentInfo *cms) | |
0f113f3e MC |
337 | { |
338 | ASN1_OBJECT **petype; | |
339 | petype = cms_get0_econtent_type(cms); | |
340 | if (petype) | |
341 | return *petype; | |
342 | return NULL; | |
343 | } | |
8931b30d DSH |
344 | |
345 | int CMS_set1_eContentType(CMS_ContentInfo *cms, const ASN1_OBJECT *oid) | |
0f113f3e MC |
346 | { |
347 | ASN1_OBJECT **petype, *etype; | |
12a765a5 | 348 | |
0f113f3e | 349 | petype = cms_get0_econtent_type(cms); |
12a765a5 | 350 | if (petype == NULL) |
0f113f3e | 351 | return 0; |
12a765a5 | 352 | if (oid == NULL) |
0f113f3e MC |
353 | return 1; |
354 | etype = OBJ_dup(oid); | |
12a765a5 | 355 | if (etype == NULL) |
0f113f3e MC |
356 | return 0; |
357 | ASN1_OBJECT_free(*petype); | |
358 | *petype = etype; | |
359 | return 1; | |
360 | } | |
8931b30d DSH |
361 | |
362 | int CMS_is_detached(CMS_ContentInfo *cms) | |
0f113f3e MC |
363 | { |
364 | ASN1_OCTET_STRING **pos; | |
12a765a5 | 365 | |
0f113f3e | 366 | pos = CMS_get0_content(cms); |
12a765a5 | 367 | if (pos == NULL) |
0f113f3e | 368 | return -1; |
12a765a5 | 369 | if (*pos != NULL) |
0f113f3e MC |
370 | return 0; |
371 | return 1; | |
372 | } | |
8931b30d DSH |
373 | |
374 | int CMS_set_detached(CMS_ContentInfo *cms, int detached) | |
0f113f3e MC |
375 | { |
376 | ASN1_OCTET_STRING **pos; | |
12a765a5 | 377 | |
0f113f3e | 378 | pos = CMS_get0_content(cms); |
12a765a5 | 379 | if (pos == NULL) |
0f113f3e MC |
380 | return 0; |
381 | if (detached) { | |
2ace7450 RS |
382 | ASN1_OCTET_STRING_free(*pos); |
383 | *pos = NULL; | |
0f113f3e MC |
384 | return 1; |
385 | } | |
90945fa3 | 386 | if (*pos == NULL) |
0f113f3e | 387 | *pos = ASN1_OCTET_STRING_new(); |
90945fa3 | 388 | if (*pos != NULL) { |
0f113f3e MC |
389 | /* |
390 | * NB: special flag to show content is created and not read in. | |
391 | */ | |
392 | (*pos)->flags |= ASN1_STRING_FLAG_CONT; | |
393 | return 1; | |
394 | } | |
9311d0c4 | 395 | ERR_raise(ERR_LIB_CMS, ERR_R_MALLOC_FAILURE); |
0f113f3e MC |
396 | return 0; |
397 | } | |
8931b30d | 398 | |
8931b30d DSH |
399 | /* Create a digest BIO from an X509_ALGOR structure */ |
400 | ||
c1669f41 SL |
401 | BIO *cms_DigestAlgorithm_init_bio(X509_ALGOR *digestAlgorithm, |
402 | const CMS_CTX *ctx) | |
0f113f3e MC |
403 | { |
404 | BIO *mdbio = NULL; | |
ac4e2577 | 405 | const ASN1_OBJECT *digestoid; |
1acb2e6f SL |
406 | const EVP_MD *digest = NULL; |
407 | EVP_MD *fetched_digest = NULL; | |
c1669f41 SL |
408 | const char *alg; |
409 | ||
0f113f3e | 410 | X509_ALGOR_get0(&digestoid, NULL, NULL, digestAlgorithm); |
c1669f41 | 411 | alg = OBJ_nid2sn(OBJ_obj2nid(digestoid)); |
1acb2e6f SL |
412 | |
413 | (void)ERR_set_mark(); | |
414 | fetched_digest = EVP_MD_fetch(ctx->libctx, alg, ctx->propq); | |
415 | ||
416 | if (fetched_digest != NULL) | |
417 | digest = fetched_digest; | |
418 | else | |
419 | digest = EVP_get_digestbyobj(digestoid); | |
c1669f41 | 420 | if (digest == NULL) { |
1acb2e6f | 421 | (void)ERR_clear_last_mark(); |
9311d0c4 | 422 | ERR_raise(ERR_LIB_CMS, CMS_R_UNKNOWN_DIGEST_ALGORITHM); |
0f113f3e MC |
423 | goto err; |
424 | } | |
1acb2e6f SL |
425 | (void)ERR_pop_to_mark(); |
426 | ||
0f113f3e | 427 | mdbio = BIO_new(BIO_f_md()); |
90945fa3 | 428 | if (mdbio == NULL || !BIO_set_md(mdbio, digest)) { |
9311d0c4 | 429 | ERR_raise(ERR_LIB_CMS, CMS_R_MD_BIO_INIT_ERROR); |
0f113f3e MC |
430 | goto err; |
431 | } | |
1acb2e6f | 432 | EVP_MD_free(fetched_digest); |
0f113f3e MC |
433 | return mdbio; |
434 | err: | |
1acb2e6f | 435 | EVP_MD_free(fetched_digest); |
ca3a82c3 | 436 | BIO_free(mdbio); |
0f113f3e MC |
437 | return NULL; |
438 | } | |
8931b30d DSH |
439 | |
440 | /* Locate a message digest content from a BIO chain based on SignerInfo */ | |
441 | ||
442 | int cms_DigestAlgorithm_find_ctx(EVP_MD_CTX *mctx, BIO *chain, | |
0f113f3e MC |
443 | X509_ALGOR *mdalg) |
444 | { | |
445 | int nid; | |
ac4e2577 | 446 | const ASN1_OBJECT *mdoid; |
0f113f3e MC |
447 | X509_ALGOR_get0(&mdoid, NULL, NULL, mdalg); |
448 | nid = OBJ_obj2nid(mdoid); | |
449 | /* Look for digest type to match signature */ | |
450 | for (;;) { | |
451 | EVP_MD_CTX *mtmp; | |
452 | chain = BIO_find_type(chain, BIO_TYPE_MD); | |
453 | if (chain == NULL) { | |
9311d0c4 | 454 | ERR_raise(ERR_LIB_CMS, CMS_R_NO_MATCHING_DIGEST); |
0f113f3e MC |
455 | return 0; |
456 | } | |
457 | BIO_get_md_ctx(chain, &mtmp); | |
458 | if (EVP_MD_CTX_type(mtmp) == nid | |
459 | /* | |
460 | * Workaround for broken implementations that use signature | |
461 | * algorithm OID instead of digest. | |
462 | */ | |
463 | || EVP_MD_pkey_type(EVP_MD_CTX_md(mtmp)) == nid) | |
464 | return EVP_MD_CTX_copy_ex(mctx, mtmp); | |
465 | chain = BIO_next(chain); | |
466 | } | |
467 | } | |
468 | ||
469 | static STACK_OF(CMS_CertificateChoices) | |
470 | **cms_get0_certificate_choices(CMS_ContentInfo *cms) | |
471 | { | |
472 | switch (OBJ_obj2nid(cms->contentType)) { | |
473 | ||
474 | case NID_pkcs7_signed: | |
475 | return &cms->d.signedData->certificates; | |
476 | ||
477 | case NID_pkcs7_enveloped: | |
6b360288 PH |
478 | if (cms->d.envelopedData->originatorInfo == NULL) |
479 | return NULL; | |
0f113f3e MC |
480 | return &cms->d.envelopedData->originatorInfo->certificates; |
481 | ||
924663c3 JZ |
482 | case NID_id_smime_ct_authEnvelopedData: |
483 | if (cms->d.authEnvelopedData->originatorInfo == NULL) | |
484 | return NULL; | |
485 | return &cms->d.authEnvelopedData->originatorInfo->certificates; | |
486 | ||
0f113f3e | 487 | default: |
9311d0c4 | 488 | ERR_raise(ERR_LIB_CMS, CMS_R_UNSUPPORTED_CONTENT_TYPE); |
0f113f3e MC |
489 | return NULL; |
490 | ||
491 | } | |
492 | } | |
8931b30d DSH |
493 | |
494 | CMS_CertificateChoices *CMS_add0_CertificateChoices(CMS_ContentInfo *cms) | |
0f113f3e MC |
495 | { |
496 | STACK_OF(CMS_CertificateChoices) **pcerts; | |
497 | CMS_CertificateChoices *cch; | |
12a765a5 | 498 | |
0f113f3e | 499 | pcerts = cms_get0_certificate_choices(cms); |
12a765a5 | 500 | if (pcerts == NULL) |
0f113f3e | 501 | return NULL; |
12a765a5 | 502 | if (*pcerts == NULL) |
0f113f3e | 503 | *pcerts = sk_CMS_CertificateChoices_new_null(); |
12a765a5 | 504 | if (*pcerts == NULL) |
0f113f3e MC |
505 | return NULL; |
506 | cch = M_ASN1_new_of(CMS_CertificateChoices); | |
507 | if (!cch) | |
508 | return NULL; | |
509 | if (!sk_CMS_CertificateChoices_push(*pcerts, cch)) { | |
510 | M_ASN1_free_of(cch, CMS_CertificateChoices); | |
511 | return NULL; | |
512 | } | |
513 | return cch; | |
514 | } | |
8931b30d DSH |
515 | |
516 | int CMS_add0_cert(CMS_ContentInfo *cms, X509 *cert) | |
0f113f3e MC |
517 | { |
518 | CMS_CertificateChoices *cch; | |
519 | STACK_OF(CMS_CertificateChoices) **pcerts; | |
520 | int i; | |
12a765a5 | 521 | |
0f113f3e | 522 | pcerts = cms_get0_certificate_choices(cms); |
12a765a5 | 523 | if (pcerts == NULL) |
0f113f3e MC |
524 | return 0; |
525 | for (i = 0; i < sk_CMS_CertificateChoices_num(*pcerts); i++) { | |
526 | cch = sk_CMS_CertificateChoices_value(*pcerts, i); | |
527 | if (cch->type == CMS_CERTCHOICE_CERT) { | |
528 | if (!X509_cmp(cch->d.certificate, cert)) { | |
9311d0c4 | 529 | ERR_raise(ERR_LIB_CMS, CMS_R_CERTIFICATE_ALREADY_PRESENT); |
0f113f3e MC |
530 | return 0; |
531 | } | |
532 | } | |
533 | } | |
534 | cch = CMS_add0_CertificateChoices(cms); | |
535 | if (!cch) | |
536 | return 0; | |
537 | cch->type = CMS_CERTCHOICE_CERT; | |
538 | cch->d.certificate = cert; | |
539 | return 1; | |
540 | } | |
8931b30d DSH |
541 | |
542 | int CMS_add1_cert(CMS_ContentInfo *cms, X509 *cert) | |
0f113f3e MC |
543 | { |
544 | int r; | |
545 | r = CMS_add0_cert(cms, cert); | |
546 | if (r > 0) | |
05f0fb9f | 547 | X509_up_ref(cert); |
0f113f3e MC |
548 | return r; |
549 | } | |
8931b30d | 550 | |
0f113f3e MC |
551 | static STACK_OF(CMS_RevocationInfoChoice) |
552 | **cms_get0_revocation_choices(CMS_ContentInfo *cms) | |
553 | { | |
554 | switch (OBJ_obj2nid(cms->contentType)) { | |
8931b30d | 555 | |
0f113f3e MC |
556 | case NID_pkcs7_signed: |
557 | return &cms->d.signedData->crls; | |
8931b30d | 558 | |
0f113f3e | 559 | case NID_pkcs7_enveloped: |
6b360288 PH |
560 | if (cms->d.envelopedData->originatorInfo == NULL) |
561 | return NULL; | |
0f113f3e | 562 | return &cms->d.envelopedData->originatorInfo->crls; |
8931b30d | 563 | |
924663c3 JZ |
564 | case NID_id_smime_ct_authEnvelopedData: |
565 | if (cms->d.authEnvelopedData->originatorInfo == NULL) | |
566 | return NULL; | |
567 | return &cms->d.authEnvelopedData->originatorInfo->crls; | |
568 | ||
0f113f3e | 569 | default: |
9311d0c4 | 570 | ERR_raise(ERR_LIB_CMS, CMS_R_UNSUPPORTED_CONTENT_TYPE); |
0f113f3e | 571 | return NULL; |
8931b30d | 572 | |
0f113f3e MC |
573 | } |
574 | } | |
8931b30d DSH |
575 | |
576 | CMS_RevocationInfoChoice *CMS_add0_RevocationInfoChoice(CMS_ContentInfo *cms) | |
0f113f3e MC |
577 | { |
578 | STACK_OF(CMS_RevocationInfoChoice) **pcrls; | |
579 | CMS_RevocationInfoChoice *rch; | |
12a765a5 | 580 | |
0f113f3e | 581 | pcrls = cms_get0_revocation_choices(cms); |
12a765a5 | 582 | if (pcrls == NULL) |
0f113f3e | 583 | return NULL; |
12a765a5 | 584 | if (*pcrls == NULL) |
0f113f3e | 585 | *pcrls = sk_CMS_RevocationInfoChoice_new_null(); |
12a765a5 | 586 | if (*pcrls == NULL) |
0f113f3e MC |
587 | return NULL; |
588 | rch = M_ASN1_new_of(CMS_RevocationInfoChoice); | |
12a765a5 | 589 | if (rch == NULL) |
0f113f3e MC |
590 | return NULL; |
591 | if (!sk_CMS_RevocationInfoChoice_push(*pcrls, rch)) { | |
592 | M_ASN1_free_of(rch, CMS_RevocationInfoChoice); | |
593 | return NULL; | |
594 | } | |
595 | return rch; | |
596 | } | |
8931b30d DSH |
597 | |
598 | int CMS_add0_crl(CMS_ContentInfo *cms, X509_CRL *crl) | |
0f113f3e MC |
599 | { |
600 | CMS_RevocationInfoChoice *rch; | |
601 | rch = CMS_add0_RevocationInfoChoice(cms); | |
602 | if (!rch) | |
603 | return 0; | |
604 | rch->type = CMS_REVCHOICE_CRL; | |
605 | rch->d.crl = crl; | |
606 | return 1; | |
607 | } | |
8931b30d | 608 | |
19048b5c | 609 | int CMS_add1_crl(CMS_ContentInfo *cms, X509_CRL *crl) |
0f113f3e MC |
610 | { |
611 | int r; | |
612 | r = CMS_add0_crl(cms, crl); | |
613 | if (r > 0) | |
65cbf983 | 614 | X509_CRL_up_ref(crl); |
0f113f3e MC |
615 | return r; |
616 | } | |
19048b5c | 617 | |
8931b30d | 618 | STACK_OF(X509) *CMS_get1_certs(CMS_ContentInfo *cms) |
0f113f3e MC |
619 | { |
620 | STACK_OF(X509) *certs = NULL; | |
621 | CMS_CertificateChoices *cch; | |
622 | STACK_OF(CMS_CertificateChoices) **pcerts; | |
623 | int i; | |
12a765a5 | 624 | |
0f113f3e | 625 | pcerts = cms_get0_certificate_choices(cms); |
12a765a5 | 626 | if (pcerts == NULL) |
0f113f3e MC |
627 | return NULL; |
628 | for (i = 0; i < sk_CMS_CertificateChoices_num(*pcerts); i++) { | |
629 | cch = sk_CMS_CertificateChoices_value(*pcerts, i); | |
630 | if (cch->type == 0) { | |
eeccc237 DDO |
631 | if (!X509_add_cert_new(&certs, cch->d.certificate, |
632 | X509_ADD_FLAG_UP_REF)) { | |
0f113f3e MC |
633 | sk_X509_pop_free(certs, X509_free); |
634 | return NULL; | |
635 | } | |
0f113f3e MC |
636 | } |
637 | } | |
638 | return certs; | |
639 | ||
640 | } | |
8931b30d DSH |
641 | |
642 | STACK_OF(X509_CRL) *CMS_get1_crls(CMS_ContentInfo *cms) | |
0f113f3e MC |
643 | { |
644 | STACK_OF(X509_CRL) *crls = NULL; | |
645 | STACK_OF(CMS_RevocationInfoChoice) **pcrls; | |
646 | CMS_RevocationInfoChoice *rch; | |
647 | int i; | |
12a765a5 | 648 | |
0f113f3e | 649 | pcrls = cms_get0_revocation_choices(cms); |
12a765a5 | 650 | if (pcrls == NULL) |
0f113f3e MC |
651 | return NULL; |
652 | for (i = 0; i < sk_CMS_RevocationInfoChoice_num(*pcrls); i++) { | |
653 | rch = sk_CMS_RevocationInfoChoice_value(*pcrls, i); | |
654 | if (rch->type == 0) { | |
655 | if (!crls) { | |
656 | crls = sk_X509_CRL_new_null(); | |
657 | if (!crls) | |
658 | return NULL; | |
659 | } | |
660 | if (!sk_X509_CRL_push(crls, rch->d.crl)) { | |
661 | sk_X509_CRL_pop_free(crls, X509_CRL_free); | |
662 | return NULL; | |
663 | } | |
65cbf983 | 664 | X509_CRL_up_ref(rch->d.crl); |
0f113f3e MC |
665 | } |
666 | } | |
667 | return crls; | |
668 | } | |
17c2764d DSH |
669 | |
670 | int cms_ias_cert_cmp(CMS_IssuerAndSerialNumber *ias, X509 *cert) | |
0f113f3e MC |
671 | { |
672 | int ret; | |
673 | ret = X509_NAME_cmp(ias->issuer, X509_get_issuer_name(cert)); | |
674 | if (ret) | |
675 | return ret; | |
1337a3a9 | 676 | return ASN1_INTEGER_cmp(ias->serialNumber, X509_get0_serialNumber(cert)); |
0f113f3e | 677 | } |
17c2764d DSH |
678 | |
679 | int cms_keyid_cert_cmp(ASN1_OCTET_STRING *keyid, X509 *cert) | |
0f113f3e | 680 | { |
d19a50c9 DSH |
681 | const ASN1_OCTET_STRING *cert_keyid = X509_get0_subject_key_id(cert); |
682 | ||
683 | if (cert_keyid == NULL) | |
0f113f3e | 684 | return -1; |
d19a50c9 | 685 | return ASN1_OCTET_STRING_cmp(keyid, cert_keyid); |
0f113f3e | 686 | } |
17c2764d DSH |
687 | |
688 | int cms_set1_ias(CMS_IssuerAndSerialNumber **pias, X509 *cert) | |
0f113f3e MC |
689 | { |
690 | CMS_IssuerAndSerialNumber *ias; | |
691 | ias = M_ASN1_new_of(CMS_IssuerAndSerialNumber); | |
692 | if (!ias) | |
693 | goto err; | |
694 | if (!X509_NAME_set(&ias->issuer, X509_get_issuer_name(cert))) | |
695 | goto err; | |
1337a3a9 | 696 | if (!ASN1_STRING_copy(ias->serialNumber, X509_get0_serialNumber(cert))) |
0f113f3e | 697 | goto err; |
2ace7450 | 698 | M_ASN1_free_of(*pias, CMS_IssuerAndSerialNumber); |
0f113f3e MC |
699 | *pias = ias; |
700 | return 1; | |
701 | err: | |
2ace7450 | 702 | M_ASN1_free_of(ias, CMS_IssuerAndSerialNumber); |
9311d0c4 | 703 | ERR_raise(ERR_LIB_CMS, ERR_R_MALLOC_FAILURE); |
0f113f3e MC |
704 | return 0; |
705 | } | |
17c2764d DSH |
706 | |
707 | int cms_set1_keyid(ASN1_OCTET_STRING **pkeyid, X509 *cert) | |
0f113f3e MC |
708 | { |
709 | ASN1_OCTET_STRING *keyid = NULL; | |
d19a50c9 DSH |
710 | const ASN1_OCTET_STRING *cert_keyid; |
711 | cert_keyid = X509_get0_subject_key_id(cert); | |
712 | if (cert_keyid == NULL) { | |
9311d0c4 | 713 | ERR_raise(ERR_LIB_CMS, CMS_R_CERTIFICATE_HAS_NO_KEYID); |
0f113f3e MC |
714 | return 0; |
715 | } | |
d19a50c9 | 716 | keyid = ASN1_STRING_dup(cert_keyid); |
0f113f3e | 717 | if (!keyid) { |
9311d0c4 | 718 | ERR_raise(ERR_LIB_CMS, ERR_R_MALLOC_FAILURE); |
0f113f3e MC |
719 | return 0; |
720 | } | |
2ace7450 | 721 | ASN1_OCTET_STRING_free(*pkeyid); |
0f113f3e MC |
722 | *pkeyid = keyid; |
723 | return 1; | |
724 | } |