1*de0e0e4dSAntonio Huete Jimenez /* $OpenBSD: pk7_lib.c,v 1.23 2021/12/12 21:30:14 tb Exp $ */
2f5b1c8a1SJohn Marino /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
3f5b1c8a1SJohn Marino * All rights reserved.
4f5b1c8a1SJohn Marino *
5f5b1c8a1SJohn Marino * This package is an SSL implementation written
6f5b1c8a1SJohn Marino * by Eric Young (eay@cryptsoft.com).
7f5b1c8a1SJohn Marino * The implementation was written so as to conform with Netscapes SSL.
8f5b1c8a1SJohn Marino *
9f5b1c8a1SJohn Marino * This library is free for commercial and non-commercial use as long as
10f5b1c8a1SJohn Marino * the following conditions are aheared to. The following conditions
11f5b1c8a1SJohn Marino * apply to all code found in this distribution, be it the RC4, RSA,
12f5b1c8a1SJohn Marino * lhash, DES, etc., code; not just the SSL code. The SSL documentation
13f5b1c8a1SJohn Marino * included with this distribution is covered by the same copyright terms
14f5b1c8a1SJohn Marino * except that the holder is Tim Hudson (tjh@cryptsoft.com).
15f5b1c8a1SJohn Marino *
16f5b1c8a1SJohn Marino * Copyright remains Eric Young's, and as such any Copyright notices in
17f5b1c8a1SJohn Marino * the code are not to be removed.
18f5b1c8a1SJohn Marino * If this package is used in a product, Eric Young should be given attribution
19f5b1c8a1SJohn Marino * as the author of the parts of the library used.
20f5b1c8a1SJohn Marino * This can be in the form of a textual message at program startup or
21f5b1c8a1SJohn Marino * in documentation (online or textual) provided with the package.
22f5b1c8a1SJohn Marino *
23f5b1c8a1SJohn Marino * Redistribution and use in source and binary forms, with or without
24f5b1c8a1SJohn Marino * modification, are permitted provided that the following conditions
25f5b1c8a1SJohn Marino * are met:
26f5b1c8a1SJohn Marino * 1. Redistributions of source code must retain the copyright
27f5b1c8a1SJohn Marino * notice, this list of conditions and the following disclaimer.
28f5b1c8a1SJohn Marino * 2. Redistributions in binary form must reproduce the above copyright
29f5b1c8a1SJohn Marino * notice, this list of conditions and the following disclaimer in the
30f5b1c8a1SJohn Marino * documentation and/or other materials provided with the distribution.
31f5b1c8a1SJohn Marino * 3. All advertising materials mentioning features or use of this software
32f5b1c8a1SJohn Marino * must display the following acknowledgement:
33f5b1c8a1SJohn Marino * "This product includes cryptographic software written by
34f5b1c8a1SJohn Marino * Eric Young (eay@cryptsoft.com)"
35f5b1c8a1SJohn Marino * The word 'cryptographic' can be left out if the rouines from the library
36f5b1c8a1SJohn Marino * being used are not cryptographic related :-).
37f5b1c8a1SJohn Marino * 4. If you include any Windows specific code (or a derivative thereof) from
38f5b1c8a1SJohn Marino * the apps directory (application code) you must include an acknowledgement:
39f5b1c8a1SJohn Marino * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
40f5b1c8a1SJohn Marino *
41f5b1c8a1SJohn Marino * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
42f5b1c8a1SJohn Marino * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
43f5b1c8a1SJohn Marino * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
44f5b1c8a1SJohn Marino * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
45f5b1c8a1SJohn Marino * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
46f5b1c8a1SJohn Marino * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
47f5b1c8a1SJohn Marino * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48f5b1c8a1SJohn Marino * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
49f5b1c8a1SJohn Marino * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
50f5b1c8a1SJohn Marino * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
51f5b1c8a1SJohn Marino * SUCH DAMAGE.
52f5b1c8a1SJohn Marino *
53f5b1c8a1SJohn Marino * The licence and distribution terms for any publically available version or
54f5b1c8a1SJohn Marino * derivative of this code cannot be changed. i.e. this code cannot simply be
55f5b1c8a1SJohn Marino * copied and put under another distribution licence
56f5b1c8a1SJohn Marino * [including the GNU Public Licence.]
57f5b1c8a1SJohn Marino */
58f5b1c8a1SJohn Marino
59f5b1c8a1SJohn Marino #include <stdio.h>
60f5b1c8a1SJohn Marino
61f5b1c8a1SJohn Marino #include <openssl/err.h>
62f5b1c8a1SJohn Marino #include <openssl/objects.h>
63f5b1c8a1SJohn Marino #include <openssl/x509.h>
64f5b1c8a1SJohn Marino
65f5b1c8a1SJohn Marino #include "asn1_locl.h"
66*de0e0e4dSAntonio Huete Jimenez #include "evp_locl.h"
67*de0e0e4dSAntonio Huete Jimenez #include "x509_lcl.h"
68f5b1c8a1SJohn Marino
69f5b1c8a1SJohn Marino long
PKCS7_ctrl(PKCS7 * p7,int cmd,long larg,char * parg)70f5b1c8a1SJohn Marino PKCS7_ctrl(PKCS7 *p7, int cmd, long larg, char *parg)
71f5b1c8a1SJohn Marino {
72f5b1c8a1SJohn Marino int nid;
73f5b1c8a1SJohn Marino long ret;
74f5b1c8a1SJohn Marino
75f5b1c8a1SJohn Marino nid = OBJ_obj2nid(p7->type);
76f5b1c8a1SJohn Marino
77f5b1c8a1SJohn Marino switch (cmd) {
78f5b1c8a1SJohn Marino case PKCS7_OP_SET_DETACHED_SIGNATURE:
79f5b1c8a1SJohn Marino if (nid == NID_pkcs7_signed) {
80f5b1c8a1SJohn Marino ret = p7->detached = (int)larg;
81f5b1c8a1SJohn Marino if (ret && PKCS7_type_is_data(p7->d.sign->contents)) {
82f5b1c8a1SJohn Marino ASN1_OCTET_STRING *os;
83f5b1c8a1SJohn Marino os = p7->d.sign->contents->d.data;
84f5b1c8a1SJohn Marino ASN1_OCTET_STRING_free(os);
85f5b1c8a1SJohn Marino p7->d.sign->contents->d.data = NULL;
86f5b1c8a1SJohn Marino }
87f5b1c8a1SJohn Marino } else {
8872c33676SMaxim Ag PKCS7error(PKCS7_R_OPERATION_NOT_SUPPORTED_ON_THIS_TYPE);
89f5b1c8a1SJohn Marino ret = 0;
90f5b1c8a1SJohn Marino }
91f5b1c8a1SJohn Marino break;
92f5b1c8a1SJohn Marino case PKCS7_OP_GET_DETACHED_SIGNATURE:
93f5b1c8a1SJohn Marino if (nid == NID_pkcs7_signed) {
94f5b1c8a1SJohn Marino if (!p7->d.sign || !p7->d.sign->contents->d.ptr)
95f5b1c8a1SJohn Marino ret = 1;
96f5b1c8a1SJohn Marino else
97f5b1c8a1SJohn Marino ret = 0;
98f5b1c8a1SJohn Marino
99f5b1c8a1SJohn Marino p7->detached = ret;
100f5b1c8a1SJohn Marino } else {
10172c33676SMaxim Ag PKCS7error(PKCS7_R_OPERATION_NOT_SUPPORTED_ON_THIS_TYPE);
102f5b1c8a1SJohn Marino ret = 0;
103f5b1c8a1SJohn Marino }
104f5b1c8a1SJohn Marino
105f5b1c8a1SJohn Marino break;
106f5b1c8a1SJohn Marino default:
10772c33676SMaxim Ag PKCS7error(PKCS7_R_UNKNOWN_OPERATION);
108f5b1c8a1SJohn Marino ret = 0;
109f5b1c8a1SJohn Marino }
110f5b1c8a1SJohn Marino return (ret);
111f5b1c8a1SJohn Marino }
112f5b1c8a1SJohn Marino
113f5b1c8a1SJohn Marino int
PKCS7_content_new(PKCS7 * p7,int type)114f5b1c8a1SJohn Marino PKCS7_content_new(PKCS7 *p7, int type)
115f5b1c8a1SJohn Marino {
116f5b1c8a1SJohn Marino PKCS7 *ret = NULL;
117f5b1c8a1SJohn Marino
118f5b1c8a1SJohn Marino if ((ret = PKCS7_new()) == NULL)
119f5b1c8a1SJohn Marino goto err;
120f5b1c8a1SJohn Marino if (!PKCS7_set_type(ret, type))
121f5b1c8a1SJohn Marino goto err;
122f5b1c8a1SJohn Marino if (!PKCS7_set_content(p7, ret))
123f5b1c8a1SJohn Marino goto err;
124f5b1c8a1SJohn Marino
125f5b1c8a1SJohn Marino return (1);
126f5b1c8a1SJohn Marino err:
127f5b1c8a1SJohn Marino if (ret != NULL)
128f5b1c8a1SJohn Marino PKCS7_free(ret);
129f5b1c8a1SJohn Marino return (0);
130f5b1c8a1SJohn Marino }
131f5b1c8a1SJohn Marino
132f5b1c8a1SJohn Marino int
PKCS7_set_content(PKCS7 * p7,PKCS7 * p7_data)133f5b1c8a1SJohn Marino PKCS7_set_content(PKCS7 *p7, PKCS7 *p7_data)
134f5b1c8a1SJohn Marino {
135f5b1c8a1SJohn Marino int i;
136f5b1c8a1SJohn Marino
137f5b1c8a1SJohn Marino i = OBJ_obj2nid(p7->type);
138f5b1c8a1SJohn Marino switch (i) {
139f5b1c8a1SJohn Marino case NID_pkcs7_signed:
140f5b1c8a1SJohn Marino if (p7->d.sign->contents != NULL)
141f5b1c8a1SJohn Marino PKCS7_free(p7->d.sign->contents);
142f5b1c8a1SJohn Marino p7->d.sign->contents = p7_data;
143f5b1c8a1SJohn Marino break;
144f5b1c8a1SJohn Marino case NID_pkcs7_digest:
145f5b1c8a1SJohn Marino if (p7->d.digest->contents != NULL)
146f5b1c8a1SJohn Marino PKCS7_free(p7->d.digest->contents);
147f5b1c8a1SJohn Marino p7->d.digest->contents = p7_data;
148f5b1c8a1SJohn Marino break;
149f5b1c8a1SJohn Marino case NID_pkcs7_data:
150f5b1c8a1SJohn Marino case NID_pkcs7_enveloped:
151f5b1c8a1SJohn Marino case NID_pkcs7_signedAndEnveloped:
152f5b1c8a1SJohn Marino case NID_pkcs7_encrypted:
153f5b1c8a1SJohn Marino default:
15472c33676SMaxim Ag PKCS7error(PKCS7_R_UNSUPPORTED_CONTENT_TYPE);
155f5b1c8a1SJohn Marino goto err;
156f5b1c8a1SJohn Marino }
157f5b1c8a1SJohn Marino return (1);
158f5b1c8a1SJohn Marino err:
159f5b1c8a1SJohn Marino return (0);
160f5b1c8a1SJohn Marino }
161f5b1c8a1SJohn Marino
162f5b1c8a1SJohn Marino int
PKCS7_set_type(PKCS7 * p7,int type)163f5b1c8a1SJohn Marino PKCS7_set_type(PKCS7 *p7, int type)
164f5b1c8a1SJohn Marino {
165f5b1c8a1SJohn Marino ASN1_OBJECT *obj;
166f5b1c8a1SJohn Marino
167f5b1c8a1SJohn Marino /*PKCS7_content_free(p7);*/
168f5b1c8a1SJohn Marino obj=OBJ_nid2obj(type); /* will not fail */
169f5b1c8a1SJohn Marino
170f5b1c8a1SJohn Marino switch (type) {
171f5b1c8a1SJohn Marino case NID_pkcs7_signed:
172f5b1c8a1SJohn Marino p7->type = obj;
173f5b1c8a1SJohn Marino if ((p7->d.sign = PKCS7_SIGNED_new()) == NULL)
174f5b1c8a1SJohn Marino goto err;
175f5b1c8a1SJohn Marino if (!ASN1_INTEGER_set(p7->d.sign->version, 1)) {
176f5b1c8a1SJohn Marino PKCS7_SIGNED_free(p7->d.sign);
177f5b1c8a1SJohn Marino p7->d.sign = NULL;
178f5b1c8a1SJohn Marino goto err;
179f5b1c8a1SJohn Marino }
180f5b1c8a1SJohn Marino break;
181f5b1c8a1SJohn Marino case NID_pkcs7_data:
182f5b1c8a1SJohn Marino p7->type = obj;
183f5b1c8a1SJohn Marino if ((p7->d.data = ASN1_OCTET_STRING_new()) == NULL)
184f5b1c8a1SJohn Marino goto err;
185f5b1c8a1SJohn Marino break;
186f5b1c8a1SJohn Marino case NID_pkcs7_signedAndEnveloped:
187f5b1c8a1SJohn Marino p7->type = obj;
188f5b1c8a1SJohn Marino if ((p7->d.signed_and_enveloped =
189f5b1c8a1SJohn Marino PKCS7_SIGN_ENVELOPE_new()) == NULL)
190f5b1c8a1SJohn Marino goto err;
191f5b1c8a1SJohn Marino if (!ASN1_INTEGER_set(p7->d.signed_and_enveloped->version, 1))
192f5b1c8a1SJohn Marino goto err;
193f5b1c8a1SJohn Marino p7->d.signed_and_enveloped->enc_data->content_type =
194f5b1c8a1SJohn Marino OBJ_nid2obj(NID_pkcs7_data);
195f5b1c8a1SJohn Marino break;
196f5b1c8a1SJohn Marino case NID_pkcs7_enveloped:
197f5b1c8a1SJohn Marino p7->type = obj;
198f5b1c8a1SJohn Marino if ((p7->d.enveloped = PKCS7_ENVELOPE_new()) == NULL)
199f5b1c8a1SJohn Marino goto err;
200f5b1c8a1SJohn Marino if (!ASN1_INTEGER_set(p7->d.enveloped->version, 0))
201f5b1c8a1SJohn Marino goto err;
202f5b1c8a1SJohn Marino p7->d.enveloped->enc_data->content_type =
203f5b1c8a1SJohn Marino OBJ_nid2obj(NID_pkcs7_data);
204f5b1c8a1SJohn Marino break;
205f5b1c8a1SJohn Marino case NID_pkcs7_encrypted:
206f5b1c8a1SJohn Marino p7->type = obj;
207f5b1c8a1SJohn Marino if ((p7->d.encrypted = PKCS7_ENCRYPT_new()) == NULL)
208f5b1c8a1SJohn Marino goto err;
209f5b1c8a1SJohn Marino if (!ASN1_INTEGER_set(p7->d.encrypted->version, 0))
210f5b1c8a1SJohn Marino goto err;
211f5b1c8a1SJohn Marino p7->d.encrypted->enc_data->content_type =
212f5b1c8a1SJohn Marino OBJ_nid2obj(NID_pkcs7_data);
213f5b1c8a1SJohn Marino break;
214f5b1c8a1SJohn Marino
215f5b1c8a1SJohn Marino case NID_pkcs7_digest:
216f5b1c8a1SJohn Marino p7->type = obj;
217f5b1c8a1SJohn Marino if ((p7->d.digest = PKCS7_DIGEST_new()) == NULL)
218f5b1c8a1SJohn Marino goto err;
219f5b1c8a1SJohn Marino if (!ASN1_INTEGER_set(p7->d.digest->version, 0))
220f5b1c8a1SJohn Marino goto err;
221f5b1c8a1SJohn Marino break;
222f5b1c8a1SJohn Marino default:
22372c33676SMaxim Ag PKCS7error(PKCS7_R_UNSUPPORTED_CONTENT_TYPE);
224f5b1c8a1SJohn Marino goto err;
225f5b1c8a1SJohn Marino }
226f5b1c8a1SJohn Marino return (1);
227f5b1c8a1SJohn Marino err:
228f5b1c8a1SJohn Marino return (0);
229f5b1c8a1SJohn Marino }
230f5b1c8a1SJohn Marino
231f5b1c8a1SJohn Marino int
PKCS7_set0_type_other(PKCS7 * p7,int type,ASN1_TYPE * other)232f5b1c8a1SJohn Marino PKCS7_set0_type_other(PKCS7 *p7, int type, ASN1_TYPE *other)
233f5b1c8a1SJohn Marino {
234f5b1c8a1SJohn Marino p7->type = OBJ_nid2obj(type);
235f5b1c8a1SJohn Marino p7->d.other = other;
236f5b1c8a1SJohn Marino return 1;
237f5b1c8a1SJohn Marino }
238f5b1c8a1SJohn Marino
239f5b1c8a1SJohn Marino int
PKCS7_add_signer(PKCS7 * p7,PKCS7_SIGNER_INFO * psi)240f5b1c8a1SJohn Marino PKCS7_add_signer(PKCS7 *p7, PKCS7_SIGNER_INFO *psi)
241f5b1c8a1SJohn Marino {
242f5b1c8a1SJohn Marino int i, j, nid;
243f5b1c8a1SJohn Marino X509_ALGOR *alg;
244f5b1c8a1SJohn Marino STACK_OF(PKCS7_SIGNER_INFO) *signer_sk;
245f5b1c8a1SJohn Marino STACK_OF(X509_ALGOR) *md_sk;
246f5b1c8a1SJohn Marino
247f5b1c8a1SJohn Marino i = OBJ_obj2nid(p7->type);
248f5b1c8a1SJohn Marino switch (i) {
249f5b1c8a1SJohn Marino case NID_pkcs7_signed:
250f5b1c8a1SJohn Marino signer_sk = p7->d.sign->signer_info;
251f5b1c8a1SJohn Marino md_sk = p7->d.sign->md_algs;
252f5b1c8a1SJohn Marino break;
253f5b1c8a1SJohn Marino case NID_pkcs7_signedAndEnveloped:
254f5b1c8a1SJohn Marino signer_sk = p7->d.signed_and_enveloped->signer_info;
255f5b1c8a1SJohn Marino md_sk = p7->d.signed_and_enveloped->md_algs;
256f5b1c8a1SJohn Marino break;
257f5b1c8a1SJohn Marino default:
25872c33676SMaxim Ag PKCS7error(PKCS7_R_WRONG_CONTENT_TYPE);
259f5b1c8a1SJohn Marino return (0);
260f5b1c8a1SJohn Marino }
261f5b1c8a1SJohn Marino
262f5b1c8a1SJohn Marino nid = OBJ_obj2nid(psi->digest_alg->algorithm);
263f5b1c8a1SJohn Marino
264f5b1c8a1SJohn Marino /* If the digest is not currently listed, add it */
265f5b1c8a1SJohn Marino j = 0;
266f5b1c8a1SJohn Marino for (i = 0; i < sk_X509_ALGOR_num(md_sk); i++) {
267f5b1c8a1SJohn Marino alg = sk_X509_ALGOR_value(md_sk, i);
268f5b1c8a1SJohn Marino if (OBJ_obj2nid(alg->algorithm) == nid) {
269f5b1c8a1SJohn Marino j = 1;
270f5b1c8a1SJohn Marino break;
271f5b1c8a1SJohn Marino }
272f5b1c8a1SJohn Marino }
273f5b1c8a1SJohn Marino if (!j) /* we need to add another algorithm */
274f5b1c8a1SJohn Marino {
275f5b1c8a1SJohn Marino if (!(alg = X509_ALGOR_new()) ||
276f5b1c8a1SJohn Marino !(alg->parameter = ASN1_TYPE_new())) {
277f5b1c8a1SJohn Marino X509_ALGOR_free(alg);
27872c33676SMaxim Ag PKCS7error(ERR_R_MALLOC_FAILURE);
279f5b1c8a1SJohn Marino return (0);
280f5b1c8a1SJohn Marino }
281f5b1c8a1SJohn Marino alg->algorithm = OBJ_nid2obj(nid);
282f5b1c8a1SJohn Marino alg->parameter->type = V_ASN1_NULL;
283f5b1c8a1SJohn Marino if (!sk_X509_ALGOR_push(md_sk, alg)) {
284f5b1c8a1SJohn Marino X509_ALGOR_free(alg);
285f5b1c8a1SJohn Marino return 0;
286f5b1c8a1SJohn Marino }
287f5b1c8a1SJohn Marino }
288f5b1c8a1SJohn Marino
289f5b1c8a1SJohn Marino if (!sk_PKCS7_SIGNER_INFO_push(signer_sk, psi))
290f5b1c8a1SJohn Marino return 0;
291f5b1c8a1SJohn Marino return (1);
292f5b1c8a1SJohn Marino }
293f5b1c8a1SJohn Marino
294f5b1c8a1SJohn Marino int
PKCS7_add_certificate(PKCS7 * p7,X509 * x509)295f5b1c8a1SJohn Marino PKCS7_add_certificate(PKCS7 *p7, X509 *x509)
296f5b1c8a1SJohn Marino {
297f5b1c8a1SJohn Marino int i;
298f5b1c8a1SJohn Marino STACK_OF(X509) **sk;
299f5b1c8a1SJohn Marino
300f5b1c8a1SJohn Marino i = OBJ_obj2nid(p7->type);
301f5b1c8a1SJohn Marino switch (i) {
302f5b1c8a1SJohn Marino case NID_pkcs7_signed:
303f5b1c8a1SJohn Marino sk = &(p7->d.sign->cert);
304f5b1c8a1SJohn Marino break;
305f5b1c8a1SJohn Marino case NID_pkcs7_signedAndEnveloped:
306f5b1c8a1SJohn Marino sk = &(p7->d.signed_and_enveloped->cert);
307f5b1c8a1SJohn Marino break;
308f5b1c8a1SJohn Marino default:
30972c33676SMaxim Ag PKCS7error(PKCS7_R_WRONG_CONTENT_TYPE);
310f5b1c8a1SJohn Marino return (0);
311f5b1c8a1SJohn Marino }
312f5b1c8a1SJohn Marino
313f5b1c8a1SJohn Marino if (*sk == NULL)
314f5b1c8a1SJohn Marino *sk = sk_X509_new_null();
315f5b1c8a1SJohn Marino if (*sk == NULL) {
31672c33676SMaxim Ag PKCS7error(ERR_R_MALLOC_FAILURE);
317f5b1c8a1SJohn Marino return 0;
318f5b1c8a1SJohn Marino }
319f5b1c8a1SJohn Marino CRYPTO_add(&x509->references, 1, CRYPTO_LOCK_X509);
320f5b1c8a1SJohn Marino if (!sk_X509_push(*sk, x509)) {
321f5b1c8a1SJohn Marino X509_free(x509);
322f5b1c8a1SJohn Marino return 0;
323f5b1c8a1SJohn Marino }
324f5b1c8a1SJohn Marino return (1);
325f5b1c8a1SJohn Marino }
326f5b1c8a1SJohn Marino
327f5b1c8a1SJohn Marino int
PKCS7_add_crl(PKCS7 * p7,X509_CRL * crl)328f5b1c8a1SJohn Marino PKCS7_add_crl(PKCS7 *p7, X509_CRL *crl)
329f5b1c8a1SJohn Marino {
330f5b1c8a1SJohn Marino int i;
331f5b1c8a1SJohn Marino STACK_OF(X509_CRL) **sk;
332f5b1c8a1SJohn Marino
333f5b1c8a1SJohn Marino i = OBJ_obj2nid(p7->type);
334f5b1c8a1SJohn Marino switch (i) {
335f5b1c8a1SJohn Marino case NID_pkcs7_signed:
336f5b1c8a1SJohn Marino sk = &(p7->d.sign->crl);
337f5b1c8a1SJohn Marino break;
338f5b1c8a1SJohn Marino case NID_pkcs7_signedAndEnveloped:
339f5b1c8a1SJohn Marino sk = &(p7->d.signed_and_enveloped->crl);
340f5b1c8a1SJohn Marino break;
341f5b1c8a1SJohn Marino default:
34272c33676SMaxim Ag PKCS7error(PKCS7_R_WRONG_CONTENT_TYPE);
343f5b1c8a1SJohn Marino return (0);
344f5b1c8a1SJohn Marino }
345f5b1c8a1SJohn Marino
346f5b1c8a1SJohn Marino if (*sk == NULL)
347f5b1c8a1SJohn Marino *sk = sk_X509_CRL_new_null();
348f5b1c8a1SJohn Marino if (*sk == NULL) {
34972c33676SMaxim Ag PKCS7error(ERR_R_MALLOC_FAILURE);
350f5b1c8a1SJohn Marino return 0;
351f5b1c8a1SJohn Marino }
352f5b1c8a1SJohn Marino
353f5b1c8a1SJohn Marino CRYPTO_add(&crl->references, 1, CRYPTO_LOCK_X509_CRL);
354f5b1c8a1SJohn Marino if (!sk_X509_CRL_push(*sk, crl)) {
355f5b1c8a1SJohn Marino X509_CRL_free(crl);
356f5b1c8a1SJohn Marino return 0;
357f5b1c8a1SJohn Marino }
358f5b1c8a1SJohn Marino return (1);
359f5b1c8a1SJohn Marino }
360f5b1c8a1SJohn Marino
361f5b1c8a1SJohn Marino int
PKCS7_SIGNER_INFO_set(PKCS7_SIGNER_INFO * p7i,X509 * x509,EVP_PKEY * pkey,const EVP_MD * dgst)362f5b1c8a1SJohn Marino PKCS7_SIGNER_INFO_set(PKCS7_SIGNER_INFO *p7i, X509 *x509, EVP_PKEY *pkey,
363f5b1c8a1SJohn Marino const EVP_MD *dgst)
364f5b1c8a1SJohn Marino {
365f5b1c8a1SJohn Marino int ret;
366f5b1c8a1SJohn Marino
367f5b1c8a1SJohn Marino /* We now need to add another PKCS7_SIGNER_INFO entry */
368f5b1c8a1SJohn Marino if (!ASN1_INTEGER_set(p7i->version, 1))
369f5b1c8a1SJohn Marino goto err;
370f5b1c8a1SJohn Marino if (!X509_NAME_set(&p7i->issuer_and_serial->issuer,
371f5b1c8a1SJohn Marino X509_get_issuer_name(x509)))
372f5b1c8a1SJohn Marino goto err;
373f5b1c8a1SJohn Marino
374f5b1c8a1SJohn Marino /* because ASN1_INTEGER_set is used to set a 'long' we will do
375f5b1c8a1SJohn Marino * things the ugly way. */
376f5b1c8a1SJohn Marino ASN1_INTEGER_free(p7i->issuer_and_serial->serial);
377f5b1c8a1SJohn Marino if (!(p7i->issuer_and_serial->serial =
37872c33676SMaxim Ag ASN1_INTEGER_dup(X509_get_serialNumber(x509))))
379f5b1c8a1SJohn Marino goto err;
380f5b1c8a1SJohn Marino
381f5b1c8a1SJohn Marino /* lets keep the pkey around for a while */
382f5b1c8a1SJohn Marino CRYPTO_add(&pkey->references, 1, CRYPTO_LOCK_EVP_PKEY);
383f5b1c8a1SJohn Marino p7i->pkey = pkey;
384f5b1c8a1SJohn Marino
385f5b1c8a1SJohn Marino /* Set the algorithms */
386f5b1c8a1SJohn Marino
387f5b1c8a1SJohn Marino X509_ALGOR_set0(p7i->digest_alg, OBJ_nid2obj(EVP_MD_type(dgst)),
388f5b1c8a1SJohn Marino V_ASN1_NULL, NULL);
389f5b1c8a1SJohn Marino
390f5b1c8a1SJohn Marino if (pkey->ameth && pkey->ameth->pkey_ctrl) {
391f5b1c8a1SJohn Marino ret = pkey->ameth->pkey_ctrl(pkey, ASN1_PKEY_CTRL_PKCS7_SIGN,
392f5b1c8a1SJohn Marino 0, p7i);
393f5b1c8a1SJohn Marino if (ret > 0)
394f5b1c8a1SJohn Marino return 1;
395f5b1c8a1SJohn Marino if (ret != -2) {
39672c33676SMaxim Ag PKCS7error(PKCS7_R_SIGNING_CTRL_FAILURE);
397f5b1c8a1SJohn Marino return 0;
398f5b1c8a1SJohn Marino }
399f5b1c8a1SJohn Marino }
40072c33676SMaxim Ag PKCS7error(PKCS7_R_SIGNING_NOT_SUPPORTED_FOR_THIS_KEY_TYPE);
401f5b1c8a1SJohn Marino err:
402f5b1c8a1SJohn Marino return 0;
403f5b1c8a1SJohn Marino }
404f5b1c8a1SJohn Marino
405f5b1c8a1SJohn Marino PKCS7_SIGNER_INFO *
PKCS7_add_signature(PKCS7 * p7,X509 * x509,EVP_PKEY * pkey,const EVP_MD * dgst)406f5b1c8a1SJohn Marino PKCS7_add_signature(PKCS7 *p7, X509 *x509, EVP_PKEY *pkey, const EVP_MD *dgst)
407f5b1c8a1SJohn Marino {
408f5b1c8a1SJohn Marino PKCS7_SIGNER_INFO *si = NULL;
409f5b1c8a1SJohn Marino
410f5b1c8a1SJohn Marino if (dgst == NULL) {
411f5b1c8a1SJohn Marino int def_nid;
412f5b1c8a1SJohn Marino if (EVP_PKEY_get_default_digest_nid(pkey, &def_nid) <= 0)
413f5b1c8a1SJohn Marino goto err;
414f5b1c8a1SJohn Marino dgst = EVP_get_digestbynid(def_nid);
415f5b1c8a1SJohn Marino if (dgst == NULL) {
41672c33676SMaxim Ag PKCS7error(PKCS7_R_NO_DEFAULT_DIGEST);
417f5b1c8a1SJohn Marino goto err;
418f5b1c8a1SJohn Marino }
419f5b1c8a1SJohn Marino }
420f5b1c8a1SJohn Marino
421f5b1c8a1SJohn Marino if ((si = PKCS7_SIGNER_INFO_new()) == NULL)
422f5b1c8a1SJohn Marino goto err;
423f5b1c8a1SJohn Marino if (!PKCS7_SIGNER_INFO_set(si, x509, pkey, dgst))
424f5b1c8a1SJohn Marino goto err;
425f5b1c8a1SJohn Marino if (!PKCS7_add_signer(p7, si))
426f5b1c8a1SJohn Marino goto err;
427f5b1c8a1SJohn Marino return (si);
428f5b1c8a1SJohn Marino err:
429f5b1c8a1SJohn Marino if (si)
430f5b1c8a1SJohn Marino PKCS7_SIGNER_INFO_free(si);
431f5b1c8a1SJohn Marino return (NULL);
432f5b1c8a1SJohn Marino }
433f5b1c8a1SJohn Marino
434f5b1c8a1SJohn Marino int
PKCS7_set_digest(PKCS7 * p7,const EVP_MD * md)435f5b1c8a1SJohn Marino PKCS7_set_digest(PKCS7 *p7, const EVP_MD *md)
436f5b1c8a1SJohn Marino {
437f5b1c8a1SJohn Marino if (PKCS7_type_is_digest(p7)) {
438f5b1c8a1SJohn Marino if (!(p7->d.digest->md->parameter = ASN1_TYPE_new())) {
43972c33676SMaxim Ag PKCS7error(ERR_R_MALLOC_FAILURE);
440f5b1c8a1SJohn Marino return 0;
441f5b1c8a1SJohn Marino }
442f5b1c8a1SJohn Marino p7->d.digest->md->parameter->type = V_ASN1_NULL;
443f5b1c8a1SJohn Marino p7->d.digest->md->algorithm = OBJ_nid2obj(EVP_MD_nid(md));
444f5b1c8a1SJohn Marino return 1;
445f5b1c8a1SJohn Marino }
446f5b1c8a1SJohn Marino
44772c33676SMaxim Ag PKCS7error(PKCS7_R_WRONG_CONTENT_TYPE);
448f5b1c8a1SJohn Marino return 1;
449f5b1c8a1SJohn Marino }
450f5b1c8a1SJohn Marino
STACK_OF(PKCS7_SIGNER_INFO)451f5b1c8a1SJohn Marino STACK_OF(PKCS7_SIGNER_INFO) *
452f5b1c8a1SJohn Marino PKCS7_get_signer_info(PKCS7 *p7)
453f5b1c8a1SJohn Marino {
454f5b1c8a1SJohn Marino if (p7 == NULL || p7->d.ptr == NULL)
455f5b1c8a1SJohn Marino return (NULL);
456f5b1c8a1SJohn Marino if (PKCS7_type_is_signed(p7)) {
457f5b1c8a1SJohn Marino return (p7->d.sign->signer_info);
458f5b1c8a1SJohn Marino } else if (PKCS7_type_is_signedAndEnveloped(p7)) {
459f5b1c8a1SJohn Marino return (p7->d.signed_and_enveloped->signer_info);
460f5b1c8a1SJohn Marino } else
461f5b1c8a1SJohn Marino return (NULL);
462f5b1c8a1SJohn Marino }
463f5b1c8a1SJohn Marino
464f5b1c8a1SJohn Marino void
PKCS7_SIGNER_INFO_get0_algs(PKCS7_SIGNER_INFO * si,EVP_PKEY ** pk,X509_ALGOR ** pdig,X509_ALGOR ** psig)465f5b1c8a1SJohn Marino PKCS7_SIGNER_INFO_get0_algs(PKCS7_SIGNER_INFO *si, EVP_PKEY **pk,
466f5b1c8a1SJohn Marino X509_ALGOR **pdig, X509_ALGOR **psig)
467f5b1c8a1SJohn Marino {
468f5b1c8a1SJohn Marino if (pk)
469f5b1c8a1SJohn Marino *pk = si->pkey;
470f5b1c8a1SJohn Marino if (pdig)
471f5b1c8a1SJohn Marino *pdig = si->digest_alg;
472f5b1c8a1SJohn Marino if (psig)
473f5b1c8a1SJohn Marino *psig = si->digest_enc_alg;
474f5b1c8a1SJohn Marino }
475f5b1c8a1SJohn Marino
476f5b1c8a1SJohn Marino void
PKCS7_RECIP_INFO_get0_alg(PKCS7_RECIP_INFO * ri,X509_ALGOR ** penc)477f5b1c8a1SJohn Marino PKCS7_RECIP_INFO_get0_alg(PKCS7_RECIP_INFO *ri, X509_ALGOR **penc)
478f5b1c8a1SJohn Marino {
479f5b1c8a1SJohn Marino if (penc)
480f5b1c8a1SJohn Marino *penc = ri->key_enc_algor;
481f5b1c8a1SJohn Marino }
482f5b1c8a1SJohn Marino
483f5b1c8a1SJohn Marino PKCS7_RECIP_INFO *
PKCS7_add_recipient(PKCS7 * p7,X509 * x509)484f5b1c8a1SJohn Marino PKCS7_add_recipient(PKCS7 *p7, X509 *x509)
485f5b1c8a1SJohn Marino {
486f5b1c8a1SJohn Marino PKCS7_RECIP_INFO *ri;
487f5b1c8a1SJohn Marino
488f5b1c8a1SJohn Marino if ((ri = PKCS7_RECIP_INFO_new()) == NULL)
489f5b1c8a1SJohn Marino goto err;
490f5b1c8a1SJohn Marino if (!PKCS7_RECIP_INFO_set(ri, x509))
491f5b1c8a1SJohn Marino goto err;
492f5b1c8a1SJohn Marino if (!PKCS7_add_recipient_info(p7, ri))
493f5b1c8a1SJohn Marino goto err;
494f5b1c8a1SJohn Marino return ri;
495f5b1c8a1SJohn Marino err:
496f5b1c8a1SJohn Marino if (ri)
497f5b1c8a1SJohn Marino PKCS7_RECIP_INFO_free(ri);
498f5b1c8a1SJohn Marino return NULL;
499f5b1c8a1SJohn Marino }
500f5b1c8a1SJohn Marino
501f5b1c8a1SJohn Marino int
PKCS7_add_recipient_info(PKCS7 * p7,PKCS7_RECIP_INFO * ri)502f5b1c8a1SJohn Marino PKCS7_add_recipient_info(PKCS7 *p7, PKCS7_RECIP_INFO *ri)
503f5b1c8a1SJohn Marino {
504f5b1c8a1SJohn Marino int i;
505f5b1c8a1SJohn Marino STACK_OF(PKCS7_RECIP_INFO) *sk;
506f5b1c8a1SJohn Marino
507f5b1c8a1SJohn Marino i = OBJ_obj2nid(p7->type);
508f5b1c8a1SJohn Marino switch (i) {
509f5b1c8a1SJohn Marino case NID_pkcs7_signedAndEnveloped:
510f5b1c8a1SJohn Marino sk = p7->d.signed_and_enveloped->recipientinfo;
511f5b1c8a1SJohn Marino break;
512f5b1c8a1SJohn Marino case NID_pkcs7_enveloped:
513f5b1c8a1SJohn Marino sk = p7->d.enveloped->recipientinfo;
514f5b1c8a1SJohn Marino break;
515f5b1c8a1SJohn Marino default:
51672c33676SMaxim Ag PKCS7error(PKCS7_R_WRONG_CONTENT_TYPE);
517f5b1c8a1SJohn Marino return (0);
518f5b1c8a1SJohn Marino }
519f5b1c8a1SJohn Marino
520f5b1c8a1SJohn Marino if (!sk_PKCS7_RECIP_INFO_push(sk, ri))
521f5b1c8a1SJohn Marino return 0;
522f5b1c8a1SJohn Marino return (1);
523f5b1c8a1SJohn Marino }
524f5b1c8a1SJohn Marino
525f5b1c8a1SJohn Marino int
PKCS7_RECIP_INFO_set(PKCS7_RECIP_INFO * p7i,X509 * x509)526f5b1c8a1SJohn Marino PKCS7_RECIP_INFO_set(PKCS7_RECIP_INFO *p7i, X509 *x509)
527f5b1c8a1SJohn Marino {
528f5b1c8a1SJohn Marino int ret;
529f5b1c8a1SJohn Marino EVP_PKEY *pkey = NULL;
530f5b1c8a1SJohn Marino if (!ASN1_INTEGER_set(p7i->version, 0))
531f5b1c8a1SJohn Marino return 0;
532f5b1c8a1SJohn Marino if (!X509_NAME_set(&p7i->issuer_and_serial->issuer,
533f5b1c8a1SJohn Marino X509_get_issuer_name(x509)))
534f5b1c8a1SJohn Marino return 0;
535f5b1c8a1SJohn Marino
536f5b1c8a1SJohn Marino ASN1_INTEGER_free(p7i->issuer_and_serial->serial);
537f5b1c8a1SJohn Marino if (!(p7i->issuer_and_serial->serial =
53872c33676SMaxim Ag ASN1_INTEGER_dup(X509_get_serialNumber(x509))))
539f5b1c8a1SJohn Marino return 0;
540f5b1c8a1SJohn Marino
541f5b1c8a1SJohn Marino pkey = X509_get_pubkey(x509);
542f5b1c8a1SJohn Marino
543f5b1c8a1SJohn Marino if (!pkey || !pkey->ameth || !pkey->ameth->pkey_ctrl) {
54472c33676SMaxim Ag PKCS7error(PKCS7_R_ENCRYPTION_NOT_SUPPORTED_FOR_THIS_KEY_TYPE);
545f5b1c8a1SJohn Marino goto err;
546f5b1c8a1SJohn Marino }
547f5b1c8a1SJohn Marino
548f5b1c8a1SJohn Marino ret = pkey->ameth->pkey_ctrl(pkey, ASN1_PKEY_CTRL_PKCS7_ENCRYPT,
549f5b1c8a1SJohn Marino 0, p7i);
550f5b1c8a1SJohn Marino if (ret == -2) {
55172c33676SMaxim Ag PKCS7error(PKCS7_R_ENCRYPTION_NOT_SUPPORTED_FOR_THIS_KEY_TYPE);
552f5b1c8a1SJohn Marino goto err;
553f5b1c8a1SJohn Marino }
554f5b1c8a1SJohn Marino if (ret <= 0) {
55572c33676SMaxim Ag PKCS7error(PKCS7_R_ENCRYPTION_CTRL_FAILURE);
556f5b1c8a1SJohn Marino goto err;
557f5b1c8a1SJohn Marino }
558f5b1c8a1SJohn Marino
559f5b1c8a1SJohn Marino EVP_PKEY_free(pkey);
560f5b1c8a1SJohn Marino
561f5b1c8a1SJohn Marino CRYPTO_add(&x509->references, 1, CRYPTO_LOCK_X509);
562f5b1c8a1SJohn Marino p7i->cert = x509;
563f5b1c8a1SJohn Marino
564f5b1c8a1SJohn Marino return 1;
565f5b1c8a1SJohn Marino
566f5b1c8a1SJohn Marino err:
567f5b1c8a1SJohn Marino EVP_PKEY_free(pkey);
568f5b1c8a1SJohn Marino return 0;
569f5b1c8a1SJohn Marino }
570f5b1c8a1SJohn Marino
571f5b1c8a1SJohn Marino X509 *
PKCS7_cert_from_signer_info(PKCS7 * p7,PKCS7_SIGNER_INFO * si)572f5b1c8a1SJohn Marino PKCS7_cert_from_signer_info(PKCS7 *p7, PKCS7_SIGNER_INFO *si)
573f5b1c8a1SJohn Marino {
574f5b1c8a1SJohn Marino if (PKCS7_type_is_signed(p7))
575f5b1c8a1SJohn Marino return(X509_find_by_issuer_and_serial(p7->d.sign->cert,
576f5b1c8a1SJohn Marino si->issuer_and_serial->issuer,
577f5b1c8a1SJohn Marino si->issuer_and_serial->serial));
578f5b1c8a1SJohn Marino else
579f5b1c8a1SJohn Marino return (NULL);
580f5b1c8a1SJohn Marino }
581f5b1c8a1SJohn Marino
582f5b1c8a1SJohn Marino int
PKCS7_set_cipher(PKCS7 * p7,const EVP_CIPHER * cipher)583f5b1c8a1SJohn Marino PKCS7_set_cipher(PKCS7 *p7, const EVP_CIPHER *cipher)
584f5b1c8a1SJohn Marino {
585f5b1c8a1SJohn Marino int i;
586f5b1c8a1SJohn Marino PKCS7_ENC_CONTENT *ec;
587f5b1c8a1SJohn Marino
588f5b1c8a1SJohn Marino i = OBJ_obj2nid(p7->type);
589f5b1c8a1SJohn Marino switch (i) {
590f5b1c8a1SJohn Marino case NID_pkcs7_signedAndEnveloped:
591f5b1c8a1SJohn Marino ec = p7->d.signed_and_enveloped->enc_data;
592f5b1c8a1SJohn Marino break;
593f5b1c8a1SJohn Marino case NID_pkcs7_enveloped:
594f5b1c8a1SJohn Marino ec = p7->d.enveloped->enc_data;
595f5b1c8a1SJohn Marino break;
596f5b1c8a1SJohn Marino default:
59772c33676SMaxim Ag PKCS7error(PKCS7_R_WRONG_CONTENT_TYPE);
598f5b1c8a1SJohn Marino return (0);
599f5b1c8a1SJohn Marino }
600f5b1c8a1SJohn Marino
601f5b1c8a1SJohn Marino /* Check cipher OID exists and has data in it*/
602f5b1c8a1SJohn Marino i = EVP_CIPHER_type(cipher);
603f5b1c8a1SJohn Marino if (i == NID_undef) {
60472c33676SMaxim Ag PKCS7error(PKCS7_R_CIPHER_HAS_NO_OBJECT_IDENTIFIER);
605f5b1c8a1SJohn Marino return (0);
606f5b1c8a1SJohn Marino }
607f5b1c8a1SJohn Marino
608f5b1c8a1SJohn Marino ec->cipher = cipher;
609f5b1c8a1SJohn Marino return 1;
610f5b1c8a1SJohn Marino }
611f5b1c8a1SJohn Marino
612f5b1c8a1SJohn Marino int
PKCS7_stream(unsigned char *** boundary,PKCS7 * p7)613f5b1c8a1SJohn Marino PKCS7_stream(unsigned char ***boundary, PKCS7 *p7)
614f5b1c8a1SJohn Marino {
615f5b1c8a1SJohn Marino ASN1_OCTET_STRING *os = NULL;
616f5b1c8a1SJohn Marino
617f5b1c8a1SJohn Marino switch (OBJ_obj2nid(p7->type)) {
618f5b1c8a1SJohn Marino case NID_pkcs7_data:
619f5b1c8a1SJohn Marino os = p7->d.data;
620f5b1c8a1SJohn Marino break;
621f5b1c8a1SJohn Marino
622f5b1c8a1SJohn Marino case NID_pkcs7_signedAndEnveloped:
623f5b1c8a1SJohn Marino os = p7->d.signed_and_enveloped->enc_data->enc_data;
624f5b1c8a1SJohn Marino if (os == NULL) {
625f5b1c8a1SJohn Marino os = ASN1_OCTET_STRING_new();
626f5b1c8a1SJohn Marino p7->d.signed_and_enveloped->enc_data->enc_data = os;
627f5b1c8a1SJohn Marino }
628f5b1c8a1SJohn Marino break;
629f5b1c8a1SJohn Marino
630f5b1c8a1SJohn Marino case NID_pkcs7_enveloped:
631f5b1c8a1SJohn Marino os = p7->d.enveloped->enc_data->enc_data;
632f5b1c8a1SJohn Marino if (os == NULL) {
633f5b1c8a1SJohn Marino os = ASN1_OCTET_STRING_new();
634f5b1c8a1SJohn Marino p7->d.enveloped->enc_data->enc_data = os;
635f5b1c8a1SJohn Marino }
636f5b1c8a1SJohn Marino break;
637f5b1c8a1SJohn Marino
638f5b1c8a1SJohn Marino case NID_pkcs7_signed:
639f5b1c8a1SJohn Marino os = p7->d.sign->contents->d.data;
640f5b1c8a1SJohn Marino break;
641f5b1c8a1SJohn Marino
642f5b1c8a1SJohn Marino default:
643f5b1c8a1SJohn Marino os = NULL;
644f5b1c8a1SJohn Marino break;
645f5b1c8a1SJohn Marino }
646f5b1c8a1SJohn Marino
647f5b1c8a1SJohn Marino if (os == NULL)
648f5b1c8a1SJohn Marino return 0;
649f5b1c8a1SJohn Marino
650f5b1c8a1SJohn Marino os->flags |= ASN1_STRING_FLAG_NDEF;
651f5b1c8a1SJohn Marino *boundary = &os->data;
652f5b1c8a1SJohn Marino
653f5b1c8a1SJohn Marino return 1;
654f5b1c8a1SJohn Marino }
655