1 /* crypto/cms/cms_lib.c */
3 * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
6 /* ====================================================================
7 * Copyright (c) 2008 The OpenSSL Project. All rights reserved.
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
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
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/)"
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.
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.
35 * 6. Redistributions of any form whatsoever must retain the following
37 * "This product includes software developed by the OpenSSL Project
38 * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
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 * ====================================================================
55 #include <openssl/asn1t.h>
56 #include <openssl/x509v3.h>
57 #include <openssl/err.h>
58 #include <openssl/pem.h>
59 #include <openssl/bio.h>
60 #include <openssl/asn1.h>
61 #include <openssl/cms.h>
64 IMPLEMENT_ASN1_FUNCTIONS(CMS_ContentInfo
)
65 IMPLEMENT_ASN1_PRINT_FUNCTION(CMS_ContentInfo
)
67 DECLARE_ASN1_ITEM(CMS_CertificateChoices
)
68 DECLARE_ASN1_ITEM(CMS_RevocationInfoChoice
)
69 DECLARE_STACK_OF(CMS_CertificateChoices
)
70 DECLARE_STACK_OF(CMS_RevocationInfoChoice
)
72 const ASN1_OBJECT
*CMS_get0_type(CMS_ContentInfo
*cms
)
74 return cms
->contentType
;
77 CMS_ContentInfo
*cms_Data_create(void)
80 cms
= CMS_ContentInfo_new();
82 cms
->contentType
= OBJ_nid2obj(NID_pkcs7_data
);
84 CMS_set_detached(cms
, 0);
89 BIO
*cms_content_bio(CMS_ContentInfo
*cms
)
91 ASN1_OCTET_STRING
**pos
= CMS_get0_content(cms
);
94 /* If content detached data goes nowhere: create NULL BIO */
96 return BIO_new(BIO_s_null());
98 * If content not detached and created return memory BIO
100 if (!*pos
|| ((*pos
)->flags
== ASN1_STRING_FLAG_CONT
))
101 return BIO_new(BIO_s_mem());
102 /* Else content was read in: return read only BIO for it */
103 return BIO_new_mem_buf((*pos
)->data
, (*pos
)->length
);
106 BIO
*CMS_dataInit(CMS_ContentInfo
*cms
, BIO
*icont
)
112 cont
= cms_content_bio(cms
);
114 CMSerr(CMS_F_CMS_DATAINIT
, CMS_R_NO_CONTENT
);
117 switch (OBJ_obj2nid(cms
->contentType
)) {
122 case NID_pkcs7_signed
:
123 cmsbio
= cms_SignedData_init_bio(cms
);
126 case NID_pkcs7_digest
:
127 cmsbio
= cms_DigestedData_init_bio(cms
);
130 case NID_id_smime_ct_compressedData
:
131 cmsbio
= cms_CompressedData_init_bio(cms
);
135 case NID_pkcs7_encrypted
:
136 cmsbio
= cms_EncryptedData_init_bio(cms
);
139 case NID_pkcs7_enveloped
:
140 cmsbio
= cms_EnvelopedData_init_bio(cms
);
144 CMSerr(CMS_F_CMS_DATAINIT
, CMS_R_UNSUPPORTED_TYPE
);
149 return BIO_push(cmsbio
, cont
);
157 int CMS_dataFinal(CMS_ContentInfo
*cms
, BIO
*cmsbio
)
159 ASN1_OCTET_STRING
**pos
= CMS_get0_content(cms
);
162 /* If ebmedded content find memory BIO and set content */
163 if (*pos
&& ((*pos
)->flags
& ASN1_STRING_FLAG_CONT
)) {
167 mbio
= BIO_find_type(cmsbio
, BIO_TYPE_MEM
);
169 CMSerr(CMS_F_CMS_DATAFINAL
, CMS_R_CONTENT_NOT_FOUND
);
172 contlen
= BIO_get_mem_data(mbio
, &cont
);
173 /* Set bio as read only so its content can't be clobbered */
174 BIO_set_flags(mbio
, BIO_FLAGS_MEM_RDONLY
);
175 BIO_set_mem_eof_return(mbio
, 0);
176 ASN1_STRING_set0(*pos
, cont
, contlen
);
177 (*pos
)->flags
&= ~ASN1_STRING_FLAG_CONT
;
180 switch (OBJ_obj2nid(cms
->contentType
)) {
183 case NID_pkcs7_enveloped
:
184 case NID_pkcs7_encrypted
:
185 case NID_id_smime_ct_compressedData
:
189 case NID_pkcs7_signed
:
190 return cms_SignedData_final(cms
, cmsbio
);
192 case NID_pkcs7_digest
:
193 return cms_DigestedData_do_final(cms
, cmsbio
, 0);
196 CMSerr(CMS_F_CMS_DATAFINAL
, CMS_R_UNSUPPORTED_TYPE
);
202 * Return an OCTET STRING pointer to content. This allows it to be accessed
206 ASN1_OCTET_STRING
**CMS_get0_content(CMS_ContentInfo
*cms
)
208 switch (OBJ_obj2nid(cms
->contentType
)) {
213 case NID_pkcs7_signed
:
214 return &cms
->d
.signedData
->encapContentInfo
->eContent
;
216 case NID_pkcs7_enveloped
:
217 return &cms
->d
.envelopedData
->encryptedContentInfo
->encryptedContent
;
219 case NID_pkcs7_digest
:
220 return &cms
->d
.digestedData
->encapContentInfo
->eContent
;
222 case NID_pkcs7_encrypted
:
223 return &cms
->d
.encryptedData
->encryptedContentInfo
->encryptedContent
;
225 case NID_id_smime_ct_authData
:
226 return &cms
->d
.authenticatedData
->encapContentInfo
->eContent
;
228 case NID_id_smime_ct_compressedData
:
229 return &cms
->d
.compressedData
->encapContentInfo
->eContent
;
232 if (cms
->d
.other
->type
== V_ASN1_OCTET_STRING
)
233 return &cms
->d
.other
->value
.octet_string
;
234 CMSerr(CMS_F_CMS_GET0_CONTENT
, CMS_R_UNSUPPORTED_CONTENT_TYPE
);
241 * Return an ASN1_OBJECT pointer to content type. This allows it to be
242 * accessed or set later.
245 static ASN1_OBJECT
**cms_get0_econtent_type(CMS_ContentInfo
*cms
)
247 switch (OBJ_obj2nid(cms
->contentType
)) {
249 case NID_pkcs7_signed
:
250 return &cms
->d
.signedData
->encapContentInfo
->eContentType
;
252 case NID_pkcs7_enveloped
:
253 return &cms
->d
.envelopedData
->encryptedContentInfo
->contentType
;
255 case NID_pkcs7_digest
:
256 return &cms
->d
.digestedData
->encapContentInfo
->eContentType
;
258 case NID_pkcs7_encrypted
:
259 return &cms
->d
.encryptedData
->encryptedContentInfo
->contentType
;
261 case NID_id_smime_ct_authData
:
262 return &cms
->d
.authenticatedData
->encapContentInfo
->eContentType
;
264 case NID_id_smime_ct_compressedData
:
265 return &cms
->d
.compressedData
->encapContentInfo
->eContentType
;
268 CMSerr(CMS_F_CMS_GET0_ECONTENT_TYPE
, CMS_R_UNSUPPORTED_CONTENT_TYPE
);
274 const ASN1_OBJECT
*CMS_get0_eContentType(CMS_ContentInfo
*cms
)
276 ASN1_OBJECT
**petype
;
277 petype
= cms_get0_econtent_type(cms
);
283 int CMS_set1_eContentType(CMS_ContentInfo
*cms
, const ASN1_OBJECT
*oid
)
285 ASN1_OBJECT
**petype
, *etype
;
286 petype
= cms_get0_econtent_type(cms
);
291 etype
= OBJ_dup(oid
);
294 ASN1_OBJECT_free(*petype
);
299 int CMS_is_detached(CMS_ContentInfo
*cms
)
301 ASN1_OCTET_STRING
**pos
;
302 pos
= CMS_get0_content(cms
);
310 int CMS_set_detached(CMS_ContentInfo
*cms
, int detached
)
312 ASN1_OCTET_STRING
**pos
;
313 pos
= CMS_get0_content(cms
);
318 ASN1_OCTET_STRING_free(*pos
);
324 *pos
= ASN1_OCTET_STRING_new();
327 * NB: special flag to show content is created and not read in.
329 (*pos
)->flags
|= ASN1_STRING_FLAG_CONT
;
332 CMSerr(CMS_F_CMS_SET_DETACHED
, ERR_R_MALLOC_FAILURE
);
336 /* Create a digest BIO from an X509_ALGOR structure */
338 BIO
*cms_DigestAlgorithm_init_bio(X509_ALGOR
*digestAlgorithm
)
341 ASN1_OBJECT
*digestoid
;
342 const EVP_MD
*digest
;
343 X509_ALGOR_get0(&digestoid
, NULL
, NULL
, digestAlgorithm
);
344 digest
= EVP_get_digestbyobj(digestoid
);
346 CMSerr(CMS_F_CMS_DIGESTALGORITHM_INIT_BIO
,
347 CMS_R_UNKNOWN_DIGEST_ALGORIHM
);
350 mdbio
= BIO_new(BIO_f_md());
351 if (!mdbio
|| !BIO_set_md(mdbio
, digest
)) {
352 CMSerr(CMS_F_CMS_DIGESTALGORITHM_INIT_BIO
, CMS_R_MD_BIO_INIT_ERROR
);
362 /* Locate a message digest content from a BIO chain based on SignerInfo */
364 int cms_DigestAlgorithm_find_ctx(EVP_MD_CTX
*mctx
, BIO
*chain
,
369 X509_ALGOR_get0(&mdoid
, NULL
, NULL
, mdalg
);
370 nid
= OBJ_obj2nid(mdoid
);
371 /* Look for digest type to match signature */
374 chain
= BIO_find_type(chain
, BIO_TYPE_MD
);
376 CMSerr(CMS_F_CMS_DIGESTALGORITHM_FIND_CTX
,
377 CMS_R_NO_MATCHING_DIGEST
);
380 BIO_get_md_ctx(chain
, &mtmp
);
381 if (EVP_MD_CTX_type(mtmp
) == nid
383 * Workaround for broken implementations that use signature
384 * algorithm OID instead of digest.
386 || EVP_MD_pkey_type(EVP_MD_CTX_md(mtmp
)) == nid
)
387 return EVP_MD_CTX_copy_ex(mctx
, mtmp
);
388 chain
= BIO_next(chain
);
392 static STACK_OF(CMS_CertificateChoices
)
393 **cms_get0_certificate_choices(CMS_ContentInfo
*cms
)
395 switch (OBJ_obj2nid(cms
->contentType
)) {
397 case NID_pkcs7_signed
:
398 return &cms
->d
.signedData
->certificates
;
400 case NID_pkcs7_enveloped
:
401 return &cms
->d
.envelopedData
->originatorInfo
->certificates
;
404 CMSerr(CMS_F_CMS_GET0_CERTIFICATE_CHOICES
,
405 CMS_R_UNSUPPORTED_CONTENT_TYPE
);
411 CMS_CertificateChoices
*CMS_add0_CertificateChoices(CMS_ContentInfo
*cms
)
413 STACK_OF(CMS_CertificateChoices
) **pcerts
;
414 CMS_CertificateChoices
*cch
;
415 pcerts
= cms_get0_certificate_choices(cms
);
419 *pcerts
= sk_CMS_CertificateChoices_new_null();
422 cch
= M_ASN1_new_of(CMS_CertificateChoices
);
425 if (!sk_CMS_CertificateChoices_push(*pcerts
, cch
)) {
426 M_ASN1_free_of(cch
, CMS_CertificateChoices
);
432 int CMS_add0_cert(CMS_ContentInfo
*cms
, X509
*cert
)
434 CMS_CertificateChoices
*cch
;
435 STACK_OF(CMS_CertificateChoices
) **pcerts
;
437 pcerts
= cms_get0_certificate_choices(cms
);
440 for (i
= 0; i
< sk_CMS_CertificateChoices_num(*pcerts
); i
++) {
441 cch
= sk_CMS_CertificateChoices_value(*pcerts
, i
);
442 if (cch
->type
== CMS_CERTCHOICE_CERT
) {
443 if (!X509_cmp(cch
->d
.certificate
, cert
)) {
444 CMSerr(CMS_F_CMS_ADD0_CERT
,
445 CMS_R_CERTIFICATE_ALREADY_PRESENT
);
450 cch
= CMS_add0_CertificateChoices(cms
);
453 cch
->type
= CMS_CERTCHOICE_CERT
;
454 cch
->d
.certificate
= cert
;
458 int CMS_add1_cert(CMS_ContentInfo
*cms
, X509
*cert
)
461 r
= CMS_add0_cert(cms
, cert
);
463 CRYPTO_add(&cert
->references
, 1, CRYPTO_LOCK_X509
);
467 static STACK_OF(CMS_RevocationInfoChoice
)
468 **cms_get0_revocation_choices(CMS_ContentInfo
*cms
)
470 switch (OBJ_obj2nid(cms
->contentType
)) {
472 case NID_pkcs7_signed
:
473 return &cms
->d
.signedData
->crls
;
475 case NID_pkcs7_enveloped
:
476 return &cms
->d
.envelopedData
->originatorInfo
->crls
;
479 CMSerr(CMS_F_CMS_GET0_REVOCATION_CHOICES
,
480 CMS_R_UNSUPPORTED_CONTENT_TYPE
);
486 CMS_RevocationInfoChoice
*CMS_add0_RevocationInfoChoice(CMS_ContentInfo
*cms
)
488 STACK_OF(CMS_RevocationInfoChoice
) **pcrls
;
489 CMS_RevocationInfoChoice
*rch
;
490 pcrls
= cms_get0_revocation_choices(cms
);
494 *pcrls
= sk_CMS_RevocationInfoChoice_new_null();
497 rch
= M_ASN1_new_of(CMS_RevocationInfoChoice
);
500 if (!sk_CMS_RevocationInfoChoice_push(*pcrls
, rch
)) {
501 M_ASN1_free_of(rch
, CMS_RevocationInfoChoice
);
507 int CMS_add0_crl(CMS_ContentInfo
*cms
, X509_CRL
*crl
)
509 CMS_RevocationInfoChoice
*rch
;
510 rch
= CMS_add0_RevocationInfoChoice(cms
);
513 rch
->type
= CMS_REVCHOICE_CRL
;
518 int CMS_add1_crl(CMS_ContentInfo
*cms
, X509_CRL
*crl
)
521 r
= CMS_add0_crl(cms
, crl
);
523 CRYPTO_add(&crl
->references
, 1, CRYPTO_LOCK_X509_CRL
);
527 STACK_OF(X509
) *CMS_get1_certs(CMS_ContentInfo
*cms
)
529 STACK_OF(X509
) *certs
= NULL
;
530 CMS_CertificateChoices
*cch
;
531 STACK_OF(CMS_CertificateChoices
) **pcerts
;
533 pcerts
= cms_get0_certificate_choices(cms
);
536 for (i
= 0; i
< sk_CMS_CertificateChoices_num(*pcerts
); i
++) {
537 cch
= sk_CMS_CertificateChoices_value(*pcerts
, i
);
538 if (cch
->type
== 0) {
540 certs
= sk_X509_new_null();
544 if (!sk_X509_push(certs
, cch
->d
.certificate
)) {
545 sk_X509_pop_free(certs
, X509_free
);
548 CRYPTO_add(&cch
->d
.certificate
->references
, 1, CRYPTO_LOCK_X509
);
555 STACK_OF(X509_CRL
) *CMS_get1_crls(CMS_ContentInfo
*cms
)
557 STACK_OF(X509_CRL
) *crls
= NULL
;
558 STACK_OF(CMS_RevocationInfoChoice
) **pcrls
;
559 CMS_RevocationInfoChoice
*rch
;
561 pcrls
= cms_get0_revocation_choices(cms
);
564 for (i
= 0; i
< sk_CMS_RevocationInfoChoice_num(*pcrls
); i
++) {
565 rch
= sk_CMS_RevocationInfoChoice_value(*pcrls
, i
);
566 if (rch
->type
== 0) {
568 crls
= sk_X509_CRL_new_null();
572 if (!sk_X509_CRL_push(crls
, rch
->d
.crl
)) {
573 sk_X509_CRL_pop_free(crls
, X509_CRL_free
);
576 CRYPTO_add(&rch
->d
.crl
->references
, 1, CRYPTO_LOCK_X509_CRL
);
582 int cms_ias_cert_cmp(CMS_IssuerAndSerialNumber
*ias
, X509
*cert
)
585 ret
= X509_NAME_cmp(ias
->issuer
, X509_get_issuer_name(cert
));
588 return ASN1_INTEGER_cmp(ias
->serialNumber
, X509_get_serialNumber(cert
));
591 int cms_keyid_cert_cmp(ASN1_OCTET_STRING
*keyid
, X509
*cert
)
593 X509_check_purpose(cert
, -1, -1);
596 return ASN1_OCTET_STRING_cmp(keyid
, cert
->skid
);
599 int cms_set1_ias(CMS_IssuerAndSerialNumber
**pias
, X509
*cert
)
601 CMS_IssuerAndSerialNumber
*ias
;
602 ias
= M_ASN1_new_of(CMS_IssuerAndSerialNumber
);
605 if (!X509_NAME_set(&ias
->issuer
, X509_get_issuer_name(cert
)))
607 if (!ASN1_STRING_copy(ias
->serialNumber
, X509_get_serialNumber(cert
)))
610 M_ASN1_free_of(*pias
, CMS_IssuerAndSerialNumber
);
615 M_ASN1_free_of(ias
, CMS_IssuerAndSerialNumber
);
616 CMSerr(CMS_F_CMS_SET1_IAS
, ERR_R_MALLOC_FAILURE
);
620 int cms_set1_keyid(ASN1_OCTET_STRING
**pkeyid
, X509
*cert
)
622 ASN1_OCTET_STRING
*keyid
= NULL
;
623 X509_check_purpose(cert
, -1, -1);
625 CMSerr(CMS_F_CMS_SET1_KEYID
, CMS_R_CERTIFICATE_HAS_NO_KEYID
);
628 keyid
= ASN1_STRING_dup(cert
->skid
);
630 CMSerr(CMS_F_CMS_SET1_KEYID
, ERR_R_MALLOC_FAILURE
);
634 ASN1_OCTET_STRING_free(*pkeyid
);