1 |
/* crypto/pkcs7/pk7_doit.c */ |
2 |
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) |
3 |
* All rights reserved. |
4 |
* |
5 |
* This package is an SSL implementation written |
6 |
* by Eric Young (eay@cryptsoft.com). |
7 |
* The implementation was written so as to conform with Netscapes SSL. |
8 |
* |
9 |
* This library is free for commercial and non-commercial use as long as |
10 |
* the following conditions are aheared to. The following conditions |
11 |
* apply to all code found in this distribution, be it the RC4, RSA, |
12 |
* lhash, DES, etc., code; not just the SSL code. The SSL documentation |
13 |
* included with this distribution is covered by the same copyright terms |
14 |
* except that the holder is Tim Hudson (tjh@cryptsoft.com). |
15 |
* |
16 |
* Copyright remains Eric Young's, and as such any Copyright notices in |
17 |
* the code are not to be removed. |
18 |
* If this package is used in a product, Eric Young should be given attribution |
19 |
* as the author of the parts of the library used. |
20 |
* This can be in the form of a textual message at program startup or |
21 |
* in documentation (online or textual) provided with the package. |
22 |
* |
23 |
* Redistribution and use in source and binary forms, with or without |
24 |
* modification, are permitted provided that the following conditions |
25 |
* are met: |
26 |
* 1. Redistributions of source code must retain the copyright |
27 |
* notice, this list of conditions and the following disclaimer. |
28 |
* 2. Redistributions in binary form must reproduce the above copyright |
29 |
* notice, this list of conditions and the following disclaimer in the |
30 |
* documentation and/or other materials provided with the distribution. |
31 |
* 3. All advertising materials mentioning features or use of this software |
32 |
* must display the following acknowledgement: |
33 |
* "This product includes cryptographic software written by |
34 |
* Eric Young (eay@cryptsoft.com)" |
35 |
* The word 'cryptographic' can be left out if the rouines from the library |
36 |
* being used are not cryptographic related :-). |
37 |
* 4. If you include any Windows specific code (or a derivative thereof) from |
38 |
* the apps directory (application code) you must include an acknowledgement: |
39 |
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" |
40 |
* |
41 |
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND |
42 |
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
43 |
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
44 |
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE |
45 |
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
46 |
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
47 |
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
48 |
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
49 |
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
50 |
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
51 |
* SUCH DAMAGE. |
52 |
* |
53 |
* The licence and distribution terms for any publically available version or |
54 |
* derivative of this code cannot be changed. i.e. this code cannot simply be |
55 |
* copied and put under another distribution licence |
56 |
* [including the GNU Public Licence.] |
57 |
*/ |
58 |
|
59 |
#include <stdio.h> |
60 |
#include "cryptlib.h" |
61 |
#include <openssl/rand.h> |
62 |
#include <openssl/objects.h> |
63 |
#include <openssl/x509.h> |
64 |
#include <openssl/x509v3.h> |
65 |
#include <openssl/err.h> |
66 |
|
67 |
static int add_attribute(STACK_OF(X509_ATTRIBUTE) **sk, int nid, int atrtype, |
68 |
void *value); |
69 |
static ASN1_TYPE *get_attribute(STACK_OF(X509_ATTRIBUTE) *sk, int nid); |
70 |
|
71 |
static int PKCS7_type_is_other(PKCS7 *p7) |
72 |
{ |
73 |
int isOther = 1; |
74 |
|
75 |
int nid = OBJ_obj2nid(p7->type); |
76 |
|
77 |
switch (nid) { |
78 |
case NID_pkcs7_data: |
79 |
case NID_pkcs7_signed: |
80 |
case NID_pkcs7_enveloped: |
81 |
case NID_pkcs7_signedAndEnveloped: |
82 |
case NID_pkcs7_digest: |
83 |
case NID_pkcs7_encrypted: |
84 |
isOther = 0; |
85 |
break; |
86 |
default: |
87 |
isOther = 1; |
88 |
} |
89 |
|
90 |
return isOther; |
91 |
|
92 |
} |
93 |
|
94 |
static ASN1_OCTET_STRING *PKCS7_get_octet_string(PKCS7 *p7) |
95 |
{ |
96 |
if (PKCS7_type_is_data(p7)) |
97 |
return p7->d.data; |
98 |
if (PKCS7_type_is_other(p7) && p7->d.other |
99 |
&& (p7->d.other->type == V_ASN1_OCTET_STRING)) |
100 |
return p7->d.other->value.octet_string; |
101 |
return NULL; |
102 |
} |
103 |
|
104 |
static int PKCS7_bio_add_digest(BIO **pbio, X509_ALGOR *alg) |
105 |
{ |
106 |
BIO *btmp; |
107 |
const EVP_MD *md; |
108 |
if ((btmp = BIO_new(BIO_f_md())) == NULL) { |
109 |
PKCS7err(PKCS7_F_PKCS7_BIO_ADD_DIGEST, ERR_R_BIO_LIB); |
110 |
goto err; |
111 |
} |
112 |
|
113 |
md = EVP_get_digestbyobj(alg->algorithm); |
114 |
if (md == NULL) { |
115 |
PKCS7err(PKCS7_F_PKCS7_BIO_ADD_DIGEST, PKCS7_R_UNKNOWN_DIGEST_TYPE); |
116 |
goto err; |
117 |
} |
118 |
|
119 |
BIO_set_md(btmp, md); |
120 |
if (*pbio == NULL) |
121 |
*pbio = btmp; |
122 |
else if (!BIO_push(*pbio, btmp)) { |
123 |
PKCS7err(PKCS7_F_PKCS7_BIO_ADD_DIGEST, ERR_R_BIO_LIB); |
124 |
goto err; |
125 |
} |
126 |
btmp = NULL; |
127 |
|
128 |
return 1; |
129 |
|
130 |
err: |
131 |
if (btmp) |
132 |
BIO_free(btmp); |
133 |
return 0; |
134 |
|
135 |
} |
136 |
|
137 |
BIO *PKCS7_dataInit(PKCS7 *p7, BIO *bio) |
138 |
{ |
139 |
int i; |
140 |
BIO *out = NULL, *btmp = NULL; |
141 |
X509_ALGOR *xa = NULL; |
142 |
const EVP_CIPHER *evp_cipher = NULL; |
143 |
STACK_OF(X509_ALGOR) *md_sk = NULL; |
144 |
STACK_OF(PKCS7_RECIP_INFO) *rsk = NULL; |
145 |
X509_ALGOR *xalg = NULL; |
146 |
PKCS7_RECIP_INFO *ri = NULL; |
147 |
EVP_PKEY *pkey; |
148 |
ASN1_OCTET_STRING *os = NULL; |
149 |
|
150 |
if (p7 == NULL) { |
151 |
PKCS7err(PKCS7_F_PKCS7_DATAINIT, PKCS7_R_INVALID_NULL_POINTER); |
152 |
return NULL; |
153 |
} |
154 |
/* |
155 |
* The content field in the PKCS7 ContentInfo is optional, but that really |
156 |
* only applies to inner content (precisely, detached signatures). |
157 |
* |
158 |
* When reading content, missing outer content is therefore treated as an |
159 |
* error. |
160 |
* |
161 |
* When creating content, PKCS7_content_new() must be called before |
162 |
* calling this method, so a NULL p7->d is always an error. |
163 |
*/ |
164 |
if (p7->d.ptr == NULL) { |
165 |
PKCS7err(PKCS7_F_PKCS7_DATAINIT, PKCS7_R_NO_CONTENT); |
166 |
return NULL; |
167 |
} |
168 |
|
169 |
i = OBJ_obj2nid(p7->type); |
170 |
p7->state = PKCS7_S_HEADER; |
171 |
|
172 |
switch (i) { |
173 |
case NID_pkcs7_signed: |
174 |
md_sk = p7->d.sign->md_algs; |
175 |
os = PKCS7_get_octet_string(p7->d.sign->contents); |
176 |
break; |
177 |
case NID_pkcs7_signedAndEnveloped: |
178 |
rsk = p7->d.signed_and_enveloped->recipientinfo; |
179 |
md_sk = p7->d.signed_and_enveloped->md_algs; |
180 |
xalg = p7->d.signed_and_enveloped->enc_data->algorithm; |
181 |
evp_cipher = p7->d.signed_and_enveloped->enc_data->cipher; |
182 |
if (evp_cipher == NULL) { |
183 |
PKCS7err(PKCS7_F_PKCS7_DATAINIT, PKCS7_R_CIPHER_NOT_INITIALIZED); |
184 |
goto err; |
185 |
} |
186 |
break; |
187 |
case NID_pkcs7_enveloped: |
188 |
rsk = p7->d.enveloped->recipientinfo; |
189 |
xalg = p7->d.enveloped->enc_data->algorithm; |
190 |
evp_cipher = p7->d.enveloped->enc_data->cipher; |
191 |
if (evp_cipher == NULL) { |
192 |
PKCS7err(PKCS7_F_PKCS7_DATAINIT, PKCS7_R_CIPHER_NOT_INITIALIZED); |
193 |
goto err; |
194 |
} |
195 |
break; |
196 |
case NID_pkcs7_digest: |
197 |
xa = p7->d.digest->md; |
198 |
os = PKCS7_get_octet_string(p7->d.digest->contents); |
199 |
break; |
200 |
default: |
201 |
PKCS7err(PKCS7_F_PKCS7_DATAINIT, PKCS7_R_UNSUPPORTED_CONTENT_TYPE); |
202 |
goto err; |
203 |
} |
204 |
|
205 |
for (i = 0; i < sk_X509_ALGOR_num(md_sk); i++) |
206 |
if (!PKCS7_bio_add_digest(&out, sk_X509_ALGOR_value(md_sk, i))) |
207 |
goto err; |
208 |
|
209 |
if (xa && !PKCS7_bio_add_digest(&out, xa)) |
210 |
goto err; |
211 |
|
212 |
if (evp_cipher != NULL) { |
213 |
unsigned char key[EVP_MAX_KEY_LENGTH]; |
214 |
unsigned char iv[EVP_MAX_IV_LENGTH]; |
215 |
int keylen, ivlen; |
216 |
int jj, max; |
217 |
unsigned char *tmp; |
218 |
EVP_CIPHER_CTX *ctx; |
219 |
|
220 |
if ((btmp = BIO_new(BIO_f_cipher())) == NULL) { |
221 |
PKCS7err(PKCS7_F_PKCS7_DATAINIT, ERR_R_BIO_LIB); |
222 |
goto err; |
223 |
} |
224 |
BIO_get_cipher_ctx(btmp, &ctx); |
225 |
keylen = EVP_CIPHER_key_length(evp_cipher); |
226 |
ivlen = EVP_CIPHER_iv_length(evp_cipher); |
227 |
xalg->algorithm = OBJ_nid2obj(EVP_CIPHER_type(evp_cipher)); |
228 |
if (ivlen > 0) |
229 |
if (RAND_pseudo_bytes(iv, ivlen) <= 0) |
230 |
goto err; |
231 |
if (EVP_CipherInit_ex(ctx, evp_cipher, NULL, NULL, NULL, 1) <= 0) |
232 |
goto err; |
233 |
if (EVP_CIPHER_CTX_rand_key(ctx, key) <= 0) |
234 |
goto err; |
235 |
if (EVP_CipherInit_ex(ctx, NULL, NULL, key, iv, 1) <= 0) |
236 |
goto err; |
237 |
|
238 |
if (ivlen > 0) { |
239 |
if (xalg->parameter == NULL) { |
240 |
xalg->parameter = ASN1_TYPE_new(); |
241 |
if (xalg->parameter == NULL) |
242 |
goto err; |
243 |
} |
244 |
if (EVP_CIPHER_param_to_asn1(ctx, xalg->parameter) < 0) |
245 |
goto err; |
246 |
} |
247 |
|
248 |
/* Lets do the pub key stuff :-) */ |
249 |
max = 0; |
250 |
for (i = 0; i < sk_PKCS7_RECIP_INFO_num(rsk); i++) { |
251 |
ri = sk_PKCS7_RECIP_INFO_value(rsk, i); |
252 |
if (ri->cert == NULL) { |
253 |
PKCS7err(PKCS7_F_PKCS7_DATAINIT, |
254 |
PKCS7_R_MISSING_CERIPEND_INFO); |
255 |
goto err; |
256 |
} |
257 |
if ((pkey = X509_get_pubkey(ri->cert)) == NULL) |
258 |
goto err; |
259 |
jj = EVP_PKEY_size(pkey); |
260 |
EVP_PKEY_free(pkey); |
261 |
if (max < jj) |
262 |
max = jj; |
263 |
} |
264 |
if ((tmp = (unsigned char *)OPENSSL_malloc(max)) == NULL) { |
265 |
PKCS7err(PKCS7_F_PKCS7_DATAINIT, ERR_R_MALLOC_FAILURE); |
266 |
goto err; |
267 |
} |
268 |
for (i = 0; i < sk_PKCS7_RECIP_INFO_num(rsk); i++) { |
269 |
ri = sk_PKCS7_RECIP_INFO_value(rsk, i); |
270 |
if ((pkey = X509_get_pubkey(ri->cert)) == NULL) |
271 |
goto err; |
272 |
jj = EVP_PKEY_encrypt(tmp, key, keylen, pkey); |
273 |
EVP_PKEY_free(pkey); |
274 |
if (jj <= 0) { |
275 |
PKCS7err(PKCS7_F_PKCS7_DATAINIT, ERR_R_EVP_LIB); |
276 |
OPENSSL_free(tmp); |
277 |
goto err; |
278 |
} |
279 |
if (!M_ASN1_OCTET_STRING_set(ri->enc_key, tmp, jj)) { |
280 |
PKCS7err(PKCS7_F_PKCS7_DATAINIT, ERR_R_MALLOC_FAILURE); |
281 |
OPENSSL_free(tmp); |
282 |
goto err; |
283 |
} |
284 |
} |
285 |
OPENSSL_free(tmp); |
286 |
OPENSSL_cleanse(key, keylen); |
287 |
|
288 |
if (out == NULL) |
289 |
out = btmp; |
290 |
else |
291 |
BIO_push(out, btmp); |
292 |
btmp = NULL; |
293 |
} |
294 |
|
295 |
if (bio == NULL) { |
296 |
if (PKCS7_is_detached(p7)) |
297 |
bio = BIO_new(BIO_s_null()); |
298 |
else if (os && os->length > 0) |
299 |
bio = BIO_new_mem_buf(os->data, os->length); |
300 |
if (bio == NULL) { |
301 |
bio = BIO_new(BIO_s_mem()); |
302 |
if (bio == NULL) |
303 |
goto err; |
304 |
BIO_set_mem_eof_return(bio, 0); |
305 |
} |
306 |
} |
307 |
BIO_push(out, bio); |
308 |
bio = NULL; |
309 |
if (0) { |
310 |
err: |
311 |
if (out != NULL) |
312 |
BIO_free_all(out); |
313 |
if (btmp != NULL) |
314 |
BIO_free_all(btmp); |
315 |
out = NULL; |
316 |
} |
317 |
return (out); |
318 |
} |
319 |
|
320 |
static int pkcs7_cmp_ri(PKCS7_RECIP_INFO *ri, X509 *pcert) |
321 |
{ |
322 |
int ret; |
323 |
ret = X509_NAME_cmp(ri->issuer_and_serial->issuer, |
324 |
pcert->cert_info->issuer); |
325 |
if (ret) |
326 |
return ret; |
327 |
return M_ASN1_INTEGER_cmp(pcert->cert_info->serialNumber, |
328 |
ri->issuer_and_serial->serial); |
329 |
} |
330 |
|
331 |
/* int */ |
332 |
BIO *PKCS7_dataDecode(PKCS7 *p7, EVP_PKEY *pkey, BIO *in_bio, X509 *pcert) |
333 |
{ |
334 |
int i, j; |
335 |
BIO *out = NULL, *btmp = NULL, *etmp = NULL, *bio = NULL; |
336 |
unsigned char *tmp = NULL; |
337 |
X509_ALGOR *xa; |
338 |
ASN1_OCTET_STRING *data_body = NULL; |
339 |
const EVP_MD *evp_md; |
340 |
const EVP_CIPHER *evp_cipher = NULL; |
341 |
EVP_CIPHER_CTX *evp_ctx = NULL; |
342 |
X509_ALGOR *enc_alg = NULL; |
343 |
STACK_OF(X509_ALGOR) *md_sk = NULL; |
344 |
STACK_OF(PKCS7_RECIP_INFO) *rsk = NULL; |
345 |
PKCS7_RECIP_INFO *ri = NULL; |
346 |
|
347 |
if (p7 == NULL) { |
348 |
PKCS7err(PKCS7_F_PKCS7_DATADECODE, PKCS7_R_INVALID_NULL_POINTER); |
349 |
return NULL; |
350 |
} |
351 |
|
352 |
if (p7->d.ptr == NULL) { |
353 |
PKCS7err(PKCS7_F_PKCS7_DATADECODE, PKCS7_R_NO_CONTENT); |
354 |
return NULL; |
355 |
} |
356 |
|
357 |
i = OBJ_obj2nid(p7->type); |
358 |
p7->state = PKCS7_S_HEADER; |
359 |
|
360 |
switch (i) { |
361 |
case NID_pkcs7_signed: |
362 |
/* |
363 |
* p7->d.sign->contents is a PKCS7 structure consisting of a contentType |
364 |
* field and optional content. |
365 |
* data_body is NULL if that structure has no (=detached) content |
366 |
* or if the contentType is wrong (i.e., not "data"). |
367 |
*/ |
368 |
data_body = PKCS7_get_octet_string(p7->d.sign->contents); |
369 |
md_sk = p7->d.sign->md_algs; |
370 |
break; |
371 |
case NID_pkcs7_signedAndEnveloped: |
372 |
rsk = p7->d.signed_and_enveloped->recipientinfo; |
373 |
md_sk = p7->d.signed_and_enveloped->md_algs; |
374 |
/* data_body is NULL if the optional EncryptedContent is missing. */ |
375 |
data_body = p7->d.signed_and_enveloped->enc_data->enc_data; |
376 |
enc_alg = p7->d.signed_and_enveloped->enc_data->algorithm; |
377 |
evp_cipher = EVP_get_cipherbyobj(enc_alg->algorithm); |
378 |
if (evp_cipher == NULL) { |
379 |
PKCS7err(PKCS7_F_PKCS7_DATADECODE, |
380 |
PKCS7_R_UNSUPPORTED_CIPHER_TYPE); |
381 |
goto err; |
382 |
} |
383 |
break; |
384 |
case NID_pkcs7_enveloped: |
385 |
rsk = p7->d.enveloped->recipientinfo; |
386 |
enc_alg = p7->d.enveloped->enc_data->algorithm; |
387 |
/* data_body is NULL if the optional EncryptedContent is missing. */ |
388 |
data_body = p7->d.enveloped->enc_data->enc_data; |
389 |
evp_cipher = EVP_get_cipherbyobj(enc_alg->algorithm); |
390 |
if (evp_cipher == NULL) { |
391 |
PKCS7err(PKCS7_F_PKCS7_DATADECODE, |
392 |
PKCS7_R_UNSUPPORTED_CIPHER_TYPE); |
393 |
goto err; |
394 |
} |
395 |
break; |
396 |
default: |
397 |
PKCS7err(PKCS7_F_PKCS7_DATADECODE, PKCS7_R_UNSUPPORTED_CONTENT_TYPE); |
398 |
goto err; |
399 |
} |
400 |
|
401 |
/* Detached content must be supplied via in_bio instead. */ |
402 |
if (data_body == NULL && in_bio == NULL) { |
403 |
PKCS7err(PKCS7_F_PKCS7_DATADECODE, PKCS7_R_NO_CONTENT); |
404 |
goto err; |
405 |
} |
406 |
|
407 |
/* We will be checking the signature */ |
408 |
if (md_sk != NULL) { |
409 |
for (i = 0; i < sk_X509_ALGOR_num(md_sk); i++) { |
410 |
xa = sk_X509_ALGOR_value(md_sk, i); |
411 |
if ((btmp = BIO_new(BIO_f_md())) == NULL) { |
412 |
PKCS7err(PKCS7_F_PKCS7_DATADECODE, ERR_R_BIO_LIB); |
413 |
goto err; |
414 |
} |
415 |
|
416 |
j = OBJ_obj2nid(xa->algorithm); |
417 |
evp_md = EVP_get_digestbynid(j); |
418 |
if (evp_md == NULL) { |
419 |
PKCS7err(PKCS7_F_PKCS7_DATADECODE, |
420 |
PKCS7_R_UNKNOWN_DIGEST_TYPE); |
421 |
goto err; |
422 |
} |
423 |
|
424 |
BIO_set_md(btmp, evp_md); |
425 |
if (out == NULL) |
426 |
out = btmp; |
427 |
else |
428 |
BIO_push(out, btmp); |
429 |
btmp = NULL; |
430 |
} |
431 |
} |
432 |
|
433 |
if (evp_cipher != NULL) { |
434 |
#if 0 |
435 |
unsigned char key[EVP_MAX_KEY_LENGTH]; |
436 |
unsigned char iv[EVP_MAX_IV_LENGTH]; |
437 |
unsigned char *p; |
438 |
int keylen, ivlen; |
439 |
int max; |
440 |
X509_OBJECT ret; |
441 |
#endif |
442 |
unsigned char *tkey = NULL; |
443 |
int tkeylen; |
444 |
int jj; |
445 |
|
446 |
if ((etmp = BIO_new(BIO_f_cipher())) == NULL) { |
447 |
PKCS7err(PKCS7_F_PKCS7_DATADECODE, ERR_R_BIO_LIB); |
448 |
goto err; |
449 |
} |
450 |
|
451 |
/* |
452 |
* It was encrypted, we need to decrypt the secret key with the |
453 |
* private key |
454 |
*/ |
455 |
|
456 |
/* |
457 |
* Find the recipientInfo which matches the passed certificate (if |
458 |
* any) |
459 |
*/ |
460 |
|
461 |
if (pcert) { |
462 |
for (i = 0; i < sk_PKCS7_RECIP_INFO_num(rsk); i++) { |
463 |
ri = sk_PKCS7_RECIP_INFO_value(rsk, i); |
464 |
if (!pkcs7_cmp_ri(ri, pcert)) |
465 |
break; |
466 |
ri = NULL; |
467 |
} |
468 |
if (ri == NULL) { |
469 |
PKCS7err(PKCS7_F_PKCS7_DATADECODE, |
470 |
PKCS7_R_NO_RECIPIENT_MATCHES_CERTIFICATE); |
471 |
goto err; |
472 |
} |
473 |
} |
474 |
|
475 |
jj = EVP_PKEY_size(pkey); |
476 |
tmp = (unsigned char *)OPENSSL_malloc(jj + 10); |
477 |
if (tmp == NULL) { |
478 |
PKCS7err(PKCS7_F_PKCS7_DATADECODE, ERR_R_MALLOC_FAILURE); |
479 |
goto err; |
480 |
} |
481 |
|
482 |
/* If we haven't got a certificate try each ri in turn */ |
483 |
|
484 |
if (pcert == NULL) { |
485 |
/* |
486 |
* Temporary storage in case EVP_PKEY_decrypt overwrites output |
487 |
* buffer on error. |
488 |
*/ |
489 |
unsigned char *tmp2; |
490 |
tmp2 = OPENSSL_malloc(jj); |
491 |
if (!tmp2) |
492 |
goto err; |
493 |
jj = -1; |
494 |
/* |
495 |
* Always attempt to decrypt all cases to avoid leaking timing |
496 |
* information about a successful decrypt. |
497 |
*/ |
498 |
for (i = 0; i < sk_PKCS7_RECIP_INFO_num(rsk); i++) { |
499 |
int tret; |
500 |
ri = sk_PKCS7_RECIP_INFO_value(rsk, i); |
501 |
tret = EVP_PKEY_decrypt(tmp2, |
502 |
M_ASN1_STRING_data(ri->enc_key), |
503 |
M_ASN1_STRING_length(ri->enc_key), |
504 |
pkey); |
505 |
if (tret > 0) { |
506 |
memcpy(tmp, tmp2, tret); |
507 |
OPENSSL_cleanse(tmp2, tret); |
508 |
jj = tret; |
509 |
} |
510 |
ERR_clear_error(); |
511 |
} |
512 |
OPENSSL_free(tmp2); |
513 |
} else { |
514 |
jj = EVP_PKEY_decrypt(tmp, |
515 |
M_ASN1_STRING_data(ri->enc_key), |
516 |
M_ASN1_STRING_length(ri->enc_key), pkey); |
517 |
ERR_clear_error(); |
518 |
} |
519 |
|
520 |
evp_ctx = NULL; |
521 |
BIO_get_cipher_ctx(etmp, &evp_ctx); |
522 |
if (EVP_CipherInit_ex(evp_ctx, evp_cipher, NULL, NULL, NULL, 0) <= 0) |
523 |
goto err; |
524 |
if (EVP_CIPHER_asn1_to_param(evp_ctx, enc_alg->parameter) < 0) |
525 |
goto err; |
526 |
/* Generate random key to counter MMA */ |
527 |
tkeylen = EVP_CIPHER_CTX_key_length(evp_ctx); |
528 |
tkey = OPENSSL_malloc(tkeylen); |
529 |
if (!tkey) |
530 |
goto err; |
531 |
if (EVP_CIPHER_CTX_rand_key(evp_ctx, tkey) <= 0) |
532 |
goto err; |
533 |
/* If we have no key use random key */ |
534 |
if (jj <= 0) { |
535 |
OPENSSL_free(tmp); |
536 |
jj = tkeylen; |
537 |
tmp = tkey; |
538 |
tkey = NULL; |
539 |
} |
540 |
|
541 |
if (jj != tkeylen) { |
542 |
/* |
543 |
* Some S/MIME clients don't use the same key and effective key |
544 |
* length. The key length is determined by the size of the |
545 |
* decrypted RSA key. |
546 |
*/ |
547 |
if (!EVP_CIPHER_CTX_set_key_length(evp_ctx, jj)) { |
548 |
/* As MMA defence use random key instead */ |
549 |
OPENSSL_cleanse(tmp, jj); |
550 |
OPENSSL_free(tmp); |
551 |
jj = tkeylen; |
552 |
tmp = tkey; |
553 |
tkey = NULL; |
554 |
} |
555 |
} |
556 |
ERR_clear_error(); |
557 |
if (EVP_CipherInit_ex(evp_ctx, NULL, NULL, tmp, NULL, 0) <= 0) |
558 |
goto err; |
559 |
|
560 |
OPENSSL_cleanse(tmp, jj); |
561 |
|
562 |
if (tkey) { |
563 |
OPENSSL_cleanse(tkey, tkeylen); |
564 |
OPENSSL_free(tkey); |
565 |
} |
566 |
|
567 |
if (out == NULL) |
568 |
out = etmp; |
569 |
else |
570 |
BIO_push(out, etmp); |
571 |
etmp = NULL; |
572 |
} |
573 |
#if 1 |
574 |
if (in_bio != NULL) { |
575 |
bio = in_bio; |
576 |
} else { |
577 |
# if 0 |
578 |
bio = BIO_new(BIO_s_mem()); |
579 |
/* |
580 |
* We need to set this so that when we have read all the data, the |
581 |
* encrypt BIO, if present, will read EOF and encode the last few |
582 |
* bytes |
583 |
*/ |
584 |
BIO_set_mem_eof_return(bio, 0); |
585 |
|
586 |
if (data_body->length > 0) |
587 |
BIO_write(bio, (char *)data_body->data, data_body->length); |
588 |
# else |
589 |
if (data_body->length > 0) |
590 |
bio = BIO_new_mem_buf(data_body->data, data_body->length); |
591 |
else { |
592 |
bio = BIO_new(BIO_s_mem()); |
593 |
BIO_set_mem_eof_return(bio, 0); |
594 |
} |
595 |
if (bio == NULL) |
596 |
goto err; |
597 |
# endif |
598 |
} |
599 |
BIO_push(out, bio); |
600 |
bio = NULL; |
601 |
#endif |
602 |
if (0) { |
603 |
err: |
604 |
if (out != NULL) |
605 |
BIO_free_all(out); |
606 |
if (btmp != NULL) |
607 |
BIO_free_all(btmp); |
608 |
if (etmp != NULL) |
609 |
BIO_free_all(etmp); |
610 |
if (bio != NULL) |
611 |
BIO_free_all(bio); |
612 |
out = NULL; |
613 |
} |
614 |
if (tmp != NULL) |
615 |
OPENSSL_free(tmp); |
616 |
return (out); |
617 |
} |
618 |
|
619 |
static BIO *PKCS7_find_digest(EVP_MD_CTX **pmd, BIO *bio, int nid) |
620 |
{ |
621 |
for (;;) { |
622 |
bio = BIO_find_type(bio, BIO_TYPE_MD); |
623 |
if (bio == NULL) { |
624 |
PKCS7err(PKCS7_F_PKCS7_FIND_DIGEST, |
625 |
PKCS7_R_UNABLE_TO_FIND_MESSAGE_DIGEST); |
626 |
return NULL; |
627 |
} |
628 |
BIO_get_md_ctx(bio, pmd); |
629 |
if (*pmd == NULL) { |
630 |
PKCS7err(PKCS7_F_PKCS7_FIND_DIGEST, ERR_R_INTERNAL_ERROR); |
631 |
return NULL; |
632 |
} |
633 |
if (EVP_MD_CTX_type(*pmd) == nid) |
634 |
return bio; |
635 |
bio = BIO_next(bio); |
636 |
} |
637 |
return NULL; |
638 |
} |
639 |
|
640 |
int PKCS7_dataFinal(PKCS7 *p7, BIO *bio) |
641 |
{ |
642 |
int ret = 0; |
643 |
int i, j; |
644 |
BIO *btmp; |
645 |
BUF_MEM *buf_mem = NULL; |
646 |
BUF_MEM *buf = NULL; |
647 |
PKCS7_SIGNER_INFO *si; |
648 |
EVP_MD_CTX *mdc, ctx_tmp; |
649 |
STACK_OF(X509_ATTRIBUTE) *sk; |
650 |
STACK_OF(PKCS7_SIGNER_INFO) *si_sk = NULL; |
651 |
ASN1_OCTET_STRING *os = NULL; |
652 |
|
653 |
if (p7 == NULL) { |
654 |
PKCS7err(PKCS7_F_PKCS7_DATAFINAL, PKCS7_R_INVALID_NULL_POINTER); |
655 |
return 0; |
656 |
} |
657 |
|
658 |
if (p7->d.ptr == NULL) { |
659 |
PKCS7err(PKCS7_F_PKCS7_DATAFINAL, PKCS7_R_NO_CONTENT); |
660 |
return 0; |
661 |
} |
662 |
|
663 |
EVP_MD_CTX_init(&ctx_tmp); |
664 |
i = OBJ_obj2nid(p7->type); |
665 |
p7->state = PKCS7_S_HEADER; |
666 |
|
667 |
switch (i) { |
668 |
case NID_pkcs7_signedAndEnveloped: |
669 |
/* XXXXXXXXXXXXXXXX */ |
670 |
si_sk = p7->d.signed_and_enveloped->signer_info; |
671 |
if (!(os = M_ASN1_OCTET_STRING_new())) { |
672 |
PKCS7err(PKCS7_F_PKCS7_DATAFINAL, ERR_R_MALLOC_FAILURE); |
673 |
goto err; |
674 |
} |
675 |
p7->d.signed_and_enveloped->enc_data->enc_data = os; |
676 |
break; |
677 |
case NID_pkcs7_enveloped: |
678 |
/* XXXXXXXXXXXXXXXX */ |
679 |
if (!(os = M_ASN1_OCTET_STRING_new())) { |
680 |
PKCS7err(PKCS7_F_PKCS7_DATAFINAL, ERR_R_MALLOC_FAILURE); |
681 |
goto err; |
682 |
} |
683 |
p7->d.enveloped->enc_data->enc_data = os; |
684 |
break; |
685 |
case NID_pkcs7_signed: |
686 |
si_sk = p7->d.sign->signer_info; |
687 |
os = PKCS7_get_octet_string(p7->d.sign->contents); |
688 |
/* If detached data then the content is excluded */ |
689 |
if (PKCS7_type_is_data(p7->d.sign->contents) && p7->detached) { |
690 |
M_ASN1_OCTET_STRING_free(os); |
691 |
os = NULL; |
692 |
p7->d.sign->contents->d.data = NULL; |
693 |
} |
694 |
break; |
695 |
|
696 |
case NID_pkcs7_digest: |
697 |
os = PKCS7_get_octet_string(p7->d.digest->contents); |
698 |
/* If detached data then the content is excluded */ |
699 |
if (PKCS7_type_is_data(p7->d.digest->contents) && p7->detached) { |
700 |
M_ASN1_OCTET_STRING_free(os); |
701 |
os = NULL; |
702 |
p7->d.digest->contents->d.data = NULL; |
703 |
} |
704 |
break; |
705 |
|
706 |
} |
707 |
|
708 |
if (si_sk != NULL) { |
709 |
if ((buf = BUF_MEM_new()) == NULL) { |
710 |
PKCS7err(PKCS7_F_PKCS7_DATAFINAL, ERR_R_BIO_LIB); |
711 |
goto err; |
712 |
} |
713 |
for (i = 0; i < sk_PKCS7_SIGNER_INFO_num(si_sk); i++) { |
714 |
si = sk_PKCS7_SIGNER_INFO_value(si_sk, i); |
715 |
if (si->pkey == NULL) |
716 |
continue; |
717 |
|
718 |
j = OBJ_obj2nid(si->digest_alg->algorithm); |
719 |
|
720 |
btmp = bio; |
721 |
|
722 |
btmp = PKCS7_find_digest(&mdc, btmp, j); |
723 |
|
724 |
if (btmp == NULL) |
725 |
goto err; |
726 |
|
727 |
/* |
728 |
* We now have the EVP_MD_CTX, lets do the signing. |
729 |
*/ |
730 |
EVP_MD_CTX_copy_ex(&ctx_tmp, mdc); |
731 |
if (!BUF_MEM_grow_clean(buf, EVP_PKEY_size(si->pkey))) { |
732 |
PKCS7err(PKCS7_F_PKCS7_DATAFINAL, ERR_R_BIO_LIB); |
733 |
goto err; |
734 |
} |
735 |
|
736 |
sk = si->auth_attr; |
737 |
|
738 |
/* |
739 |
* If there are attributes, we add the digest attribute and only |
740 |
* sign the attributes |
741 |
*/ |
742 |
if ((sk != NULL) && (sk_X509_ATTRIBUTE_num(sk) != 0)) { |
743 |
unsigned char md_data[EVP_MAX_MD_SIZE], *abuf = NULL; |
744 |
unsigned int md_len, alen; |
745 |
ASN1_OCTET_STRING *digest; |
746 |
ASN1_UTCTIME *sign_time; |
747 |
const EVP_MD *md_tmp; |
748 |
|
749 |
/* Add signing time if not already present */ |
750 |
if (!PKCS7_get_signed_attribute(si, NID_pkcs9_signingTime)) { |
751 |
if (!(sign_time = X509_gmtime_adj(NULL, 0))) { |
752 |
PKCS7err(PKCS7_F_PKCS7_DATAFINAL, |
753 |
ERR_R_MALLOC_FAILURE); |
754 |
goto err; |
755 |
} |
756 |
if (!PKCS7_add_signed_attribute(si, |
757 |
NID_pkcs9_signingTime, |
758 |
V_ASN1_UTCTIME, |
759 |
sign_time)) { |
760 |
M_ASN1_UTCTIME_free(sign_time); |
761 |
goto err; |
762 |
} |
763 |
} |
764 |
|
765 |
/* Add digest */ |
766 |
md_tmp = EVP_MD_CTX_md(&ctx_tmp); |
767 |
EVP_DigestFinal_ex(&ctx_tmp, md_data, &md_len); |
768 |
if (!(digest = M_ASN1_OCTET_STRING_new())) { |
769 |
PKCS7err(PKCS7_F_PKCS7_DATAFINAL, ERR_R_MALLOC_FAILURE); |
770 |
goto err; |
771 |
} |
772 |
if (!M_ASN1_OCTET_STRING_set(digest, md_data, md_len)) { |
773 |
PKCS7err(PKCS7_F_PKCS7_DATAFINAL, ERR_R_MALLOC_FAILURE); |
774 |
M_ASN1_OCTET_STRING_free(digest); |
775 |
goto err; |
776 |
} |
777 |
if (!PKCS7_add_signed_attribute(si, |
778 |
NID_pkcs9_messageDigest, |
779 |
V_ASN1_OCTET_STRING, digest)) |
780 |
{ |
781 |
M_ASN1_OCTET_STRING_free(digest); |
782 |
goto err; |
783 |
} |
784 |
|
785 |
/* Now sign the attributes */ |
786 |
EVP_SignInit_ex(&ctx_tmp, md_tmp, NULL); |
787 |
alen = ASN1_item_i2d((ASN1_VALUE *)sk, &abuf, |
788 |
ASN1_ITEM_rptr(PKCS7_ATTR_SIGN)); |
789 |
if (!abuf) |
790 |
goto err; |
791 |
EVP_SignUpdate(&ctx_tmp, abuf, alen); |
792 |
OPENSSL_free(abuf); |
793 |
} |
794 |
#ifndef OPENSSL_NO_DSA |
795 |
if (si->pkey->type == EVP_PKEY_DSA) |
796 |
ctx_tmp.digest = EVP_dss1(); |
797 |
#endif |
798 |
#ifndef OPENSSL_NO_ECDSA |
799 |
if (si->pkey->type == EVP_PKEY_EC) |
800 |
ctx_tmp.digest = EVP_ecdsa(); |
801 |
#endif |
802 |
|
803 |
if (!EVP_SignFinal(&ctx_tmp, (unsigned char *)buf->data, |
804 |
(unsigned int *)&buf->length, si->pkey)) { |
805 |
PKCS7err(PKCS7_F_PKCS7_DATAFINAL, ERR_R_EVP_LIB); |
806 |
goto err; |
807 |
} |
808 |
if (!ASN1_STRING_set(si->enc_digest, |
809 |
(unsigned char *)buf->data, buf->length)) { |
810 |
PKCS7err(PKCS7_F_PKCS7_DATAFINAL, ERR_R_ASN1_LIB); |
811 |
goto err; |
812 |
} |
813 |
} |
814 |
} else if (i == NID_pkcs7_digest) { |
815 |
unsigned char md_data[EVP_MAX_MD_SIZE]; |
816 |
unsigned int md_len; |
817 |
if (!PKCS7_find_digest(&mdc, bio, |
818 |
OBJ_obj2nid(p7->d.digest->md->algorithm))) |
819 |
goto err; |
820 |
EVP_DigestFinal_ex(mdc, md_data, &md_len); |
821 |
M_ASN1_OCTET_STRING_set(p7->d.digest->digest, md_data, md_len); |
822 |
} |
823 |
|
824 |
if (!PKCS7_is_detached(p7)) { |
825 |
/* |
826 |
* NOTE(emilia): I think we only reach os == NULL here because detached |
827 |
* digested data support is broken. |
828 |
*/ |
829 |
if (os == NULL) |
830 |
goto err; |
831 |
btmp = BIO_find_type(bio, BIO_TYPE_MEM); |
832 |
if (btmp == NULL) { |
833 |
PKCS7err(PKCS7_F_PKCS7_DATAFINAL, PKCS7_R_UNABLE_TO_FIND_MEM_BIO); |
834 |
goto err; |
835 |
} |
836 |
BIO_get_mem_ptr(btmp, &buf_mem); |
837 |
/* |
838 |
* Mark the BIO read only then we can use its copy of the data |
839 |
* instead of making an extra copy. |
840 |
*/ |
841 |
BIO_set_flags(btmp, BIO_FLAGS_MEM_RDONLY); |
842 |
BIO_set_mem_eof_return(btmp, 0); |
843 |
os->data = (unsigned char *)buf_mem->data; |
844 |
os->length = buf_mem->length; |
845 |
#if 0 |
846 |
M_ASN1_OCTET_STRING_set(os, |
847 |
(unsigned char *)buf_mem->data, |
848 |
buf_mem->length); |
849 |
#endif |
850 |
} |
851 |
ret = 1; |
852 |
err: |
853 |
EVP_MD_CTX_cleanup(&ctx_tmp); |
854 |
if (buf != NULL) |
855 |
BUF_MEM_free(buf); |
856 |
return (ret); |
857 |
} |
858 |
|
859 |
int PKCS7_dataVerify(X509_STORE *cert_store, X509_STORE_CTX *ctx, BIO *bio, |
860 |
PKCS7 *p7, PKCS7_SIGNER_INFO *si) |
861 |
{ |
862 |
PKCS7_ISSUER_AND_SERIAL *ias; |
863 |
int ret = 0, i; |
864 |
STACK_OF(X509) *cert; |
865 |
X509 *x509; |
866 |
|
867 |
if (p7 == NULL) { |
868 |
PKCS7err(PKCS7_F_PKCS7_DATAVERIFY, PKCS7_R_INVALID_NULL_POINTER); |
869 |
return 0; |
870 |
} |
871 |
|
872 |
if (p7->d.ptr == NULL) { |
873 |
PKCS7err(PKCS7_F_PKCS7_DATAVERIFY, PKCS7_R_NO_CONTENT); |
874 |
return 0; |
875 |
} |
876 |
|
877 |
if (PKCS7_type_is_signed(p7)) { |
878 |
cert = p7->d.sign->cert; |
879 |
} else if (PKCS7_type_is_signedAndEnveloped(p7)) { |
880 |
cert = p7->d.signed_and_enveloped->cert; |
881 |
} else { |
882 |
PKCS7err(PKCS7_F_PKCS7_DATAVERIFY, PKCS7_R_WRONG_PKCS7_TYPE); |
883 |
goto err; |
884 |
} |
885 |
/* XXXXXXXXXXXXXXXXXXXXXXX */ |
886 |
ias = si->issuer_and_serial; |
887 |
|
888 |
x509 = X509_find_by_issuer_and_serial(cert, ias->issuer, ias->serial); |
889 |
|
890 |
/* were we able to find the cert in passed to us */ |
891 |
if (x509 == NULL) { |
892 |
PKCS7err(PKCS7_F_PKCS7_DATAVERIFY, |
893 |
PKCS7_R_UNABLE_TO_FIND_CERTIFICATE); |
894 |
goto err; |
895 |
} |
896 |
|
897 |
/* Lets verify */ |
898 |
if (!X509_STORE_CTX_init(ctx, cert_store, x509, cert)) { |
899 |
PKCS7err(PKCS7_F_PKCS7_DATAVERIFY, ERR_R_X509_LIB); |
900 |
goto err; |
901 |
} |
902 |
X509_STORE_CTX_set_purpose(ctx, X509_PURPOSE_SMIME_SIGN); |
903 |
i = X509_verify_cert(ctx); |
904 |
if (i <= 0) { |
905 |
PKCS7err(PKCS7_F_PKCS7_DATAVERIFY, ERR_R_X509_LIB); |
906 |
X509_STORE_CTX_cleanup(ctx); |
907 |
goto err; |
908 |
} |
909 |
X509_STORE_CTX_cleanup(ctx); |
910 |
|
911 |
return PKCS7_signatureVerify(bio, p7, si, x509); |
912 |
err: |
913 |
return ret; |
914 |
} |
915 |
|
916 |
int PKCS7_signatureVerify(BIO *bio, PKCS7 *p7, PKCS7_SIGNER_INFO *si, |
917 |
X509 *x509) |
918 |
{ |
919 |
ASN1_OCTET_STRING *os; |
920 |
EVP_MD_CTX mdc_tmp, *mdc; |
921 |
int ret = 0, i; |
922 |
int md_type; |
923 |
STACK_OF(X509_ATTRIBUTE) *sk; |
924 |
BIO *btmp; |
925 |
EVP_PKEY *pkey; |
926 |
|
927 |
EVP_MD_CTX_init(&mdc_tmp); |
928 |
|
929 |
if (!PKCS7_type_is_signed(p7) && !PKCS7_type_is_signedAndEnveloped(p7)) { |
930 |
PKCS7err(PKCS7_F_PKCS7_SIGNATUREVERIFY, PKCS7_R_WRONG_PKCS7_TYPE); |
931 |
goto err; |
932 |
} |
933 |
|
934 |
md_type = OBJ_obj2nid(si->digest_alg->algorithm); |
935 |
|
936 |
btmp = bio; |
937 |
for (;;) { |
938 |
if ((btmp == NULL) || |
939 |
((btmp = BIO_find_type(btmp, BIO_TYPE_MD)) == NULL)) { |
940 |
PKCS7err(PKCS7_F_PKCS7_SIGNATUREVERIFY, |
941 |
PKCS7_R_UNABLE_TO_FIND_MESSAGE_DIGEST); |
942 |
goto err; |
943 |
} |
944 |
BIO_get_md_ctx(btmp, &mdc); |
945 |
if (mdc == NULL) { |
946 |
PKCS7err(PKCS7_F_PKCS7_SIGNATUREVERIFY, ERR_R_INTERNAL_ERROR); |
947 |
goto err; |
948 |
} |
949 |
if (EVP_MD_CTX_type(mdc) == md_type) |
950 |
break; |
951 |
/* |
952 |
* Workaround for some broken clients that put the signature OID |
953 |
* instead of the digest OID in digest_alg->algorithm |
954 |
*/ |
955 |
if (EVP_MD_pkey_type(EVP_MD_CTX_md(mdc)) == md_type) |
956 |
break; |
957 |
btmp = BIO_next(btmp); |
958 |
} |
959 |
|
960 |
/* |
961 |
* mdc is the digest ctx that we want, unless there are attributes, in |
962 |
* which case the digest is the signed attributes |
963 |
*/ |
964 |
EVP_MD_CTX_copy_ex(&mdc_tmp, mdc); |
965 |
|
966 |
sk = si->auth_attr; |
967 |
if ((sk != NULL) && (sk_X509_ATTRIBUTE_num(sk) != 0)) { |
968 |
unsigned char md_dat[EVP_MAX_MD_SIZE], *abuf = NULL; |
969 |
unsigned int md_len, alen; |
970 |
ASN1_OCTET_STRING *message_digest; |
971 |
|
972 |
EVP_DigestFinal_ex(&mdc_tmp, md_dat, &md_len); |
973 |
message_digest = PKCS7_digest_from_attributes(sk); |
974 |
if (!message_digest) { |
975 |
PKCS7err(PKCS7_F_PKCS7_SIGNATUREVERIFY, |
976 |
PKCS7_R_UNABLE_TO_FIND_MESSAGE_DIGEST); |
977 |
goto err; |
978 |
} |
979 |
if ((message_digest->length != (int)md_len) || |
980 |
(memcmp(message_digest->data, md_dat, md_len))) { |
981 |
#if 0 |
982 |
{ |
983 |
int ii; |
984 |
for (ii = 0; ii < message_digest->length; ii++) |
985 |
printf("%02X", message_digest->data[ii]); |
986 |
printf(" sent\n"); |
987 |
for (ii = 0; ii < md_len; ii++) |
988 |
printf("%02X", md_dat[ii]); |
989 |
printf(" calc\n"); |
990 |
} |
991 |
#endif |
992 |
PKCS7err(PKCS7_F_PKCS7_SIGNATUREVERIFY, PKCS7_R_DIGEST_FAILURE); |
993 |
ret = -1; |
994 |
goto err; |
995 |
} |
996 |
|
997 |
EVP_VerifyInit_ex(&mdc_tmp, EVP_get_digestbynid(md_type), NULL); |
998 |
|
999 |
alen = ASN1_item_i2d((ASN1_VALUE *)sk, &abuf, |
1000 |
ASN1_ITEM_rptr(PKCS7_ATTR_VERIFY)); |
1001 |
EVP_VerifyUpdate(&mdc_tmp, abuf, alen); |
1002 |
|
1003 |
OPENSSL_free(abuf); |
1004 |
} |
1005 |
|
1006 |
os = si->enc_digest; |
1007 |
pkey = X509_get_pubkey(x509); |
1008 |
if (!pkey) { |
1009 |
ret = -1; |
1010 |
goto err; |
1011 |
} |
1012 |
#ifndef OPENSSL_NO_DSA |
1013 |
if (pkey->type == EVP_PKEY_DSA) |
1014 |
mdc_tmp.digest = EVP_dss1(); |
1015 |
#endif |
1016 |
#ifndef OPENSSL_NO_ECDSA |
1017 |
if (pkey->type == EVP_PKEY_EC) |
1018 |
mdc_tmp.digest = EVP_ecdsa(); |
1019 |
#endif |
1020 |
|
1021 |
i = EVP_VerifyFinal(&mdc_tmp, os->data, os->length, pkey); |
1022 |
EVP_PKEY_free(pkey); |
1023 |
if (i <= 0) { |
1024 |
PKCS7err(PKCS7_F_PKCS7_SIGNATUREVERIFY, PKCS7_R_SIGNATURE_FAILURE); |
1025 |
ret = -1; |
1026 |
goto err; |
1027 |
} else |
1028 |
ret = 1; |
1029 |
err: |
1030 |
EVP_MD_CTX_cleanup(&mdc_tmp); |
1031 |
return (ret); |
1032 |
} |
1033 |
|
1034 |
PKCS7_ISSUER_AND_SERIAL *PKCS7_get_issuer_and_serial(PKCS7 *p7, int idx) |
1035 |
{ |
1036 |
STACK_OF(PKCS7_RECIP_INFO) *rsk; |
1037 |
PKCS7_RECIP_INFO *ri; |
1038 |
int i; |
1039 |
|
1040 |
i = OBJ_obj2nid(p7->type); |
1041 |
if (i != NID_pkcs7_signedAndEnveloped) |
1042 |
return NULL; |
1043 |
if (p7->d.signed_and_enveloped == NULL) |
1044 |
return NULL; |
1045 |
rsk = p7->d.signed_and_enveloped->recipientinfo; |
1046 |
if (rsk == NULL) |
1047 |
return NULL; |
1048 |
ri = sk_PKCS7_RECIP_INFO_value(rsk, 0); |
1049 |
if (sk_PKCS7_RECIP_INFO_num(rsk) <= idx) |
1050 |
return (NULL); |
1051 |
ri = sk_PKCS7_RECIP_INFO_value(rsk, idx); |
1052 |
return (ri->issuer_and_serial); |
1053 |
} |
1054 |
|
1055 |
ASN1_TYPE *PKCS7_get_signed_attribute(PKCS7_SIGNER_INFO *si, int nid) |
1056 |
{ |
1057 |
return (get_attribute(si->auth_attr, nid)); |
1058 |
} |
1059 |
|
1060 |
ASN1_TYPE *PKCS7_get_attribute(PKCS7_SIGNER_INFO *si, int nid) |
1061 |
{ |
1062 |
return (get_attribute(si->unauth_attr, nid)); |
1063 |
} |
1064 |
|
1065 |
static ASN1_TYPE *get_attribute(STACK_OF(X509_ATTRIBUTE) *sk, int nid) |
1066 |
{ |
1067 |
int i; |
1068 |
X509_ATTRIBUTE *xa; |
1069 |
ASN1_OBJECT *o; |
1070 |
|
1071 |
o = OBJ_nid2obj(nid); |
1072 |
if (!o || !sk) |
1073 |
return (NULL); |
1074 |
for (i = 0; i < sk_X509_ATTRIBUTE_num(sk); i++) { |
1075 |
xa = sk_X509_ATTRIBUTE_value(sk, i); |
1076 |
if (OBJ_cmp(xa->object, o) == 0) { |
1077 |
if (!xa->single && sk_ASN1_TYPE_num(xa->value.set)) |
1078 |
return (sk_ASN1_TYPE_value(xa->value.set, 0)); |
1079 |
else |
1080 |
return (NULL); |
1081 |
} |
1082 |
} |
1083 |
return (NULL); |
1084 |
} |
1085 |
|
1086 |
ASN1_OCTET_STRING *PKCS7_digest_from_attributes(STACK_OF(X509_ATTRIBUTE) *sk) |
1087 |
{ |
1088 |
ASN1_TYPE *astype; |
1089 |
if (!(astype = get_attribute(sk, NID_pkcs9_messageDigest))) |
1090 |
return NULL; |
1091 |
return astype->value.octet_string; |
1092 |
} |
1093 |
|
1094 |
int PKCS7_set_signed_attributes(PKCS7_SIGNER_INFO *p7si, |
1095 |
STACK_OF(X509_ATTRIBUTE) *sk) |
1096 |
{ |
1097 |
int i; |
1098 |
|
1099 |
if (p7si->auth_attr != NULL) |
1100 |
sk_X509_ATTRIBUTE_pop_free(p7si->auth_attr, X509_ATTRIBUTE_free); |
1101 |
p7si->auth_attr = sk_X509_ATTRIBUTE_dup(sk); |
1102 |
if (p7si->auth_attr == NULL) |
1103 |
return 0; |
1104 |
for (i = 0; i < sk_X509_ATTRIBUTE_num(sk); i++) { |
1105 |
if ((sk_X509_ATTRIBUTE_set(p7si->auth_attr, i, |
1106 |
X509_ATTRIBUTE_dup(sk_X509_ATTRIBUTE_value |
1107 |
(sk, i)))) |
1108 |
== NULL) |
1109 |
return (0); |
1110 |
} |
1111 |
return (1); |
1112 |
} |
1113 |
|
1114 |
int PKCS7_set_attributes(PKCS7_SIGNER_INFO *p7si, |
1115 |
STACK_OF(X509_ATTRIBUTE) *sk) |
1116 |
{ |
1117 |
int i; |
1118 |
|
1119 |
if (p7si->unauth_attr != NULL) |
1120 |
sk_X509_ATTRIBUTE_pop_free(p7si->unauth_attr, X509_ATTRIBUTE_free); |
1121 |
p7si->unauth_attr = sk_X509_ATTRIBUTE_dup(sk); |
1122 |
if (p7si->unauth_attr == NULL) |
1123 |
return 0; |
1124 |
for (i = 0; i < sk_X509_ATTRIBUTE_num(sk); i++) { |
1125 |
if ((sk_X509_ATTRIBUTE_set(p7si->unauth_attr, i, |
1126 |
X509_ATTRIBUTE_dup(sk_X509_ATTRIBUTE_value |
1127 |
(sk, i)))) |
1128 |
== NULL) |
1129 |
return (0); |
1130 |
} |
1131 |
return (1); |
1132 |
} |
1133 |
|
1134 |
int PKCS7_add_signed_attribute(PKCS7_SIGNER_INFO *p7si, int nid, int atrtype, |
1135 |
void *value) |
1136 |
{ |
1137 |
return (add_attribute(&(p7si->auth_attr), nid, atrtype, value)); |
1138 |
} |
1139 |
|
1140 |
int PKCS7_add_attribute(PKCS7_SIGNER_INFO *p7si, int nid, int atrtype, |
1141 |
void *value) |
1142 |
{ |
1143 |
return (add_attribute(&(p7si->unauth_attr), nid, atrtype, value)); |
1144 |
} |
1145 |
|
1146 |
static int add_attribute(STACK_OF(X509_ATTRIBUTE) **sk, int nid, int atrtype, |
1147 |
void *value) |
1148 |
{ |
1149 |
X509_ATTRIBUTE *attr = NULL; |
1150 |
|
1151 |
if (*sk == NULL) { |
1152 |
if (!(*sk = sk_X509_ATTRIBUTE_new_null())) |
1153 |
return 0; |
1154 |
new_attrib: |
1155 |
if (!(attr = X509_ATTRIBUTE_create(nid, atrtype, value))) |
1156 |
return 0; |
1157 |
if (!sk_X509_ATTRIBUTE_push(*sk, attr)) { |
1158 |
X509_ATTRIBUTE_free(attr); |
1159 |
return 0; |
1160 |
} |
1161 |
} else { |
1162 |
int i; |
1163 |
|
1164 |
for (i = 0; i < sk_X509_ATTRIBUTE_num(*sk); i++) { |
1165 |
attr = sk_X509_ATTRIBUTE_value(*sk, i); |
1166 |
if (OBJ_obj2nid(attr->object) == nid) { |
1167 |
X509_ATTRIBUTE_free(attr); |
1168 |
attr = X509_ATTRIBUTE_create(nid, atrtype, value); |
1169 |
if (attr == NULL) |
1170 |
return 0; |
1171 |
if (!sk_X509_ATTRIBUTE_set(*sk, i, attr)) { |
1172 |
X509_ATTRIBUTE_free(attr); |
1173 |
return 0; |
1174 |
} |
1175 |
goto end; |
1176 |
} |
1177 |
} |
1178 |
goto new_attrib; |
1179 |
} |
1180 |
end: |
1181 |
return (1); |
1182 |
} |