There was a need to support thread ID types that couldn't be reliably cast
[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 static void receipt_request_print(BIO *out, CMS_ContentInfo *cms);
74 static CMS_ReceiptRequest *make_receipt_request(STACK *rr_to, int rr_allorfirst,
75                                                                 STACK *rr_from);
76
77 #define SMIME_OP        0x10
78 #define SMIME_IP        0x20
79 #define SMIME_SIGNERS   0x40
80 #define SMIME_ENCRYPT           (1 | SMIME_OP)
81 #define SMIME_DECRYPT           (2 | SMIME_IP)
82 #define SMIME_SIGN              (3 | SMIME_OP | SMIME_SIGNERS)
83 #define SMIME_VERIFY            (4 | SMIME_IP)
84 #define SMIME_CMSOUT            (5 | SMIME_IP | SMIME_OP)
85 #define SMIME_RESIGN            (6 | SMIME_IP | SMIME_OP | SMIME_SIGNERS)
86 #define SMIME_DATAOUT           (7 | SMIME_IP)
87 #define SMIME_DATA_CREATE       (8 | SMIME_OP)
88 #define SMIME_DIGEST_VERIFY     (9 | SMIME_IP)
89 #define SMIME_DIGEST_CREATE     (10 | SMIME_OP)
90 #define SMIME_UNCOMPRESS        (11 | SMIME_IP)
91 #define SMIME_COMPRESS          (12 | SMIME_OP)
92 #define SMIME_ENCRYPTED_DECRYPT (13 | SMIME_IP)
93 #define SMIME_ENCRYPTED_ENCRYPT (14 | SMIME_OP)
94
95 int MAIN(int, char **);
96
97 int MAIN(int argc, char **argv)
98         {
99         ENGINE *e = NULL;
100         int operation = 0;
101         int ret = 0;
102         char **args;
103         const char *inmode = "r", *outmode = "w";
104         char *infile = NULL, *outfile = NULL;
105         char *signerfile = NULL, *recipfile = NULL;
106         STACK *sksigners = NULL, *skkeys = NULL;
107         char *certfile = NULL, *keyfile = NULL, *contfile=NULL;
108         const EVP_CIPHER *cipher = NULL;
109         CMS_ContentInfo *cms = NULL;
110         X509_STORE *store = NULL;
111         X509 *cert = NULL, *recip = NULL, *signer = NULL;
112         EVP_PKEY *key = NULL;
113         STACK_OF(X509) *encerts = NULL, *other = NULL;
114         BIO *in = NULL, *out = NULL, *indata = NULL;
115         int badarg = 0;
116         int flags = CMS_DETACHED, noout = 0, print = 0;
117         int rr_print = 0, rr_allorfirst = -1;
118         STACK *rr_to = NULL, *rr_from = NULL;
119         CMS_ReceiptRequest *rr = NULL;
120         char *to = NULL, *from = NULL, *subject = NULL;
121         char *CAfile = NULL, *CApath = NULL;
122         char *passargin = NULL, *passin = NULL;
123         char *inrand = NULL;
124         int need_rand = 0;
125         const EVP_MD *sign_md = NULL;
126         int informat = FORMAT_SMIME, outformat = FORMAT_SMIME;
127         int keyform = FORMAT_PEM;
128 #ifndef OPENSSL_NO_ENGINE
129         char *engine=NULL;
130 #endif
131         unsigned char *secret_key = NULL, *secret_keyid = NULL;
132         size_t secret_keylen = 0, secret_keyidlen = 0;
133
134         ASN1_OBJECT *econtent_type = NULL;
135
136         X509_VERIFY_PARAM *vpm = NULL;
137
138         args = argv + 1;
139         ret = 1;
140
141         apps_startup();
142
143         if (bio_err == NULL)
144                 {
145                 if ((bio_err = BIO_new(BIO_s_file())) != NULL)
146                         BIO_set_fp(bio_err, stderr, BIO_NOCLOSE|BIO_FP_TEXT);
147                 }
148
149         if (!load_config(bio_err, NULL))
150                 goto end;
151
152         while (!badarg && *args && *args[0] == '-')
153                 {
154                 if (!strcmp (*args, "-encrypt"))
155                         operation = SMIME_ENCRYPT;
156                 else if (!strcmp (*args, "-decrypt"))
157                         operation = SMIME_DECRYPT;
158                 else if (!strcmp (*args, "-sign"))
159                         operation = SMIME_SIGN;
160                 else if (!strcmp (*args, "-resign"))
161                         operation = SMIME_RESIGN;
162                 else if (!strcmp (*args, "-verify"))
163                         operation = SMIME_VERIFY;
164                 else if (!strcmp (*args, "-cmsout"))
165                         operation = SMIME_CMSOUT;
166                 else if (!strcmp (*args, "-data_out"))
167                         operation = SMIME_DATAOUT;
168                 else if (!strcmp (*args, "-data_create"))
169                         operation = SMIME_DATA_CREATE;
170                 else if (!strcmp (*args, "-digest_verify"))
171                         operation = SMIME_DIGEST_VERIFY;
172                 else if (!strcmp (*args, "-digest_create"))
173                         operation = SMIME_DIGEST_CREATE;
174                 else if (!strcmp (*args, "-compress"))
175                         operation = SMIME_COMPRESS;
176                 else if (!strcmp (*args, "-uncompress"))
177                         operation = SMIME_UNCOMPRESS;
178                 else if (!strcmp (*args, "-EncryptedData_decrypt"))
179                         operation = SMIME_ENCRYPTED_DECRYPT;
180                 else if (!strcmp (*args, "-EncryptedData_encrypt"))
181                         operation = SMIME_ENCRYPTED_ENCRYPT;
182 #ifndef OPENSSL_NO_DES
183                 else if (!strcmp (*args, "-des3")) 
184                                 cipher = EVP_des_ede3_cbc();
185                 else if (!strcmp (*args, "-des")) 
186                                 cipher = EVP_des_cbc();
187 #endif
188 #ifndef OPENSSL_NO_SEED
189                 else if (!strcmp (*args, "-seed")) 
190                                 cipher = EVP_seed_cbc();
191 #endif
192 #ifndef OPENSSL_NO_RC2
193                 else if (!strcmp (*args, "-rc2-40")) 
194                                 cipher = EVP_rc2_40_cbc();
195                 else if (!strcmp (*args, "-rc2-128")) 
196                                 cipher = EVP_rc2_cbc();
197                 else if (!strcmp (*args, "-rc2-64")) 
198                                 cipher = EVP_rc2_64_cbc();
199 #endif
200 #ifndef OPENSSL_NO_AES
201                 else if (!strcmp(*args,"-aes128"))
202                                 cipher = EVP_aes_128_cbc();
203                 else if (!strcmp(*args,"-aes192"))
204                                 cipher = EVP_aes_192_cbc();
205                 else if (!strcmp(*args,"-aes256"))
206                                 cipher = EVP_aes_256_cbc();
207 #endif
208 #ifndef OPENSSL_NO_CAMELLIA
209                 else if (!strcmp(*args,"-camellia128"))
210                                 cipher = EVP_camellia_128_cbc();
211                 else if (!strcmp(*args,"-camellia192"))
212                                 cipher = EVP_camellia_192_cbc();
213                 else if (!strcmp(*args,"-camellia256"))
214                                 cipher = EVP_camellia_256_cbc();
215 #endif
216                 else if (!strcmp (*args, "-text")) 
217                                 flags |= CMS_TEXT;
218                 else if (!strcmp (*args, "-nointern")) 
219                                 flags |= CMS_NOINTERN;
220                 else if (!strcmp (*args, "-noverify") 
221                         || !strcmp (*args, "-no_signer_cert_verify")) 
222                                 flags |= CMS_NO_SIGNER_CERT_VERIFY;
223                 else if (!strcmp (*args, "-nocerts")) 
224                                 flags |= CMS_NOCERTS;
225                 else if (!strcmp (*args, "-noattr")) 
226                                 flags |= CMS_NOATTR;
227                 else if (!strcmp (*args, "-nodetach")) 
228                                 flags &= ~CMS_DETACHED;
229                 else if (!strcmp (*args, "-nosmimecap"))
230                                 flags |= CMS_NOSMIMECAP;
231                 else if (!strcmp (*args, "-binary"))
232                                 flags |= CMS_BINARY;
233                 else if (!strcmp (*args, "-keyid"))
234                                 flags |= CMS_USE_KEYID;
235                 else if (!strcmp (*args, "-nosigs"))
236                                 flags |= CMS_NOSIGS;
237                 else if (!strcmp (*args, "-no_content_verify"))
238                                 flags |= CMS_NO_CONTENT_VERIFY;
239                 else if (!strcmp (*args, "-no_attr_verify"))
240                                 flags |= CMS_NO_ATTR_VERIFY;
241                 else if (!strcmp (*args, "-stream"))
242                                 flags |= CMS_STREAM;
243                 else if (!strcmp (*args, "-indef"))
244                                 flags |= CMS_STREAM;
245                 else if (!strcmp (*args, "-noindef"))
246                                 flags &= ~CMS_STREAM;
247                 else if (!strcmp (*args, "-nooldmime"))
248                                 flags |= CMS_NOOLDMIMETYPE;
249                 else if (!strcmp (*args, "-crlfeol"))
250                                 flags |= CMS_CRLFEOL;
251                 else if (!strcmp (*args, "-noout"))
252                                 noout = 1;
253                 else if (!strcmp (*args, "-receipt_request_print"))
254                                 rr_print = 1;
255                 else if (!strcmp (*args, "-receipt_request_all"))
256                                 rr_allorfirst = 0;
257                 else if (!strcmp (*args, "-receipt_request_first"))
258                                 rr_allorfirst = 1;
259                 else if (!strcmp(*args,"-receipt_request_from"))
260                         {
261                         if (!args[1])
262                                 goto argerr;
263                         args++;
264                         if (!rr_from)
265                                 rr_from = sk_new_null();
266                         sk_push(rr_from, *args);
267                         }
268                 else if (!strcmp(*args,"-receipt_request_to"))
269                         {
270                         if (!args[1])
271                                 goto argerr;
272                         args++;
273                         if (!rr_to)
274                                 rr_to = sk_new_null();
275                         sk_push(rr_to, *args);
276                         }
277                 else if (!strcmp (*args, "-print"))
278                                 {
279                                 noout = 1;
280                                 print = 1;
281                                 }
282                 else if (!strcmp(*args,"-secretkey"))
283                         {
284                         long ltmp;
285                         if (!args[1])
286                                 goto argerr;
287                         args++;
288                         secret_key = string_to_hex(*args, &ltmp);
289                         if (!secret_key)
290                                 {
291                                 BIO_printf(bio_err, "Invalid key %s\n", *args);
292                                 goto argerr;
293                                 }
294                         secret_keylen = (size_t)ltmp;
295                         }
296                 else if (!strcmp(*args,"-secretkeyid"))
297                         {
298                         long ltmp;
299                         if (!args[1])
300                                 goto argerr;
301                         args++;
302                         secret_keyid = string_to_hex(*args, &ltmp);
303                         if (!secret_keyid)
304                                 {
305                                 BIO_printf(bio_err, "Invalid id %s\n", *args);
306                                 goto argerr;
307                                 }
308                         secret_keyidlen = (size_t)ltmp;
309                         }
310                 else if (!strcmp(*args,"-econtent_type"))
311                         {
312                         if (!args[1])
313                                 goto argerr;
314                         args++;
315                         econtent_type = OBJ_txt2obj(*args, 0);
316                         if (!econtent_type)
317                                 {
318                                 BIO_printf(bio_err, "Invalid OID %s\n", *args);
319                                 goto argerr;
320                                 }
321                         }
322                 else if (!strcmp(*args,"-rand"))
323                         {
324                         if (!args[1])
325                                 goto argerr;
326                         args++;
327                         inrand = *args;
328                         need_rand = 1;
329                         }
330 #ifndef OPENSSL_NO_ENGINE
331                 else if (!strcmp(*args,"-engine"))
332                         {
333                         if (!args[1])
334                                 goto argerr;
335                         engine = *++args;
336                         }
337 #endif
338                 else if (!strcmp(*args,"-passin"))
339                         {
340                         if (!args[1])
341                                 goto argerr;
342                         passargin = *++args;
343                         }
344                 else if (!strcmp (*args, "-to"))
345                         {
346                         if (!args[1])
347                                 goto argerr;
348                         to = *++args;
349                         }
350                 else if (!strcmp (*args, "-from"))
351                         {
352                         if (!args[1])
353                                 goto argerr;
354                         from = *++args;
355                         }
356                 else if (!strcmp (*args, "-subject"))
357                         {
358                         if (!args[1])
359                                 goto argerr;
360                         subject = *++args;
361                         }
362                 else if (!strcmp (*args, "-signer"))
363                         {
364                         if (!args[1])
365                                 goto argerr;
366                         /* If previous -signer argument add signer to list */
367
368                         if (signerfile)
369                                 {
370                                 if (!sksigners)
371                                         sksigners = sk_new_null();
372                                 sk_push(sksigners, signerfile);
373                                 if (!keyfile)
374                                         keyfile = signerfile;
375                                 if (!skkeys)
376                                         skkeys = sk_new_null();
377                                 sk_push(skkeys, keyfile);
378                                 keyfile = NULL;
379                                 }
380                         signerfile = *++args;
381                         }
382                 else if (!strcmp (*args, "-recip"))
383                         {
384                         if (!args[1])
385                                 goto argerr;
386                         recipfile = *++args;
387                         }
388                 else if (!strcmp (*args, "-md"))
389                         {
390                         if (!args[1])
391                                 goto argerr;
392                         sign_md = EVP_get_digestbyname(*++args);
393                         if (sign_md == NULL)
394                                 {
395                                 BIO_printf(bio_err, "Unknown digest %s\n",
396                                                         *args);
397                                 goto argerr;
398                                 }
399                         }
400                 else if (!strcmp (*args, "-inkey"))
401                         {
402                         if (!args[1])   
403                                 goto argerr;
404                         /* If previous -inkey arument add signer to list */
405                         if (keyfile)
406                                 {
407                                 if (!signerfile)
408                                         {
409                                         BIO_puts(bio_err, "Illegal -inkey without -signer\n");
410                                         goto argerr;
411                                         }
412                                 if (!sksigners)
413                                         sksigners = sk_new_null();
414                                 sk_push(sksigners, signerfile);
415                                 signerfile = NULL;
416                                 if (!skkeys)
417                                         skkeys = sk_new_null();
418                                 sk_push(skkeys, keyfile);
419                                 }
420                         keyfile = *++args;
421                         }
422                 else if (!strcmp (*args, "-keyform"))
423                         {
424                         if (!args[1])
425                                 goto argerr;
426                         keyform = str2fmt(*++args);
427                         }
428                 else if (!strcmp (*args, "-certfile"))
429                         {
430                         if (!args[1])
431                                 goto argerr;
432                         certfile = *++args;
433                         }
434                 else if (!strcmp (*args, "-CAfile"))
435                         {
436                         if (!args[1])
437                                 goto argerr;
438                         CAfile = *++args;
439                         }
440                 else if (!strcmp (*args, "-CApath"))
441                         {
442                         if (!args[1])
443                                 goto argerr;
444                         CApath = *++args;
445                         }
446                 else if (!strcmp (*args, "-in"))
447                         {
448                         if (!args[1])
449                                 goto argerr;
450                         infile = *++args;
451                         }
452                 else if (!strcmp (*args, "-inform"))
453                         {
454                         if (!args[1])
455                                 goto argerr;
456                         informat = str2fmt(*++args);
457                         }
458                 else if (!strcmp (*args, "-outform"))
459                         {
460                         if (!args[1])
461                                 goto argerr;
462                         outformat = str2fmt(*++args);
463                         }
464                 else if (!strcmp (*args, "-out"))
465                         {
466                         if (!args[1])
467                                 goto argerr;
468                         outfile = *++args;
469                         }
470                 else if (!strcmp (*args, "-content"))
471                         {
472                         if (!args[1])
473                                 goto argerr;
474                         contfile = *++args;
475                         }
476                 else if (args_verify(&args, NULL, &badarg, bio_err, &vpm))
477                         continue;
478                 else if ((cipher = EVP_get_cipherbyname(*args + 1)) == NULL)
479                         badarg = 1;
480                 args++;
481                 }
482
483         if (((rr_allorfirst != -1) || rr_from) && !rr_to)
484                 {
485                 BIO_puts(bio_err, "No Signed Receipts Recipients\n");
486                 goto argerr;
487                 }
488
489         if (!(operation & SMIME_SIGNERS)  && (rr_to || rr_from))
490                 {
491                 BIO_puts(bio_err, "Signed receipts only allowed with -sign\n");
492                 goto argerr;
493                 }
494         if (!(operation & SMIME_SIGNERS) && (skkeys || sksigners))
495                 {
496                 BIO_puts(bio_err, "Multiple signers or keys not allowed\n");
497                 goto argerr;
498                 }
499
500         if (operation & SMIME_SIGNERS)
501                 {
502                 if (keyfile && !signerfile)
503                         {
504                         BIO_puts(bio_err, "Illegal -inkey without -signer\n");
505                         goto argerr;
506                         }
507                 /* Check to see if any final signer needs to be appended */
508                 if (signerfile)
509                         {
510                         if (!sksigners)
511                                 sksigners = sk_new_null();
512                         sk_push(sksigners, signerfile);
513                         if (!skkeys)
514                                 skkeys = sk_new_null();
515                         if (!keyfile)
516                                 keyfile = signerfile;
517                         sk_push(skkeys, keyfile);
518                         }
519                 if (!sksigners)
520                         {
521                         BIO_printf(bio_err, "No signer certificate specified\n");
522                         badarg = 1;
523                         }
524                 signerfile = NULL;
525                 keyfile = NULL;
526                 need_rand = 1;
527                 }
528         else if (operation == SMIME_DECRYPT)
529                 {
530                 if (!recipfile && !keyfile && !secret_key)
531                         {
532                         BIO_printf(bio_err, "No recipient certificate or key specified\n");
533                         badarg = 1;
534                         }
535                 }
536         else if (operation == SMIME_ENCRYPT)
537                 {
538                 if (!*args && !secret_key)
539                         {
540                         BIO_printf(bio_err, "No recipient(s) certificate(s) specified\n");
541                         badarg = 1;
542                         }
543                 need_rand = 1;
544                 }
545         else if (!operation)
546                 badarg = 1;
547
548         if (badarg)
549                 {
550                 argerr:
551                 BIO_printf (bio_err, "Usage smime [options] cert.pem ...\n");
552                 BIO_printf (bio_err, "where options are\n");
553                 BIO_printf (bio_err, "-encrypt       encrypt message\n");
554                 BIO_printf (bio_err, "-decrypt       decrypt encrypted message\n");
555                 BIO_printf (bio_err, "-sign          sign message\n");
556                 BIO_printf (bio_err, "-verify        verify signed message\n");
557                 BIO_printf (bio_err, "-cmsout        output CMS structure\n");
558 #ifndef OPENSSL_NO_DES
559                 BIO_printf (bio_err, "-des3          encrypt with triple DES\n");
560                 BIO_printf (bio_err, "-des           encrypt with DES\n");
561 #endif
562 #ifndef OPENSSL_NO_SEED
563                 BIO_printf (bio_err, "-seed          encrypt with SEED\n");
564 #endif
565 #ifndef OPENSSL_NO_RC2
566                 BIO_printf (bio_err, "-rc2-40        encrypt with RC2-40 (default)\n");
567                 BIO_printf (bio_err, "-rc2-64        encrypt with RC2-64\n");
568                 BIO_printf (bio_err, "-rc2-128       encrypt with RC2-128\n");
569 #endif
570 #ifndef OPENSSL_NO_AES
571                 BIO_printf (bio_err, "-aes128, -aes192, -aes256\n");
572                 BIO_printf (bio_err, "               encrypt PEM output with cbc aes\n");
573 #endif
574 #ifndef OPENSSL_NO_CAMELLIA
575                 BIO_printf (bio_err, "-camellia128, -camellia192, -camellia256\n");
576                 BIO_printf (bio_err, "               encrypt PEM output with cbc camellia\n");
577 #endif
578                 BIO_printf (bio_err, "-nointern      don't search certificates in message for signer\n");
579                 BIO_printf (bio_err, "-nosigs        don't verify message signature\n");
580                 BIO_printf (bio_err, "-noverify      don't verify signers certificate\n");
581                 BIO_printf (bio_err, "-nocerts       don't include signers certificate when signing\n");
582                 BIO_printf (bio_err, "-nodetach      use opaque signing\n");
583                 BIO_printf (bio_err, "-noattr        don't include any signed attributes\n");
584                 BIO_printf (bio_err, "-binary        don't translate message to text\n");
585                 BIO_printf (bio_err, "-certfile file other certificates file\n");
586                 BIO_printf (bio_err, "-signer file   signer certificate file\n");
587                 BIO_printf (bio_err, "-recip  file   recipient certificate file for decryption\n");
588                 BIO_printf (bio_err, "-skeyid        use subject key identifier\n");
589                 BIO_printf (bio_err, "-in file       input file\n");
590                 BIO_printf (bio_err, "-inform arg    input format SMIME (default), PEM or DER\n");
591                 BIO_printf (bio_err, "-inkey file    input private key (if not signer or recipient)\n");
592                 BIO_printf (bio_err, "-keyform arg   input private key format (PEM or ENGINE)\n");
593                 BIO_printf (bio_err, "-out file      output file\n");
594                 BIO_printf (bio_err, "-outform arg   output format SMIME (default), PEM or DER\n");
595                 BIO_printf (bio_err, "-content file  supply or override content for detached signature\n");
596                 BIO_printf (bio_err, "-to addr       to address\n");
597                 BIO_printf (bio_err, "-from ad       from address\n");
598                 BIO_printf (bio_err, "-subject s     subject\n");
599                 BIO_printf (bio_err, "-text          include or delete text MIME headers\n");
600                 BIO_printf (bio_err, "-CApath dir    trusted certificates directory\n");
601                 BIO_printf (bio_err, "-CAfile file   trusted certificates file\n");
602                 BIO_printf (bio_err, "-crl_check     check revocation status of signer's certificate using CRLs\n");
603                 BIO_printf (bio_err, "-crl_check_all check revocation status of signer's certificate chain using CRLs\n");
604 #ifndef OPENSSL_NO_ENGINE
605                 BIO_printf (bio_err, "-engine e      use engine e, possibly a hardware device.\n");
606 #endif
607                 BIO_printf (bio_err, "-passin arg    input file pass phrase source\n");
608                 BIO_printf(bio_err,  "-rand file%cfile%c...\n", LIST_SEPARATOR_CHAR, LIST_SEPARATOR_CHAR);
609                 BIO_printf(bio_err,  "               load the file (or the files in the directory) into\n");
610                 BIO_printf(bio_err,  "               the random number generator\n");
611                 BIO_printf (bio_err, "cert.pem       recipient certificate(s) for encryption\n");
612                 goto end;
613                 }
614
615 #ifndef OPENSSL_NO_ENGINE
616         e = setup_engine(bio_err, engine, 0);
617 #endif
618
619         if (!app_passwd(bio_err, passargin, NULL, &passin, NULL))
620                 {
621                 BIO_printf(bio_err, "Error getting password\n");
622                 goto end;
623                 }
624
625         if (need_rand)
626                 {
627                 app_RAND_load_file(NULL, bio_err, (inrand != NULL));
628                 if (inrand != NULL)
629                         BIO_printf(bio_err,"%ld semi-random bytes loaded\n",
630                                 app_RAND_load_files(inrand));
631                 }
632
633         ret = 2;
634
635         if (!(operation & SMIME_SIGNERS))
636                 flags &= ~CMS_DETACHED;
637
638         if (operation & SMIME_OP)
639                 {
640                 if (outformat == FORMAT_ASN1)
641                         outmode = "wb";
642                 }
643         else
644                 {
645                 if (flags & CMS_BINARY)
646                         outmode = "wb";
647                 }
648
649         if (operation & SMIME_IP)
650                 {
651                 if (informat == FORMAT_ASN1)
652                         inmode = "rb";
653                 }
654         else
655                 {
656                 if (flags & CMS_BINARY)
657                         inmode = "rb";
658                 }
659
660         if (operation == SMIME_ENCRYPT)
661                 {
662                 if (!cipher)
663                         {
664 #ifndef OPENSSL_NO_DES                  
665                         cipher = EVP_des_ede3_cbc();
666 #else
667                         BIO_printf(bio_err, "No cipher selected\n");
668                         goto end;
669 #endif
670                         }
671
672                 if (secret_key && !secret_keyid)
673                         {
674                         BIO_printf(bio_err, "No sectre key id\n");
675                         goto end;
676                         }
677
678                 if (*args)
679                         encerts = sk_X509_new_null();
680                 while (*args)
681                         {
682                         if (!(cert = load_cert(bio_err,*args,FORMAT_PEM,
683                                 NULL, e, "recipient certificate file")))
684                                 goto end;
685                         sk_X509_push(encerts, cert);
686                         cert = NULL;
687                         args++;
688                         }
689                 }
690
691         if (certfile)
692                 {
693                 if (!(other = load_certs(bio_err,certfile,FORMAT_PEM, NULL,
694                         e, "certificate file")))
695                         {
696                         ERR_print_errors(bio_err);
697                         goto end;
698                         }
699                 }
700
701         if (recipfile && (operation == SMIME_DECRYPT))
702                 {
703                 if (!(recip = load_cert(bio_err,recipfile,FORMAT_PEM,NULL,
704                         e, "recipient certificate file")))
705                         {
706                         ERR_print_errors(bio_err);
707                         goto end;
708                         }
709                 }
710
711         if (operation == SMIME_DECRYPT)
712                 {
713                 if (!keyfile)
714                         keyfile = recipfile;
715                 }
716         else if (operation == SMIME_SIGN)
717                 {
718                 if (!keyfile)
719                         keyfile = signerfile;
720                 }
721         else keyfile = NULL;
722
723         if (keyfile)
724                 {
725                 key = load_key(bio_err, keyfile, keyform, 0, passin, e,
726                                "signing key file");
727                 if (!key)
728                         goto end;
729                 }
730
731         if (infile)
732                 {
733                 if (!(in = BIO_new_file(infile, inmode)))
734                         {
735                         BIO_printf (bio_err,
736                                  "Can't open input file %s\n", infile);
737                         goto end;
738                         }
739                 }
740         else
741                 in = BIO_new_fp(stdin, BIO_NOCLOSE);
742
743         if (operation & SMIME_IP)
744                 {
745                 if (informat == FORMAT_SMIME) 
746                         cms = SMIME_read_CMS(in, &indata);
747                 else if (informat == FORMAT_PEM) 
748                         cms = PEM_read_bio_CMS(in, NULL, NULL, NULL);
749                 else if (informat == FORMAT_ASN1) 
750                         cms = d2i_CMS_bio(in, NULL);
751                 else
752                         {
753                         BIO_printf(bio_err, "Bad input format for CMS file\n");
754                         goto end;
755                         }
756
757                 if (!cms)
758                         {
759                         BIO_printf(bio_err, "Error reading S/MIME message\n");
760                         goto end;
761                         }
762                 if (contfile)
763                         {
764                         BIO_free(indata);
765                         if (!(indata = BIO_new_file(contfile, "rb")))
766                                 {
767                                 BIO_printf(bio_err, "Can't read content file %s\n", contfile);
768                                 goto end;
769                                 }
770                         }
771                 }
772
773         if (outfile)
774                 {
775                 if (!(out = BIO_new_file(outfile, outmode)))
776                         {
777                         BIO_printf (bio_err,
778                                  "Can't open output file %s\n", outfile);
779                         goto end;
780                         }
781                 }
782         else
783                 {
784                 out = BIO_new_fp(stdout, BIO_NOCLOSE);
785 #ifdef OPENSSL_SYS_VMS
786                 {
787                     BIO *tmpbio = BIO_new(BIO_f_linebuffer());
788                     out = BIO_push(tmpbio, out);
789                 }
790 #endif
791                 }
792
793         if (operation == SMIME_VERIFY)
794                 {
795                 if (!(store = setup_verify(bio_err, CAfile, CApath)))
796                         goto end;
797                 X509_STORE_set_verify_cb_func(store, smime_cb);
798                 if (vpm)
799                         X509_STORE_set1_param(store, vpm);
800                 }
801
802
803         ret = 3;
804
805         if (operation == SMIME_DATA_CREATE)
806                 {
807                 cms = CMS_data_create(in, flags);
808                 }
809         else if (operation == SMIME_DIGEST_CREATE)
810                 {
811                 cms = CMS_digest_create(in, sign_md, flags);
812                 }
813         else if (operation == SMIME_COMPRESS)
814                 {
815                 cms = CMS_compress(in, -1, flags);
816                 }
817         else if (operation == SMIME_ENCRYPT)
818                 {
819                 flags |= CMS_PARTIAL;
820                 cms = CMS_encrypt(encerts, in, cipher, flags);
821                 if (!cms)
822                         goto end;
823                 if (secret_key)
824                         {
825                         if (!CMS_add0_recipient_key(cms, NID_undef, 
826                                                 secret_key, secret_keylen,
827                                                 secret_keyid, secret_keyidlen,
828                                                 NULL, NULL, NULL))
829                                 goto end;
830                         /* NULL these because call absorbs them */
831                         secret_key = NULL;
832                         secret_keyid = NULL;
833                         }
834                 if (!(flags & CMS_STREAM))
835                         {
836                         if (!CMS_final(cms, in, flags))
837                                 goto end;
838                         }
839                 }
840         else if (operation == SMIME_ENCRYPTED_ENCRYPT)
841                 {
842                 cms = CMS_EncryptedData_encrypt(in, cipher,
843                                                 secret_key, secret_keylen,
844                                                 flags);
845
846                 }
847         else if (operation & SMIME_SIGNERS)
848                 {
849                 int i;
850                 /* If detached data content we enable streaming if
851                  * S/MIME output format.
852                  */
853                 if (operation == SMIME_SIGN)
854                         {
855                                 
856                         if (flags & CMS_DETACHED)
857                                 {
858                                 if (outformat == FORMAT_SMIME)
859                                         flags |= CMS_STREAM;
860                                 }
861                         flags |= CMS_PARTIAL;
862                         cms = CMS_sign(NULL, NULL, other, in, flags);
863                         if (!cms)
864                                 goto end;
865                         if (econtent_type)
866                                 CMS_set1_eContentType(cms, econtent_type);
867
868                         if (rr_to)
869                                 {
870                                 rr = make_receipt_request(rr_to, rr_allorfirst,
871                                                                 rr_from);
872                                 if (!rr)
873                                         {
874                                         BIO_puts(bio_err,
875                                 "Signed Receipt Request Creation Error\n");
876                                         goto end;
877                                         }
878                                 }
879                         }
880                 else
881                         flags |= CMS_REUSE_DIGEST;
882                 for (i = 0; i < sk_num(sksigners); i++)
883                         {
884                         CMS_SignerInfo *si;
885                         signerfile = sk_value(sksigners, i);
886                         keyfile = sk_value(skkeys, i);
887                         signer = load_cert(bio_err, signerfile,FORMAT_PEM, NULL,
888                                         e, "signer certificate");
889                         if (!signer)
890                                 goto end;
891                         key = load_key(bio_err, keyfile, keyform, 0, passin, e,
892                                "signing key file");
893                         if (!key)
894                                 goto end;
895                         si = CMS_add1_signer(cms, signer, key, sign_md, flags);
896                         if (!si)
897                                 goto end;
898                         if (rr && !CMS_add1_ReceiptRequest(si, rr))
899                                 goto end;
900                         X509_free(signer);
901                         signer = NULL;
902                         EVP_PKEY_free(key);
903                         key = NULL;
904                         }
905                 /* If not streaming or resigning finalize structure */
906                 if ((operation == SMIME_SIGN) && !(flags & CMS_STREAM))
907                         {
908                         if (!CMS_final(cms, in, flags))
909                                 goto end;
910                         }
911                 }
912
913         if (!cms)
914                 {
915                 BIO_printf(bio_err, "Error creating CMS structure\n");
916                 goto end;
917                 }
918
919         ret = 4;
920         if (operation == SMIME_DECRYPT)
921                 {
922
923                 if (secret_key)
924                         {
925                         if (!CMS_decrypt_set1_key(cms,
926                                                 secret_key, secret_keylen,
927                                                 secret_keyid, secret_keyidlen))
928                                 {
929                                 BIO_puts(bio_err,
930                                         "Error decrypting CMS using secret key\n");
931                                 goto end;
932                                 }
933                         }
934
935                 if (key)
936                         {
937                         if (!CMS_decrypt_set1_pkey(cms, key, recip))
938                                 {
939                                 BIO_puts(bio_err,
940                                         "Error decrypting CMS using private key\n");
941                                 goto end;
942                                 }
943                         }
944
945                 if (!CMS_decrypt(cms, NULL, NULL, indata, out, flags))
946                         {
947                         BIO_printf(bio_err, "Error decrypting CMS structure\n");
948                         goto end;
949                         }
950                 }
951         else if (operation == SMIME_DATAOUT)
952                 {
953                 if (!CMS_data(cms, out, flags))
954                         goto end;
955                 }
956         else if (operation == SMIME_UNCOMPRESS)
957                 {
958                 if (!CMS_uncompress(cms, indata, out, flags))
959                         goto end;
960                 }
961         else if (operation == SMIME_DIGEST_VERIFY)
962                 {
963                 if (CMS_digest_verify(cms, indata, out, flags) > 0)
964                         BIO_printf(bio_err, "Verification successful\n");
965                 else
966                         {
967                         BIO_printf(bio_err, "Verification failure\n");
968                         goto end;
969                         }
970                 }
971         else if (operation == SMIME_ENCRYPTED_DECRYPT)
972                 {
973                 if (!CMS_EncryptedData_decrypt(cms, secret_key, secret_keylen,
974                                                 indata, out, flags))
975                         goto end;
976                 }
977         else if (operation == SMIME_VERIFY)
978                 {
979                 if (CMS_verify(cms, other, store, indata, out, flags) > 0)
980                         BIO_printf(bio_err, "Verification successful\n");
981                 else
982                         {
983                         BIO_printf(bio_err, "Verification failure\n");
984                         goto end;
985                         }
986                 if (signerfile)
987                         {
988                         STACK_OF(X509) *signers;
989                         signers = CMS_get0_signers(cms);
990                         if (!save_certs(signerfile, signers))
991                                 {
992                                 BIO_printf(bio_err,
993                                                 "Error writing signers to %s\n",
994                                                                 signerfile);
995                                 ret = 5;
996                                 goto end;
997                                 }
998                         sk_X509_free(signers);
999                         }
1000                 if (rr_print)
1001                         receipt_request_print(bio_err, cms);
1002                                         
1003                 }
1004         else
1005                 {
1006                 if (noout)
1007                         {
1008                         if (print)
1009                                 CMS_ContentInfo_print_ctx(out, cms, 0, NULL);
1010                         }
1011                 else if (outformat == FORMAT_SMIME)
1012                         {
1013                         if (to)
1014                                 BIO_printf(out, "To: %s\n", to);
1015                         if (from)
1016                                 BIO_printf(out, "From: %s\n", from);
1017                         if (subject)
1018                                 BIO_printf(out, "Subject: %s\n", subject);
1019                         if (operation == SMIME_RESIGN)
1020                                 ret = SMIME_write_CMS(out, cms, indata, flags);
1021                         else
1022                                 ret = SMIME_write_CMS(out, cms, in, flags);
1023                         }
1024                 else if (outformat == FORMAT_PEM) 
1025                         ret = PEM_write_bio_CMS_stream(out, cms, in, flags);
1026                 else if (outformat == FORMAT_ASN1) 
1027                         ret = i2d_CMS_bio_stream(out,cms, in, flags);
1028                 else
1029                         {
1030                         BIO_printf(bio_err, "Bad output format for CMS file\n");
1031                         goto end;
1032                         }
1033                 if (ret <= 0)
1034                         {
1035                         ret = 6;
1036                         goto end;
1037                         }
1038                 }
1039         ret = 0;
1040 end:
1041         if (ret)
1042                 ERR_print_errors(bio_err);
1043         if (need_rand)
1044                 app_RAND_write_file(NULL, bio_err);
1045         sk_X509_pop_free(encerts, X509_free);
1046         sk_X509_pop_free(other, X509_free);
1047         if (vpm)
1048                 X509_VERIFY_PARAM_free(vpm);
1049         if (sksigners)
1050                 sk_free(sksigners);
1051         if (skkeys)
1052                 sk_free(skkeys);
1053         if (secret_key)
1054                 OPENSSL_free(secret_key);
1055         if (secret_keyid)
1056                 OPENSSL_free(secret_keyid);
1057         if (econtent_type)
1058                 ASN1_OBJECT_free(econtent_type);
1059         if (rr)
1060                 CMS_ReceiptRequest_free(rr);
1061         if (rr_to)
1062                 sk_free(rr_to);
1063         if (rr_from)
1064                 sk_free(rr_from);
1065         X509_STORE_free(store);
1066         X509_free(cert);
1067         X509_free(recip);
1068         X509_free(signer);
1069         EVP_PKEY_free(key);
1070         CMS_ContentInfo_free(cms);
1071         BIO_free(in);
1072         BIO_free(indata);
1073         BIO_free_all(out);
1074         if (passin) OPENSSL_free(passin);
1075         return (ret);
1076 }
1077
1078 static int save_certs(char *signerfile, STACK_OF(X509) *signers)
1079         {
1080         int i;
1081         BIO *tmp;
1082         if (!signerfile)
1083                 return 1;
1084         tmp = BIO_new_file(signerfile, "w");
1085         if (!tmp) return 0;
1086         for(i = 0; i < sk_X509_num(signers); i++)
1087                 PEM_write_bio_X509(tmp, sk_X509_value(signers, i));
1088         BIO_free(tmp);
1089         return 1;
1090         }
1091         
1092
1093 /* Minimal callback just to output policy info (if any) */
1094
1095 static int smime_cb(int ok, X509_STORE_CTX *ctx)
1096         {
1097         int error;
1098
1099         error = X509_STORE_CTX_get_error(ctx);
1100
1101         if ((error != X509_V_ERR_NO_EXPLICIT_POLICY)
1102                 && ((error != X509_V_OK) || (ok != 2)))
1103                 return ok;
1104
1105         policies_print(NULL, ctx);
1106
1107         return ok;
1108
1109         }
1110
1111 static void gnames_stack_print(BIO *out, STACK_OF(GENERAL_NAMES) *gns)
1112         {
1113         STACK_OF(GENERAL_NAME) *gens;
1114         GENERAL_NAME *gen;
1115         int i, j;
1116         for (i = 0; i < sk_GENERAL_NAMES_num(gns); i++)
1117                 {
1118                 gens = sk_GENERAL_NAMES_value(gns, i);
1119                 for (j = 0; j < sk_GENERAL_NAME_num(gens); j++)
1120                         {
1121                         gen = sk_GENERAL_NAME_value(gens, j);
1122                         BIO_puts(out, "    ");
1123                         GENERAL_NAME_print(out, gen);
1124                         BIO_puts(out, "\n");
1125                         }
1126                 }
1127         return;
1128         }
1129
1130 static void receipt_request_print(BIO *out, CMS_ContentInfo *cms)
1131         {
1132         STACK_OF(CMS_SignerInfo) *sis;
1133         CMS_SignerInfo *si;
1134         CMS_ReceiptRequest *rr;
1135         int allorfirst;
1136         STACK_OF(GENERAL_NAMES) *rto, *rlist;
1137         ASN1_STRING *scid;
1138         int i, rv;
1139         sis = CMS_get0_SignerInfos(cms);
1140         for (i = 0; i < sk_CMS_SignerInfo_num(sis); i++)
1141                 {
1142                 si = sk_CMS_SignerInfo_value(sis, i);
1143                 rv = CMS_get1_ReceiptRequest(si, &rr);
1144                 BIO_printf(bio_err, "Signer %d:\n", i + 1);
1145                 if (rv == 0)
1146                         BIO_puts(bio_err, "  No Receipt Request\n");
1147                 else if (rv < 0)
1148                         {
1149                         BIO_puts(bio_err, "  Receipt Request Parse Error\n");
1150                         ERR_print_errors(bio_err);
1151                         }
1152                 else
1153                         {
1154                         char *id;
1155                         int idlen;
1156                         CMS_ReceiptRequest_get0_values(rr, &scid, &allorfirst,
1157                                                         &rlist, &rto);
1158                         BIO_puts(out, "  Signed Content ID:\n");
1159                         idlen = ASN1_STRING_length(scid);
1160                         id = (char *)ASN1_STRING_data(scid);
1161                         BIO_dump_indent(out, id, idlen, 4);
1162                         BIO_puts(out, "  Receipts From");
1163                         if (rlist)
1164                                 {
1165                                 BIO_puts(out, " List:\n");
1166                                 gnames_stack_print(out, rlist);
1167                                 }
1168                         else if (allorfirst == 1)
1169                                 BIO_puts(out, ": First Tier\n");
1170                         else if (allorfirst == 0)
1171                                 BIO_puts(out, ": All\n");
1172                         else
1173                                 BIO_printf(out, " Unknown (%d)\n", allorfirst);
1174                         BIO_puts(out, "  Receipts To:\n");
1175                         gnames_stack_print(out, rto);
1176                         }
1177                 if (rr)
1178                         CMS_ReceiptRequest_free(rr);
1179                 }
1180         }
1181
1182 static STACK_OF(GENERAL_NAMES) *make_names_stack(STACK *ns)
1183         {
1184         int i;
1185         STACK_OF(GENERAL_NAMES) *ret;
1186         GENERAL_NAMES *gens = NULL;
1187         GENERAL_NAME *gen = NULL;
1188         ret = sk_GENERAL_NAMES_new_null();
1189         if (!ret)
1190                 goto err;
1191         for (i = 0; i < sk_num(ns); i++)
1192                 {
1193                 char *str = sk_value(ns, i);
1194                 gen = a2i_GENERAL_NAME(NULL, NULL, NULL, GEN_EMAIL, str, 0);
1195                 if (!gen)
1196                         goto err;
1197                 gens = GENERAL_NAMES_new();
1198                 if (!gens)
1199                         goto err;
1200                 if (!sk_GENERAL_NAME_push(gens, gen))
1201                         goto err;
1202                 gen = NULL;
1203                 if (!sk_GENERAL_NAMES_push(ret, gens))
1204                         goto err;
1205                 gens = NULL;
1206                 }
1207
1208         return ret;
1209
1210         err:
1211         if (ret)
1212                 sk_GENERAL_NAMES_pop_free(ret, GENERAL_NAMES_free);
1213         if (gens)
1214                 GENERAL_NAMES_free(gens);
1215         if (gen)
1216                 GENERAL_NAME_free(gen);
1217         return NULL;
1218         }
1219
1220
1221 static CMS_ReceiptRequest *make_receipt_request(STACK *rr_to, int rr_allorfirst,
1222                                                                 STACK *rr_from)
1223         {
1224         STACK_OF(GENERAL_NAMES) *rct_to, *rct_from;
1225         CMS_ReceiptRequest *rr;
1226         rct_to = make_names_stack(rr_to);
1227         if (!rct_to)
1228                 goto err;
1229         if (rr_from)
1230                 {
1231                 rct_from = make_names_stack(rr_from);
1232                 if (!rct_from)
1233                         goto err;
1234                 }
1235         else
1236                 rct_from = NULL;
1237         rr = CMS_ReceiptRequest_create0(NULL, -1, rr_allorfirst, rct_from,
1238                                                 rct_to);
1239         return rr;
1240         err:
1241         return NULL;
1242         }
1243
1244 #endif