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