]>
Commit | Line | Data |
---|---|---|
94b2c29f | 1 | /* crypto/cms/cms_lib.c */ |
40720ce3 MC |
2 | /* |
3 | * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL | |
94b2c29f DSH |
4 | * project. |
5 | */ | |
6 | /* ==================================================================== | |
7 | * Copyright (c) 2008 The OpenSSL Project. All rights reserved. | |
8 | * | |
9 | * Redistribution and use in source and binary forms, with or without | |
10 | * modification, are permitted provided that the following conditions | |
11 | * are met: | |
12 | * | |
13 | * 1. Redistributions of source code must retain the above copyright | |
40720ce3 | 14 | * notice, this list of conditions and the following disclaimer. |
94b2c29f DSH |
15 | * |
16 | * 2. Redistributions in binary form must reproduce the above copyright | |
17 | * notice, this list of conditions and the following disclaimer in | |
18 | * the documentation and/or other materials provided with the | |
19 | * distribution. | |
20 | * | |
21 | * 3. All advertising materials mentioning features or use of this | |
22 | * software must display the following acknowledgment: | |
23 | * "This product includes software developed by the OpenSSL Project | |
24 | * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" | |
25 | * | |
26 | * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to | |
27 | * endorse or promote products derived from this software without | |
28 | * prior written permission. For written permission, please contact | |
29 | * licensing@OpenSSL.org. | |
30 | * | |
31 | * 5. Products derived from this software may not be called "OpenSSL" | |
32 | * nor may "OpenSSL" appear in their names without prior written | |
33 | * permission of the OpenSSL Project. | |
34 | * | |
35 | * 6. Redistributions of any form whatsoever must retain the following | |
36 | * acknowledgment: | |
37 | * "This product includes software developed by the OpenSSL Project | |
38 | * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" | |
39 | * | |
40 | * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY | |
41 | * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
42 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |
43 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR | |
44 | * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |
45 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | |
46 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
47 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
48 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, | |
49 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |
50 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED | |
51 | * OF THE POSSIBILITY OF SUCH DAMAGE. | |
52 | * ==================================================================== | |
53 | */ | |
54 | ||
55 | #include <openssl/asn1t.h> | |
56 | #include <openssl/x509.h> | |
57 | #include <openssl/err.h> | |
58 | #include <openssl/pem.h> | |
59 | #include <openssl/bio.h> | |
60 | #include <openssl/asn1.h> | |
61 | #include "cms.h" | |
62 | #include "cms_lcl.h" | |
63 | ||
64 | IMPLEMENT_ASN1_FUNCTIONS_const(CMS_ContentInfo) | |
65 | ||
66 | DECLARE_ASN1_ITEM(CMS_CertificateChoices) | |
67 | DECLARE_ASN1_ITEM(CMS_RevocationInfoChoice) | |
68 | DECLARE_STACK_OF(CMS_CertificateChoices) | |
69 | DECLARE_STACK_OF(CMS_RevocationInfoChoice) | |
70 | ||
71 | const ASN1_OBJECT *CMS_get0_type(CMS_ContentInfo *cms) | |
40720ce3 MC |
72 | { |
73 | return cms->contentType; | |
74 | } | |
94b2c29f DSH |
75 | |
76 | CMS_ContentInfo *cms_Data_create(void) | |
40720ce3 MC |
77 | { |
78 | CMS_ContentInfo *cms; | |
79 | cms = CMS_ContentInfo_new(); | |
80 | if (cms) { | |
81 | cms->contentType = OBJ_nid2obj(NID_pkcs7_data); | |
82 | /* Never detached */ | |
83 | CMS_set_detached(cms, 0); | |
84 | } | |
85 | return cms; | |
86 | } | |
94b2c29f DSH |
87 | |
88 | BIO *cms_content_bio(CMS_ContentInfo *cms) | |
40720ce3 MC |
89 | { |
90 | ASN1_OCTET_STRING **pos = CMS_get0_content(cms); | |
91 | if (!pos) | |
92 | return NULL; | |
93 | /* If content detached data goes nowhere: create NULL BIO */ | |
94 | if (!*pos) | |
95 | return BIO_new(BIO_s_null()); | |
96 | /* | |
97 | * If content not detached and created return memory BIO | |
98 | */ | |
99 | if (!*pos || ((*pos)->flags == ASN1_STRING_FLAG_CONT)) | |
100 | return BIO_new(BIO_s_mem()); | |
101 | /* Else content was read in: return read only BIO for it */ | |
102 | return BIO_new_mem_buf((*pos)->data, (*pos)->length); | |
103 | } | |
94b2c29f DSH |
104 | |
105 | BIO *CMS_dataInit(CMS_ContentInfo *cms, BIO *icont) | |
40720ce3 MC |
106 | { |
107 | BIO *cmsbio, *cont; | |
108 | if (icont) | |
109 | cont = icont; | |
110 | else | |
111 | cont = cms_content_bio(cms); | |
112 | if (!cont) { | |
113 | CMSerr(CMS_F_CMS_DATAINIT, CMS_R_NO_CONTENT); | |
114 | return NULL; | |
115 | } | |
116 | switch (OBJ_obj2nid(cms->contentType)) { | |
117 | ||
118 | case NID_pkcs7_data: | |
119 | return cont; | |
120 | ||
121 | case NID_pkcs7_signed: | |
122 | cmsbio = cms_SignedData_init_bio(cms); | |
123 | break; | |
124 | ||
125 | case NID_pkcs7_digest: | |
126 | cmsbio = cms_DigestedData_init_bio(cms); | |
127 | break; | |
94b2c29f | 128 | #ifdef ZLIB |
40720ce3 MC |
129 | case NID_id_smime_ct_compressedData: |
130 | cmsbio = cms_CompressedData_init_bio(cms); | |
131 | break; | |
94b2c29f DSH |
132 | #endif |
133 | ||
40720ce3 MC |
134 | case NID_pkcs7_encrypted: |
135 | cmsbio = cms_EncryptedData_init_bio(cms); | |
136 | break; | |
94b2c29f | 137 | |
40720ce3 MC |
138 | case NID_pkcs7_enveloped: |
139 | cmsbio = cms_EnvelopedData_init_bio(cms); | |
140 | break; | |
94b2c29f | 141 | |
40720ce3 MC |
142 | default: |
143 | CMSerr(CMS_F_CMS_DATAINIT, CMS_R_UNSUPPORTED_TYPE); | |
144 | return NULL; | |
145 | } | |
94b2c29f | 146 | |
40720ce3 MC |
147 | if (cmsbio) |
148 | return BIO_push(cmsbio, cont); | |
94b2c29f | 149 | |
40720ce3 MC |
150 | if (!icont) |
151 | BIO_free(cont); | |
152 | return NULL; | |
94b2c29f | 153 | |
40720ce3 | 154 | } |
94b2c29f DSH |
155 | |
156 | int CMS_dataFinal(CMS_ContentInfo *cms, BIO *cmsbio) | |
40720ce3 MC |
157 | { |
158 | ASN1_OCTET_STRING **pos = CMS_get0_content(cms); | |
159 | if (!pos) | |
160 | return 0; | |
161 | /* If ebmedded content find memory BIO and set content */ | |
162 | if (*pos && ((*pos)->flags & ASN1_STRING_FLAG_CONT)) { | |
163 | BIO *mbio; | |
164 | unsigned char *cont; | |
165 | long contlen; | |
166 | mbio = BIO_find_type(cmsbio, BIO_TYPE_MEM); | |
167 | if (!mbio) { | |
168 | CMSerr(CMS_F_CMS_DATAFINAL, CMS_R_CONTENT_NOT_FOUND); | |
169 | return 0; | |
170 | } | |
171 | contlen = BIO_get_mem_data(mbio, &cont); | |
172 | /* Set bio as read only so its content can't be clobbered */ | |
173 | BIO_set_flags(mbio, BIO_FLAGS_MEM_RDONLY); | |
174 | BIO_set_mem_eof_return(mbio, 0); | |
175 | ASN1_STRING_set0(*pos, cont, contlen); | |
176 | (*pos)->flags &= ~ASN1_STRING_FLAG_CONT; | |
177 | } | |
178 | ||
179 | switch (OBJ_obj2nid(cms->contentType)) { | |
180 | ||
181 | case NID_pkcs7_data: | |
182 | case NID_pkcs7_enveloped: | |
183 | case NID_pkcs7_encrypted: | |
184 | case NID_id_smime_ct_compressedData: | |
185 | /* Nothing to do */ | |
186 | return 1; | |
187 | ||
188 | case NID_pkcs7_signed: | |
189 | return cms_SignedData_final(cms, cmsbio); | |
190 | ||
191 | case NID_pkcs7_digest: | |
192 | return cms_DigestedData_do_final(cms, cmsbio, 0); | |
193 | ||
194 | default: | |
195 | CMSerr(CMS_F_CMS_DATAFINAL, CMS_R_UNSUPPORTED_TYPE); | |
196 | return 0; | |
197 | } | |
198 | } | |
199 | ||
200 | /* | |
201 | * Return an OCTET STRING pointer to content. This allows it to be accessed | |
202 | * or set later. | |
94b2c29f DSH |
203 | */ |
204 | ||
205 | ASN1_OCTET_STRING **CMS_get0_content(CMS_ContentInfo *cms) | |
40720ce3 MC |
206 | { |
207 | switch (OBJ_obj2nid(cms->contentType)) { | |
94b2c29f | 208 | |
40720ce3 MC |
209 | case NID_pkcs7_data: |
210 | return &cms->d.data; | |
94b2c29f | 211 | |
40720ce3 MC |
212 | case NID_pkcs7_signed: |
213 | return &cms->d.signedData->encapContentInfo->eContent; | |
94b2c29f | 214 | |
40720ce3 MC |
215 | case NID_pkcs7_enveloped: |
216 | return &cms->d.envelopedData->encryptedContentInfo->encryptedContent; | |
94b2c29f | 217 | |
40720ce3 MC |
218 | case NID_pkcs7_digest: |
219 | return &cms->d.digestedData->encapContentInfo->eContent; | |
94b2c29f | 220 | |
40720ce3 MC |
221 | case NID_pkcs7_encrypted: |
222 | return &cms->d.encryptedData->encryptedContentInfo->encryptedContent; | |
94b2c29f | 223 | |
40720ce3 MC |
224 | case NID_id_smime_ct_authData: |
225 | return &cms->d.authenticatedData->encapContentInfo->eContent; | |
94b2c29f | 226 | |
40720ce3 MC |
227 | case NID_id_smime_ct_compressedData: |
228 | return &cms->d.compressedData->encapContentInfo->eContent; | |
94b2c29f | 229 | |
40720ce3 MC |
230 | default: |
231 | if (cms->d.other->type == V_ASN1_OCTET_STRING) | |
232 | return &cms->d.other->value.octet_string; | |
233 | CMSerr(CMS_F_CMS_GET0_CONTENT, CMS_R_UNSUPPORTED_CONTENT_TYPE); | |
234 | return NULL; | |
94b2c29f | 235 | |
40720ce3 MC |
236 | } |
237 | } | |
94b2c29f | 238 | |
40720ce3 MC |
239 | /* |
240 | * Return an ASN1_OBJECT pointer to content type. This allows it to be | |
241 | * accessed or set later. | |
94b2c29f DSH |
242 | */ |
243 | ||
244 | static ASN1_OBJECT **cms_get0_econtent_type(CMS_ContentInfo *cms) | |
40720ce3 MC |
245 | { |
246 | switch (OBJ_obj2nid(cms->contentType)) { | |
94b2c29f | 247 | |
40720ce3 MC |
248 | case NID_pkcs7_signed: |
249 | return &cms->d.signedData->encapContentInfo->eContentType; | |
94b2c29f | 250 | |
40720ce3 MC |
251 | case NID_pkcs7_enveloped: |
252 | return &cms->d.envelopedData->encryptedContentInfo->contentType; | |
94b2c29f | 253 | |
40720ce3 MC |
254 | case NID_pkcs7_digest: |
255 | return &cms->d.digestedData->encapContentInfo->eContentType; | |
94b2c29f | 256 | |
40720ce3 MC |
257 | case NID_pkcs7_encrypted: |
258 | return &cms->d.encryptedData->encryptedContentInfo->contentType; | |
94b2c29f | 259 | |
40720ce3 MC |
260 | case NID_id_smime_ct_authData: |
261 | return &cms->d.authenticatedData->encapContentInfo->eContentType; | |
94b2c29f | 262 | |
40720ce3 MC |
263 | case NID_id_smime_ct_compressedData: |
264 | return &cms->d.compressedData->encapContentInfo->eContentType; | |
94b2c29f | 265 | |
40720ce3 MC |
266 | default: |
267 | CMSerr(CMS_F_CMS_GET0_ECONTENT_TYPE, CMS_R_UNSUPPORTED_CONTENT_TYPE); | |
268 | return NULL; | |
94b2c29f | 269 | |
40720ce3 MC |
270 | } |
271 | } | |
94b2c29f DSH |
272 | |
273 | const ASN1_OBJECT *CMS_get0_eContentType(CMS_ContentInfo *cms) | |
40720ce3 MC |
274 | { |
275 | ASN1_OBJECT **petype; | |
276 | petype = cms_get0_econtent_type(cms); | |
277 | if (petype) | |
278 | return *petype; | |
279 | return NULL; | |
280 | } | |
94b2c29f DSH |
281 | |
282 | int CMS_set1_eContentType(CMS_ContentInfo *cms, const ASN1_OBJECT *oid) | |
40720ce3 MC |
283 | { |
284 | ASN1_OBJECT **petype, *etype; | |
285 | petype = cms_get0_econtent_type(cms); | |
286 | if (!petype) | |
287 | return 0; | |
288 | if (!oid) | |
289 | return 1; | |
290 | etype = OBJ_dup(oid); | |
291 | if (!etype) | |
292 | return 0; | |
293 | ASN1_OBJECT_free(*petype); | |
294 | *petype = etype; | |
295 | return 1; | |
296 | } | |
94b2c29f DSH |
297 | |
298 | int CMS_is_detached(CMS_ContentInfo *cms) | |
40720ce3 MC |
299 | { |
300 | ASN1_OCTET_STRING **pos; | |
301 | pos = CMS_get0_content(cms); | |
302 | if (!pos) | |
303 | return -1; | |
304 | if (*pos) | |
305 | return 0; | |
306 | return 1; | |
307 | } | |
94b2c29f DSH |
308 | |
309 | int CMS_set_detached(CMS_ContentInfo *cms, int detached) | |
40720ce3 MC |
310 | { |
311 | ASN1_OCTET_STRING **pos; | |
312 | pos = CMS_get0_content(cms); | |
313 | if (!pos) | |
314 | return 0; | |
315 | if (detached) { | |
316 | if (*pos) { | |
317 | ASN1_OCTET_STRING_free(*pos); | |
318 | *pos = NULL; | |
319 | } | |
320 | return 1; | |
321 | } | |
322 | if (!*pos) | |
323 | *pos = ASN1_OCTET_STRING_new(); | |
324 | if (*pos) { | |
325 | /* | |
326 | * NB: special flag to show content is created and not read in. | |
327 | */ | |
328 | (*pos)->flags |= ASN1_STRING_FLAG_CONT; | |
329 | return 1; | |
330 | } | |
331 | CMSerr(CMS_F_CMS_SET_DETACHED, ERR_R_MALLOC_FAILURE); | |
332 | return 0; | |
333 | } | |
94b2c29f DSH |
334 | |
335 | /* Set up an X509_ALGOR DigestAlgorithmIdentifier from an EVP_MD */ | |
336 | ||
337 | void cms_DigestAlgorithm_set(X509_ALGOR *alg, const EVP_MD *md) | |
40720ce3 MC |
338 | { |
339 | int param_type; | |
340 | ||
341 | switch (EVP_MD_type(md)) { | |
342 | case NID_sha1: | |
343 | case NID_sha224: | |
344 | case NID_sha256: | |
345 | case NID_sha384: | |
346 | case NID_sha512: | |
347 | param_type = V_ASN1_UNDEF; | |
348 | break; | |
349 | ||
350 | default: | |
351 | param_type = V_ASN1_NULL; | |
352 | break; | |
353 | } | |
354 | ||
355 | X509_ALGOR_set0(alg, OBJ_nid2obj(EVP_MD_type(md)), param_type, NULL); | |
356 | ||
357 | } | |
94b2c29f DSH |
358 | |
359 | /* Create a digest BIO from an X509_ALGOR structure */ | |
360 | ||
361 | BIO *cms_DigestAlgorithm_init_bio(X509_ALGOR *digestAlgorithm) | |
40720ce3 MC |
362 | { |
363 | BIO *mdbio = NULL; | |
364 | ASN1_OBJECT *digestoid; | |
365 | const EVP_MD *digest; | |
366 | X509_ALGOR_get0(&digestoid, NULL, NULL, digestAlgorithm); | |
367 | digest = EVP_get_digestbyobj(digestoid); | |
368 | if (!digest) { | |
369 | CMSerr(CMS_F_CMS_DIGESTALGORITHM_INIT_BIO, | |
370 | CMS_R_UNKNOWN_DIGEST_ALGORIHM); | |
371 | goto err; | |
372 | } | |
373 | mdbio = BIO_new(BIO_f_md()); | |
374 | if (!mdbio || !BIO_set_md(mdbio, digest)) { | |
375 | CMSerr(CMS_F_CMS_DIGESTALGORITHM_INIT_BIO, CMS_R_MD_BIO_INIT_ERROR); | |
376 | goto err; | |
377 | } | |
378 | return mdbio; | |
379 | err: | |
380 | if (mdbio) | |
381 | BIO_free(mdbio); | |
382 | return NULL; | |
383 | } | |
94b2c29f DSH |
384 | |
385 | /* Locate a message digest content from a BIO chain based on SignerInfo */ | |
386 | ||
387 | int cms_DigestAlgorithm_find_ctx(EVP_MD_CTX *mctx, BIO *chain, | |
40720ce3 MC |
388 | X509_ALGOR *mdalg) |
389 | { | |
390 | int nid; | |
391 | ASN1_OBJECT *mdoid; | |
392 | X509_ALGOR_get0(&mdoid, NULL, NULL, mdalg); | |
393 | nid = OBJ_obj2nid(mdoid); | |
394 | /* Look for digest type to match signature */ | |
395 | for (;;) { | |
396 | EVP_MD_CTX *mtmp; | |
397 | chain = BIO_find_type(chain, BIO_TYPE_MD); | |
398 | if (chain == NULL) { | |
399 | CMSerr(CMS_F_CMS_DIGESTALGORITHM_FIND_CTX, | |
400 | CMS_R_NO_MATCHING_DIGEST); | |
401 | return 0; | |
402 | } | |
403 | BIO_get_md_ctx(chain, &mtmp); | |
404 | if (EVP_MD_CTX_type(mtmp) == nid | |
405 | /* | |
406 | * Workaround for broken implementations that use signature | |
407 | * algorithm OID instead of digest. | |
408 | */ | |
409 | || EVP_MD_pkey_type(EVP_MD_CTX_md(mtmp)) == nid) { | |
410 | EVP_MD_CTX_copy_ex(mctx, mtmp); | |
411 | return 1; | |
412 | } | |
413 | chain = BIO_next(chain); | |
414 | } | |
415 | } | |
416 | ||
417 | static STACK_OF(CMS_CertificateChoices) | |
418 | **cms_get0_certificate_choices(CMS_ContentInfo *cms) | |
419 | { | |
420 | switch (OBJ_obj2nid(cms->contentType)) { | |
421 | ||
422 | case NID_pkcs7_signed: | |
423 | return &cms->d.signedData->certificates; | |
424 | ||
425 | case NID_pkcs7_enveloped: | |
426 | return &cms->d.envelopedData->originatorInfo->certificates; | |
427 | ||
428 | default: | |
429 | CMSerr(CMS_F_CMS_GET0_CERTIFICATE_CHOICES, | |
430 | CMS_R_UNSUPPORTED_CONTENT_TYPE); | |
431 | return NULL; | |
432 | ||
433 | } | |
434 | } | |
94b2c29f DSH |
435 | |
436 | CMS_CertificateChoices *CMS_add0_CertificateChoices(CMS_ContentInfo *cms) | |
40720ce3 MC |
437 | { |
438 | STACK_OF(CMS_CertificateChoices) **pcerts; | |
439 | CMS_CertificateChoices *cch; | |
440 | pcerts = cms_get0_certificate_choices(cms); | |
441 | if (!pcerts) | |
442 | return NULL; | |
443 | if (!*pcerts) | |
444 | *pcerts = sk_CMS_CertificateChoices_new_null(); | |
445 | if (!*pcerts) | |
446 | return NULL; | |
447 | cch = M_ASN1_new_of(CMS_CertificateChoices); | |
448 | if (!cch) | |
449 | return NULL; | |
450 | if (!sk_CMS_CertificateChoices_push(*pcerts, cch)) { | |
451 | M_ASN1_free_of(cch, CMS_CertificateChoices); | |
452 | return NULL; | |
453 | } | |
454 | return cch; | |
455 | } | |
94b2c29f DSH |
456 | |
457 | int CMS_add0_cert(CMS_ContentInfo *cms, X509 *cert) | |
40720ce3 MC |
458 | { |
459 | CMS_CertificateChoices *cch; | |
460 | STACK_OF(CMS_CertificateChoices) **pcerts; | |
461 | int i; | |
462 | pcerts = cms_get0_certificate_choices(cms); | |
463 | if (!pcerts) | |
464 | return 0; | |
465 | for (i = 0; i < sk_CMS_CertificateChoices_num(*pcerts); i++) { | |
466 | cch = sk_CMS_CertificateChoices_value(*pcerts, i); | |
467 | if (cch->type == CMS_CERTCHOICE_CERT) { | |
468 | if (!X509_cmp(cch->d.certificate, cert)) { | |
469 | CMSerr(CMS_F_CMS_ADD0_CERT, | |
470 | CMS_R_CERTIFICATE_ALREADY_PRESENT); | |
471 | return 0; | |
472 | } | |
473 | } | |
474 | } | |
475 | cch = CMS_add0_CertificateChoices(cms); | |
476 | if (!cch) | |
477 | return 0; | |
478 | cch->type = CMS_CERTCHOICE_CERT; | |
479 | cch->d.certificate = cert; | |
480 | return 1; | |
481 | } | |
94b2c29f DSH |
482 | |
483 | int CMS_add1_cert(CMS_ContentInfo *cms, X509 *cert) | |
40720ce3 MC |
484 | { |
485 | int r; | |
486 | r = CMS_add0_cert(cms, cert); | |
487 | if (r > 0) | |
488 | CRYPTO_add(&cert->references, 1, CRYPTO_LOCK_X509); | |
489 | return r; | |
490 | } | |
94b2c29f | 491 | |
40720ce3 MC |
492 | static STACK_OF(CMS_RevocationInfoChoice) |
493 | **cms_get0_revocation_choices(CMS_ContentInfo *cms) | |
494 | { | |
495 | switch (OBJ_obj2nid(cms->contentType)) { | |
94b2c29f | 496 | |
40720ce3 MC |
497 | case NID_pkcs7_signed: |
498 | return &cms->d.signedData->crls; | |
94b2c29f | 499 | |
40720ce3 MC |
500 | case NID_pkcs7_enveloped: |
501 | return &cms->d.envelopedData->originatorInfo->crls; | |
94b2c29f | 502 | |
40720ce3 MC |
503 | default: |
504 | CMSerr(CMS_F_CMS_GET0_REVOCATION_CHOICES, | |
505 | CMS_R_UNSUPPORTED_CONTENT_TYPE); | |
506 | return NULL; | |
94b2c29f | 507 | |
40720ce3 MC |
508 | } |
509 | } | |
94b2c29f DSH |
510 | |
511 | CMS_RevocationInfoChoice *CMS_add0_RevocationInfoChoice(CMS_ContentInfo *cms) | |
40720ce3 MC |
512 | { |
513 | STACK_OF(CMS_RevocationInfoChoice) **pcrls; | |
514 | CMS_RevocationInfoChoice *rch; | |
515 | pcrls = cms_get0_revocation_choices(cms); | |
516 | if (!pcrls) | |
517 | return NULL; | |
518 | if (!*pcrls) | |
519 | *pcrls = sk_CMS_RevocationInfoChoice_new_null(); | |
520 | if (!*pcrls) | |
521 | return NULL; | |
522 | rch = M_ASN1_new_of(CMS_RevocationInfoChoice); | |
523 | if (!rch) | |
524 | return NULL; | |
525 | if (!sk_CMS_RevocationInfoChoice_push(*pcrls, rch)) { | |
526 | M_ASN1_free_of(rch, CMS_RevocationInfoChoice); | |
527 | return NULL; | |
528 | } | |
529 | return rch; | |
530 | } | |
94b2c29f DSH |
531 | |
532 | int CMS_add0_crl(CMS_ContentInfo *cms, X509_CRL *crl) | |
40720ce3 MC |
533 | { |
534 | CMS_RevocationInfoChoice *rch; | |
535 | rch = CMS_add0_RevocationInfoChoice(cms); | |
536 | if (!rch) | |
537 | return 0; | |
538 | rch->type = CMS_REVCHOICE_CRL; | |
539 | rch->d.crl = crl; | |
540 | return 1; | |
541 | } | |
94b2c29f DSH |
542 | |
543 | STACK_OF(X509) *CMS_get1_certs(CMS_ContentInfo *cms) | |
40720ce3 MC |
544 | { |
545 | STACK_OF(X509) *certs = NULL; | |
546 | CMS_CertificateChoices *cch; | |
547 | STACK_OF(CMS_CertificateChoices) **pcerts; | |
548 | int i; | |
549 | pcerts = cms_get0_certificate_choices(cms); | |
550 | if (!pcerts) | |
551 | return NULL; | |
552 | for (i = 0; i < sk_CMS_CertificateChoices_num(*pcerts); i++) { | |
553 | cch = sk_CMS_CertificateChoices_value(*pcerts, i); | |
554 | if (cch->type == 0) { | |
555 | if (!certs) { | |
556 | certs = sk_X509_new_null(); | |
557 | if (!certs) | |
558 | return NULL; | |
559 | } | |
560 | if (!sk_X509_push(certs, cch->d.certificate)) { | |
561 | sk_X509_pop_free(certs, X509_free); | |
562 | return NULL; | |
563 | } | |
564 | CRYPTO_add(&cch->d.certificate->references, 1, CRYPTO_LOCK_X509); | |
565 | } | |
566 | } | |
567 | return certs; | |
568 | ||
569 | } | |
94b2c29f DSH |
570 | |
571 | STACK_OF(X509_CRL) *CMS_get1_crls(CMS_ContentInfo *cms) | |
40720ce3 MC |
572 | { |
573 | STACK_OF(X509_CRL) *crls = NULL; | |
574 | STACK_OF(CMS_RevocationInfoChoice) **pcrls; | |
575 | CMS_RevocationInfoChoice *rch; | |
576 | int i; | |
577 | pcrls = cms_get0_revocation_choices(cms); | |
578 | if (!pcrls) | |
579 | return NULL; | |
580 | for (i = 0; i < sk_CMS_RevocationInfoChoice_num(*pcrls); i++) { | |
581 | rch = sk_CMS_RevocationInfoChoice_value(*pcrls, i); | |
582 | if (rch->type == 0) { | |
583 | if (!crls) { | |
584 | crls = sk_X509_CRL_new_null(); | |
585 | if (!crls) | |
586 | return NULL; | |
587 | } | |
588 | if (!sk_X509_CRL_push(crls, rch->d.crl)) { | |
589 | sk_X509_CRL_pop_free(crls, X509_CRL_free); | |
590 | return NULL; | |
591 | } | |
592 | CRYPTO_add(&rch->d.crl->references, 1, CRYPTO_LOCK_X509_CRL); | |
593 | } | |
594 | } | |
595 | return crls; | |
596 | } |