]>
Commit | Line | Data |
---|---|---|
62867571 | 1 | /* |
da1c088f | 2 | * Copyright 1995-2023 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 | 189 | { |
ad57a13b RL |
190 | int i, j; |
191 | ASN1_OBJECT *obj; | |
0f113f3e MC |
192 | X509_ALGOR *alg; |
193 | STACK_OF(PKCS7_SIGNER_INFO) *signer_sk; | |
194 | STACK_OF(X509_ALGOR) *md_sk; | |
195 | ||
196 | i = OBJ_obj2nid(p7->type); | |
197 | switch (i) { | |
198 | case NID_pkcs7_signed: | |
199 | signer_sk = p7->d.sign->signer_info; | |
200 | md_sk = p7->d.sign->md_algs; | |
201 | break; | |
202 | case NID_pkcs7_signedAndEnveloped: | |
203 | signer_sk = p7->d.signed_and_enveloped->signer_info; | |
204 | md_sk = p7->d.signed_and_enveloped->md_algs; | |
205 | break; | |
206 | default: | |
9311d0c4 | 207 | ERR_raise(ERR_LIB_PKCS7, PKCS7_R_WRONG_CONTENT_TYPE); |
26a7d938 | 208 | return 0; |
0f113f3e MC |
209 | } |
210 | ||
ad57a13b | 211 | obj = psi->digest_alg->algorithm; |
0f113f3e MC |
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); | |
ad57a13b | 216 | if (OBJ_cmp(obj, alg->algorithm) == 0) { |
0f113f3e MC |
217 | j = 1; |
218 | break; | |
219 | } | |
220 | } | |
221 | if (!j) { /* we need to add another algorithm */ | |
ad57a13b RL |
222 | int nid; |
223 | ||
75ebbd9a RS |
224 | if ((alg = X509_ALGOR_new()) == NULL |
225 | || (alg->parameter = ASN1_TYPE_new()) == NULL) { | |
0f113f3e | 226 | X509_ALGOR_free(alg); |
e077455e | 227 | ERR_raise(ERR_LIB_PKCS7, ERR_R_ASN1_LIB); |
26a7d938 | 228 | return 0; |
0f113f3e | 229 | } |
ad57a13b RL |
230 | /* |
231 | * If there is a constant copy of the ASN1 OBJECT in libcrypto, then | |
232 | * use that. Otherwise, use a dynamically duplicated copy | |
233 | */ | |
234 | if ((nid = OBJ_obj2nid(obj)) != NID_undef) | |
235 | alg->algorithm = OBJ_nid2obj(nid); | |
236 | else | |
237 | alg->algorithm = OBJ_dup(obj); | |
0f113f3e | 238 | alg->parameter->type = V_ASN1_NULL; |
ad57a13b | 239 | if (alg->algorithm == NULL || !sk_X509_ALGOR_push(md_sk, alg)) { |
0f113f3e MC |
240 | X509_ALGOR_free(alg); |
241 | return 0; | |
242 | } | |
243 | } | |
244 | ||
681618cf | 245 | psi->ctx = ossl_pkcs7_get0_ctx(p7); |
0f113f3e MC |
246 | if (!sk_PKCS7_SIGNER_INFO_push(signer_sk, psi)) |
247 | return 0; | |
208fb891 | 248 | return 1; |
0f113f3e | 249 | } |
d02b48c6 | 250 | |
6b691a5c | 251 | int PKCS7_add_certificate(PKCS7 *p7, X509 *x509) |
0f113f3e MC |
252 | { |
253 | int i; | |
254 | STACK_OF(X509) **sk; | |
255 | ||
256 | i = OBJ_obj2nid(p7->type); | |
257 | switch (i) { | |
258 | case NID_pkcs7_signed: | |
259 | sk = &(p7->d.sign->cert); | |
260 | break; | |
261 | case NID_pkcs7_signedAndEnveloped: | |
262 | sk = &(p7->d.signed_and_enveloped->cert); | |
263 | break; | |
264 | default: | |
9311d0c4 | 265 | ERR_raise(ERR_LIB_PKCS7, PKCS7_R_WRONG_CONTENT_TYPE); |
26a7d938 | 266 | return 0; |
0f113f3e MC |
267 | } |
268 | ||
c1be4d61 | 269 | return ossl_x509_add_cert_new(sk, x509, X509_ADD_FLAG_UP_REF); |
0f113f3e | 270 | } |
d02b48c6 | 271 | |
6b691a5c | 272 | int PKCS7_add_crl(PKCS7 *p7, X509_CRL *crl) |
0f113f3e MC |
273 | { |
274 | int i; | |
275 | STACK_OF(X509_CRL) **sk; | |
276 | ||
277 | i = OBJ_obj2nid(p7->type); | |
278 | switch (i) { | |
279 | case NID_pkcs7_signed: | |
280 | sk = &(p7->d.sign->crl); | |
281 | break; | |
282 | case NID_pkcs7_signedAndEnveloped: | |
283 | sk = &(p7->d.signed_and_enveloped->crl); | |
284 | break; | |
285 | default: | |
9311d0c4 | 286 | ERR_raise(ERR_LIB_PKCS7, PKCS7_R_WRONG_CONTENT_TYPE); |
26a7d938 | 287 | return 0; |
0f113f3e MC |
288 | } |
289 | ||
290 | if (*sk == NULL) | |
291 | *sk = sk_X509_CRL_new_null(); | |
292 | if (*sk == NULL) { | |
e077455e | 293 | ERR_raise(ERR_LIB_PKCS7, ERR_R_CRYPTO_LIB); |
0f113f3e MC |
294 | return 0; |
295 | } | |
296 | ||
65cbf983 | 297 | X509_CRL_up_ref(crl); |
0f113f3e MC |
298 | if (!sk_X509_CRL_push(*sk, crl)) { |
299 | X509_CRL_free(crl); | |
300 | return 0; | |
301 | } | |
208fb891 | 302 | return 1; |
0f113f3e | 303 | } |
d02b48c6 | 304 | |
3e878d92 SL |
305 | static int pkcs7_ecdsa_or_dsa_sign_verify_setup(PKCS7_SIGNER_INFO *si, |
306 | int verify) | |
307 | { | |
04bc3c12 | 308 | if (!verify) { |
3e878d92 SL |
309 | int snid, hnid; |
310 | X509_ALGOR *alg1, *alg2; | |
311 | EVP_PKEY *pkey = si->pkey; | |
312 | ||
313 | PKCS7_SIGNER_INFO_get0_algs(si, NULL, &alg1, &alg2); | |
314 | if (alg1 == NULL || alg1->algorithm == NULL) | |
315 | return -1; | |
316 | hnid = OBJ_obj2nid(alg1->algorithm); | |
317 | if (hnid == NID_undef) | |
318 | return -1; | |
ed576acd | 319 | if (!OBJ_find_sigid_by_algs(&snid, hnid, EVP_PKEY_get_id(pkey))) |
3e878d92 | 320 | return -1; |
04bc3c12 | 321 | return X509_ALGOR_set0(alg2, OBJ_nid2obj(snid), V_ASN1_UNDEF, NULL); |
3e878d92 SL |
322 | } |
323 | return 1; | |
324 | } | |
325 | ||
326 | static int pkcs7_rsa_sign_verify_setup(PKCS7_SIGNER_INFO *si, int verify) | |
327 | { | |
04bc3c12 | 328 | if (!verify) { |
3e878d92 SL |
329 | X509_ALGOR *alg = NULL; |
330 | ||
331 | PKCS7_SIGNER_INFO_get0_algs(si, NULL, NULL, &alg); | |
332 | if (alg != NULL) | |
04bc3c12 DDO |
333 | return X509_ALGOR_set0(alg, OBJ_nid2obj(NID_rsaEncryption), |
334 | V_ASN1_NULL, NULL); | |
3e878d92 SL |
335 | } |
336 | return 1; | |
337 | } | |
338 | ||
6b691a5c | 339 | int PKCS7_SIGNER_INFO_set(PKCS7_SIGNER_INFO *p7i, X509 *x509, EVP_PKEY *pkey, |
0f113f3e MC |
340 | const EVP_MD *dgst) |
341 | { | |
342 | int ret; | |
343 | ||
344 | /* We now need to add another PKCS7_SIGNER_INFO entry */ | |
345 | if (!ASN1_INTEGER_set(p7i->version, 1)) | |
04bc3c12 | 346 | return 0; |
0f113f3e MC |
347 | if (!X509_NAME_set(&p7i->issuer_and_serial->issuer, |
348 | X509_get_issuer_name(x509))) | |
04bc3c12 | 349 | return 0; |
0f113f3e MC |
350 | |
351 | /* | |
352 | * because ASN1_INTEGER_set is used to set a 'long' we will do things the | |
353 | * ugly way. | |
354 | */ | |
f422a514 | 355 | ASN1_INTEGER_free(p7i->issuer_and_serial->serial); |
0f113f3e | 356 | if (!(p7i->issuer_and_serial->serial = |
1337a3a9 | 357 | ASN1_INTEGER_dup(X509_get0_serialNumber(x509)))) |
04bc3c12 | 358 | return 0; |
0f113f3e MC |
359 | |
360 | /* lets keep the pkey around for a while */ | |
3aeb9348 | 361 | EVP_PKEY_up_ref(pkey); |
0f113f3e MC |
362 | p7i->pkey = pkey; |
363 | ||
364 | /* Set the algorithms */ | |
365 | ||
04bc3c12 DDO |
366 | if (!X509_ALGOR_set0(p7i->digest_alg, OBJ_nid2obj(EVP_MD_get_type(dgst)), |
367 | V_ASN1_NULL, NULL)) | |
368 | return 0; | |
0f113f3e | 369 | |
3e878d92 SL |
370 | if (EVP_PKEY_is_a(pkey, "EC") || EVP_PKEY_is_a(pkey, "DSA")) |
371 | return pkcs7_ecdsa_or_dsa_sign_verify_setup(p7i, 0); | |
372 | if (EVP_PKEY_is_a(pkey, "RSA")) | |
373 | return pkcs7_rsa_sign_verify_setup(p7i, 0); | |
374 | ||
375 | if (pkey->ameth != NULL && pkey->ameth->pkey_ctrl != NULL) { | |
0f113f3e MC |
376 | ret = pkey->ameth->pkey_ctrl(pkey, ASN1_PKEY_CTRL_PKCS7_SIGN, 0, p7i); |
377 | if (ret > 0) | |
378 | return 1; | |
379 | if (ret != -2) { | |
9311d0c4 | 380 | ERR_raise(ERR_LIB_PKCS7, PKCS7_R_SIGNING_CTRL_FAILURE); |
0f113f3e MC |
381 | return 0; |
382 | } | |
383 | } | |
9311d0c4 | 384 | ERR_raise(ERR_LIB_PKCS7, PKCS7_R_SIGNING_NOT_SUPPORTED_FOR_THIS_KEY_TYPE); |
0f113f3e MC |
385 | return 0; |
386 | } | |
d02b48c6 | 387 | |
6b691a5c | 388 | PKCS7_SIGNER_INFO *PKCS7_add_signature(PKCS7 *p7, X509 *x509, EVP_PKEY *pkey, |
0f113f3e MC |
389 | const EVP_MD *dgst) |
390 | { | |
391 | PKCS7_SIGNER_INFO *si = NULL; | |
392 | ||
393 | if (dgst == NULL) { | |
394 | int def_nid; | |
395 | if (EVP_PKEY_get_default_digest_nid(pkey, &def_nid) <= 0) | |
396 | goto err; | |
397 | dgst = EVP_get_digestbynid(def_nid); | |
398 | if (dgst == NULL) { | |
9311d0c4 | 399 | ERR_raise(ERR_LIB_PKCS7, PKCS7_R_NO_DEFAULT_DIGEST); |
0f113f3e MC |
400 | goto err; |
401 | } | |
402 | } | |
403 | ||
404 | if ((si = PKCS7_SIGNER_INFO_new()) == NULL) | |
405 | goto err; | |
639e5760 | 406 | if (PKCS7_SIGNER_INFO_set(si, x509, pkey, dgst) <= 0) |
0f113f3e MC |
407 | goto err; |
408 | if (!PKCS7_add_signer(p7, si)) | |
409 | goto err; | |
26a7d938 | 410 | return si; |
0f113f3e | 411 | err: |
e0e920b1 | 412 | PKCS7_SIGNER_INFO_free(si); |
26a7d938 | 413 | return NULL; |
0f113f3e | 414 | } |
d02b48c6 | 415 | |
90a1f2d7 SL |
416 | static STACK_OF(X509) *pkcs7_get_signer_certs(const PKCS7 *p7) |
417 | { | |
80253dbd TM |
418 | if (p7->d.ptr == NULL) |
419 | return NULL; | |
90a1f2d7 SL |
420 | if (PKCS7_type_is_signed(p7)) |
421 | return p7->d.sign->cert; | |
422 | if (PKCS7_type_is_signedAndEnveloped(p7)) | |
423 | return p7->d.signed_and_enveloped->cert; | |
424 | return NULL; | |
425 | } | |
426 | ||
427 | static STACK_OF(PKCS7_RECIP_INFO) *pkcs7_get_recipient_info(const PKCS7 *p7) | |
428 | { | |
80253dbd TM |
429 | if (p7->d.ptr == NULL) |
430 | return NULL; | |
90a1f2d7 SL |
431 | if (PKCS7_type_is_signedAndEnveloped(p7)) |
432 | return p7->d.signed_and_enveloped->recipientinfo; | |
433 | if (PKCS7_type_is_enveloped(p7)) | |
434 | return p7->d.enveloped->recipientinfo; | |
435 | return NULL; | |
436 | } | |
437 | ||
438 | /* | |
439 | * Set up the library context into any loaded structure that needs it. | |
440 | * i.e loaded X509 objects. | |
441 | */ | |
681618cf | 442 | void ossl_pkcs7_resolve_libctx(PKCS7 *p7) |
90a1f2d7 SL |
443 | { |
444 | int i; | |
681618cf SL |
445 | const PKCS7_CTX *ctx = ossl_pkcs7_get0_ctx(p7); |
446 | OSSL_LIB_CTX *libctx = ossl_pkcs7_ctx_get0_libctx(ctx); | |
447 | const char *propq = ossl_pkcs7_ctx_get0_propq(ctx); | |
80253dbd TM |
448 | STACK_OF(PKCS7_RECIP_INFO) *rinfos; |
449 | STACK_OF(PKCS7_SIGNER_INFO) *sinfos; | |
450 | STACK_OF(X509) *certs; | |
90a1f2d7 | 451 | |
80253dbd | 452 | if (ctx == NULL || p7->d.ptr == NULL) |
90a1f2d7 SL |
453 | return; |
454 | ||
80253dbd TM |
455 | rinfos = pkcs7_get_recipient_info(p7); |
456 | sinfos = PKCS7_get_signer_info(p7); | |
457 | certs = pkcs7_get_signer_certs(p7); | |
458 | ||
90a1f2d7 | 459 | for (i = 0; i < sk_X509_num(certs); i++) |
4669015d | 460 | ossl_x509_set0_libctx(sk_X509_value(certs, i), libctx, propq); |
90a1f2d7 SL |
461 | |
462 | for (i = 0; i < sk_PKCS7_RECIP_INFO_num(rinfos); i++) { | |
463 | PKCS7_RECIP_INFO *ri = sk_PKCS7_RECIP_INFO_value(rinfos, i); | |
464 | ||
4669015d | 465 | ossl_x509_set0_libctx(ri->cert, libctx, propq); |
90a1f2d7 SL |
466 | } |
467 | ||
468 | for (i = 0; i < sk_PKCS7_SIGNER_INFO_num(sinfos); i++) { | |
469 | PKCS7_SIGNER_INFO *si = sk_PKCS7_SIGNER_INFO_value(sinfos, i); | |
470 | ||
471 | if (si != NULL) | |
472 | si->ctx = ctx; | |
473 | } | |
474 | } | |
475 | ||
681618cf | 476 | const PKCS7_CTX *ossl_pkcs7_get0_ctx(const PKCS7 *p7) |
90a1f2d7 SL |
477 | { |
478 | return p7 != NULL ? &p7->ctx : NULL; | |
479 | } | |
480 | ||
b536880c JS |
481 | void ossl_pkcs7_set0_libctx(PKCS7 *p7, OSSL_LIB_CTX *ctx) |
482 | { | |
483 | p7->ctx.libctx = ctx; | |
484 | } | |
485 | ||
486 | int ossl_pkcs7_set1_propq(PKCS7 *p7, const char *propq) | |
487 | { | |
488 | if (p7->ctx.propq != NULL) { | |
489 | OPENSSL_free(p7->ctx.propq); | |
490 | p7->ctx.propq = NULL; | |
491 | } | |
492 | if (propq != NULL) { | |
493 | p7->ctx.propq = OPENSSL_strdup(propq); | |
e077455e | 494 | if (p7->ctx.propq == NULL) |
b536880c | 495 | return 0; |
b536880c JS |
496 | } |
497 | return 1; | |
498 | } | |
499 | ||
500 | int ossl_pkcs7_ctx_propagate(const PKCS7 *from, PKCS7 *to) | |
501 | { | |
502 | ossl_pkcs7_set0_libctx(to, from->ctx.libctx); | |
503 | if (!ossl_pkcs7_set1_propq(to, from->ctx.propq)) | |
504 | return 0; | |
505 | ||
506 | ossl_pkcs7_resolve_libctx(to); | |
507 | return 1; | |
508 | } | |
509 | ||
681618cf | 510 | OSSL_LIB_CTX *ossl_pkcs7_ctx_get0_libctx(const PKCS7_CTX *ctx) |
90a1f2d7 SL |
511 | { |
512 | return ctx != NULL ? ctx->libctx : NULL; | |
513 | } | |
681618cf | 514 | const char *ossl_pkcs7_ctx_get0_propq(const PKCS7_CTX *ctx) |
90a1f2d7 SL |
515 | { |
516 | return ctx != NULL ? ctx->propq : NULL; | |
517 | } | |
518 | ||
c5a55463 | 519 | int PKCS7_set_digest(PKCS7 *p7, const EVP_MD *md) |
0f113f3e MC |
520 | { |
521 | if (PKCS7_type_is_digest(p7)) { | |
75ebbd9a | 522 | if ((p7->d.digest->md->parameter = ASN1_TYPE_new()) == NULL) { |
e077455e | 523 | ERR_raise(ERR_LIB_PKCS7, ERR_R_ASN1_LIB); |
0f113f3e MC |
524 | return 0; |
525 | } | |
526 | p7->d.digest->md->parameter->type = V_ASN1_NULL; | |
527 | p7->d.digest->md->algorithm = OBJ_nid2obj(EVP_MD_nid(md)); | |
528 | return 1; | |
529 | } | |
530 | ||
9311d0c4 | 531 | ERR_raise(ERR_LIB_PKCS7, PKCS7_R_WRONG_CONTENT_TYPE); |
0f113f3e MC |
532 | return 1; |
533 | } | |
c5a55463 | 534 | |
b05b50e6 | 535 | STACK_OF(PKCS7_SIGNER_INFO) *PKCS7_get_signer_info(PKCS7 *p7) |
0f113f3e | 536 | { |
c225c3cf EK |
537 | if (p7 == NULL || p7->d.ptr == NULL) |
538 | return NULL; | |
0f113f3e | 539 | if (PKCS7_type_is_signed(p7)) { |
26a7d938 | 540 | return p7->d.sign->signer_info; |
0f113f3e | 541 | } else if (PKCS7_type_is_signedAndEnveloped(p7)) { |
26a7d938 | 542 | return p7->d.signed_and_enveloped->signer_info; |
0f113f3e | 543 | } else |
26a7d938 | 544 | return NULL; |
0f113f3e | 545 | } |
d02b48c6 | 546 | |
492a9e24 | 547 | void PKCS7_SIGNER_INFO_get0_algs(PKCS7_SIGNER_INFO *si, EVP_PKEY **pk, |
0f113f3e MC |
548 | X509_ALGOR **pdig, X509_ALGOR **psig) |
549 | { | |
550 | if (pk) | |
551 | *pk = si->pkey; | |
552 | if (pdig) | |
553 | *pdig = si->digest_alg; | |
554 | if (psig) | |
555 | *psig = si->digest_enc_alg; | |
556 | } | |
492a9e24 | 557 | |
e4b21c74 | 558 | void PKCS7_RECIP_INFO_get0_alg(PKCS7_RECIP_INFO *ri, X509_ALGOR **penc) |
0f113f3e MC |
559 | { |
560 | if (penc) | |
561 | *penc = ri->key_enc_algor; | |
562 | } | |
e4b21c74 | 563 | |
6b691a5c | 564 | PKCS7_RECIP_INFO *PKCS7_add_recipient(PKCS7 *p7, X509 *x509) |
0f113f3e MC |
565 | { |
566 | PKCS7_RECIP_INFO *ri; | |
567 | ||
568 | if ((ri = PKCS7_RECIP_INFO_new()) == NULL) | |
569 | goto err; | |
639e5760 | 570 | if (PKCS7_RECIP_INFO_set(ri, x509) <= 0) |
0f113f3e MC |
571 | goto err; |
572 | if (!PKCS7_add_recipient_info(p7, ri)) | |
573 | goto err; | |
681618cf | 574 | ri->ctx = ossl_pkcs7_get0_ctx(p7); |
0f113f3e MC |
575 | return ri; |
576 | err: | |
e0e920b1 | 577 | PKCS7_RECIP_INFO_free(ri); |
0f113f3e MC |
578 | return NULL; |
579 | } | |
58964a49 | 580 | |
6b691a5c | 581 | int PKCS7_add_recipient_info(PKCS7 *p7, PKCS7_RECIP_INFO *ri) |
0f113f3e MC |
582 | { |
583 | int i; | |
584 | STACK_OF(PKCS7_RECIP_INFO) *sk; | |
585 | ||
586 | i = OBJ_obj2nid(p7->type); | |
587 | switch (i) { | |
588 | case NID_pkcs7_signedAndEnveloped: | |
589 | sk = p7->d.signed_and_enveloped->recipientinfo; | |
590 | break; | |
591 | case NID_pkcs7_enveloped: | |
592 | sk = p7->d.enveloped->recipientinfo; | |
593 | break; | |
594 | default: | |
9311d0c4 | 595 | ERR_raise(ERR_LIB_PKCS7, PKCS7_R_WRONG_CONTENT_TYPE); |
26a7d938 | 596 | return 0; |
0f113f3e MC |
597 | } |
598 | ||
599 | if (!sk_PKCS7_RECIP_INFO_push(sk, ri)) | |
600 | return 0; | |
208fb891 | 601 | return 1; |
0f113f3e | 602 | } |
58964a49 | 603 | |
3e878d92 SL |
604 | static int pkcs7_rsa_encrypt_decrypt_setup(PKCS7_RECIP_INFO *ri, int decrypt) |
605 | { | |
606 | X509_ALGOR *alg = NULL; | |
607 | ||
04bc3c12 | 608 | if (!decrypt) { |
3e878d92 SL |
609 | PKCS7_RECIP_INFO_get0_alg(ri, &alg); |
610 | if (alg != NULL) | |
04bc3c12 DDO |
611 | return X509_ALGOR_set0(alg, OBJ_nid2obj(NID_rsaEncryption), |
612 | V_ASN1_NULL, NULL); | |
3e878d92 SL |
613 | } |
614 | return 1; | |
615 | } | |
616 | ||
6b691a5c | 617 | int PKCS7_RECIP_INFO_set(PKCS7_RECIP_INFO *p7i, X509 *x509) |
0f113f3e MC |
618 | { |
619 | int ret; | |
620 | EVP_PKEY *pkey = NULL; | |
621 | if (!ASN1_INTEGER_set(p7i->version, 0)) | |
622 | return 0; | |
623 | if (!X509_NAME_set(&p7i->issuer_and_serial->issuer, | |
624 | X509_get_issuer_name(x509))) | |
625 | return 0; | |
626 | ||
f422a514 | 627 | ASN1_INTEGER_free(p7i->issuer_and_serial->serial); |
0f113f3e | 628 | if (!(p7i->issuer_and_serial->serial = |
1337a3a9 | 629 | ASN1_INTEGER_dup(X509_get0_serialNumber(x509)))) |
0f113f3e MC |
630 | return 0; |
631 | ||
8382fd3a | 632 | pkey = X509_get0_pubkey(x509); |
3e878d92 SL |
633 | if (pkey == NULL) |
634 | return 0; | |
0f113f3e | 635 | |
3e878d92 SL |
636 | if (EVP_PKEY_is_a(pkey, "RSA-PSS")) |
637 | return -2; | |
638 | if (EVP_PKEY_is_a(pkey, "RSA")) { | |
639 | if (pkcs7_rsa_encrypt_decrypt_setup(p7i, 0) <= 0) | |
640 | goto err; | |
641 | goto finished; | |
642 | } | |
643 | ||
644 | if (pkey->ameth == NULL || pkey->ameth->pkey_ctrl == NULL) { | |
9311d0c4 RL |
645 | ERR_raise(ERR_LIB_PKCS7, |
646 | PKCS7_R_ENCRYPTION_NOT_SUPPORTED_FOR_THIS_KEY_TYPE); | |
0f113f3e MC |
647 | goto err; |
648 | } | |
649 | ||
650 | ret = pkey->ameth->pkey_ctrl(pkey, ASN1_PKEY_CTRL_PKCS7_ENCRYPT, 0, p7i); | |
651 | if (ret == -2) { | |
9311d0c4 RL |
652 | ERR_raise(ERR_LIB_PKCS7, |
653 | PKCS7_R_ENCRYPTION_NOT_SUPPORTED_FOR_THIS_KEY_TYPE); | |
0f113f3e MC |
654 | goto err; |
655 | } | |
656 | if (ret <= 0) { | |
9311d0c4 | 657 | ERR_raise(ERR_LIB_PKCS7, PKCS7_R_ENCRYPTION_CTRL_FAILURE); |
0f113f3e MC |
658 | goto err; |
659 | } | |
3e878d92 | 660 | finished: |
05f0fb9f | 661 | X509_up_ref(x509); |
0f113f3e MC |
662 | p7i->cert = x509; |
663 | ||
664 | return 1; | |
665 | ||
666 | err: | |
0f113f3e MC |
667 | return 0; |
668 | } | |
58964a49 | 669 | |
6b691a5c | 670 | X509 *PKCS7_cert_from_signer_info(PKCS7 *p7, PKCS7_SIGNER_INFO *si) |
0f113f3e MC |
671 | { |
672 | if (PKCS7_type_is_signed(p7)) | |
673 | return (X509_find_by_issuer_and_serial(p7->d.sign->cert, | |
674 | si->issuer_and_serial->issuer, | |
675 | si-> | |
676 | issuer_and_serial->serial)); | |
677 | else | |
26a7d938 | 678 | return NULL; |
0f113f3e | 679 | } |
d02b48c6 | 680 | |
84fa704c | 681 | int PKCS7_set_cipher(PKCS7 *p7, const EVP_CIPHER *cipher) |
0f113f3e MC |
682 | { |
683 | int i; | |
684 | PKCS7_ENC_CONTENT *ec; | |
685 | ||
686 | i = OBJ_obj2nid(p7->type); | |
687 | switch (i) { | |
688 | case NID_pkcs7_signedAndEnveloped: | |
689 | ec = p7->d.signed_and_enveloped->enc_data; | |
690 | break; | |
691 | case NID_pkcs7_enveloped: | |
692 | ec = p7->d.enveloped->enc_data; | |
693 | break; | |
694 | default: | |
9311d0c4 | 695 | ERR_raise(ERR_LIB_PKCS7, PKCS7_R_WRONG_CONTENT_TYPE); |
26a7d938 | 696 | return 0; |
0f113f3e MC |
697 | } |
698 | ||
699 | /* Check cipher OID exists and has data in it */ | |
ed576acd | 700 | i = EVP_CIPHER_get_type(cipher); |
0f113f3e | 701 | if (i == NID_undef) { |
9311d0c4 | 702 | ERR_raise(ERR_LIB_PKCS7, PKCS7_R_CIPHER_HAS_NO_OBJECT_IDENTIFIER); |
26a7d938 | 703 | return 0; |
0f113f3e MC |
704 | } |
705 | ||
706 | ec->cipher = cipher; | |
681618cf | 707 | ec->ctx = ossl_pkcs7_get0_ctx(p7); |
0f113f3e MC |
708 | return 1; |
709 | } | |
58964a49 | 710 | |
9fdcc21f | 711 | /* unfortunately cannot constify BIO_new_NDEF() due to this and CMS_stream() */ |
11d8cdc6 | 712 | int PKCS7_stream(unsigned char ***boundary, PKCS7 *p7) |
0f113f3e MC |
713 | { |
714 | ASN1_OCTET_STRING *os = NULL; | |
715 | ||
716 | switch (OBJ_obj2nid(p7->type)) { | |
717 | case NID_pkcs7_data: | |
718 | os = p7->d.data; | |
719 | break; | |
720 | ||
721 | case NID_pkcs7_signedAndEnveloped: | |
722 | os = p7->d.signed_and_enveloped->enc_data->enc_data; | |
723 | if (os == NULL) { | |
f422a514 | 724 | os = ASN1_OCTET_STRING_new(); |
0f113f3e MC |
725 | p7->d.signed_and_enveloped->enc_data->enc_data = os; |
726 | } | |
727 | break; | |
728 | ||
729 | case NID_pkcs7_enveloped: | |
730 | os = p7->d.enveloped->enc_data->enc_data; | |
731 | if (os == NULL) { | |
f422a514 | 732 | os = ASN1_OCTET_STRING_new(); |
0f113f3e MC |
733 | p7->d.enveloped->enc_data->enc_data = os; |
734 | } | |
735 | break; | |
736 | ||
737 | case NID_pkcs7_signed: | |
738 | os = p7->d.sign->contents->d.data; | |
739 | break; | |
740 | ||
741 | default: | |
742 | os = NULL; | |
743 | break; | |
744 | } | |
745 | ||
746 | if (os == NULL) | |
747 | return 0; | |
748 | ||
749 | os->flags |= ASN1_STRING_FLAG_NDEF; | |
750 | *boundary = &os->data; | |
751 | ||
752 | return 1; | |
753 | } |