Typos.
[openssl.git] / apps / cms.c
1 /* apps/cms.c */
2 /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
3  * project.
4  */
5 /* ====================================================================
6  * Copyright (c) 2008 The OpenSSL Project.  All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer. 
14  *
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in
17  *    the documentation and/or other materials provided with the
18  *    distribution.
19  *
20  * 3. All advertising materials mentioning features or use of this
21  *    software must display the following acknowledgment:
22  *    "This product includes software developed by the OpenSSL Project
23  *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
24  *
25  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
26  *    endorse or promote products derived from this software without
27  *    prior written permission. For written permission, please contact
28  *    licensing@OpenSSL.org.
29  *
30  * 5. Products derived from this software may not be called "OpenSSL"
31  *    nor may "OpenSSL" appear in their names without prior written
32  *    permission of the OpenSSL Project.
33  *
34  * 6. Redistributions of any form whatsoever must retain the following
35  *    acknowledgment:
36  *    "This product includes software developed by the OpenSSL Project
37  *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
38  *
39  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
40  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
41  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
42  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
43  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
44  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
45  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
46  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
48  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
49  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
50  * OF THE POSSIBILITY OF SUCH DAMAGE.
51  * ====================================================================
52  */
53
54 /* CMS utility function */
55
56 #include <stdio.h>
57 #include <string.h>
58 #include "apps.h"
59
60 #ifndef OPENSSL_NO_CMS
61
62 #include <openssl/crypto.h>
63 #include <openssl/pem.h>
64 #include <openssl/err.h>
65 #include <openssl/x509_vfy.h>
66 #include <openssl/x509v3.h>
67 #include <openssl/cms.h>
68
69 #undef PROG
70 #define PROG cms_main
71 static int save_certs(char *signerfile, STACK_OF(X509) *signers);
72 static int smime_cb(int ok, X509_STORE_CTX *ctx);
73
74 #define SMIME_OP        0x10
75 #define SMIME_IP        0x20
76 #define SMIME_SIGNERS   0x40
77 #define SMIME_ENCRYPT           (1 | SMIME_OP)
78 #define SMIME_DECRYPT           (2 | SMIME_IP)
79 #define SMIME_SIGN              (3 | SMIME_OP | SMIME_SIGNERS)
80 #define SMIME_VERIFY            (4 | SMIME_IP)
81 #define SMIME_CMSOUT            (5 | SMIME_IP | SMIME_OP)
82 #define SMIME_RESIGN            (6 | SMIME_IP | SMIME_OP | SMIME_SIGNERS)
83 #define SMIME_DATAOUT           (7 | SMIME_IP)
84 #define SMIME_DATA_CREATE       (8 | SMIME_OP)
85 #define SMIME_DIGEST_VERIFY     (9 | SMIME_IP)
86 #define SMIME_DIGEST_CREATE     (10 | SMIME_OP)
87 #define SMIME_UNCOMPRESS        (11 | SMIME_IP)
88 #define SMIME_COMPRESS          (12 | SMIME_OP)
89 #define SMIME_ENCRYPTED_DECRYPT (13 | SMIME_IP)
90
91 int MAIN(int, char **);
92
93 int MAIN(int argc, char **argv)
94         {
95         ENGINE *e = NULL;
96         int operation = 0;
97         int ret = 0;
98         char **args;
99         const char *inmode = "r", *outmode = "w";
100         char *infile = NULL, *outfile = NULL;
101         char *signerfile = NULL, *recipfile = NULL;
102         STACK *sksigners = NULL, *skkeys = NULL;
103         char *certfile = NULL, *keyfile = NULL, *contfile=NULL;
104         const EVP_CIPHER *cipher = NULL;
105         CMS_ContentInfo *cms = NULL;
106         X509_STORE *store = NULL;
107         X509 *cert = NULL, *recip = NULL, *signer = NULL;
108         EVP_PKEY *key = NULL;
109         STACK_OF(X509) *encerts = NULL, *other = NULL;
110         BIO *in = NULL, *out = NULL, *indata = NULL;
111         int badarg = 0;
112         int flags = CMS_DETACHED;
113         char *to = NULL, *from = NULL, *subject = NULL;
114         char *CAfile = NULL, *CApath = NULL;
115         char *passargin = NULL, *passin = NULL;
116         char *inrand = NULL;
117         int need_rand = 0;
118         int indef = 0;
119         const EVP_MD *sign_md = NULL;
120         int informat = FORMAT_SMIME, outformat = FORMAT_SMIME;
121         int keyform = FORMAT_PEM;
122 #ifndef OPENSSL_NO_ENGINE
123         char *engine=NULL;
124 #endif
125         unsigned char *secret_key = NULL;
126         size_t secret_keylen;
127
128         X509_VERIFY_PARAM *vpm = NULL;
129
130         args = argv + 1;
131         ret = 1;
132
133         apps_startup();
134
135         if (bio_err == NULL)
136                 {
137                 if ((bio_err = BIO_new(BIO_s_file())) != NULL)
138                         BIO_set_fp(bio_err, stderr, BIO_NOCLOSE|BIO_FP_TEXT);
139                 }
140
141         if (!load_config(bio_err, NULL))
142                 goto end;
143
144         while (!badarg && *args && *args[0] == '-')
145                 {
146                 if (!strcmp (*args, "-encrypt"))
147                         operation = SMIME_ENCRYPT;
148                 else if (!strcmp (*args, "-decrypt"))
149                         operation = SMIME_DECRYPT;
150                 else if (!strcmp (*args, "-sign"))
151                         operation = SMIME_SIGN;
152                 else if (!strcmp (*args, "-resign"))
153                         operation = SMIME_RESIGN;
154                 else if (!strcmp (*args, "-verify"))
155                         operation = SMIME_VERIFY;
156                 else if (!strcmp (*args, "-cmsout"))
157                         operation = SMIME_CMSOUT;
158                 else if (!strcmp (*args, "-data_out"))
159                         operation = SMIME_DATAOUT;
160                 else if (!strcmp (*args, "-data_create"))
161                         operation = SMIME_DATA_CREATE;
162                 else if (!strcmp (*args, "-digest_verify"))
163                         operation = SMIME_DIGEST_VERIFY;
164                 else if (!strcmp (*args, "-digest_create"))
165                         operation = SMIME_DIGEST_CREATE;
166                 else if (!strcmp (*args, "-compress"))
167                         operation = SMIME_COMPRESS;
168                 else if (!strcmp (*args, "-uncompress"))
169                         operation = SMIME_UNCOMPRESS;
170                 else if (!strcmp (*args, "-EncryptedData_decrypt"))
171                         operation = SMIME_ENCRYPTED_DECRYPT;
172 #ifndef OPENSSL_NO_DES
173                 else if (!strcmp (*args, "-des3")) 
174                                 cipher = EVP_des_ede3_cbc();
175                 else if (!strcmp (*args, "-des")) 
176                                 cipher = EVP_des_cbc();
177 #endif
178 #ifndef OPENSSL_NO_SEED
179                 else if (!strcmp (*args, "-seed")) 
180                                 cipher = EVP_seed_cbc();
181 #endif
182 #ifndef OPENSSL_NO_RC2
183                 else if (!strcmp (*args, "-rc2-40")) 
184                                 cipher = EVP_rc2_40_cbc();
185                 else if (!strcmp (*args, "-rc2-128")) 
186                                 cipher = EVP_rc2_cbc();
187                 else if (!strcmp (*args, "-rc2-64")) 
188                                 cipher = EVP_rc2_64_cbc();
189 #endif
190 #ifndef OPENSSL_NO_AES
191                 else if (!strcmp(*args,"-aes128"))
192                                 cipher = EVP_aes_128_cbc();
193                 else if (!strcmp(*args,"-aes192"))
194                                 cipher = EVP_aes_192_cbc();
195                 else if (!strcmp(*args,"-aes256"))
196                                 cipher = EVP_aes_256_cbc();
197 #endif
198 #ifndef OPENSSL_NO_CAMELLIA
199                 else if (!strcmp(*args,"-camellia128"))
200                                 cipher = EVP_camellia_128_cbc();
201                 else if (!strcmp(*args,"-camellia192"))
202                                 cipher = EVP_camellia_192_cbc();
203                 else if (!strcmp(*args,"-camellia256"))
204                                 cipher = EVP_camellia_256_cbc();
205 #endif
206                 else if (!strcmp (*args, "-text")) 
207                                 flags |= CMS_TEXT;
208                 else if (!strcmp (*args, "-nointern")) 
209                                 flags |= CMS_NOINTERN;
210                 else if (!strcmp (*args, "-noverify") 
211                         || !strcmp (*args, "-no_signer_cert_verify")) 
212                                 flags |= CMS_NO_SIGNER_CERT_VERIFY;
213                 else if (!strcmp (*args, "-nocerts")) 
214                                 flags |= CMS_NOCERTS;
215                 else if (!strcmp (*args, "-noattr")) 
216                                 flags |= CMS_NOATTR;
217                 else if (!strcmp (*args, "-nodetach")) 
218                                 flags &= ~CMS_DETACHED;
219                 else if (!strcmp (*args, "-nosmimecap"))
220                                 flags |= CMS_NOSMIMECAP;
221                 else if (!strcmp (*args, "-binary"))
222                                 flags |= CMS_BINARY;
223                 else if (!strcmp (*args, "-keyid"))
224                                 flags |= CMS_USE_KEYID;
225                 else if (!strcmp (*args, "-nosigs"))
226                                 flags |= CMS_NOSIGS;
227                 else if (!strcmp (*args, "-no_content_verify"))
228                                 flags |= CMS_NO_CONTENT_VERIFY;
229                 else if (!strcmp (*args, "-no_attr_verify"))
230                                 flags |= CMS_NO_ATTR_VERIFY;
231                 else if (!strcmp (*args, "-stream"))
232                                 indef = 1;
233                 else if (!strcmp (*args, "-indef"))
234                                 indef = 1;
235                 else if (!strcmp (*args, "-noindef"))
236                                 indef = 0;
237                 else if (!strcmp (*args, "-nooldmime"))
238                                 flags |= CMS_NOOLDMIMETYPE;
239                 else if (!strcmp (*args, "-crlfeol"))
240                                 flags |= CMS_CRLFEOL;
241                 else if (!strcmp(*args,"-secretkey"))
242                         {
243                         long ltmp;
244                         if (!args[1])
245                                 goto argerr;
246                         args++;
247                         secret_key = string_to_hex(*args, &ltmp);
248                         if (!secret_key)
249                                 {
250                                 BIO_printf(bio_err, "Invalid key %s\n", *args);
251                                 goto argerr;
252                                 }
253                         secret_keylen = (size_t)ltmp;
254                         }
255                 else if (!strcmp(*args,"-rand"))
256                         {
257                         if (!args[1])
258                                 goto argerr;
259                         args++;
260                         inrand = *args;
261                         need_rand = 1;
262                         }
263 #ifndef OPENSSL_NO_ENGINE
264                 else if (!strcmp(*args,"-engine"))
265                         {
266                         if (!args[1])
267                                 goto argerr;
268                         engine = *++args;
269                         }
270 #endif
271                 else if (!strcmp(*args,"-passin"))
272                         {
273                         if (!args[1])
274                                 goto argerr;
275                         passargin = *++args;
276                         }
277                 else if (!strcmp (*args, "-to"))
278                         {
279                         if (!args[1])
280                                 goto argerr;
281                         to = *++args;
282                         }
283                 else if (!strcmp (*args, "-from"))
284                         {
285                         if (!args[1])
286                                 goto argerr;
287                         from = *++args;
288                         }
289                 else if (!strcmp (*args, "-subject"))
290                         {
291                         if (!args[1])
292                                 goto argerr;
293                         subject = *++args;
294                         }
295                 else if (!strcmp (*args, "-signer"))
296                         {
297                         if (!args[1])
298                                 goto argerr;
299                         /* If previous -signer argument add signer to list */
300
301                         if (signerfile)
302                                 {
303                                 if (!sksigners)
304                                         sksigners = sk_new_null();
305                                 sk_push(sksigners, signerfile);
306                                 if (!keyfile)
307                                         keyfile = signerfile;
308                                 if (!skkeys)
309                                         skkeys = sk_new_null();
310                                 sk_push(skkeys, keyfile);
311                                 keyfile = NULL;
312                                 }
313                         signerfile = *++args;
314                         }
315                 else if (!strcmp (*args, "-recip"))
316                         {
317                         if (!args[1])
318                                 goto argerr;
319                         recipfile = *++args;
320                         }
321                 else if (!strcmp (*args, "-md"))
322                         {
323                         if (!args[1])
324                                 goto argerr;
325                         sign_md = EVP_get_digestbyname(*++args);
326                         if (sign_md == NULL)
327                                 {
328                                 BIO_printf(bio_err, "Unknown digest %s\n",
329                                                         *args);
330                                 goto argerr;
331                                 }
332                         }
333                 else if (!strcmp (*args, "-inkey"))
334                         {
335                         if (!args[1])   
336                                 goto argerr;
337                         /* If previous -inkey arument add signer to list */
338                         if (keyfile)
339                                 {
340                                 if (!signerfile)
341                                         {
342                                         BIO_puts(bio_err, "Illegal -inkey without -signer\n");
343                                         goto argerr;
344                                         }
345                                 if (!sksigners)
346                                         sksigners = sk_new_null();
347                                 sk_push(sksigners, signerfile);
348                                 signerfile = NULL;
349                                 if (!skkeys)
350                                         skkeys = sk_new_null();
351                                 sk_push(skkeys, keyfile);
352                                 }
353                         keyfile = *++args;
354                         }
355                 else if (!strcmp (*args, "-keyform"))
356                         {
357                         if (!args[1])
358                                 goto argerr;
359                         keyform = str2fmt(*++args);
360                         }
361                 else if (!strcmp (*args, "-certfile"))
362                         {
363                         if (!args[1])
364                                 goto argerr;
365                         certfile = *++args;
366                         }
367                 else if (!strcmp (*args, "-CAfile"))
368                         {
369                         if (!args[1])
370                                 goto argerr;
371                         CAfile = *++args;
372                         }
373                 else if (!strcmp (*args, "-CApath"))
374                         {
375                         if (!args[1])
376                                 goto argerr;
377                         CApath = *++args;
378                         }
379                 else if (!strcmp (*args, "-in"))
380                         {
381                         if (!args[1])
382                                 goto argerr;
383                         infile = *++args;
384                         }
385                 else if (!strcmp (*args, "-inform"))
386                         {
387                         if (!args[1])
388                                 goto argerr;
389                         informat = str2fmt(*++args);
390                         }
391                 else if (!strcmp (*args, "-outform"))
392                         {
393                         if (!args[1])
394                                 goto argerr;
395                         outformat = str2fmt(*++args);
396                         }
397                 else if (!strcmp (*args, "-out"))
398                         {
399                         if (!args[1])
400                                 goto argerr;
401                         outfile = *++args;
402                         }
403                 else if (!strcmp (*args, "-content"))
404                         {
405                         if (!args[1])
406                                 goto argerr;
407                         contfile = *++args;
408                         }
409                 else if (args_verify(&args, NULL, &badarg, bio_err, &vpm))
410                         continue;
411                 else if ((cipher = EVP_get_cipherbyname(*args + 1)) == NULL)
412                         badarg = 1;
413                 args++;
414                 }
415
416         if (!(operation & SMIME_SIGNERS) && (skkeys || sksigners))
417                 {
418                 BIO_puts(bio_err, "Multiple signers or keys not allowed\n");
419                 goto argerr;
420                 }
421
422         if (operation & SMIME_SIGNERS)
423                 {
424                 /* Check to see if any final signer needs to be appended */
425                 if (keyfile && !signerfile)
426                         {
427                         BIO_puts(bio_err, "Illegal -inkey without -signer\n");
428                         goto argerr;
429                         }
430                 if (signerfile)
431                         {
432                         if (!sksigners)
433                                 sksigners = sk_new_null();
434                         sk_push(sksigners, signerfile);
435                         if (!skkeys)
436                                 skkeys = sk_new_null();
437                         if (!keyfile)
438                                 keyfile = signerfile;
439                         sk_push(skkeys, keyfile);
440                         }
441                 if (!sksigners)
442                         {
443                         BIO_printf(bio_err, "No signer certificate specified\n");
444                         badarg = 1;
445                         }
446                 signerfile = NULL;
447                 keyfile = NULL;
448                 need_rand = 1;
449                 }
450         else if (operation == SMIME_DECRYPT)
451                 {
452                 if (!recipfile && !keyfile)
453                         {
454                         BIO_printf(bio_err, "No recipient certificate or key specified\n");
455                         badarg = 1;
456                         }
457                 }
458         else if (operation == SMIME_ENCRYPT)
459                 {
460                 if (!*args)
461                         {
462                         BIO_printf(bio_err, "No recipient(s) certificate(s) specified\n");
463                         badarg = 1;
464                         }
465                 need_rand = 1;
466                 }
467         else if (!operation)
468                 badarg = 1;
469
470         if (badarg)
471                 {
472                 argerr:
473                 BIO_printf (bio_err, "Usage smime [options] cert.pem ...\n");
474                 BIO_printf (bio_err, "where options are\n");
475                 BIO_printf (bio_err, "-encrypt       encrypt message\n");
476                 BIO_printf (bio_err, "-decrypt       decrypt encrypted message\n");
477                 BIO_printf (bio_err, "-sign          sign message\n");
478                 BIO_printf (bio_err, "-verify        verify signed message\n");
479                 BIO_printf (bio_err, "-cmsout        output CMS structure\n");
480 #ifndef OPENSSL_NO_DES
481                 BIO_printf (bio_err, "-des3          encrypt with triple DES\n");
482                 BIO_printf (bio_err, "-des           encrypt with DES\n");
483 #endif
484 #ifndef OPENSSL_NO_SEED
485                 BIO_printf (bio_err, "-seed          encrypt with SEED\n");
486 #endif
487 #ifndef OPENSSL_NO_RC2
488                 BIO_printf (bio_err, "-rc2-40        encrypt with RC2-40 (default)\n");
489                 BIO_printf (bio_err, "-rc2-64        encrypt with RC2-64\n");
490                 BIO_printf (bio_err, "-rc2-128       encrypt with RC2-128\n");
491 #endif
492 #ifndef OPENSSL_NO_AES
493                 BIO_printf (bio_err, "-aes128, -aes192, -aes256\n");
494                 BIO_printf (bio_err, "               encrypt PEM output with cbc aes\n");
495 #endif
496 #ifndef OPENSSL_NO_CAMELLIA
497                 BIO_printf (bio_err, "-camellia128, -camellia192, -camellia256\n");
498                 BIO_printf (bio_err, "               encrypt PEM output with cbc camellia\n");
499 #endif
500                 BIO_printf (bio_err, "-nointern      don't search certificates in message for signer\n");
501                 BIO_printf (bio_err, "-nosigs        don't verify message signature\n");
502                 BIO_printf (bio_err, "-noverify      don't verify signers certificate\n");
503                 BIO_printf (bio_err, "-nocerts       don't include signers certificate when signing\n");
504                 BIO_printf (bio_err, "-nodetach      use opaque signing\n");
505                 BIO_printf (bio_err, "-noattr        don't include any signed attributes\n");
506                 BIO_printf (bio_err, "-binary        don't translate message to text\n");
507                 BIO_printf (bio_err, "-certfile file other certificates file\n");
508                 BIO_printf (bio_err, "-signer file   signer certificate file\n");
509                 BIO_printf (bio_err, "-recip  file   recipient certificate file for decryption\n");
510                 BIO_printf (bio_err, "-skeyid        use subject key identifier\n");
511                 BIO_printf (bio_err, "-in file       input file\n");
512                 BIO_printf (bio_err, "-inform arg    input format SMIME (default), PEM or DER\n");
513                 BIO_printf (bio_err, "-inkey file    input private key (if not signer or recipient)\n");
514                 BIO_printf (bio_err, "-keyform arg   input private key format (PEM or ENGINE)\n");
515                 BIO_printf (bio_err, "-out file      output file\n");
516                 BIO_printf (bio_err, "-outform arg   output format SMIME (default), PEM or DER\n");
517                 BIO_printf (bio_err, "-content file  supply or override content for detached signature\n");
518                 BIO_printf (bio_err, "-to addr       to address\n");
519                 BIO_printf (bio_err, "-from ad       from address\n");
520                 BIO_printf (bio_err, "-subject s     subject\n");
521                 BIO_printf (bio_err, "-text          include or delete text MIME headers\n");
522                 BIO_printf (bio_err, "-CApath dir    trusted certificates directory\n");
523                 BIO_printf (bio_err, "-CAfile file   trusted certificates file\n");
524                 BIO_printf (bio_err, "-crl_check     check revocation status of signer's certificate using CRLs\n");
525                 BIO_printf (bio_err, "-crl_check_all check revocation status of signer's certificate chain using CRLs\n");
526 #ifndef OPENSSL_NO_ENGINE
527                 BIO_printf (bio_err, "-engine e      use engine e, possibly a hardware device.\n");
528 #endif
529                 BIO_printf (bio_err, "-passin arg    input file pass phrase source\n");
530                 BIO_printf(bio_err,  "-rand file%cfile%c...\n", LIST_SEPARATOR_CHAR, LIST_SEPARATOR_CHAR);
531                 BIO_printf(bio_err,  "               load the file (or the files in the directory) into\n");
532                 BIO_printf(bio_err,  "               the random number generator\n");
533                 BIO_printf (bio_err, "cert.pem       recipient certificate(s) for encryption\n");
534                 goto end;
535                 }
536
537 #ifndef OPENSSL_NO_ENGINE
538         e = setup_engine(bio_err, engine, 0);
539 #endif
540
541         if (!app_passwd(bio_err, passargin, NULL, &passin, NULL))
542                 {
543                 BIO_printf(bio_err, "Error getting password\n");
544                 goto end;
545                 }
546
547         if (need_rand)
548                 {
549                 app_RAND_load_file(NULL, bio_err, (inrand != NULL));
550                 if (inrand != NULL)
551                         BIO_printf(bio_err,"%ld semi-random bytes loaded\n",
552                                 app_RAND_load_files(inrand));
553                 }
554
555         ret = 2;
556
557         if (!(operation & SMIME_SIGNERS))
558                 flags &= ~CMS_DETACHED;
559
560         if (operation & SMIME_OP)
561                 {
562                 if (outformat == FORMAT_ASN1)
563                         outmode = "wb";
564                 }
565         else
566                 {
567                 if (flags & CMS_BINARY)
568                         outmode = "wb";
569                 }
570
571         if (operation & SMIME_IP)
572                 {
573                 if (informat == FORMAT_ASN1)
574                         inmode = "rb";
575                 }
576         else
577                 {
578                 if (flags & CMS_BINARY)
579                         inmode = "rb";
580                 }
581
582         if (operation == SMIME_ENCRYPT)
583                 {
584                 if (!cipher)
585                         {
586 #ifndef OPENSSL_NO_RC2                  
587                         cipher = EVP_rc2_40_cbc();
588 #else
589                         BIO_printf(bio_err, "No cipher selected\n");
590                         goto end;
591 #endif
592                         }
593                 encerts = sk_X509_new_null();
594                 while (*args)
595                         {
596                         if (!(cert = load_cert(bio_err,*args,FORMAT_PEM,
597                                 NULL, e, "recipient certificate file")))
598                                 {
599 #if 0                           /* An appropriate message is already printed */
600                                 BIO_printf(bio_err, "Can't read recipient certificate file %s\n", *args);
601 #endif
602                                 goto end;
603                                 }
604                         sk_X509_push(encerts, cert);
605                         cert = NULL;
606                         args++;
607                         }
608                 }
609
610         if (certfile)
611                 {
612                 if (!(other = load_certs(bio_err,certfile,FORMAT_PEM, NULL,
613                         e, "certificate file")))
614                         {
615                         ERR_print_errors(bio_err);
616                         goto end;
617                         }
618                 }
619
620         if (recipfile && (operation == SMIME_DECRYPT))
621                 {
622                 if (!(recip = load_cert(bio_err,recipfile,FORMAT_PEM,NULL,
623                         e, "recipient certificate file")))
624                         {
625                         ERR_print_errors(bio_err);
626                         goto end;
627                         }
628                 }
629
630         if (operation == SMIME_DECRYPT)
631                 {
632                 if (!keyfile)
633                         keyfile = recipfile;
634                 }
635         else if (operation == SMIME_SIGN)
636                 {
637                 if (!keyfile)
638                         keyfile = signerfile;
639                 }
640         else keyfile = NULL;
641
642         if (keyfile)
643                 {
644                 key = load_key(bio_err, keyfile, keyform, 0, passin, e,
645                                "signing key file");
646                 if (!key)
647                         goto end;
648                 }
649
650         if (infile)
651                 {
652                 if (!(in = BIO_new_file(infile, inmode)))
653                         {
654                         BIO_printf (bio_err,
655                                  "Can't open input file %s\n", infile);
656                         goto end;
657                         }
658                 }
659         else
660                 in = BIO_new_fp(stdin, BIO_NOCLOSE);
661
662         if (operation & SMIME_IP)
663                 {
664                 if (informat == FORMAT_SMIME) 
665                         cms = SMIME_read_CMS(in, &indata);
666                 else if (informat == FORMAT_PEM) 
667                         cms = PEM_read_bio_CMS(in, NULL, NULL, NULL);
668                 else if (informat == FORMAT_ASN1) 
669                         cms = d2i_CMS_bio(in, NULL);
670                 else
671                         {
672                         BIO_printf(bio_err, "Bad input format for CMS file\n");
673                         goto end;
674                         }
675
676                 if (!cms)
677                         {
678                         BIO_printf(bio_err, "Error reading S/MIME message\n");
679                         goto end;
680                         }
681                 if (contfile)
682                         {
683                         BIO_free(indata);
684                         if (!(indata = BIO_new_file(contfile, "rb")))
685                                 {
686                                 BIO_printf(bio_err, "Can't read content file %s\n", contfile);
687                                 goto end;
688                                 }
689                         }
690                 }
691
692         if (outfile)
693                 {
694                 if (!(out = BIO_new_file(outfile, outmode)))
695                         {
696                         BIO_printf (bio_err,
697                                  "Can't open output file %s\n", outfile);
698                         goto end;
699                         }
700                 }
701         else
702                 {
703                 out = BIO_new_fp(stdout, BIO_NOCLOSE);
704 #ifdef OPENSSL_SYS_VMS
705                 {
706                     BIO *tmpbio = BIO_new(BIO_f_linebuffer());
707                     out = BIO_push(tmpbio, out);
708                 }
709 #endif
710                 }
711
712         if (operation == SMIME_VERIFY)
713                 {
714                 if (!(store = setup_verify(bio_err, CAfile, CApath)))
715                         goto end;
716                 X509_STORE_set_verify_cb_func(store, smime_cb);
717                 if (vpm)
718                         X509_STORE_set1_param(store, vpm);
719                 }
720
721
722         ret = 3;
723
724         if (operation == SMIME_DATA_CREATE)
725                 {
726                 if (indef)
727                         flags |= CMS_STREAM;
728                 cms = CMS_data_create(in, flags);
729                 }
730         else if (operation == SMIME_DIGEST_CREATE)
731                 {
732                 if (indef)
733                         flags |= CMS_STREAM;
734                 cms = CMS_digest_create(in, sign_md, flags);
735                 }
736         else if (operation == SMIME_COMPRESS)
737                 {
738                 if (indef)
739                         flags |= CMS_STREAM;
740                 cms = CMS_compress(in, -1, flags);
741                 }
742         else if (operation == SMIME_ENCRYPT)
743                 {
744                 if (indef)
745                         flags |= CMS_STREAM;
746                 cms = CMS_encrypt(encerts, in, cipher, flags);
747                 }
748         else if (operation & SMIME_SIGNERS)
749                 {
750                 int i;
751                 /* If detached data content we only enable streaming if
752                  * S/MIME output format.
753                  */
754                 if (operation == SMIME_SIGN)
755                         {
756                         if (flags & CMS_DETACHED)
757                                 {
758                                 if (outformat == FORMAT_SMIME)
759                                         flags |= CMS_STREAM;
760                                 }
761                         else if (indef)
762                                 flags |= CMS_STREAM;
763                         flags |= CMS_PARTIAL;
764                         cms = CMS_sign(NULL, NULL, other, in, flags);
765                         if (!cms)
766                                 goto end;
767                         }
768                 else
769                         flags |= CMS_REUSE_DIGEST;
770                 for (i = 0; i < sk_num(sksigners); i++)
771                         {
772                         signerfile = sk_value(sksigners, i);
773                         keyfile = sk_value(skkeys, i);
774                         signer = load_cert(bio_err, signerfile,FORMAT_PEM, NULL,
775                                         e, "signer certificate");
776                         if (!signer)
777                                 goto end;
778                         key = load_key(bio_err, keyfile, keyform, 0, passin, e,
779                                "signing key file");
780                         if (!key)
781                                 goto end;
782                         if (!CMS_add1_signer(cms, signer, key, sign_md, flags))
783                                 goto end;
784                         X509_free(signer);
785                         signer = NULL;
786                         EVP_PKEY_free(key);
787                         key = NULL;
788                         }
789                 /* If not streaming or resigning finalize structure */
790                 if ((operation == SMIME_SIGN) && !(flags & CMS_STREAM))
791                         {
792                         if (!CMS_final(cms, in, flags))
793                                 goto end;
794                         }
795                 }
796
797         if (!cms)
798                 {
799                 BIO_printf(bio_err, "Error creating CMS structure\n");
800                 goto end;
801                 }
802
803         ret = 4;
804         if (operation == SMIME_DECRYPT)
805                 {
806                 if (!CMS_decrypt(cms, key, recip, out, flags))
807                         {
808                         BIO_printf(bio_err, "Error decrypting CMS structure\n");
809                         goto end;
810                         }
811                 }
812         else if (operation == SMIME_DATAOUT)
813                 {
814                 if (!CMS_data(cms, out, flags))
815                         goto end;
816                 }
817         else if (operation == SMIME_UNCOMPRESS)
818                 {
819                 if (!CMS_uncompress(cms, indata, out, flags))
820                         goto end;
821                 }
822         else if (operation == SMIME_DIGEST_VERIFY)
823                 {
824                 if (CMS_digest_verify(cms, indata, out, flags) > 0)
825                         BIO_printf(bio_err, "Verification successful\n");
826                 else
827                         {
828                         BIO_printf(bio_err, "Verification failure\n");
829                         goto end;
830                         }
831                 }
832         else if (operation == SMIME_ENCRYPTED_DECRYPT)
833                 {
834                 if (!CMS_EncryptedData_decrypt(cms, secret_key, secret_keylen,
835                                                 indata, out, flags))
836                         goto end;
837                 }
838         else if (operation == SMIME_VERIFY)
839                 {
840                 if (CMS_verify(cms, other, store, indata, out, flags) > 0)
841                         BIO_printf(bio_err, "Verification successful\n");
842                 else
843                         {
844                         BIO_printf(bio_err, "Verification failure\n");
845                         goto end;
846                         }
847                 if (signerfile)
848                         {
849                         STACK_OF(X509) *signers;
850                         signers = CMS_get0_signers(cms);
851                         if (!save_certs(signerfile, signers))
852                                 {
853                                 BIO_printf(bio_err,
854                                                 "Error writing signers to %s\n",
855                                                                 signerfile);
856                                 ret = 5;
857                                 goto end;
858                                 }
859                         sk_X509_free(signers);
860                         }
861                 }
862         else
863                 {
864                 if (outformat == FORMAT_SMIME) 
865                         {
866                         if (to)
867                                 BIO_printf(out, "To: %s\n", to);
868                         if (from)
869                                 BIO_printf(out, "From: %s\n", from);
870                         if (subject)
871                                 BIO_printf(out, "Subject: %s\n", subject);
872                         if (operation == SMIME_RESIGN)
873                                 ret = SMIME_write_CMS(out, cms, indata, flags);
874                         else
875                                 ret = SMIME_write_CMS(out, cms, in, flags);
876                         }
877                 else if (outformat == FORMAT_PEM) 
878                         ret = PEM_write_bio_CMS_stream(out, cms, in, flags);
879                 else if (outformat == FORMAT_ASN1) 
880                         ret = i2d_CMS_bio_stream(out,cms, in, flags);
881                 else
882                         {
883                         BIO_printf(bio_err, "Bad output format for CMS file\n");
884                         goto end;
885                         }
886                 if (ret <= 0)
887                         {
888                         ret = 6;
889                         goto end;
890                         }
891                 }
892         ret = 0;
893 end:
894         if (ret)
895                 ERR_print_errors(bio_err);
896         if (need_rand)
897                 app_RAND_write_file(NULL, bio_err);
898         sk_X509_pop_free(encerts, X509_free);
899         sk_X509_pop_free(other, X509_free);
900         if (vpm)
901                 X509_VERIFY_PARAM_free(vpm);
902         if (sksigners)
903                 sk_free(sksigners);
904         if (skkeys)
905                 sk_free(skkeys);
906         if (secret_key)
907                 OPENSSL_free(secret_key);
908         X509_STORE_free(store);
909         X509_free(cert);
910         X509_free(recip);
911         X509_free(signer);
912         EVP_PKEY_free(key);
913         CMS_ContentInfo_free(cms);
914         BIO_free(in);
915         BIO_free(indata);
916         BIO_free_all(out);
917         if (passin) OPENSSL_free(passin);
918         return (ret);
919 }
920
921 static int save_certs(char *signerfile, STACK_OF(X509) *signers)
922         {
923         int i;
924         BIO *tmp;
925         if (!signerfile)
926                 return 1;
927         tmp = BIO_new_file(signerfile, "w");
928         if (!tmp) return 0;
929         for(i = 0; i < sk_X509_num(signers); i++)
930                 PEM_write_bio_X509(tmp, sk_X509_value(signers, i));
931         BIO_free(tmp);
932         return 1;
933         }
934         
935
936 /* Minimal callback just to output policy info (if any) */
937
938 static int smime_cb(int ok, X509_STORE_CTX *ctx)
939         {
940         int error;
941
942         error = X509_STORE_CTX_get_error(ctx);
943
944         if ((error != X509_V_ERR_NO_EXPLICIT_POLICY)
945                 && ((error != X509_V_OK) || (ok != 2)))
946                 return ok;
947
948         policies_print(NULL, ctx);
949
950         return ok;
951
952         }
953
954 #endif