]>
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> | |
ec577822 BM |
11 | #include <openssl/rand.h> |
12 | #include <openssl/objects.h> | |
13 | #include <openssl/x509.h> | |
5a9a4b29 | 14 | #include <openssl/x509v3.h> |
8f2e4fdf | 15 | #include <openssl/err.h> |
ad57a13b RL |
16 | #include "internal/cryptlib.h" |
17 | #include "internal/sizes.h" | |
36b91a19 | 18 | #include "crypto/evp.h" |
90a1f2d7 | 19 | #include "pk7_local.h" |
d02b48c6 | 20 | |
b6436ff2 | 21 | static int add_attribute(STACK_OF(X509_ATTRIBUTE) **sk, int nid, int atrtype, |
0f113f3e | 22 | void *value); |
63b64f19 | 23 | static ASN1_TYPE *get_attribute(const STACK_OF(X509_ATTRIBUTE) *sk, int nid); |
dfeab068 | 24 | |
db554ae1 | 25 | int PKCS7_type_is_other(PKCS7 *p7) |
0f113f3e MC |
26 | { |
27 | int isOther = 1; | |
28 | ||
29 | int nid = OBJ_obj2nid(p7->type); | |
30 | ||
31 | switch (nid) { | |
32 | case NID_pkcs7_data: | |
33 | case NID_pkcs7_signed: | |
34 | case NID_pkcs7_enveloped: | |
35 | case NID_pkcs7_signedAndEnveloped: | |
36 | case NID_pkcs7_digest: | |
37 | case NID_pkcs7_encrypted: | |
38 | isOther = 0; | |
39 | break; | |
40 | default: | |
41 | isOther = 1; | |
42 | } | |
43 | ||
44 | return isOther; | |
45 | ||
46 | } | |
67fec850 | 47 | |
db554ae1 | 48 | ASN1_OCTET_STRING *PKCS7_get_octet_string(PKCS7 *p7) |
0f113f3e MC |
49 | { |
50 | if (PKCS7_type_is_data(p7)) | |
51 | return p7->d.data; | |
52 | if (PKCS7_type_is_other(p7) && p7->d.other | |
53 | && (p7->d.other->type == V_ASN1_OCTET_STRING)) | |
54 | return p7->d.other->value.octet_string; | |
55 | return NULL; | |
56 | } | |
67fec850 | 57 | |
90a1f2d7 SL |
58 | static int pkcs7_bio_add_digest(BIO **pbio, X509_ALGOR *alg, |
59 | const PKCS7_CTX *ctx) | |
0f113f3e MC |
60 | { |
61 | BIO *btmp; | |
ad57a13b | 62 | char name[OSSL_MAX_NAME_SIZE]; |
90a1f2d7 | 63 | EVP_MD *fetched = NULL; |
bd1bbbfe | 64 | const EVP_MD *md; |
90a1f2d7 | 65 | |
0f113f3e | 66 | if ((btmp = BIO_new(BIO_f_md())) == NULL) { |
9311d0c4 | 67 | ERR_raise(ERR_LIB_PKCS7, ERR_R_BIO_LIB); |
0f113f3e MC |
68 | goto err; |
69 | } | |
70 | ||
ad57a13b | 71 | OBJ_obj2txt(name, sizeof(name), alg->algorithm, 0); |
bd1bbbfe DB |
72 | |
73 | (void)ERR_set_mark(); | |
681618cf SL |
74 | fetched = EVP_MD_fetch(ossl_pkcs7_ctx_get0_libctx(ctx), name, |
75 | ossl_pkcs7_ctx_get0_propq(ctx)); | |
bd1bbbfe DB |
76 | if (fetched != NULL) |
77 | md = fetched; | |
78 | else | |
79 | md = EVP_get_digestbyname(name); | |
80 | ||
81 | if (md == NULL) { | |
82 | (void)ERR_clear_last_mark(); | |
9311d0c4 | 83 | ERR_raise(ERR_LIB_PKCS7, PKCS7_R_UNKNOWN_DIGEST_TYPE); |
0f113f3e MC |
84 | goto err; |
85 | } | |
bd1bbbfe | 86 | (void)ERR_pop_to_mark(); |
0f113f3e | 87 | |
6eebe6c0 TM |
88 | if (BIO_set_md(btmp, md) <= 0) { |
89 | ERR_raise(ERR_LIB_PKCS7, ERR_R_BIO_LIB); | |
90 | EVP_MD_free(fetched); | |
91 | goto err; | |
92 | } | |
90a1f2d7 | 93 | EVP_MD_free(fetched); |
0f113f3e MC |
94 | if (*pbio == NULL) |
95 | *pbio = btmp; | |
96 | else if (!BIO_push(*pbio, btmp)) { | |
9311d0c4 | 97 | ERR_raise(ERR_LIB_PKCS7, ERR_R_BIO_LIB); |
0f113f3e MC |
98 | goto err; |
99 | } | |
100 | btmp = NULL; | |
101 | ||
102 | return 1; | |
103 | ||
104 | err: | |
ca3a82c3 | 105 | BIO_free(btmp); |
0f113f3e | 106 | return 0; |
0f113f3e | 107 | } |
399a6f0b | 108 | |
0f113f3e MC |
109 | static int pkcs7_encode_rinfo(PKCS7_RECIP_INFO *ri, |
110 | unsigned char *key, int keylen) | |
111 | { | |
112 | EVP_PKEY_CTX *pctx = NULL; | |
113 | EVP_PKEY *pkey = NULL; | |
114 | unsigned char *ek = NULL; | |
115 | int ret = 0; | |
116 | size_t eklen; | |
90a1f2d7 | 117 | const PKCS7_CTX *ctx = ri->ctx; |
399a6f0b | 118 | |
8382fd3a | 119 | pkey = X509_get0_pubkey(ri->cert); |
12a765a5 | 120 | if (pkey == NULL) |
0f113f3e | 121 | return 0; |
399a6f0b | 122 | |
681618cf SL |
123 | pctx = EVP_PKEY_CTX_new_from_pkey(ossl_pkcs7_ctx_get0_libctx(ctx), pkey, |
124 | ossl_pkcs7_ctx_get0_propq(ctx)); | |
12a765a5 | 125 | if (pctx == NULL) |
0f113f3e | 126 | return 0; |
399a6f0b | 127 | |
0f113f3e MC |
128 | if (EVP_PKEY_encrypt_init(pctx) <= 0) |
129 | goto err; | |
399a6f0b | 130 | |
0f113f3e MC |
131 | if (EVP_PKEY_encrypt(pctx, NULL, &eklen, key, keylen) <= 0) |
132 | goto err; | |
399a6f0b | 133 | |
0f113f3e | 134 | ek = OPENSSL_malloc(eklen); |
e077455e | 135 | if (ek == NULL) |
0f113f3e | 136 | goto err; |
399a6f0b | 137 | |
0f113f3e MC |
138 | if (EVP_PKEY_encrypt(pctx, ek, &eklen, key, keylen) <= 0) |
139 | goto err; | |
399a6f0b | 140 | |
0f113f3e MC |
141 | ASN1_STRING_set0(ri->enc_key, ek, eklen); |
142 | ek = NULL; | |
399a6f0b | 143 | |
0f113f3e | 144 | ret = 1; |
399a6f0b | 145 | |
0f113f3e | 146 | err: |
c5ba2d99 | 147 | EVP_PKEY_CTX_free(pctx); |
b548a1f1 | 148 | OPENSSL_free(ek); |
0f113f3e | 149 | return ret; |
399a6f0b | 150 | |
0f113f3e | 151 | } |
399a6f0b | 152 | |
777c47ac | 153 | static int pkcs7_decrypt_rinfo(unsigned char **pek, int *peklen, |
5840ed0c BE |
154 | PKCS7_RECIP_INFO *ri, EVP_PKEY *pkey, |
155 | size_t fixlen) | |
0f113f3e MC |
156 | { |
157 | EVP_PKEY_CTX *pctx = NULL; | |
158 | unsigned char *ek = NULL; | |
159 | size_t eklen; | |
0f113f3e | 160 | int ret = -1; |
90a1f2d7 | 161 | const PKCS7_CTX *ctx = ri->ctx; |
0f113f3e | 162 | |
681618cf SL |
163 | pctx = EVP_PKEY_CTX_new_from_pkey(ossl_pkcs7_ctx_get0_libctx(ctx), pkey, |
164 | ossl_pkcs7_ctx_get0_propq(ctx)); | |
12a765a5 | 165 | if (pctx == NULL) |
0f113f3e MC |
166 | return -1; |
167 | ||
168 | if (EVP_PKEY_decrypt_init(pctx) <= 0) | |
169 | goto err; | |
170 | ||
056dade3 HK |
171 | if (EVP_PKEY_is_a(pkey, "RSA")) |
172 | /* upper layer pkcs7 code incorrectly assumes that a successful RSA | |
173 | * decryption means that the key matches ciphertext (which never | |
174 | * was the case, implicit rejection or not), so to make it work | |
175 | * disable implicit rejection for RSA keys */ | |
176 | EVP_PKEY_CTX_ctrl_str(pctx, "rsa_pkcs1_implicit_rejection", "0"); | |
177 | ||
36b91a19 DDO |
178 | ret = evp_pkey_decrypt_alloc(pctx, &ek, &eklen, fixlen, |
179 | ri->enc_key->data, ri->enc_key->length); | |
180 | if (ret <= 0) | |
0f113f3e | 181 | goto err; |
0f113f3e MC |
182 | |
183 | ret = 1; | |
184 | ||
4b45c6e5 | 185 | OPENSSL_clear_free(*pek, *peklen); |
0f113f3e MC |
186 | *pek = ek; |
187 | *peklen = eklen; | |
188 | ||
189 | err: | |
c5ba2d99 | 190 | EVP_PKEY_CTX_free(pctx); |
b548a1f1 | 191 | if (!ret) |
0f113f3e MC |
192 | OPENSSL_free(ek); |
193 | ||
194 | return ret; | |
195 | } | |
399a6f0b | 196 | |
6b691a5c | 197 | BIO *PKCS7_dataInit(PKCS7 *p7, BIO *bio) |
0f113f3e MC |
198 | { |
199 | int i; | |
200 | BIO *out = NULL, *btmp = NULL; | |
201 | X509_ALGOR *xa = NULL; | |
90a1f2d7 | 202 | EVP_CIPHER *fetched_cipher = NULL; |
835b2900 | 203 | const EVP_CIPHER *cipher; |
0f113f3e MC |
204 | const EVP_CIPHER *evp_cipher = NULL; |
205 | STACK_OF(X509_ALGOR) *md_sk = NULL; | |
206 | STACK_OF(PKCS7_RECIP_INFO) *rsk = NULL; | |
207 | X509_ALGOR *xalg = NULL; | |
208 | PKCS7_RECIP_INFO *ri = NULL; | |
209 | ASN1_OCTET_STRING *os = NULL; | |
90a1f2d7 | 210 | const PKCS7_CTX *p7_ctx; |
038f4dc6 SL |
211 | OSSL_LIB_CTX *libctx; |
212 | const char *propq; | |
0f113f3e | 213 | |
c225c3cf | 214 | if (p7 == NULL) { |
9311d0c4 | 215 | ERR_raise(ERR_LIB_PKCS7, PKCS7_R_INVALID_NULL_POINTER); |
c225c3cf EK |
216 | return NULL; |
217 | } | |
681618cf SL |
218 | p7_ctx = ossl_pkcs7_get0_ctx(p7); |
219 | libctx = ossl_pkcs7_ctx_get0_libctx(p7_ctx); | |
220 | propq = ossl_pkcs7_ctx_get0_propq(p7_ctx); | |
90a1f2d7 | 221 | |
c225c3cf EK |
222 | /* |
223 | * The content field in the PKCS7 ContentInfo is optional, but that really | |
224 | * only applies to inner content (precisely, detached signatures). | |
225 | * | |
226 | * When reading content, missing outer content is therefore treated as an | |
227 | * error. | |
228 | * | |
229 | * When creating content, PKCS7_content_new() must be called before | |
230 | * calling this method, so a NULL p7->d is always an error. | |
231 | */ | |
232 | if (p7->d.ptr == NULL) { | |
9311d0c4 | 233 | ERR_raise(ERR_LIB_PKCS7, PKCS7_R_NO_CONTENT); |
c225c3cf EK |
234 | return NULL; |
235 | } | |
236 | ||
0f113f3e MC |
237 | i = OBJ_obj2nid(p7->type); |
238 | p7->state = PKCS7_S_HEADER; | |
239 | ||
240 | switch (i) { | |
241 | case NID_pkcs7_signed: | |
242 | md_sk = p7->d.sign->md_algs; | |
243 | os = PKCS7_get_octet_string(p7->d.sign->contents); | |
244 | break; | |
245 | case NID_pkcs7_signedAndEnveloped: | |
246 | rsk = p7->d.signed_and_enveloped->recipientinfo; | |
247 | md_sk = p7->d.signed_and_enveloped->md_algs; | |
248 | xalg = p7->d.signed_and_enveloped->enc_data->algorithm; | |
249 | evp_cipher = p7->d.signed_and_enveloped->enc_data->cipher; | |
250 | if (evp_cipher == NULL) { | |
9311d0c4 | 251 | ERR_raise(ERR_LIB_PKCS7, PKCS7_R_CIPHER_NOT_INITIALIZED); |
0f113f3e MC |
252 | goto err; |
253 | } | |
254 | break; | |
255 | case NID_pkcs7_enveloped: | |
256 | rsk = p7->d.enveloped->recipientinfo; | |
257 | xalg = p7->d.enveloped->enc_data->algorithm; | |
258 | evp_cipher = p7->d.enveloped->enc_data->cipher; | |
259 | if (evp_cipher == NULL) { | |
9311d0c4 | 260 | ERR_raise(ERR_LIB_PKCS7, PKCS7_R_CIPHER_NOT_INITIALIZED); |
0f113f3e MC |
261 | goto err; |
262 | } | |
263 | break; | |
264 | case NID_pkcs7_digest: | |
265 | xa = p7->d.digest->md; | |
266 | os = PKCS7_get_octet_string(p7->d.digest->contents); | |
267 | break; | |
268 | case NID_pkcs7_data: | |
269 | break; | |
270 | default: | |
9311d0c4 | 271 | ERR_raise(ERR_LIB_PKCS7, PKCS7_R_UNSUPPORTED_CONTENT_TYPE); |
0f113f3e MC |
272 | goto err; |
273 | } | |
274 | ||
275 | for (i = 0; i < sk_X509_ALGOR_num(md_sk); i++) | |
90a1f2d7 | 276 | if (!pkcs7_bio_add_digest(&out, sk_X509_ALGOR_value(md_sk, i), p7_ctx)) |
0f113f3e MC |
277 | goto err; |
278 | ||
90a1f2d7 | 279 | if (xa && !pkcs7_bio_add_digest(&out, xa, p7_ctx)) |
0f113f3e MC |
280 | goto err; |
281 | ||
282 | if (evp_cipher != NULL) { | |
283 | unsigned char key[EVP_MAX_KEY_LENGTH]; | |
284 | unsigned char iv[EVP_MAX_IV_LENGTH]; | |
285 | int keylen, ivlen; | |
286 | EVP_CIPHER_CTX *ctx; | |
287 | ||
288 | if ((btmp = BIO_new(BIO_f_cipher())) == NULL) { | |
9311d0c4 | 289 | ERR_raise(ERR_LIB_PKCS7, ERR_R_BIO_LIB); |
0f113f3e MC |
290 | goto err; |
291 | } | |
292 | BIO_get_cipher_ctx(btmp, &ctx); | |
ed576acd TM |
293 | keylen = EVP_CIPHER_get_key_length(evp_cipher); |
294 | ivlen = EVP_CIPHER_get_iv_length(evp_cipher); | |
295 | xalg->algorithm = OBJ_nid2obj(EVP_CIPHER_get_type(evp_cipher)); | |
0f113f3e | 296 | if (ivlen > 0) |
5cbd2ea3 | 297 | if (RAND_bytes_ex(libctx, iv, ivlen, 0) <= 0) |
0f113f3e | 298 | goto err; |
90a1f2d7 | 299 | |
835b2900 | 300 | (void)ERR_set_mark(); |
038f4dc6 | 301 | fetched_cipher = EVP_CIPHER_fetch(libctx, |
ed576acd | 302 | EVP_CIPHER_get0_name(evp_cipher), |
038f4dc6 | 303 | propq); |
0f0b7dfb | 304 | (void)ERR_pop_to_mark(); |
835b2900 DB |
305 | if (fetched_cipher != NULL) |
306 | cipher = fetched_cipher; | |
307 | else | |
308 | cipher = evp_cipher; | |
309 | ||
835b2900 | 310 | if (EVP_CipherInit_ex(ctx, cipher, NULL, NULL, NULL, 1) <= 0) |
90a1f2d7 SL |
311 | goto err; |
312 | ||
313 | EVP_CIPHER_free(fetched_cipher); | |
314 | fetched_cipher = NULL; | |
315 | ||
0f113f3e MC |
316 | if (EVP_CIPHER_CTX_rand_key(ctx, key) <= 0) |
317 | goto err; | |
318 | if (EVP_CipherInit_ex(ctx, NULL, NULL, key, iv, 1) <= 0) | |
319 | goto err; | |
320 | ||
321 | if (ivlen > 0) { | |
322 | if (xalg->parameter == NULL) { | |
323 | xalg->parameter = ASN1_TYPE_new(); | |
324 | if (xalg->parameter == NULL) | |
325 | goto err; | |
326 | } | |
e3663717 | 327 | if (EVP_CIPHER_param_to_asn1(ctx, xalg->parameter) <= 0) |
0f113f3e MC |
328 | goto err; |
329 | } | |
330 | ||
331 | /* Lets do the pub key stuff :-) */ | |
332 | for (i = 0; i < sk_PKCS7_RECIP_INFO_num(rsk); i++) { | |
333 | ri = sk_PKCS7_RECIP_INFO_value(rsk, i); | |
334 | if (pkcs7_encode_rinfo(ri, key, keylen) <= 0) | |
335 | goto err; | |
336 | } | |
337 | OPENSSL_cleanse(key, keylen); | |
338 | ||
339 | if (out == NULL) | |
340 | out = btmp; | |
341 | else | |
342 | BIO_push(out, btmp); | |
343 | btmp = NULL; | |
344 | } | |
345 | ||
346 | if (bio == NULL) { | |
4718f449 | 347 | if (PKCS7_is_detached(p7)) { |
0f113f3e | 348 | bio = BIO_new(BIO_s_null()); |
4718f449 | 349 | } else if (os && os->length > 0) { |
0f113f3e | 350 | bio = BIO_new_mem_buf(os->data, os->length); |
4718f449 | 351 | } else { |
0f113f3e MC |
352 | bio = BIO_new(BIO_s_mem()); |
353 | if (bio == NULL) | |
354 | goto err; | |
355 | BIO_set_mem_eof_return(bio, 0); | |
356 | } | |
4718f449 MC |
357 | if (bio == NULL) |
358 | goto err; | |
0f113f3e MC |
359 | } |
360 | if (out) | |
361 | BIO_push(out, bio); | |
362 | else | |
363 | out = bio; | |
ca3a82c3 RS |
364 | return out; |
365 | ||
0f113f3e | 366 | err: |
90a1f2d7 | 367 | EVP_CIPHER_free(fetched_cipher); |
ca3a82c3 RS |
368 | BIO_free_all(out); |
369 | BIO_free_all(btmp); | |
370 | return NULL; | |
0f113f3e | 371 | } |
dfeab068 | 372 | |
8f2e4fdf | 373 | static int pkcs7_cmp_ri(PKCS7_RECIP_INFO *ri, X509 *pcert) |
0f113f3e MC |
374 | { |
375 | int ret; | |
376 | ret = X509_NAME_cmp(ri->issuer_and_serial->issuer, | |
a8d8e06b | 377 | X509_get_issuer_name(pcert)); |
0f113f3e MC |
378 | if (ret) |
379 | return ret; | |
1337a3a9 | 380 | return ASN1_INTEGER_cmp(X509_get0_serialNumber(pcert), |
a8d8e06b | 381 | ri->issuer_and_serial->serial); |
0f113f3e | 382 | } |
8f2e4fdf | 383 | |
dfeab068 | 384 | /* int */ |
84fa704c | 385 | BIO *PKCS7_dataDecode(PKCS7 *p7, EVP_PKEY *pkey, BIO *in_bio, X509 *pcert) |
0f113f3e | 386 | { |
90a1f2d7 | 387 | int i, len; |
0f113f3e MC |
388 | BIO *out = NULL, *btmp = NULL, *etmp = NULL, *bio = NULL; |
389 | X509_ALGOR *xa; | |
390 | ASN1_OCTET_STRING *data_body = NULL; | |
90a1f2d7 | 391 | EVP_MD *evp_md = NULL; |
bd1bbbfe | 392 | const EVP_MD *md; |
90a1f2d7 | 393 | EVP_CIPHER *evp_cipher = NULL; |
835b2900 | 394 | const EVP_CIPHER *cipher = NULL; |
0f113f3e MC |
395 | EVP_CIPHER_CTX *evp_ctx = NULL; |
396 | X509_ALGOR *enc_alg = NULL; | |
397 | STACK_OF(X509_ALGOR) *md_sk = NULL; | |
398 | STACK_OF(PKCS7_RECIP_INFO) *rsk = NULL; | |
399 | PKCS7_RECIP_INFO *ri = NULL; | |
400 | unsigned char *ek = NULL, *tkey = NULL; | |
401 | int eklen = 0, tkeylen = 0; | |
ad57a13b | 402 | char name[OSSL_MAX_NAME_SIZE]; |
90a1f2d7 | 403 | const PKCS7_CTX *p7_ctx; |
038f4dc6 SL |
404 | OSSL_LIB_CTX *libctx; |
405 | const char *propq; | |
0f113f3e | 406 | |
c225c3cf | 407 | if (p7 == NULL) { |
9311d0c4 | 408 | ERR_raise(ERR_LIB_PKCS7, PKCS7_R_INVALID_NULL_POINTER); |
c225c3cf EK |
409 | return NULL; |
410 | } | |
411 | ||
681618cf SL |
412 | p7_ctx = ossl_pkcs7_get0_ctx(p7); |
413 | libctx = ossl_pkcs7_ctx_get0_libctx(p7_ctx); | |
414 | propq = ossl_pkcs7_ctx_get0_propq(p7_ctx); | |
90a1f2d7 | 415 | |
c225c3cf | 416 | if (p7->d.ptr == NULL) { |
9311d0c4 | 417 | ERR_raise(ERR_LIB_PKCS7, PKCS7_R_NO_CONTENT); |
c225c3cf EK |
418 | return NULL; |
419 | } | |
420 | ||
0f113f3e MC |
421 | i = OBJ_obj2nid(p7->type); |
422 | p7->state = PKCS7_S_HEADER; | |
423 | ||
424 | switch (i) { | |
425 | case NID_pkcs7_signed: | |
59302b60 EK |
426 | /* |
427 | * p7->d.sign->contents is a PKCS7 structure consisting of a contentType | |
428 | * field and optional content. | |
429 | * data_body is NULL if that structure has no (=detached) content | |
430 | * or if the contentType is wrong (i.e., not "data"). | |
431 | */ | |
0f113f3e MC |
432 | data_body = PKCS7_get_octet_string(p7->d.sign->contents); |
433 | if (!PKCS7_is_detached(p7) && data_body == NULL) { | |
9311d0c4 | 434 | ERR_raise(ERR_LIB_PKCS7, PKCS7_R_INVALID_SIGNED_DATA_TYPE); |
0f113f3e MC |
435 | goto err; |
436 | } | |
437 | md_sk = p7->d.sign->md_algs; | |
438 | break; | |
439 | case NID_pkcs7_signedAndEnveloped: | |
440 | rsk = p7->d.signed_and_enveloped->recipientinfo; | |
441 | md_sk = p7->d.signed_and_enveloped->md_algs; | |
59302b60 | 442 | /* data_body is NULL if the optional EncryptedContent is missing. */ |
0f113f3e MC |
443 | data_body = p7->d.signed_and_enveloped->enc_data->enc_data; |
444 | enc_alg = p7->d.signed_and_enveloped->enc_data->algorithm; | |
90a1f2d7 | 445 | |
ad57a13b | 446 | OBJ_obj2txt(name, sizeof(name), enc_alg->algorithm, 0); |
835b2900 DB |
447 | |
448 | (void)ERR_set_mark(); | |
038f4dc6 | 449 | evp_cipher = EVP_CIPHER_fetch(libctx, name, propq); |
835b2900 DB |
450 | if (evp_cipher != NULL) |
451 | cipher = evp_cipher; | |
452 | else | |
453 | cipher = EVP_get_cipherbyname(name); | |
454 | ||
455 | if (cipher == NULL) { | |
456 | (void)ERR_clear_last_mark(); | |
9311d0c4 | 457 | ERR_raise(ERR_LIB_PKCS7, PKCS7_R_UNSUPPORTED_CIPHER_TYPE); |
0f113f3e MC |
458 | goto err; |
459 | } | |
835b2900 | 460 | (void)ERR_pop_to_mark(); |
0f113f3e MC |
461 | break; |
462 | case NID_pkcs7_enveloped: | |
463 | rsk = p7->d.enveloped->recipientinfo; | |
464 | enc_alg = p7->d.enveloped->enc_data->algorithm; | |
59302b60 | 465 | /* data_body is NULL if the optional EncryptedContent is missing. */ |
0f113f3e | 466 | data_body = p7->d.enveloped->enc_data->enc_data; |
ad57a13b | 467 | OBJ_obj2txt(name, sizeof(name), enc_alg->algorithm, 0); |
835b2900 DB |
468 | |
469 | (void)ERR_set_mark(); | |
038f4dc6 | 470 | evp_cipher = EVP_CIPHER_fetch(libctx, name, propq); |
835b2900 DB |
471 | if (evp_cipher != NULL) |
472 | cipher = evp_cipher; | |
473 | else | |
474 | cipher = EVP_get_cipherbyname(name); | |
475 | ||
476 | if (cipher == NULL) { | |
477 | (void)ERR_clear_last_mark(); | |
9311d0c4 | 478 | ERR_raise(ERR_LIB_PKCS7, PKCS7_R_UNSUPPORTED_CIPHER_TYPE); |
0f113f3e MC |
479 | goto err; |
480 | } | |
835b2900 | 481 | (void)ERR_pop_to_mark(); |
0f113f3e MC |
482 | break; |
483 | default: | |
9311d0c4 | 484 | ERR_raise(ERR_LIB_PKCS7, PKCS7_R_UNSUPPORTED_CONTENT_TYPE); |
0f113f3e MC |
485 | goto err; |
486 | } | |
487 | ||
59302b60 EK |
488 | /* Detached content must be supplied via in_bio instead. */ |
489 | if (data_body == NULL && in_bio == NULL) { | |
9311d0c4 | 490 | ERR_raise(ERR_LIB_PKCS7, PKCS7_R_NO_CONTENT); |
59302b60 EK |
491 | goto err; |
492 | } | |
493 | ||
0f113f3e MC |
494 | /* We will be checking the signature */ |
495 | if (md_sk != NULL) { | |
496 | for (i = 0; i < sk_X509_ALGOR_num(md_sk); i++) { | |
497 | xa = sk_X509_ALGOR_value(md_sk, i); | |
498 | if ((btmp = BIO_new(BIO_f_md())) == NULL) { | |
9311d0c4 | 499 | ERR_raise(ERR_LIB_PKCS7, ERR_R_BIO_LIB); |
0f113f3e MC |
500 | goto err; |
501 | } | |
502 | ||
ad57a13b | 503 | OBJ_obj2txt(name, sizeof(name), xa->algorithm, 0); |
bd1bbbfe DB |
504 | |
505 | (void)ERR_set_mark(); | |
038f4dc6 | 506 | evp_md = EVP_MD_fetch(libctx, name, propq); |
bd1bbbfe DB |
507 | if (evp_md != NULL) |
508 | md = evp_md; | |
509 | else | |
510 | md = EVP_get_digestbyname(name); | |
511 | ||
512 | if (md == NULL) { | |
513 | (void)ERR_clear_last_mark(); | |
9311d0c4 | 514 | ERR_raise(ERR_LIB_PKCS7, PKCS7_R_UNKNOWN_DIGEST_TYPE); |
0f113f3e MC |
515 | goto err; |
516 | } | |
bd1bbbfe | 517 | (void)ERR_pop_to_mark(); |
0f113f3e | 518 | |
6eebe6c0 TM |
519 | if (BIO_set_md(btmp, md) <= 0) { |
520 | EVP_MD_free(evp_md); | |
521 | ERR_raise(ERR_LIB_PKCS7, ERR_R_BIO_LIB); | |
522 | goto err; | |
523 | } | |
90a1f2d7 | 524 | EVP_MD_free(evp_md); |
0f113f3e MC |
525 | if (out == NULL) |
526 | out = btmp; | |
527 | else | |
528 | BIO_push(out, btmp); | |
529 | btmp = NULL; | |
530 | } | |
531 | } | |
532 | ||
835b2900 | 533 | if (cipher != NULL) { |
0f113f3e | 534 | if ((etmp = BIO_new(BIO_f_cipher())) == NULL) { |
9311d0c4 | 535 | ERR_raise(ERR_LIB_PKCS7, ERR_R_BIO_LIB); |
0f113f3e MC |
536 | goto err; |
537 | } | |
538 | ||
539 | /* | |
540 | * It was encrypted, we need to decrypt the secret key with the | |
541 | * private key | |
542 | */ | |
543 | ||
544 | /* | |
545 | * Find the recipientInfo which matches the passed certificate (if | |
546 | * any) | |
547 | */ | |
548 | ||
549 | if (pcert) { | |
550 | for (i = 0; i < sk_PKCS7_RECIP_INFO_num(rsk); i++) { | |
551 | ri = sk_PKCS7_RECIP_INFO_value(rsk, i); | |
552 | if (!pkcs7_cmp_ri(ri, pcert)) | |
553 | break; | |
554 | ri = NULL; | |
555 | } | |
556 | if (ri == NULL) { | |
9311d0c4 RL |
557 | ERR_raise(ERR_LIB_PKCS7, |
558 | PKCS7_R_NO_RECIPIENT_MATCHES_CERTIFICATE); | |
0f113f3e MC |
559 | goto err; |
560 | } | |
561 | } | |
562 | ||
563 | /* If we haven't got a certificate try each ri in turn */ | |
564 | if (pcert == NULL) { | |
565 | /* | |
566 | * Always attempt to decrypt all rinfo even after success as a | |
567 | * defence against MMA timing attacks. | |
568 | */ | |
569 | for (i = 0; i < sk_PKCS7_RECIP_INFO_num(rsk); i++) { | |
570 | ri = sk_PKCS7_RECIP_INFO_value(rsk, i); | |
90a1f2d7 | 571 | ri->ctx = p7_ctx; |
5840ed0c | 572 | if (pkcs7_decrypt_rinfo(&ek, &eklen, ri, pkey, |
ed576acd | 573 | EVP_CIPHER_get_key_length(cipher)) < 0) |
0f113f3e MC |
574 | goto err; |
575 | ERR_clear_error(); | |
576 | } | |
577 | } else { | |
90a1f2d7 | 578 | ri->ctx = p7_ctx; |
0f113f3e | 579 | /* Only exit on fatal errors, not decrypt failure */ |
5840ed0c | 580 | if (pkcs7_decrypt_rinfo(&ek, &eklen, ri, pkey, 0) < 0) |
0f113f3e MC |
581 | goto err; |
582 | ERR_clear_error(); | |
583 | } | |
584 | ||
585 | evp_ctx = NULL; | |
586 | BIO_get_cipher_ctx(etmp, &evp_ctx); | |
835b2900 | 587 | if (EVP_CipherInit_ex(evp_ctx, cipher, NULL, NULL, NULL, 0) <= 0) |
0f113f3e | 588 | goto err; |
114d99b4 | 589 | if (EVP_CIPHER_asn1_to_param(evp_ctx, enc_alg->parameter) <= 0) |
0f113f3e MC |
590 | goto err; |
591 | /* Generate random key as MMA defence */ | |
ed576acd | 592 | len = EVP_CIPHER_CTX_get_key_length(evp_ctx); |
eae4a008 SL |
593 | if (len <= 0) |
594 | goto err; | |
595 | tkeylen = (size_t)len; | |
0f113f3e | 596 | tkey = OPENSSL_malloc(tkeylen); |
90945fa3 | 597 | if (tkey == NULL) |
0f113f3e MC |
598 | goto err; |
599 | if (EVP_CIPHER_CTX_rand_key(evp_ctx, tkey) <= 0) | |
600 | goto err; | |
601 | if (ek == NULL) { | |
602 | ek = tkey; | |
603 | eklen = tkeylen; | |
604 | tkey = NULL; | |
605 | } | |
606 | ||
ed576acd | 607 | if (eklen != EVP_CIPHER_CTX_get_key_length(evp_ctx)) { |
0f113f3e MC |
608 | /* |
609 | * Some S/MIME clients don't use the same key and effective key | |
610 | * length. The key length is determined by the size of the | |
611 | * decrypted RSA key. | |
612 | */ | |
8d9fec17 | 613 | if (EVP_CIPHER_CTX_set_key_length(evp_ctx, eklen) <= 0) { |
0f113f3e | 614 | /* Use random key as MMA defence */ |
4b45c6e5 | 615 | OPENSSL_clear_free(ek, eklen); |
0f113f3e MC |
616 | ek = tkey; |
617 | eklen = tkeylen; | |
618 | tkey = NULL; | |
619 | } | |
620 | } | |
621 | /* Clear errors so we don't leak information useful in MMA */ | |
622 | ERR_clear_error(); | |
623 | if (EVP_CipherInit_ex(evp_ctx, NULL, NULL, ek, NULL, 0) <= 0) | |
624 | goto err; | |
625 | ||
4b45c6e5 RS |
626 | OPENSSL_clear_free(ek, eklen); |
627 | ek = NULL; | |
628 | OPENSSL_clear_free(tkey, tkeylen); | |
629 | tkey = NULL; | |
0f113f3e MC |
630 | |
631 | if (out == NULL) | |
632 | out = etmp; | |
633 | else | |
634 | BIO_push(out, etmp); | |
635 | etmp = NULL; | |
636 | } | |
59302b60 | 637 | if (in_bio != NULL) { |
0f113f3e MC |
638 | bio = in_bio; |
639 | } else { | |
0f113f3e MC |
640 | if (data_body->length > 0) |
641 | bio = BIO_new_mem_buf(data_body->data, data_body->length); | |
642 | else { | |
643 | bio = BIO_new(BIO_s_mem()); | |
90945fa3 MC |
644 | if (bio == NULL) |
645 | goto err; | |
0f113f3e MC |
646 | BIO_set_mem_eof_return(bio, 0); |
647 | } | |
648 | if (bio == NULL) | |
649 | goto err; | |
0f113f3e MC |
650 | } |
651 | BIO_push(out, bio); | |
652 | bio = NULL; | |
90a1f2d7 | 653 | EVP_CIPHER_free(evp_cipher); |
4b45c6e5 RS |
654 | return out; |
655 | ||
0f113f3e | 656 | err: |
90a1f2d7 | 657 | EVP_CIPHER_free(evp_cipher); |
4b45c6e5 RS |
658 | OPENSSL_clear_free(ek, eklen); |
659 | OPENSSL_clear_free(tkey, tkeylen); | |
660 | BIO_free_all(out); | |
661 | BIO_free_all(btmp); | |
662 | BIO_free_all(etmp); | |
663 | BIO_free_all(bio); | |
02e112a8 | 664 | return NULL; |
0f113f3e | 665 | } |
d02b48c6 | 666 | |
c5a55463 | 667 | static BIO *PKCS7_find_digest(EVP_MD_CTX **pmd, BIO *bio, int nid) |
0f113f3e MC |
668 | { |
669 | for (;;) { | |
670 | bio = BIO_find_type(bio, BIO_TYPE_MD); | |
671 | if (bio == NULL) { | |
9311d0c4 | 672 | ERR_raise(ERR_LIB_PKCS7, PKCS7_R_UNABLE_TO_FIND_MESSAGE_DIGEST); |
0f113f3e MC |
673 | return NULL; |
674 | } | |
675 | BIO_get_md_ctx(bio, pmd); | |
676 | if (*pmd == NULL) { | |
9311d0c4 | 677 | ERR_raise(ERR_LIB_PKCS7, ERR_R_INTERNAL_ERROR); |
0f113f3e MC |
678 | return NULL; |
679 | } | |
ed576acd | 680 | if (EVP_MD_CTX_get_type(*pmd) == nid) |
0f113f3e MC |
681 | return bio; |
682 | bio = BIO_next(bio); | |
683 | } | |
684 | return NULL; | |
685 | } | |
c5a55463 | 686 | |
76fa8f18 | 687 | static int do_pkcs7_signed_attrib(PKCS7_SIGNER_INFO *si, EVP_MD_CTX *mctx) |
0f113f3e MC |
688 | { |
689 | unsigned char md_data[EVP_MAX_MD_SIZE]; | |
690 | unsigned int md_len; | |
691 | ||
692 | /* Add signing time if not already present */ | |
693 | if (!PKCS7_get_signed_attribute(si, NID_pkcs9_signingTime)) { | |
694 | if (!PKCS7_add0_attrib_signing_time(si, NULL)) { | |
e077455e | 695 | ERR_raise(ERR_LIB_PKCS7, ERR_R_PKCS7_LIB); |
0f113f3e MC |
696 | return 0; |
697 | } | |
698 | } | |
699 | ||
700 | /* Add digest */ | |
701 | if (!EVP_DigestFinal_ex(mctx, md_data, &md_len)) { | |
9311d0c4 | 702 | ERR_raise(ERR_LIB_PKCS7, ERR_R_EVP_LIB); |
0f113f3e MC |
703 | return 0; |
704 | } | |
705 | if (!PKCS7_add1_attrib_digest(si, md_data, md_len)) { | |
e077455e | 706 | ERR_raise(ERR_LIB_PKCS7, ERR_R_PKCS7_LIB); |
0f113f3e MC |
707 | return 0; |
708 | } | |
709 | ||
710 | /* Now sign the attributes */ | |
711 | if (!PKCS7_SIGNER_INFO_sign(si)) | |
712 | return 0; | |
713 | ||
714 | return 1; | |
715 | } | |
716 | ||
6b691a5c | 717 | int PKCS7_dataFinal(PKCS7 *p7, BIO *bio) |
0f113f3e MC |
718 | { |
719 | int ret = 0; | |
720 | int i, j; | |
721 | BIO *btmp; | |
722 | PKCS7_SIGNER_INFO *si; | |
6e59a892 | 723 | EVP_MD_CTX *mdc, *ctx_tmp; |
0f113f3e MC |
724 | STACK_OF(X509_ATTRIBUTE) *sk; |
725 | STACK_OF(PKCS7_SIGNER_INFO) *si_sk = NULL; | |
726 | ASN1_OCTET_STRING *os = NULL; | |
90a1f2d7 | 727 | const PKCS7_CTX *p7_ctx; |
0f113f3e | 728 | |
c225c3cf | 729 | if (p7 == NULL) { |
9311d0c4 | 730 | ERR_raise(ERR_LIB_PKCS7, PKCS7_R_INVALID_NULL_POINTER); |
c225c3cf EK |
731 | return 0; |
732 | } | |
733 | ||
681618cf | 734 | p7_ctx = ossl_pkcs7_get0_ctx(p7); |
90a1f2d7 | 735 | |
c225c3cf | 736 | if (p7->d.ptr == NULL) { |
9311d0c4 | 737 | ERR_raise(ERR_LIB_PKCS7, PKCS7_R_NO_CONTENT); |
c225c3cf EK |
738 | return 0; |
739 | } | |
740 | ||
bfb0641f | 741 | ctx_tmp = EVP_MD_CTX_new(); |
6e59a892 | 742 | if (ctx_tmp == NULL) { |
e077455e | 743 | ERR_raise(ERR_LIB_PKCS7, ERR_R_EVP_LIB); |
6e59a892 RL |
744 | return 0; |
745 | } | |
746 | ||
0f113f3e MC |
747 | i = OBJ_obj2nid(p7->type); |
748 | p7->state = PKCS7_S_HEADER; | |
749 | ||
750 | switch (i) { | |
751 | case NID_pkcs7_data: | |
752 | os = p7->d.data; | |
753 | break; | |
754 | case NID_pkcs7_signedAndEnveloped: | |
755 | /* XXXXXXXXXXXXXXXX */ | |
756 | si_sk = p7->d.signed_and_enveloped->signer_info; | |
757 | os = p7->d.signed_and_enveloped->enc_data->enc_data; | |
90945fa3 | 758 | if (os == NULL) { |
f422a514 | 759 | os = ASN1_OCTET_STRING_new(); |
90945fa3 | 760 | if (os == NULL) { |
e077455e | 761 | ERR_raise(ERR_LIB_PKCS7, ERR_R_ASN1_LIB); |
0f113f3e MC |
762 | goto err; |
763 | } | |
764 | p7->d.signed_and_enveloped->enc_data->enc_data = os; | |
765 | } | |
766 | break; | |
767 | case NID_pkcs7_enveloped: | |
768 | /* XXXXXXXXXXXXXXXX */ | |
769 | os = p7->d.enveloped->enc_data->enc_data; | |
90945fa3 | 770 | if (os == NULL) { |
f422a514 | 771 | os = ASN1_OCTET_STRING_new(); |
90945fa3 | 772 | if (os == NULL) { |
e077455e | 773 | ERR_raise(ERR_LIB_PKCS7, ERR_R_ASN1_LIB); |
0f113f3e MC |
774 | goto err; |
775 | } | |
776 | p7->d.enveloped->enc_data->enc_data = os; | |
777 | } | |
778 | break; | |
779 | case NID_pkcs7_signed: | |
780 | si_sk = p7->d.sign->signer_info; | |
781 | os = PKCS7_get_octet_string(p7->d.sign->contents); | |
782 | /* If detached data then the content is excluded */ | |
783 | if (PKCS7_type_is_data(p7->d.sign->contents) && p7->detached) { | |
f422a514 | 784 | ASN1_OCTET_STRING_free(os); |
c225c3cf | 785 | os = NULL; |
0f113f3e MC |
786 | p7->d.sign->contents->d.data = NULL; |
787 | } | |
788 | break; | |
789 | ||
790 | case NID_pkcs7_digest: | |
791 | os = PKCS7_get_octet_string(p7->d.digest->contents); | |
792 | /* If detached data then the content is excluded */ | |
793 | if (PKCS7_type_is_data(p7->d.digest->contents) && p7->detached) { | |
f422a514 | 794 | ASN1_OCTET_STRING_free(os); |
c225c3cf | 795 | os = NULL; |
0f113f3e MC |
796 | p7->d.digest->contents->d.data = NULL; |
797 | } | |
798 | break; | |
799 | ||
800 | default: | |
9311d0c4 | 801 | ERR_raise(ERR_LIB_PKCS7, PKCS7_R_UNSUPPORTED_CONTENT_TYPE); |
0f113f3e MC |
802 | goto err; |
803 | } | |
804 | ||
805 | if (si_sk != NULL) { | |
806 | for (i = 0; i < sk_PKCS7_SIGNER_INFO_num(si_sk); i++) { | |
807 | si = sk_PKCS7_SIGNER_INFO_value(si_sk, i); | |
808 | if (si->pkey == NULL) | |
809 | continue; | |
810 | ||
811 | j = OBJ_obj2nid(si->digest_alg->algorithm); | |
812 | ||
813 | btmp = bio; | |
814 | ||
815 | btmp = PKCS7_find_digest(&mdc, btmp, j); | |
816 | ||
817 | if (btmp == NULL) | |
818 | goto err; | |
819 | ||
820 | /* | |
821 | * We now have the EVP_MD_CTX, lets do the signing. | |
822 | */ | |
6e59a892 | 823 | if (!EVP_MD_CTX_copy_ex(ctx_tmp, mdc)) |
0f113f3e MC |
824 | goto err; |
825 | ||
826 | sk = si->auth_attr; | |
827 | ||
828 | /* | |
829 | * If there are attributes, we add the digest attribute and only | |
830 | * sign the attributes | |
831 | */ | |
832 | if (sk_X509_ATTRIBUTE_num(sk) > 0) { | |
6e59a892 | 833 | if (!do_pkcs7_signed_attrib(si, ctx_tmp)) |
0f113f3e MC |
834 | goto err; |
835 | } else { | |
836 | unsigned char *abuf = NULL; | |
837 | unsigned int abuflen; | |
ed576acd | 838 | abuflen = EVP_PKEY_get_size(si->pkey); |
0f113f3e | 839 | abuf = OPENSSL_malloc(abuflen); |
90945fa3 | 840 | if (abuf == NULL) |
0f113f3e MC |
841 | goto err; |
842 | ||
d8652be0 | 843 | if (!EVP_SignFinal_ex(ctx_tmp, abuf, &abuflen, si->pkey, |
681618cf SL |
844 | ossl_pkcs7_ctx_get0_libctx(p7_ctx), |
845 | ossl_pkcs7_ctx_get0_propq(p7_ctx))) { | |
d54ac5c4 | 846 | OPENSSL_free(abuf); |
9311d0c4 | 847 | ERR_raise(ERR_LIB_PKCS7, ERR_R_EVP_LIB); |
0f113f3e MC |
848 | goto err; |
849 | } | |
850 | ASN1_STRING_set0(si->enc_digest, abuf, abuflen); | |
851 | } | |
852 | } | |
853 | } else if (i == NID_pkcs7_digest) { | |
854 | unsigned char md_data[EVP_MAX_MD_SIZE]; | |
855 | unsigned int md_len; | |
856 | if (!PKCS7_find_digest(&mdc, bio, | |
857 | OBJ_obj2nid(p7->d.digest->md->algorithm))) | |
858 | goto err; | |
859 | if (!EVP_DigestFinal_ex(mdc, md_data, &md_len)) | |
860 | goto err; | |
d356dc56 MC |
861 | if (!ASN1_OCTET_STRING_set(p7->d.digest->digest, md_data, md_len)) |
862 | goto err; | |
0f113f3e MC |
863 | } |
864 | ||
c225c3cf | 865 | if (!PKCS7_is_detached(p7)) { |
0f113f3e | 866 | /* |
c225c3cf EK |
867 | * NOTE(emilia): I think we only reach os == NULL here because detached |
868 | * digested data support is broken. | |
0f113f3e | 869 | */ |
c225c3cf EK |
870 | if (os == NULL) |
871 | goto err; | |
872 | if (!(os->flags & ASN1_STRING_FLAG_NDEF)) { | |
873 | char *cont; | |
874 | long contlen; | |
875 | btmp = BIO_find_type(bio, BIO_TYPE_MEM); | |
876 | if (btmp == NULL) { | |
9311d0c4 | 877 | ERR_raise(ERR_LIB_PKCS7, PKCS7_R_UNABLE_TO_FIND_MEM_BIO); |
c225c3cf EK |
878 | goto err; |
879 | } | |
880 | contlen = BIO_get_mem_data(btmp, &cont); | |
881 | /* | |
882 | * Mark the BIO read only then we can use its copy of the data | |
883 | * instead of making an extra copy. | |
884 | */ | |
885 | BIO_set_flags(btmp, BIO_FLAGS_MEM_RDONLY); | |
886 | BIO_set_mem_eof_return(btmp, 0); | |
887 | ASN1_STRING_set0(os, (unsigned char *)cont, contlen); | |
888 | } | |
0f113f3e MC |
889 | } |
890 | ret = 1; | |
891 | err: | |
bfb0641f | 892 | EVP_MD_CTX_free(ctx_tmp); |
26a7d938 | 893 | return ret; |
0f113f3e | 894 | } |
d02b48c6 | 895 | |
76fa8f18 | 896 | int PKCS7_SIGNER_INFO_sign(PKCS7_SIGNER_INFO *si) |
0f113f3e | 897 | { |
6e59a892 | 898 | EVP_MD_CTX *mctx; |
e6803117 | 899 | EVP_PKEY_CTX *pctx = NULL; |
0f113f3e MC |
900 | unsigned char *abuf = NULL; |
901 | int alen; | |
902 | size_t siglen; | |
903 | const EVP_MD *md = NULL; | |
90a1f2d7 | 904 | const PKCS7_CTX *ctx = si->ctx; |
0f113f3e MC |
905 | |
906 | md = EVP_get_digestbyobj(si->digest_alg->algorithm); | |
907 | if (md == NULL) | |
908 | return 0; | |
909 | ||
bfb0641f | 910 | mctx = EVP_MD_CTX_new(); |
6e59a892 | 911 | if (mctx == NULL) { |
e077455e | 912 | ERR_raise(ERR_LIB_PKCS7, ERR_R_EVP_LIB); |
6e59a892 RL |
913 | goto err; |
914 | } | |
915 | ||
ed576acd | 916 | if (EVP_DigestSignInit_ex(mctx, &pctx, EVP_MD_get0_name(md), |
681618cf | 917 | ossl_pkcs7_ctx_get0_libctx(ctx), |
1666eec8 P |
918 | ossl_pkcs7_ctx_get0_propq(ctx), si->pkey, |
919 | NULL) <= 0) | |
0f113f3e MC |
920 | goto err; |
921 | ||
0f113f3e MC |
922 | alen = ASN1_item_i2d((ASN1_VALUE *)si->auth_attr, &abuf, |
923 | ASN1_ITEM_rptr(PKCS7_ATTR_SIGN)); | |
924 | if (!abuf) | |
925 | goto err; | |
6e59a892 | 926 | if (EVP_DigestSignUpdate(mctx, abuf, alen) <= 0) |
0f113f3e MC |
927 | goto err; |
928 | OPENSSL_free(abuf); | |
929 | abuf = NULL; | |
6e59a892 | 930 | if (EVP_DigestSignFinal(mctx, NULL, &siglen) <= 0) |
0f113f3e MC |
931 | goto err; |
932 | abuf = OPENSSL_malloc(siglen); | |
90945fa3 | 933 | if (abuf == NULL) |
0f113f3e | 934 | goto err; |
6e59a892 | 935 | if (EVP_DigestSignFinal(mctx, abuf, &siglen) <= 0) |
0f113f3e MC |
936 | goto err; |
937 | ||
bfb0641f | 938 | EVP_MD_CTX_free(mctx); |
0f113f3e MC |
939 | |
940 | ASN1_STRING_set0(si->enc_digest, abuf, siglen); | |
941 | ||
942 | return 1; | |
943 | ||
944 | err: | |
b548a1f1 | 945 | OPENSSL_free(abuf); |
bfb0641f | 946 | EVP_MD_CTX_free(mctx); |
0f113f3e | 947 | return 0; |
0f113f3e | 948 | } |
76fa8f18 | 949 | |
2b445654 | 950 | /* This partly overlaps with PKCS7_verify(). It does not support flags. */ |
6b691a5c | 951 | int PKCS7_dataVerify(X509_STORE *cert_store, X509_STORE_CTX *ctx, BIO *bio, |
0f113f3e MC |
952 | PKCS7 *p7, PKCS7_SIGNER_INFO *si) |
953 | { | |
954 | PKCS7_ISSUER_AND_SERIAL *ias; | |
955 | int ret = 0, i; | |
2b445654 DDO |
956 | STACK_OF(X509) *untrusted; |
957 | STACK_OF(X509_CRL) *crls; | |
958 | X509 *signer; | |
0f113f3e | 959 | |
c225c3cf | 960 | if (p7 == NULL) { |
9311d0c4 | 961 | ERR_raise(ERR_LIB_PKCS7, PKCS7_R_INVALID_NULL_POINTER); |
c225c3cf EK |
962 | return 0; |
963 | } | |
964 | ||
965 | if (p7->d.ptr == NULL) { | |
9311d0c4 | 966 | ERR_raise(ERR_LIB_PKCS7, PKCS7_R_NO_CONTENT); |
c225c3cf EK |
967 | return 0; |
968 | } | |
969 | ||
0f113f3e | 970 | if (PKCS7_type_is_signed(p7)) { |
2b445654 DDO |
971 | untrusted = p7->d.sign->cert; |
972 | crls = p7->d.sign->crl; | |
0f113f3e | 973 | } else if (PKCS7_type_is_signedAndEnveloped(p7)) { |
2b445654 DDO |
974 | untrusted = p7->d.signed_and_enveloped->cert; |
975 | crls = p7->d.signed_and_enveloped->crl; | |
0f113f3e | 976 | } else { |
9311d0c4 | 977 | ERR_raise(ERR_LIB_PKCS7, PKCS7_R_WRONG_PKCS7_TYPE); |
0f113f3e MC |
978 | goto err; |
979 | } | |
2b445654 DDO |
980 | X509_STORE_CTX_set0_crls(ctx, crls); |
981 | ||
0f113f3e MC |
982 | /* XXXXXXXXXXXXXXXXXXXXXXX */ |
983 | ias = si->issuer_and_serial; | |
984 | ||
2b445654 | 985 | signer = X509_find_by_issuer_and_serial(untrusted, ias->issuer, ias->serial); |
0f113f3e | 986 | |
2b445654 DDO |
987 | /* Were we able to find the signer certificate in passed to us? */ |
988 | if (signer == NULL) { | |
9311d0c4 | 989 | ERR_raise(ERR_LIB_PKCS7, PKCS7_R_UNABLE_TO_FIND_CERTIFICATE); |
0f113f3e MC |
990 | goto err; |
991 | } | |
992 | ||
993 | /* Lets verify */ | |
2b445654 | 994 | if (!X509_STORE_CTX_init(ctx, cert_store, signer, untrusted)) { |
9311d0c4 | 995 | ERR_raise(ERR_LIB_PKCS7, ERR_R_X509_LIB); |
0f113f3e MC |
996 | goto err; |
997 | } | |
998 | X509_STORE_CTX_set_purpose(ctx, X509_PURPOSE_SMIME_SIGN); | |
999 | i = X509_verify_cert(ctx); | |
1000 | if (i <= 0) { | |
9311d0c4 | 1001 | ERR_raise(ERR_LIB_PKCS7, ERR_R_X509_LIB); |
0f113f3e MC |
1002 | goto err; |
1003 | } | |
0f113f3e | 1004 | |
2b445654 | 1005 | return PKCS7_signatureVerify(bio, p7, si, signer); |
0f113f3e MC |
1006 | err: |
1007 | return ret; | |
1008 | } | |
170afce5 DSH |
1009 | |
1010 | int PKCS7_signatureVerify(BIO *bio, PKCS7 *p7, PKCS7_SIGNER_INFO *si, | |
2b445654 | 1011 | X509 *signer) |
dfeab068 | 1012 | { |
0f113f3e | 1013 | ASN1_OCTET_STRING *os; |
6e59a892 | 1014 | EVP_MD_CTX *mdc_tmp, *mdc; |
bd1bbbfe | 1015 | const EVP_MD *md; |
90a1f2d7 | 1016 | EVP_MD *fetched_md = NULL; |
0f113f3e MC |
1017 | int ret = 0, i; |
1018 | int md_type; | |
1019 | STACK_OF(X509_ATTRIBUTE) *sk; | |
1020 | BIO *btmp; | |
1021 | EVP_PKEY *pkey; | |
681618cf SL |
1022 | const PKCS7_CTX *ctx = ossl_pkcs7_get0_ctx(p7); |
1023 | OSSL_LIB_CTX *libctx = ossl_pkcs7_ctx_get0_libctx(ctx); | |
1024 | const char *propq = ossl_pkcs7_ctx_get0_propq(ctx); | |
0f113f3e | 1025 | |
bfb0641f | 1026 | mdc_tmp = EVP_MD_CTX_new(); |
6e59a892 | 1027 | if (mdc_tmp == NULL) { |
e077455e | 1028 | ERR_raise(ERR_LIB_PKCS7, ERR_R_EVP_LIB); |
6e59a892 RL |
1029 | goto err; |
1030 | } | |
0f113f3e MC |
1031 | |
1032 | if (!PKCS7_type_is_signed(p7) && !PKCS7_type_is_signedAndEnveloped(p7)) { | |
9311d0c4 | 1033 | ERR_raise(ERR_LIB_PKCS7, PKCS7_R_WRONG_PKCS7_TYPE); |
0f113f3e MC |
1034 | goto err; |
1035 | } | |
1036 | ||
1037 | md_type = OBJ_obj2nid(si->digest_alg->algorithm); | |
1038 | ||
1039 | btmp = bio; | |
1040 | for (;;) { | |
1041 | if ((btmp == NULL) || | |
1042 | ((btmp = BIO_find_type(btmp, BIO_TYPE_MD)) == NULL)) { | |
9311d0c4 | 1043 | ERR_raise(ERR_LIB_PKCS7, PKCS7_R_UNABLE_TO_FIND_MESSAGE_DIGEST); |
0f113f3e MC |
1044 | goto err; |
1045 | } | |
1046 | BIO_get_md_ctx(btmp, &mdc); | |
1047 | if (mdc == NULL) { | |
9311d0c4 | 1048 | ERR_raise(ERR_LIB_PKCS7, ERR_R_INTERNAL_ERROR); |
0f113f3e MC |
1049 | goto err; |
1050 | } | |
ed576acd | 1051 | if (EVP_MD_CTX_get_type(mdc) == md_type) |
0f113f3e MC |
1052 | break; |
1053 | /* | |
1054 | * Workaround for some broken clients that put the signature OID | |
1055 | * instead of the digest OID in digest_alg->algorithm | |
1056 | */ | |
ed576acd | 1057 | if (EVP_MD_get_pkey_type(EVP_MD_CTX_get0_md(mdc)) == md_type) |
0f113f3e MC |
1058 | break; |
1059 | btmp = BIO_next(btmp); | |
1060 | } | |
1061 | ||
1062 | /* | |
1063 | * mdc is the digest ctx that we want, unless there are attributes, in | |
1064 | * which case the digest is the signed attributes | |
1065 | */ | |
6e59a892 | 1066 | if (!EVP_MD_CTX_copy_ex(mdc_tmp, mdc)) |
0f113f3e MC |
1067 | goto err; |
1068 | ||
1069 | sk = si->auth_attr; | |
1070 | if ((sk != NULL) && (sk_X509_ATTRIBUTE_num(sk) != 0)) { | |
1071 | unsigned char md_dat[EVP_MAX_MD_SIZE], *abuf = NULL; | |
1072 | unsigned int md_len; | |
1073 | int alen; | |
1074 | ASN1_OCTET_STRING *message_digest; | |
1075 | ||
6e59a892 | 1076 | if (!EVP_DigestFinal_ex(mdc_tmp, md_dat, &md_len)) |
0f113f3e MC |
1077 | goto err; |
1078 | message_digest = PKCS7_digest_from_attributes(sk); | |
1079 | if (!message_digest) { | |
9311d0c4 | 1080 | ERR_raise(ERR_LIB_PKCS7, PKCS7_R_UNABLE_TO_FIND_MESSAGE_DIGEST); |
0f113f3e MC |
1081 | goto err; |
1082 | } | |
1083 | if ((message_digest->length != (int)md_len) || | |
1084 | (memcmp(message_digest->data, md_dat, md_len))) { | |
9311d0c4 | 1085 | ERR_raise(ERR_LIB_PKCS7, PKCS7_R_DIGEST_FAILURE); |
0f113f3e MC |
1086 | ret = -1; |
1087 | goto err; | |
1088 | } | |
1089 | ||
bd1bbbfe | 1090 | (void)ERR_set_mark(); |
038f4dc6 | 1091 | fetched_md = EVP_MD_fetch(libctx, OBJ_nid2sn(md_type), propq); |
bd1bbbfe DB |
1092 | |
1093 | if (fetched_md != NULL) | |
1094 | md = fetched_md; | |
1095 | else | |
1096 | md = EVP_get_digestbynid(md_type); | |
1097 | ||
1098 | if (md == NULL || !EVP_VerifyInit_ex(mdc_tmp, md, NULL)) { | |
1099 | (void)ERR_clear_last_mark(); | |
0f113f3e | 1100 | goto err; |
bd1bbbfe DB |
1101 | } |
1102 | (void)ERR_pop_to_mark(); | |
0f113f3e MC |
1103 | |
1104 | alen = ASN1_item_i2d((ASN1_VALUE *)sk, &abuf, | |
1105 | ASN1_ITEM_rptr(PKCS7_ATTR_VERIFY)); | |
1106 | if (alen <= 0) { | |
9311d0c4 | 1107 | ERR_raise(ERR_LIB_PKCS7, ERR_R_ASN1_LIB); |
0f113f3e MC |
1108 | ret = -1; |
1109 | goto err; | |
1110 | } | |
6e59a892 | 1111 | if (!EVP_VerifyUpdate(mdc_tmp, abuf, alen)) |
0f113f3e MC |
1112 | goto err; |
1113 | ||
1114 | OPENSSL_free(abuf); | |
1115 | } | |
1116 | ||
1117 | os = si->enc_digest; | |
2b445654 | 1118 | pkey = X509_get0_pubkey(signer); |
12a765a5 | 1119 | if (pkey == NULL) { |
0f113f3e MC |
1120 | ret = -1; |
1121 | goto err; | |
1122 | } | |
1123 | ||
038f4dc6 | 1124 | i = EVP_VerifyFinal_ex(mdc_tmp, os->data, os->length, pkey, libctx, propq); |
0f113f3e | 1125 | if (i <= 0) { |
9311d0c4 | 1126 | ERR_raise(ERR_LIB_PKCS7, PKCS7_R_SIGNATURE_FAILURE); |
0f113f3e MC |
1127 | ret = -1; |
1128 | goto err; | |
c5ba2d99 RS |
1129 | } |
1130 | ret = 1; | |
0f113f3e | 1131 | err: |
bfb0641f | 1132 | EVP_MD_CTX_free(mdc_tmp); |
90a1f2d7 | 1133 | EVP_MD_free(fetched_md); |
26a7d938 | 1134 | return ret; |
0f113f3e | 1135 | } |
d02b48c6 | 1136 | |
6b691a5c | 1137 | PKCS7_ISSUER_AND_SERIAL *PKCS7_get_issuer_and_serial(PKCS7 *p7, int idx) |
0f113f3e MC |
1138 | { |
1139 | STACK_OF(PKCS7_RECIP_INFO) *rsk; | |
1140 | PKCS7_RECIP_INFO *ri; | |
1141 | int i; | |
1142 | ||
1143 | i = OBJ_obj2nid(p7->type); | |
1144 | if (i != NID_pkcs7_signedAndEnveloped) | |
1145 | return NULL; | |
1146 | if (p7->d.signed_and_enveloped == NULL) | |
1147 | return NULL; | |
1148 | rsk = p7->d.signed_and_enveloped->recipientinfo; | |
1149 | if (rsk == NULL) | |
1150 | return NULL; | |
0f113f3e | 1151 | if (sk_PKCS7_RECIP_INFO_num(rsk) <= idx) |
26a7d938 | 1152 | return NULL; |
0f113f3e | 1153 | ri = sk_PKCS7_RECIP_INFO_value(rsk, idx); |
26a7d938 | 1154 | return ri->issuer_and_serial; |
0f113f3e | 1155 | } |
dfeab068 | 1156 | |
63b64f19 | 1157 | ASN1_TYPE *PKCS7_get_signed_attribute(const PKCS7_SIGNER_INFO *si, int nid) |
0f113f3e | 1158 | { |
26a7d938 | 1159 | return get_attribute(si->auth_attr, nid); |
0f113f3e | 1160 | } |
dfeab068 | 1161 | |
63b64f19 | 1162 | ASN1_TYPE *PKCS7_get_attribute(const PKCS7_SIGNER_INFO *si, int nid) |
0f113f3e | 1163 | { |
26a7d938 | 1164 | return get_attribute(si->unauth_attr, nid); |
0f113f3e | 1165 | } |
dfeab068 | 1166 | |
63b64f19 | 1167 | static ASN1_TYPE *get_attribute(const STACK_OF(X509_ATTRIBUTE) *sk, int nid) |
0f113f3e | 1168 | { |
ba9e3721 DDO |
1169 | int idx = X509at_get_attr_by_NID(sk, nid, -1); |
1170 | ||
1171 | if (idx < 0) | |
1172 | return NULL; | |
1173 | return X509_ATTRIBUTE_get0_type(X509at_get_attr(sk, idx), 0); | |
0f113f3e | 1174 | } |
dfeab068 | 1175 | |
b6436ff2 | 1176 | ASN1_OCTET_STRING *PKCS7_digest_from_attributes(STACK_OF(X509_ATTRIBUTE) *sk) |
10243d97 | 1177 | { |
0f113f3e | 1178 | ASN1_TYPE *astype; |
75ebbd9a | 1179 | if ((astype = get_attribute(sk, NID_pkcs9_messageDigest)) == NULL) |
0f113f3e MC |
1180 | return NULL; |
1181 | return astype->value.octet_string; | |
10243d97 | 1182 | } |
dfeab068 | 1183 | |
b6436ff2 | 1184 | int PKCS7_set_signed_attributes(PKCS7_SIGNER_INFO *p7si, |
0f113f3e MC |
1185 | STACK_OF(X509_ATTRIBUTE) *sk) |
1186 | { | |
1187 | int i; | |
1188 | ||
222561fe | 1189 | sk_X509_ATTRIBUTE_pop_free(p7si->auth_attr, X509_ATTRIBUTE_free); |
0f113f3e MC |
1190 | p7si->auth_attr = sk_X509_ATTRIBUTE_dup(sk); |
1191 | if (p7si->auth_attr == NULL) | |
1192 | return 0; | |
1193 | for (i = 0; i < sk_X509_ATTRIBUTE_num(sk); i++) { | |
1194 | if ((sk_X509_ATTRIBUTE_set(p7si->auth_attr, i, | |
1195 | X509_ATTRIBUTE_dup(sk_X509_ATTRIBUTE_value | |
1196 | (sk, i)))) | |
1197 | == NULL) | |
26a7d938 | 1198 | return 0; |
0f113f3e | 1199 | } |
208fb891 | 1200 | return 1; |
0f113f3e MC |
1201 | } |
1202 | ||
1203 | int PKCS7_set_attributes(PKCS7_SIGNER_INFO *p7si, | |
1204 | STACK_OF(X509_ATTRIBUTE) *sk) | |
1205 | { | |
1206 | int i; | |
1207 | ||
222561fe | 1208 | sk_X509_ATTRIBUTE_pop_free(p7si->unauth_attr, X509_ATTRIBUTE_free); |
0f113f3e MC |
1209 | p7si->unauth_attr = sk_X509_ATTRIBUTE_dup(sk); |
1210 | if (p7si->unauth_attr == NULL) | |
1211 | return 0; | |
1212 | for (i = 0; i < sk_X509_ATTRIBUTE_num(sk); i++) { | |
1213 | if ((sk_X509_ATTRIBUTE_set(p7si->unauth_attr, i, | |
1214 | X509_ATTRIBUTE_dup(sk_X509_ATTRIBUTE_value | |
1215 | (sk, i)))) | |
1216 | == NULL) | |
26a7d938 | 1217 | return 0; |
0f113f3e | 1218 | } |
208fb891 | 1219 | return 1; |
0f113f3e | 1220 | } |
dfeab068 | 1221 | |
6b691a5c | 1222 | int PKCS7_add_signed_attribute(PKCS7_SIGNER_INFO *p7si, int nid, int atrtype, |
0f113f3e MC |
1223 | void *value) |
1224 | { | |
26a7d938 | 1225 | return add_attribute(&(p7si->auth_attr), nid, atrtype, value); |
0f113f3e | 1226 | } |
dfeab068 | 1227 | |
6b691a5c | 1228 | int PKCS7_add_attribute(PKCS7_SIGNER_INFO *p7si, int nid, int atrtype, |
0f113f3e MC |
1229 | void *value) |
1230 | { | |
26a7d938 | 1231 | return add_attribute(&(p7si->unauth_attr), nid, atrtype, value); |
0f113f3e | 1232 | } |
dfeab068 | 1233 | |
b6436ff2 | 1234 | static int add_attribute(STACK_OF(X509_ATTRIBUTE) **sk, int nid, int atrtype, |
0f113f3e MC |
1235 | void *value) |
1236 | { | |
1237 | X509_ATTRIBUTE *attr = NULL; | |
1238 | ||
1239 | if (*sk == NULL) { | |
75ebbd9a | 1240 | if ((*sk = sk_X509_ATTRIBUTE_new_null()) == NULL) |
0f113f3e MC |
1241 | return 0; |
1242 | new_attrib: | |
75ebbd9a | 1243 | if ((attr = X509_ATTRIBUTE_create(nid, atrtype, value)) == NULL) |
0f113f3e MC |
1244 | return 0; |
1245 | if (!sk_X509_ATTRIBUTE_push(*sk, attr)) { | |
1246 | X509_ATTRIBUTE_free(attr); | |
1247 | return 0; | |
1248 | } | |
1249 | } else { | |
1250 | int i; | |
1251 | ||
1252 | for (i = 0; i < sk_X509_ATTRIBUTE_num(*sk); i++) { | |
1253 | attr = sk_X509_ATTRIBUTE_value(*sk, i); | |
9b0a4531 | 1254 | if (OBJ_obj2nid(X509_ATTRIBUTE_get0_object(attr)) == nid) { |
0f113f3e MC |
1255 | X509_ATTRIBUTE_free(attr); |
1256 | attr = X509_ATTRIBUTE_create(nid, atrtype, value); | |
1257 | if (attr == NULL) | |
1258 | return 0; | |
1259 | if (!sk_X509_ATTRIBUTE_set(*sk, i, attr)) { | |
1260 | X509_ATTRIBUTE_free(attr); | |
1261 | return 0; | |
1262 | } | |
1263 | goto end; | |
1264 | } | |
1265 | } | |
1266 | goto new_attrib; | |
1267 | } | |
1268 | end: | |
208fb891 | 1269 | return 1; |
0f113f3e | 1270 | } |