Constify d2i, s2i, c2i and r2i functions and other associated
[openssl.git] / crypto / pkcs7 / pk7_doit.c
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
66 static int add_attribute(STACK_OF(X509_ATTRIBUTE) **sk, int nid, int atrtype,
67                          void *value);
68 static ASN1_TYPE *get_attribute(STACK_OF(X509_ATTRIBUTE) *sk, int nid);
69
70 static int PKCS7_type_is_other(PKCS7* p7)
71         {
72         int isOther=1;
73         
74         int nid=OBJ_obj2nid(p7->type);
75
76         switch( nid )
77                 {
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                 {
110                 PKCS7err(PKCS7_F_PKCS7_BIO_ADD_DIGEST,ERR_R_BIO_LIB);
111                 goto err;
112                 }
113
114         md=EVP_get_digestbyobj(alg->algorithm);
115         if (md == NULL)
116                 {
117                 PKCS7err(PKCS7_F_PKCS7_BIO_ADD_DIGEST,PKCS7_R_UNKNOWN_DIGEST_TYPE);
118                 goto err;
119                 }
120
121         BIO_set_md(btmp,md);
122         if (*pbio == NULL)
123                 *pbio=btmp;
124         else if (!BIO_push(*pbio,btmp))
125                 {
126                 PKCS7err(PKCS7_F_PKCS7_BIO_ADD_DIGEST,ERR_R_BIO_LIB);
127                 goto err;
128                 }
129         btmp=NULL;
130
131         return 1;
132
133         err:
134         if (btmp)
135                 BIO_free(btmp);
136         return 0;
137
138         }
139
140 BIO *PKCS7_dataInit(PKCS7 *p7, BIO *bio)
141         {
142         int i;
143         BIO *out=NULL,*btmp=NULL;
144         X509_ALGOR *xa = NULL;
145         const EVP_CIPHER *evp_cipher=NULL;
146         STACK_OF(X509_ALGOR) *md_sk=NULL;
147         STACK_OF(PKCS7_RECIP_INFO) *rsk=NULL;
148         X509_ALGOR *xalg=NULL;
149         PKCS7_RECIP_INFO *ri=NULL;
150         EVP_PKEY *pkey;
151         ASN1_OCTET_STRING *os=NULL;
152
153         i=OBJ_obj2nid(p7->type);
154         p7->state=PKCS7_S_HEADER;
155
156         switch (i)
157                 {
158         case NID_pkcs7_signed:
159                 md_sk=p7->d.sign->md_algs;
160                 os = PKCS7_get_octet_string(p7->d.sign->contents);
161                 break;
162         case NID_pkcs7_signedAndEnveloped:
163                 rsk=p7->d.signed_and_enveloped->recipientinfo;
164                 md_sk=p7->d.signed_and_enveloped->md_algs;
165                 xalg=p7->d.signed_and_enveloped->enc_data->algorithm;
166                 evp_cipher=p7->d.signed_and_enveloped->enc_data->cipher;
167                 if (evp_cipher == NULL)
168                         {
169                         PKCS7err(PKCS7_F_PKCS7_DATAINIT,
170                                                 PKCS7_R_CIPHER_NOT_INITIALIZED);
171                         goto err;
172                         }
173                 break;
174         case NID_pkcs7_enveloped:
175                 rsk=p7->d.enveloped->recipientinfo;
176                 xalg=p7->d.enveloped->enc_data->algorithm;
177                 evp_cipher=p7->d.enveloped->enc_data->cipher;
178                 if (evp_cipher == NULL)
179                         {
180                         PKCS7err(PKCS7_F_PKCS7_DATAINIT,
181                                                 PKCS7_R_CIPHER_NOT_INITIALIZED);
182                         goto err;
183                         }
184                 break;
185         case NID_pkcs7_digest:
186                 xa = p7->d.digest->md;
187                 os = PKCS7_get_octet_string(p7->d.digest->contents);
188                 break;
189         default:
190                 PKCS7err(PKCS7_F_PKCS7_DATAINIT,PKCS7_R_UNSUPPORTED_CONTENT_TYPE);
191                 goto err;
192                 }
193
194         for (i=0; i<sk_X509_ALGOR_num(md_sk); i++)
195                 if (!PKCS7_bio_add_digest(&out, sk_X509_ALGOR_value(md_sk, i)))
196                         goto err;
197
198         if (xa && !PKCS7_bio_add_digest(&out, xa))
199                         goto err;
200
201         if (evp_cipher != NULL)
202                 {
203                 unsigned char key[EVP_MAX_KEY_LENGTH];
204                 unsigned char iv[EVP_MAX_IV_LENGTH];
205                 int keylen,ivlen;
206                 int jj,max;
207                 unsigned char *tmp;
208                 EVP_CIPHER_CTX *ctx;
209
210                 if ((btmp=BIO_new(BIO_f_cipher())) == NULL)
211                         {
212                         PKCS7err(PKCS7_F_PKCS7_DATAINIT,ERR_R_BIO_LIB);
213                         goto err;
214                         }
215                 BIO_get_cipher_ctx(btmp, &ctx);
216                 keylen=EVP_CIPHER_key_length(evp_cipher);
217                 ivlen=EVP_CIPHER_iv_length(evp_cipher);
218                 if (RAND_bytes(key,keylen) <= 0)
219                         goto err;
220                 xalg->algorithm = OBJ_nid2obj(EVP_CIPHER_type(evp_cipher));
221                 if (ivlen > 0) RAND_pseudo_bytes(iv,ivlen);
222                 EVP_CipherInit_ex(ctx, evp_cipher, NULL, key, iv, 1);
223
224                 if (ivlen > 0) {
225                         if (xalg->parameter == NULL) 
226                                                 xalg->parameter=ASN1_TYPE_new();
227                         if(EVP_CIPHER_param_to_asn1(ctx, xalg->parameter) < 0)
228                                                                        goto err;
229                 }
230
231                 /* Lets do the pub key stuff :-) */
232                 max=0;
233                 for (i=0; i<sk_PKCS7_RECIP_INFO_num(rsk); i++)
234                         {
235                         ri=sk_PKCS7_RECIP_INFO_value(rsk,i);
236                         if (ri->cert == NULL)
237                                 {
238                                 PKCS7err(PKCS7_F_PKCS7_DATAINIT,PKCS7_R_MISSING_CERIPEND_INFO);
239                                 goto err;
240                                 }
241                         pkey=X509_get_pubkey(ri->cert);
242                         jj=EVP_PKEY_size(pkey);
243                         EVP_PKEY_free(pkey);
244                         if (max < jj) max=jj;
245                         }
246                 if ((tmp=(unsigned char *)OPENSSL_malloc(max)) == NULL)
247                         {
248                         PKCS7err(PKCS7_F_PKCS7_DATAINIT,ERR_R_MALLOC_FAILURE);
249                         goto err;
250                         }
251                 for (i=0; i<sk_PKCS7_RECIP_INFO_num(rsk); i++)
252                         {
253                         ri=sk_PKCS7_RECIP_INFO_value(rsk,i);
254                         pkey=X509_get_pubkey(ri->cert);
255                         jj=EVP_PKEY_encrypt(tmp,key,keylen,pkey);
256                         EVP_PKEY_free(pkey);
257                         if (jj <= 0)
258                                 {
259                                 PKCS7err(PKCS7_F_PKCS7_DATAINIT,ERR_R_EVP_LIB);
260                                 OPENSSL_free(tmp);
261                                 goto err;
262                                 }
263                         M_ASN1_OCTET_STRING_set(ri->enc_key,tmp,jj);
264                         }
265                 OPENSSL_free(tmp);
266                 OPENSSL_cleanse(key, keylen);
267
268                 if (out == NULL)
269                         out=btmp;
270                 else
271                         BIO_push(out,btmp);
272                 btmp=NULL;
273                 }
274
275         if (bio == NULL)
276                 {
277                 if (PKCS7_is_detached(p7))
278                         bio=BIO_new(BIO_s_null());
279                 else if (os && os->length > 0)
280                         bio = BIO_new_mem_buf(os->data, os->length);
281                 if(bio == NULL)
282                         {
283                         bio=BIO_new(BIO_s_mem());
284                         BIO_set_mem_eof_return(bio,0);
285                         }
286                 }
287         BIO_push(out,bio);
288         bio=NULL;
289         if (0)
290                 {
291 err:
292                 if (out != NULL)
293                         BIO_free_all(out);
294                 if (btmp != NULL)
295                         BIO_free_all(btmp);
296                 out=NULL;
297                 }
298         return(out);
299         }
300
301 /* int */
302 BIO *PKCS7_dataDecode(PKCS7 *p7, EVP_PKEY *pkey, BIO *in_bio, X509 *pcert)
303         {
304         int i,j;
305         BIO *out=NULL,*btmp=NULL,*etmp=NULL,*bio=NULL;
306         unsigned char *tmp=NULL;
307         X509_ALGOR *xa;
308         ASN1_OCTET_STRING *data_body=NULL;
309         const EVP_MD *evp_md;
310         const EVP_CIPHER *evp_cipher=NULL;
311         EVP_CIPHER_CTX *evp_ctx=NULL;
312         X509_ALGOR *enc_alg=NULL;
313         STACK_OF(X509_ALGOR) *md_sk=NULL;
314         STACK_OF(PKCS7_RECIP_INFO) *rsk=NULL;
315         X509_ALGOR *xalg=NULL;
316         PKCS7_RECIP_INFO *ri=NULL;
317
318         i=OBJ_obj2nid(p7->type);
319         p7->state=PKCS7_S_HEADER;
320
321         switch (i)
322                 {
323         case NID_pkcs7_signed:
324                 data_body=PKCS7_get_octet_string(p7->d.sign->contents);
325                 md_sk=p7->d.sign->md_algs;
326                 break;
327         case NID_pkcs7_signedAndEnveloped:
328                 rsk=p7->d.signed_and_enveloped->recipientinfo;
329                 md_sk=p7->d.signed_and_enveloped->md_algs;
330                 data_body=p7->d.signed_and_enveloped->enc_data->enc_data;
331                 enc_alg=p7->d.signed_and_enveloped->enc_data->algorithm;
332                 evp_cipher=EVP_get_cipherbyobj(enc_alg->algorithm);
333                 if (evp_cipher == NULL)
334                         {
335                         PKCS7err(PKCS7_F_PKCS7_DATADECODE,PKCS7_R_UNSUPPORTED_CIPHER_TYPE);
336                         goto err;
337                         }
338                 xalg=p7->d.signed_and_enveloped->enc_data->algorithm;
339                 break;
340         case NID_pkcs7_enveloped:
341                 rsk=p7->d.enveloped->recipientinfo;
342                 enc_alg=p7->d.enveloped->enc_data->algorithm;
343                 data_body=p7->d.enveloped->enc_data->enc_data;
344                 evp_cipher=EVP_get_cipherbyobj(enc_alg->algorithm);
345                 if (evp_cipher == NULL)
346                         {
347                         PKCS7err(PKCS7_F_PKCS7_DATADECODE,PKCS7_R_UNSUPPORTED_CIPHER_TYPE);
348                         goto err;
349                         }
350                 xalg=p7->d.enveloped->enc_data->algorithm;
351                 break;
352         default:
353                 PKCS7err(PKCS7_F_PKCS7_DATADECODE,PKCS7_R_UNSUPPORTED_CONTENT_TYPE);
354                 goto err;
355                 }
356
357         /* We will be checking the signature */
358         if (md_sk != NULL)
359                 {
360                 for (i=0; i<sk_X509_ALGOR_num(md_sk); i++)
361                         {
362                         xa=sk_X509_ALGOR_value(md_sk,i);
363                         if ((btmp=BIO_new(BIO_f_md())) == NULL)
364                                 {
365                                 PKCS7err(PKCS7_F_PKCS7_DATADECODE,ERR_R_BIO_LIB);
366                                 goto err;
367                                 }
368
369                         j=OBJ_obj2nid(xa->algorithm);
370                         evp_md=EVP_get_digestbynid(j);
371                         if (evp_md == NULL)
372                                 {
373                                 PKCS7err(PKCS7_F_PKCS7_DATADECODE,PKCS7_R_UNKNOWN_DIGEST_TYPE);
374                                 goto err;
375                                 }
376
377                         BIO_set_md(btmp,evp_md);
378                         if (out == NULL)
379                                 out=btmp;
380                         else
381                                 BIO_push(out,btmp);
382                         btmp=NULL;
383                         }
384                 }
385
386         if (evp_cipher != NULL)
387                 {
388 #if 0
389                 unsigned char key[EVP_MAX_KEY_LENGTH];
390                 unsigned char iv[EVP_MAX_IV_LENGTH];
391                 unsigned char *p;
392                 int keylen,ivlen;
393                 int max;
394                 X509_OBJECT ret;
395 #endif
396                 int jj;
397
398                 if ((etmp=BIO_new(BIO_f_cipher())) == NULL)
399                         {
400                         PKCS7err(PKCS7_F_PKCS7_DATADECODE,ERR_R_BIO_LIB);
401                         goto err;
402                         }
403
404                 /* It was encrypted, we need to decrypt the secret key
405                  * with the private key */
406
407                 /* Find the recipientInfo which matches the passed certificate
408                  * (if any)
409                  */
410
411                 for (i=0; i<sk_PKCS7_RECIP_INFO_num(rsk); i++) {
412                         ri=sk_PKCS7_RECIP_INFO_value(rsk,i);
413                         if(!X509_NAME_cmp(ri->issuer_and_serial->issuer,
414                                         pcert->cert_info->issuer) &&
415                              !M_ASN1_INTEGER_cmp(pcert->cert_info->serialNumber,
416                                         ri->issuer_and_serial->serial)) break;
417                         ri=NULL;
418                 }
419                 if (ri == NULL) {
420                         PKCS7err(PKCS7_F_PKCS7_DATADECODE,
421                                  PKCS7_R_NO_RECIPIENT_MATCHES_CERTIFICATE);
422                         goto err;
423                 }
424
425                 jj=EVP_PKEY_size(pkey);
426                 tmp=(unsigned char *)OPENSSL_malloc(jj+10);
427                 if (tmp == NULL)
428                         {
429                         PKCS7err(PKCS7_F_PKCS7_DATADECODE,ERR_R_MALLOC_FAILURE);
430                         goto err;
431                         }
432
433                 jj=EVP_PKEY_decrypt(tmp, M_ASN1_STRING_data(ri->enc_key),
434                         M_ASN1_STRING_length(ri->enc_key), pkey);
435                 if (jj <= 0)
436                         {
437                         PKCS7err(PKCS7_F_PKCS7_DATADECODE,ERR_R_EVP_LIB);
438                         goto err;
439                         }
440
441                 evp_ctx=NULL;
442                 BIO_get_cipher_ctx(etmp,&evp_ctx);
443                 EVP_CipherInit_ex(evp_ctx,evp_cipher,NULL,NULL,NULL,0);
444                 if (EVP_CIPHER_asn1_to_param(evp_ctx,enc_alg->parameter) < 0)
445                         goto err;
446
447                 if (jj != EVP_CIPHER_CTX_key_length(evp_ctx)) {
448                         /* Some S/MIME clients don't use the same key
449                          * and effective key length. The key length is
450                          * determined by the size of the decrypted RSA key.
451                          */
452                         if(!EVP_CIPHER_CTX_set_key_length(evp_ctx, jj))
453                                 {
454                                 PKCS7err(PKCS7_F_PKCS7_DATADECODE,
455                                         PKCS7_R_DECRYPTED_KEY_IS_WRONG_LENGTH);
456                                 goto err;
457                                 }
458                 } 
459                 EVP_CipherInit_ex(evp_ctx,NULL,NULL,tmp,NULL,0);
460
461                 OPENSSL_cleanse(tmp,jj);
462
463                 if (out == NULL)
464                         out=etmp;
465                 else
466                         BIO_push(out,etmp);
467                 etmp=NULL;
468                 }
469
470 #if 1
471         if (PKCS7_is_detached(p7) || (in_bio != NULL))
472                 {
473                 bio=in_bio;
474                 }
475         else 
476                 {
477 #if 0
478                 bio=BIO_new(BIO_s_mem());
479                 /* We need to set this so that when we have read all
480                  * the data, the encrypt BIO, if present, will read
481                  * EOF and encode the last few bytes */
482                 BIO_set_mem_eof_return(bio,0);
483
484                 if (data_body->length > 0)
485                         BIO_write(bio,(char *)data_body->data,data_body->length);
486 #else
487                 if (data_body->length > 0)
488                       bio = BIO_new_mem_buf(data_body->data,data_body->length);
489                 else {
490                         bio=BIO_new(BIO_s_mem());
491                         BIO_set_mem_eof_return(bio,0);
492                 }
493 #endif
494                 }
495         BIO_push(out,bio);
496         bio=NULL;
497 #endif
498         if (0)
499                 {
500 err:
501                 if (out != NULL) BIO_free_all(out);
502                 if (btmp != NULL) BIO_free_all(btmp);
503                 if (etmp != NULL) BIO_free_all(etmp);
504                 if (bio != NULL) BIO_free_all(bio);
505                 out=NULL;
506                 }
507         if (tmp != NULL)
508                 OPENSSL_free(tmp);
509         return(out);
510         }
511
512 static BIO *PKCS7_find_digest(EVP_MD_CTX **pmd, BIO *bio, int nid)
513         {
514         for (;;)
515                 {
516                 bio=BIO_find_type(bio,BIO_TYPE_MD);
517                 if (bio == NULL)
518                         {
519                         PKCS7err(PKCS7_F_FIND_DIGEST,PKCS7_R_UNABLE_TO_FIND_MESSAGE_DIGEST);
520                         return NULL;    
521                         }
522                 BIO_get_md_ctx(bio,pmd);
523                 if (*pmd == NULL)
524                         {
525                         PKCS7err(PKCS7_F_PKCS7_DATASIGN,ERR_R_INTERNAL_ERROR);
526                         return NULL;
527                         }       
528                 if (EVP_MD_CTX_type(*pmd) == nid)
529                         return bio;
530                 bio=BIO_next(bio);
531                 }
532         return NULL;
533         }
534
535 int PKCS7_dataFinal(PKCS7 *p7, BIO *bio)
536         {
537         int ret=0;
538         int i,j;
539         BIO *btmp;
540         BUF_MEM *buf_mem=NULL;
541         BUF_MEM *buf=NULL;
542         PKCS7_SIGNER_INFO *si;
543         EVP_MD_CTX *mdc,ctx_tmp;
544         STACK_OF(X509_ATTRIBUTE) *sk;
545         STACK_OF(PKCS7_SIGNER_INFO) *si_sk=NULL;
546         ASN1_OCTET_STRING *os=NULL;
547
548         EVP_MD_CTX_init(&ctx_tmp);
549         i=OBJ_obj2nid(p7->type);
550         p7->state=PKCS7_S_HEADER;
551
552         switch (i)
553                 {
554         case NID_pkcs7_signedAndEnveloped:
555                 /* XXXXXXXXXXXXXXXX */
556                 si_sk=p7->d.signed_and_enveloped->signer_info;
557                 os=M_ASN1_OCTET_STRING_new();
558                 p7->d.signed_and_enveloped->enc_data->enc_data=os;
559                 break;
560         case NID_pkcs7_enveloped:
561                 /* XXXXXXXXXXXXXXXX */
562                 os=M_ASN1_OCTET_STRING_new();
563                 p7->d.enveloped->enc_data->enc_data=os;
564                 break;
565         case NID_pkcs7_signed:
566                 si_sk=p7->d.sign->signer_info;
567                 os=PKCS7_get_octet_string(p7->d.sign->contents);
568                 /* If detached data then the content is excluded */
569                 if(PKCS7_type_is_data(p7->d.sign->contents) && p7->detached) {
570                         M_ASN1_OCTET_STRING_free(os);
571                         p7->d.sign->contents->d.data = NULL;
572                 }
573                 break;
574
575         case NID_pkcs7_digest:
576                 os=PKCS7_get_octet_string(p7->d.digest->contents);
577                 /* If detached data then the content is excluded */
578                 if(PKCS7_type_is_data(p7->d.digest->contents) && p7->detached)
579                         {
580                         M_ASN1_OCTET_STRING_free(os);
581                         p7->d.digest->contents->d.data = NULL;
582                         }
583                 break;
584
585                 }
586
587         if (si_sk != NULL)
588                 {
589                 if ((buf=BUF_MEM_new()) == NULL)
590                         {
591                         PKCS7err(PKCS7_F_PKCS7_DATASIGN,ERR_R_BIO_LIB);
592                         goto err;
593                         }
594                 for (i=0; i<sk_PKCS7_SIGNER_INFO_num(si_sk); i++)
595                         {
596                         si=sk_PKCS7_SIGNER_INFO_value(si_sk,i);
597                         if (si->pkey == NULL) continue;
598
599                         j=OBJ_obj2nid(si->digest_alg->algorithm);
600
601                         btmp=bio;
602
603                         btmp = PKCS7_find_digest(&mdc, btmp, j);
604
605                         if (btmp == NULL)
606                                 goto err;
607
608                         /* We now have the EVP_MD_CTX, lets do the
609                          * signing. */
610                         EVP_MD_CTX_copy_ex(&ctx_tmp,mdc);
611                         if (!BUF_MEM_grow_clean(buf,EVP_PKEY_size(si->pkey)))
612                                 {
613                                 PKCS7err(PKCS7_F_PKCS7_DATASIGN,ERR_R_BIO_LIB);
614                                 goto err;
615                                 }
616
617                         sk=si->auth_attr;
618
619                         /* If there are attributes, we add the digest
620                          * attribute and only sign the attributes */
621                         if ((sk != NULL) && (sk_X509_ATTRIBUTE_num(sk) != 0))
622                                 {
623                                 unsigned char md_data[EVP_MAX_MD_SIZE], *abuf=NULL;
624                                 unsigned int md_len, alen;
625                                 ASN1_OCTET_STRING *digest;
626                                 ASN1_UTCTIME *sign_time;
627                                 const EVP_MD *md_tmp;
628
629                                 /* Add signing time if not already present */
630                                 if (!PKCS7_get_signed_attribute(si,
631                                                         NID_pkcs9_signingTime))
632                                         {
633                                         sign_time=X509_gmtime_adj(NULL,0);
634                                         PKCS7_add_signed_attribute(si,
635                                                 NID_pkcs9_signingTime,
636                                                 V_ASN1_UTCTIME,sign_time);
637                                         }
638
639                                 /* Add digest */
640                                 md_tmp=EVP_MD_CTX_md(&ctx_tmp);
641                                 EVP_DigestFinal_ex(&ctx_tmp,md_data,&md_len);
642                                 digest=M_ASN1_OCTET_STRING_new();
643                                 M_ASN1_OCTET_STRING_set(digest,md_data,md_len);
644                                 PKCS7_add_signed_attribute(si,
645                                         NID_pkcs9_messageDigest,
646                                         V_ASN1_OCTET_STRING,digest);
647
648                                 /* Now sign the attributes */
649                                 EVP_SignInit_ex(&ctx_tmp,md_tmp,NULL);
650                                 alen = ASN1_item_i2d((ASN1_VALUE *)sk,&abuf,
651                                                         ASN1_ITEM_rptr(PKCS7_ATTR_SIGN));
652                                 if(!abuf) goto err;
653                                 EVP_SignUpdate(&ctx_tmp,abuf,alen);
654                                 OPENSSL_free(abuf);
655                                 }
656
657 #ifndef OPENSSL_NO_DSA
658                         if (si->pkey->type == EVP_PKEY_DSA)
659                                 ctx_tmp.digest=EVP_dss1();
660 #endif
661 #ifndef OPENSSL_NO_ECDSA
662                         if (si->pkey->type == EVP_PKEY_EC)
663                                 ctx_tmp.digest=EVP_ecdsa();
664 #endif
665
666                         if (!EVP_SignFinal(&ctx_tmp,(unsigned char *)buf->data,
667                                 (unsigned int *)&buf->length,si->pkey))
668                                 {
669                                 PKCS7err(PKCS7_F_PKCS7_DATASIGN,ERR_R_EVP_LIB);
670                                 goto err;
671                                 }
672                         if (!ASN1_STRING_set(si->enc_digest,
673                                 (unsigned char *)buf->data,buf->length))
674                                 {
675                                 PKCS7err(PKCS7_F_PKCS7_DATASIGN,ERR_R_ASN1_LIB);
676                                 goto err;
677                                 }
678                         }
679                 }
680         else if (i == NID_pkcs7_digest)
681                 {
682                 unsigned char md_data[EVP_MAX_MD_SIZE];
683                 unsigned int md_len;
684                 if (!PKCS7_find_digest(&mdc, bio,
685                                 OBJ_obj2nid(p7->d.digest->md->algorithm)))
686                         goto err;
687                 EVP_DigestFinal_ex(mdc,md_data,&md_len);
688                 M_ASN1_OCTET_STRING_set(p7->d.digest->digest, md_data, md_len);
689                 }
690
691         if (!PKCS7_is_detached(p7))
692                 {
693                 btmp=BIO_find_type(bio,BIO_TYPE_MEM);
694                 if (btmp == NULL)
695                         {
696                         PKCS7err(PKCS7_F_PKCS7_DATASIGN,PKCS7_R_UNABLE_TO_FIND_MEM_BIO);
697                         goto err;
698                         }
699                 BIO_get_mem_ptr(btmp,&buf_mem);
700                 /* Mark the BIO read only then we can use its copy of the data
701                  * instead of making an extra copy.
702                  */
703                 BIO_set_flags(btmp, BIO_FLAGS_MEM_RDONLY);
704                 BIO_set_mem_eof_return(btmp, 0);
705                 os->data = (unsigned char *)buf_mem->data;
706                 os->length = buf_mem->length;
707 #if 0
708                 M_ASN1_OCTET_STRING_set(os,
709                         (unsigned char *)buf_mem->data,buf_mem->length);
710 #endif
711                 }
712         ret=1;
713 err:
714         EVP_MD_CTX_cleanup(&ctx_tmp);
715         if (buf != NULL) BUF_MEM_free(buf);
716         return(ret);
717         }
718
719 int PKCS7_dataVerify(X509_STORE *cert_store, X509_STORE_CTX *ctx, BIO *bio,
720              PKCS7 *p7, PKCS7_SIGNER_INFO *si)
721         {
722         PKCS7_ISSUER_AND_SERIAL *ias;
723         int ret=0,i;
724         STACK_OF(X509) *cert;
725         X509 *x509;
726
727         if (PKCS7_type_is_signed(p7))
728                 {
729                 cert=p7->d.sign->cert;
730                 }
731         else if (PKCS7_type_is_signedAndEnveloped(p7))
732                 {
733                 cert=p7->d.signed_and_enveloped->cert;
734                 }
735         else
736                 {
737                 PKCS7err(PKCS7_F_PKCS7_DATAVERIFY,PKCS7_R_WRONG_PKCS7_TYPE);
738                 goto err;
739                 }
740         /* XXXXXXXXXXXXXXXXXXXXXXX */
741         ias=si->issuer_and_serial;
742
743         x509=X509_find_by_issuer_and_serial(cert,ias->issuer,ias->serial);
744
745         /* were we able to find the cert in passed to us */
746         if (x509 == NULL)
747                 {
748                 PKCS7err(PKCS7_F_PKCS7_DATAVERIFY,PKCS7_R_UNABLE_TO_FIND_CERTIFICATE);
749                 goto err;
750                 }
751
752         /* Lets verify */
753         if(!X509_STORE_CTX_init(ctx,cert_store,x509,cert))
754                 {
755                 PKCS7err(PKCS7_F_PKCS7_DATAVERIFY,ERR_R_X509_LIB);
756                 goto err;
757                 }
758         X509_STORE_CTX_set_purpose(ctx, X509_PURPOSE_SMIME_SIGN);
759         i=X509_verify_cert(ctx);
760         if (i <= 0) 
761                 {
762                 PKCS7err(PKCS7_F_PKCS7_DATAVERIFY,ERR_R_X509_LIB);
763                 X509_STORE_CTX_cleanup(ctx);
764                 goto err;
765                 }
766         X509_STORE_CTX_cleanup(ctx);
767
768         return PKCS7_signatureVerify(bio, p7, si, x509);
769         err:
770         return ret;
771         }
772
773 int PKCS7_signatureVerify(BIO *bio, PKCS7 *p7, PKCS7_SIGNER_INFO *si,
774                                                                 X509 *x509)
775         {
776         ASN1_OCTET_STRING *os;
777         EVP_MD_CTX mdc_tmp,*mdc;
778         int ret=0,i;
779         int md_type;
780         STACK_OF(X509_ATTRIBUTE) *sk;
781         BIO *btmp;
782         EVP_PKEY *pkey;
783
784         EVP_MD_CTX_init(&mdc_tmp);
785
786         if (!PKCS7_type_is_signed(p7) && 
787                                 !PKCS7_type_is_signedAndEnveloped(p7)) {
788                 PKCS7err(PKCS7_F_PKCS7_SIGNATUREVERIFY,
789                                                 PKCS7_R_WRONG_PKCS7_TYPE);
790                 goto err;
791         }
792
793         md_type=OBJ_obj2nid(si->digest_alg->algorithm);
794
795         btmp=bio;
796         for (;;)
797                 {
798                 if ((btmp == NULL) ||
799                         ((btmp=BIO_find_type(btmp,BIO_TYPE_MD)) == NULL))
800                         {
801                         PKCS7err(PKCS7_F_PKCS7_SIGNATUREVERIFY,
802                                         PKCS7_R_UNABLE_TO_FIND_MESSAGE_DIGEST);
803                         goto err;
804                         }
805                 BIO_get_md_ctx(btmp,&mdc);
806                 if (mdc == NULL)
807                         {
808                         PKCS7err(PKCS7_F_PKCS7_SIGNATUREVERIFY,
809                                                         ERR_R_INTERNAL_ERROR);
810                         goto err;
811                         }
812                 if (EVP_MD_CTX_type(mdc) == md_type)
813                         break;
814                 /* Workaround for some broken clients that put the signature
815                  * OID instead of the digest OID in digest_alg->algorithm
816                  */
817                 if (EVP_MD_pkey_type(EVP_MD_CTX_md(mdc)) == md_type)
818                         break;
819                 btmp=BIO_next(btmp);
820                 }
821
822         /* mdc is the digest ctx that we want, unless there are attributes,
823          * in which case the digest is the signed attributes */
824         EVP_MD_CTX_copy_ex(&mdc_tmp,mdc);
825
826         sk=si->auth_attr;
827         if ((sk != NULL) && (sk_X509_ATTRIBUTE_num(sk) != 0))
828                 {
829                 unsigned char md_dat[EVP_MAX_MD_SIZE], *abuf = NULL;
830                 unsigned int md_len, alen;
831                 ASN1_OCTET_STRING *message_digest;
832
833                 EVP_DigestFinal_ex(&mdc_tmp,md_dat,&md_len);
834                 message_digest=PKCS7_digest_from_attributes(sk);
835                 if (!message_digest)
836                         {
837                         PKCS7err(PKCS7_F_PKCS7_SIGNATUREVERIFY,
838                                         PKCS7_R_UNABLE_TO_FIND_MESSAGE_DIGEST);
839                         goto err;
840                         }
841                 if ((message_digest->length != (int)md_len) ||
842                         (memcmp(message_digest->data,md_dat,md_len)))
843                         {
844 #if 0
845 {
846 int ii;
847 for (ii=0; ii<message_digest->length; ii++)
848         printf("%02X",message_digest->data[ii]); printf(" sent\n");
849 for (ii=0; ii<md_len; ii++) printf("%02X",md_dat[ii]); printf(" calc\n");
850 }
851 #endif
852                         PKCS7err(PKCS7_F_PKCS7_SIGNATUREVERIFY,
853                                                         PKCS7_R_DIGEST_FAILURE);
854                         ret= -1;
855                         goto err;
856                         }
857
858                 EVP_VerifyInit_ex(&mdc_tmp,EVP_get_digestbynid(md_type), NULL);
859
860                 alen = ASN1_item_i2d((ASN1_VALUE *)sk, &abuf,
861                                                 ASN1_ITEM_rptr(PKCS7_ATTR_VERIFY));
862                 EVP_VerifyUpdate(&mdc_tmp, abuf, alen);
863
864                 OPENSSL_free(abuf);
865                 }
866
867         os=si->enc_digest;
868         pkey = X509_get_pubkey(x509);
869         if (!pkey)
870                 {
871                 ret = -1;
872                 goto err;
873                 }
874 #ifndef OPENSSL_NO_DSA
875         if(pkey->type == EVP_PKEY_DSA) mdc_tmp.digest=EVP_dss1();
876 #endif
877 #ifndef OPENSSL_NO_ECDSA
878         if (pkey->type == EVP_PKEY_EC) mdc_tmp.digest=EVP_ecdsa();
879 #endif
880
881         i=EVP_VerifyFinal(&mdc_tmp,os->data,os->length, pkey);
882         EVP_PKEY_free(pkey);
883         if (i <= 0)
884                 {
885                 PKCS7err(PKCS7_F_PKCS7_SIGNATUREVERIFY,
886                                                 PKCS7_R_SIGNATURE_FAILURE);
887                 ret= -1;
888                 goto err;
889                 }
890         else
891                 ret=1;
892 err:
893         EVP_MD_CTX_cleanup(&mdc_tmp);
894         return(ret);
895         }
896
897 PKCS7_ISSUER_AND_SERIAL *PKCS7_get_issuer_and_serial(PKCS7 *p7, int idx)
898         {
899         STACK_OF(PKCS7_RECIP_INFO) *rsk;
900         PKCS7_RECIP_INFO *ri;
901         int i;
902
903         i=OBJ_obj2nid(p7->type);
904         if (i != NID_pkcs7_signedAndEnveloped) return(NULL);
905         rsk=p7->d.signed_and_enveloped->recipientinfo;
906         ri=sk_PKCS7_RECIP_INFO_value(rsk,0);
907         if (sk_PKCS7_RECIP_INFO_num(rsk) <= idx) return(NULL);
908         ri=sk_PKCS7_RECIP_INFO_value(rsk,idx);
909         return(ri->issuer_and_serial);
910         }
911
912 ASN1_TYPE *PKCS7_get_signed_attribute(PKCS7_SIGNER_INFO *si, int nid)
913         {
914         return(get_attribute(si->auth_attr,nid));
915         }
916
917 ASN1_TYPE *PKCS7_get_attribute(PKCS7_SIGNER_INFO *si, int nid)
918         {
919         return(get_attribute(si->unauth_attr,nid));
920         }
921
922 static ASN1_TYPE *get_attribute(STACK_OF(X509_ATTRIBUTE) *sk, int nid)
923         {
924         int i;
925         X509_ATTRIBUTE *xa;
926         ASN1_OBJECT *o;
927
928         o=OBJ_nid2obj(nid);
929         if (!o || !sk) return(NULL);
930         for (i=0; i<sk_X509_ATTRIBUTE_num(sk); i++)
931                 {
932                 xa=sk_X509_ATTRIBUTE_value(sk,i);
933                 if (OBJ_cmp(xa->object,o) == 0)
934                         {
935                         if (!xa->single && sk_ASN1_TYPE_num(xa->value.set))
936                                 return(sk_ASN1_TYPE_value(xa->value.set,0));
937                         else
938                                 return(NULL);
939                         }
940                 }
941         return(NULL);
942         }
943
944 ASN1_OCTET_STRING *PKCS7_digest_from_attributes(STACK_OF(X509_ATTRIBUTE) *sk)
945 {
946         ASN1_TYPE *astype;
947         if(!(astype = get_attribute(sk, NID_pkcs9_messageDigest))) return NULL;
948         return astype->value.octet_string;
949 }
950
951 int PKCS7_set_signed_attributes(PKCS7_SIGNER_INFO *p7si,
952                                 STACK_OF(X509_ATTRIBUTE) *sk)
953         {
954         int i;
955
956         if (p7si->auth_attr != NULL)
957                 sk_X509_ATTRIBUTE_pop_free(p7si->auth_attr,X509_ATTRIBUTE_free);
958         p7si->auth_attr=sk_X509_ATTRIBUTE_dup(sk);
959         for (i=0; i<sk_X509_ATTRIBUTE_num(sk); i++)
960                 {
961                 if ((sk_X509_ATTRIBUTE_set(p7si->auth_attr,i,
962                         X509_ATTRIBUTE_dup(sk_X509_ATTRIBUTE_value(sk,i))))
963                     == NULL)
964                         return(0);
965                 }
966         return(1);
967         }
968
969 int PKCS7_set_attributes(PKCS7_SIGNER_INFO *p7si, STACK_OF(X509_ATTRIBUTE) *sk)
970         {
971         int i;
972
973         if (p7si->unauth_attr != NULL)
974                 sk_X509_ATTRIBUTE_pop_free(p7si->unauth_attr,
975                                            X509_ATTRIBUTE_free);
976         p7si->unauth_attr=sk_X509_ATTRIBUTE_dup(sk);
977         for (i=0; i<sk_X509_ATTRIBUTE_num(sk); i++)
978                 {
979                 if ((sk_X509_ATTRIBUTE_set(p7si->unauth_attr,i,
980                         X509_ATTRIBUTE_dup(sk_X509_ATTRIBUTE_value(sk,i))))
981                     == NULL)
982                         return(0);
983                 }
984         return(1);
985         }
986
987 int PKCS7_add_signed_attribute(PKCS7_SIGNER_INFO *p7si, int nid, int atrtype,
988              void *value)
989         {
990         return(add_attribute(&(p7si->auth_attr),nid,atrtype,value));
991         }
992
993 int PKCS7_add_attribute(PKCS7_SIGNER_INFO *p7si, int nid, int atrtype,
994              void *value)
995         {
996         return(add_attribute(&(p7si->unauth_attr),nid,atrtype,value));
997         }
998
999 static int add_attribute(STACK_OF(X509_ATTRIBUTE) **sk, int nid, int atrtype,
1000                          void *value)
1001         {
1002         X509_ATTRIBUTE *attr=NULL;
1003
1004         if (*sk == NULL)
1005                 {
1006                 *sk = sk_X509_ATTRIBUTE_new_null();
1007 new_attrib:
1008                 attr=X509_ATTRIBUTE_create(nid,atrtype,value);
1009                 sk_X509_ATTRIBUTE_push(*sk,attr);
1010                 }
1011         else
1012                 {
1013                 int i;
1014
1015                 for (i=0; i<sk_X509_ATTRIBUTE_num(*sk); i++)
1016                         {
1017                         attr=sk_X509_ATTRIBUTE_value(*sk,i);
1018                         if (OBJ_obj2nid(attr->object) == nid)
1019                                 {
1020                                 X509_ATTRIBUTE_free(attr);
1021                                 attr=X509_ATTRIBUTE_create(nid,atrtype,value);
1022                                 sk_X509_ATTRIBUTE_set(*sk,i,attr);
1023                                 goto end;
1024                                 }
1025                         }
1026                 goto new_attrib;
1027                 }
1028 end:
1029         return(1);
1030         }
1031