]>
Commit | Line | Data |
---|---|---|
62867571 | 1 | /* |
4333b89f | 2 | * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. |
d02b48c6 | 3 | * |
b7617a3a | 4 | * Licensed under the Apache License 2.0 (the "License"). You may not use |
62867571 RS |
5 | * this file except in compliance with the License. You can obtain a copy |
6 | * in the file LICENSE in the source distribution or at | |
7 | * https://www.openssl.org/source/license.html | |
d02b48c6 RE |
8 | */ |
9 | ||
10 | #include <stdio.h> | |
b39fc560 | 11 | #include "internal/cryptlib.h" |
ec577822 BM |
12 | #include <openssl/objects.h> |
13 | #include <openssl/x509.h> | |
3e878d92 | 14 | #include <openssl/pkcs7.h> |
25f2138b DMSP |
15 | #include "crypto/asn1.h" |
16 | #include "crypto/evp.h" | |
eeccc237 | 17 | #include "crypto/x509.h" /* for sk_X509_add1_cert() */ |
90a1f2d7 | 18 | #include "pk7_local.h" |
d02b48c6 | 19 | |
6b691a5c | 20 | long PKCS7_ctrl(PKCS7 *p7, int cmd, long larg, char *parg) |
0f113f3e MC |
21 | { |
22 | int nid; | |
23 | long ret; | |
24 | ||
25 | nid = OBJ_obj2nid(p7->type); | |
26 | ||
27 | switch (cmd) { | |
c225c3cf | 28 | /* NOTE(emilia): does not support detached digested data. */ |
0f113f3e MC |
29 | case PKCS7_OP_SET_DETACHED_SIGNATURE: |
30 | if (nid == NID_pkcs7_signed) { | |
31 | ret = p7->detached = (int)larg; | |
32 | if (ret && PKCS7_type_is_data(p7->d.sign->contents)) { | |
33 | ASN1_OCTET_STRING *os; | |
34 | os = p7->d.sign->contents->d.data; | |
35 | ASN1_OCTET_STRING_free(os); | |
36 | p7->d.sign->contents->d.data = NULL; | |
37 | } | |
38 | } else { | |
9311d0c4 RL |
39 | ERR_raise(ERR_LIB_PKCS7, |
40 | PKCS7_R_OPERATION_NOT_SUPPORTED_ON_THIS_TYPE); | |
0f113f3e MC |
41 | ret = 0; |
42 | } | |
43 | break; | |
44 | case PKCS7_OP_GET_DETACHED_SIGNATURE: | |
45 | if (nid == NID_pkcs7_signed) { | |
12a765a5 | 46 | if (p7->d.sign == NULL || p7->d.sign->contents->d.ptr == NULL) |
0f113f3e MC |
47 | ret = 1; |
48 | else | |
49 | ret = 0; | |
50 | ||
51 | p7->detached = ret; | |
52 | } else { | |
9311d0c4 RL |
53 | ERR_raise(ERR_LIB_PKCS7, |
54 | PKCS7_R_OPERATION_NOT_SUPPORTED_ON_THIS_TYPE); | |
0f113f3e MC |
55 | ret = 0; |
56 | } | |
57 | ||
58 | break; | |
59 | default: | |
9311d0c4 | 60 | ERR_raise(ERR_LIB_PKCS7, PKCS7_R_UNKNOWN_OPERATION); |
0f113f3e MC |
61 | ret = 0; |
62 | } | |
26a7d938 | 63 | return ret; |
0f113f3e | 64 | } |
d02b48c6 | 65 | |
6b691a5c | 66 | int PKCS7_content_new(PKCS7 *p7, int type) |
0f113f3e MC |
67 | { |
68 | PKCS7 *ret = NULL; | |
69 | ||
70 | if ((ret = PKCS7_new()) == NULL) | |
71 | goto err; | |
72 | if (!PKCS7_set_type(ret, type)) | |
73 | goto err; | |
74 | if (!PKCS7_set_content(p7, ret)) | |
75 | goto err; | |
76 | ||
208fb891 | 77 | return 1; |
0f113f3e | 78 | err: |
e0e920b1 | 79 | PKCS7_free(ret); |
26a7d938 | 80 | return 0; |
0f113f3e | 81 | } |
d02b48c6 | 82 | |
6b691a5c | 83 | int PKCS7_set_content(PKCS7 *p7, PKCS7 *p7_data) |
0f113f3e MC |
84 | { |
85 | int i; | |
86 | ||
87 | i = OBJ_obj2nid(p7->type); | |
88 | switch (i) { | |
89 | case NID_pkcs7_signed: | |
e0e920b1 | 90 | PKCS7_free(p7->d.sign->contents); |
0f113f3e MC |
91 | p7->d.sign->contents = p7_data; |
92 | break; | |
93 | case NID_pkcs7_digest: | |
e0e920b1 | 94 | PKCS7_free(p7->d.digest->contents); |
0f113f3e MC |
95 | p7->d.digest->contents = p7_data; |
96 | break; | |
97 | case NID_pkcs7_data: | |
98 | case NID_pkcs7_enveloped: | |
99 | case NID_pkcs7_signedAndEnveloped: | |
100 | case NID_pkcs7_encrypted: | |
101 | default: | |
9311d0c4 | 102 | ERR_raise(ERR_LIB_PKCS7, PKCS7_R_UNSUPPORTED_CONTENT_TYPE); |
0f113f3e MC |
103 | goto err; |
104 | } | |
208fb891 | 105 | return 1; |
0f113f3e | 106 | err: |
26a7d938 | 107 | return 0; |
0f113f3e | 108 | } |
d02b48c6 | 109 | |
6b691a5c | 110 | int PKCS7_set_type(PKCS7 *p7, int type) |
0f113f3e MC |
111 | { |
112 | ASN1_OBJECT *obj; | |
113 | ||
114 | /* | |
115 | * PKCS7_content_free(p7); | |
116 | */ | |
117 | obj = OBJ_nid2obj(type); /* will not fail */ | |
118 | ||
119 | switch (type) { | |
120 | case NID_pkcs7_signed: | |
121 | p7->type = obj; | |
122 | if ((p7->d.sign = PKCS7_SIGNED_new()) == NULL) | |
123 | goto err; | |
124 | if (!ASN1_INTEGER_set(p7->d.sign->version, 1)) { | |
125 | PKCS7_SIGNED_free(p7->d.sign); | |
126 | p7->d.sign = NULL; | |
127 | goto err; | |
128 | } | |
129 | break; | |
130 | case NID_pkcs7_data: | |
131 | p7->type = obj; | |
f422a514 | 132 | if ((p7->d.data = ASN1_OCTET_STRING_new()) == NULL) |
0f113f3e MC |
133 | goto err; |
134 | break; | |
135 | case NID_pkcs7_signedAndEnveloped: | |
136 | p7->type = obj; | |
137 | if ((p7->d.signed_and_enveloped = PKCS7_SIGN_ENVELOPE_new()) | |
138 | == NULL) | |
139 | goto err; | |
0f113f3e MC |
140 | if (!ASN1_INTEGER_set(p7->d.signed_and_enveloped->version, 1)) |
141 | goto err; | |
142 | p7->d.signed_and_enveloped->enc_data->content_type | |
143 | = OBJ_nid2obj(NID_pkcs7_data); | |
144 | break; | |
145 | case NID_pkcs7_enveloped: | |
146 | p7->type = obj; | |
147 | if ((p7->d.enveloped = PKCS7_ENVELOPE_new()) | |
148 | == NULL) | |
149 | goto err; | |
150 | if (!ASN1_INTEGER_set(p7->d.enveloped->version, 0)) | |
151 | goto err; | |
152 | p7->d.enveloped->enc_data->content_type = OBJ_nid2obj(NID_pkcs7_data); | |
153 | break; | |
154 | case NID_pkcs7_encrypted: | |
155 | p7->type = obj; | |
156 | if ((p7->d.encrypted = PKCS7_ENCRYPT_new()) | |
157 | == NULL) | |
158 | goto err; | |
159 | if (!ASN1_INTEGER_set(p7->d.encrypted->version, 0)) | |
160 | goto err; | |
161 | p7->d.encrypted->enc_data->content_type = OBJ_nid2obj(NID_pkcs7_data); | |
162 | break; | |
163 | ||
164 | case NID_pkcs7_digest: | |
165 | p7->type = obj; | |
166 | if ((p7->d.digest = PKCS7_DIGEST_new()) | |
167 | == NULL) | |
168 | goto err; | |
169 | if (!ASN1_INTEGER_set(p7->d.digest->version, 0)) | |
170 | goto err; | |
171 | break; | |
172 | default: | |
9311d0c4 | 173 | ERR_raise(ERR_LIB_PKCS7, PKCS7_R_UNSUPPORTED_CONTENT_TYPE); |
0f113f3e MC |
174 | goto err; |
175 | } | |
208fb891 | 176 | return 1; |
0f113f3e | 177 | err: |
26a7d938 | 178 | return 0; |
0f113f3e | 179 | } |
d02b48c6 | 180 | |
8d9086df | 181 | int PKCS7_set0_type_other(PKCS7 *p7, int type, ASN1_TYPE *other) |
0f113f3e MC |
182 | { |
183 | p7->type = OBJ_nid2obj(type); | |
184 | p7->d.other = other; | |
185 | return 1; | |
186 | } | |
8d9086df | 187 | |
6b691a5c | 188 | int PKCS7_add_signer(PKCS7 *p7, PKCS7_SIGNER_INFO *psi) |
0f113f3e MC |
189 | { |
190 | int i, j, nid; | |
191 | X509_ALGOR *alg; | |
192 | STACK_OF(PKCS7_SIGNER_INFO) *signer_sk; | |
193 | STACK_OF(X509_ALGOR) *md_sk; | |
194 | ||
195 | i = OBJ_obj2nid(p7->type); | |
196 | switch (i) { | |
197 | case NID_pkcs7_signed: | |
198 | signer_sk = p7->d.sign->signer_info; | |
199 | md_sk = p7->d.sign->md_algs; | |
200 | break; | |
201 | case NID_pkcs7_signedAndEnveloped: | |
202 | signer_sk = p7->d.signed_and_enveloped->signer_info; | |
203 | md_sk = p7->d.signed_and_enveloped->md_algs; | |
204 | break; | |
205 | default: | |
9311d0c4 | 206 | ERR_raise(ERR_LIB_PKCS7, PKCS7_R_WRONG_CONTENT_TYPE); |
26a7d938 | 207 | return 0; |
0f113f3e MC |
208 | } |
209 | ||
210 | nid = OBJ_obj2nid(psi->digest_alg->algorithm); | |
211 | ||
212 | /* If the digest is not currently listed, add it */ | |
213 | j = 0; | |
214 | for (i = 0; i < sk_X509_ALGOR_num(md_sk); i++) { | |
215 | alg = sk_X509_ALGOR_value(md_sk, i); | |
216 | if (OBJ_obj2nid(alg->algorithm) == nid) { | |
217 | j = 1; | |
218 | break; | |
219 | } | |
220 | } | |
221 | if (!j) { /* we need to add another algorithm */ | |
75ebbd9a RS |
222 | if ((alg = X509_ALGOR_new()) == NULL |
223 | || (alg->parameter = ASN1_TYPE_new()) == NULL) { | |
0f113f3e | 224 | X509_ALGOR_free(alg); |
9311d0c4 | 225 | ERR_raise(ERR_LIB_PKCS7, ERR_R_MALLOC_FAILURE); |
26a7d938 | 226 | return 0; |
0f113f3e MC |
227 | } |
228 | alg->algorithm = OBJ_nid2obj(nid); | |
229 | alg->parameter->type = V_ASN1_NULL; | |
230 | if (!sk_X509_ALGOR_push(md_sk, alg)) { | |
231 | X509_ALGOR_free(alg); | |
232 | return 0; | |
233 | } | |
234 | } | |
235 | ||
681618cf | 236 | psi->ctx = ossl_pkcs7_get0_ctx(p7); |
0f113f3e MC |
237 | if (!sk_PKCS7_SIGNER_INFO_push(signer_sk, psi)) |
238 | return 0; | |
208fb891 | 239 | return 1; |
0f113f3e | 240 | } |
d02b48c6 | 241 | |
6b691a5c | 242 | int PKCS7_add_certificate(PKCS7 *p7, X509 *x509) |
0f113f3e MC |
243 | { |
244 | int i; | |
245 | STACK_OF(X509) **sk; | |
246 | ||
247 | i = OBJ_obj2nid(p7->type); | |
248 | switch (i) { | |
249 | case NID_pkcs7_signed: | |
250 | sk = &(p7->d.sign->cert); | |
251 | break; | |
252 | case NID_pkcs7_signedAndEnveloped: | |
253 | sk = &(p7->d.signed_and_enveloped->cert); | |
254 | break; | |
255 | default: | |
9311d0c4 | 256 | ERR_raise(ERR_LIB_PKCS7, PKCS7_R_WRONG_CONTENT_TYPE); |
26a7d938 | 257 | return 0; |
0f113f3e MC |
258 | } |
259 | ||
c1be4d61 | 260 | return ossl_x509_add_cert_new(sk, x509, X509_ADD_FLAG_UP_REF); |
0f113f3e | 261 | } |
d02b48c6 | 262 | |
6b691a5c | 263 | int PKCS7_add_crl(PKCS7 *p7, X509_CRL *crl) |
0f113f3e MC |
264 | { |
265 | int i; | |
266 | STACK_OF(X509_CRL) **sk; | |
267 | ||
268 | i = OBJ_obj2nid(p7->type); | |
269 | switch (i) { | |
270 | case NID_pkcs7_signed: | |
271 | sk = &(p7->d.sign->crl); | |
272 | break; | |
273 | case NID_pkcs7_signedAndEnveloped: | |
274 | sk = &(p7->d.signed_and_enveloped->crl); | |
275 | break; | |
276 | default: | |
9311d0c4 | 277 | ERR_raise(ERR_LIB_PKCS7, PKCS7_R_WRONG_CONTENT_TYPE); |
26a7d938 | 278 | return 0; |
0f113f3e MC |
279 | } |
280 | ||
281 | if (*sk == NULL) | |
282 | *sk = sk_X509_CRL_new_null(); | |
283 | if (*sk == NULL) { | |
9311d0c4 | 284 | ERR_raise(ERR_LIB_PKCS7, ERR_R_MALLOC_FAILURE); |
0f113f3e MC |
285 | return 0; |
286 | } | |
287 | ||
65cbf983 | 288 | X509_CRL_up_ref(crl); |
0f113f3e MC |
289 | if (!sk_X509_CRL_push(*sk, crl)) { |
290 | X509_CRL_free(crl); | |
291 | return 0; | |
292 | } | |
208fb891 | 293 | return 1; |
0f113f3e | 294 | } |
d02b48c6 | 295 | |
3e878d92 SL |
296 | static int pkcs7_ecdsa_or_dsa_sign_verify_setup(PKCS7_SIGNER_INFO *si, |
297 | int verify) | |
298 | { | |
299 | if (verify == 0) { | |
300 | int snid, hnid; | |
301 | X509_ALGOR *alg1, *alg2; | |
302 | EVP_PKEY *pkey = si->pkey; | |
303 | ||
304 | PKCS7_SIGNER_INFO_get0_algs(si, NULL, &alg1, &alg2); | |
305 | if (alg1 == NULL || alg1->algorithm == NULL) | |
306 | return -1; | |
307 | hnid = OBJ_obj2nid(alg1->algorithm); | |
308 | if (hnid == NID_undef) | |
309 | return -1; | |
310 | if (!OBJ_find_sigid_by_algs(&snid, hnid, EVP_PKEY_id(pkey))) | |
311 | return -1; | |
312 | X509_ALGOR_set0(alg2, OBJ_nid2obj(snid), V_ASN1_UNDEF, 0); | |
313 | } | |
314 | return 1; | |
315 | } | |
316 | ||
317 | static int pkcs7_rsa_sign_verify_setup(PKCS7_SIGNER_INFO *si, int verify) | |
318 | { | |
319 | if (verify == 0) { | |
320 | X509_ALGOR *alg = NULL; | |
321 | ||
322 | PKCS7_SIGNER_INFO_get0_algs(si, NULL, NULL, &alg); | |
323 | if (alg != NULL) | |
324 | X509_ALGOR_set0(alg, OBJ_nid2obj(NID_rsaEncryption), V_ASN1_NULL, 0); | |
325 | } | |
326 | return 1; | |
327 | } | |
328 | ||
6b691a5c | 329 | int PKCS7_SIGNER_INFO_set(PKCS7_SIGNER_INFO *p7i, X509 *x509, EVP_PKEY *pkey, |
0f113f3e MC |
330 | const EVP_MD *dgst) |
331 | { | |
332 | int ret; | |
333 | ||
334 | /* We now need to add another PKCS7_SIGNER_INFO entry */ | |
335 | if (!ASN1_INTEGER_set(p7i->version, 1)) | |
336 | goto err; | |
337 | if (!X509_NAME_set(&p7i->issuer_and_serial->issuer, | |
338 | X509_get_issuer_name(x509))) | |
339 | goto err; | |
340 | ||
341 | /* | |
342 | * because ASN1_INTEGER_set is used to set a 'long' we will do things the | |
343 | * ugly way. | |
344 | */ | |
f422a514 | 345 | ASN1_INTEGER_free(p7i->issuer_and_serial->serial); |
0f113f3e | 346 | if (!(p7i->issuer_and_serial->serial = |
1337a3a9 | 347 | ASN1_INTEGER_dup(X509_get0_serialNumber(x509)))) |
0f113f3e MC |
348 | goto err; |
349 | ||
350 | /* lets keep the pkey around for a while */ | |
3aeb9348 | 351 | EVP_PKEY_up_ref(pkey); |
0f113f3e MC |
352 | p7i->pkey = pkey; |
353 | ||
354 | /* Set the algorithms */ | |
355 | ||
356 | X509_ALGOR_set0(p7i->digest_alg, OBJ_nid2obj(EVP_MD_type(dgst)), | |
357 | V_ASN1_NULL, NULL); | |
358 | ||
3e878d92 SL |
359 | if (EVP_PKEY_is_a(pkey, "EC") || EVP_PKEY_is_a(pkey, "DSA")) |
360 | return pkcs7_ecdsa_or_dsa_sign_verify_setup(p7i, 0); | |
361 | if (EVP_PKEY_is_a(pkey, "RSA")) | |
362 | return pkcs7_rsa_sign_verify_setup(p7i, 0); | |
363 | ||
364 | if (pkey->ameth != NULL && pkey->ameth->pkey_ctrl != NULL) { | |
0f113f3e MC |
365 | ret = pkey->ameth->pkey_ctrl(pkey, ASN1_PKEY_CTRL_PKCS7_SIGN, 0, p7i); |
366 | if (ret > 0) | |
367 | return 1; | |
368 | if (ret != -2) { | |
9311d0c4 | 369 | ERR_raise(ERR_LIB_PKCS7, PKCS7_R_SIGNING_CTRL_FAILURE); |
0f113f3e MC |
370 | return 0; |
371 | } | |
372 | } | |
9311d0c4 | 373 | ERR_raise(ERR_LIB_PKCS7, PKCS7_R_SIGNING_NOT_SUPPORTED_FOR_THIS_KEY_TYPE); |
0f113f3e MC |
374 | err: |
375 | return 0; | |
376 | } | |
d02b48c6 | 377 | |
6b691a5c | 378 | PKCS7_SIGNER_INFO *PKCS7_add_signature(PKCS7 *p7, X509 *x509, EVP_PKEY *pkey, |
0f113f3e MC |
379 | const EVP_MD *dgst) |
380 | { | |
381 | PKCS7_SIGNER_INFO *si = NULL; | |
382 | ||
383 | if (dgst == NULL) { | |
384 | int def_nid; | |
385 | if (EVP_PKEY_get_default_digest_nid(pkey, &def_nid) <= 0) | |
386 | goto err; | |
387 | dgst = EVP_get_digestbynid(def_nid); | |
388 | if (dgst == NULL) { | |
9311d0c4 | 389 | ERR_raise(ERR_LIB_PKCS7, PKCS7_R_NO_DEFAULT_DIGEST); |
0f113f3e MC |
390 | goto err; |
391 | } | |
392 | } | |
393 | ||
394 | if ((si = PKCS7_SIGNER_INFO_new()) == NULL) | |
395 | goto err; | |
396 | if (!PKCS7_SIGNER_INFO_set(si, x509, pkey, dgst)) | |
397 | goto err; | |
398 | if (!PKCS7_add_signer(p7, si)) | |
399 | goto err; | |
26a7d938 | 400 | return si; |
0f113f3e | 401 | err: |
e0e920b1 | 402 | PKCS7_SIGNER_INFO_free(si); |
26a7d938 | 403 | return NULL; |
0f113f3e | 404 | } |
d02b48c6 | 405 | |
90a1f2d7 SL |
406 | static STACK_OF(X509) *pkcs7_get_signer_certs(const PKCS7 *p7) |
407 | { | |
408 | if (PKCS7_type_is_signed(p7)) | |
409 | return p7->d.sign->cert; | |
410 | if (PKCS7_type_is_signedAndEnveloped(p7)) | |
411 | return p7->d.signed_and_enveloped->cert; | |
412 | return NULL; | |
413 | } | |
414 | ||
415 | static STACK_OF(PKCS7_RECIP_INFO) *pkcs7_get_recipient_info(const PKCS7 *p7) | |
416 | { | |
417 | if (PKCS7_type_is_signedAndEnveloped(p7)) | |
418 | return p7->d.signed_and_enveloped->recipientinfo; | |
419 | if (PKCS7_type_is_enveloped(p7)) | |
420 | return p7->d.enveloped->recipientinfo; | |
421 | return NULL; | |
422 | } | |
423 | ||
424 | /* | |
425 | * Set up the library context into any loaded structure that needs it. | |
426 | * i.e loaded X509 objects. | |
427 | */ | |
681618cf | 428 | void ossl_pkcs7_resolve_libctx(PKCS7 *p7) |
90a1f2d7 SL |
429 | { |
430 | int i; | |
681618cf SL |
431 | const PKCS7_CTX *ctx = ossl_pkcs7_get0_ctx(p7); |
432 | OSSL_LIB_CTX *libctx = ossl_pkcs7_ctx_get0_libctx(ctx); | |
433 | const char *propq = ossl_pkcs7_ctx_get0_propq(ctx); | |
90a1f2d7 SL |
434 | STACK_OF(PKCS7_RECIP_INFO) *rinfos = pkcs7_get_recipient_info(p7); |
435 | STACK_OF(PKCS7_SIGNER_INFO) *sinfos = PKCS7_get_signer_info(p7); | |
436 | STACK_OF(X509) *certs = pkcs7_get_signer_certs(p7); | |
437 | ||
438 | if (ctx == NULL) | |
439 | return; | |
440 | ||
441 | for (i = 0; i < sk_X509_num(certs); i++) | |
4669015d | 442 | ossl_x509_set0_libctx(sk_X509_value(certs, i), libctx, propq); |
90a1f2d7 SL |
443 | |
444 | for (i = 0; i < sk_PKCS7_RECIP_INFO_num(rinfos); i++) { | |
445 | PKCS7_RECIP_INFO *ri = sk_PKCS7_RECIP_INFO_value(rinfos, i); | |
446 | ||
4669015d | 447 | ossl_x509_set0_libctx(ri->cert, libctx, propq); |
90a1f2d7 SL |
448 | } |
449 | ||
450 | for (i = 0; i < sk_PKCS7_SIGNER_INFO_num(sinfos); i++) { | |
451 | PKCS7_SIGNER_INFO *si = sk_PKCS7_SIGNER_INFO_value(sinfos, i); | |
452 | ||
453 | if (si != NULL) | |
454 | si->ctx = ctx; | |
455 | } | |
456 | } | |
457 | ||
681618cf | 458 | const PKCS7_CTX *ossl_pkcs7_get0_ctx(const PKCS7 *p7) |
90a1f2d7 SL |
459 | { |
460 | return p7 != NULL ? &p7->ctx : NULL; | |
461 | } | |
462 | ||
681618cf | 463 | OSSL_LIB_CTX *ossl_pkcs7_ctx_get0_libctx(const PKCS7_CTX *ctx) |
90a1f2d7 SL |
464 | { |
465 | return ctx != NULL ? ctx->libctx : NULL; | |
466 | } | |
681618cf | 467 | const char *ossl_pkcs7_ctx_get0_propq(const PKCS7_CTX *ctx) |
90a1f2d7 SL |
468 | { |
469 | return ctx != NULL ? ctx->propq : NULL; | |
470 | } | |
471 | ||
c5a55463 | 472 | int PKCS7_set_digest(PKCS7 *p7, const EVP_MD *md) |
0f113f3e MC |
473 | { |
474 | if (PKCS7_type_is_digest(p7)) { | |
75ebbd9a | 475 | if ((p7->d.digest->md->parameter = ASN1_TYPE_new()) == NULL) { |
9311d0c4 | 476 | ERR_raise(ERR_LIB_PKCS7, ERR_R_MALLOC_FAILURE); |
0f113f3e MC |
477 | return 0; |
478 | } | |
479 | p7->d.digest->md->parameter->type = V_ASN1_NULL; | |
480 | p7->d.digest->md->algorithm = OBJ_nid2obj(EVP_MD_nid(md)); | |
481 | return 1; | |
482 | } | |
483 | ||
9311d0c4 | 484 | ERR_raise(ERR_LIB_PKCS7, PKCS7_R_WRONG_CONTENT_TYPE); |
0f113f3e MC |
485 | return 1; |
486 | } | |
c5a55463 | 487 | |
b05b50e6 | 488 | STACK_OF(PKCS7_SIGNER_INFO) *PKCS7_get_signer_info(PKCS7 *p7) |
0f113f3e | 489 | { |
c225c3cf EK |
490 | if (p7 == NULL || p7->d.ptr == NULL) |
491 | return NULL; | |
0f113f3e | 492 | if (PKCS7_type_is_signed(p7)) { |
26a7d938 | 493 | return p7->d.sign->signer_info; |
0f113f3e | 494 | } else if (PKCS7_type_is_signedAndEnveloped(p7)) { |
26a7d938 | 495 | return p7->d.signed_and_enveloped->signer_info; |
0f113f3e | 496 | } else |
26a7d938 | 497 | return NULL; |
0f113f3e | 498 | } |
d02b48c6 | 499 | |
492a9e24 | 500 | void PKCS7_SIGNER_INFO_get0_algs(PKCS7_SIGNER_INFO *si, EVP_PKEY **pk, |
0f113f3e MC |
501 | X509_ALGOR **pdig, X509_ALGOR **psig) |
502 | { | |
503 | if (pk) | |
504 | *pk = si->pkey; | |
505 | if (pdig) | |
506 | *pdig = si->digest_alg; | |
507 | if (psig) | |
508 | *psig = si->digest_enc_alg; | |
509 | } | |
492a9e24 | 510 | |
e4b21c74 | 511 | void PKCS7_RECIP_INFO_get0_alg(PKCS7_RECIP_INFO *ri, X509_ALGOR **penc) |
0f113f3e MC |
512 | { |
513 | if (penc) | |
514 | *penc = ri->key_enc_algor; | |
515 | } | |
e4b21c74 | 516 | |
6b691a5c | 517 | PKCS7_RECIP_INFO *PKCS7_add_recipient(PKCS7 *p7, X509 *x509) |
0f113f3e MC |
518 | { |
519 | PKCS7_RECIP_INFO *ri; | |
520 | ||
521 | if ((ri = PKCS7_RECIP_INFO_new()) == NULL) | |
522 | goto err; | |
523 | if (!PKCS7_RECIP_INFO_set(ri, x509)) | |
524 | goto err; | |
525 | if (!PKCS7_add_recipient_info(p7, ri)) | |
526 | goto err; | |
681618cf | 527 | ri->ctx = ossl_pkcs7_get0_ctx(p7); |
0f113f3e MC |
528 | return ri; |
529 | err: | |
e0e920b1 | 530 | PKCS7_RECIP_INFO_free(ri); |
0f113f3e MC |
531 | return NULL; |
532 | } | |
58964a49 | 533 | |
6b691a5c | 534 | int PKCS7_add_recipient_info(PKCS7 *p7, PKCS7_RECIP_INFO *ri) |
0f113f3e MC |
535 | { |
536 | int i; | |
537 | STACK_OF(PKCS7_RECIP_INFO) *sk; | |
538 | ||
539 | i = OBJ_obj2nid(p7->type); | |
540 | switch (i) { | |
541 | case NID_pkcs7_signedAndEnveloped: | |
542 | sk = p7->d.signed_and_enveloped->recipientinfo; | |
543 | break; | |
544 | case NID_pkcs7_enveloped: | |
545 | sk = p7->d.enveloped->recipientinfo; | |
546 | break; | |
547 | default: | |
9311d0c4 | 548 | ERR_raise(ERR_LIB_PKCS7, PKCS7_R_WRONG_CONTENT_TYPE); |
26a7d938 | 549 | return 0; |
0f113f3e MC |
550 | } |
551 | ||
552 | if (!sk_PKCS7_RECIP_INFO_push(sk, ri)) | |
553 | return 0; | |
208fb891 | 554 | return 1; |
0f113f3e | 555 | } |
58964a49 | 556 | |
3e878d92 SL |
557 | static int pkcs7_rsa_encrypt_decrypt_setup(PKCS7_RECIP_INFO *ri, int decrypt) |
558 | { | |
559 | X509_ALGOR *alg = NULL; | |
560 | ||
561 | if (decrypt == 0) { | |
562 | PKCS7_RECIP_INFO_get0_alg(ri, &alg); | |
563 | if (alg != NULL) | |
564 | X509_ALGOR_set0(alg, OBJ_nid2obj(NID_rsaEncryption), V_ASN1_NULL, 0); | |
565 | } | |
566 | return 1; | |
567 | } | |
568 | ||
6b691a5c | 569 | int PKCS7_RECIP_INFO_set(PKCS7_RECIP_INFO *p7i, X509 *x509) |
0f113f3e MC |
570 | { |
571 | int ret; | |
572 | EVP_PKEY *pkey = NULL; | |
573 | if (!ASN1_INTEGER_set(p7i->version, 0)) | |
574 | return 0; | |
575 | if (!X509_NAME_set(&p7i->issuer_and_serial->issuer, | |
576 | X509_get_issuer_name(x509))) | |
577 | return 0; | |
578 | ||
f422a514 | 579 | ASN1_INTEGER_free(p7i->issuer_and_serial->serial); |
0f113f3e | 580 | if (!(p7i->issuer_and_serial->serial = |
1337a3a9 | 581 | ASN1_INTEGER_dup(X509_get0_serialNumber(x509)))) |
0f113f3e MC |
582 | return 0; |
583 | ||
8382fd3a | 584 | pkey = X509_get0_pubkey(x509); |
3e878d92 SL |
585 | if (pkey == NULL) |
586 | return 0; | |
0f113f3e | 587 | |
3e878d92 SL |
588 | if (EVP_PKEY_is_a(pkey, "RSA-PSS")) |
589 | return -2; | |
590 | if (EVP_PKEY_is_a(pkey, "RSA")) { | |
591 | if (pkcs7_rsa_encrypt_decrypt_setup(p7i, 0) <= 0) | |
592 | goto err; | |
593 | goto finished; | |
594 | } | |
595 | ||
596 | if (pkey->ameth == NULL || pkey->ameth->pkey_ctrl == NULL) { | |
9311d0c4 RL |
597 | ERR_raise(ERR_LIB_PKCS7, |
598 | PKCS7_R_ENCRYPTION_NOT_SUPPORTED_FOR_THIS_KEY_TYPE); | |
0f113f3e MC |
599 | goto err; |
600 | } | |
601 | ||
602 | ret = pkey->ameth->pkey_ctrl(pkey, ASN1_PKEY_CTRL_PKCS7_ENCRYPT, 0, p7i); | |
603 | if (ret == -2) { | |
9311d0c4 RL |
604 | ERR_raise(ERR_LIB_PKCS7, |
605 | PKCS7_R_ENCRYPTION_NOT_SUPPORTED_FOR_THIS_KEY_TYPE); | |
0f113f3e MC |
606 | goto err; |
607 | } | |
608 | if (ret <= 0) { | |
9311d0c4 | 609 | ERR_raise(ERR_LIB_PKCS7, PKCS7_R_ENCRYPTION_CTRL_FAILURE); |
0f113f3e MC |
610 | goto err; |
611 | } | |
3e878d92 | 612 | finished: |
05f0fb9f | 613 | X509_up_ref(x509); |
0f113f3e MC |
614 | p7i->cert = x509; |
615 | ||
616 | return 1; | |
617 | ||
618 | err: | |
0f113f3e MC |
619 | return 0; |
620 | } | |
58964a49 | 621 | |
6b691a5c | 622 | X509 *PKCS7_cert_from_signer_info(PKCS7 *p7, PKCS7_SIGNER_INFO *si) |
0f113f3e MC |
623 | { |
624 | if (PKCS7_type_is_signed(p7)) | |
625 | return (X509_find_by_issuer_and_serial(p7->d.sign->cert, | |
626 | si->issuer_and_serial->issuer, | |
627 | si-> | |
628 | issuer_and_serial->serial)); | |
629 | else | |
26a7d938 | 630 | return NULL; |
0f113f3e | 631 | } |
d02b48c6 | 632 | |
84fa704c | 633 | int PKCS7_set_cipher(PKCS7 *p7, const EVP_CIPHER *cipher) |
0f113f3e MC |
634 | { |
635 | int i; | |
636 | PKCS7_ENC_CONTENT *ec; | |
637 | ||
638 | i = OBJ_obj2nid(p7->type); | |
639 | switch (i) { | |
640 | case NID_pkcs7_signedAndEnveloped: | |
641 | ec = p7->d.signed_and_enveloped->enc_data; | |
642 | break; | |
643 | case NID_pkcs7_enveloped: | |
644 | ec = p7->d.enveloped->enc_data; | |
645 | break; | |
646 | default: | |
9311d0c4 | 647 | ERR_raise(ERR_LIB_PKCS7, PKCS7_R_WRONG_CONTENT_TYPE); |
26a7d938 | 648 | return 0; |
0f113f3e MC |
649 | } |
650 | ||
651 | /* Check cipher OID exists and has data in it */ | |
652 | i = EVP_CIPHER_type(cipher); | |
653 | if (i == NID_undef) { | |
9311d0c4 | 654 | ERR_raise(ERR_LIB_PKCS7, PKCS7_R_CIPHER_HAS_NO_OBJECT_IDENTIFIER); |
26a7d938 | 655 | return 0; |
0f113f3e MC |
656 | } |
657 | ||
658 | ec->cipher = cipher; | |
681618cf | 659 | ec->ctx = ossl_pkcs7_get0_ctx(p7); |
0f113f3e MC |
660 | return 1; |
661 | } | |
58964a49 | 662 | |
9fdcc21f | 663 | /* unfortunately cannot constify BIO_new_NDEF() due to this and CMS_stream() */ |
11d8cdc6 | 664 | int PKCS7_stream(unsigned char ***boundary, PKCS7 *p7) |
0f113f3e MC |
665 | { |
666 | ASN1_OCTET_STRING *os = NULL; | |
667 | ||
668 | switch (OBJ_obj2nid(p7->type)) { | |
669 | case NID_pkcs7_data: | |
670 | os = p7->d.data; | |
671 | break; | |
672 | ||
673 | case NID_pkcs7_signedAndEnveloped: | |
674 | os = p7->d.signed_and_enveloped->enc_data->enc_data; | |
675 | if (os == NULL) { | |
f422a514 | 676 | os = ASN1_OCTET_STRING_new(); |
0f113f3e MC |
677 | p7->d.signed_and_enveloped->enc_data->enc_data = os; |
678 | } | |
679 | break; | |
680 | ||
681 | case NID_pkcs7_enveloped: | |
682 | os = p7->d.enveloped->enc_data->enc_data; | |
683 | if (os == NULL) { | |
f422a514 | 684 | os = ASN1_OCTET_STRING_new(); |
0f113f3e MC |
685 | p7->d.enveloped->enc_data->enc_data = os; |
686 | } | |
687 | break; | |
688 | ||
689 | case NID_pkcs7_signed: | |
690 | os = p7->d.sign->contents->d.data; | |
691 | break; | |
692 | ||
693 | default: | |
694 | os = NULL; | |
695 | break; | |
696 | } | |
697 | ||
698 | if (os == NULL) | |
699 | return 0; | |
700 | ||
701 | os->flags |= ASN1_STRING_FLAG_NDEF; | |
702 | *boundary = &os->data; | |
703 | ||
704 | return 1; | |
705 | } |