xref: /openbsd-src/usr.bin/openssl/cms.c (revision 6156097ae53296992463cb27d4cd81f9df1c2aac)
1*6156097aSjob /* $OpenBSD: cms.c,v 1.36 2024/08/12 15:34:58 job Exp $ */
2c8d13811Sjsing /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
3c8d13811Sjsing  * project.
4c8d13811Sjsing  */
5c8d13811Sjsing /* ====================================================================
6c8d13811Sjsing  * Copyright (c) 2008 The OpenSSL Project.  All rights reserved.
7c8d13811Sjsing  *
8c8d13811Sjsing  * Redistribution and use in source and binary forms, with or without
9c8d13811Sjsing  * modification, are permitted provided that the following conditions
10c8d13811Sjsing  * are met:
11c8d13811Sjsing  *
12c8d13811Sjsing  * 1. Redistributions of source code must retain the above copyright
13c8d13811Sjsing  *    notice, this list of conditions and the following disclaimer.
14c8d13811Sjsing  *
15c8d13811Sjsing  * 2. Redistributions in binary form must reproduce the above copyright
16c8d13811Sjsing  *    notice, this list of conditions and the following disclaimer in
17c8d13811Sjsing  *    the documentation and/or other materials provided with the
18c8d13811Sjsing  *    distribution.
19c8d13811Sjsing  *
20c8d13811Sjsing  * 3. All advertising materials mentioning features or use of this
21c8d13811Sjsing  *    software must display the following acknowledgment:
22c8d13811Sjsing  *    "This product includes software developed by the OpenSSL Project
23c8d13811Sjsing  *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
24c8d13811Sjsing  *
25c8d13811Sjsing  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
26c8d13811Sjsing  *    endorse or promote products derived from this software without
27c8d13811Sjsing  *    prior written permission. For written permission, please contact
28c8d13811Sjsing  *    licensing@OpenSSL.org.
29c8d13811Sjsing  *
30c8d13811Sjsing  * 5. Products derived from this software may not be called "OpenSSL"
31c8d13811Sjsing  *    nor may "OpenSSL" appear in their names without prior written
32c8d13811Sjsing  *    permission of the OpenSSL Project.
33c8d13811Sjsing  *
34c8d13811Sjsing  * 6. Redistributions of any form whatsoever must retain the following
35c8d13811Sjsing  *    acknowledgment:
36c8d13811Sjsing  *    "This product includes software developed by the OpenSSL Project
37c8d13811Sjsing  *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
38c8d13811Sjsing  *
39c8d13811Sjsing  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
40c8d13811Sjsing  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
41c8d13811Sjsing  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
42c8d13811Sjsing  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
43c8d13811Sjsing  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
44c8d13811Sjsing  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
45c8d13811Sjsing  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
46c8d13811Sjsing  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47c8d13811Sjsing  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
48c8d13811Sjsing  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
49c8d13811Sjsing  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
50c8d13811Sjsing  * OF THE POSSIBILITY OF SUCH DAMAGE.
51c8d13811Sjsing  * ====================================================================
52c8d13811Sjsing  */
53c8d13811Sjsing 
54c8d13811Sjsing /* CMS utility function */
55c8d13811Sjsing 
56c8d13811Sjsing #include <stdio.h>
57c8d13811Sjsing #include <string.h>
58c8d13811Sjsing 
59c8d13811Sjsing #include "apps.h"
60c8d13811Sjsing 
61c8d13811Sjsing #ifndef OPENSSL_NO_CMS
62c8d13811Sjsing 
63c8d13811Sjsing #include <openssl/crypto.h>
64c8d13811Sjsing #include <openssl/err.h>
65c8d13811Sjsing #include <openssl/pem.h>
66c8d13811Sjsing #include <openssl/x509_vfy.h>
67c8d13811Sjsing #include <openssl/x509v3.h>
68c8d13811Sjsing 
696ff77328Sjsing #include <openssl/cms.h>
706ff77328Sjsing 
71c8d13811Sjsing static int save_certs(char *signerfile, STACK_OF(X509) *signers);
72c8d13811Sjsing static void receipt_request_print(BIO *out, CMS_ContentInfo *cms);
73c8d13811Sjsing static CMS_ReceiptRequest *make_receipt_request(
74c8d13811Sjsing     STACK_OF(OPENSSL_STRING) *rr_to, int rr_allorfirst,
75c8d13811Sjsing     STACK_OF(OPENSSL_STRING) *rr_from);
7699e5b935Sinoguchi static int cms_set_pkey_param(EVP_PKEY_CTX *pctx,
7799e5b935Sinoguchi     STACK_OF(OPENSSL_STRING) *param);
78c8d13811Sjsing 
79c8d13811Sjsing #define SMIME_OP	0x10
80c8d13811Sjsing #define SMIME_IP	0x20
81c8d13811Sjsing #define SMIME_SIGNERS	0x40
82c8d13811Sjsing #define SMIME_ENCRYPT		(1 | SMIME_OP)
83c8d13811Sjsing #define SMIME_DECRYPT		(2 | SMIME_IP)
84c8d13811Sjsing #define SMIME_SIGN		(3 | SMIME_OP | SMIME_SIGNERS)
85c8d13811Sjsing #define SMIME_VERIFY		(4 | SMIME_IP)
86c8d13811Sjsing #define SMIME_CMSOUT		(5 | SMIME_IP | SMIME_OP)
87c8d13811Sjsing #define SMIME_RESIGN		(6 | SMIME_IP | SMIME_OP | SMIME_SIGNERS)
88c8d13811Sjsing #define SMIME_DATAOUT		(7 | SMIME_IP)
89c8d13811Sjsing #define SMIME_DATA_CREATE	(8 | SMIME_OP)
90c8d13811Sjsing #define SMIME_DIGEST_VERIFY	(9 | SMIME_IP)
91c8d13811Sjsing #define SMIME_DIGEST_CREATE	(10 | SMIME_OP)
92c8d13811Sjsing #define SMIME_UNCOMPRESS	(11 | SMIME_IP)
93c8d13811Sjsing #define SMIME_COMPRESS		(12 | SMIME_OP)
94c8d13811Sjsing #define SMIME_ENCRYPTED_DECRYPT	(13 | SMIME_IP)
95c8d13811Sjsing #define SMIME_ENCRYPTED_ENCRYPT	(14 | SMIME_OP)
96c8d13811Sjsing #define SMIME_SIGN_RECEIPT	(15 | SMIME_IP | SMIME_OP)
97c8d13811Sjsing #define SMIME_VERIFY_RECEIPT	(16 | SMIME_IP)
98c8d13811Sjsing 
99c8d13811Sjsing int verify_err = 0;
100c8d13811Sjsing 
101514c2dabSinoguchi struct cms_key_param {
10299e5b935Sinoguchi 	int idx;
10399e5b935Sinoguchi 	STACK_OF(OPENSSL_STRING) *param;
104514c2dabSinoguchi 	struct cms_key_param *next;
10599e5b935Sinoguchi };
10699e5b935Sinoguchi 
107c49a7990Sinoguchi static struct {
108c49a7990Sinoguchi 	char *CAfile;
109c49a7990Sinoguchi 	char *CApath;
110c49a7990Sinoguchi 	X509 *cert;
111c49a7990Sinoguchi 	char *certfile;
112c49a7990Sinoguchi 	char *certsoutfile;
113*6156097aSjob 	char *crlfile;
114c49a7990Sinoguchi 	const EVP_CIPHER *cipher;
115c49a7990Sinoguchi 	char *contfile;
116c49a7990Sinoguchi 	ASN1_OBJECT *econtent_type;
117c49a7990Sinoguchi 	STACK_OF(X509) *encerts;
118c49a7990Sinoguchi 	int flags;
119c49a7990Sinoguchi 	char *from;
120c49a7990Sinoguchi 	char *infile;
121c49a7990Sinoguchi 	int informat;
122c49a7990Sinoguchi 	struct cms_key_param *key_first;
123c49a7990Sinoguchi 	struct cms_key_param *key_param;
124c49a7990Sinoguchi 	char *keyfile;
125c49a7990Sinoguchi 	int keyform;
126c49a7990Sinoguchi 	int noout;
127c49a7990Sinoguchi 	int operation;
128c49a7990Sinoguchi 	char *outfile;
129c49a7990Sinoguchi 	int outformat;
130c49a7990Sinoguchi 	char *passargin;
131c49a7990Sinoguchi 	int print;
132c49a7990Sinoguchi 	unsigned char *pwri_pass;
133c49a7990Sinoguchi 	int rr_allorfirst;
134c49a7990Sinoguchi 	STACK_OF(OPENSSL_STRING) *rr_from;
135c49a7990Sinoguchi 	int rr_print;
136c49a7990Sinoguchi 	STACK_OF(OPENSSL_STRING) *rr_to;
137c49a7990Sinoguchi 	char *rctfile;
138c49a7990Sinoguchi 	int rctformat;
139c49a7990Sinoguchi 	char *recipfile;
140c49a7990Sinoguchi 	unsigned char *secret_key;
141c49a7990Sinoguchi 	unsigned char *secret_keyid;
142c49a7990Sinoguchi 	size_t secret_keyidlen;
143c49a7990Sinoguchi 	size_t secret_keylen;
144c49a7990Sinoguchi 	const EVP_MD *sign_md;
145c49a7990Sinoguchi 	char *signerfile;
146c49a7990Sinoguchi 	STACK_OF(OPENSSL_STRING) *skkeys;
147c49a7990Sinoguchi 	STACK_OF(OPENSSL_STRING) *sksigners;
148c49a7990Sinoguchi 	char *subject;
149c49a7990Sinoguchi 	char *to;
150c49a7990Sinoguchi 	int verify_retcode;
151c49a7990Sinoguchi 	X509_VERIFY_PARAM *vpm;
152e7718adaStb } cfg;
153c49a7990Sinoguchi 
154c49a7990Sinoguchi static const EVP_CIPHER *
155c49a7990Sinoguchi get_cipher_by_name(char *name)
156c49a7990Sinoguchi {
157c49a7990Sinoguchi 	if (name == NULL || strcmp(name, "") == 0)
158c49a7990Sinoguchi 		return (NULL);
159c49a7990Sinoguchi #ifndef OPENSSL_NO_AES
160c49a7990Sinoguchi 	else if (strcmp(name, "aes128") == 0)
161c49a7990Sinoguchi 		return EVP_aes_128_cbc();
162c49a7990Sinoguchi 	else if (strcmp(name, "aes192") == 0)
163c49a7990Sinoguchi 		return EVP_aes_192_cbc();
164c49a7990Sinoguchi 	else if (strcmp(name, "aes256") == 0)
165c49a7990Sinoguchi 		return EVP_aes_256_cbc();
166c49a7990Sinoguchi #endif
167c49a7990Sinoguchi #ifndef OPENSSL_NO_CAMELLIA
168c49a7990Sinoguchi 	else if (strcmp(name, "camellia128") == 0)
169c49a7990Sinoguchi 		return EVP_camellia_128_cbc();
170c49a7990Sinoguchi 	else if (strcmp(name, "camellia192") == 0)
171c49a7990Sinoguchi 		return EVP_camellia_192_cbc();
172c49a7990Sinoguchi 	else if (strcmp(name, "camellia256") == 0)
173c49a7990Sinoguchi 		return EVP_camellia_256_cbc();
174c49a7990Sinoguchi #endif
175c49a7990Sinoguchi #ifndef OPENSSL_NO_DES
176c49a7990Sinoguchi 	else if (strcmp(name, "des") == 0)
177c49a7990Sinoguchi 		return EVP_des_cbc();
178c49a7990Sinoguchi 	else if (strcmp(name, "des3") == 0)
179c49a7990Sinoguchi 		return EVP_des_ede3_cbc();
180c49a7990Sinoguchi #endif
181c49a7990Sinoguchi #ifndef OPENSSL_NO_RC2
182c49a7990Sinoguchi 	else if (!strcmp(name, "rc2-40"))
183c49a7990Sinoguchi 		return EVP_rc2_40_cbc();
184c49a7990Sinoguchi 	else if (!strcmp(name, "rc2-64"))
185c49a7990Sinoguchi 		return EVP_rc2_64_cbc();
186c49a7990Sinoguchi 	else if (!strcmp(name, "rc2-128"))
187c49a7990Sinoguchi 		return EVP_rc2_cbc();
188c49a7990Sinoguchi #endif
189c49a7990Sinoguchi 	else
190c49a7990Sinoguchi 		return (NULL);
191c49a7990Sinoguchi }
192c49a7990Sinoguchi 
193c49a7990Sinoguchi static int
194c49a7990Sinoguchi cms_opt_cipher(int argc, char **argv, int *argsused)
195c49a7990Sinoguchi {
196c49a7990Sinoguchi 	char *name = argv[0];
197c49a7990Sinoguchi 
198c49a7990Sinoguchi 	if (*name++ != '-')
199c49a7990Sinoguchi 		return (1);
200c49a7990Sinoguchi 
201e7718adaStb 	if ((cfg.cipher = get_cipher_by_name(name)) == NULL)
202e7718adaStb 		if ((cfg.cipher = EVP_get_cipherbyname(name)) == NULL)
203c49a7990Sinoguchi 			return (1);
204c49a7990Sinoguchi 
205c49a7990Sinoguchi 	*argsused = 1;
206c49a7990Sinoguchi 	return (0);
207c49a7990Sinoguchi }
208c49a7990Sinoguchi 
209c49a7990Sinoguchi static int
210c49a7990Sinoguchi cms_opt_econtent_type(char *arg)
211c49a7990Sinoguchi {
212e7718adaStb 	ASN1_OBJECT_free(cfg.econtent_type);
21331ee89baSinoguchi 
214e7718adaStb 	if ((cfg.econtent_type = OBJ_txt2obj(arg, 0)) == NULL) {
215c49a7990Sinoguchi 		BIO_printf(bio_err, "Invalid OID %s\n", arg);
216c49a7990Sinoguchi 		return (1);
217c49a7990Sinoguchi 	}
218c49a7990Sinoguchi 	return (0);
219c49a7990Sinoguchi }
220c49a7990Sinoguchi 
221c49a7990Sinoguchi static int
222c49a7990Sinoguchi cms_opt_inkey(char *arg)
223c49a7990Sinoguchi {
224e7718adaStb 	if (cfg.keyfile == NULL) {
225e7718adaStb 		cfg.keyfile = arg;
226909cae1aSinoguchi 		return (0);
227909cae1aSinoguchi 	}
228909cae1aSinoguchi 
229e7718adaStb 	if (cfg.signerfile == NULL) {
230c49a7990Sinoguchi 		BIO_puts(bio_err, "Illegal -inkey without -signer\n");
231c49a7990Sinoguchi 		return (1);
232c49a7990Sinoguchi 	}
233c49a7990Sinoguchi 
234e7718adaStb 	if (cfg.sksigners == NULL)
235e7718adaStb 		cfg.sksigners = sk_OPENSSL_STRING_new_null();
236e7718adaStb 	if (cfg.sksigners == NULL)
237c49a7990Sinoguchi 		return (1);
238e7718adaStb 	if (!sk_OPENSSL_STRING_push(cfg.sksigners, cfg.signerfile))
239c49a7990Sinoguchi 		return (1);
240c49a7990Sinoguchi 
241e7718adaStb 	cfg.signerfile = NULL;
242c49a7990Sinoguchi 
243e7718adaStb 	if (cfg.skkeys == NULL)
244e7718adaStb 		cfg.skkeys = sk_OPENSSL_STRING_new_null();
245e7718adaStb 	if (cfg.skkeys == NULL)
246c49a7990Sinoguchi 		return (1);
247e7718adaStb 	if (!sk_OPENSSL_STRING_push(cfg.skkeys, cfg.keyfile))
248c49a7990Sinoguchi 		return (1);
249909cae1aSinoguchi 
250e7718adaStb 	cfg.keyfile = arg;
251c49a7990Sinoguchi 	return (0);
252c49a7990Sinoguchi }
253c49a7990Sinoguchi 
254c49a7990Sinoguchi static int
255c49a7990Sinoguchi cms_opt_keyopt(char *arg)
256c49a7990Sinoguchi {
257c49a7990Sinoguchi 	int keyidx = -1;
258c49a7990Sinoguchi 
259e7718adaStb 	if (cfg.operation == SMIME_ENCRYPT) {
260e7718adaStb 		if (cfg.encerts != NULL)
261e7718adaStb 			keyidx += sk_X509_num(cfg.encerts);
262c49a7990Sinoguchi 	} else {
263e7718adaStb 		if (cfg.keyfile != NULL || cfg.signerfile != NULL)
264c49a7990Sinoguchi 			keyidx++;
265e7718adaStb 		if (cfg.skkeys != NULL)
266e7718adaStb 			keyidx += sk_OPENSSL_STRING_num(cfg.skkeys);
267c49a7990Sinoguchi 	}
268c49a7990Sinoguchi 
269c49a7990Sinoguchi 	if (keyidx < 0) {
270c49a7990Sinoguchi 		BIO_printf(bio_err, "No key specified\n");
271c49a7990Sinoguchi 		return (1);
272c49a7990Sinoguchi 	}
273c49a7990Sinoguchi 
274e7718adaStb 	if (cfg.key_param == NULL ||
275e7718adaStb 	    cfg.key_param->idx != keyidx) {
276c49a7990Sinoguchi 		struct cms_key_param *nparam;
277c49a7990Sinoguchi 
278a99a5440Sinoguchi 		if ((nparam = calloc(1, sizeof(struct cms_key_param))) == NULL)
279c49a7990Sinoguchi 			return (1);
280c49a7990Sinoguchi 
281c49a7990Sinoguchi 		nparam->idx = keyidx;
282c49a7990Sinoguchi 		if ((nparam->param = sk_OPENSSL_STRING_new_null()) == NULL) {
283c49a7990Sinoguchi 			free(nparam);
284c49a7990Sinoguchi 			return (1);
285c49a7990Sinoguchi 		}
286c49a7990Sinoguchi 
287c49a7990Sinoguchi 		nparam->next = NULL;
288e7718adaStb 		if (cfg.key_first == NULL)
289e7718adaStb 			cfg.key_first = nparam;
290c49a7990Sinoguchi 		else
291e7718adaStb 			cfg.key_param->next = nparam;
292c49a7990Sinoguchi 
293e7718adaStb 		cfg.key_param = nparam;
294c49a7990Sinoguchi 	}
295c49a7990Sinoguchi 
296e7718adaStb 	if (!sk_OPENSSL_STRING_push(cfg.key_param->param, arg))
297c49a7990Sinoguchi 		return (1);
298c49a7990Sinoguchi 
299c49a7990Sinoguchi 	return (0);
300c49a7990Sinoguchi }
301c49a7990Sinoguchi 
302c49a7990Sinoguchi static int
303c49a7990Sinoguchi cms_opt_md(char *arg)
304c49a7990Sinoguchi {
305e7718adaStb 	if ((cfg.sign_md = EVP_get_digestbyname(arg)) == NULL) {
306c49a7990Sinoguchi 		BIO_printf(bio_err, "Unknown digest %s\n", arg);
307c49a7990Sinoguchi 		return (1);
308c49a7990Sinoguchi 	}
309c49a7990Sinoguchi 	return (0);
310c49a7990Sinoguchi }
311c49a7990Sinoguchi 
312c49a7990Sinoguchi static int
313c49a7990Sinoguchi cms_opt_print(void)
314c49a7990Sinoguchi {
315e7718adaStb 	cfg.noout = 1;
316e7718adaStb 	cfg.print = 1;
317c49a7990Sinoguchi 	return (0);
318c49a7990Sinoguchi }
319c49a7990Sinoguchi 
320c49a7990Sinoguchi static int
321c49a7990Sinoguchi cms_opt_pwri_pass(char *arg)
322c49a7990Sinoguchi {
323e7718adaStb 	cfg.pwri_pass = (unsigned char *)arg;
324c49a7990Sinoguchi 	return (0);
325c49a7990Sinoguchi }
326c49a7990Sinoguchi 
327c49a7990Sinoguchi static int
328c49a7990Sinoguchi cms_opt_recip(char *arg)
329c49a7990Sinoguchi {
330e7718adaStb 	if (cfg.operation == SMIME_ENCRYPT) {
331e7718adaStb 		if (cfg.encerts == NULL) {
332e7718adaStb 			if ((cfg.encerts = sk_X509_new_null()) == NULL)
333c49a7990Sinoguchi 				return (1);
334c49a7990Sinoguchi 		}
335c49a7990Sinoguchi 
336e7718adaStb 		cfg.cert = load_cert(bio_err, arg, FORMAT_PEM,
337c49a7990Sinoguchi 		    NULL, "recipient certificate file");
338e7718adaStb 		if (cfg.cert == NULL)
339c49a7990Sinoguchi 			return (1);
340c49a7990Sinoguchi 
341e7718adaStb 		if (!sk_X509_push(cfg.encerts, cfg.cert))
342c49a7990Sinoguchi 			return (1);
343c49a7990Sinoguchi 
344e7718adaStb 		cfg.cert = NULL;
345c49a7990Sinoguchi 	} else {
346e7718adaStb 		cfg.recipfile = arg;
347c49a7990Sinoguchi 	}
348c49a7990Sinoguchi 	return (0);
349c49a7990Sinoguchi }
350c49a7990Sinoguchi 
351c49a7990Sinoguchi static int
352c49a7990Sinoguchi cms_opt_receipt_request_from(char *arg)
353c49a7990Sinoguchi {
354e7718adaStb 	if (cfg.rr_from == NULL)
355e7718adaStb 		cfg.rr_from = sk_OPENSSL_STRING_new_null();
356e7718adaStb 	if (cfg.rr_from == NULL)
357c49a7990Sinoguchi 		return (1);
358e7718adaStb 	if (!sk_OPENSSL_STRING_push(cfg.rr_from, arg))
359c49a7990Sinoguchi 		return (1);
360c49a7990Sinoguchi 
361c49a7990Sinoguchi 	return (0);
362c49a7990Sinoguchi }
363c49a7990Sinoguchi 
364c49a7990Sinoguchi static int
365c49a7990Sinoguchi cms_opt_receipt_request_to(char *arg)
366c49a7990Sinoguchi {
367e7718adaStb 	if (cfg.rr_to == NULL)
368e7718adaStb 		cfg.rr_to = sk_OPENSSL_STRING_new_null();
369e7718adaStb 	if (cfg.rr_to == NULL)
370c49a7990Sinoguchi 		return (1);
371e7718adaStb 	if (!sk_OPENSSL_STRING_push(cfg.rr_to, arg))
372c49a7990Sinoguchi 		return (1);
373c49a7990Sinoguchi 
374c49a7990Sinoguchi 	return (0);
375c49a7990Sinoguchi }
376c49a7990Sinoguchi 
377c49a7990Sinoguchi static int
378c49a7990Sinoguchi cms_opt_secretkey(char *arg)
379c49a7990Sinoguchi {
380c49a7990Sinoguchi 	long ltmp;
381c49a7990Sinoguchi 
382e7718adaStb 	free(cfg.secret_key);
38331ee89baSinoguchi 
384e7718adaStb 	if ((cfg.secret_key = string_to_hex(arg, &ltmp)) == NULL) {
385c49a7990Sinoguchi 		BIO_printf(bio_err, "Invalid key %s\n", arg);
386c49a7990Sinoguchi 		return (1);
387c49a7990Sinoguchi 	}
388e7718adaStb 	cfg.secret_keylen = (size_t)ltmp;
389c49a7990Sinoguchi 	return (0);
390c49a7990Sinoguchi }
391c49a7990Sinoguchi 
392c49a7990Sinoguchi static int
393c49a7990Sinoguchi cms_opt_secretkeyid(char *arg)
394c49a7990Sinoguchi {
395c49a7990Sinoguchi 	long ltmp;
396c49a7990Sinoguchi 
397e7718adaStb 	free(cfg.secret_keyid);
39831ee89baSinoguchi 
399e7718adaStb 	if ((cfg.secret_keyid = string_to_hex(arg, &ltmp)) == NULL) {
400c49a7990Sinoguchi 		BIO_printf(bio_err, "Invalid id %s\n", arg);
401c49a7990Sinoguchi 		return (1);
402c49a7990Sinoguchi 	}
403e7718adaStb 	cfg.secret_keyidlen = (size_t)ltmp;
404c49a7990Sinoguchi 	return (0);
405c49a7990Sinoguchi }
406c49a7990Sinoguchi 
407c49a7990Sinoguchi static int
408c49a7990Sinoguchi cms_opt_signer(char *arg)
409c49a7990Sinoguchi {
410e7718adaStb 	if (cfg.signerfile == NULL) {
411e7718adaStb 		cfg.signerfile = arg;
412909cae1aSinoguchi 		return (0);
413909cae1aSinoguchi 	}
414909cae1aSinoguchi 
415e7718adaStb 	if (cfg.sksigners == NULL)
416e7718adaStb 		cfg.sksigners = sk_OPENSSL_STRING_new_null();
417e7718adaStb 	if (cfg.sksigners == NULL)
418c49a7990Sinoguchi 		return (1);
419e7718adaStb 	if (!sk_OPENSSL_STRING_push(cfg.sksigners, cfg.signerfile))
420c49a7990Sinoguchi 		return (1);
421c49a7990Sinoguchi 
422e7718adaStb 	if (cfg.keyfile == NULL)
423e7718adaStb 		cfg.keyfile = cfg.signerfile;
424c49a7990Sinoguchi 
425e7718adaStb 	if (cfg.skkeys == NULL)
426e7718adaStb 		cfg.skkeys = sk_OPENSSL_STRING_new_null();
427e7718adaStb 	if (cfg.skkeys == NULL)
428c49a7990Sinoguchi 		return (1);
429e7718adaStb 	if (!sk_OPENSSL_STRING_push(cfg.skkeys, cfg.keyfile))
430c49a7990Sinoguchi 		return (1);
431c49a7990Sinoguchi 
432e7718adaStb 	cfg.keyfile = NULL;
433909cae1aSinoguchi 
434e7718adaStb 	cfg.signerfile = arg;
435c49a7990Sinoguchi 	return (0);
436c49a7990Sinoguchi }
437c49a7990Sinoguchi 
438c49a7990Sinoguchi static int
439c49a7990Sinoguchi cms_opt_verify_param(int argc, char **argv, int *argsused)
440c49a7990Sinoguchi {
441c49a7990Sinoguchi 	int oargc = argc;
442c49a7990Sinoguchi 	int badarg = 0;
443c49a7990Sinoguchi 
444e7718adaStb 	if (!args_verify(&argv, &argc, &badarg, bio_err, &cfg.vpm))
445c49a7990Sinoguchi 		return (1);
446c49a7990Sinoguchi 	if (badarg)
447c49a7990Sinoguchi 		return (1);
448c49a7990Sinoguchi 
449c49a7990Sinoguchi 	*argsused = oargc - argc;
450c49a7990Sinoguchi 
451c49a7990Sinoguchi 	return (0);
452c49a7990Sinoguchi }
453c49a7990Sinoguchi 
454c49a7990Sinoguchi static int
455c49a7990Sinoguchi cms_opt_verify_receipt(char *arg)
456c49a7990Sinoguchi {
457e7718adaStb 	cfg.operation = SMIME_VERIFY_RECEIPT;
458e7718adaStb 	cfg.rctfile = arg;
459c49a7990Sinoguchi 	return (0);
460c49a7990Sinoguchi }
461c49a7990Sinoguchi 
462c49a7990Sinoguchi static const struct option cms_options[] = {
463c49a7990Sinoguchi #ifndef OPENSSL_NO_AES
464c49a7990Sinoguchi 	{
465c49a7990Sinoguchi 		.name = "aes128",
466c49a7990Sinoguchi 		.desc = "Encrypt PEM output with CBC AES",
467c49a7990Sinoguchi 		.type = OPTION_ARGV_FUNC,
468c49a7990Sinoguchi 		.opt.argvfunc = cms_opt_cipher,
469c49a7990Sinoguchi 	},
470c49a7990Sinoguchi 	{
471c49a7990Sinoguchi 		.name = "aes192",
472c49a7990Sinoguchi 		.desc = "Encrypt PEM output with CBC AES",
473c49a7990Sinoguchi 		.type = OPTION_ARGV_FUNC,
474c49a7990Sinoguchi 		.opt.argvfunc = cms_opt_cipher,
475c49a7990Sinoguchi 	},
476c49a7990Sinoguchi 	{
477c49a7990Sinoguchi 		.name = "aes256",
478c49a7990Sinoguchi 		.desc = "Encrypt PEM output with CBC AES",
479c49a7990Sinoguchi 		.type = OPTION_ARGV_FUNC,
480c49a7990Sinoguchi 		.opt.argvfunc = cms_opt_cipher,
481c49a7990Sinoguchi 	},
482c49a7990Sinoguchi #endif
483c49a7990Sinoguchi #ifndef OPENSSL_NO_CAMELLIA
484c49a7990Sinoguchi 	{
485c49a7990Sinoguchi 		.name = "camellia128",
486c49a7990Sinoguchi 		.desc = "Encrypt PEM output with CBC Camellia",
487c49a7990Sinoguchi 		.type = OPTION_ARGV_FUNC,
488c49a7990Sinoguchi 		.opt.argvfunc = cms_opt_cipher,
489c49a7990Sinoguchi 	},
490c49a7990Sinoguchi 	{
491c49a7990Sinoguchi 		.name = "camellia192",
492c49a7990Sinoguchi 		.desc = "Encrypt PEM output with CBC Camellia",
493c49a7990Sinoguchi 		.type = OPTION_ARGV_FUNC,
494c49a7990Sinoguchi 		.opt.argvfunc = cms_opt_cipher,
495c49a7990Sinoguchi 	},
496c49a7990Sinoguchi 	{
497c49a7990Sinoguchi 		.name = "camellia256",
498c49a7990Sinoguchi 		.desc = "Encrypt PEM output with CBC Camellia",
499c49a7990Sinoguchi 		.type = OPTION_ARGV_FUNC,
500c49a7990Sinoguchi 		.opt.argvfunc = cms_opt_cipher,
501c49a7990Sinoguchi 	},
502c49a7990Sinoguchi #endif
503c49a7990Sinoguchi #ifndef OPENSSL_NO_DES
504c49a7990Sinoguchi 	{
505c49a7990Sinoguchi 		.name = "des",
506c49a7990Sinoguchi 		.desc = "Encrypt with DES",
507c49a7990Sinoguchi 		.type = OPTION_ARGV_FUNC,
508c49a7990Sinoguchi 		.opt.argvfunc = cms_opt_cipher,
509c49a7990Sinoguchi 	},
510c49a7990Sinoguchi 	{
511c49a7990Sinoguchi 		.name = "des3",
51238ab7229Sinoguchi 		.desc = "Encrypt with triple DES (default)",
513c49a7990Sinoguchi 		.type = OPTION_ARGV_FUNC,
514c49a7990Sinoguchi 		.opt.argvfunc = cms_opt_cipher,
515c49a7990Sinoguchi 	},
516c49a7990Sinoguchi #endif
517c49a7990Sinoguchi #ifndef OPENSSL_NO_RC2
518c49a7990Sinoguchi 	{
519c49a7990Sinoguchi 		.name = "rc2-40",
52038ab7229Sinoguchi 		.desc = "Encrypt with RC2-40",
521c49a7990Sinoguchi 		.type = OPTION_ARGV_FUNC,
522c49a7990Sinoguchi 		.opt.argvfunc = cms_opt_cipher,
523c49a7990Sinoguchi 	},
524c49a7990Sinoguchi 	{
525c49a7990Sinoguchi 		.name = "rc2-64",
526c49a7990Sinoguchi 		.desc = "Encrypt with RC2-64",
527c49a7990Sinoguchi 		.type = OPTION_ARGV_FUNC,
528c49a7990Sinoguchi 		.opt.argvfunc = cms_opt_cipher,
529c49a7990Sinoguchi 	},
530c49a7990Sinoguchi 	{
531c49a7990Sinoguchi 		.name = "rc2-128",
532c49a7990Sinoguchi 		.desc = "Encrypt with RC2-128",
533c49a7990Sinoguchi 		.type = OPTION_ARGV_FUNC,
534c49a7990Sinoguchi 		.opt.argvfunc = cms_opt_cipher,
535c49a7990Sinoguchi 	},
536c49a7990Sinoguchi #endif
537c49a7990Sinoguchi 	{
538c49a7990Sinoguchi 		.name = "CAfile",
539c49a7990Sinoguchi 		.argname = "file",
540c49a7990Sinoguchi 		.desc = "Certificate Authority file",
541c49a7990Sinoguchi 		.type = OPTION_ARG,
542e7718adaStb 		.opt.arg = &cfg.CAfile,
543c49a7990Sinoguchi 	},
544c49a7990Sinoguchi 	{
545c49a7990Sinoguchi 		.name = "CApath",
546c49a7990Sinoguchi 		.argname = "path",
547c49a7990Sinoguchi 		.desc = "Certificate Authority path",
548c49a7990Sinoguchi 		.type = OPTION_ARG,
549e7718adaStb 		.opt.arg = &cfg.CApath,
550c49a7990Sinoguchi 	},
551c49a7990Sinoguchi 	{
552*6156097aSjob 		.name = "CRLfile",
553*6156097aSjob 		.argname = "file",
554*6156097aSjob 		.desc = "Other certificate revocation lists file",
555*6156097aSjob 		.type = OPTION_ARG,
556*6156097aSjob 		.opt.arg = &cfg.crlfile,
557*6156097aSjob 	},
558*6156097aSjob 	{
559c49a7990Sinoguchi 		.name = "binary",
560c49a7990Sinoguchi 		.desc = "Do not translate message to text",
561c49a7990Sinoguchi 		.type = OPTION_VALUE_OR,
562e7718adaStb 		.opt.value = &cfg.flags,
563c49a7990Sinoguchi 		.value = CMS_BINARY,
564c49a7990Sinoguchi 	},
565c49a7990Sinoguchi 	{
566c49a7990Sinoguchi 		.name = "certfile",
567c49a7990Sinoguchi 		.argname = "file",
568c49a7990Sinoguchi 		.desc = "Other certificates file",
569c49a7990Sinoguchi 		.type = OPTION_ARG,
570e7718adaStb 		.opt.arg = &cfg.certfile,
571c49a7990Sinoguchi 	},
572c49a7990Sinoguchi 	{
573c49a7990Sinoguchi 		.name = "certsout",
574c49a7990Sinoguchi 		.argname = "file",
575c49a7990Sinoguchi 		.desc = "Certificate output file",
576c49a7990Sinoguchi 		.type = OPTION_ARG,
577e7718adaStb 		.opt.arg = &cfg.certsoutfile,
578c49a7990Sinoguchi 	},
579c49a7990Sinoguchi 	{
580c49a7990Sinoguchi 		.name = "cmsout",
581c49a7990Sinoguchi 		.desc = "Output CMS structure",
582c49a7990Sinoguchi 		.type = OPTION_VALUE,
583e7718adaStb 		.opt.value = &cfg.operation,
584c49a7990Sinoguchi 		.value = SMIME_CMSOUT,
585c49a7990Sinoguchi 	},
586c49a7990Sinoguchi 	{
587c49a7990Sinoguchi 		.name = "compress",
588c49a7990Sinoguchi 		.desc = "Create CMS CompressedData type",
589c49a7990Sinoguchi 		.type = OPTION_VALUE,
590e7718adaStb 		.opt.value = &cfg.operation,
591c49a7990Sinoguchi 		.value = SMIME_COMPRESS,
592c49a7990Sinoguchi 	},
593c49a7990Sinoguchi 	{
594c49a7990Sinoguchi 		.name = "content",
595c49a7990Sinoguchi 		.argname = "file",
596c49a7990Sinoguchi 		.desc = "Supply or override content for detached signature",
597c49a7990Sinoguchi 		.type = OPTION_ARG,
598e7718adaStb 		.opt.arg = &cfg.contfile,
599c49a7990Sinoguchi 	},
600c49a7990Sinoguchi 	{
601c49a7990Sinoguchi 		.name = "crlfeol",
602c49a7990Sinoguchi 		.desc = "Use CRLF as EOL termination instead of CR only",
603c49a7990Sinoguchi 		.type = OPTION_VALUE_OR,
604e7718adaStb 		.opt.value = &cfg.flags,
605c49a7990Sinoguchi 		.value = CMS_CRLFEOL,
606c49a7990Sinoguchi 	},
607c49a7990Sinoguchi 	{
608c49a7990Sinoguchi 		.name = "data_create",
609c49a7990Sinoguchi 		.desc = "Create CMS Data type",
610c49a7990Sinoguchi 		.type = OPTION_VALUE,
611e7718adaStb 		.opt.value = &cfg.operation,
612c49a7990Sinoguchi 		.value = SMIME_DATA_CREATE,
613c49a7990Sinoguchi 	},
614c49a7990Sinoguchi 	{
615c49a7990Sinoguchi 		.name = "data_out",
616c49a7990Sinoguchi 		.desc = "Output content from the input CMS Data type",
617c49a7990Sinoguchi 		.type = OPTION_VALUE,
618e7718adaStb 		.opt.value = &cfg.operation,
619c49a7990Sinoguchi 		.value = SMIME_DATAOUT,
620c49a7990Sinoguchi 	},
621c49a7990Sinoguchi 	{
622c49a7990Sinoguchi 		.name = "debug_decrypt",
623c49a7990Sinoguchi 		.desc = "Set the CMS_DEBUG_DECRYPT flag when decrypting",
624c49a7990Sinoguchi 		.type = OPTION_VALUE_OR,
625e7718adaStb 		.opt.value = &cfg.flags,
626c49a7990Sinoguchi 		.value = CMS_DEBUG_DECRYPT,
627c49a7990Sinoguchi 	},
628c49a7990Sinoguchi 	{
629c49a7990Sinoguchi 		.name = "decrypt",
630c49a7990Sinoguchi 		.desc = "Decrypt encrypted message",
631c49a7990Sinoguchi 		.type = OPTION_VALUE,
632e7718adaStb 		.opt.value = &cfg.operation,
633c49a7990Sinoguchi 		.value = SMIME_DECRYPT,
634c49a7990Sinoguchi 	},
635c49a7990Sinoguchi 	{
636c49a7990Sinoguchi 		.name = "digest_create",
637c49a7990Sinoguchi 		.desc = "Create CMS DigestedData type",
638c49a7990Sinoguchi 		.type = OPTION_VALUE,
639e7718adaStb 		.opt.value = &cfg.operation,
640c49a7990Sinoguchi 		.value = SMIME_DIGEST_CREATE,
641c49a7990Sinoguchi 	},
642c49a7990Sinoguchi 	{
643c49a7990Sinoguchi 		.name = "digest_verify",
644c49a7990Sinoguchi 		.desc = "Verify CMS DigestedData type and output the content",
645c49a7990Sinoguchi 		.type = OPTION_VALUE,
646e7718adaStb 		.opt.value = &cfg.operation,
647c49a7990Sinoguchi 		.value = SMIME_DIGEST_VERIFY,
648c49a7990Sinoguchi 	},
649c49a7990Sinoguchi 	{
650c49a7990Sinoguchi 		.name = "econtent_type",
651c49a7990Sinoguchi 		.argname = "type",
652c49a7990Sinoguchi 		.desc = "Set the encapsulated content type",
653c49a7990Sinoguchi 		.type = OPTION_ARG_FUNC,
654c49a7990Sinoguchi 		.opt.argfunc = cms_opt_econtent_type,
655c49a7990Sinoguchi 	},
656c49a7990Sinoguchi 	{
657c49a7990Sinoguchi 		.name = "encrypt",
658c49a7990Sinoguchi 		.desc = "Encrypt message",
659c49a7990Sinoguchi 		.type = OPTION_VALUE,
660e7718adaStb 		.opt.value = &cfg.operation,
661c49a7990Sinoguchi 		.value = SMIME_ENCRYPT,
662c49a7990Sinoguchi 	},
663c49a7990Sinoguchi 	{
664c49a7990Sinoguchi 		.name = "EncryptedData_decrypt",
665c49a7990Sinoguchi 		.desc = "Decrypt CMS EncryptedData",
666c49a7990Sinoguchi 		.type = OPTION_VALUE,
667e7718adaStb 		.opt.value = &cfg.operation,
668c49a7990Sinoguchi 		.value = SMIME_ENCRYPTED_DECRYPT,
669c49a7990Sinoguchi 	},
670c49a7990Sinoguchi 	{
671c49a7990Sinoguchi 		.name = "EncryptedData_encrypt",
672c49a7990Sinoguchi 		.desc = "Encrypt content using supplied symmetric key and algorithm",
673c49a7990Sinoguchi 		.type = OPTION_VALUE,
674e7718adaStb 		.opt.value = &cfg.operation,
675c49a7990Sinoguchi 		.value = SMIME_ENCRYPTED_ENCRYPT,
676c49a7990Sinoguchi 	},
677c49a7990Sinoguchi 	{
678c49a7990Sinoguchi 		.name = "from",
679c49a7990Sinoguchi 		.argname = "addr",
680c49a7990Sinoguchi 		.desc = "From address",
681c49a7990Sinoguchi 		.type = OPTION_ARG,
682e7718adaStb 		.opt.arg = &cfg.from,
683c49a7990Sinoguchi 	},
684c49a7990Sinoguchi 	{
685c49a7990Sinoguchi 		.name = "in",
686c49a7990Sinoguchi 		.argname = "file",
687c49a7990Sinoguchi 		.desc = "Input file",
688c49a7990Sinoguchi 		.type = OPTION_ARG,
689e7718adaStb 		.opt.arg = &cfg.infile,
690c49a7990Sinoguchi 	},
691c49a7990Sinoguchi 	{
692c49a7990Sinoguchi 		.name = "indef",
693c49a7990Sinoguchi 		.desc = "Same as -stream",
694c49a7990Sinoguchi 		.type = OPTION_VALUE_OR,
695e7718adaStb 		.opt.value = &cfg.flags,
696c49a7990Sinoguchi 		.value = CMS_STREAM,
697c49a7990Sinoguchi 	},
698c49a7990Sinoguchi 	{
699c49a7990Sinoguchi 		.name = "inform",
700c49a7990Sinoguchi 		.argname = "fmt",
701c49a7990Sinoguchi 		.desc = "Input format (DER, PEM or SMIME (default))",
702c49a7990Sinoguchi 		.type = OPTION_ARG_FORMAT,
703e7718adaStb 		.opt.value = &cfg.informat,
704c49a7990Sinoguchi 	},
705c49a7990Sinoguchi 	{
706c49a7990Sinoguchi 		.name = "inkey",
707c49a7990Sinoguchi 		.argname = "file",
708c49a7990Sinoguchi 		.desc = "Input key file",
709c49a7990Sinoguchi 		.type = OPTION_ARG_FUNC,
710c49a7990Sinoguchi 		.opt.argfunc = cms_opt_inkey,
711c49a7990Sinoguchi 	},
712c49a7990Sinoguchi 	{
713c49a7990Sinoguchi 		.name = "keyform",
714c49a7990Sinoguchi 		.argname = "fmt",
715c49a7990Sinoguchi 		.desc = "Input key format (DER or PEM (default))",
716c49a7990Sinoguchi 		.type = OPTION_ARG_FORMAT,
717e7718adaStb 		.opt.value = &cfg.keyform,
718c49a7990Sinoguchi 	},
719c49a7990Sinoguchi 	{
720c49a7990Sinoguchi 		.name = "keyid",
721c49a7990Sinoguchi 		.desc = "Use subject key identifier",
722c49a7990Sinoguchi 		.type = OPTION_VALUE_OR,
723e7718adaStb 		.opt.value = &cfg.flags,
724c49a7990Sinoguchi 		.value = CMS_USE_KEYID,
725c49a7990Sinoguchi 	},
726c49a7990Sinoguchi 	{
727c49a7990Sinoguchi 		.name = "keyopt",
728c49a7990Sinoguchi 		.argname = "nm:v",
729c49a7990Sinoguchi 		.desc = "Set public key parameters",
730c49a7990Sinoguchi 		.type = OPTION_ARG_FUNC,
731c49a7990Sinoguchi 		.opt.argfunc = cms_opt_keyopt,
732c49a7990Sinoguchi 	},
733c49a7990Sinoguchi 	{
734c49a7990Sinoguchi 		.name = "md",
735c49a7990Sinoguchi 		.argname = "digest",
736c49a7990Sinoguchi 		.desc = "Digest to use when signing or resigning",
737c49a7990Sinoguchi 		.type = OPTION_ARG_FUNC,
738c49a7990Sinoguchi 		.opt.argfunc = cms_opt_md,
739c49a7990Sinoguchi 	},
740c49a7990Sinoguchi 	{
741c49a7990Sinoguchi 		.name = "no_attr_verify",
742c49a7990Sinoguchi 		.desc = "Do not verify the signer's attribute of a signature",
743c49a7990Sinoguchi 		.type = OPTION_VALUE_OR,
744e7718adaStb 		.opt.value = &cfg.flags,
745c49a7990Sinoguchi 		.value = CMS_NO_ATTR_VERIFY,
746c49a7990Sinoguchi 	},
747c49a7990Sinoguchi 	{
748c49a7990Sinoguchi 		.name = "no_content_verify",
749c49a7990Sinoguchi 		.desc = "Do not verify the content of a signed message",
750c49a7990Sinoguchi 		.type = OPTION_VALUE_OR,
751e7718adaStb 		.opt.value = &cfg.flags,
752c49a7990Sinoguchi 		.value = CMS_NO_CONTENT_VERIFY,
753c49a7990Sinoguchi 	},
754c49a7990Sinoguchi 	{
755c49a7990Sinoguchi 		.name = "no_signer_cert_verify",
756c49a7990Sinoguchi 		.desc = "Do not verify the signer's certificate",
757c49a7990Sinoguchi 		.type = OPTION_VALUE_OR,
758e7718adaStb 		.opt.value = &cfg.flags,
759c49a7990Sinoguchi 		.value = CMS_NO_SIGNER_CERT_VERIFY,
760c49a7990Sinoguchi 	},
761c49a7990Sinoguchi 	{
762c49a7990Sinoguchi 		.name = "noattr",
763c49a7990Sinoguchi 		.desc = "Do not include any signed attributes",
764c49a7990Sinoguchi 		.type = OPTION_VALUE_OR,
765e7718adaStb 		.opt.value = &cfg.flags,
766c49a7990Sinoguchi 		.value = CMS_NOATTR,
767c49a7990Sinoguchi 	},
768c49a7990Sinoguchi 	{
769c49a7990Sinoguchi 		.name = "nocerts",
770c49a7990Sinoguchi 		.desc = "Do not include signer's certificate when signing",
771c49a7990Sinoguchi 		.type = OPTION_VALUE_OR,
772e7718adaStb 		.opt.value = &cfg.flags,
773c49a7990Sinoguchi 		.value = CMS_NOCERTS,
774c49a7990Sinoguchi 	},
775c49a7990Sinoguchi 	{
776c49a7990Sinoguchi 		.name = "nodetach",
777c49a7990Sinoguchi 		.desc = "Use opaque signing",
778c49a7990Sinoguchi 		.type = OPTION_VALUE_AND,
779e7718adaStb 		.opt.value = &cfg.flags,
780c49a7990Sinoguchi 		.value = ~CMS_DETACHED,
781c49a7990Sinoguchi 	},
782c49a7990Sinoguchi 	{
783c49a7990Sinoguchi 		.name = "noindef",
784c49a7990Sinoguchi 		.desc = "Disable CMS streaming",
785c49a7990Sinoguchi 		.type = OPTION_VALUE_AND,
786e7718adaStb 		.opt.value = &cfg.flags,
787c49a7990Sinoguchi 		.value = ~CMS_STREAM,
788c49a7990Sinoguchi 	},
789c49a7990Sinoguchi 	{
790c49a7990Sinoguchi 		.name = "nointern",
791c49a7990Sinoguchi 		.desc = "Do not search certificates in message for signer",
792c49a7990Sinoguchi 		.type = OPTION_VALUE_OR,
793e7718adaStb 		.opt.value = &cfg.flags,
794c49a7990Sinoguchi 		.value = CMS_NOINTERN,
795c49a7990Sinoguchi 	},
796c49a7990Sinoguchi 	{
797c49a7990Sinoguchi 		.name = "nooldmime",
798c49a7990Sinoguchi 		.desc = "Output old S/MIME content type",
799c49a7990Sinoguchi 		.type = OPTION_VALUE_OR,
800e7718adaStb 		.opt.value = &cfg.flags,
801c49a7990Sinoguchi 		.value = CMS_NOOLDMIMETYPE,
802c49a7990Sinoguchi 	},
803c49a7990Sinoguchi 	{
804c49a7990Sinoguchi 		.name = "noout",
805c49a7990Sinoguchi 		.desc = "Do not output the parsed CMS structure",
806c49a7990Sinoguchi 		.type = OPTION_FLAG,
807e7718adaStb 		.opt.flag = &cfg.noout,
808c49a7990Sinoguchi 	},
809c49a7990Sinoguchi 	{
810c49a7990Sinoguchi 		.name = "nosigs",
811c49a7990Sinoguchi 		.desc = "Do not verify message signature",
812c49a7990Sinoguchi 		.type = OPTION_VALUE_OR,
813e7718adaStb 		.opt.value = &cfg.flags,
814c49a7990Sinoguchi 		.value = CMS_NOSIGS,
815c49a7990Sinoguchi 	},
816c49a7990Sinoguchi 	{
817c49a7990Sinoguchi 		.name = "nosmimecap",
818c49a7990Sinoguchi 		.desc = "Omit the SMIMECapabilities attribute",
819c49a7990Sinoguchi 		.type = OPTION_VALUE_OR,
820e7718adaStb 		.opt.value = &cfg.flags,
821c49a7990Sinoguchi 		.value = CMS_NOSMIMECAP,
822c49a7990Sinoguchi 	},
823c49a7990Sinoguchi 	{
824c49a7990Sinoguchi 		.name = "noverify",
825c49a7990Sinoguchi 		.desc = "Do not verify signer's certificate",
826c49a7990Sinoguchi 		.type = OPTION_VALUE_OR,
827e7718adaStb 		.opt.value = &cfg.flags,
828c49a7990Sinoguchi 		.value = CMS_NO_SIGNER_CERT_VERIFY,
829c49a7990Sinoguchi 	},
830c49a7990Sinoguchi 	{
831c49a7990Sinoguchi 		.name = "out",
832c49a7990Sinoguchi 		.argname = "file",
833c49a7990Sinoguchi 		.desc = "Output file",
834c49a7990Sinoguchi 		.type = OPTION_ARG,
835e7718adaStb 		.opt.arg = &cfg.outfile,
836c49a7990Sinoguchi 	},
837c49a7990Sinoguchi 	{
838c49a7990Sinoguchi 		.name = "outform",
839c49a7990Sinoguchi 		.argname = "fmt",
840c49a7990Sinoguchi 		.desc = "Output format (DER, PEM or SMIME (default))",
841c49a7990Sinoguchi 		.type = OPTION_ARG_FORMAT,
842e7718adaStb 		.opt.value = &cfg.outformat,
843c49a7990Sinoguchi 	},
844c49a7990Sinoguchi 	{
845c49a7990Sinoguchi 		.name = "passin",
846c49a7990Sinoguchi 		.argname = "src",
847c49a7990Sinoguchi 		.desc = "Private key password source",
848c49a7990Sinoguchi 		.type = OPTION_ARG,
849e7718adaStb 		.opt.arg = &cfg.passargin,
850c49a7990Sinoguchi 	},
851c49a7990Sinoguchi 	{
852c49a7990Sinoguchi 		.name = "print",
853c49a7990Sinoguchi 		.desc = "Print out all fields of the CMS structure for the -cmsout",
854c49a7990Sinoguchi 		.type = OPTION_FUNC,
855c49a7990Sinoguchi 		.opt.func = cms_opt_print,
856c49a7990Sinoguchi 	},
857c49a7990Sinoguchi 	{
858c49a7990Sinoguchi 		.name = "pwri_password",
859c49a7990Sinoguchi 		.argname = "arg",
860c49a7990Sinoguchi 		.desc = "Specify PasswordRecipientInfo (PWRI) password to use",
861c49a7990Sinoguchi 		.type = OPTION_ARG_FUNC,
862c49a7990Sinoguchi 		.opt.argfunc = cms_opt_pwri_pass,
863c49a7990Sinoguchi 	},
864c49a7990Sinoguchi 	{
865c49a7990Sinoguchi 		.name = "rctform",
866c49a7990Sinoguchi 		.argname = "fmt",
867c49a7990Sinoguchi 		.desc = "Receipt file format (DER, PEM or SMIME (default))",
868c49a7990Sinoguchi 		.type = OPTION_ARG_FORMAT,
869e7718adaStb 		.opt.value = &cfg.rctformat,
870c49a7990Sinoguchi 	},
871c49a7990Sinoguchi 	{
872c49a7990Sinoguchi 		.name = "receipt_request_all",
873c49a7990Sinoguchi 		.desc = "Indicate requests should be provided by all recipients",
874c49a7990Sinoguchi 		.type = OPTION_VALUE,
875e7718adaStb 		.opt.value = &cfg.rr_allorfirst,
876c49a7990Sinoguchi 		.value = 0,
877c49a7990Sinoguchi 	},
878c49a7990Sinoguchi 	{
879c49a7990Sinoguchi 		.name = "receipt_request_first",
880c49a7990Sinoguchi 		.desc = "Indicate requests should be provided by first tier recipient",
881c49a7990Sinoguchi 		.type = OPTION_VALUE,
882e7718adaStb 		.opt.value = &cfg.rr_allorfirst,
883c49a7990Sinoguchi 		.value = 1,
884c49a7990Sinoguchi 	},
885c49a7990Sinoguchi 	{
886c49a7990Sinoguchi 		.name = "receipt_request_from",
887c49a7990Sinoguchi 		.argname = "addr",
888c49a7990Sinoguchi 		.desc = "Add explicit email address where receipts should be supplied",
889c49a7990Sinoguchi 		.type = OPTION_ARG_FUNC,
890c49a7990Sinoguchi 		.opt.argfunc = cms_opt_receipt_request_from,
891c49a7990Sinoguchi 	},
892c49a7990Sinoguchi 	{
893c49a7990Sinoguchi 		.name = "receipt_request_print",
894c49a7990Sinoguchi 		.desc = "Print out the contents of any signed receipt requests",
895c49a7990Sinoguchi 		.type = OPTION_FLAG,
896e7718adaStb 		.opt.flag = &cfg.rr_print,
897c49a7990Sinoguchi 	},
898c49a7990Sinoguchi 	{
899c49a7990Sinoguchi 		.name = "receipt_request_to",
900c49a7990Sinoguchi 		.argname = "addr",
901c49a7990Sinoguchi 		.desc = "Add explicit email address where receipts should be sent to",
902c49a7990Sinoguchi 		.type = OPTION_ARG_FUNC,
903c49a7990Sinoguchi 		.opt.argfunc = cms_opt_receipt_request_to,
904c49a7990Sinoguchi 	},
905c49a7990Sinoguchi 	{
906c49a7990Sinoguchi 		.name = "recip",
907c49a7990Sinoguchi 		.argname = "file",
908c49a7990Sinoguchi 		.desc = "Recipient certificate file for decryption",
909c49a7990Sinoguchi 		.type = OPTION_ARG_FUNC,
910c49a7990Sinoguchi 		.opt.argfunc = cms_opt_recip,
911c49a7990Sinoguchi 	},
912c49a7990Sinoguchi 	{
913c49a7990Sinoguchi 		.name = "resign",
914c49a7990Sinoguchi 		.desc = "Resign a signed message",
915c49a7990Sinoguchi 		.type = OPTION_VALUE,
916e7718adaStb 		.opt.value = &cfg.operation,
917c49a7990Sinoguchi 		.value = SMIME_RESIGN,
918c49a7990Sinoguchi 	},
919c49a7990Sinoguchi 	{
920c49a7990Sinoguchi 		.name = "secretkey",
921c49a7990Sinoguchi 		.argname = "key",
922c49a7990Sinoguchi 		.desc = "Specify symmetric key to use",
923c49a7990Sinoguchi 		.type = OPTION_ARG_FUNC,
924c49a7990Sinoguchi 		.opt.argfunc = cms_opt_secretkey,
925c49a7990Sinoguchi 	},
926c49a7990Sinoguchi 	{
927c49a7990Sinoguchi 		.name = "secretkeyid",
928c49a7990Sinoguchi 		.argname = "id",
929c49a7990Sinoguchi 		.desc = "The key identifier for the supplied symmetric key",
930c49a7990Sinoguchi 		.type = OPTION_ARG_FUNC,
931c49a7990Sinoguchi 		.opt.argfunc = cms_opt_secretkeyid,
932c49a7990Sinoguchi 	},
933c49a7990Sinoguchi 	{
934c49a7990Sinoguchi 		.name = "sign",
935c49a7990Sinoguchi 		.desc = "Sign message",
936c49a7990Sinoguchi 		.type = OPTION_VALUE,
937e7718adaStb 		.opt.value = &cfg.operation,
938c49a7990Sinoguchi 		.value = SMIME_SIGN,
939c49a7990Sinoguchi 	},
940c49a7990Sinoguchi 	{
941c49a7990Sinoguchi 		.name = "sign_receipt",
942c49a7990Sinoguchi 		.desc = "Generate a signed receipt for the message",
943c49a7990Sinoguchi 		.type = OPTION_VALUE,
944e7718adaStb 		.opt.value = &cfg.operation,
945c49a7990Sinoguchi 		.value = SMIME_SIGN_RECEIPT,
946c49a7990Sinoguchi 	},
947c49a7990Sinoguchi 	{
948c49a7990Sinoguchi 		.name = "signer",
949c49a7990Sinoguchi 		.argname = "file",
950c49a7990Sinoguchi 		.desc = "Signer certificate file",
951c49a7990Sinoguchi 		.type = OPTION_ARG_FUNC,
952c49a7990Sinoguchi 		.opt.argfunc = cms_opt_signer,
953c49a7990Sinoguchi 	},
954c49a7990Sinoguchi 	{
955c49a7990Sinoguchi 		.name = "stream",
956c49a7990Sinoguchi 		.desc = "Enable CMS streaming",
957c49a7990Sinoguchi 		.type = OPTION_VALUE_OR,
958e7718adaStb 		.opt.value = &cfg.flags,
959c49a7990Sinoguchi 		.value = CMS_STREAM,
960c49a7990Sinoguchi 	},
961c49a7990Sinoguchi 	{
962c49a7990Sinoguchi 		.name = "subject",
963c49a7990Sinoguchi 		.argname = "s",
964c49a7990Sinoguchi 		.desc = "Subject",
965c49a7990Sinoguchi 		.type = OPTION_ARG,
966e7718adaStb 		.opt.arg = &cfg.subject,
967c49a7990Sinoguchi 	},
968c49a7990Sinoguchi 	{
969c49a7990Sinoguchi 		.name = "text",
970c49a7990Sinoguchi 		.desc = "Include or delete text MIME headers",
971c49a7990Sinoguchi 		.type = OPTION_VALUE_OR,
972e7718adaStb 		.opt.value = &cfg.flags,
973c49a7990Sinoguchi 		.value = CMS_TEXT,
974c49a7990Sinoguchi 	},
975c49a7990Sinoguchi 	{
976c49a7990Sinoguchi 		.name = "to",
977c49a7990Sinoguchi 		.argname = "addr",
978c49a7990Sinoguchi 		.desc = "To address",
979c49a7990Sinoguchi 		.type = OPTION_ARG,
980e7718adaStb 		.opt.arg = &cfg.to,
981c49a7990Sinoguchi 	},
982c49a7990Sinoguchi 	{
983c49a7990Sinoguchi 		.name = "uncompress",
984c49a7990Sinoguchi 		.desc = "Uncompress CMS CompressedData type",
985c49a7990Sinoguchi 		.type = OPTION_VALUE,
986e7718adaStb 		.opt.value = &cfg.operation,
987c49a7990Sinoguchi 		.value = SMIME_UNCOMPRESS,
988c49a7990Sinoguchi 	},
989c49a7990Sinoguchi 	{
990c49a7990Sinoguchi 		.name = "verify",
991c49a7990Sinoguchi 		.desc = "Verify signed message",
992c49a7990Sinoguchi 		.type = OPTION_VALUE,
993e7718adaStb 		.opt.value = &cfg.operation,
994c49a7990Sinoguchi 		.value = SMIME_VERIFY,
995c49a7990Sinoguchi 	},
996c49a7990Sinoguchi 	{
997c49a7990Sinoguchi 		.name = "verify_receipt",
998c49a7990Sinoguchi 		.argname = "file",
999c49a7990Sinoguchi 		.desc = "Verify a signed receipt in file",
1000c49a7990Sinoguchi 		.type = OPTION_ARG_FUNC,
1001c49a7990Sinoguchi 		.opt.argfunc = cms_opt_verify_receipt,
1002c49a7990Sinoguchi 	},
1003c49a7990Sinoguchi 	{
1004c49a7990Sinoguchi 		.name = "verify_retcode",
1005c49a7990Sinoguchi 		.desc = "Set verification error code to exit code",
1006c49a7990Sinoguchi 		.type = OPTION_FLAG,
1007e7718adaStb 		.opt.flag = &cfg.verify_retcode,
1008c49a7990Sinoguchi 	},
1009c49a7990Sinoguchi 	{
1010c49a7990Sinoguchi 		.name = "check_ss_sig",
1011c49a7990Sinoguchi 		.type = OPTION_ARGV_FUNC,
1012c49a7990Sinoguchi 		.opt.argvfunc = cms_opt_verify_param,
1013c49a7990Sinoguchi 	},
1014c49a7990Sinoguchi 	{
1015c49a7990Sinoguchi 		.name = "crl_check",
1016c49a7990Sinoguchi 		.type = OPTION_ARGV_FUNC,
1017c49a7990Sinoguchi 		.opt.argvfunc = cms_opt_verify_param,
1018c49a7990Sinoguchi 	},
1019c49a7990Sinoguchi 	{
1020c49a7990Sinoguchi 		.name = "crl_check_all",
1021c49a7990Sinoguchi 		.type = OPTION_ARGV_FUNC,
1022c49a7990Sinoguchi 		.opt.argvfunc = cms_opt_verify_param,
1023c49a7990Sinoguchi 	},
1024c49a7990Sinoguchi 	{
1025c49a7990Sinoguchi 		.name = "extended_crl",
1026c49a7990Sinoguchi 		.type = OPTION_ARGV_FUNC,
1027c49a7990Sinoguchi 		.opt.argvfunc = cms_opt_verify_param,
1028c49a7990Sinoguchi 	},
1029c49a7990Sinoguchi 	{
1030c49a7990Sinoguchi 		.name = "ignore_critical",
1031c49a7990Sinoguchi 		.type = OPTION_ARGV_FUNC,
1032c49a7990Sinoguchi 		.opt.argvfunc = cms_opt_verify_param,
1033c49a7990Sinoguchi 	},
1034c49a7990Sinoguchi 	{
1035c49a7990Sinoguchi 		.name = "issuer_checks",
1036c49a7990Sinoguchi 		.type = OPTION_ARGV_FUNC,
1037c49a7990Sinoguchi 		.opt.argvfunc = cms_opt_verify_param,
1038c49a7990Sinoguchi 	},
1039c49a7990Sinoguchi 	{
1040c49a7990Sinoguchi 		.name = "policy",
1041c49a7990Sinoguchi 		.type = OPTION_ARGV_FUNC,
1042c49a7990Sinoguchi 		.opt.argvfunc = cms_opt_verify_param,
1043c49a7990Sinoguchi 	},
1044c49a7990Sinoguchi 	{
1045c49a7990Sinoguchi 		.name = "policy_check",
1046c49a7990Sinoguchi 		.type = OPTION_ARGV_FUNC,
1047c49a7990Sinoguchi 		.opt.argvfunc = cms_opt_verify_param,
1048c49a7990Sinoguchi 	},
1049c49a7990Sinoguchi 	{
1050c49a7990Sinoguchi 		.name = "purpose",
1051c49a7990Sinoguchi 		.type = OPTION_ARGV_FUNC,
1052c49a7990Sinoguchi 		.opt.argvfunc = cms_opt_verify_param,
1053c49a7990Sinoguchi 	},
1054c49a7990Sinoguchi 	{
1055c49a7990Sinoguchi 		.name = "x509_strict",
1056c49a7990Sinoguchi 		.type = OPTION_ARGV_FUNC,
1057c49a7990Sinoguchi 		.opt.argvfunc = cms_opt_verify_param,
1058c49a7990Sinoguchi 	},
1059c49a7990Sinoguchi 	{
1060c49a7990Sinoguchi 		.name = NULL,
1061c49a7990Sinoguchi 		.type = OPTION_ARGV_FUNC,
1062c49a7990Sinoguchi 		.opt.argvfunc = cms_opt_cipher,
1063c49a7990Sinoguchi 	},
1064c49a7990Sinoguchi 	{ NULL },
1065c49a7990Sinoguchi };
1066c49a7990Sinoguchi 
1067c49a7990Sinoguchi static const struct option verify_shared_options[] = {
1068c49a7990Sinoguchi 	{
1069c49a7990Sinoguchi 		.name = "check_ss_sig",
1070c49a7990Sinoguchi 		.desc = "Check the root CA self-signed certificate signature",
1071c49a7990Sinoguchi 	},
1072c49a7990Sinoguchi 	{
1073c49a7990Sinoguchi 		.name = "crl_check",
1074c49a7990Sinoguchi 		.desc = "Enable CRL checking for the leaf certificate",
1075c49a7990Sinoguchi 	},
1076c49a7990Sinoguchi 	{
1077c49a7990Sinoguchi 		.name = "crl_check_all",
1078c49a7990Sinoguchi 		.desc = "Enable CRL checking for the entire certificate chain",
1079c49a7990Sinoguchi 	},
1080c49a7990Sinoguchi 	{
1081c49a7990Sinoguchi 		.name = "extended_crl",
1082c49a7990Sinoguchi 		.desc = "Enable extended CRL support",
1083c49a7990Sinoguchi 	},
1084c49a7990Sinoguchi 	{
1085c49a7990Sinoguchi 		.name = "ignore_critical",
1086c49a7990Sinoguchi 		.desc = "Disable critical extension checking",
1087c49a7990Sinoguchi 	},
1088c49a7990Sinoguchi 	{
1089c49a7990Sinoguchi 		.name = "issuer_checks",
1090c49a7990Sinoguchi 		.desc = "Enable debugging of certificate issuer checks",
1091c49a7990Sinoguchi 	},
1092c49a7990Sinoguchi 	{
1093c49a7990Sinoguchi 		.name = "policy",
1094c49a7990Sinoguchi 		.argname = "name",
1095c49a7990Sinoguchi 		.desc = "Add given policy to the acceptable set",
1096c49a7990Sinoguchi 	},
1097c49a7990Sinoguchi 	{
1098c49a7990Sinoguchi 		.name = "policy_check",
1099c49a7990Sinoguchi 		.desc = "Enable certificate policy checking",
1100c49a7990Sinoguchi 	},
1101c49a7990Sinoguchi 	{
1102c49a7990Sinoguchi 		.name = "purpose",
1103c49a7990Sinoguchi 		.argname = "name",
1104c49a7990Sinoguchi 		.desc = "Verify for the given purpose",
1105c49a7990Sinoguchi 	},
1106c49a7990Sinoguchi 	{
1107c49a7990Sinoguchi 		.name = "x509_strict",
1108c49a7990Sinoguchi 		.desc = "Use strict X.509 rules (disables workarounds)",
1109c49a7990Sinoguchi 	},
1110c49a7990Sinoguchi 	{ NULL },
1111c49a7990Sinoguchi };
1112c49a7990Sinoguchi 
1113c49a7990Sinoguchi static void
1114c49a7990Sinoguchi cms_usage(void)
1115c49a7990Sinoguchi {
1116c49a7990Sinoguchi 	int i;
1117c49a7990Sinoguchi 
1118c49a7990Sinoguchi 	fprintf(stderr, "usage: cms "
1119c49a7990Sinoguchi 	    "[-aes128 | -aes192 | -aes256 | -camellia128 |\n"
1120c49a7990Sinoguchi 	    "    -camellia192 | -camellia256 | -des | -des3 |\n"
1121c49a7990Sinoguchi 	    "    -rc2-40 | -rc2-64 | -rc2-128] [-CAfile file]\n"
1122*6156097aSjob 	    "    [-CApath directory] [-CRLfile file] [-binary]\n"
1123*6156097aSjob 	    "    [-certfile file] [-certsout file] [-cmsout] [-compress]\n"
1124*6156097aSjob 	    "    [-content file] [-crlfeol] [-data_create] [-data_out]\n"
1125*6156097aSjob 	    "    [-debug_decrypt] [-decrypt] [-digest_create] [-digest_verify]\n"
1126c49a7990Sinoguchi 	    "    [-econtent_type type] [-encrypt] [-EncryptedData_decrypt]\n"
1127c49a7990Sinoguchi 	    "    [-EncryptedData_encrypt] [-from addr] [-in file]\n"
1128c49a7990Sinoguchi 	    "    [-inform der | pem | smime] [-inkey file]\n"
1129c49a7990Sinoguchi 	    "    [-keyform der | pem] [-keyid] [-keyopt nm:v] [-md digest]\n"
1130c49a7990Sinoguchi 	    "    [-no_attr_verify] [-no_content_verify]\n"
1131c49a7990Sinoguchi 	    "    [-no_signer_cert_verify] [-noattr] [-nocerts] [-nodetach]\n"
1132c49a7990Sinoguchi 	    "    [-nointern] [-nooldmime] [-noout] [-nosigs] [-nosmimecap]\n"
1133c49a7990Sinoguchi 	    "    [-noverify] [-out file] [-outform der | pem | smime]\n"
1134c49a7990Sinoguchi 	    "    [-passin src] [-print] [-pwri_password arg]\n"
1135c49a7990Sinoguchi 	    "    [-rctform der | pem | smime]\n"
1136c49a7990Sinoguchi 	    "    [-receipt_request_all | -receipt_request_first]\n"
1137c49a7990Sinoguchi 	    "    [-receipt_request_from addr] [-receipt_request_print]\n"
1138c49a7990Sinoguchi 	    "    [-receipt_request_to addr] [-recip file] [-resign]\n"
1139c49a7990Sinoguchi 	    "    [-secretkey key] [-secretkeyid id] [-sign] [-sign_receipt]\n"
1140c49a7990Sinoguchi 	    "    [-signer file] [-stream | -indef | -noindef] [-subject s]\n"
1141c49a7990Sinoguchi 	    "    [-text] [-to addr] [-uncompress] [-verify]\n"
1142c49a7990Sinoguchi 	    "    [-verify_receipt file] [-verify_retcode] [cert.pem ...]\n\n");
1143c49a7990Sinoguchi 
1144c49a7990Sinoguchi 	options_usage(cms_options);
1145c49a7990Sinoguchi 
1146c49a7990Sinoguchi 	fprintf(stderr, "\nVerification options:\n\n");
1147c49a7990Sinoguchi 	options_usage(verify_shared_options);
1148c49a7990Sinoguchi 
1149c49a7990Sinoguchi 	fprintf(stderr, "\nValid purposes:\n\n");
1150c49a7990Sinoguchi 	for (i = 0; i < X509_PURPOSE_get_count(); i++) {
11515bbf7eacStb 		const X509_PURPOSE *ptmp = X509_PURPOSE_get0(i);
1152c49a7990Sinoguchi 		fprintf(stderr, "  %-18s%s\n", X509_PURPOSE_get0_sname(ptmp),
1153c49a7990Sinoguchi 		    X509_PURPOSE_get0_name(ptmp));
1154c49a7990Sinoguchi 	}
1155c49a7990Sinoguchi }
1156c49a7990Sinoguchi 
1157c8d13811Sjsing int
1158c8d13811Sjsing cms_main(int argc, char **argv)
1159c8d13811Sjsing {
1160c8d13811Sjsing 	int ret = 0;
1161c8d13811Sjsing 	char **args;
1162c49a7990Sinoguchi 	int argsused = 0;
1163c8d13811Sjsing 	const char *inmode = "r", *outmode = "w";
1164c8d13811Sjsing 	CMS_ContentInfo *cms = NULL, *rcms = NULL;
1165c8d13811Sjsing 	X509_STORE *store = NULL;
1166c49a7990Sinoguchi 	X509 *recip = NULL, *signer = NULL;
1167c8d13811Sjsing 	EVP_PKEY *key = NULL;
1168c49a7990Sinoguchi 	STACK_OF(X509) *other = NULL;
1169*6156097aSjob 	STACK_OF(X509_CRL) *crls = NULL;
1170c8d13811Sjsing 	BIO *in = NULL, *out = NULL, *indata = NULL, *rctin = NULL;
1171c8d13811Sjsing 	int badarg = 0;
1172c8d13811Sjsing 	CMS_ReceiptRequest *rr = NULL;
1173c49a7990Sinoguchi 	char *passin = NULL;
1174c49a7990Sinoguchi 	unsigned char *pwri_tmp = NULL;
1175c8d13811Sjsing 
1176c8d13811Sjsing 	if (pledge("stdio rpath wpath cpath tty", NULL) == -1) {
1177c8d13811Sjsing 		perror("pledge");
1178c8d13811Sjsing 		exit(1);
1179c8d13811Sjsing 	}
1180c8d13811Sjsing 
1181e7718adaStb 	memset(&cfg, 0, sizeof(cfg));
1182e7718adaStb 	cfg.flags = CMS_DETACHED;
1183e7718adaStb 	cfg.rr_allorfirst = -1;
1184e7718adaStb 	cfg.informat = FORMAT_SMIME;
1185e7718adaStb 	cfg.outformat = FORMAT_SMIME;
1186e7718adaStb 	cfg.rctformat = FORMAT_SMIME;
1187e7718adaStb 	cfg.keyform = FORMAT_PEM;
1188c49a7990Sinoguchi 	if (options_parse(argc, argv, cms_options, NULL, &argsused) != 0) {
1189c49a7990Sinoguchi 		goto argerr;
1190c49a7990Sinoguchi 	}
1191c49a7990Sinoguchi 	args = argv + argsused;
1192c8d13811Sjsing 	ret = 1;
1193c8d13811Sjsing 
1194e7718adaStb 	if (((cfg.rr_allorfirst != -1) || cfg.rr_from != NULL) &&
1195e7718adaStb 	    cfg.rr_to == NULL) {
1196c8d13811Sjsing 		BIO_puts(bio_err, "No Signed Receipts Recipients\n");
1197c8d13811Sjsing 		goto argerr;
1198c8d13811Sjsing 	}
1199e7718adaStb 	if (!(cfg.operation & SMIME_SIGNERS) &&
1200e7718adaStb 	    (cfg.rr_to != NULL || cfg.rr_from != NULL)) {
1201c8d13811Sjsing 		BIO_puts(bio_err, "Signed receipts only allowed with -sign\n");
1202c8d13811Sjsing 		goto argerr;
1203c8d13811Sjsing 	}
1204e7718adaStb 	if (!(cfg.operation & SMIME_SIGNERS) &&
1205e7718adaStb 	    (cfg.skkeys != NULL || cfg.sksigners != NULL)) {
1206c8d13811Sjsing 		BIO_puts(bio_err, "Multiple signers or keys not allowed\n");
1207c8d13811Sjsing 		goto argerr;
1208c8d13811Sjsing 	}
1209e7718adaStb 	if (cfg.operation & SMIME_SIGNERS) {
1210e7718adaStb 		if (cfg.keyfile != NULL &&
1211e7718adaStb 		    cfg.signerfile == NULL) {
1212c8d13811Sjsing 			BIO_puts(bio_err, "Illegal -inkey without -signer\n");
1213c8d13811Sjsing 			goto argerr;
1214c8d13811Sjsing 		}
1215c8d13811Sjsing 		/* Check to see if any final signer needs to be appended */
1216e7718adaStb 		if (cfg.signerfile != NULL) {
1217e7718adaStb 			if (cfg.sksigners == NULL &&
1218e7718adaStb 			    (cfg.sksigners =
121930b9607cSinoguchi 			    sk_OPENSSL_STRING_new_null()) == NULL)
1220d4271273Sinoguchi 				goto end;
1221e7718adaStb 			if (!sk_OPENSSL_STRING_push(cfg.sksigners,
1222e7718adaStb 			    cfg.signerfile))
1223514c2dabSinoguchi 				goto end;
1224e7718adaStb 			if (cfg.skkeys == NULL &&
1225e7718adaStb 			    (cfg.skkeys =
122630b9607cSinoguchi 			    sk_OPENSSL_STRING_new_null()) == NULL)
1227d4271273Sinoguchi 				goto end;
1228e7718adaStb 			if (cfg.keyfile == NULL)
1229e7718adaStb 				cfg.keyfile = cfg.signerfile;
1230e7718adaStb 			if (!sk_OPENSSL_STRING_push(cfg.skkeys,
1231e7718adaStb 			    cfg.keyfile))
1232514c2dabSinoguchi 				goto end;
1233c8d13811Sjsing 		}
1234e7718adaStb 		if (cfg.sksigners == NULL) {
1235c8d13811Sjsing 			BIO_printf(bio_err,
1236c8d13811Sjsing 			    "No signer certificate specified\n");
1237c8d13811Sjsing 			badarg = 1;
1238c8d13811Sjsing 		}
1239e7718adaStb 		cfg.signerfile = NULL;
1240e7718adaStb 		cfg.keyfile = NULL;
1241e7718adaStb 	} else if (cfg.operation == SMIME_DECRYPT) {
1242e7718adaStb 		if (cfg.recipfile == NULL &&
1243e7718adaStb 		    cfg.keyfile == NULL &&
1244e7718adaStb 		    cfg.secret_key == NULL &&
1245e7718adaStb 		    cfg.pwri_pass == NULL) {
1246c8d13811Sjsing 			BIO_printf(bio_err,
1247c8d13811Sjsing 			    "No recipient certificate or key specified\n");
1248c8d13811Sjsing 			badarg = 1;
1249c8d13811Sjsing 		}
1250e7718adaStb 	} else if (cfg.operation == SMIME_ENCRYPT) {
1251e7718adaStb 		if (*args == NULL && cfg.secret_key == NULL &&
1252e7718adaStb 		    cfg.pwri_pass == NULL &&
1253e7718adaStb 		    cfg.encerts == NULL) {
1254c8d13811Sjsing 			BIO_printf(bio_err,
1255c8d13811Sjsing 			    "No recipient(s) certificate(s) specified\n");
1256c8d13811Sjsing 			badarg = 1;
1257c8d13811Sjsing 		}
1258e7718adaStb 	} else if (!cfg.operation) {
1259c8d13811Sjsing 		badarg = 1;
126030b9607cSinoguchi 	}
1261c8d13811Sjsing 
1262c8d13811Sjsing 	if (badarg) {
1263c8d13811Sjsing  argerr:
1264c49a7990Sinoguchi 		cms_usage();
1265c8d13811Sjsing 		goto end;
1266c8d13811Sjsing 	}
1267c8d13811Sjsing 
1268e7718adaStb 	if (!app_passwd(bio_err, cfg.passargin, NULL, &passin, NULL)) {
1269c8d13811Sjsing 		BIO_printf(bio_err, "Error getting password\n");
1270c8d13811Sjsing 		goto end;
1271c8d13811Sjsing 	}
1272c8d13811Sjsing 	ret = 2;
1273c8d13811Sjsing 
1274e7718adaStb 	if (!(cfg.operation & SMIME_SIGNERS))
1275e7718adaStb 		cfg.flags &= ~CMS_DETACHED;
1276c8d13811Sjsing 
1277e7718adaStb 	if (cfg.operation & SMIME_OP) {
1278e7718adaStb 		if (cfg.outformat == FORMAT_ASN1)
1279c8d13811Sjsing 			outmode = "wb";
1280c8d13811Sjsing 	} else {
1281e7718adaStb 		if (cfg.flags & CMS_BINARY)
1282c8d13811Sjsing 			outmode = "wb";
1283c8d13811Sjsing 	}
1284c8d13811Sjsing 
1285e7718adaStb 	if (cfg.operation & SMIME_IP) {
1286e7718adaStb 		if (cfg.informat == FORMAT_ASN1)
1287c8d13811Sjsing 			inmode = "rb";
1288c8d13811Sjsing 	} else {
1289e7718adaStb 		if (cfg.flags & CMS_BINARY)
1290c8d13811Sjsing 			inmode = "rb";
1291c8d13811Sjsing 	}
1292c8d13811Sjsing 
1293e7718adaStb 	if (cfg.operation == SMIME_ENCRYPT) {
1294e7718adaStb 		if (cfg.cipher == NULL) {
1295c8d13811Sjsing #ifndef OPENSSL_NO_DES
1296e7718adaStb 			cfg.cipher = EVP_des_ede3_cbc();
1297c8d13811Sjsing #else
1298c8d13811Sjsing 			BIO_printf(bio_err, "No cipher selected\n");
1299c8d13811Sjsing 			goto end;
1300c8d13811Sjsing #endif
1301c8d13811Sjsing 		}
1302e7718adaStb 		if (cfg.secret_key != NULL &&
1303e7718adaStb 		    cfg.secret_keyid == NULL) {
1304c8d13811Sjsing 			BIO_printf(bio_err, "No secret key id\n");
1305c8d13811Sjsing 			goto end;
1306c8d13811Sjsing 		}
1307e7718adaStb 		if (*args != NULL && cfg.encerts == NULL)
1308e7718adaStb 			if ((cfg.encerts = sk_X509_new_null()) == NULL)
1309d4271273Sinoguchi 				goto end;
1310c8d13811Sjsing 		while (*args) {
1311e7718adaStb 			if ((cfg.cert = load_cert(bio_err, *args,
131230b9607cSinoguchi 			    FORMAT_PEM, NULL,
131330b9607cSinoguchi 			    "recipient certificate file")) == NULL)
1314c8d13811Sjsing 				goto end;
1315e7718adaStb 			if (!sk_X509_push(cfg.encerts, cfg.cert))
1316514c2dabSinoguchi 				goto end;
1317e7718adaStb 			cfg.cert = NULL;
1318c8d13811Sjsing 			args++;
1319c8d13811Sjsing 		}
1320c8d13811Sjsing 	}
1321e7718adaStb 	if (cfg.certfile != NULL) {
1322e7718adaStb 		if ((other = load_certs(bio_err, cfg.certfile,
132330b9607cSinoguchi 		    FORMAT_PEM, NULL, "certificate file")) == NULL) {
1324c8d13811Sjsing 			ERR_print_errors(bio_err);
1325c8d13811Sjsing 			goto end;
1326c8d13811Sjsing 		}
1327c8d13811Sjsing 	}
1328*6156097aSjob 
1329*6156097aSjob 	if (cfg.crlfile != NULL) {
1330*6156097aSjob 		crls = load_crls(bio_err, cfg.crlfile, FORMAT_PEM, NULL,
1331*6156097aSjob 		    "other CRLs");
1332*6156097aSjob 		if (crls == NULL)
1333*6156097aSjob 			goto end;
1334*6156097aSjob 	}
1335*6156097aSjob 
1336e7718adaStb 	if (cfg.recipfile != NULL &&
1337e7718adaStb 	    (cfg.operation == SMIME_DECRYPT)) {
1338e7718adaStb 		if ((recip = load_cert(bio_err, cfg.recipfile,
133930b9607cSinoguchi 		    FORMAT_PEM, NULL, "recipient certificate file")) == NULL) {
1340c8d13811Sjsing 			ERR_print_errors(bio_err);
1341c8d13811Sjsing 			goto end;
1342c8d13811Sjsing 		}
1343c8d13811Sjsing 	}
1344e7718adaStb 	if (cfg.operation == SMIME_SIGN_RECEIPT) {
1345e7718adaStb 		if ((signer = load_cert(bio_err, cfg.signerfile,
134630b9607cSinoguchi 		    FORMAT_PEM, NULL,
13478261c604Sinoguchi 		    "receipt signer certificate file")) == NULL) {
1348c8d13811Sjsing 			ERR_print_errors(bio_err);
1349c8d13811Sjsing 			goto end;
1350c8d13811Sjsing 		}
1351c8d13811Sjsing 	}
1352e7718adaStb 	if (cfg.operation == SMIME_DECRYPT) {
1353e7718adaStb 		if (cfg.keyfile == NULL)
1354e7718adaStb 			cfg.keyfile = cfg.recipfile;
1355e7718adaStb 	} else if ((cfg.operation == SMIME_SIGN) ||
1356e7718adaStb 	    (cfg.operation == SMIME_SIGN_RECEIPT)) {
1357e7718adaStb 		if (cfg.keyfile == NULL)
1358e7718adaStb 			cfg.keyfile = cfg.signerfile;
135930b9607cSinoguchi 	} else {
1360e7718adaStb 		cfg.keyfile = NULL;
136130b9607cSinoguchi 	}
1362c8d13811Sjsing 
1363e7718adaStb 	if (cfg.keyfile != NULL) {
1364e7718adaStb 		key = load_key(bio_err, cfg.keyfile, cfg.keyform,
136530b9607cSinoguchi 		    0, passin, "signing key file");
13668261c604Sinoguchi 		if (key == NULL)
1367c8d13811Sjsing 			goto end;
1368c8d13811Sjsing 	}
1369e7718adaStb 	if (cfg.infile != NULL) {
1370e7718adaStb 		if ((in = BIO_new_file(cfg.infile, inmode)) == NULL) {
1371c8d13811Sjsing 			BIO_printf(bio_err,
1372e7718adaStb 			    "Can't open input file %s\n", cfg.infile);
1373c8d13811Sjsing 			goto end;
1374c8d13811Sjsing 		}
137530b9607cSinoguchi 	} else {
137662235713Sinoguchi 		if ((in = BIO_new_fp(stdin, BIO_NOCLOSE)) == NULL)
137762235713Sinoguchi 			goto end;
137830b9607cSinoguchi 	}
1379c8d13811Sjsing 
1380e7718adaStb 	if (cfg.operation & SMIME_IP) {
1381e7718adaStb 		if (cfg.informat == FORMAT_SMIME)
1382c8d13811Sjsing 			cms = SMIME_read_CMS(in, &indata);
1383e7718adaStb 		else if (cfg.informat == FORMAT_PEM)
1384c8d13811Sjsing 			cms = PEM_read_bio_CMS(in, NULL, NULL, NULL);
1385e7718adaStb 		else if (cfg.informat == FORMAT_ASN1)
1386c8d13811Sjsing 			cms = d2i_CMS_bio(in, NULL);
1387c8d13811Sjsing 		else {
1388c8d13811Sjsing 			BIO_printf(bio_err, "Bad input format for CMS file\n");
1389c8d13811Sjsing 			goto end;
1390c8d13811Sjsing 		}
1391c8d13811Sjsing 
13928261c604Sinoguchi 		if (cms == NULL) {
1393c8d13811Sjsing 			BIO_printf(bio_err, "Error reading S/MIME message\n");
1394c8d13811Sjsing 			goto end;
1395c8d13811Sjsing 		}
1396e7718adaStb 		if (cfg.contfile != NULL) {
1397c8d13811Sjsing 			BIO_free(indata);
1398e7718adaStb 			if ((indata = BIO_new_file(cfg.contfile,
139930b9607cSinoguchi 			    "rb")) == NULL) {
1400c8d13811Sjsing 				BIO_printf(bio_err,
140130b9607cSinoguchi 				    "Can't read content file %s\n",
1402e7718adaStb 				    cfg.contfile);
1403c8d13811Sjsing 				goto end;
1404c8d13811Sjsing 			}
1405c8d13811Sjsing 		}
1406e7718adaStb 		if (cfg.certsoutfile != NULL) {
1407c8d13811Sjsing 			STACK_OF(X509) *allcerts;
14086ee93950Sinoguchi 			if ((allcerts = CMS_get1_certs(cms)) == NULL)
14096ee93950Sinoguchi 				goto end;
1410e7718adaStb 			if (!save_certs(cfg.certsoutfile, allcerts)) {
1411c8d13811Sjsing 				BIO_printf(bio_err,
1412c8d13811Sjsing 				    "Error writing certs to %s\n",
1413e7718adaStb 				    cfg.certsoutfile);
141458c4462fSinoguchi 				sk_X509_pop_free(allcerts, X509_free);
1415c8d13811Sjsing 				ret = 5;
1416c8d13811Sjsing 				goto end;
1417c8d13811Sjsing 			}
1418c8d13811Sjsing 			sk_X509_pop_free(allcerts, X509_free);
1419c8d13811Sjsing 		}
1420c8d13811Sjsing 	}
1421e7718adaStb 	if (cfg.rctfile != NULL) {
1422e7718adaStb 		char *rctmode = (cfg.rctformat == FORMAT_ASN1) ?
142330b9607cSinoguchi 		    "rb" : "r";
1424e7718adaStb 		if ((rctin = BIO_new_file(cfg.rctfile, rctmode)) == NULL) {
1425c8d13811Sjsing 			BIO_printf(bio_err,
1426e7718adaStb 			    "Can't open receipt file %s\n", cfg.rctfile);
1427c8d13811Sjsing 			goto end;
1428c8d13811Sjsing 		}
1429e7718adaStb 		if (cfg.rctformat == FORMAT_SMIME)
1430c8d13811Sjsing 			rcms = SMIME_read_CMS(rctin, NULL);
1431e7718adaStb 		else if (cfg.rctformat == FORMAT_PEM)
1432c8d13811Sjsing 			rcms = PEM_read_bio_CMS(rctin, NULL, NULL, NULL);
1433e7718adaStb 		else if (cfg.rctformat == FORMAT_ASN1)
1434c8d13811Sjsing 			rcms = d2i_CMS_bio(rctin, NULL);
1435c8d13811Sjsing 		else {
1436c8d13811Sjsing 			BIO_printf(bio_err, "Bad input format for receipt\n");
1437c8d13811Sjsing 			goto end;
1438c8d13811Sjsing 		}
1439c8d13811Sjsing 
14408261c604Sinoguchi 		if (rcms == NULL) {
1441c8d13811Sjsing 			BIO_printf(bio_err, "Error reading receipt\n");
1442c8d13811Sjsing 			goto end;
1443c8d13811Sjsing 		}
1444c8d13811Sjsing 	}
1445e7718adaStb 	if (cfg.outfile != NULL) {
1446e7718adaStb 		if ((out = BIO_new_file(cfg.outfile, outmode)) == NULL) {
1447c8d13811Sjsing 			BIO_printf(bio_err,
1448e7718adaStb 			    "Can't open output file %s\n", cfg.outfile);
1449c8d13811Sjsing 			goto end;
1450c8d13811Sjsing 		}
1451c8d13811Sjsing 	} else {
145262235713Sinoguchi 		if ((out = BIO_new_fp(stdout, BIO_NOCLOSE)) == NULL)
145362235713Sinoguchi 			goto end;
1454c8d13811Sjsing 	}
1455c8d13811Sjsing 
1456e7718adaStb 	if ((cfg.operation == SMIME_VERIFY) ||
1457e7718adaStb 	    (cfg.operation == SMIME_VERIFY_RECEIPT)) {
1458e7718adaStb 		if ((store = setup_verify(bio_err, cfg.CAfile,
1459e7718adaStb 		    cfg.CApath)) == NULL)
1460c8d13811Sjsing 			goto end;
1461e7718adaStb 		if (cfg.vpm != NULL) {
1462e7718adaStb 			if (!X509_STORE_set1_param(store, cfg.vpm))
146362235713Sinoguchi 				goto end;
146462235713Sinoguchi 		}
1465c8d13811Sjsing 	}
1466c8d13811Sjsing 	ret = 3;
1467c8d13811Sjsing 
1468e7718adaStb 	if (cfg.operation == SMIME_DATA_CREATE) {
1469e7718adaStb 		cms = CMS_data_create(in, cfg.flags);
1470e7718adaStb 	} else if (cfg.operation == SMIME_DIGEST_CREATE) {
1471e7718adaStb 		cms = CMS_digest_create(in, cfg.sign_md,
1472e7718adaStb 		    cfg.flags);
1473e7718adaStb 	} else if (cfg.operation == SMIME_COMPRESS) {
1474e7718adaStb 		cms = CMS_compress(in, -1, cfg.flags);
1475e7718adaStb 	} else if (cfg.operation == SMIME_ENCRYPT) {
147699e5b935Sinoguchi 		int i;
1477e7718adaStb 		cfg.flags |= CMS_PARTIAL;
1478e7718adaStb 		cms = CMS_encrypt(NULL, in, cfg.cipher,
1479e7718adaStb 		    cfg.flags);
148099e5b935Sinoguchi 		if (cms == NULL)
1481c8d13811Sjsing 			goto end;
1482e7718adaStb 		for (i = 0; i < sk_X509_num(cfg.encerts); i++) {
148399e5b935Sinoguchi 			CMS_RecipientInfo *ri;
1484514c2dabSinoguchi 			struct cms_key_param *kparam;
1485e7718adaStb 			int tflags = cfg.flags;
148662235713Sinoguchi 			X509 *x;
148762235713Sinoguchi 
1488e7718adaStb 			if ((x = sk_X509_value(cfg.encerts, i)) == NULL)
148962235713Sinoguchi 				goto end;
1490e7718adaStb 			for (kparam = cfg.key_first; kparam != NULL;
149130b9607cSinoguchi 			    kparam = kparam->next) {
149299e5b935Sinoguchi 				if (kparam->idx == i) {
149399e5b935Sinoguchi 					tflags |= CMS_KEY_PARAM;
149499e5b935Sinoguchi 					break;
149599e5b935Sinoguchi 				}
149699e5b935Sinoguchi 			}
149799e5b935Sinoguchi 			ri = CMS_add1_recipient_cert(cms, x, tflags);
149899e5b935Sinoguchi 			if (ri == NULL)
149999e5b935Sinoguchi 				goto end;
150099e5b935Sinoguchi 			if (kparam != NULL) {
150199e5b935Sinoguchi 				EVP_PKEY_CTX *pctx;
150230b9607cSinoguchi 				if ((pctx = CMS_RecipientInfo_get0_pkey_ctx(
150330b9607cSinoguchi 				    ri)) == NULL)
15046ee93950Sinoguchi 					goto end;
150599e5b935Sinoguchi 				if (!cms_set_pkey_param(pctx, kparam->param))
150699e5b935Sinoguchi 					goto end;
150799e5b935Sinoguchi 			}
150899e5b935Sinoguchi 		}
150999e5b935Sinoguchi 
1510e7718adaStb 		if (cfg.secret_key != NULL) {
151130b9607cSinoguchi 			if (CMS_add0_recipient_key(cms, NID_undef,
1512e7718adaStb 			    cfg.secret_key, cfg.secret_keylen,
1513e7718adaStb 			    cfg.secret_keyid, cfg.secret_keyidlen,
15148261c604Sinoguchi 			    NULL, NULL, NULL) == NULL)
1515c8d13811Sjsing 				goto end;
1516c8d13811Sjsing 			/* NULL these because call absorbs them */
1517e7718adaStb 			cfg.secret_key = NULL;
1518e7718adaStb 			cfg.secret_keyid = NULL;
1519c8d13811Sjsing 		}
1520e7718adaStb 		if (cfg.pwri_pass != NULL) {
1521e7718adaStb 			pwri_tmp = strdup(cfg.pwri_pass);
15228261c604Sinoguchi 			if (pwri_tmp == NULL)
1523c8d13811Sjsing 				goto end;
15248261c604Sinoguchi 			if (CMS_add0_recipient_password(cms, -1, NID_undef,
15258261c604Sinoguchi 			    NID_undef, pwri_tmp, -1, NULL) == NULL)
1526c8d13811Sjsing 				goto end;
1527c8d13811Sjsing 			pwri_tmp = NULL;
1528c8d13811Sjsing 		}
1529e7718adaStb 		if (!(cfg.flags & CMS_STREAM)) {
1530e7718adaStb 			if (!CMS_final(cms, in, NULL, cfg.flags))
1531c8d13811Sjsing 				goto end;
1532c8d13811Sjsing 		}
1533e7718adaStb 	} else if (cfg.operation == SMIME_ENCRYPTED_ENCRYPT) {
1534e7718adaStb 		cms = CMS_EncryptedData_encrypt(in, cfg.cipher,
1535e7718adaStb 		    cfg.secret_key, cfg.secret_keylen,
1536e7718adaStb 		    cfg.flags);
1537c8d13811Sjsing 
1538e7718adaStb 	} else if (cfg.operation == SMIME_SIGN_RECEIPT) {
1539c8d13811Sjsing 		CMS_ContentInfo *srcms = NULL;
1540c8d13811Sjsing 		STACK_OF(CMS_SignerInfo) *sis;
1541c8d13811Sjsing 		CMS_SignerInfo *si;
1542c8d13811Sjsing 		sis = CMS_get0_SignerInfos(cms);
15438261c604Sinoguchi 		if (sis == NULL)
1544c8d13811Sjsing 			goto end;
1545c8d13811Sjsing 		si = sk_CMS_SignerInfo_value(sis, 0);
154662235713Sinoguchi 		if (si == NULL)
154762235713Sinoguchi 			goto end;
154830b9607cSinoguchi 		srcms = CMS_sign_receipt(si, signer, key, other,
1549e7718adaStb 		    cfg.flags);
15508261c604Sinoguchi 		if (srcms == NULL)
1551c8d13811Sjsing 			goto end;
1552c8d13811Sjsing 		CMS_ContentInfo_free(cms);
1553c8d13811Sjsing 		cms = srcms;
1554e7718adaStb 	} else if (cfg.operation & SMIME_SIGNERS) {
1555c8d13811Sjsing 		int i;
1556c8d13811Sjsing 		/*
1557c8d13811Sjsing 		 * If detached data content we enable streaming if S/MIME
1558c8d13811Sjsing 		 * output format.
1559c8d13811Sjsing 		 */
1560e7718adaStb 		if (cfg.operation == SMIME_SIGN) {
1561c8d13811Sjsing 
1562e7718adaStb 			if (cfg.flags & CMS_DETACHED) {
1563e7718adaStb 				if (cfg.outformat == FORMAT_SMIME)
1564e7718adaStb 					cfg.flags |= CMS_STREAM;
1565c8d13811Sjsing 			}
1566e7718adaStb 			cfg.flags |= CMS_PARTIAL;
1567e7718adaStb 			cms = CMS_sign(NULL, NULL, other, in, cfg.flags);
15688261c604Sinoguchi 			if (cms == NULL)
1569c8d13811Sjsing 				goto end;
1570e7718adaStb 			if (cfg.econtent_type != NULL)
157130b9607cSinoguchi 				if (!CMS_set1_eContentType(cms,
1572e7718adaStb 				    cfg.econtent_type))
15736ee93950Sinoguchi 					goto end;
1574c8d13811Sjsing 
1575e7718adaStb 			if (cfg.rr_to != NULL) {
1576e7718adaStb 				rr = make_receipt_request(cfg.rr_to,
1577e7718adaStb 				    cfg.rr_allorfirst,
1578e7718adaStb 				    cfg.rr_from);
15798261c604Sinoguchi 				if (rr == NULL) {
1580c8d13811Sjsing 					BIO_puts(bio_err,
1581c8d13811Sjsing 					    "Signed Receipt Request Creation Error\n");
1582c8d13811Sjsing 					goto end;
1583c8d13811Sjsing 				}
1584c8d13811Sjsing 			}
158530b9607cSinoguchi 		} else {
1586e7718adaStb 			cfg.flags |= CMS_REUSE_DIGEST;
158730b9607cSinoguchi 		}
158830b9607cSinoguchi 
1589e7718adaStb 		for (i = 0; i < sk_OPENSSL_STRING_num(cfg.sksigners); i++) {
1590c8d13811Sjsing 			CMS_SignerInfo *si;
1591514c2dabSinoguchi 			struct cms_key_param *kparam;
1592e7718adaStb 			int tflags = cfg.flags;
159399e5b935Sinoguchi 
1594e7718adaStb 			cfg.signerfile = sk_OPENSSL_STRING_value(
1595e7718adaStb 			    cfg.sksigners, i);
1596e7718adaStb 			cfg.keyfile = sk_OPENSSL_STRING_value(
1597e7718adaStb 			    cfg.skkeys, i);
159830b9607cSinoguchi 
1599e7718adaStb 			signer = load_cert(bio_err, cfg.signerfile,
160030b9607cSinoguchi 			    FORMAT_PEM, NULL, "signer certificate");
16018261c604Sinoguchi 			if (signer == NULL)
1602c8d13811Sjsing 				goto end;
1603e7718adaStb 			key = load_key(bio_err, cfg.keyfile,
1604e7718adaStb 			    cfg.keyform, 0, passin, "signing key file");
16058261c604Sinoguchi 			if (key == NULL)
1606c8d13811Sjsing 				goto end;
1607e7718adaStb 			for (kparam = cfg.key_first; kparam != NULL;
160830b9607cSinoguchi 			    kparam = kparam->next) {
160999e5b935Sinoguchi 				if (kparam->idx == i) {
161099e5b935Sinoguchi 					tflags |= CMS_KEY_PARAM;
161199e5b935Sinoguchi 					break;
161299e5b935Sinoguchi 				}
161399e5b935Sinoguchi 			}
161430b9607cSinoguchi 			si = CMS_add1_signer(cms, signer, key,
1615e7718adaStb 			    cfg.sign_md, tflags);
161699e5b935Sinoguchi 			if (si == NULL)
1617c8d13811Sjsing 				goto end;
161899e5b935Sinoguchi 			if (kparam != NULL) {
161999e5b935Sinoguchi 				EVP_PKEY_CTX *pctx;
162030b9607cSinoguchi 				if ((pctx = CMS_SignerInfo_get0_pkey_ctx(
162130b9607cSinoguchi 				    si)) == NULL)
16226ee93950Sinoguchi 					goto end;
162399e5b935Sinoguchi 				if (!cms_set_pkey_param(pctx, kparam->param))
162499e5b935Sinoguchi 					goto end;
162599e5b935Sinoguchi 			}
16268261c604Sinoguchi 			if (rr != NULL && !CMS_add1_ReceiptRequest(si, rr))
1627c8d13811Sjsing 				goto end;
1628c8d13811Sjsing 			X509_free(signer);
1629c8d13811Sjsing 			signer = NULL;
1630c8d13811Sjsing 			EVP_PKEY_free(key);
1631c8d13811Sjsing 			key = NULL;
1632c8d13811Sjsing 		}
1633c8d13811Sjsing 		/* If not streaming or resigning finalize structure */
1634e7718adaStb 		if ((cfg.operation == SMIME_SIGN) &&
1635e7718adaStb 		    !(cfg.flags & CMS_STREAM)) {
1636e7718adaStb 			if (!CMS_final(cms, in, NULL, cfg.flags))
1637c8d13811Sjsing 				goto end;
1638c8d13811Sjsing 		}
1639c8d13811Sjsing 	}
16408261c604Sinoguchi 	if (cms == NULL) {
1641c8d13811Sjsing 		BIO_printf(bio_err, "Error creating CMS structure\n");
1642c8d13811Sjsing 		goto end;
1643c8d13811Sjsing 	}
1644c8d13811Sjsing 	ret = 4;
1645e7718adaStb 	if (cfg.operation == SMIME_DECRYPT) {
1646e7718adaStb 		if (cfg.flags & CMS_DEBUG_DECRYPT)
164730b9607cSinoguchi 			CMS_decrypt(cms, NULL, NULL, NULL, NULL,
1648e7718adaStb 			    cfg.flags);
1649c8d13811Sjsing 
1650e7718adaStb 		if (cfg.secret_key != NULL) {
1651e7718adaStb 			if (!CMS_decrypt_set1_key(cms, cfg.secret_key,
1652e7718adaStb 			    cfg.secret_keylen, cfg.secret_keyid,
1653e7718adaStb 			    cfg.secret_keyidlen)) {
1654c8d13811Sjsing 				BIO_puts(bio_err,
1655c8d13811Sjsing 				    "Error decrypting CMS using secret key\n");
1656c8d13811Sjsing 				goto end;
1657c8d13811Sjsing 			}
1658c8d13811Sjsing 		}
16598261c604Sinoguchi 		if (key != NULL) {
1660c8d13811Sjsing 			if (!CMS_decrypt_set1_pkey(cms, key, recip)) {
1661c8d13811Sjsing 				BIO_puts(bio_err,
1662c8d13811Sjsing 				    "Error decrypting CMS using private key\n");
1663c8d13811Sjsing 				goto end;
1664c8d13811Sjsing 			}
1665c8d13811Sjsing 		}
1666e7718adaStb 		if (cfg.pwri_pass != NULL) {
166730b9607cSinoguchi 			if (!CMS_decrypt_set1_password(cms,
1668e7718adaStb 			    cfg.pwri_pass, -1)) {
1669c8d13811Sjsing 				BIO_puts(bio_err,
1670c8d13811Sjsing 				    "Error decrypting CMS using password\n");
1671c8d13811Sjsing 				goto end;
1672c8d13811Sjsing 			}
1673c8d13811Sjsing 		}
167430b9607cSinoguchi 		if (!CMS_decrypt(cms, NULL, NULL, indata, out,
1675e7718adaStb 		    cfg.flags)) {
1676c8d13811Sjsing 			BIO_printf(bio_err, "Error decrypting CMS structure\n");
1677c8d13811Sjsing 			goto end;
1678c8d13811Sjsing 		}
1679e7718adaStb 	} else if (cfg.operation == SMIME_DATAOUT) {
1680e7718adaStb 		if (!CMS_data(cms, out, cfg.flags))
1681c8d13811Sjsing 			goto end;
1682e7718adaStb 	} else if (cfg.operation == SMIME_UNCOMPRESS) {
1683e7718adaStb 		if (!CMS_uncompress(cms, indata, out, cfg.flags))
1684c8d13811Sjsing 			goto end;
1685e7718adaStb 	} else if (cfg.operation == SMIME_DIGEST_VERIFY) {
1686e7718adaStb 		if (CMS_digest_verify(cms, indata, out, cfg.flags) > 0)
1687c8d13811Sjsing 			BIO_printf(bio_err, "Verification successful\n");
1688c8d13811Sjsing 		else {
1689c8d13811Sjsing 			BIO_printf(bio_err, "Verification failure\n");
1690c8d13811Sjsing 			goto end;
1691c8d13811Sjsing 		}
1692e7718adaStb 	} else if (cfg.operation == SMIME_ENCRYPTED_DECRYPT) {
1693e7718adaStb 		if (!CMS_EncryptedData_decrypt(cms, cfg.secret_key,
1694e7718adaStb 		    cfg.secret_keylen, indata, out, cfg.flags))
1695c8d13811Sjsing 			goto end;
1696e7718adaStb 	} else if (cfg.operation == SMIME_VERIFY) {
1697*6156097aSjob 		if (cfg.crlfile != NULL) {
1698*6156097aSjob 			int i;
1699*6156097aSjob 
1700*6156097aSjob 			for (i = 0; i < sk_X509_CRL_num(crls); i++) {
1701*6156097aSjob 				X509_CRL *crl = sk_X509_CRL_value(crls, i);
1702*6156097aSjob 				if (!CMS_add1_crl(cms, crl))
1703*6156097aSjob 					goto end;
1704*6156097aSjob 			}
1705*6156097aSjob 		}
170630b9607cSinoguchi 		if (CMS_verify(cms, other, store, indata, out,
1707e7718adaStb 		    cfg.flags) > 0) {
1708c8d13811Sjsing 			BIO_printf(bio_err, "Verification successful\n");
170930b9607cSinoguchi 		} else {
1710c8d13811Sjsing 			BIO_printf(bio_err, "Verification failure\n");
1711e7718adaStb 			if (cfg.verify_retcode)
1712c8d13811Sjsing 				ret = verify_err + 32;
1713c8d13811Sjsing 			goto end;
1714c8d13811Sjsing 		}
1715e7718adaStb 		if (cfg.signerfile != NULL) {
1716c8d13811Sjsing 			STACK_OF(X509) *signers;
17176ee93950Sinoguchi 			if ((signers = CMS_get0_signers(cms)) == NULL)
17186ee93950Sinoguchi 				goto end;
1719e7718adaStb 			if (!save_certs(cfg.signerfile, signers)) {
1720c8d13811Sjsing 				BIO_printf(bio_err,
1721c8d13811Sjsing 				    "Error writing signers to %s\n",
1722e7718adaStb 				    cfg.signerfile);
172358c4462fSinoguchi 				sk_X509_free(signers);
1724c8d13811Sjsing 				ret = 5;
1725c8d13811Sjsing 				goto end;
1726c8d13811Sjsing 			}
1727c8d13811Sjsing 			sk_X509_free(signers);
1728c8d13811Sjsing 		}
1729e7718adaStb 		if (cfg.rr_print)
1730c8d13811Sjsing 			receipt_request_print(bio_err, cms);
1731c8d13811Sjsing 
1732e7718adaStb 	} else if (cfg.operation == SMIME_VERIFY_RECEIPT) {
173330b9607cSinoguchi 		if (CMS_verify_receipt(rcms, cms, other, store,
1734e7718adaStb 		    cfg.flags) > 0) {
1735c8d13811Sjsing 			BIO_printf(bio_err, "Verification successful\n");
173630b9607cSinoguchi 		} else {
1737c8d13811Sjsing 			BIO_printf(bio_err, "Verification failure\n");
1738c8d13811Sjsing 			goto end;
1739c8d13811Sjsing 		}
1740c8d13811Sjsing 	} else {
1741e7718adaStb 		if (cfg.noout) {
1742e7718adaStb 			if (cfg.print &&
17436ee93950Sinoguchi 			    !CMS_ContentInfo_print_ctx(out, cms, 0, NULL))
17446ee93950Sinoguchi 				goto end;
1745e7718adaStb 		} else if (cfg.outformat == FORMAT_SMIME) {
1746e7718adaStb 			if (cfg.to != NULL)
1747e7718adaStb 				BIO_printf(out, "To: %s\n", cfg.to);
1748e7718adaStb 			if (cfg.from != NULL)
1749e7718adaStb 				BIO_printf(out, "From: %s\n", cfg.from);
1750e7718adaStb 			if (cfg.subject != NULL)
175130b9607cSinoguchi 				BIO_printf(out, "Subject: %s\n",
1752e7718adaStb 				    cfg.subject);
1753e7718adaStb 			if (cfg.operation == SMIME_RESIGN)
175430b9607cSinoguchi 				ret = SMIME_write_CMS(out, cms, indata,
1755e7718adaStb 				    cfg.flags);
1756c8d13811Sjsing 			else
175730b9607cSinoguchi 				ret = SMIME_write_CMS(out, cms, in,
1758e7718adaStb 				    cfg.flags);
1759e7718adaStb 		} else if (cfg.outformat == FORMAT_PEM) {
176030b9607cSinoguchi 			ret = PEM_write_bio_CMS_stream(out, cms, in,
1761e7718adaStb 			    cfg.flags);
1762e7718adaStb 		} else if (cfg.outformat == FORMAT_ASN1) {
1763e7718adaStb 			ret = i2d_CMS_bio_stream(out, cms, in, cfg.flags);
176430b9607cSinoguchi 		} else {
1765c8d13811Sjsing 			BIO_printf(bio_err, "Bad output format for CMS file\n");
1766c8d13811Sjsing 			goto end;
1767c8d13811Sjsing 		}
1768c8d13811Sjsing 		if (ret <= 0) {
1769c8d13811Sjsing 			ret = 6;
1770c8d13811Sjsing 			goto end;
1771c8d13811Sjsing 		}
1772c8d13811Sjsing 	}
1773c8d13811Sjsing 	ret = 0;
1774c8d13811Sjsing 
1775c8d13811Sjsing  end:
1776c8d13811Sjsing 	if (ret)
1777c8d13811Sjsing 		ERR_print_errors(bio_err);
1778d852947dSjsing 
1779e7718adaStb 	sk_X509_pop_free(cfg.encerts, X509_free);
1780c8d13811Sjsing 	sk_X509_pop_free(other, X509_free);
1781*6156097aSjob 	sk_X509_CRL_pop_free(crls, X509_CRL_free);
1782e7718adaStb 	X509_VERIFY_PARAM_free(cfg.vpm);
1783e7718adaStb 	sk_OPENSSL_STRING_free(cfg.sksigners);
1784e7718adaStb 	sk_OPENSSL_STRING_free(cfg.skkeys);
1785e7718adaStb 	free(cfg.secret_key);
1786e7718adaStb 	free(cfg.secret_keyid);
1787c8d13811Sjsing 	free(pwri_tmp);
1788e7718adaStb 	ASN1_OBJECT_free(cfg.econtent_type);
1789c8d13811Sjsing 	CMS_ReceiptRequest_free(rr);
1790e7718adaStb 	sk_OPENSSL_STRING_free(cfg.rr_to);
1791e7718adaStb 	sk_OPENSSL_STRING_free(cfg.rr_from);
1792e7718adaStb 	for (cfg.key_param = cfg.key_first; cfg.key_param;) {
1793514c2dabSinoguchi 		struct cms_key_param *tparam;
1794e7718adaStb 		sk_OPENSSL_STRING_free(cfg.key_param->param);
1795e7718adaStb 		tparam = cfg.key_param->next;
1796e7718adaStb 		free(cfg.key_param);
1797e7718adaStb 		cfg.key_param = tparam;
179899e5b935Sinoguchi 	}
1799c8d13811Sjsing 	X509_STORE_free(store);
1800e7718adaStb 	X509_free(cfg.cert);
1801c8d13811Sjsing 	X509_free(recip);
1802c8d13811Sjsing 	X509_free(signer);
1803c8d13811Sjsing 	EVP_PKEY_free(key);
1804c8d13811Sjsing 	CMS_ContentInfo_free(cms);
1805c8d13811Sjsing 	CMS_ContentInfo_free(rcms);
1806c8d13811Sjsing 	BIO_free(rctin);
1807c8d13811Sjsing 	BIO_free(in);
1808c8d13811Sjsing 	BIO_free(indata);
1809c8d13811Sjsing 	BIO_free_all(out);
1810c8d13811Sjsing 	free(passin);
1811d852947dSjsing 
1812c8d13811Sjsing 	return (ret);
1813c8d13811Sjsing }
1814c8d13811Sjsing 
1815c8d13811Sjsing static int
1816c8d13811Sjsing save_certs(char *signerfile, STACK_OF(X509) *signers)
1817c8d13811Sjsing {
1818c8d13811Sjsing 	int i;
1819c8d13811Sjsing 	BIO *tmp;
1820c8d13811Sjsing 
18218261c604Sinoguchi 	if (signerfile == NULL)
1822c8d13811Sjsing 		return 1;
1823c8d13811Sjsing 	tmp = BIO_new_file(signerfile, "w");
18248261c604Sinoguchi 	if (tmp == NULL)
1825c8d13811Sjsing 		return 0;
1826c8d13811Sjsing 	for (i = 0; i < sk_X509_num(signers); i++)
1827c8d13811Sjsing 		PEM_write_bio_X509(tmp, sk_X509_value(signers, i));
1828c8d13811Sjsing 	BIO_free(tmp);
1829c8d13811Sjsing 	return 1;
1830c8d13811Sjsing }
1831c8d13811Sjsing 
1832c8d13811Sjsing static void
1833c8d13811Sjsing gnames_stack_print(BIO *out, STACK_OF(GENERAL_NAMES) *gns)
1834c8d13811Sjsing {
1835c8d13811Sjsing 	STACK_OF(GENERAL_NAME) *gens;
1836c8d13811Sjsing 	GENERAL_NAME *gen;
1837c8d13811Sjsing 	int i, j;
1838c8d13811Sjsing 
1839c8d13811Sjsing 	for (i = 0; i < sk_GENERAL_NAMES_num(gns); i++) {
1840c8d13811Sjsing 		gens = sk_GENERAL_NAMES_value(gns, i);
1841c8d13811Sjsing 		for (j = 0; j < sk_GENERAL_NAME_num(gens); j++) {
1842c8d13811Sjsing 			gen = sk_GENERAL_NAME_value(gens, j);
1843c8d13811Sjsing 			BIO_puts(out, "    ");
1844c8d13811Sjsing 			GENERAL_NAME_print(out, gen);
1845c8d13811Sjsing 			BIO_puts(out, "\n");
1846c8d13811Sjsing 		}
1847c8d13811Sjsing 	}
1848c8d13811Sjsing 	return;
1849c8d13811Sjsing }
1850c8d13811Sjsing 
1851c8d13811Sjsing static void
1852c8d13811Sjsing receipt_request_print(BIO *out, CMS_ContentInfo *cms)
1853c8d13811Sjsing {
1854c8d13811Sjsing 	STACK_OF(CMS_SignerInfo) *sis;
1855c8d13811Sjsing 	CMS_SignerInfo *si;
1856c8d13811Sjsing 	CMS_ReceiptRequest *rr;
1857c8d13811Sjsing 	int allorfirst;
1858c8d13811Sjsing 	STACK_OF(GENERAL_NAMES) *rto, *rlist;
1859c8d13811Sjsing 	ASN1_STRING *scid;
1860c8d13811Sjsing 	int i, rv;
1861c8d13811Sjsing 
18626ee93950Sinoguchi 	if ((sis = CMS_get0_SignerInfos(cms)) == NULL)
18636ee93950Sinoguchi 		return;
1864c8d13811Sjsing 	for (i = 0; i < sk_CMS_SignerInfo_num(sis); i++) {
186562235713Sinoguchi 		if ((si = sk_CMS_SignerInfo_value(sis, i)) == NULL)
186662235713Sinoguchi 			return;
1867c8d13811Sjsing 		rv = CMS_get1_ReceiptRequest(si, &rr);
1868c8d13811Sjsing 		BIO_printf(bio_err, "Signer %d:\n", i + 1);
186930b9607cSinoguchi 		if (rv == 0) {
1870c8d13811Sjsing 			BIO_puts(bio_err, "  No Receipt Request\n");
187130b9607cSinoguchi 		} else if (rv < 0) {
1872c8d13811Sjsing 			BIO_puts(bio_err, "  Receipt Request Parse Error\n");
1873c8d13811Sjsing 			ERR_print_errors(bio_err);
1874c8d13811Sjsing 		} else {
1875c8d13811Sjsing 			char *id;
1876c8d13811Sjsing 			int idlen;
187730b9607cSinoguchi 
1878c8d13811Sjsing 			CMS_ReceiptRequest_get0_values(rr, &scid, &allorfirst,
1879c8d13811Sjsing 			    &rlist, &rto);
1880c8d13811Sjsing 			BIO_puts(out, "  Signed Content ID:\n");
1881c8d13811Sjsing 			idlen = ASN1_STRING_length(scid);
1882c8d13811Sjsing 			id = (char *) ASN1_STRING_data(scid);
1883c8d13811Sjsing 			BIO_dump_indent(out, id, idlen, 4);
1884c8d13811Sjsing 			BIO_puts(out, "  Receipts From");
18858261c604Sinoguchi 			if (rlist != NULL) {
1886c8d13811Sjsing 				BIO_puts(out, " List:\n");
1887c8d13811Sjsing 				gnames_stack_print(out, rlist);
188830b9607cSinoguchi 			} else if (allorfirst == 1) {
1889c8d13811Sjsing 				BIO_puts(out, ": First Tier\n");
189030b9607cSinoguchi 			} else if (allorfirst == 0) {
1891c8d13811Sjsing 				BIO_puts(out, ": All\n");
189230b9607cSinoguchi 			} else {
1893c8d13811Sjsing 				BIO_printf(out, " Unknown (%d)\n", allorfirst);
189430b9607cSinoguchi 			}
1895c8d13811Sjsing 			BIO_puts(out, "  Receipts To:\n");
1896c8d13811Sjsing 			gnames_stack_print(out, rto);
1897c8d13811Sjsing 		}
1898c8d13811Sjsing 		CMS_ReceiptRequest_free(rr);
1899c8d13811Sjsing 	}
1900c8d13811Sjsing }
1901c8d13811Sjsing 
1902c8d13811Sjsing static STACK_OF(GENERAL_NAMES) *
1903c8d13811Sjsing make_names_stack(STACK_OF(OPENSSL_STRING) *ns)
1904c8d13811Sjsing {
1905c8d13811Sjsing 	int i;
1906c8d13811Sjsing 	STACK_OF(GENERAL_NAMES) *ret;
1907c8d13811Sjsing 	GENERAL_NAMES *gens = NULL;
1908c8d13811Sjsing 	GENERAL_NAME *gen = NULL;
19098261c604Sinoguchi 
1910d4271273Sinoguchi 	if ((ret = sk_GENERAL_NAMES_new_null()) == NULL)
1911c8d13811Sjsing 		goto err;
1912c8d13811Sjsing 	for (i = 0; i < sk_OPENSSL_STRING_num(ns); i++) {
1913c8d13811Sjsing 		char *str = sk_OPENSSL_STRING_value(ns, i);
1914c8d13811Sjsing 		gen = a2i_GENERAL_NAME(NULL, NULL, NULL, GEN_EMAIL, str, 0);
19158261c604Sinoguchi 		if (gen == NULL)
1916c8d13811Sjsing 			goto err;
1917c8d13811Sjsing 		gens = GENERAL_NAMES_new();
19188261c604Sinoguchi 		if (gens == NULL)
1919c8d13811Sjsing 			goto err;
1920c8d13811Sjsing 		if (!sk_GENERAL_NAME_push(gens, gen))
1921c8d13811Sjsing 			goto err;
1922c8d13811Sjsing 		gen = NULL;
1923c8d13811Sjsing 		if (!sk_GENERAL_NAMES_push(ret, gens))
1924c8d13811Sjsing 			goto err;
1925c8d13811Sjsing 		gens = NULL;
1926c8d13811Sjsing 	}
1927c8d13811Sjsing 
1928c8d13811Sjsing 	return ret;
1929c8d13811Sjsing 
1930c8d13811Sjsing  err:
1931c8d13811Sjsing 	sk_GENERAL_NAMES_pop_free(ret, GENERAL_NAMES_free);
1932c8d13811Sjsing 	GENERAL_NAMES_free(gens);
1933c8d13811Sjsing 	GENERAL_NAME_free(gen);
1934d852947dSjsing 
1935c8d13811Sjsing 	return NULL;
1936c8d13811Sjsing }
1937c8d13811Sjsing 
1938c8d13811Sjsing 
1939c8d13811Sjsing static CMS_ReceiptRequest *
1940c8d13811Sjsing make_receipt_request(STACK_OF(OPENSSL_STRING) *rr_to, int rr_allorfirst,
1941c8d13811Sjsing     STACK_OF(OPENSSL_STRING) *rr_from)
1942c8d13811Sjsing {
19436a7aa66eSinoguchi 	STACK_OF(GENERAL_NAMES) *rct_to = NULL, *rct_from = NULL;
1944c8d13811Sjsing 	CMS_ReceiptRequest *rr;
1945c8d13811Sjsing 
1946c8d13811Sjsing 	rct_to = make_names_stack(rr_to);
19478261c604Sinoguchi 	if (rct_to == NULL)
1948c8d13811Sjsing 		goto err;
19498261c604Sinoguchi 	if (rr_from != NULL) {
1950c8d13811Sjsing 		rct_from = make_names_stack(rr_from);
19518261c604Sinoguchi 		if (rct_from == NULL)
1952c8d13811Sjsing 			goto err;
195330b9607cSinoguchi 	} else {
1954c8d13811Sjsing 		rct_from = NULL;
195530b9607cSinoguchi 	}
19566ee93950Sinoguchi 
19576ee93950Sinoguchi 	if ((rr = CMS_ReceiptRequest_create0(NULL, -1, rr_allorfirst, rct_from,
19586ee93950Sinoguchi 	    rct_to)) == NULL)
19596ee93950Sinoguchi 		goto err;
19606ee93950Sinoguchi 
1961c8d13811Sjsing 	return rr;
1962c8d13811Sjsing 
1963c8d13811Sjsing  err:
19646a7aa66eSinoguchi 	sk_GENERAL_NAMES_pop_free(rct_to, GENERAL_NAMES_free);
19656a7aa66eSinoguchi 	sk_GENERAL_NAMES_pop_free(rct_from, GENERAL_NAMES_free);
1966c8d13811Sjsing 	return NULL;
1967c8d13811Sjsing }
1968c8d13811Sjsing 
196999e5b935Sinoguchi static int
197099e5b935Sinoguchi cms_set_pkey_param(EVP_PKEY_CTX *pctx, STACK_OF(OPENSSL_STRING) *param)
197199e5b935Sinoguchi {
197299e5b935Sinoguchi 	char *keyopt;
197399e5b935Sinoguchi 	int i;
1974514c2dabSinoguchi 
197599e5b935Sinoguchi 	if (sk_OPENSSL_STRING_num(param) <= 0)
197699e5b935Sinoguchi 		return 1;
197799e5b935Sinoguchi 	for (i = 0; i < sk_OPENSSL_STRING_num(param); i++) {
197899e5b935Sinoguchi 		keyopt = sk_OPENSSL_STRING_value(param, i);
197999e5b935Sinoguchi 		if (pkey_ctrl_string(pctx, keyopt) <= 0) {
198099e5b935Sinoguchi 			BIO_printf(bio_err, "parameter error \"%s\"\n", keyopt);
198199e5b935Sinoguchi 			ERR_print_errors(bio_err);
198299e5b935Sinoguchi 			return 0;
198399e5b935Sinoguchi 		}
198499e5b935Sinoguchi 	}
198599e5b935Sinoguchi 	return 1;
198699e5b935Sinoguchi }
198799e5b935Sinoguchi 
1988c8d13811Sjsing #endif
1989