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