jcs's openbsd hax
openbsd
1/* $OpenBSD: cms.c,v 1.40 2025/12/20 07:02:37 tb Exp $ */
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
59#include "apps.h"
60
61#ifndef OPENSSL_NO_CMS
62
63#include <openssl/crypto.h>
64#include <openssl/err.h>
65#include <openssl/pem.h>
66#include <openssl/x509_vfy.h>
67#include <openssl/x509v3.h>
68
69#include <openssl/cms.h>
70
71static int save_certs(char *signerfile, STACK_OF(X509) *signers);
72static void receipt_request_print(BIO *out, CMS_ContentInfo *cms);
73static CMS_ReceiptRequest *make_receipt_request(
74 STACK_OF(OPENSSL_STRING) *rr_to, int rr_allorfirst,
75 STACK_OF(OPENSSL_STRING) *rr_from);
76static int cms_set_pkey_param(EVP_PKEY_CTX *pctx,
77 STACK_OF(OPENSSL_STRING) *param);
78
79#define SMIME_OP 0x10
80#define SMIME_IP 0x20
81#define SMIME_SIGNERS 0x40
82#define SMIME_ENCRYPT (1 | SMIME_OP)
83#define SMIME_DECRYPT (2 | SMIME_IP)
84#define SMIME_SIGN (3 | SMIME_OP | SMIME_SIGNERS)
85#define SMIME_VERIFY (4 | SMIME_IP)
86#define SMIME_CMSOUT (5 | SMIME_IP | SMIME_OP)
87#define SMIME_RESIGN (6 | SMIME_IP | SMIME_OP | SMIME_SIGNERS)
88#define SMIME_DATAOUT (7 | SMIME_IP)
89#define SMIME_DATA_CREATE (8 | SMIME_OP)
90#define SMIME_DIGEST_VERIFY (9 | SMIME_IP)
91#define SMIME_DIGEST_CREATE (10 | SMIME_OP)
92#define SMIME_ENCRYPTED_DECRYPT (11 | SMIME_IP)
93#define SMIME_ENCRYPTED_ENCRYPT (12 | SMIME_OP)
94#define SMIME_SIGN_RECEIPT (13 | SMIME_IP | SMIME_OP)
95#define SMIME_VERIFY_RECEIPT (14 | SMIME_IP)
96
97int verify_err = 0;
98
99struct cms_key_param {
100 int idx;
101 STACK_OF(OPENSSL_STRING) *param;
102 struct cms_key_param *next;
103};
104
105static struct {
106 char *CAfile;
107 char *CApath;
108 X509 *cert;
109 char *certfile;
110 char *certsoutfile;
111 char *crlfile;
112 const EVP_CIPHER *cipher;
113 char *contfile;
114 ASN1_OBJECT *econtent_type;
115 STACK_OF(X509) *encerts;
116 int flags;
117 char *from;
118 char *infile;
119 int informat;
120 struct cms_key_param *key_first;
121 struct cms_key_param *key_param;
122 char *keyfile;
123 int keyform;
124 int noout;
125 int operation;
126 char *outfile;
127 int outformat;
128 char *passargin;
129 int print;
130 unsigned char *pwri_pass;
131 int rr_allorfirst;
132 STACK_OF(OPENSSL_STRING) *rr_from;
133 int rr_print;
134 STACK_OF(OPENSSL_STRING) *rr_to;
135 char *rctfile;
136 int rctformat;
137 char *recipfile;
138 unsigned char *secret_key;
139 unsigned char *secret_keyid;
140 size_t secret_keyidlen;
141 size_t secret_keylen;
142 const EVP_MD *sign_md;
143 char *signerfile;
144 STACK_OF(OPENSSL_STRING) *skkeys;
145 STACK_OF(OPENSSL_STRING) *sksigners;
146 char *subject;
147 char *to;
148 int verify_retcode;
149 X509_VERIFY_PARAM *vpm;
150} cfg;
151
152static const EVP_CIPHER *
153get_cipher_by_name(char *name)
154{
155 if (name == NULL || strcmp(name, "") == 0)
156 return (NULL);
157#ifndef OPENSSL_NO_AES
158 else if (strcmp(name, "aes128") == 0)
159 return EVP_aes_128_cbc();
160 else if (strcmp(name, "aes192") == 0)
161 return EVP_aes_192_cbc();
162 else if (strcmp(name, "aes256") == 0)
163 return EVP_aes_256_cbc();
164#endif
165#ifndef OPENSSL_NO_CAMELLIA
166 else if (strcmp(name, "camellia128") == 0)
167 return EVP_camellia_128_cbc();
168 else if (strcmp(name, "camellia192") == 0)
169 return EVP_camellia_192_cbc();
170 else if (strcmp(name, "camellia256") == 0)
171 return EVP_camellia_256_cbc();
172#endif
173#ifndef OPENSSL_NO_DES
174 else if (strcmp(name, "des") == 0)
175 return EVP_des_cbc();
176 else if (strcmp(name, "des3") == 0)
177 return EVP_des_ede3_cbc();
178#endif
179#ifndef OPENSSL_NO_RC2
180 else if (!strcmp(name, "rc2-40"))
181 return EVP_rc2_40_cbc();
182 else if (!strcmp(name, "rc2-64"))
183 return EVP_rc2_64_cbc();
184 else if (!strcmp(name, "rc2-128"))
185 return EVP_rc2_cbc();
186#endif
187 else
188 return (NULL);
189}
190
191static int
192cms_opt_cipher(int argc, char **argv, int *argsused)
193{
194 const EVP_CIPHER *cipher;
195 char *name = argv[0];
196
197 if (*name++ != '-')
198 return (1);
199
200 if ((cipher = get_cipher_by_name(name)) == NULL)
201 if ((cipher = EVP_get_cipherbyname(name)) == NULL)
202 return (1);
203
204 /*
205 * XXX - this should really be done in CMS_{encrypt,decrypt}() until
206 * we have proper support for AuthEnvelopedData (RFC 5084), but this
207 * is good enough for now to avoid outputting garbage with this rusty
208 * swiss army knife.
209 */
210 if ((EVP_CIPHER_flags(cipher) & EVP_CIPH_FLAG_AEAD_CIPHER) != 0) {
211 BIO_printf(bio_err, "AuthEnvelopedData is not supported\n");
212 return (1);
213 }
214 if (EVP_CIPHER_mode(cipher) == EVP_CIPH_XTS_MODE) {
215 BIO_printf(bio_err, "XTS mode not supported\n");
216 return (1);
217 }
218
219 cfg.cipher = cipher;
220
221 *argsused = 1;
222 return (0);
223}
224
225static int
226cms_opt_econtent_type(char *arg)
227{
228 ASN1_OBJECT_free(cfg.econtent_type);
229
230 if ((cfg.econtent_type = OBJ_txt2obj(arg, 0)) == NULL) {
231 BIO_printf(bio_err, "Invalid OID %s\n", arg);
232 return (1);
233 }
234 return (0);
235}
236
237static int
238cms_opt_inkey(char *arg)
239{
240 if (cfg.keyfile == NULL) {
241 cfg.keyfile = arg;
242 return (0);
243 }
244
245 if (cfg.signerfile == NULL) {
246 BIO_puts(bio_err, "Illegal -inkey without -signer\n");
247 return (1);
248 }
249
250 if (cfg.sksigners == NULL)
251 cfg.sksigners = sk_OPENSSL_STRING_new_null();
252 if (cfg.sksigners == NULL)
253 return (1);
254 if (!sk_OPENSSL_STRING_push(cfg.sksigners, cfg.signerfile))
255 return (1);
256
257 cfg.signerfile = NULL;
258
259 if (cfg.skkeys == NULL)
260 cfg.skkeys = sk_OPENSSL_STRING_new_null();
261 if (cfg.skkeys == NULL)
262 return (1);
263 if (!sk_OPENSSL_STRING_push(cfg.skkeys, cfg.keyfile))
264 return (1);
265
266 cfg.keyfile = arg;
267 return (0);
268}
269
270static int
271cms_opt_keyopt(char *arg)
272{
273 int keyidx = -1;
274
275 if (cfg.operation == SMIME_ENCRYPT) {
276 if (cfg.encerts != NULL)
277 keyidx += sk_X509_num(cfg.encerts);
278 } else {
279 if (cfg.keyfile != NULL || cfg.signerfile != NULL)
280 keyidx++;
281 if (cfg.skkeys != NULL)
282 keyidx += sk_OPENSSL_STRING_num(cfg.skkeys);
283 }
284
285 if (keyidx < 0) {
286 BIO_printf(bio_err, "No key specified\n");
287 return (1);
288 }
289
290 if (cfg.key_param == NULL ||
291 cfg.key_param->idx != keyidx) {
292 struct cms_key_param *nparam;
293
294 if ((nparam = calloc(1, sizeof(struct cms_key_param))) == NULL)
295 return (1);
296
297 nparam->idx = keyidx;
298 if ((nparam->param = sk_OPENSSL_STRING_new_null()) == NULL) {
299 free(nparam);
300 return (1);
301 }
302
303 nparam->next = NULL;
304 if (cfg.key_first == NULL)
305 cfg.key_first = nparam;
306 else
307 cfg.key_param->next = nparam;
308
309 cfg.key_param = nparam;
310 }
311
312 if (!sk_OPENSSL_STRING_push(cfg.key_param->param, arg))
313 return (1);
314
315 return (0);
316}
317
318static int
319cms_opt_md(char *arg)
320{
321 if ((cfg.sign_md = EVP_get_digestbyname(arg)) == NULL) {
322 BIO_printf(bio_err, "Unknown digest %s\n", arg);
323 return (1);
324 }
325 return (0);
326}
327
328static int
329cms_opt_print(void)
330{
331 cfg.noout = 1;
332 cfg.print = 1;
333 return (0);
334}
335
336static int
337cms_opt_pwri_pass(char *arg)
338{
339 cfg.pwri_pass = (unsigned char *)arg;
340 return (0);
341}
342
343static int
344cms_opt_recip(char *arg)
345{
346 if (cfg.operation == SMIME_ENCRYPT) {
347 if (cfg.encerts == NULL) {
348 if ((cfg.encerts = sk_X509_new_null()) == NULL)
349 return (1);
350 }
351
352 cfg.cert = load_cert(bio_err, arg, FORMAT_PEM,
353 NULL, "recipient certificate file");
354 if (cfg.cert == NULL)
355 return (1);
356
357 if (!sk_X509_push(cfg.encerts, cfg.cert))
358 return (1);
359
360 cfg.cert = NULL;
361 } else {
362 cfg.recipfile = arg;
363 }
364 return (0);
365}
366
367static int
368cms_opt_receipt_request_from(char *arg)
369{
370 if (cfg.rr_from == NULL)
371 cfg.rr_from = sk_OPENSSL_STRING_new_null();
372 if (cfg.rr_from == NULL)
373 return (1);
374 if (!sk_OPENSSL_STRING_push(cfg.rr_from, arg))
375 return (1);
376
377 return (0);
378}
379
380static int
381cms_opt_receipt_request_to(char *arg)
382{
383 if (cfg.rr_to == NULL)
384 cfg.rr_to = sk_OPENSSL_STRING_new_null();
385 if (cfg.rr_to == NULL)
386 return (1);
387 if (!sk_OPENSSL_STRING_push(cfg.rr_to, arg))
388 return (1);
389
390 return (0);
391}
392
393static int
394cms_opt_secretkey(char *arg)
395{
396 long ltmp;
397
398 free(cfg.secret_key);
399
400 if ((cfg.secret_key = string_to_hex(arg, <mp)) == NULL) {
401 BIO_printf(bio_err, "Invalid key %s\n", arg);
402 return (1);
403 }
404 cfg.secret_keylen = (size_t)ltmp;
405 return (0);
406}
407
408static int
409cms_opt_secretkeyid(char *arg)
410{
411 long ltmp;
412
413 free(cfg.secret_keyid);
414
415 if ((cfg.secret_keyid = string_to_hex(arg, <mp)) == NULL) {
416 BIO_printf(bio_err, "Invalid id %s\n", arg);
417 return (1);
418 }
419 cfg.secret_keyidlen = (size_t)ltmp;
420 return (0);
421}
422
423static int
424cms_opt_signer(char *arg)
425{
426 if (cfg.signerfile == NULL) {
427 cfg.signerfile = arg;
428 return (0);
429 }
430
431 if (cfg.sksigners == NULL)
432 cfg.sksigners = sk_OPENSSL_STRING_new_null();
433 if (cfg.sksigners == NULL)
434 return (1);
435 if (!sk_OPENSSL_STRING_push(cfg.sksigners, cfg.signerfile))
436 return (1);
437
438 if (cfg.keyfile == NULL)
439 cfg.keyfile = cfg.signerfile;
440
441 if (cfg.skkeys == NULL)
442 cfg.skkeys = sk_OPENSSL_STRING_new_null();
443 if (cfg.skkeys == NULL)
444 return (1);
445 if (!sk_OPENSSL_STRING_push(cfg.skkeys, cfg.keyfile))
446 return (1);
447
448 cfg.keyfile = NULL;
449
450 cfg.signerfile = arg;
451 return (0);
452}
453
454static int
455cms_opt_verify_param(int argc, char **argv, int *argsused)
456{
457 int oargc = argc;
458 int badarg = 0;
459
460 if (!args_verify(&argv, &argc, &badarg, bio_err, &cfg.vpm))
461 return (1);
462 if (badarg)
463 return (1);
464
465 *argsused = oargc - argc;
466
467 return (0);
468}
469
470static int
471cms_opt_verify_receipt(char *arg)
472{
473 cfg.operation = SMIME_VERIFY_RECEIPT;
474 cfg.rctfile = arg;
475 return (0);
476}
477
478static const struct option cms_options[] = {
479#ifndef OPENSSL_NO_AES
480 {
481 .name = "aes128",
482 .desc = "Encrypt PEM output with CBC AES",
483 .type = OPTION_ARGV_FUNC,
484 .opt.argvfunc = cms_opt_cipher,
485 },
486 {
487 .name = "aes192",
488 .desc = "Encrypt PEM output with CBC AES",
489 .type = OPTION_ARGV_FUNC,
490 .opt.argvfunc = cms_opt_cipher,
491 },
492 {
493 .name = "aes256",
494 .desc = "Encrypt PEM output with CBC AES (default)",
495 .type = OPTION_ARGV_FUNC,
496 .opt.argvfunc = cms_opt_cipher,
497 },
498#endif
499#ifndef OPENSSL_NO_CAMELLIA
500 {
501 .name = "camellia128",
502 .desc = "Encrypt PEM output with CBC Camellia",
503 .type = OPTION_ARGV_FUNC,
504 .opt.argvfunc = cms_opt_cipher,
505 },
506 {
507 .name = "camellia192",
508 .desc = "Encrypt PEM output with CBC Camellia",
509 .type = OPTION_ARGV_FUNC,
510 .opt.argvfunc = cms_opt_cipher,
511 },
512 {
513 .name = "camellia256",
514 .desc = "Encrypt PEM output with CBC Camellia",
515 .type = OPTION_ARGV_FUNC,
516 .opt.argvfunc = cms_opt_cipher,
517 },
518#endif
519#ifndef OPENSSL_NO_DES
520 {
521 .name = "des",
522 .desc = "Encrypt with DES",
523 .type = OPTION_ARGV_FUNC,
524 .opt.argvfunc = cms_opt_cipher,
525 },
526 {
527 .name = "des3",
528 .desc = "Encrypt with triple DES",
529 .type = OPTION_ARGV_FUNC,
530 .opt.argvfunc = cms_opt_cipher,
531 },
532#endif
533#ifndef OPENSSL_NO_RC2
534 {
535 .name = "rc2-40",
536 .desc = "Encrypt with RC2-40",
537 .type = OPTION_ARGV_FUNC,
538 .opt.argvfunc = cms_opt_cipher,
539 },
540 {
541 .name = "rc2-64",
542 .desc = "Encrypt with RC2-64",
543 .type = OPTION_ARGV_FUNC,
544 .opt.argvfunc = cms_opt_cipher,
545 },
546 {
547 .name = "rc2-128",
548 .desc = "Encrypt with RC2-128",
549 .type = OPTION_ARGV_FUNC,
550 .opt.argvfunc = cms_opt_cipher,
551 },
552#endif
553 {
554 .name = "CAfile",
555 .argname = "file",
556 .desc = "Certificate Authority file",
557 .type = OPTION_ARG,
558 .opt.arg = &cfg.CAfile,
559 },
560 {
561 .name = "CApath",
562 .argname = "path",
563 .desc = "Certificate Authority path",
564 .type = OPTION_ARG,
565 .opt.arg = &cfg.CApath,
566 },
567 {
568 .name = "CRLfile",
569 .argname = "file",
570 .desc = "Other certificate revocation lists file",
571 .type = OPTION_ARG,
572 .opt.arg = &cfg.crlfile,
573 },
574 {
575 .name = "binary",
576 .desc = "Do not translate message to text",
577 .type = OPTION_VALUE_OR,
578 .opt.value = &cfg.flags,
579 .value = CMS_BINARY,
580 },
581 {
582 .name = "certfile",
583 .argname = "file",
584 .desc = "Other certificates file",
585 .type = OPTION_ARG,
586 .opt.arg = &cfg.certfile,
587 },
588 {
589 .name = "certsout",
590 .argname = "file",
591 .desc = "Certificate output file",
592 .type = OPTION_ARG,
593 .opt.arg = &cfg.certsoutfile,
594 },
595 {
596 .name = "cmsout",
597 .desc = "Output CMS structure",
598 .type = OPTION_VALUE,
599 .opt.value = &cfg.operation,
600 .value = SMIME_CMSOUT,
601 },
602 {
603 .name = "content",
604 .argname = "file",
605 .desc = "Supply or override content for detached signature",
606 .type = OPTION_ARG,
607 .opt.arg = &cfg.contfile,
608 },
609 {
610 .name = "crlfeol",
611 .desc = "Use CRLF as EOL termination instead of CR only",
612 .type = OPTION_VALUE_OR,
613 .opt.value = &cfg.flags,
614 .value = CMS_CRLFEOL,
615 },
616 {
617 .name = "data_create",
618 .desc = "Create CMS Data type",
619 .type = OPTION_VALUE,
620 .opt.value = &cfg.operation,
621 .value = SMIME_DATA_CREATE,
622 },
623 {
624 .name = "data_out",
625 .desc = "Output content from the input CMS Data type",
626 .type = OPTION_VALUE,
627 .opt.value = &cfg.operation,
628 .value = SMIME_DATAOUT,
629 },
630 {
631 .name = "debug_decrypt",
632 .desc = "Set the CMS_DEBUG_DECRYPT flag when decrypting",
633 .type = OPTION_VALUE_OR,
634 .opt.value = &cfg.flags,
635 .value = CMS_DEBUG_DECRYPT,
636 },
637 {
638 .name = "decrypt",
639 .desc = "Decrypt encrypted message",
640 .type = OPTION_VALUE,
641 .opt.value = &cfg.operation,
642 .value = SMIME_DECRYPT,
643 },
644 {
645 .name = "digest_create",
646 .desc = "Create CMS DigestedData type",
647 .type = OPTION_VALUE,
648 .opt.value = &cfg.operation,
649 .value = SMIME_DIGEST_CREATE,
650 },
651 {
652 .name = "digest_verify",
653 .desc = "Verify CMS DigestedData type and output the content",
654 .type = OPTION_VALUE,
655 .opt.value = &cfg.operation,
656 .value = SMIME_DIGEST_VERIFY,
657 },
658 {
659 .name = "econtent_type",
660 .argname = "type",
661 .desc = "Set the encapsulated content type",
662 .type = OPTION_ARG_FUNC,
663 .opt.argfunc = cms_opt_econtent_type,
664 },
665 {
666 .name = "encrypt",
667 .desc = "Encrypt message",
668 .type = OPTION_VALUE,
669 .opt.value = &cfg.operation,
670 .value = SMIME_ENCRYPT,
671 },
672 {
673 .name = "EncryptedData_decrypt",
674 .desc = "Decrypt CMS EncryptedData",
675 .type = OPTION_VALUE,
676 .opt.value = &cfg.operation,
677 .value = SMIME_ENCRYPTED_DECRYPT,
678 },
679 {
680 .name = "EncryptedData_encrypt",
681 .desc = "Encrypt content using supplied symmetric key and algorithm",
682 .type = OPTION_VALUE,
683 .opt.value = &cfg.operation,
684 .value = SMIME_ENCRYPTED_ENCRYPT,
685 },
686 {
687 .name = "from",
688 .argname = "addr",
689 .desc = "From address",
690 .type = OPTION_ARG,
691 .opt.arg = &cfg.from,
692 },
693 {
694 .name = "in",
695 .argname = "file",
696 .desc = "Input file",
697 .type = OPTION_ARG,
698 .opt.arg = &cfg.infile,
699 },
700 {
701 .name = "indef",
702 .desc = "Same as -stream",
703 .type = OPTION_VALUE_OR,
704 .opt.value = &cfg.flags,
705 .value = CMS_STREAM,
706 },
707 {
708 .name = "inform",
709 .argname = "fmt",
710 .desc = "Input format (DER, PEM or SMIME (default))",
711 .type = OPTION_ARG_FORMAT,
712 .opt.value = &cfg.informat,
713 },
714 {
715 .name = "inkey",
716 .argname = "file",
717 .desc = "Input key file",
718 .type = OPTION_ARG_FUNC,
719 .opt.argfunc = cms_opt_inkey,
720 },
721 {
722 .name = "keyform",
723 .argname = "fmt",
724 .desc = "Input key format (DER or PEM (default))",
725 .type = OPTION_ARG_FORMAT,
726 .opt.value = &cfg.keyform,
727 },
728 {
729 .name = "keyid",
730 .desc = "Use subject key identifier",
731 .type = OPTION_VALUE_OR,
732 .opt.value = &cfg.flags,
733 .value = CMS_USE_KEYID,
734 },
735 {
736 .name = "keyopt",
737 .argname = "nm:v",
738 .desc = "Set public key parameters",
739 .type = OPTION_ARG_FUNC,
740 .opt.argfunc = cms_opt_keyopt,
741 },
742 {
743 .name = "md",
744 .argname = "digest",
745 .desc = "Digest to use when signing or resigning",
746 .type = OPTION_ARG_FUNC,
747 .opt.argfunc = cms_opt_md,
748 },
749 {
750 .name = "no_attr_verify",
751 .desc = "Do not verify the signer's attribute of a signature",
752 .type = OPTION_VALUE_OR,
753 .opt.value = &cfg.flags,
754 .value = CMS_NO_ATTR_VERIFY,
755 },
756 {
757 .name = "no_content_verify",
758 .desc = "Do not verify the content of a signed message",
759 .type = OPTION_VALUE_OR,
760 .opt.value = &cfg.flags,
761 .value = CMS_NO_CONTENT_VERIFY,
762 },
763 {
764 .name = "no_signer_cert_verify",
765 .desc = "Do not verify the signer's certificate",
766 .type = OPTION_VALUE_OR,
767 .opt.value = &cfg.flags,
768 .value = CMS_NO_SIGNER_CERT_VERIFY,
769 },
770 {
771 .name = "noattr",
772 .desc = "Do not include any signed attributes",
773 .type = OPTION_VALUE_OR,
774 .opt.value = &cfg.flags,
775 .value = CMS_NOATTR,
776 },
777 {
778 .name = "nocerts",
779 .desc = "Do not include signer's certificate when signing",
780 .type = OPTION_VALUE_OR,
781 .opt.value = &cfg.flags,
782 .value = CMS_NOCERTS,
783 },
784 {
785 .name = "nodetach",
786 .desc = "Use opaque signing",
787 .type = OPTION_VALUE_AND,
788 .opt.value = &cfg.flags,
789 .value = ~CMS_DETACHED,
790 },
791 {
792 .name = "noindef",
793 .desc = "Disable CMS streaming",
794 .type = OPTION_VALUE_AND,
795 .opt.value = &cfg.flags,
796 .value = ~CMS_STREAM,
797 },
798 {
799 .name = "nointern",
800 .desc = "Do not search certificates in message for signer",
801 .type = OPTION_VALUE_OR,
802 .opt.value = &cfg.flags,
803 .value = CMS_NOINTERN,
804 },
805 {
806 .name = "nooldmime",
807 .desc = "Output old S/MIME content type",
808 .type = OPTION_VALUE_OR,
809 .opt.value = &cfg.flags,
810 .value = CMS_NOOLDMIMETYPE,
811 },
812 {
813 .name = "noout",
814 .desc = "Do not output the parsed CMS structure",
815 .type = OPTION_FLAG,
816 .opt.flag = &cfg.noout,
817 },
818 {
819 .name = "nosigs",
820 .desc = "Do not verify message signature",
821 .type = OPTION_VALUE_OR,
822 .opt.value = &cfg.flags,
823 .value = CMS_NOSIGS,
824 },
825 {
826 .name = "nosmimecap",
827 .desc = "Omit the SMIMECapabilities attribute",
828 .type = OPTION_VALUE_OR,
829 .opt.value = &cfg.flags,
830 .value = CMS_NOSMIMECAP,
831 },
832 {
833 .name = "noverify",
834 .desc = "Do not verify signer's certificate",
835 .type = OPTION_VALUE_OR,
836 .opt.value = &cfg.flags,
837 .value = CMS_NO_SIGNER_CERT_VERIFY,
838 },
839 {
840 .name = "out",
841 .argname = "file",
842 .desc = "Output file",
843 .type = OPTION_ARG,
844 .opt.arg = &cfg.outfile,
845 },
846 {
847 .name = "outform",
848 .argname = "fmt",
849 .desc = "Output format (DER, PEM or SMIME (default))",
850 .type = OPTION_ARG_FORMAT,
851 .opt.value = &cfg.outformat,
852 },
853 {
854 .name = "passin",
855 .argname = "src",
856 .desc = "Private key password source",
857 .type = OPTION_ARG,
858 .opt.arg = &cfg.passargin,
859 },
860 {
861 .name = "print",
862 .desc = "Print out all fields of the CMS structure for the -cmsout",
863 .type = OPTION_FUNC,
864 .opt.func = cms_opt_print,
865 },
866 {
867 .name = "pwri_password",
868 .argname = "arg",
869 .desc = "Specify PasswordRecipientInfo (PWRI) password to use",
870 .type = OPTION_ARG_FUNC,
871 .opt.argfunc = cms_opt_pwri_pass,
872 },
873 {
874 .name = "rctform",
875 .argname = "fmt",
876 .desc = "Receipt file format (DER, PEM or SMIME (default))",
877 .type = OPTION_ARG_FORMAT,
878 .opt.value = &cfg.rctformat,
879 },
880 {
881 .name = "receipt_request_all",
882 .desc = "Indicate requests should be provided by all recipients",
883 .type = OPTION_VALUE,
884 .opt.value = &cfg.rr_allorfirst,
885 .value = 0,
886 },
887 {
888 .name = "receipt_request_first",
889 .desc = "Indicate requests should be provided by first tier recipient",
890 .type = OPTION_VALUE,
891 .opt.value = &cfg.rr_allorfirst,
892 .value = 1,
893 },
894 {
895 .name = "receipt_request_from",
896 .argname = "addr",
897 .desc = "Add explicit email address where receipts should be supplied",
898 .type = OPTION_ARG_FUNC,
899 .opt.argfunc = cms_opt_receipt_request_from,
900 },
901 {
902 .name = "receipt_request_print",
903 .desc = "Print out the contents of any signed receipt requests",
904 .type = OPTION_FLAG,
905 .opt.flag = &cfg.rr_print,
906 },
907 {
908 .name = "receipt_request_to",
909 .argname = "addr",
910 .desc = "Add explicit email address where receipts should be sent to",
911 .type = OPTION_ARG_FUNC,
912 .opt.argfunc = cms_opt_receipt_request_to,
913 },
914 {
915 .name = "recip",
916 .argname = "file",
917 .desc = "Recipient certificate file for decryption",
918 .type = OPTION_ARG_FUNC,
919 .opt.argfunc = cms_opt_recip,
920 },
921 {
922 .name = "resign",
923 .desc = "Resign a signed message",
924 .type = OPTION_VALUE,
925 .opt.value = &cfg.operation,
926 .value = SMIME_RESIGN,
927 },
928 {
929 .name = "secretkey",
930 .argname = "key",
931 .desc = "Specify symmetric key to use",
932 .type = OPTION_ARG_FUNC,
933 .opt.argfunc = cms_opt_secretkey,
934 },
935 {
936 .name = "secretkeyid",
937 .argname = "id",
938 .desc = "The key identifier for the supplied symmetric key",
939 .type = OPTION_ARG_FUNC,
940 .opt.argfunc = cms_opt_secretkeyid,
941 },
942 {
943 .name = "sign",
944 .desc = "Sign message",
945 .type = OPTION_VALUE,
946 .opt.value = &cfg.operation,
947 .value = SMIME_SIGN,
948 },
949 {
950 .name = "sign_receipt",
951 .desc = "Generate a signed receipt for the message",
952 .type = OPTION_VALUE,
953 .opt.value = &cfg.operation,
954 .value = SMIME_SIGN_RECEIPT,
955 },
956 {
957 .name = "signer",
958 .argname = "file",
959 .desc = "Signer certificate file",
960 .type = OPTION_ARG_FUNC,
961 .opt.argfunc = cms_opt_signer,
962 },
963 {
964 .name = "stream",
965 .desc = "Enable CMS streaming",
966 .type = OPTION_VALUE_OR,
967 .opt.value = &cfg.flags,
968 .value = CMS_STREAM,
969 },
970 {
971 .name = "subject",
972 .argname = "s",
973 .desc = "Subject",
974 .type = OPTION_ARG,
975 .opt.arg = &cfg.subject,
976 },
977 {
978 .name = "text",
979 .desc = "Include or delete text MIME headers",
980 .type = OPTION_VALUE_OR,
981 .opt.value = &cfg.flags,
982 .value = CMS_TEXT,
983 },
984 {
985 .name = "to",
986 .argname = "addr",
987 .desc = "To address",
988 .type = OPTION_ARG,
989 .opt.arg = &cfg.to,
990 },
991 {
992 .name = "verify",
993 .desc = "Verify signed message",
994 .type = OPTION_VALUE,
995 .opt.value = &cfg.operation,
996 .value = SMIME_VERIFY,
997 },
998 {
999 .name = "verify_receipt",
1000 .argname = "file",
1001 .desc = "Verify a signed receipt in file",
1002 .type = OPTION_ARG_FUNC,
1003 .opt.argfunc = cms_opt_verify_receipt,
1004 },
1005 {
1006 .name = "verify_retcode",
1007 .desc = "Set verification error code to exit code",
1008 .type = OPTION_FLAG,
1009 .opt.flag = &cfg.verify_retcode,
1010 },
1011 {
1012 .name = "check_ss_sig",
1013 .type = OPTION_ARGV_FUNC,
1014 .opt.argvfunc = cms_opt_verify_param,
1015 },
1016 {
1017 .name = "crl_check",
1018 .type = OPTION_ARGV_FUNC,
1019 .opt.argvfunc = cms_opt_verify_param,
1020 },
1021 {
1022 .name = "crl_check_all",
1023 .type = OPTION_ARGV_FUNC,
1024 .opt.argvfunc = cms_opt_verify_param,
1025 },
1026 {
1027 .name = "extended_crl",
1028 .type = OPTION_ARGV_FUNC,
1029 .opt.argvfunc = cms_opt_verify_param,
1030 },
1031 {
1032 .name = "ignore_critical",
1033 .type = OPTION_ARGV_FUNC,
1034 .opt.argvfunc = cms_opt_verify_param,
1035 },
1036 {
1037 .name = "issuer_checks",
1038 .type = OPTION_ARGV_FUNC,
1039 .opt.argvfunc = cms_opt_verify_param,
1040 },
1041 {
1042 .name = "policy",
1043 .type = OPTION_ARGV_FUNC,
1044 .opt.argvfunc = cms_opt_verify_param,
1045 },
1046 {
1047 .name = "policy_check",
1048 .type = OPTION_ARGV_FUNC,
1049 .opt.argvfunc = cms_opt_verify_param,
1050 },
1051 {
1052 .name = "purpose",
1053 .type = OPTION_ARGV_FUNC,
1054 .opt.argvfunc = cms_opt_verify_param,
1055 },
1056 {
1057 .name = "x509_strict",
1058 .type = OPTION_ARGV_FUNC,
1059 .opt.argvfunc = cms_opt_verify_param,
1060 },
1061 {
1062 .name = NULL,
1063 .type = OPTION_ARGV_FUNC,
1064 .opt.argvfunc = cms_opt_cipher,
1065 },
1066 { NULL },
1067};
1068
1069static const struct option verify_shared_options[] = {
1070 {
1071 .name = "check_ss_sig",
1072 .desc = "Check the root CA self-signed certificate signature",
1073 },
1074 {
1075 .name = "crl_check",
1076 .desc = "Enable CRL checking for the leaf certificate",
1077 },
1078 {
1079 .name = "crl_check_all",
1080 .desc = "Enable CRL checking for the entire certificate chain",
1081 },
1082 {
1083 .name = "extended_crl",
1084 .desc = "Enable extended CRL support",
1085 },
1086 {
1087 .name = "ignore_critical",
1088 .desc = "Disable critical extension checking",
1089 },
1090 {
1091 .name = "issuer_checks",
1092 .desc = "Enable debugging of certificate issuer checks",
1093 },
1094 {
1095 .name = "policy",
1096 .argname = "name",
1097 .desc = "Add given policy to the acceptable set",
1098 },
1099 {
1100 .name = "policy_check",
1101 .desc = "Enable certificate policy checking",
1102 },
1103 {
1104 .name = "purpose",
1105 .argname = "name",
1106 .desc = "Verify for the given purpose",
1107 },
1108 {
1109 .name = "x509_strict",
1110 .desc = "Use strict X.509 rules (disables workarounds)",
1111 },
1112 { NULL },
1113};
1114
1115static void
1116cms_usage(void)
1117{
1118 int i;
1119
1120 fprintf(stderr, "usage: cms "
1121 "[-aes128 | -aes192 | -aes256 | -camellia128 |\n"
1122 " -camellia192 | -camellia256 | -des | -des3 |\n"
1123 " -rc2-40 | -rc2-64 | -rc2-128] [-CAfile file]\n"
1124 " [-CApath directory] [-CRLfile file] [-binary]\n"
1125 " [-certfile file] [-certsout file] [-cmsout]\n"
1126 " [-content file] [-crlfeol] [-data_create] [-data_out]\n"
1127 " [-debug_decrypt] [-decrypt] [-digest_create] [-digest_verify]\n"
1128 " [-econtent_type type] [-encrypt] [-EncryptedData_decrypt]\n"
1129 " [-EncryptedData_encrypt] [-from addr] [-in file]\n"
1130 " [-inform der | pem | smime] [-inkey file]\n"
1131 " [-keyform der | pem] [-keyid] [-keyopt nm:v] [-md digest]\n"
1132 " [-no_attr_verify] [-no_content_verify]\n"
1133 " [-no_signer_cert_verify] [-noattr] [-nocerts] [-nodetach]\n"
1134 " [-nointern] [-nooldmime] [-noout] [-nosigs] [-nosmimecap]\n"
1135 " [-noverify] [-out file] [-outform der | pem | smime]\n"
1136 " [-passin src] [-print] [-pwri_password arg]\n"
1137 " [-rctform der | pem | smime]\n"
1138 " [-receipt_request_all | -receipt_request_first]\n"
1139 " [-receipt_request_from addr] [-receipt_request_print]\n"
1140 " [-receipt_request_to addr] [-recip file] [-resign]\n"
1141 " [-secretkey key] [-secretkeyid id] [-sign] [-sign_receipt]\n"
1142 " [-signer file] [-stream | -indef | -noindef] [-subject s]\n"
1143 " [-text] [-to addr] [-verify]\n"
1144 " [-verify_receipt file] [-verify_retcode] [cert.pem ...]\n\n");
1145
1146 options_usage(cms_options);
1147
1148 fprintf(stderr, "\nVerification options:\n\n");
1149 options_usage(verify_shared_options);
1150
1151 fprintf(stderr, "\nValid purposes:\n\n");
1152 for (i = 0; i < X509_PURPOSE_get_count(); i++) {
1153 const X509_PURPOSE *ptmp = X509_PURPOSE_get0(i);
1154 fprintf(stderr, " %-18s%s\n", X509_PURPOSE_get0_sname(ptmp),
1155 X509_PURPOSE_get0_name(ptmp));
1156 }
1157}
1158
1159int
1160cms_main(int argc, char **argv)
1161{
1162 int ret = 0;
1163 char **args;
1164 int argsused = 0;
1165 const char *inmode = "r", *outmode = "w";
1166 CMS_ContentInfo *cms = NULL, *rcms = NULL;
1167 X509_STORE *store = NULL;
1168 X509 *recip = NULL, *signer = NULL;
1169 EVP_PKEY *key = NULL;
1170 STACK_OF(X509) *other = NULL;
1171 STACK_OF(X509_CRL) *crls = NULL;
1172 BIO *in = NULL, *out = NULL, *indata = NULL, *rctin = NULL;
1173 int badarg = 0;
1174 CMS_ReceiptRequest *rr = NULL;
1175 char *passin = NULL;
1176 unsigned char *pwri_tmp = NULL;
1177
1178 if (pledge("stdio rpath wpath cpath tty", NULL) == -1) {
1179 perror("pledge");
1180 exit(1);
1181 }
1182
1183 memset(&cfg, 0, sizeof(cfg));
1184 cfg.flags = CMS_DETACHED;
1185 cfg.rr_allorfirst = -1;
1186 cfg.informat = FORMAT_SMIME;
1187 cfg.outformat = FORMAT_SMIME;
1188 cfg.rctformat = FORMAT_SMIME;
1189 cfg.keyform = FORMAT_PEM;
1190 if (options_parse(argc, argv, cms_options, NULL, &argsused) != 0) {
1191 goto argerr;
1192 }
1193 args = argv + argsused;
1194 ret = 1;
1195
1196 if (((cfg.rr_allorfirst != -1) || cfg.rr_from != NULL) &&
1197 cfg.rr_to == NULL) {
1198 BIO_puts(bio_err, "No Signed Receipts Recipients\n");
1199 goto argerr;
1200 }
1201 if (!(cfg.operation & SMIME_SIGNERS) &&
1202 (cfg.rr_to != NULL || cfg.rr_from != NULL)) {
1203 BIO_puts(bio_err, "Signed receipts only allowed with -sign\n");
1204 goto argerr;
1205 }
1206 if (!(cfg.operation & SMIME_SIGNERS) &&
1207 (cfg.skkeys != NULL || cfg.sksigners != NULL)) {
1208 BIO_puts(bio_err, "Multiple signers or keys not allowed\n");
1209 goto argerr;
1210 }
1211 if (cfg.operation & SMIME_SIGNERS) {
1212 if (cfg.keyfile != NULL &&
1213 cfg.signerfile == NULL) {
1214 BIO_puts(bio_err, "Illegal -inkey without -signer\n");
1215 goto argerr;
1216 }
1217 /* Check to see if any final signer needs to be appended */
1218 if (cfg.signerfile != NULL) {
1219 if (cfg.sksigners == NULL &&
1220 (cfg.sksigners =
1221 sk_OPENSSL_STRING_new_null()) == NULL)
1222 goto end;
1223 if (!sk_OPENSSL_STRING_push(cfg.sksigners,
1224 cfg.signerfile))
1225 goto end;
1226 if (cfg.skkeys == NULL &&
1227 (cfg.skkeys =
1228 sk_OPENSSL_STRING_new_null()) == NULL)
1229 goto end;
1230 if (cfg.keyfile == NULL)
1231 cfg.keyfile = cfg.signerfile;
1232 if (!sk_OPENSSL_STRING_push(cfg.skkeys,
1233 cfg.keyfile))
1234 goto end;
1235 }
1236 if (cfg.sksigners == NULL) {
1237 BIO_printf(bio_err,
1238 "No signer certificate specified\n");
1239 badarg = 1;
1240 }
1241 cfg.signerfile = NULL;
1242 cfg.keyfile = NULL;
1243 } else if (cfg.operation == SMIME_DECRYPT) {
1244 if (cfg.recipfile == NULL &&
1245 cfg.keyfile == NULL &&
1246 cfg.secret_key == NULL &&
1247 cfg.pwri_pass == NULL) {
1248 BIO_printf(bio_err,
1249 "No recipient certificate or key specified\n");
1250 badarg = 1;
1251 }
1252 } else if (cfg.operation == SMIME_ENCRYPT) {
1253 if (*args == NULL && cfg.secret_key == NULL &&
1254 cfg.pwri_pass == NULL &&
1255 cfg.encerts == NULL) {
1256 BIO_printf(bio_err,
1257 "No recipient(s) certificate(s) specified\n");
1258 badarg = 1;
1259 }
1260 } else if (!cfg.operation) {
1261 badarg = 1;
1262 }
1263
1264 if (badarg) {
1265 argerr:
1266 cms_usage();
1267 goto end;
1268 }
1269
1270 if (!app_passwd(bio_err, cfg.passargin, NULL, &passin, NULL)) {
1271 BIO_printf(bio_err, "Error getting password\n");
1272 goto end;
1273 }
1274 ret = 2;
1275
1276 if (!(cfg.operation & SMIME_SIGNERS))
1277 cfg.flags &= ~CMS_DETACHED;
1278
1279 if (cfg.operation & SMIME_OP) {
1280 if (cfg.outformat == FORMAT_ASN1)
1281 outmode = "wb";
1282 } else {
1283 if (cfg.flags & CMS_BINARY)
1284 outmode = "wb";
1285 }
1286
1287 if (cfg.operation & SMIME_IP) {
1288 if (cfg.informat == FORMAT_ASN1)
1289 inmode = "rb";
1290 } else {
1291 if (cfg.flags & CMS_BINARY)
1292 inmode = "rb";
1293 }
1294
1295 if (cfg.operation == SMIME_ENCRYPT) {
1296 if (cfg.cipher == NULL)
1297 cfg.cipher = EVP_aes_256_cbc();
1298 if (cfg.secret_key != NULL &&
1299 cfg.secret_keyid == NULL) {
1300 BIO_printf(bio_err, "No secret key id\n");
1301 goto end;
1302 }
1303 if (*args != NULL && cfg.encerts == NULL)
1304 if ((cfg.encerts = sk_X509_new_null()) == NULL)
1305 goto end;
1306 while (*args) {
1307 if ((cfg.cert = load_cert(bio_err, *args,
1308 FORMAT_PEM, NULL,
1309 "recipient certificate file")) == NULL)
1310 goto end;
1311 if (!sk_X509_push(cfg.encerts, cfg.cert))
1312 goto end;
1313 cfg.cert = NULL;
1314 args++;
1315 }
1316 }
1317 if (cfg.certfile != NULL) {
1318 if ((other = load_certs(bio_err, cfg.certfile,
1319 FORMAT_PEM, NULL, "certificate file")) == NULL) {
1320 ERR_print_errors(bio_err);
1321 goto end;
1322 }
1323 }
1324
1325 if (cfg.crlfile != NULL) {
1326 crls = load_crls(bio_err, cfg.crlfile, FORMAT_PEM, NULL,
1327 "other CRLs");
1328 if (crls == NULL)
1329 goto end;
1330 }
1331
1332 if (cfg.recipfile != NULL &&
1333 (cfg.operation == SMIME_DECRYPT)) {
1334 if ((recip = load_cert(bio_err, cfg.recipfile,
1335 FORMAT_PEM, NULL, "recipient certificate file")) == NULL) {
1336 ERR_print_errors(bio_err);
1337 goto end;
1338 }
1339 }
1340 if (cfg.operation == SMIME_SIGN_RECEIPT) {
1341 if ((signer = load_cert(bio_err, cfg.signerfile,
1342 FORMAT_PEM, NULL,
1343 "receipt signer certificate file")) == NULL) {
1344 ERR_print_errors(bio_err);
1345 goto end;
1346 }
1347 }
1348 if (cfg.operation == SMIME_DECRYPT) {
1349 if (cfg.keyfile == NULL)
1350 cfg.keyfile = cfg.recipfile;
1351 } else if ((cfg.operation == SMIME_SIGN) ||
1352 (cfg.operation == SMIME_SIGN_RECEIPT)) {
1353 if (cfg.keyfile == NULL)
1354 cfg.keyfile = cfg.signerfile;
1355 } else {
1356 cfg.keyfile = NULL;
1357 }
1358
1359 if (cfg.keyfile != NULL) {
1360 key = load_key(bio_err, cfg.keyfile, cfg.keyform,
1361 0, passin, "signing key file");
1362 if (key == NULL)
1363 goto end;
1364 }
1365 if (cfg.infile != NULL) {
1366 if ((in = BIO_new_file(cfg.infile, inmode)) == NULL) {
1367 BIO_printf(bio_err,
1368 "Can't open input file %s\n", cfg.infile);
1369 goto end;
1370 }
1371 } else {
1372 if ((in = BIO_new_fp(stdin, BIO_NOCLOSE)) == NULL)
1373 goto end;
1374 }
1375
1376 if (cfg.operation & SMIME_IP) {
1377 if (cfg.informat == FORMAT_SMIME)
1378 cms = SMIME_read_CMS(in, &indata);
1379 else if (cfg.informat == FORMAT_PEM)
1380 cms = PEM_read_bio_CMS(in, NULL, NULL, NULL);
1381 else if (cfg.informat == FORMAT_ASN1)
1382 cms = d2i_CMS_bio(in, NULL);
1383 else {
1384 BIO_printf(bio_err, "Bad input format for CMS file\n");
1385 goto end;
1386 }
1387
1388 if (cms == NULL) {
1389 BIO_printf(bio_err, "Error reading S/MIME message\n");
1390 goto end;
1391 }
1392 if (cfg.contfile != NULL) {
1393 BIO_free(indata);
1394 if ((indata = BIO_new_file(cfg.contfile,
1395 "rb")) == NULL) {
1396 BIO_printf(bio_err,
1397 "Can't read content file %s\n",
1398 cfg.contfile);
1399 goto end;
1400 }
1401 }
1402 if (cfg.certsoutfile != NULL) {
1403 STACK_OF(X509) *allcerts;
1404 if ((allcerts = CMS_get1_certs(cms)) == NULL)
1405 goto end;
1406 if (!save_certs(cfg.certsoutfile, allcerts)) {
1407 BIO_printf(bio_err,
1408 "Error writing certs to %s\n",
1409 cfg.certsoutfile);
1410 sk_X509_pop_free(allcerts, X509_free);
1411 ret = 5;
1412 goto end;
1413 }
1414 sk_X509_pop_free(allcerts, X509_free);
1415 }
1416 }
1417 if (cfg.rctfile != NULL) {
1418 char *rctmode = (cfg.rctformat == FORMAT_ASN1) ?
1419 "rb" : "r";
1420 if ((rctin = BIO_new_file(cfg.rctfile, rctmode)) == NULL) {
1421 BIO_printf(bio_err,
1422 "Can't open receipt file %s\n", cfg.rctfile);
1423 goto end;
1424 }
1425 if (cfg.rctformat == FORMAT_SMIME)
1426 rcms = SMIME_read_CMS(rctin, NULL);
1427 else if (cfg.rctformat == FORMAT_PEM)
1428 rcms = PEM_read_bio_CMS(rctin, NULL, NULL, NULL);
1429 else if (cfg.rctformat == FORMAT_ASN1)
1430 rcms = d2i_CMS_bio(rctin, NULL);
1431 else {
1432 BIO_printf(bio_err, "Bad input format for receipt\n");
1433 goto end;
1434 }
1435
1436 if (rcms == NULL) {
1437 BIO_printf(bio_err, "Error reading receipt\n");
1438 goto end;
1439 }
1440 }
1441 if (cfg.outfile != NULL) {
1442 if ((out = BIO_new_file(cfg.outfile, outmode)) == NULL) {
1443 BIO_printf(bio_err,
1444 "Can't open output file %s\n", cfg.outfile);
1445 goto end;
1446 }
1447 } else {
1448 if ((out = BIO_new_fp(stdout, BIO_NOCLOSE)) == NULL)
1449 goto end;
1450 }
1451
1452 if ((cfg.operation == SMIME_VERIFY) ||
1453 (cfg.operation == SMIME_VERIFY_RECEIPT)) {
1454 if ((store = setup_verify(bio_err, cfg.CAfile,
1455 cfg.CApath)) == NULL)
1456 goto end;
1457 if (cfg.vpm != NULL) {
1458 if (!X509_STORE_set1_param(store, cfg.vpm))
1459 goto end;
1460 }
1461 }
1462 ret = 3;
1463
1464 if (cfg.operation == SMIME_DATA_CREATE) {
1465 cms = CMS_data_create(in, cfg.flags);
1466 } else if (cfg.operation == SMIME_DIGEST_CREATE) {
1467 cms = CMS_digest_create(in, cfg.sign_md,
1468 cfg.flags);
1469 } else if (cfg.operation == SMIME_ENCRYPT) {
1470 int i;
1471 cfg.flags |= CMS_PARTIAL;
1472 cms = CMS_encrypt(NULL, in, cfg.cipher,
1473 cfg.flags);
1474 if (cms == NULL)
1475 goto end;
1476 for (i = 0; i < sk_X509_num(cfg.encerts); i++) {
1477 CMS_RecipientInfo *ri;
1478 struct cms_key_param *kparam;
1479 int tflags = cfg.flags;
1480 X509 *x;
1481
1482 if ((x = sk_X509_value(cfg.encerts, i)) == NULL)
1483 goto end;
1484 for (kparam = cfg.key_first; kparam != NULL;
1485 kparam = kparam->next) {
1486 if (kparam->idx == i) {
1487 tflags |= CMS_KEY_PARAM;
1488 break;
1489 }
1490 }
1491 ri = CMS_add1_recipient_cert(cms, x, tflags);
1492 if (ri == NULL)
1493 goto end;
1494 if (kparam != NULL) {
1495 EVP_PKEY_CTX *pctx;
1496 if ((pctx = CMS_RecipientInfo_get0_pkey_ctx(
1497 ri)) == NULL)
1498 goto end;
1499 if (!cms_set_pkey_param(pctx, kparam->param))
1500 goto end;
1501 }
1502 }
1503
1504 if (cfg.secret_key != NULL) {
1505 if (CMS_add0_recipient_key(cms, NID_undef,
1506 cfg.secret_key, cfg.secret_keylen,
1507 cfg.secret_keyid, cfg.secret_keyidlen,
1508 NULL, NULL, NULL) == NULL)
1509 goto end;
1510 /* NULL these because call absorbs them */
1511 cfg.secret_key = NULL;
1512 cfg.secret_keyid = NULL;
1513 }
1514 if (cfg.pwri_pass != NULL) {
1515 pwri_tmp = strdup(cfg.pwri_pass);
1516 if (pwri_tmp == NULL)
1517 goto end;
1518 if (CMS_add0_recipient_password(cms, -1, NID_undef,
1519 NID_undef, pwri_tmp, -1, NULL) == NULL)
1520 goto end;
1521 pwri_tmp = NULL;
1522 }
1523 if (!(cfg.flags & CMS_STREAM)) {
1524 if (!CMS_final(cms, in, NULL, cfg.flags))
1525 goto end;
1526 }
1527 } else if (cfg.operation == SMIME_ENCRYPTED_ENCRYPT) {
1528 cms = CMS_EncryptedData_encrypt(in, cfg.cipher,
1529 cfg.secret_key, cfg.secret_keylen,
1530 cfg.flags);
1531
1532 } else if (cfg.operation == SMIME_SIGN_RECEIPT) {
1533 CMS_ContentInfo *srcms = NULL;
1534 STACK_OF(CMS_SignerInfo) *sis;
1535 CMS_SignerInfo *si;
1536 sis = CMS_get0_SignerInfos(cms);
1537 if (sis == NULL)
1538 goto end;
1539 si = sk_CMS_SignerInfo_value(sis, 0);
1540 if (si == NULL)
1541 goto end;
1542 srcms = CMS_sign_receipt(si, signer, key, other,
1543 cfg.flags);
1544 if (srcms == NULL)
1545 goto end;
1546 CMS_ContentInfo_free(cms);
1547 cms = srcms;
1548 } else if (cfg.operation & SMIME_SIGNERS) {
1549 int i;
1550 /*
1551 * If detached data content we enable streaming if S/MIME
1552 * output format.
1553 */
1554 if (cfg.operation == SMIME_SIGN) {
1555
1556 if (cfg.flags & CMS_DETACHED) {
1557 if (cfg.outformat == FORMAT_SMIME)
1558 cfg.flags |= CMS_STREAM;
1559 }
1560 cfg.flags |= CMS_PARTIAL;
1561 cms = CMS_sign(NULL, NULL, other, in, cfg.flags);
1562 if (cms == NULL)
1563 goto end;
1564 if (cfg.econtent_type != NULL)
1565 if (!CMS_set1_eContentType(cms,
1566 cfg.econtent_type))
1567 goto end;
1568
1569 if (cfg.rr_to != NULL) {
1570 rr = make_receipt_request(cfg.rr_to,
1571 cfg.rr_allorfirst,
1572 cfg.rr_from);
1573 if (rr == NULL) {
1574 BIO_puts(bio_err,
1575 "Signed Receipt Request Creation Error\n");
1576 goto end;
1577 }
1578 }
1579 } else {
1580 cfg.flags |= CMS_REUSE_DIGEST;
1581 }
1582
1583 for (i = 0; i < sk_OPENSSL_STRING_num(cfg.sksigners); i++) {
1584 CMS_SignerInfo *si;
1585 struct cms_key_param *kparam;
1586 int tflags = cfg.flags;
1587
1588 cfg.signerfile = sk_OPENSSL_STRING_value(
1589 cfg.sksigners, i);
1590 cfg.keyfile = sk_OPENSSL_STRING_value(
1591 cfg.skkeys, i);
1592
1593 signer = load_cert(bio_err, cfg.signerfile,
1594 FORMAT_PEM, NULL, "signer certificate");
1595 if (signer == NULL)
1596 goto end;
1597 key = load_key(bio_err, cfg.keyfile,
1598 cfg.keyform, 0, passin, "signing key file");
1599 if (key == NULL)
1600 goto end;
1601 for (kparam = cfg.key_first; kparam != NULL;
1602 kparam = kparam->next) {
1603 if (kparam->idx == i) {
1604 tflags |= CMS_KEY_PARAM;
1605 break;
1606 }
1607 }
1608 si = CMS_add1_signer(cms, signer, key,
1609 cfg.sign_md, tflags);
1610 if (si == NULL)
1611 goto end;
1612 if (kparam != NULL) {
1613 EVP_PKEY_CTX *pctx;
1614 if ((pctx = CMS_SignerInfo_get0_pkey_ctx(
1615 si)) == NULL)
1616 goto end;
1617 if (!cms_set_pkey_param(pctx, kparam->param))
1618 goto end;
1619 }
1620 if (rr != NULL && !CMS_add1_ReceiptRequest(si, rr))
1621 goto end;
1622 X509_free(signer);
1623 signer = NULL;
1624 EVP_PKEY_free(key);
1625 key = NULL;
1626 }
1627 /* If not streaming or resigning finalize structure */
1628 if ((cfg.operation == SMIME_SIGN) &&
1629 !(cfg.flags & CMS_STREAM)) {
1630 if (!CMS_final(cms, in, NULL, cfg.flags))
1631 goto end;
1632 }
1633 }
1634 if (cms == NULL) {
1635 BIO_printf(bio_err, "Error creating CMS structure\n");
1636 goto end;
1637 }
1638 ret = 4;
1639 if (cfg.operation == SMIME_DECRYPT) {
1640 if (cfg.flags & CMS_DEBUG_DECRYPT)
1641 CMS_decrypt(cms, NULL, NULL, NULL, NULL,
1642 cfg.flags);
1643
1644 if (cfg.secret_key != NULL) {
1645 if (!CMS_decrypt_set1_key(cms, cfg.secret_key,
1646 cfg.secret_keylen, cfg.secret_keyid,
1647 cfg.secret_keyidlen)) {
1648 BIO_puts(bio_err,
1649 "Error decrypting CMS using secret key\n");
1650 goto end;
1651 }
1652 }
1653 if (key != NULL) {
1654 if (!CMS_decrypt_set1_pkey(cms, key, recip)) {
1655 BIO_puts(bio_err,
1656 "Error decrypting CMS using private key\n");
1657 goto end;
1658 }
1659 }
1660 if (cfg.pwri_pass != NULL) {
1661 if (!CMS_decrypt_set1_password(cms,
1662 cfg.pwri_pass, -1)) {
1663 BIO_puts(bio_err,
1664 "Error decrypting CMS using password\n");
1665 goto end;
1666 }
1667 }
1668 if (!CMS_decrypt(cms, NULL, NULL, indata, out,
1669 cfg.flags)) {
1670 BIO_printf(bio_err, "Error decrypting CMS structure\n");
1671 goto end;
1672 }
1673 } else if (cfg.operation == SMIME_DATAOUT) {
1674 if (!CMS_data(cms, out, cfg.flags))
1675 goto end;
1676 } else if (cfg.operation == SMIME_DIGEST_VERIFY) {
1677 if (CMS_digest_verify(cms, indata, out, cfg.flags) > 0)
1678 BIO_printf(bio_err, "Verification successful\n");
1679 else {
1680 BIO_printf(bio_err, "Verification failure\n");
1681 goto end;
1682 }
1683 } else if (cfg.operation == SMIME_ENCRYPTED_DECRYPT) {
1684 if (!CMS_EncryptedData_decrypt(cms, cfg.secret_key,
1685 cfg.secret_keylen, indata, out, cfg.flags))
1686 goto end;
1687 } else if (cfg.operation == SMIME_VERIFY) {
1688 if (cfg.crlfile != NULL) {
1689 int i;
1690
1691 for (i = 0; i < sk_X509_CRL_num(crls); i++) {
1692 X509_CRL *crl = sk_X509_CRL_value(crls, i);
1693 if (!CMS_add1_crl(cms, crl))
1694 goto end;
1695 }
1696 }
1697 if (CMS_verify(cms, other, store, indata, out,
1698 cfg.flags) > 0) {
1699 BIO_printf(bio_err, "Verification successful\n");
1700 } else {
1701 BIO_printf(bio_err, "Verification failure\n");
1702 if (cfg.verify_retcode)
1703 ret = verify_err + 32;
1704 goto end;
1705 }
1706 if (cfg.signerfile != NULL) {
1707 STACK_OF(X509) *signers;
1708 if ((signers = CMS_get0_signers(cms)) == NULL)
1709 goto end;
1710 if (!save_certs(cfg.signerfile, signers)) {
1711 BIO_printf(bio_err,
1712 "Error writing signers to %s\n",
1713 cfg.signerfile);
1714 sk_X509_free(signers);
1715 ret = 5;
1716 goto end;
1717 }
1718 sk_X509_free(signers);
1719 }
1720 if (cfg.rr_print)
1721 receipt_request_print(bio_err, cms);
1722
1723 } else if (cfg.operation == SMIME_VERIFY_RECEIPT) {
1724 if (CMS_verify_receipt(rcms, cms, other, store,
1725 cfg.flags) > 0) {
1726 BIO_printf(bio_err, "Verification successful\n");
1727 } else {
1728 BIO_printf(bio_err, "Verification failure\n");
1729 goto end;
1730 }
1731 } else {
1732 if (cfg.noout) {
1733 if (cfg.print &&
1734 !CMS_ContentInfo_print_ctx(out, cms, 0, NULL))
1735 goto end;
1736 } else if (cfg.outformat == FORMAT_SMIME) {
1737 if (cfg.to != NULL)
1738 BIO_printf(out, "To: %s\n", cfg.to);
1739 if (cfg.from != NULL)
1740 BIO_printf(out, "From: %s\n", cfg.from);
1741 if (cfg.subject != NULL)
1742 BIO_printf(out, "Subject: %s\n",
1743 cfg.subject);
1744 if (cfg.operation == SMIME_RESIGN)
1745 ret = SMIME_write_CMS(out, cms, indata,
1746 cfg.flags);
1747 else
1748 ret = SMIME_write_CMS(out, cms, in,
1749 cfg.flags);
1750 } else if (cfg.outformat == FORMAT_PEM) {
1751 ret = PEM_write_bio_CMS_stream(out, cms, in,
1752 cfg.flags);
1753 } else if (cfg.outformat == FORMAT_ASN1) {
1754 ret = i2d_CMS_bio_stream(out, cms, in, cfg.flags);
1755 } else {
1756 BIO_printf(bio_err, "Bad output format for CMS file\n");
1757 goto end;
1758 }
1759 if (ret <= 0) {
1760 ret = 6;
1761 goto end;
1762 }
1763 }
1764 ret = 0;
1765
1766 end:
1767 if (ret)
1768 ERR_print_errors(bio_err);
1769
1770 sk_X509_pop_free(cfg.encerts, X509_free);
1771 sk_X509_pop_free(other, X509_free);
1772 sk_X509_CRL_pop_free(crls, X509_CRL_free);
1773 X509_VERIFY_PARAM_free(cfg.vpm);
1774 sk_OPENSSL_STRING_free(cfg.sksigners);
1775 sk_OPENSSL_STRING_free(cfg.skkeys);
1776 free(cfg.secret_key);
1777 free(cfg.secret_keyid);
1778 free(pwri_tmp);
1779 ASN1_OBJECT_free(cfg.econtent_type);
1780 CMS_ReceiptRequest_free(rr);
1781 sk_OPENSSL_STRING_free(cfg.rr_to);
1782 sk_OPENSSL_STRING_free(cfg.rr_from);
1783 for (cfg.key_param = cfg.key_first; cfg.key_param;) {
1784 struct cms_key_param *tparam;
1785 sk_OPENSSL_STRING_free(cfg.key_param->param);
1786 tparam = cfg.key_param->next;
1787 free(cfg.key_param);
1788 cfg.key_param = tparam;
1789 }
1790 X509_STORE_free(store);
1791 X509_free(cfg.cert);
1792 X509_free(recip);
1793 X509_free(signer);
1794 EVP_PKEY_free(key);
1795 CMS_ContentInfo_free(cms);
1796 CMS_ContentInfo_free(rcms);
1797 BIO_free(rctin);
1798 BIO_free(in);
1799 BIO_free(indata);
1800 BIO_free_all(out);
1801 free(passin);
1802
1803 return (ret);
1804}
1805
1806static int
1807save_certs(char *signerfile, STACK_OF(X509) *signers)
1808{
1809 int i;
1810 BIO *tmp;
1811
1812 if (signerfile == NULL)
1813 return 1;
1814 tmp = BIO_new_file(signerfile, "w");
1815 if (tmp == NULL)
1816 return 0;
1817 for (i = 0; i < sk_X509_num(signers); i++)
1818 PEM_write_bio_X509(tmp, sk_X509_value(signers, i));
1819 BIO_free(tmp);
1820 return 1;
1821}
1822
1823static void
1824gnames_stack_print(BIO *out, STACK_OF(GENERAL_NAMES) *gns)
1825{
1826 STACK_OF(GENERAL_NAME) *gens;
1827 GENERAL_NAME *gen;
1828 int i, j;
1829
1830 for (i = 0; i < sk_GENERAL_NAMES_num(gns); i++) {
1831 gens = sk_GENERAL_NAMES_value(gns, i);
1832 for (j = 0; j < sk_GENERAL_NAME_num(gens); j++) {
1833 gen = sk_GENERAL_NAME_value(gens, j);
1834 BIO_puts(out, " ");
1835 GENERAL_NAME_print(out, gen);
1836 BIO_puts(out, "\n");
1837 }
1838 }
1839 return;
1840}
1841
1842static void
1843receipt_request_print(BIO *out, CMS_ContentInfo *cms)
1844{
1845 STACK_OF(CMS_SignerInfo) *sis;
1846 CMS_SignerInfo *si;
1847 CMS_ReceiptRequest *rr;
1848 int allorfirst;
1849 STACK_OF(GENERAL_NAMES) *rto, *rlist;
1850 ASN1_STRING *scid;
1851 int i, rv;
1852
1853 if ((sis = CMS_get0_SignerInfos(cms)) == NULL)
1854 return;
1855 for (i = 0; i < sk_CMS_SignerInfo_num(sis); i++) {
1856 if ((si = sk_CMS_SignerInfo_value(sis, i)) == NULL)
1857 return;
1858 rv = CMS_get1_ReceiptRequest(si, &rr);
1859 BIO_printf(bio_err, "Signer %d:\n", i + 1);
1860 if (rv == 0) {
1861 BIO_puts(bio_err, " No Receipt Request\n");
1862 } else if (rv < 0) {
1863 BIO_puts(bio_err, " Receipt Request Parse Error\n");
1864 ERR_print_errors(bio_err);
1865 } else {
1866 const char *id;
1867 int idlen;
1868
1869 CMS_ReceiptRequest_get0_values(rr, &scid, &allorfirst,
1870 &rlist, &rto);
1871 BIO_puts(out, " Signed Content ID:\n");
1872 idlen = ASN1_STRING_length(scid);
1873 id = (const char *) ASN1_STRING_get0_data(scid);
1874 BIO_dump_indent(out, id, idlen, 4);
1875 BIO_puts(out, " Receipts From");
1876 if (rlist != NULL) {
1877 BIO_puts(out, " List:\n");
1878 gnames_stack_print(out, rlist);
1879 } else if (allorfirst == 1) {
1880 BIO_puts(out, ": First Tier\n");
1881 } else if (allorfirst == 0) {
1882 BIO_puts(out, ": All\n");
1883 } else {
1884 BIO_printf(out, " Unknown (%d)\n", allorfirst);
1885 }
1886 BIO_puts(out, " Receipts To:\n");
1887 gnames_stack_print(out, rto);
1888 }
1889 CMS_ReceiptRequest_free(rr);
1890 }
1891}
1892
1893static STACK_OF(GENERAL_NAMES) *
1894make_names_stack(STACK_OF(OPENSSL_STRING) *ns)
1895{
1896 int i;
1897 STACK_OF(GENERAL_NAMES) *ret;
1898 GENERAL_NAMES *gens = NULL;
1899 GENERAL_NAME *gen = NULL;
1900
1901 if ((ret = sk_GENERAL_NAMES_new_null()) == NULL)
1902 goto err;
1903 for (i = 0; i < sk_OPENSSL_STRING_num(ns); i++) {
1904 char *str = sk_OPENSSL_STRING_value(ns, i);
1905 gen = a2i_GENERAL_NAME(NULL, NULL, NULL, GEN_EMAIL, str, 0);
1906 if (gen == NULL)
1907 goto err;
1908 gens = GENERAL_NAMES_new();
1909 if (gens == NULL)
1910 goto err;
1911 if (!sk_GENERAL_NAME_push(gens, gen))
1912 goto err;
1913 gen = NULL;
1914 if (!sk_GENERAL_NAMES_push(ret, gens))
1915 goto err;
1916 gens = NULL;
1917 }
1918
1919 return ret;
1920
1921 err:
1922 sk_GENERAL_NAMES_pop_free(ret, GENERAL_NAMES_free);
1923 GENERAL_NAMES_free(gens);
1924 GENERAL_NAME_free(gen);
1925
1926 return NULL;
1927}
1928
1929
1930static CMS_ReceiptRequest *
1931make_receipt_request(STACK_OF(OPENSSL_STRING) *rr_to, int rr_allorfirst,
1932 STACK_OF(OPENSSL_STRING) *rr_from)
1933{
1934 STACK_OF(GENERAL_NAMES) *rct_to = NULL, *rct_from = NULL;
1935 CMS_ReceiptRequest *rr;
1936
1937 rct_to = make_names_stack(rr_to);
1938 if (rct_to == NULL)
1939 goto err;
1940 if (rr_from != NULL) {
1941 rct_from = make_names_stack(rr_from);
1942 if (rct_from == NULL)
1943 goto err;
1944 } else {
1945 rct_from = NULL;
1946 }
1947
1948 if ((rr = CMS_ReceiptRequest_create0(NULL, -1, rr_allorfirst, rct_from,
1949 rct_to)) == NULL)
1950 goto err;
1951
1952 return rr;
1953
1954 err:
1955 sk_GENERAL_NAMES_pop_free(rct_to, GENERAL_NAMES_free);
1956 sk_GENERAL_NAMES_pop_free(rct_from, GENERAL_NAMES_free);
1957 return NULL;
1958}
1959
1960static int
1961cms_set_pkey_param(EVP_PKEY_CTX *pctx, STACK_OF(OPENSSL_STRING) *param)
1962{
1963 char *keyopt;
1964 int i;
1965
1966 if (sk_OPENSSL_STRING_num(param) <= 0)
1967 return 1;
1968 for (i = 0; i < sk_OPENSSL_STRING_num(param); i++) {
1969 keyopt = sk_OPENSSL_STRING_value(param, i);
1970 if (pkey_ctrl_string(pctx, keyopt) <= 0) {
1971 BIO_printf(bio_err, "parameter error \"%s\"\n", keyopt);
1972 ERR_print_errors(bio_err);
1973 return 0;
1974 }
1975 }
1976 return 1;
1977}
1978
1979#endif