xref: /openbsd-src/lib/libcrypto/cms/cms_lib.c (revision 7a9020cd0142ffa8aefc1557149a140147228b71)
1*7a9020cdStb /* $OpenBSD: cms_lib.c,v 1.26 2024/11/01 18:53:35 tb Exp $ */
2b8b016bfSjsing /*
3f29d8588Sjsing  * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
4f29d8588Sjsing  * project.
5f29d8588Sjsing  */
6f29d8588Sjsing /* ====================================================================
7f29d8588Sjsing  * Copyright (c) 2008 The OpenSSL Project.  All rights reserved.
8b8b016bfSjsing  *
9f29d8588Sjsing  * Redistribution and use in source and binary forms, with or without
10f29d8588Sjsing  * modification, are permitted provided that the following conditions
11f29d8588Sjsing  * are met:
12f29d8588Sjsing  *
13f29d8588Sjsing  * 1. Redistributions of source code must retain the above copyright
14f29d8588Sjsing  *    notice, this list of conditions and the following disclaimer.
15f29d8588Sjsing  *
16f29d8588Sjsing  * 2. Redistributions in binary form must reproduce the above copyright
17f29d8588Sjsing  *    notice, this list of conditions and the following disclaimer in
18f29d8588Sjsing  *    the documentation and/or other materials provided with the
19f29d8588Sjsing  *    distribution.
20f29d8588Sjsing  *
21f29d8588Sjsing  * 3. All advertising materials mentioning features or use of this
22f29d8588Sjsing  *    software must display the following acknowledgment:
23f29d8588Sjsing  *    "This product includes software developed by the OpenSSL Project
24f29d8588Sjsing  *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
25f29d8588Sjsing  *
26f29d8588Sjsing  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
27f29d8588Sjsing  *    endorse or promote products derived from this software without
28f29d8588Sjsing  *    prior written permission. For written permission, please contact
29f29d8588Sjsing  *    licensing@OpenSSL.org.
30f29d8588Sjsing  *
31f29d8588Sjsing  * 5. Products derived from this software may not be called "OpenSSL"
32f29d8588Sjsing  *    nor may "OpenSSL" appear in their names without prior written
33f29d8588Sjsing  *    permission of the OpenSSL Project.
34f29d8588Sjsing  *
35f29d8588Sjsing  * 6. Redistributions of any form whatsoever must retain the following
36f29d8588Sjsing  *    acknowledgment:
37f29d8588Sjsing  *    "This product includes software developed by the OpenSSL Project
38f29d8588Sjsing  *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
39f29d8588Sjsing  *
40f29d8588Sjsing  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
41f29d8588Sjsing  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
42f29d8588Sjsing  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
43f29d8588Sjsing  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
44f29d8588Sjsing  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
45f29d8588Sjsing  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
46f29d8588Sjsing  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
47f29d8588Sjsing  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48f29d8588Sjsing  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
49f29d8588Sjsing  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
50f29d8588Sjsing  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
51f29d8588Sjsing  * OF THE POSSIBILITY OF SUCH DAMAGE.
52f29d8588Sjsing  * ====================================================================
53b8b016bfSjsing  */
54b8b016bfSjsing 
55*7a9020cdStb #include <stddef.h>
56*7a9020cdStb 
57b8b016bfSjsing #include <openssl/asn1.h>
58*7a9020cdStb #include <openssl/bio.h>
59b8b016bfSjsing #include <openssl/cms.h>
60*7a9020cdStb #include <openssl/err.h>
61*7a9020cdStb #include <openssl/evp.h>
62*7a9020cdStb #include <openssl/objects.h>
63*7a9020cdStb #include <openssl/x509.h>
64*7a9020cdStb #include <openssl/x509v3.h>
65b8b016bfSjsing 
66c9675a23Stb #include "cms_local.h"
67c9675a23Stb #include "x509_local.h"
680a940e1fSjsing 
690a940e1fSjsing CMS_ContentInfo *
700a940e1fSjsing d2i_CMS_ContentInfo(CMS_ContentInfo **a, const unsigned char **in, long len)
710a940e1fSjsing {
720a940e1fSjsing 	return (CMS_ContentInfo *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
730a940e1fSjsing 	    &CMS_ContentInfo_it);
740a940e1fSjsing }
75ead8f799Sbeck LCRYPTO_ALIAS(d2i_CMS_ContentInfo);
760a940e1fSjsing 
770a940e1fSjsing int
780a940e1fSjsing i2d_CMS_ContentInfo(CMS_ContentInfo *a, unsigned char **out)
790a940e1fSjsing {
800a940e1fSjsing 	return ASN1_item_i2d((ASN1_VALUE *)a, out, &CMS_ContentInfo_it);
810a940e1fSjsing }
82ead8f799Sbeck LCRYPTO_ALIAS(i2d_CMS_ContentInfo);
830a940e1fSjsing 
840a940e1fSjsing CMS_ContentInfo *
850a940e1fSjsing CMS_ContentInfo_new(void)
860a940e1fSjsing {
870a940e1fSjsing 	return (CMS_ContentInfo *)ASN1_item_new(&CMS_ContentInfo_it);
880a940e1fSjsing }
89ead8f799Sbeck LCRYPTO_ALIAS(CMS_ContentInfo_new);
900a940e1fSjsing 
910a940e1fSjsing void
920a940e1fSjsing CMS_ContentInfo_free(CMS_ContentInfo *a)
930a940e1fSjsing {
940a940e1fSjsing 	ASN1_item_free((ASN1_VALUE *)a, &CMS_ContentInfo_it);
950a940e1fSjsing }
96ead8f799Sbeck LCRYPTO_ALIAS(CMS_ContentInfo_free);
970a940e1fSjsing 
980a940e1fSjsing int
990a940e1fSjsing CMS_ContentInfo_print_ctx(BIO *out, CMS_ContentInfo *x, int indent, const ASN1_PCTX *pctx)
1000a940e1fSjsing {
1010a940e1fSjsing 	return ASN1_item_print(out, (ASN1_VALUE *)x, indent,
1020a940e1fSjsing 	    &CMS_ContentInfo_it, pctx);
1030a940e1fSjsing }
104ead8f799Sbeck LCRYPTO_ALIAS(CMS_ContentInfo_print_ctx);
105b8b016bfSjsing 
10672419cc7Sjsing const ASN1_OBJECT *
10772419cc7Sjsing CMS_get0_type(const CMS_ContentInfo *cms)
108b8b016bfSjsing {
109b8b016bfSjsing 	return cms->contentType;
110b8b016bfSjsing }
111ead8f799Sbeck LCRYPTO_ALIAS(CMS_get0_type);
112b8b016bfSjsing 
11372419cc7Sjsing CMS_ContentInfo *
11472419cc7Sjsing cms_Data_create(void)
115b8b016bfSjsing {
116b8b016bfSjsing 	CMS_ContentInfo *cms;
11772419cc7Sjsing 
118b8b016bfSjsing 	cms = CMS_ContentInfo_new();
119b8b016bfSjsing 	if (cms != NULL) {
120b8b016bfSjsing 		cms->contentType = OBJ_nid2obj(NID_pkcs7_data);
121b8b016bfSjsing 		/* Never detached */
122b8b016bfSjsing 		CMS_set_detached(cms, 0);
123b8b016bfSjsing 	}
124b8b016bfSjsing 	return cms;
125b8b016bfSjsing }
126b8b016bfSjsing 
12790fa8d06Stb static BIO *
12872419cc7Sjsing cms_content_bio(CMS_ContentInfo *cms)
129b8b016bfSjsing {
1303a0e71e8Stb 	ASN1_OCTET_STRING **pos;
13172419cc7Sjsing 
1323a0e71e8Stb 	if ((pos = CMS_get0_content(cms)) == NULL)
133b8b016bfSjsing 		return NULL;
1343a0e71e8Stb 
1353a0e71e8Stb 	/* If content is detached, data goes nowhere: create null BIO. */
1363a0e71e8Stb 	if (*pos == NULL)
137b8b016bfSjsing 		return BIO_new(BIO_s_null());
1383a0e71e8Stb 
1393a0e71e8Stb 	/* If content is not detached and was created, return memory BIO. */
1403a0e71e8Stb 	if ((*pos)->flags == ASN1_STRING_FLAG_CONT)
141b8b016bfSjsing 		return BIO_new(BIO_s_mem());
14272419cc7Sjsing 
1433a0e71e8Stb 	/* Else content was read in: return read-only BIO for it. */
144b8b016bfSjsing 	return BIO_new_mem_buf((*pos)->data, (*pos)->length);
145b8b016bfSjsing }
146b8b016bfSjsing 
14772419cc7Sjsing BIO *
14837128564Stb CMS_dataInit(CMS_ContentInfo *cms, BIO *in_content_bio)
149b8b016bfSjsing {
15037128564Stb 	BIO *cms_bio = NULL, *content_bio = NULL;
15172419cc7Sjsing 
15237128564Stb 	if ((content_bio = in_content_bio) == NULL)
15337128564Stb 		content_bio = cms_content_bio(cms);
15437128564Stb 	if (content_bio == NULL) {
155be6ec861Sjsing 		CMSerror(CMS_R_NO_CONTENT);
1566590b22dStb 		goto err;
157b8b016bfSjsing 	}
158b8b016bfSjsing 
15971d39bbeStb 	switch (OBJ_obj2nid(cms->contentType)) {
160b8b016bfSjsing 	case NID_pkcs7_data:
16137128564Stb 		return content_bio;
162b8b016bfSjsing 	case NID_pkcs7_signed:
16337128564Stb 		if ((cms_bio = cms_SignedData_init_bio(cms)) == NULL)
16471d39bbeStb 			goto err;
165b8b016bfSjsing 		break;
166b8b016bfSjsing 	case NID_pkcs7_digest:
16737128564Stb 		if ((cms_bio = cms_DigestedData_init_bio(cms)) == NULL)
16871d39bbeStb 			goto err;
169b8b016bfSjsing 		break;
170b8b016bfSjsing 	case NID_pkcs7_encrypted:
17137128564Stb 		if ((cms_bio = cms_EncryptedData_init_bio(cms)) == NULL)
17271d39bbeStb 			goto err;
173b8b016bfSjsing 		break;
174b8b016bfSjsing 	case NID_pkcs7_enveloped:
17537128564Stb 		if ((cms_bio = cms_EnvelopedData_init_bio(cms)) == NULL)
17671d39bbeStb 			goto err;
177b8b016bfSjsing 		break;
178b8b016bfSjsing 	default:
179be6ec861Sjsing 		CMSerror(CMS_R_UNSUPPORTED_TYPE);
1806590b22dStb 		goto err;
181b8b016bfSjsing 	}
182b8b016bfSjsing 
18337128564Stb 	return BIO_push(cms_bio, content_bio);
184b8b016bfSjsing 
1856590b22dStb  err:
18637128564Stb 	if (content_bio != in_content_bio)
18737128564Stb 		BIO_free(content_bio);
188b8b016bfSjsing 
18972419cc7Sjsing 	return NULL;
190b8b016bfSjsing }
191ead8f799Sbeck LCRYPTO_ALIAS(CMS_dataInit);
192b8b016bfSjsing 
19372419cc7Sjsing int
19472419cc7Sjsing CMS_dataFinal(CMS_ContentInfo *cms, BIO *cmsbio)
195b8b016bfSjsing {
196b8b016bfSjsing 	ASN1_OCTET_STRING **pos = CMS_get0_content(cms);
19772419cc7Sjsing 
198b8b016bfSjsing 	if (!pos)
199b8b016bfSjsing 		return 0;
200b8b016bfSjsing 	/* If embedded content find memory BIO and set content */
201b8b016bfSjsing 	if (*pos && ((*pos)->flags & ASN1_STRING_FLAG_CONT)) {
202b8b016bfSjsing 		BIO *mbio;
203b8b016bfSjsing 		unsigned char *cont;
204b8b016bfSjsing 		long contlen;
205b8b016bfSjsing 		mbio = BIO_find_type(cmsbio, BIO_TYPE_MEM);
206b8b016bfSjsing 		if (!mbio) {
207be6ec861Sjsing 			CMSerror(CMS_R_CONTENT_NOT_FOUND);
208b8b016bfSjsing 			return 0;
209b8b016bfSjsing 		}
210b8b016bfSjsing 		contlen = BIO_get_mem_data(mbio, &cont);
211b8b016bfSjsing 		/* Set bio as read only so its content can't be clobbered */
212b8b016bfSjsing 		BIO_set_flags(mbio, BIO_FLAGS_MEM_RDONLY);
213b8b016bfSjsing 		BIO_set_mem_eof_return(mbio, 0);
214b8b016bfSjsing 		ASN1_STRING_set0(*pos, cont, contlen);
215b8b016bfSjsing 		(*pos)->flags &= ~ASN1_STRING_FLAG_CONT;
216b8b016bfSjsing 	}
217b8b016bfSjsing 
218b8b016bfSjsing 	switch (OBJ_obj2nid(cms->contentType)) {
219b8b016bfSjsing 
220b8b016bfSjsing 	case NID_pkcs7_data:
221b8b016bfSjsing 	case NID_pkcs7_enveloped:
222b8b016bfSjsing 	case NID_pkcs7_encrypted:
223b8b016bfSjsing 	case NID_id_smime_ct_compressedData:
224b8b016bfSjsing 		/* Nothing to do */
225b8b016bfSjsing 		return 1;
226b8b016bfSjsing 
227b8b016bfSjsing 	case NID_pkcs7_signed:
228b8b016bfSjsing 		return cms_SignedData_final(cms, cmsbio);
229b8b016bfSjsing 
230b8b016bfSjsing 	case NID_pkcs7_digest:
231b8b016bfSjsing 		return cms_DigestedData_do_final(cms, cmsbio, 0);
232b8b016bfSjsing 
233b8b016bfSjsing 	default:
234be6ec861Sjsing 		CMSerror(CMS_R_UNSUPPORTED_TYPE);
235b8b016bfSjsing 		return 0;
236b8b016bfSjsing 	}
237b8b016bfSjsing }
238ead8f799Sbeck LCRYPTO_ALIAS(CMS_dataFinal);
239b8b016bfSjsing 
2405e651e03Stb int
2415e651e03Stb CMS_get_version(const CMS_ContentInfo *cms, long *version)
2425e651e03Stb {
2435e651e03Stb 	switch (OBJ_obj2nid(cms->contentType)) {
2445e651e03Stb 	case NID_pkcs7_signed:
2455e651e03Stb 		*version = cms->d.signedData->version;
2465e651e03Stb 		return 1;
2475e651e03Stb 
2485e651e03Stb 	case NID_pkcs7_enveloped:
2495e651e03Stb 		*version = cms->d.envelopedData->version;
2505e651e03Stb 		return 1;
2515e651e03Stb 
2525e651e03Stb 	case NID_pkcs7_digest:
2535e651e03Stb 		*version = cms->d.digestedData->version;
2545e651e03Stb 		return 1;
2555e651e03Stb 
2565e651e03Stb 	case NID_pkcs7_encrypted:
2575e651e03Stb 		*version = cms->d.encryptedData->version;
2585e651e03Stb 		return 1;
2595e651e03Stb 
2605e651e03Stb 	case NID_id_smime_ct_authData:
2615e651e03Stb 		*version = cms->d.authenticatedData->version;
2625e651e03Stb 		return 1;
2635e651e03Stb 
2645e651e03Stb 	case NID_id_smime_ct_compressedData:
2655e651e03Stb 		*version = cms->d.compressedData->version;
2665e651e03Stb 		return 1;
2675e651e03Stb 
2685e651e03Stb 	default:
2695e651e03Stb 		CMSerror(CMS_R_UNSUPPORTED_TYPE);
2705e651e03Stb 		return 0;
2715e651e03Stb 	}
2725e651e03Stb }
2735e651e03Stb LCRYPTO_ALIAS(CMS_get_version);
2745e651e03Stb 
2755e651e03Stb int
2765e651e03Stb CMS_SignerInfo_get_version(const CMS_SignerInfo *si, long *version)
2775e651e03Stb {
2785e651e03Stb 	*version = si->version;
2795e651e03Stb 	return 1;
2805e651e03Stb }
2815e651e03Stb LCRYPTO_ALIAS(CMS_SignerInfo_get_version);
2825e651e03Stb 
283b8b016bfSjsing /*
284b8b016bfSjsing  * Return an OCTET STRING pointer to content. This allows it to be accessed
285b8b016bfSjsing  * or set later.
286b8b016bfSjsing  */
287b8b016bfSjsing 
28872419cc7Sjsing ASN1_OCTET_STRING **
28972419cc7Sjsing CMS_get0_content(CMS_ContentInfo *cms)
290b8b016bfSjsing {
291b8b016bfSjsing 	switch (OBJ_obj2nid(cms->contentType)) {
292b8b016bfSjsing 	case NID_pkcs7_data:
293b8b016bfSjsing 		return &cms->d.data;
294b8b016bfSjsing 
295b8b016bfSjsing 	case NID_pkcs7_signed:
296b8b016bfSjsing 		return &cms->d.signedData->encapContentInfo->eContent;
297b8b016bfSjsing 
298b8b016bfSjsing 	case NID_pkcs7_enveloped:
299b8b016bfSjsing 		return &cms->d.envelopedData->encryptedContentInfo->encryptedContent;
300b8b016bfSjsing 
301b8b016bfSjsing 	case NID_pkcs7_digest:
302b8b016bfSjsing 		return &cms->d.digestedData->encapContentInfo->eContent;
303b8b016bfSjsing 
304b8b016bfSjsing 	case NID_pkcs7_encrypted:
305b8b016bfSjsing 		return &cms->d.encryptedData->encryptedContentInfo->encryptedContent;
306b8b016bfSjsing 
307b8b016bfSjsing 	case NID_id_smime_ct_authData:
308b8b016bfSjsing 		return &cms->d.authenticatedData->encapContentInfo->eContent;
309b8b016bfSjsing 
310b8b016bfSjsing 	case NID_id_smime_ct_compressedData:
311b8b016bfSjsing 		return &cms->d.compressedData->encapContentInfo->eContent;
312b8b016bfSjsing 
313b8b016bfSjsing 	default:
314b8b016bfSjsing 		if (cms->d.other->type == V_ASN1_OCTET_STRING)
315b8b016bfSjsing 			return &cms->d.other->value.octet_string;
316be6ec861Sjsing 		CMSerror(CMS_R_UNSUPPORTED_CONTENT_TYPE);
317b8b016bfSjsing 		return NULL;
318b8b016bfSjsing 	}
319b8b016bfSjsing }
3207bfedc82Sjoshua LCRYPTO_ALIAS(CMS_get0_content);
321b8b016bfSjsing 
322b8b016bfSjsing /*
323b8b016bfSjsing  * Return an ASN1_OBJECT pointer to content type. This allows it to be
324b8b016bfSjsing  * accessed or set later.
325b8b016bfSjsing  */
326b8b016bfSjsing 
32772419cc7Sjsing static ASN1_OBJECT **
32872419cc7Sjsing cms_get0_econtent_type(CMS_ContentInfo *cms)
329b8b016bfSjsing {
330b8b016bfSjsing 	switch (OBJ_obj2nid(cms->contentType)) {
331b8b016bfSjsing 	case NID_pkcs7_signed:
332b8b016bfSjsing 		return &cms->d.signedData->encapContentInfo->eContentType;
333b8b016bfSjsing 
334b8b016bfSjsing 	case NID_pkcs7_enveloped:
335b8b016bfSjsing 		return &cms->d.envelopedData->encryptedContentInfo->contentType;
336b8b016bfSjsing 
337b8b016bfSjsing 	case NID_pkcs7_digest:
338b8b016bfSjsing 		return &cms->d.digestedData->encapContentInfo->eContentType;
339b8b016bfSjsing 
340b8b016bfSjsing 	case NID_pkcs7_encrypted:
341b8b016bfSjsing 		return &cms->d.encryptedData->encryptedContentInfo->contentType;
342b8b016bfSjsing 
343b8b016bfSjsing 	case NID_id_smime_ct_authData:
344b8b016bfSjsing 		return &cms->d.authenticatedData->encapContentInfo->eContentType;
345b8b016bfSjsing 
346b8b016bfSjsing 	case NID_id_smime_ct_compressedData:
347b8b016bfSjsing 		return &cms->d.compressedData->encapContentInfo->eContentType;
348b8b016bfSjsing 
349b8b016bfSjsing 	default:
350be6ec861Sjsing 		CMSerror(CMS_R_UNSUPPORTED_CONTENT_TYPE);
351b8b016bfSjsing 		return NULL;
352b8b016bfSjsing 	}
353b8b016bfSjsing }
354b8b016bfSjsing 
35572419cc7Sjsing const ASN1_OBJECT *
35672419cc7Sjsing CMS_get0_eContentType(CMS_ContentInfo *cms)
357b8b016bfSjsing {
358b8b016bfSjsing 	ASN1_OBJECT **petype;
35972419cc7Sjsing 
360b8b016bfSjsing 	petype = cms_get0_econtent_type(cms);
361b8b016bfSjsing 	if (petype)
362b8b016bfSjsing 		return *petype;
36372419cc7Sjsing 
364b8b016bfSjsing 	return NULL;
365b8b016bfSjsing }
366ead8f799Sbeck LCRYPTO_ALIAS(CMS_get0_eContentType);
367b8b016bfSjsing 
36872419cc7Sjsing int
36972419cc7Sjsing CMS_set1_eContentType(CMS_ContentInfo *cms, const ASN1_OBJECT *oid)
370b8b016bfSjsing {
371b8b016bfSjsing 	ASN1_OBJECT **petype, *etype;
37272419cc7Sjsing 
373b8b016bfSjsing 	petype = cms_get0_econtent_type(cms);
374b8b016bfSjsing 	if (!petype)
375b8b016bfSjsing 		return 0;
376b8b016bfSjsing 	if (!oid)
377b8b016bfSjsing 		return 1;
378b8b016bfSjsing 	etype = OBJ_dup(oid);
379b8b016bfSjsing 	if (!etype)
380b8b016bfSjsing 		return 0;
381b8b016bfSjsing 	ASN1_OBJECT_free(*petype);
382b8b016bfSjsing 	*petype = etype;
38372419cc7Sjsing 
384b8b016bfSjsing 	return 1;
385b8b016bfSjsing }
386ead8f799Sbeck LCRYPTO_ALIAS(CMS_set1_eContentType);
387b8b016bfSjsing 
38872419cc7Sjsing int
38972419cc7Sjsing CMS_is_detached(CMS_ContentInfo *cms)
390b8b016bfSjsing {
391b8b016bfSjsing 	ASN1_OCTET_STRING **pos;
39272419cc7Sjsing 
393b8b016bfSjsing 	pos = CMS_get0_content(cms);
394b8b016bfSjsing 	if (!pos)
395b8b016bfSjsing 		return -1;
396b8b016bfSjsing 	if (*pos)
397b8b016bfSjsing 		return 0;
39872419cc7Sjsing 
399b8b016bfSjsing 	return 1;
400b8b016bfSjsing }
401ead8f799Sbeck LCRYPTO_ALIAS(CMS_is_detached);
402b8b016bfSjsing 
40372419cc7Sjsing int
40472419cc7Sjsing CMS_set_detached(CMS_ContentInfo *cms, int detached)
405b8b016bfSjsing {
406b8b016bfSjsing 	ASN1_OCTET_STRING **pos;
40772419cc7Sjsing 
408b8b016bfSjsing 	pos = CMS_get0_content(cms);
409b8b016bfSjsing 	if (!pos)
410b8b016bfSjsing 		return 0;
411b8b016bfSjsing 	if (detached) {
412b8b016bfSjsing 		ASN1_OCTET_STRING_free(*pos);
413b8b016bfSjsing 		*pos = NULL;
414b8b016bfSjsing 		return 1;
415b8b016bfSjsing 	}
416b8b016bfSjsing 	if (*pos == NULL)
417b8b016bfSjsing 		*pos = ASN1_OCTET_STRING_new();
418b8b016bfSjsing 	if (*pos != NULL) {
419b8b016bfSjsing 		/*
420b8b016bfSjsing 		 * NB: special flag to show content is created and not read in.
421b8b016bfSjsing 		 */
422b8b016bfSjsing 		(*pos)->flags |= ASN1_STRING_FLAG_CONT;
423b8b016bfSjsing 		return 1;
424b8b016bfSjsing 	}
425be6ec861Sjsing 	CMSerror(ERR_R_MALLOC_FAILURE);
42672419cc7Sjsing 
427b8b016bfSjsing 	return 0;
428b8b016bfSjsing }
429ead8f799Sbeck LCRYPTO_ALIAS(CMS_set_detached);
430b8b016bfSjsing 
431b8b016bfSjsing /* Create a digest BIO from an X509_ALGOR structure */
432b8b016bfSjsing 
43372419cc7Sjsing BIO *
43472419cc7Sjsing cms_DigestAlgorithm_init_bio(X509_ALGOR *digestAlgorithm)
435b8b016bfSjsing {
436b8b016bfSjsing 	BIO *mdbio = NULL;
437b8b016bfSjsing 	const ASN1_OBJECT *digestoid;
438b8b016bfSjsing 	const EVP_MD *digest;
43972419cc7Sjsing 
440b8b016bfSjsing 	X509_ALGOR_get0(&digestoid, NULL, NULL, digestAlgorithm);
441b8b016bfSjsing 	digest = EVP_get_digestbyobj(digestoid);
442b8b016bfSjsing 	if (!digest) {
443be6ec861Sjsing 		CMSerror(CMS_R_UNKNOWN_DIGEST_ALGORITHM);
444b8b016bfSjsing 		goto err;
445b8b016bfSjsing 	}
446b8b016bfSjsing 	mdbio = BIO_new(BIO_f_md());
447b8b016bfSjsing 	if (mdbio == NULL || !BIO_set_md(mdbio, digest)) {
448be6ec861Sjsing 		CMSerror(CMS_R_MD_BIO_INIT_ERROR);
449b8b016bfSjsing 		goto err;
450b8b016bfSjsing 	}
451b8b016bfSjsing 	return mdbio;
45272419cc7Sjsing 
453b8b016bfSjsing  err:
454b8b016bfSjsing 	BIO_free(mdbio);
45572419cc7Sjsing 
456b8b016bfSjsing 	return NULL;
457b8b016bfSjsing }
458b8b016bfSjsing 
459b8b016bfSjsing /* Locate a message digest content from a BIO chain based on SignerInfo */
460b8b016bfSjsing 
46172419cc7Sjsing int
46272419cc7Sjsing cms_DigestAlgorithm_find_ctx(EVP_MD_CTX *mctx, BIO *chain, X509_ALGOR *mdalg)
463b8b016bfSjsing {
464b8b016bfSjsing 	int nid;
465b8b016bfSjsing 	const ASN1_OBJECT *mdoid;
46672419cc7Sjsing 
467b8b016bfSjsing 	X509_ALGOR_get0(&mdoid, NULL, NULL, mdalg);
468b8b016bfSjsing 	nid = OBJ_obj2nid(mdoid);
469b8b016bfSjsing 	/* Look for digest type to match signature */
470b8b016bfSjsing 	for (;;) {
471b8b016bfSjsing 		EVP_MD_CTX *mtmp;
472b8b016bfSjsing 		chain = BIO_find_type(chain, BIO_TYPE_MD);
473b8b016bfSjsing 		if (chain == NULL) {
474be6ec861Sjsing 			CMSerror(CMS_R_NO_MATCHING_DIGEST);
475b8b016bfSjsing 			return 0;
476b8b016bfSjsing 		}
477b8b016bfSjsing 		BIO_get_md_ctx(chain, &mtmp);
478b8b016bfSjsing 		if (EVP_MD_CTX_type(mtmp) == nid
479b8b016bfSjsing 			/*
480b8b016bfSjsing 			 * Workaround for broken implementations that use signature
481b8b016bfSjsing 			 * algorithm OID instead of digest.
482b8b016bfSjsing 			 */
483b8b016bfSjsing 			|| EVP_MD_pkey_type(EVP_MD_CTX_md(mtmp)) == nid)
484b8b016bfSjsing 			return EVP_MD_CTX_copy_ex(mctx, mtmp);
485b8b016bfSjsing 		chain = BIO_next(chain);
486b8b016bfSjsing 	}
487b8b016bfSjsing }
488b8b016bfSjsing 
48972419cc7Sjsing static STACK_OF(CMS_CertificateChoices) **
49072419cc7Sjsing cms_get0_certificate_choices(CMS_ContentInfo *cms)
491b8b016bfSjsing {
492b8b016bfSjsing 	switch (OBJ_obj2nid(cms->contentType)) {
493b8b016bfSjsing 	case NID_pkcs7_signed:
494b8b016bfSjsing 		return &cms->d.signedData->certificates;
495b8b016bfSjsing 
496b8b016bfSjsing 	case NID_pkcs7_enveloped:
497b8b016bfSjsing 		if (cms->d.envelopedData->originatorInfo == NULL)
498b8b016bfSjsing 			return NULL;
499b8b016bfSjsing 		return &cms->d.envelopedData->originatorInfo->certificates;
500b8b016bfSjsing 
501b8b016bfSjsing 	default:
502be6ec861Sjsing 		CMSerror(CMS_R_UNSUPPORTED_CONTENT_TYPE);
503b8b016bfSjsing 		return NULL;
504b8b016bfSjsing 	}
505b8b016bfSjsing }
506b8b016bfSjsing 
50772419cc7Sjsing CMS_CertificateChoices *
50872419cc7Sjsing CMS_add0_CertificateChoices(CMS_ContentInfo *cms)
509b8b016bfSjsing {
510b8b016bfSjsing 	STACK_OF(CMS_CertificateChoices) **pcerts;
511b8b016bfSjsing 	CMS_CertificateChoices *cch;
51272419cc7Sjsing 
513b8b016bfSjsing 	pcerts = cms_get0_certificate_choices(cms);
514b8b016bfSjsing 	if (!pcerts)
515b8b016bfSjsing 		return NULL;
516b8b016bfSjsing 	if (!*pcerts)
517b8b016bfSjsing 		*pcerts = sk_CMS_CertificateChoices_new_null();
518b8b016bfSjsing 	if (!*pcerts)
519b8b016bfSjsing 		return NULL;
520f2f5f7c4Sjsing 	cch = (CMS_CertificateChoices *)ASN1_item_new(&CMS_CertificateChoices_it);
521b8b016bfSjsing 	if (!cch)
522b8b016bfSjsing 		return NULL;
523b8b016bfSjsing 	if (!sk_CMS_CertificateChoices_push(*pcerts, cch)) {
524f2f5f7c4Sjsing 		ASN1_item_free((ASN1_VALUE *)cch, &CMS_CertificateChoices_it);
525b8b016bfSjsing 		return NULL;
526b8b016bfSjsing 	}
52772419cc7Sjsing 
528b8b016bfSjsing 	return cch;
529b8b016bfSjsing }
530ead8f799Sbeck LCRYPTO_ALIAS(CMS_add0_CertificateChoices);
531b8b016bfSjsing 
53272419cc7Sjsing int
53372419cc7Sjsing CMS_add0_cert(CMS_ContentInfo *cms, X509 *cert)
534b8b016bfSjsing {
535b8b016bfSjsing 	CMS_CertificateChoices *cch;
536b8b016bfSjsing 	STACK_OF(CMS_CertificateChoices) **pcerts;
537b8b016bfSjsing 	int i;
53872419cc7Sjsing 
539b8b016bfSjsing 	pcerts = cms_get0_certificate_choices(cms);
540b8b016bfSjsing 	if (!pcerts)
541b8b016bfSjsing 		return 0;
542b8b016bfSjsing 	for (i = 0; i < sk_CMS_CertificateChoices_num(*pcerts); i++) {
543b8b016bfSjsing 		cch = sk_CMS_CertificateChoices_value(*pcerts, i);
544b8b016bfSjsing 		if (cch->type == CMS_CERTCHOICE_CERT) {
545b8b016bfSjsing 			if (!X509_cmp(cch->d.certificate, cert)) {
546be6ec861Sjsing 			    CMSerror(CMS_R_CERTIFICATE_ALREADY_PRESENT);
547b8b016bfSjsing 			    return 0;
548b8b016bfSjsing 			}
549b8b016bfSjsing 		}
550b8b016bfSjsing 	}
551b8b016bfSjsing 	cch = CMS_add0_CertificateChoices(cms);
552b8b016bfSjsing 	if (!cch)
553b8b016bfSjsing 		return 0;
554b8b016bfSjsing 	cch->type = CMS_CERTCHOICE_CERT;
555b8b016bfSjsing 	cch->d.certificate = cert;
55672419cc7Sjsing 
557b8b016bfSjsing 	return 1;
558b8b016bfSjsing }
559ead8f799Sbeck LCRYPTO_ALIAS(CMS_add0_cert);
560b8b016bfSjsing 
56172419cc7Sjsing int
56272419cc7Sjsing CMS_add1_cert(CMS_ContentInfo *cms, X509 *cert)
563b8b016bfSjsing {
564b8b016bfSjsing 	int r;
56572419cc7Sjsing 
566b8b016bfSjsing 	r = CMS_add0_cert(cms, cert);
567b8b016bfSjsing 	if (r > 0)
568b8b016bfSjsing 		X509_up_ref(cert);
56972419cc7Sjsing 
570b8b016bfSjsing 	return r;
571b8b016bfSjsing }
572ead8f799Sbeck LCRYPTO_ALIAS(CMS_add1_cert);
573b8b016bfSjsing 
57472419cc7Sjsing static STACK_OF(CMS_RevocationInfoChoice) **
57572419cc7Sjsing cms_get0_revocation_choices(CMS_ContentInfo *cms)
576b8b016bfSjsing {
577b8b016bfSjsing 	switch (OBJ_obj2nid(cms->contentType)) {
578b8b016bfSjsing 	case NID_pkcs7_signed:
579b8b016bfSjsing 		return &cms->d.signedData->crls;
580b8b016bfSjsing 
581b8b016bfSjsing 	case NID_pkcs7_enveloped:
582b8b016bfSjsing 		if (cms->d.envelopedData->originatorInfo == NULL)
583b8b016bfSjsing 			return NULL;
584b8b016bfSjsing 		return &cms->d.envelopedData->originatorInfo->crls;
585b8b016bfSjsing 
586b8b016bfSjsing 	default:
587be6ec861Sjsing 		CMSerror(CMS_R_UNSUPPORTED_CONTENT_TYPE);
588b8b016bfSjsing 		return NULL;
589b8b016bfSjsing 	}
590b8b016bfSjsing }
591b8b016bfSjsing 
59272419cc7Sjsing CMS_RevocationInfoChoice *
59372419cc7Sjsing CMS_add0_RevocationInfoChoice(CMS_ContentInfo *cms)
594b8b016bfSjsing {
595b8b016bfSjsing 	STACK_OF(CMS_RevocationInfoChoice) **pcrls;
596b8b016bfSjsing 	CMS_RevocationInfoChoice *rch;
59772419cc7Sjsing 
598b8b016bfSjsing 	pcrls = cms_get0_revocation_choices(cms);
599b8b016bfSjsing 	if (!pcrls)
600b8b016bfSjsing 		return NULL;
601b8b016bfSjsing 	if (!*pcrls)
602b8b016bfSjsing 		*pcrls = sk_CMS_RevocationInfoChoice_new_null();
603b8b016bfSjsing 	if (!*pcrls)
604b8b016bfSjsing 		return NULL;
605f2f5f7c4Sjsing 	rch = (CMS_RevocationInfoChoice *)ASN1_item_new(&CMS_RevocationInfoChoice_it);
606b8b016bfSjsing 	if (!rch)
607b8b016bfSjsing 		return NULL;
608b8b016bfSjsing 	if (!sk_CMS_RevocationInfoChoice_push(*pcrls, rch)) {
609f2f5f7c4Sjsing 		ASN1_item_free((ASN1_VALUE *)rch, &CMS_RevocationInfoChoice_it);
610b8b016bfSjsing 		return NULL;
611b8b016bfSjsing 	}
61272419cc7Sjsing 
613b8b016bfSjsing 	return rch;
614b8b016bfSjsing }
615ead8f799Sbeck LCRYPTO_ALIAS(CMS_add0_RevocationInfoChoice);
616b8b016bfSjsing 
61772419cc7Sjsing int
61872419cc7Sjsing CMS_add0_crl(CMS_ContentInfo *cms, X509_CRL *crl)
619b8b016bfSjsing {
620b8b016bfSjsing 	CMS_RevocationInfoChoice *rch;
62172419cc7Sjsing 
622b8b016bfSjsing 	rch = CMS_add0_RevocationInfoChoice(cms);
623b8b016bfSjsing 	if (!rch)
624b8b016bfSjsing 		return 0;
625b8b016bfSjsing 	rch->type = CMS_REVCHOICE_CRL;
626b8b016bfSjsing 	rch->d.crl = crl;
62772419cc7Sjsing 
628b8b016bfSjsing 	return 1;
629b8b016bfSjsing }
630ead8f799Sbeck LCRYPTO_ALIAS(CMS_add0_crl);
631b8b016bfSjsing 
63272419cc7Sjsing int
63372419cc7Sjsing CMS_add1_crl(CMS_ContentInfo *cms, X509_CRL *crl)
634b8b016bfSjsing {
635b8b016bfSjsing 	int r;
63672419cc7Sjsing 
637b8b016bfSjsing 	r = CMS_add0_crl(cms, crl);
638b8b016bfSjsing 	if (r > 0)
639b8b016bfSjsing 		X509_CRL_up_ref(crl);
64072419cc7Sjsing 
641b8b016bfSjsing 	return r;
642b8b016bfSjsing }
643ead8f799Sbeck LCRYPTO_ALIAS(CMS_add1_crl);
644b8b016bfSjsing 
64572419cc7Sjsing STACK_OF(X509) *
64672419cc7Sjsing CMS_get1_certs(CMS_ContentInfo *cms)
647b8b016bfSjsing {
648b8b016bfSjsing 	STACK_OF(X509) *certs = NULL;
649b8b016bfSjsing 	CMS_CertificateChoices *cch;
650b8b016bfSjsing 	STACK_OF(CMS_CertificateChoices) **pcerts;
651b8b016bfSjsing 	int i;
65272419cc7Sjsing 
653b8b016bfSjsing 	pcerts = cms_get0_certificate_choices(cms);
654b8b016bfSjsing 	if (!pcerts)
655b8b016bfSjsing 		return NULL;
656b8b016bfSjsing 	for (i = 0; i < sk_CMS_CertificateChoices_num(*pcerts); i++) {
657b8b016bfSjsing 		cch = sk_CMS_CertificateChoices_value(*pcerts, i);
658b8b016bfSjsing 		if (cch->type == 0) {
659b8b016bfSjsing 			if (!certs) {
660b8b016bfSjsing 			    certs = sk_X509_new_null();
661b8b016bfSjsing 			    if (!certs)
662b8b016bfSjsing 			        return NULL;
663b8b016bfSjsing 			}
664b8b016bfSjsing 			if (!sk_X509_push(certs, cch->d.certificate)) {
665b8b016bfSjsing 			    sk_X509_pop_free(certs, X509_free);
666b8b016bfSjsing 			    return NULL;
667b8b016bfSjsing 			}
668b8b016bfSjsing 			X509_up_ref(cch->d.certificate);
669b8b016bfSjsing 		}
670b8b016bfSjsing 	}
671b8b016bfSjsing 	return certs;
672b8b016bfSjsing }
673ead8f799Sbeck LCRYPTO_ALIAS(CMS_get1_certs);
674b8b016bfSjsing 
67572419cc7Sjsing STACK_OF(X509_CRL) *
67672419cc7Sjsing CMS_get1_crls(CMS_ContentInfo *cms)
677b8b016bfSjsing {
678b8b016bfSjsing 	STACK_OF(X509_CRL) *crls = NULL;
679b8b016bfSjsing 	STACK_OF(CMS_RevocationInfoChoice) **pcrls;
680b8b016bfSjsing 	CMS_RevocationInfoChoice *rch;
681b8b016bfSjsing 	int i;
68272419cc7Sjsing 
683b8b016bfSjsing 	pcrls = cms_get0_revocation_choices(cms);
684b8b016bfSjsing 	if (!pcrls)
685b8b016bfSjsing 		return NULL;
686b8b016bfSjsing 	for (i = 0; i < sk_CMS_RevocationInfoChoice_num(*pcrls); i++) {
687b8b016bfSjsing 		rch = sk_CMS_RevocationInfoChoice_value(*pcrls, i);
688b8b016bfSjsing 		if (rch->type == 0) {
689b8b016bfSjsing 			if (!crls) {
690b8b016bfSjsing 			    crls = sk_X509_CRL_new_null();
691b8b016bfSjsing 			    if (!crls)
692b8b016bfSjsing 			        return NULL;
693b8b016bfSjsing 			}
694b8b016bfSjsing 			if (!sk_X509_CRL_push(crls, rch->d.crl)) {
695b8b016bfSjsing 			    sk_X509_CRL_pop_free(crls, X509_CRL_free);
696b8b016bfSjsing 			    return NULL;
697b8b016bfSjsing 			}
698b8b016bfSjsing 			X509_CRL_up_ref(rch->d.crl);
699b8b016bfSjsing 		}
700b8b016bfSjsing 	}
701b8b016bfSjsing 	return crls;
702b8b016bfSjsing }
703ead8f799Sbeck LCRYPTO_ALIAS(CMS_get1_crls);
704b8b016bfSjsing 
705969b657eSjsing static const ASN1_OCTET_STRING *
706969b657eSjsing cms_X509_get0_subject_key_id(X509 *x)
707969b657eSjsing {
708969b657eSjsing 	/* Call for side-effect of computing hash and caching extensions */
709969b657eSjsing 	X509_check_purpose(x, -1, -1);
710969b657eSjsing 	return x->skid;
711969b657eSjsing }
712969b657eSjsing 
71372419cc7Sjsing int
71472419cc7Sjsing cms_ias_cert_cmp(CMS_IssuerAndSerialNumber *ias, X509 *cert)
715b8b016bfSjsing {
716b8b016bfSjsing 	int ret;
71772419cc7Sjsing 
718b8b016bfSjsing 	ret = X509_NAME_cmp(ias->issuer, X509_get_issuer_name(cert));
719b8b016bfSjsing 	if (ret)
720b8b016bfSjsing 		return ret;
72172419cc7Sjsing 
722b8b016bfSjsing 	return ASN1_INTEGER_cmp(ias->serialNumber, X509_get_serialNumber(cert));
723b8b016bfSjsing }
724b8b016bfSjsing 
72572419cc7Sjsing int
72672419cc7Sjsing cms_keyid_cert_cmp(ASN1_OCTET_STRING *keyid, X509 *cert)
727b8b016bfSjsing {
728969b657eSjsing 	const ASN1_OCTET_STRING *cert_keyid = cms_X509_get0_subject_key_id(cert);
729b8b016bfSjsing 
730b8b016bfSjsing 	if (cert_keyid == NULL)
731b8b016bfSjsing 		return -1;
73272419cc7Sjsing 
733b8b016bfSjsing 	return ASN1_OCTET_STRING_cmp(keyid, cert_keyid);
734b8b016bfSjsing }
735b8b016bfSjsing 
73672419cc7Sjsing int
73772419cc7Sjsing cms_set1_ias(CMS_IssuerAndSerialNumber **pias, X509 *cert)
738b8b016bfSjsing {
739b8b016bfSjsing 	CMS_IssuerAndSerialNumber *ias;
74072419cc7Sjsing 
741f2f5f7c4Sjsing 	ias = (CMS_IssuerAndSerialNumber *)ASN1_item_new(&CMS_IssuerAndSerialNumber_it);
742b8b016bfSjsing 	if (!ias)
743b8b016bfSjsing 		goto err;
744b8b016bfSjsing 	if (!X509_NAME_set(&ias->issuer, X509_get_issuer_name(cert)))
745b8b016bfSjsing 		goto err;
746b8b016bfSjsing 	if (!ASN1_STRING_copy(ias->serialNumber, X509_get_serialNumber(cert)))
747b8b016bfSjsing 		goto err;
748f2f5f7c4Sjsing 	ASN1_item_free((ASN1_VALUE *)*pias, &CMS_IssuerAndSerialNumber_it);
749b8b016bfSjsing 	*pias = ias;
75072419cc7Sjsing 
751b8b016bfSjsing 	return 1;
75272419cc7Sjsing 
753b8b016bfSjsing  err:
754f2f5f7c4Sjsing 	ASN1_item_free((ASN1_VALUE *)ias, &CMS_IssuerAndSerialNumber_it);
755be6ec861Sjsing 	CMSerror(ERR_R_MALLOC_FAILURE);
75672419cc7Sjsing 
757b8b016bfSjsing 	return 0;
758b8b016bfSjsing }
759b8b016bfSjsing 
76072419cc7Sjsing int
76172419cc7Sjsing cms_set1_keyid(ASN1_OCTET_STRING **pkeyid, X509 *cert)
762b8b016bfSjsing {
763b8b016bfSjsing 	ASN1_OCTET_STRING *keyid = NULL;
764b8b016bfSjsing 	const ASN1_OCTET_STRING *cert_keyid;
76572419cc7Sjsing 
766969b657eSjsing 	cert_keyid = cms_X509_get0_subject_key_id(cert);
767b8b016bfSjsing 	if (cert_keyid == NULL) {
768be6ec861Sjsing 		CMSerror(CMS_R_CERTIFICATE_HAS_NO_KEYID);
769b8b016bfSjsing 		return 0;
770b8b016bfSjsing 	}
771b8b016bfSjsing 	keyid = ASN1_STRING_dup(cert_keyid);
772b8b016bfSjsing 	if (!keyid) {
773be6ec861Sjsing 		CMSerror(ERR_R_MALLOC_FAILURE);
774b8b016bfSjsing 		return 0;
775b8b016bfSjsing 	}
776b8b016bfSjsing 	ASN1_OCTET_STRING_free(*pkeyid);
777b8b016bfSjsing 	*pkeyid = keyid;
77872419cc7Sjsing 
779b8b016bfSjsing 	return 1;
780b8b016bfSjsing }
781