cms_lib.c revision 183234
1240116Smarcel/* crypto/cms/cms_lib.c */
2240116Smarcel/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
3240116Smarcel * project.
4240116Smarcel */
5240116Smarcel/* ====================================================================
6240116Smarcel * Copyright (c) 2008 The OpenSSL Project.  All rights reserved.
7240116Smarcel *
8240116Smarcel * Redistribution and use in source and binary forms, with or without
9240116Smarcel * modification, are permitted provided that the following conditions
10240116Smarcel * are met:
11240116Smarcel *
12240116Smarcel * 1. Redistributions of source code must retain the above copyright
13240116Smarcel *    notice, this list of conditions and the following disclaimer.
14240116Smarcel *
15240116Smarcel * 2. Redistributions in binary form must reproduce the above copyright
16240116Smarcel *    notice, this list of conditions and the following disclaimer in
17240116Smarcel *    the documentation and/or other materials provided with the
18240116Smarcel *    distribution.
19240116Smarcel *
20240116Smarcel * 3. All advertising materials mentioning features or use of this
21240116Smarcel *    software must display the following acknowledgment:
22240116Smarcel *    "This product includes software developed by the OpenSSL Project
23240116Smarcel *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
24240116Smarcel *
25240116Smarcel * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
26273929Sjmmv *    endorse or promote products derived from this software without
27273929Sjmmv *    prior written permission. For written permission, please contact
28240116Smarcel *    licensing@OpenSSL.org.
29240116Smarcel *
30240116Smarcel * 5. Products derived from this software may not be called "OpenSSL"
31240116Smarcel *    nor may "OpenSSL" appear in their names without prior written
32240116Smarcel *    permission of the OpenSSL Project.
33240116Smarcel *
34240116Smarcel * 6. Redistributions of any form whatsoever must retain the following
35240116Smarcel *    acknowledgment:
36240116Smarcel *    "This product includes software developed by the OpenSSL Project
37240116Smarcel *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
38240116Smarcel *
39240116Smarcel * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
40240116Smarcel * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
41273929Sjmmv * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
42240116Smarcel * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
43240116Smarcel * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
44240116Smarcel * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
45240116Smarcel * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
46240116Smarcel * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47240116Smarcel * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
48240116Smarcel * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
49240116Smarcel * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
50240116Smarcel * OF THE POSSIBILITY OF SUCH DAMAGE.
51240116Smarcel * ====================================================================
52240116Smarcel */
53240116Smarcel
54240116Smarcel#include <openssl/asn1t.h>
55240116Smarcel#include <openssl/x509.h>
56240116Smarcel#include <openssl/err.h>
57240116Smarcel#include <openssl/pem.h>
58240116Smarcel#include <openssl/bio.h>
59240116Smarcel#include <openssl/asn1.h>
60240116Smarcel#include "cms.h"
61240116Smarcel#include "cms_lcl.h"
62240116Smarcel
63240116SmarcelIMPLEMENT_ASN1_FUNCTIONS_const(CMS_ContentInfo)
64240116Smarcel
65240116SmarcelDECLARE_ASN1_ITEM(CMS_CertificateChoices)
66240116SmarcelDECLARE_ASN1_ITEM(CMS_RevocationInfoChoice)
67240116SmarcelDECLARE_STACK_OF(CMS_CertificateChoices)
68240116SmarcelDECLARE_STACK_OF(CMS_RevocationInfoChoice)
69240116Smarcel
70240116Smarcelconst ASN1_OBJECT *CMS_get0_type(CMS_ContentInfo *cms)
71240116Smarcel	{
72240116Smarcel	return cms->contentType;
73240116Smarcel	}
74240116Smarcel
75240116SmarcelCMS_ContentInfo *cms_Data_create(void)
76240116Smarcel	{
77240116Smarcel	CMS_ContentInfo *cms;
78240116Smarcel	cms = CMS_ContentInfo_new();
79240116Smarcel	if (cms)
80240116Smarcel		{
81240116Smarcel		cms->contentType = OBJ_nid2obj(NID_pkcs7_data);
82240116Smarcel		/* Never detached */
83240116Smarcel		CMS_set_detached(cms, 0);
84240116Smarcel		}
85240116Smarcel	return cms;
86240116Smarcel	}
87240116Smarcel
88240116SmarcelBIO *cms_content_bio(CMS_ContentInfo *cms)
89240116Smarcel	{
90240116Smarcel	ASN1_OCTET_STRING **pos = CMS_get0_content(cms);
91240116Smarcel	if (!pos)
92240116Smarcel		return NULL;
93240116Smarcel	/* If content detached data goes nowhere: create NULL BIO */
94240116Smarcel	if (!*pos)
95240116Smarcel		return BIO_new(BIO_s_null());
96240116Smarcel	/* If content not detached and created return memory BIO
97240116Smarcel	 */
98240116Smarcel	if (!*pos || ((*pos)->flags == ASN1_STRING_FLAG_CONT))
99240116Smarcel		return BIO_new(BIO_s_mem());
100240116Smarcel	/* Else content was read in: return read only BIO for it */
101240116Smarcel	return BIO_new_mem_buf((*pos)->data, (*pos)->length);
102240116Smarcel	}
103240116Smarcel
104240116SmarcelBIO *CMS_dataInit(CMS_ContentInfo *cms, BIO *icont)
105240116Smarcel	{
106240116Smarcel	BIO *cmsbio, *cont;
107240116Smarcel	if (icont)
108240116Smarcel		cont = icont;
109240116Smarcel	else
110240116Smarcel		cont = cms_content_bio(cms);
111240116Smarcel	if (!cont)
112240116Smarcel		{
113240116Smarcel		CMSerr(CMS_F_CMS_DATAINIT, CMS_R_NO_CONTENT);
114240116Smarcel		return NULL;
115240116Smarcel		}
116240116Smarcel	switch (OBJ_obj2nid(cms->contentType))
117240116Smarcel		{
118240116Smarcel
119240116Smarcel		case NID_pkcs7_data:
120240116Smarcel		return cont;
121240116Smarcel
122240116Smarcel		case NID_pkcs7_signed:
123240116Smarcel		cmsbio = cms_SignedData_init_bio(cms);
124240116Smarcel		break;
125240116Smarcel
126240116Smarcel		case NID_pkcs7_digest:
127240116Smarcel		cmsbio = cms_DigestedData_init_bio(cms);
128240116Smarcel		break;
129240116Smarcel#ifdef ZLIB
130240116Smarcel		case NID_id_smime_ct_compressedData:
131240116Smarcel		cmsbio = cms_CompressedData_init_bio(cms);
132240116Smarcel		break;
133240116Smarcel#endif
134240116Smarcel
135240116Smarcel		case NID_pkcs7_encrypted:
136240116Smarcel		cmsbio = cms_EncryptedData_init_bio(cms);
137240116Smarcel		break;
138240116Smarcel
139240116Smarcel		case NID_pkcs7_enveloped:
140240116Smarcel		cmsbio = cms_EnvelopedData_init_bio(cms);
141240116Smarcel		break;
142240116Smarcel
143240116Smarcel		default:
144240116Smarcel		CMSerr(CMS_F_CMS_DATAINIT, CMS_R_UNSUPPORTED_TYPE);
145240116Smarcel		return NULL;
146240116Smarcel		}
147240116Smarcel
148240116Smarcel	if (cmsbio)
149240116Smarcel		return BIO_push(cmsbio, cont);
150240116Smarcel
151240116Smarcel	if (!icont)
152240116Smarcel		BIO_free(cont);
153240116Smarcel	return NULL;
154240116Smarcel
155240116Smarcel	}
156240116Smarcel
157240116Smarcelint CMS_dataFinal(CMS_ContentInfo *cms, BIO *cmsbio)
158240116Smarcel	{
159240116Smarcel	ASN1_OCTET_STRING **pos = CMS_get0_content(cms);
160240116Smarcel	if (!pos)
161240116Smarcel		return 0;
162240116Smarcel	/* If ebmedded content find memory BIO and set content */
163240116Smarcel	if (*pos && ((*pos)->flags & ASN1_STRING_FLAG_CONT))
164240116Smarcel		{
165240116Smarcel		BIO *mbio;
166240116Smarcel		unsigned char *cont;
167240116Smarcel		long contlen;
168240116Smarcel		mbio = BIO_find_type(cmsbio, BIO_TYPE_MEM);
169240116Smarcel		if (!mbio)
170240116Smarcel			{
171240116Smarcel			CMSerr(CMS_F_CMS_DATAFINAL, CMS_R_CONTENT_NOT_FOUND);
172240116Smarcel			return 0;
173240116Smarcel			}
174240116Smarcel		contlen = BIO_get_mem_data(mbio, &cont);
175240116Smarcel		/* Set bio as read only so its content can't be clobbered */
176240116Smarcel		BIO_set_flags(mbio, BIO_FLAGS_MEM_RDONLY);
177240116Smarcel		BIO_set_mem_eof_return(mbio, 0);
178240116Smarcel		ASN1_STRING_set0(*pos, cont, contlen);
179240116Smarcel		(*pos)->flags &= ~ASN1_STRING_FLAG_CONT;
180240116Smarcel		}
181240116Smarcel
182240116Smarcel	switch (OBJ_obj2nid(cms->contentType))
183240116Smarcel		{
184240116Smarcel
185240116Smarcel		case NID_pkcs7_data:
186240116Smarcel		case NID_pkcs7_enveloped:
187240116Smarcel		case NID_pkcs7_encrypted:
188240116Smarcel		case NID_id_smime_ct_compressedData:
189240116Smarcel		/* Nothing to do */
190240116Smarcel		return 1;
191240116Smarcel
192240116Smarcel		case NID_pkcs7_signed:
193240116Smarcel		return cms_SignedData_final(cms, cmsbio);
194240116Smarcel
195240116Smarcel		case NID_pkcs7_digest:
196240116Smarcel		return cms_DigestedData_do_final(cms, cmsbio, 0);
197240116Smarcel
198240116Smarcel		default:
199240116Smarcel		CMSerr(CMS_F_CMS_DATAFINAL, CMS_R_UNSUPPORTED_TYPE);
200240116Smarcel		return 0;
201240116Smarcel		}
202240116Smarcel	}
203240116Smarcel
204240116Smarcel/* Return an OCTET STRING pointer to content. This allows it to
205240116Smarcel * be accessed or set later.
206240116Smarcel */
207240116Smarcel
208240116SmarcelASN1_OCTET_STRING **CMS_get0_content(CMS_ContentInfo *cms)
209240116Smarcel	{
210240116Smarcel	switch (OBJ_obj2nid(cms->contentType))
211240116Smarcel		{
212240116Smarcel
213240116Smarcel		case NID_pkcs7_data:
214240116Smarcel		return &cms->d.data;
215240116Smarcel
216240116Smarcel		case NID_pkcs7_signed:
217240116Smarcel		return &cms->d.signedData->encapContentInfo->eContent;
218240116Smarcel
219240116Smarcel		case NID_pkcs7_enveloped:
220240116Smarcel		return &cms->d.envelopedData->encryptedContentInfo->encryptedContent;
221240116Smarcel
222240116Smarcel		case NID_pkcs7_digest:
223240116Smarcel		return &cms->d.digestedData->encapContentInfo->eContent;
224240116Smarcel
225240116Smarcel		case NID_pkcs7_encrypted:
226240116Smarcel		return &cms->d.encryptedData->encryptedContentInfo->encryptedContent;
227240116Smarcel
228240116Smarcel		case NID_id_smime_ct_authData:
229240116Smarcel		return &cms->d.authenticatedData->encapContentInfo->eContent;
230240116Smarcel
231240116Smarcel		case NID_id_smime_ct_compressedData:
232240116Smarcel		return &cms->d.compressedData->encapContentInfo->eContent;
233240116Smarcel
234240116Smarcel		default:
235240116Smarcel		if (cms->d.other->type == V_ASN1_OCTET_STRING)
236240116Smarcel			return &cms->d.other->value.octet_string;
237240116Smarcel		CMSerr(CMS_F_CMS_GET0_CONTENT, CMS_R_UNSUPPORTED_CONTENT_TYPE);
238240116Smarcel		return NULL;
239240116Smarcel
240240116Smarcel		}
241240116Smarcel	}
242240116Smarcel
243240116Smarcel/* Return an ASN1_OBJECT pointer to content type. This allows it to
244240116Smarcel * be accessed or set later.
245240116Smarcel */
246240116Smarcel
247240116Smarcelstatic ASN1_OBJECT **cms_get0_econtent_type(CMS_ContentInfo *cms)
248240116Smarcel	{
249240116Smarcel	switch (OBJ_obj2nid(cms->contentType))
250240116Smarcel		{
251240116Smarcel
252240116Smarcel		case NID_pkcs7_signed:
253240116Smarcel		return &cms->d.signedData->encapContentInfo->eContentType;
254240116Smarcel
255240116Smarcel		case NID_pkcs7_enveloped:
256240116Smarcel		return &cms->d.envelopedData->encryptedContentInfo->contentType;
257240116Smarcel
258240116Smarcel		case NID_pkcs7_digest:
259240116Smarcel		return &cms->d.digestedData->encapContentInfo->eContentType;
260240116Smarcel
261240116Smarcel		case NID_pkcs7_encrypted:
262240116Smarcel		return &cms->d.encryptedData->encryptedContentInfo->contentType;
263240116Smarcel
264240116Smarcel		case NID_id_smime_ct_authData:
265240116Smarcel		return &cms->d.authenticatedData->encapContentInfo->eContentType;
266240116Smarcel
267240116Smarcel		case NID_id_smime_ct_compressedData:
268240116Smarcel		return &cms->d.compressedData->encapContentInfo->eContentType;
269240116Smarcel
270240116Smarcel		default:
271240116Smarcel		CMSerr(CMS_F_CMS_GET0_ECONTENT_TYPE,
272240116Smarcel					CMS_R_UNSUPPORTED_CONTENT_TYPE);
273240116Smarcel		return NULL;
274240116Smarcel
275240116Smarcel		}
276240116Smarcel	}
277240116Smarcel
278240116Smarcelconst ASN1_OBJECT *CMS_get0_eContentType(CMS_ContentInfo *cms)
279240116Smarcel	{
280240116Smarcel	ASN1_OBJECT **petype;
281240116Smarcel	petype = cms_get0_econtent_type(cms);
282240116Smarcel	if (petype)
283240116Smarcel		return *petype;
284240116Smarcel	return NULL;
285240116Smarcel	}
286240116Smarcel
287240116Smarcelint CMS_set1_eContentType(CMS_ContentInfo *cms, const ASN1_OBJECT *oid)
288240116Smarcel	{
289240116Smarcel	ASN1_OBJECT **petype, *etype;
290240116Smarcel	petype = cms_get0_econtent_type(cms);
291240116Smarcel	if (!petype)
292240116Smarcel		return 0;
293240116Smarcel	if (!oid)
294240116Smarcel		return 1;
295240116Smarcel	etype = OBJ_dup(oid);
296240116Smarcel	if (!etype)
297240116Smarcel		return 0;
298240116Smarcel	ASN1_OBJECT_free(*petype);
299240116Smarcel	*petype = etype;
300240116Smarcel	return 1;
301240116Smarcel	}
302240116Smarcel
303240116Smarcelint CMS_is_detached(CMS_ContentInfo *cms)
304240116Smarcel	{
305240116Smarcel	ASN1_OCTET_STRING **pos;
306240116Smarcel	pos = CMS_get0_content(cms);
307240116Smarcel	if (!pos)
308240116Smarcel		return -1;
309240116Smarcel	if (*pos)
310240116Smarcel		return 0;
311240116Smarcel	return 1;
312240116Smarcel	}
313240116Smarcel
314240116Smarcelint CMS_set_detached(CMS_ContentInfo *cms, int detached)
315240116Smarcel	{
316240116Smarcel	ASN1_OCTET_STRING **pos;
317240116Smarcel	pos = CMS_get0_content(cms);
318240116Smarcel	if (!pos)
319240116Smarcel		return 0;
320240116Smarcel	if (detached)
321240116Smarcel		{
322240116Smarcel		if (*pos)
323240116Smarcel			{
324240116Smarcel			ASN1_OCTET_STRING_free(*pos);
325240116Smarcel			*pos = NULL;
326240116Smarcel			}
327240116Smarcel		return 1;
328240116Smarcel		}
329240116Smarcel	if (!*pos)
330240116Smarcel		*pos = ASN1_OCTET_STRING_new();
331240116Smarcel	if (*pos)
332240116Smarcel		{
333240116Smarcel		/* NB: special flag to show content is created and not
334240116Smarcel		 * read in.
335240116Smarcel		 */
336240116Smarcel		(*pos)->flags |= ASN1_STRING_FLAG_CONT;
337240116Smarcel		return 1;
338240116Smarcel		}
339240116Smarcel	CMSerr(CMS_F_CMS_SET_DETACHED, ERR_R_MALLOC_FAILURE);
340240116Smarcel	return 0;
341240116Smarcel	}
342240116Smarcel
343240116Smarcel/* Set up an X509_ALGOR DigestAlgorithmIdentifier from an EVP_MD */
344240116Smarcel
345240116Smarcelvoid cms_DigestAlgorithm_set(X509_ALGOR *alg, const EVP_MD *md)
346240116Smarcel	{
347240116Smarcel	int param_type;
348240116Smarcel
349240116Smarcel	switch (EVP_MD_type(md))
350240116Smarcel		{
351240116Smarcel		case NID_sha1:
352240116Smarcel		case NID_sha224:
353240116Smarcel		case NID_sha256:
354240116Smarcel		case NID_sha384:
355240116Smarcel		case NID_sha512:
356240116Smarcel		param_type = V_ASN1_UNDEF;
357240116Smarcel		break;
358240116Smarcel
359240116Smarcel		default:
360240116Smarcel		param_type = V_ASN1_NULL;
361240116Smarcel		break;
362240116Smarcel		}
363240116Smarcel
364240116Smarcel	X509_ALGOR_set0(alg, OBJ_nid2obj(EVP_MD_type(md)), param_type, NULL);
365240116Smarcel
366240116Smarcel	}
367240116Smarcel
368240116Smarcel/* Create a digest BIO from an X509_ALGOR structure */
369240116Smarcel
370240116SmarcelBIO *cms_DigestAlgorithm_init_bio(X509_ALGOR *digestAlgorithm)
371240116Smarcel	{
372240116Smarcel	BIO *mdbio = NULL;
373240116Smarcel	ASN1_OBJECT *digestoid;
374240116Smarcel	const EVP_MD *digest;
375240116Smarcel	X509_ALGOR_get0(&digestoid, NULL, NULL, digestAlgorithm);
376240116Smarcel	digest = EVP_get_digestbyobj(digestoid);
377240116Smarcel	if (!digest)
378240116Smarcel		{
379240116Smarcel		CMSerr(CMS_F_CMS_DIGESTALGORITHM_INIT_BIO,
380240116Smarcel				CMS_R_UNKNOWN_DIGEST_ALGORIHM);
381240116Smarcel		goto err;
382240116Smarcel		}
383240116Smarcel	mdbio = BIO_new(BIO_f_md());
384240116Smarcel	if (!mdbio || !BIO_set_md(mdbio, digest))
385240116Smarcel		{
386240116Smarcel		CMSerr(CMS_F_CMS_DIGESTALGORITHM_INIT_BIO,
387273929Sjmmv				CMS_R_MD_BIO_INIT_ERROR);
388		goto err;
389		}
390	return mdbio;
391	err:
392	if (mdbio)
393		BIO_free(mdbio);
394	return NULL;
395	}
396
397/* Locate a message digest content from a BIO chain based on SignerInfo */
398
399int cms_DigestAlgorithm_find_ctx(EVP_MD_CTX *mctx, BIO *chain,
400					X509_ALGOR *mdalg)
401	{
402	int nid;
403	ASN1_OBJECT *mdoid;
404	X509_ALGOR_get0(&mdoid, NULL, NULL, mdalg);
405	nid = OBJ_obj2nid(mdoid);
406	/* Look for digest type to match signature */
407	for (;;)
408		{
409		EVP_MD_CTX *mtmp;
410		chain = BIO_find_type(chain, BIO_TYPE_MD);
411		if (chain == NULL)
412			{
413			CMSerr(CMS_F_CMS_DIGESTALGORITHM_FIND_CTX,
414						CMS_R_NO_MATCHING_DIGEST);
415			return 0;
416			}
417		BIO_get_md_ctx(chain, &mtmp);
418		if (EVP_MD_CTX_type(mtmp) == nid)
419			{
420			EVP_MD_CTX_copy_ex(mctx, mtmp);
421			return 1;
422			}
423		chain = BIO_next(chain);
424		}
425	}
426
427static STACK_OF(CMS_CertificateChoices) **cms_get0_certificate_choices(CMS_ContentInfo *cms)
428	{
429	switch (OBJ_obj2nid(cms->contentType))
430		{
431
432		case NID_pkcs7_signed:
433		return &cms->d.signedData->certificates;
434
435		case NID_pkcs7_enveloped:
436		return &cms->d.envelopedData->originatorInfo->certificates;
437
438		default:
439		CMSerr(CMS_F_CMS_GET0_CERTIFICATE_CHOICES,
440					CMS_R_UNSUPPORTED_CONTENT_TYPE);
441		return NULL;
442
443		}
444	}
445
446CMS_CertificateChoices *CMS_add0_CertificateChoices(CMS_ContentInfo *cms)
447	{
448	STACK_OF(CMS_CertificateChoices) **pcerts;
449	CMS_CertificateChoices *cch;
450	pcerts = cms_get0_certificate_choices(cms);
451	if (!pcerts)
452		return NULL;
453	if (!*pcerts)
454		*pcerts = sk_CMS_CertificateChoices_new_null();
455	if (!*pcerts)
456		return NULL;
457	cch = M_ASN1_new_of(CMS_CertificateChoices);
458	if (!cch)
459		return NULL;
460	if (!sk_CMS_CertificateChoices_push(*pcerts, cch))
461		{
462		M_ASN1_free_of(cch, CMS_CertificateChoices);
463		return NULL;
464		}
465	return cch;
466	}
467
468int CMS_add0_cert(CMS_ContentInfo *cms, X509 *cert)
469	{
470	CMS_CertificateChoices *cch;
471	STACK_OF(CMS_CertificateChoices) **pcerts;
472	int i;
473	pcerts = cms_get0_certificate_choices(cms);
474	if (!pcerts)
475		return 0;
476	if (!pcerts)
477		return 0;
478	for (i = 0; i < sk_CMS_CertificateChoices_num(*pcerts); i++)
479		{
480		cch = sk_CMS_CertificateChoices_value(*pcerts, i);
481		if (cch->type == CMS_CERTCHOICE_CERT)
482			{
483			if (!X509_cmp(cch->d.certificate, cert))
484				{
485				CMSerr(CMS_F_CMS_ADD0_CERT,
486					CMS_R_CERTIFICATE_ALREADY_PRESENT);
487				return 0;
488				}
489			}
490		}
491	cch = CMS_add0_CertificateChoices(cms);
492	if (!cch)
493		return 0;
494	cch->type = CMS_CERTCHOICE_CERT;
495	cch->d.certificate = cert;
496	return 1;
497	}
498
499int CMS_add1_cert(CMS_ContentInfo *cms, X509 *cert)
500	{
501	int r;
502	r = CMS_add0_cert(cms, cert);
503	if (r > 0)
504		CRYPTO_add(&cert->references, 1, CRYPTO_LOCK_X509);
505	return r;
506	}
507
508static STACK_OF(CMS_RevocationInfoChoice) **cms_get0_revocation_choices(CMS_ContentInfo *cms)
509	{
510	switch (OBJ_obj2nid(cms->contentType))
511		{
512
513		case NID_pkcs7_signed:
514		return &cms->d.signedData->crls;
515
516		case NID_pkcs7_enveloped:
517		return &cms->d.envelopedData->originatorInfo->crls;
518
519		default:
520		CMSerr(CMS_F_CMS_GET0_REVOCATION_CHOICES,
521					CMS_R_UNSUPPORTED_CONTENT_TYPE);
522		return NULL;
523
524		}
525	}
526
527CMS_RevocationInfoChoice *CMS_add0_RevocationInfoChoice(CMS_ContentInfo *cms)
528	{
529	STACK_OF(CMS_RevocationInfoChoice) **pcrls;
530	CMS_RevocationInfoChoice *rch;
531	pcrls = cms_get0_revocation_choices(cms);
532	if (!pcrls)
533		return NULL;
534	if (!*pcrls)
535		*pcrls = sk_CMS_RevocationInfoChoice_new_null();
536	if (!*pcrls)
537		return NULL;
538	rch = M_ASN1_new_of(CMS_RevocationInfoChoice);
539	if (!rch)
540		return NULL;
541	if (!sk_CMS_RevocationInfoChoice_push(*pcrls, rch))
542		{
543		M_ASN1_free_of(rch, CMS_RevocationInfoChoice);
544		return NULL;
545		}
546	return rch;
547	}
548
549int CMS_add0_crl(CMS_ContentInfo *cms, X509_CRL *crl)
550	{
551	CMS_RevocationInfoChoice *rch;
552	rch = CMS_add0_RevocationInfoChoice(cms);
553	if (!rch)
554		return 0;
555	rch->type = CMS_REVCHOICE_CRL;
556	rch->d.crl = crl;
557	return 1;
558	}
559
560STACK_OF(X509) *CMS_get1_certs(CMS_ContentInfo *cms)
561	{
562	STACK_OF(X509) *certs = NULL;
563	CMS_CertificateChoices *cch;
564	STACK_OF(CMS_CertificateChoices) **pcerts;
565	int i;
566	pcerts = cms_get0_certificate_choices(cms);
567	if (!pcerts)
568		return NULL;
569	for (i = 0; i < sk_CMS_CertificateChoices_num(*pcerts); i++)
570		{
571		cch = sk_CMS_CertificateChoices_value(*pcerts, i);
572		if (cch->type == 0)
573			{
574			if (!certs)
575				{
576				certs = sk_X509_new_null();
577				if (!certs)
578					return NULL;
579				}
580			if (!sk_X509_push(certs, cch->d.certificate))
581				{
582				sk_X509_pop_free(certs, X509_free);
583				return NULL;
584				}
585			CRYPTO_add(&cch->d.certificate->references,
586						1, CRYPTO_LOCK_X509);
587			}
588		}
589	return certs;
590
591	}
592
593STACK_OF(X509_CRL) *CMS_get1_crls(CMS_ContentInfo *cms)
594	{
595	STACK_OF(X509_CRL) *crls = NULL;
596	STACK_OF(CMS_RevocationInfoChoice) **pcrls;
597	CMS_RevocationInfoChoice *rch;
598	int i;
599	pcrls = cms_get0_revocation_choices(cms);
600	if (!pcrls)
601		return NULL;
602	for (i = 0; i < sk_CMS_RevocationInfoChoice_num(*pcrls); i++)
603		{
604		rch = sk_CMS_RevocationInfoChoice_value(*pcrls, i);
605		if (rch->type == 0)
606			{
607			if (!crls)
608				{
609				crls = sk_X509_CRL_new_null();
610				if (!crls)
611					return NULL;
612				}
613			if (!sk_X509_CRL_push(crls, rch->d.crl))
614				{
615				sk_X509_CRL_pop_free(crls, X509_CRL_free);
616				return NULL;
617				}
618			CRYPTO_add(&rch->d.crl->references,
619						1, CRYPTO_LOCK_X509_CRL);
620			}
621		}
622	return crls;
623	}
624