1183234Ssimon/* apps/cms.c */
2183234Ssimon/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
3183234Ssimon * project.
4183234Ssimon */
5183234Ssimon/* ====================================================================
6183234Ssimon * Copyright (c) 2008 The OpenSSL Project.  All rights reserved.
7183234Ssimon *
8183234Ssimon * Redistribution and use in source and binary forms, with or without
9183234Ssimon * modification, are permitted provided that the following conditions
10183234Ssimon * are met:
11183234Ssimon *
12183234Ssimon * 1. Redistributions of source code must retain the above copyright
13183234Ssimon *    notice, this list of conditions and the following disclaimer.
14183234Ssimon *
15183234Ssimon * 2. Redistributions in binary form must reproduce the above copyright
16183234Ssimon *    notice, this list of conditions and the following disclaimer in
17183234Ssimon *    the documentation and/or other materials provided with the
18183234Ssimon *    distribution.
19183234Ssimon *
20183234Ssimon * 3. All advertising materials mentioning features or use of this
21183234Ssimon *    software must display the following acknowledgment:
22183234Ssimon *    "This product includes software developed by the OpenSSL Project
23183234Ssimon *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
24183234Ssimon *
25183234Ssimon * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
26183234Ssimon *    endorse or promote products derived from this software without
27183234Ssimon *    prior written permission. For written permission, please contact
28183234Ssimon *    licensing@OpenSSL.org.
29183234Ssimon *
30183234Ssimon * 5. Products derived from this software may not be called "OpenSSL"
31183234Ssimon *    nor may "OpenSSL" appear in their names without prior written
32183234Ssimon *    permission of the OpenSSL Project.
33183234Ssimon *
34183234Ssimon * 6. Redistributions of any form whatsoever must retain the following
35183234Ssimon *    acknowledgment:
36183234Ssimon *    "This product includes software developed by the OpenSSL Project
37183234Ssimon *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
38183234Ssimon *
39183234Ssimon * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
40183234Ssimon * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
41183234Ssimon * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
42183234Ssimon * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
43183234Ssimon * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
44183234Ssimon * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
45183234Ssimon * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
46183234Ssimon * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47183234Ssimon * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
48183234Ssimon * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
49183234Ssimon * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
50183234Ssimon * OF THE POSSIBILITY OF SUCH DAMAGE.
51183234Ssimon * ====================================================================
52183234Ssimon */
53183234Ssimon
54183234Ssimon/* CMS utility function */
55183234Ssimon
56183234Ssimon#include <stdio.h>
57183234Ssimon#include <string.h>
58183234Ssimon#include "apps.h"
59183234Ssimon
60183234Ssimon#ifndef OPENSSL_NO_CMS
61183234Ssimon
62183234Ssimon#include <openssl/crypto.h>
63183234Ssimon#include <openssl/pem.h>
64183234Ssimon#include <openssl/err.h>
65183234Ssimon#include <openssl/x509_vfy.h>
66183234Ssimon#include <openssl/x509v3.h>
67183234Ssimon#include <openssl/cms.h>
68183234Ssimon
69183234Ssimon#undef PROG
70183234Ssimon#define PROG cms_main
71183234Ssimonstatic int save_certs(char *signerfile, STACK_OF(X509) *signers);
72183234Ssimonstatic int cms_cb(int ok, X509_STORE_CTX *ctx);
73183234Ssimonstatic void receipt_request_print(BIO *out, CMS_ContentInfo *cms);
74238405Sjkimstatic CMS_ReceiptRequest *make_receipt_request(STACK_OF(OPENSSL_STRING) *rr_to,
75238405Sjkim						int rr_allorfirst,
76238405Sjkim					STACK_OF(OPENSSL_STRING) *rr_from);
77183234Ssimon
78183234Ssimon#define SMIME_OP	0x10
79183234Ssimon#define SMIME_IP	0x20
80183234Ssimon#define SMIME_SIGNERS	0x40
81183234Ssimon#define SMIME_ENCRYPT		(1 | SMIME_OP)
82183234Ssimon#define SMIME_DECRYPT		(2 | SMIME_IP)
83183234Ssimon#define SMIME_SIGN		(3 | SMIME_OP | SMIME_SIGNERS)
84183234Ssimon#define SMIME_VERIFY		(4 | SMIME_IP)
85183234Ssimon#define SMIME_CMSOUT		(5 | SMIME_IP | SMIME_OP)
86183234Ssimon#define SMIME_RESIGN		(6 | SMIME_IP | SMIME_OP | SMIME_SIGNERS)
87183234Ssimon#define SMIME_DATAOUT		(7 | SMIME_IP)
88183234Ssimon#define SMIME_DATA_CREATE	(8 | SMIME_OP)
89183234Ssimon#define SMIME_DIGEST_VERIFY	(9 | SMIME_IP)
90183234Ssimon#define SMIME_DIGEST_CREATE	(10 | SMIME_OP)
91183234Ssimon#define SMIME_UNCOMPRESS	(11 | SMIME_IP)
92183234Ssimon#define SMIME_COMPRESS		(12 | SMIME_OP)
93183234Ssimon#define SMIME_ENCRYPTED_DECRYPT	(13 | SMIME_IP)
94183234Ssimon#define SMIME_ENCRYPTED_ENCRYPT	(14 | SMIME_OP)
95183234Ssimon#define SMIME_SIGN_RECEIPT	(15 | SMIME_IP | SMIME_OP)
96183234Ssimon#define SMIME_VERIFY_RECEIPT	(16 | SMIME_IP)
97183234Ssimon
98238405Sjkimint verify_err = 0;
99238405Sjkim
100183234Ssimonint MAIN(int, char **);
101183234Ssimon
102183234Ssimonint MAIN(int argc, char **argv)
103183234Ssimon	{
104183234Ssimon	ENGINE *e = NULL;
105183234Ssimon	int operation = 0;
106183234Ssimon	int ret = 0;
107183234Ssimon	char **args;
108183234Ssimon	const char *inmode = "r", *outmode = "w";
109183234Ssimon	char *infile = NULL, *outfile = NULL, *rctfile = NULL;
110183234Ssimon	char *signerfile = NULL, *recipfile = NULL;
111238405Sjkim	STACK_OF(OPENSSL_STRING) *sksigners = NULL, *skkeys = NULL;
112183234Ssimon	char *certfile = NULL, *keyfile = NULL, *contfile=NULL;
113183234Ssimon	char *certsoutfile = NULL;
114183234Ssimon	const EVP_CIPHER *cipher = NULL;
115183234Ssimon	CMS_ContentInfo *cms = NULL, *rcms = NULL;
116183234Ssimon	X509_STORE *store = NULL;
117183234Ssimon	X509 *cert = NULL, *recip = NULL, *signer = NULL;
118183234Ssimon	EVP_PKEY *key = NULL;
119183234Ssimon	STACK_OF(X509) *encerts = NULL, *other = NULL;
120183234Ssimon	BIO *in = NULL, *out = NULL, *indata = NULL, *rctin = NULL;
121183234Ssimon	int badarg = 0;
122238405Sjkim	int flags = CMS_DETACHED, noout = 0, print = 0;
123238405Sjkim	int verify_retcode = 0;
124183234Ssimon	int rr_print = 0, rr_allorfirst = -1;
125238405Sjkim	STACK_OF(OPENSSL_STRING) *rr_to = NULL, *rr_from = NULL;
126183234Ssimon	CMS_ReceiptRequest *rr = NULL;
127183234Ssimon	char *to = NULL, *from = NULL, *subject = NULL;
128183234Ssimon	char *CAfile = NULL, *CApath = NULL;
129183234Ssimon	char *passargin = NULL, *passin = NULL;
130183234Ssimon	char *inrand = NULL;
131183234Ssimon	int need_rand = 0;
132183234Ssimon	const EVP_MD *sign_md = NULL;
133183234Ssimon	int informat = FORMAT_SMIME, outformat = FORMAT_SMIME;
134183234Ssimon        int rctformat = FORMAT_SMIME, keyform = FORMAT_PEM;
135183234Ssimon#ifndef OPENSSL_NO_ENGINE
136183234Ssimon	char *engine=NULL;
137183234Ssimon#endif
138183234Ssimon	unsigned char *secret_key = NULL, *secret_keyid = NULL;
139238405Sjkim	unsigned char *pwri_pass = NULL, *pwri_tmp = NULL;
140183234Ssimon	size_t secret_keylen = 0, secret_keyidlen = 0;
141183234Ssimon
142183234Ssimon	ASN1_OBJECT *econtent_type = NULL;
143183234Ssimon
144183234Ssimon	X509_VERIFY_PARAM *vpm = NULL;
145183234Ssimon
146183234Ssimon	args = argv + 1;
147183234Ssimon	ret = 1;
148183234Ssimon
149183234Ssimon	apps_startup();
150183234Ssimon
151183234Ssimon	if (bio_err == NULL)
152183234Ssimon		{
153183234Ssimon		if ((bio_err = BIO_new(BIO_s_file())) != NULL)
154183234Ssimon			BIO_set_fp(bio_err, stderr, BIO_NOCLOSE|BIO_FP_TEXT);
155183234Ssimon		}
156183234Ssimon
157183234Ssimon	if (!load_config(bio_err, NULL))
158183234Ssimon		goto end;
159183234Ssimon
160183234Ssimon	while (!badarg && *args && *args[0] == '-')
161183234Ssimon		{
162183234Ssimon		if (!strcmp (*args, "-encrypt"))
163183234Ssimon			operation = SMIME_ENCRYPT;
164183234Ssimon		else if (!strcmp (*args, "-decrypt"))
165183234Ssimon			operation = SMIME_DECRYPT;
166183234Ssimon		else if (!strcmp (*args, "-sign"))
167183234Ssimon			operation = SMIME_SIGN;
168183234Ssimon		else if (!strcmp (*args, "-sign_receipt"))
169183234Ssimon			operation = SMIME_SIGN_RECEIPT;
170183234Ssimon		else if (!strcmp (*args, "-resign"))
171183234Ssimon			operation = SMIME_RESIGN;
172183234Ssimon		else if (!strcmp (*args, "-verify"))
173183234Ssimon			operation = SMIME_VERIFY;
174238405Sjkim		else if (!strcmp (*args, "-verify_retcode"))
175238405Sjkim			verify_retcode = 1;
176183234Ssimon		else if (!strcmp(*args,"-verify_receipt"))
177183234Ssimon			{
178183234Ssimon			operation = SMIME_VERIFY_RECEIPT;
179183234Ssimon			if (!args[1])
180183234Ssimon				goto argerr;
181183234Ssimon			args++;
182183234Ssimon			rctfile = *args;
183183234Ssimon			}
184183234Ssimon		else if (!strcmp (*args, "-cmsout"))
185183234Ssimon			operation = SMIME_CMSOUT;
186183234Ssimon		else if (!strcmp (*args, "-data_out"))
187183234Ssimon			operation = SMIME_DATAOUT;
188183234Ssimon		else if (!strcmp (*args, "-data_create"))
189183234Ssimon			operation = SMIME_DATA_CREATE;
190183234Ssimon		else if (!strcmp (*args, "-digest_verify"))
191183234Ssimon			operation = SMIME_DIGEST_VERIFY;
192183234Ssimon		else if (!strcmp (*args, "-digest_create"))
193183234Ssimon			operation = SMIME_DIGEST_CREATE;
194183234Ssimon		else if (!strcmp (*args, "-compress"))
195183234Ssimon			operation = SMIME_COMPRESS;
196183234Ssimon		else if (!strcmp (*args, "-uncompress"))
197183234Ssimon			operation = SMIME_UNCOMPRESS;
198183234Ssimon		else if (!strcmp (*args, "-EncryptedData_decrypt"))
199183234Ssimon			operation = SMIME_ENCRYPTED_DECRYPT;
200183234Ssimon		else if (!strcmp (*args, "-EncryptedData_encrypt"))
201183234Ssimon			operation = SMIME_ENCRYPTED_ENCRYPT;
202183234Ssimon#ifndef OPENSSL_NO_DES
203183234Ssimon		else if (!strcmp (*args, "-des3"))
204183234Ssimon				cipher = EVP_des_ede3_cbc();
205183234Ssimon		else if (!strcmp (*args, "-des"))
206183234Ssimon				cipher = EVP_des_cbc();
207183234Ssimon#endif
208183234Ssimon#ifndef OPENSSL_NO_SEED
209183234Ssimon		else if (!strcmp (*args, "-seed"))
210183234Ssimon				cipher = EVP_seed_cbc();
211183234Ssimon#endif
212183234Ssimon#ifndef OPENSSL_NO_RC2
213183234Ssimon		else if (!strcmp (*args, "-rc2-40"))
214183234Ssimon				cipher = EVP_rc2_40_cbc();
215183234Ssimon		else if (!strcmp (*args, "-rc2-128"))
216183234Ssimon				cipher = EVP_rc2_cbc();
217183234Ssimon		else if (!strcmp (*args, "-rc2-64"))
218183234Ssimon				cipher = EVP_rc2_64_cbc();
219183234Ssimon#endif
220183234Ssimon#ifndef OPENSSL_NO_AES
221183234Ssimon		else if (!strcmp(*args,"-aes128"))
222183234Ssimon				cipher = EVP_aes_128_cbc();
223183234Ssimon		else if (!strcmp(*args,"-aes192"))
224183234Ssimon				cipher = EVP_aes_192_cbc();
225183234Ssimon		else if (!strcmp(*args,"-aes256"))
226183234Ssimon				cipher = EVP_aes_256_cbc();
227183234Ssimon#endif
228183234Ssimon#ifndef OPENSSL_NO_CAMELLIA
229183234Ssimon		else if (!strcmp(*args,"-camellia128"))
230183234Ssimon				cipher = EVP_camellia_128_cbc();
231183234Ssimon		else if (!strcmp(*args,"-camellia192"))
232183234Ssimon				cipher = EVP_camellia_192_cbc();
233183234Ssimon		else if (!strcmp(*args,"-camellia256"))
234183234Ssimon				cipher = EVP_camellia_256_cbc();
235183234Ssimon#endif
236246772Sjkim		else if (!strcmp (*args, "-debug_decrypt"))
237246772Sjkim				flags |= CMS_DEBUG_DECRYPT;
238183234Ssimon		else if (!strcmp (*args, "-text"))
239183234Ssimon				flags |= CMS_TEXT;
240183234Ssimon		else if (!strcmp (*args, "-nointern"))
241183234Ssimon				flags |= CMS_NOINTERN;
242183234Ssimon		else if (!strcmp (*args, "-noverify")
243183234Ssimon			|| !strcmp (*args, "-no_signer_cert_verify"))
244183234Ssimon				flags |= CMS_NO_SIGNER_CERT_VERIFY;
245183234Ssimon		else if (!strcmp (*args, "-nocerts"))
246183234Ssimon				flags |= CMS_NOCERTS;
247183234Ssimon		else if (!strcmp (*args, "-noattr"))
248183234Ssimon				flags |= CMS_NOATTR;
249183234Ssimon		else if (!strcmp (*args, "-nodetach"))
250183234Ssimon				flags &= ~CMS_DETACHED;
251183234Ssimon		else if (!strcmp (*args, "-nosmimecap"))
252183234Ssimon				flags |= CMS_NOSMIMECAP;
253183234Ssimon		else if (!strcmp (*args, "-binary"))
254183234Ssimon				flags |= CMS_BINARY;
255183234Ssimon		else if (!strcmp (*args, "-keyid"))
256183234Ssimon				flags |= CMS_USE_KEYID;
257183234Ssimon		else if (!strcmp (*args, "-nosigs"))
258183234Ssimon				flags |= CMS_NOSIGS;
259183234Ssimon		else if (!strcmp (*args, "-no_content_verify"))
260183234Ssimon				flags |= CMS_NO_CONTENT_VERIFY;
261183234Ssimon		else if (!strcmp (*args, "-no_attr_verify"))
262183234Ssimon				flags |= CMS_NO_ATTR_VERIFY;
263183234Ssimon		else if (!strcmp (*args, "-stream"))
264238405Sjkim				flags |= CMS_STREAM;
265183234Ssimon		else if (!strcmp (*args, "-indef"))
266238405Sjkim				flags |= CMS_STREAM;
267183234Ssimon		else if (!strcmp (*args, "-noindef"))
268183234Ssimon				flags &= ~CMS_STREAM;
269183234Ssimon		else if (!strcmp (*args, "-nooldmime"))
270183234Ssimon				flags |= CMS_NOOLDMIMETYPE;
271183234Ssimon		else if (!strcmp (*args, "-crlfeol"))
272183234Ssimon				flags |= CMS_CRLFEOL;
273238405Sjkim		else if (!strcmp (*args, "-noout"))
274238405Sjkim				noout = 1;
275183234Ssimon		else if (!strcmp (*args, "-receipt_request_print"))
276183234Ssimon				rr_print = 1;
277183234Ssimon		else if (!strcmp (*args, "-receipt_request_all"))
278183234Ssimon				rr_allorfirst = 0;
279183234Ssimon		else if (!strcmp (*args, "-receipt_request_first"))
280183234Ssimon				rr_allorfirst = 1;
281183234Ssimon		else if (!strcmp(*args,"-receipt_request_from"))
282183234Ssimon			{
283183234Ssimon			if (!args[1])
284183234Ssimon				goto argerr;
285183234Ssimon			args++;
286183234Ssimon			if (!rr_from)
287238405Sjkim				rr_from = sk_OPENSSL_STRING_new_null();
288238405Sjkim			sk_OPENSSL_STRING_push(rr_from, *args);
289183234Ssimon			}
290183234Ssimon		else if (!strcmp(*args,"-receipt_request_to"))
291183234Ssimon			{
292183234Ssimon			if (!args[1])
293183234Ssimon				goto argerr;
294183234Ssimon			args++;
295183234Ssimon			if (!rr_to)
296238405Sjkim				rr_to = sk_OPENSSL_STRING_new_null();
297238405Sjkim			sk_OPENSSL_STRING_push(rr_to, *args);
298183234Ssimon			}
299238405Sjkim		else if (!strcmp (*args, "-print"))
300238405Sjkim				{
301238405Sjkim				noout = 1;
302238405Sjkim				print = 1;
303238405Sjkim				}
304183234Ssimon		else if (!strcmp(*args,"-secretkey"))
305183234Ssimon			{
306183234Ssimon			long ltmp;
307183234Ssimon			if (!args[1])
308183234Ssimon				goto argerr;
309183234Ssimon			args++;
310183234Ssimon			secret_key = string_to_hex(*args, &ltmp);
311183234Ssimon			if (!secret_key)
312183234Ssimon				{
313183234Ssimon				BIO_printf(bio_err, "Invalid key %s\n", *args);
314183234Ssimon				goto argerr;
315183234Ssimon				}
316183234Ssimon			secret_keylen = (size_t)ltmp;
317183234Ssimon			}
318183234Ssimon		else if (!strcmp(*args,"-secretkeyid"))
319183234Ssimon			{
320183234Ssimon			long ltmp;
321183234Ssimon			if (!args[1])
322183234Ssimon				goto argerr;
323183234Ssimon			args++;
324183234Ssimon			secret_keyid = string_to_hex(*args, &ltmp);
325183234Ssimon			if (!secret_keyid)
326183234Ssimon				{
327183234Ssimon				BIO_printf(bio_err, "Invalid id %s\n", *args);
328183234Ssimon				goto argerr;
329183234Ssimon				}
330183234Ssimon			secret_keyidlen = (size_t)ltmp;
331183234Ssimon			}
332238405Sjkim		else if (!strcmp(*args,"-pwri_password"))
333238405Sjkim			{
334238405Sjkim			if (!args[1])
335238405Sjkim				goto argerr;
336238405Sjkim			args++;
337238405Sjkim			pwri_pass = (unsigned char *)*args;
338238405Sjkim			}
339183234Ssimon		else if (!strcmp(*args,"-econtent_type"))
340183234Ssimon			{
341183234Ssimon			if (!args[1])
342183234Ssimon				goto argerr;
343183234Ssimon			args++;
344183234Ssimon			econtent_type = OBJ_txt2obj(*args, 0);
345183234Ssimon			if (!econtent_type)
346183234Ssimon				{
347183234Ssimon				BIO_printf(bio_err, "Invalid OID %s\n", *args);
348183234Ssimon				goto argerr;
349183234Ssimon				}
350183234Ssimon			}
351183234Ssimon		else if (!strcmp(*args,"-rand"))
352183234Ssimon			{
353183234Ssimon			if (!args[1])
354183234Ssimon				goto argerr;
355183234Ssimon			args++;
356183234Ssimon			inrand = *args;
357183234Ssimon			need_rand = 1;
358183234Ssimon			}
359183234Ssimon#ifndef OPENSSL_NO_ENGINE
360183234Ssimon		else if (!strcmp(*args,"-engine"))
361183234Ssimon			{
362183234Ssimon			if (!args[1])
363183234Ssimon				goto argerr;
364183234Ssimon			engine = *++args;
365183234Ssimon			}
366183234Ssimon#endif
367183234Ssimon		else if (!strcmp(*args,"-passin"))
368183234Ssimon			{
369183234Ssimon			if (!args[1])
370183234Ssimon				goto argerr;
371183234Ssimon			passargin = *++args;
372183234Ssimon			}
373183234Ssimon		else if (!strcmp (*args, "-to"))
374183234Ssimon			{
375183234Ssimon			if (!args[1])
376183234Ssimon				goto argerr;
377183234Ssimon			to = *++args;
378183234Ssimon			}
379183234Ssimon		else if (!strcmp (*args, "-from"))
380183234Ssimon			{
381183234Ssimon			if (!args[1])
382183234Ssimon				goto argerr;
383183234Ssimon			from = *++args;
384183234Ssimon			}
385183234Ssimon		else if (!strcmp (*args, "-subject"))
386183234Ssimon			{
387183234Ssimon			if (!args[1])
388183234Ssimon				goto argerr;
389183234Ssimon			subject = *++args;
390183234Ssimon			}
391183234Ssimon		else if (!strcmp (*args, "-signer"))
392183234Ssimon			{
393183234Ssimon			if (!args[1])
394183234Ssimon				goto argerr;
395183234Ssimon			/* If previous -signer argument add signer to list */
396183234Ssimon
397183234Ssimon			if (signerfile)
398183234Ssimon				{
399183234Ssimon				if (!sksigners)
400238405Sjkim					sksigners = sk_OPENSSL_STRING_new_null();
401238405Sjkim				sk_OPENSSL_STRING_push(sksigners, signerfile);
402183234Ssimon				if (!keyfile)
403183234Ssimon					keyfile = signerfile;
404183234Ssimon				if (!skkeys)
405238405Sjkim					skkeys = sk_OPENSSL_STRING_new_null();
406238405Sjkim				sk_OPENSSL_STRING_push(skkeys, keyfile);
407183234Ssimon				keyfile = NULL;
408183234Ssimon				}
409183234Ssimon			signerfile = *++args;
410183234Ssimon			}
411183234Ssimon		else if (!strcmp (*args, "-recip"))
412183234Ssimon			{
413183234Ssimon			if (!args[1])
414183234Ssimon				goto argerr;
415183234Ssimon			recipfile = *++args;
416183234Ssimon			}
417183234Ssimon		else if (!strcmp (*args, "-certsout"))
418183234Ssimon			{
419183234Ssimon			if (!args[1])
420183234Ssimon				goto argerr;
421183234Ssimon			certsoutfile = *++args;
422183234Ssimon			}
423183234Ssimon		else if (!strcmp (*args, "-md"))
424183234Ssimon			{
425183234Ssimon			if (!args[1])
426183234Ssimon				goto argerr;
427183234Ssimon			sign_md = EVP_get_digestbyname(*++args);
428183234Ssimon			if (sign_md == NULL)
429183234Ssimon				{
430183234Ssimon				BIO_printf(bio_err, "Unknown digest %s\n",
431183234Ssimon							*args);
432183234Ssimon				goto argerr;
433183234Ssimon				}
434183234Ssimon			}
435183234Ssimon		else if (!strcmp (*args, "-inkey"))
436183234Ssimon			{
437183234Ssimon			if (!args[1])
438183234Ssimon				goto argerr;
439183234Ssimon			/* If previous -inkey arument add signer to list */
440183234Ssimon			if (keyfile)
441183234Ssimon				{
442183234Ssimon				if (!signerfile)
443183234Ssimon					{
444183234Ssimon					BIO_puts(bio_err, "Illegal -inkey without -signer\n");
445183234Ssimon					goto argerr;
446183234Ssimon					}
447183234Ssimon				if (!sksigners)
448238405Sjkim					sksigners = sk_OPENSSL_STRING_new_null();
449238405Sjkim				sk_OPENSSL_STRING_push(sksigners, signerfile);
450183234Ssimon				signerfile = NULL;
451183234Ssimon				if (!skkeys)
452238405Sjkim					skkeys = sk_OPENSSL_STRING_new_null();
453238405Sjkim				sk_OPENSSL_STRING_push(skkeys, keyfile);
454183234Ssimon				}
455183234Ssimon			keyfile = *++args;
456183234Ssimon			}
457183234Ssimon		else if (!strcmp (*args, "-keyform"))
458183234Ssimon			{
459183234Ssimon			if (!args[1])
460183234Ssimon				goto argerr;
461183234Ssimon			keyform = str2fmt(*++args);
462183234Ssimon			}
463183234Ssimon		else if (!strcmp (*args, "-rctform"))
464183234Ssimon			{
465183234Ssimon			if (!args[1])
466183234Ssimon				goto argerr;
467183234Ssimon			rctformat = str2fmt(*++args);
468183234Ssimon			}
469183234Ssimon		else if (!strcmp (*args, "-certfile"))
470183234Ssimon			{
471183234Ssimon			if (!args[1])
472183234Ssimon				goto argerr;
473183234Ssimon			certfile = *++args;
474183234Ssimon			}
475183234Ssimon		else if (!strcmp (*args, "-CAfile"))
476183234Ssimon			{
477183234Ssimon			if (!args[1])
478183234Ssimon				goto argerr;
479183234Ssimon			CAfile = *++args;
480183234Ssimon			}
481183234Ssimon		else if (!strcmp (*args, "-CApath"))
482183234Ssimon			{
483183234Ssimon			if (!args[1])
484183234Ssimon				goto argerr;
485183234Ssimon			CApath = *++args;
486183234Ssimon			}
487183234Ssimon		else if (!strcmp (*args, "-in"))
488183234Ssimon			{
489183234Ssimon			if (!args[1])
490183234Ssimon				goto argerr;
491183234Ssimon			infile = *++args;
492183234Ssimon			}
493183234Ssimon		else if (!strcmp (*args, "-inform"))
494183234Ssimon			{
495183234Ssimon			if (!args[1])
496183234Ssimon				goto argerr;
497183234Ssimon			informat = str2fmt(*++args);
498183234Ssimon			}
499183234Ssimon		else if (!strcmp (*args, "-outform"))
500183234Ssimon			{
501183234Ssimon			if (!args[1])
502183234Ssimon				goto argerr;
503183234Ssimon			outformat = str2fmt(*++args);
504183234Ssimon			}
505183234Ssimon		else if (!strcmp (*args, "-out"))
506183234Ssimon			{
507183234Ssimon			if (!args[1])
508183234Ssimon				goto argerr;
509183234Ssimon			outfile = *++args;
510183234Ssimon			}
511183234Ssimon		else if (!strcmp (*args, "-content"))
512183234Ssimon			{
513183234Ssimon			if (!args[1])
514183234Ssimon				goto argerr;
515183234Ssimon			contfile = *++args;
516183234Ssimon			}
517183234Ssimon		else if (args_verify(&args, NULL, &badarg, bio_err, &vpm))
518183234Ssimon			continue;
519183234Ssimon		else if ((cipher = EVP_get_cipherbyname(*args + 1)) == NULL)
520183234Ssimon			badarg = 1;
521183234Ssimon		args++;
522183234Ssimon		}
523183234Ssimon
524183234Ssimon	if (((rr_allorfirst != -1) || rr_from) && !rr_to)
525183234Ssimon		{
526183234Ssimon		BIO_puts(bio_err, "No Signed Receipts Recipients\n");
527183234Ssimon		goto argerr;
528183234Ssimon		}
529183234Ssimon
530183234Ssimon	if (!(operation & SMIME_SIGNERS)  && (rr_to || rr_from))
531183234Ssimon		{
532183234Ssimon		BIO_puts(bio_err, "Signed receipts only allowed with -sign\n");
533183234Ssimon		goto argerr;
534183234Ssimon		}
535183234Ssimon	if (!(operation & SMIME_SIGNERS) && (skkeys || sksigners))
536183234Ssimon		{
537183234Ssimon		BIO_puts(bio_err, "Multiple signers or keys not allowed\n");
538183234Ssimon		goto argerr;
539183234Ssimon		}
540183234Ssimon
541183234Ssimon	if (operation & SMIME_SIGNERS)
542183234Ssimon		{
543183234Ssimon		if (keyfile && !signerfile)
544183234Ssimon			{
545183234Ssimon			BIO_puts(bio_err, "Illegal -inkey without -signer\n");
546183234Ssimon			goto argerr;
547183234Ssimon			}
548183234Ssimon		/* Check to see if any final signer needs to be appended */
549183234Ssimon		if (signerfile)
550183234Ssimon			{
551183234Ssimon			if (!sksigners)
552238405Sjkim				sksigners = sk_OPENSSL_STRING_new_null();
553238405Sjkim			sk_OPENSSL_STRING_push(sksigners, signerfile);
554183234Ssimon			if (!skkeys)
555238405Sjkim				skkeys = sk_OPENSSL_STRING_new_null();
556183234Ssimon			if (!keyfile)
557183234Ssimon				keyfile = signerfile;
558238405Sjkim			sk_OPENSSL_STRING_push(skkeys, keyfile);
559183234Ssimon			}
560183234Ssimon		if (!sksigners)
561183234Ssimon			{
562183234Ssimon			BIO_printf(bio_err, "No signer certificate specified\n");
563183234Ssimon			badarg = 1;
564183234Ssimon			}
565183234Ssimon		signerfile = NULL;
566183234Ssimon		keyfile = NULL;
567183234Ssimon		need_rand = 1;
568183234Ssimon		}
569183234Ssimon
570183234Ssimon	else if (operation == SMIME_DECRYPT)
571183234Ssimon		{
572238405Sjkim		if (!recipfile && !keyfile && !secret_key && !pwri_pass)
573183234Ssimon			{
574183234Ssimon			BIO_printf(bio_err, "No recipient certificate or key specified\n");
575183234Ssimon			badarg = 1;
576183234Ssimon			}
577183234Ssimon		}
578183234Ssimon	else if (operation == SMIME_ENCRYPT)
579183234Ssimon		{
580238405Sjkim		if (!*args && !secret_key && !pwri_pass)
581183234Ssimon			{
582183234Ssimon			BIO_printf(bio_err, "No recipient(s) certificate(s) specified\n");
583183234Ssimon			badarg = 1;
584183234Ssimon			}
585183234Ssimon		need_rand = 1;
586183234Ssimon		}
587183234Ssimon	else if (!operation)
588183234Ssimon		badarg = 1;
589183234Ssimon
590183234Ssimon	if (badarg)
591183234Ssimon		{
592183234Ssimon		argerr:
593183234Ssimon		BIO_printf (bio_err, "Usage cms [options] cert.pem ...\n");
594183234Ssimon		BIO_printf (bio_err, "where options are\n");
595183234Ssimon		BIO_printf (bio_err, "-encrypt       encrypt message\n");
596183234Ssimon		BIO_printf (bio_err, "-decrypt       decrypt encrypted message\n");
597183234Ssimon		BIO_printf (bio_err, "-sign          sign message\n");
598183234Ssimon		BIO_printf (bio_err, "-verify        verify signed message\n");
599183234Ssimon		BIO_printf (bio_err, "-cmsout        output CMS structure\n");
600183234Ssimon#ifndef OPENSSL_NO_DES
601183234Ssimon		BIO_printf (bio_err, "-des3          encrypt with triple DES\n");
602183234Ssimon		BIO_printf (bio_err, "-des           encrypt with DES\n");
603183234Ssimon#endif
604183234Ssimon#ifndef OPENSSL_NO_SEED
605183234Ssimon		BIO_printf (bio_err, "-seed          encrypt with SEED\n");
606183234Ssimon#endif
607183234Ssimon#ifndef OPENSSL_NO_RC2
608183234Ssimon		BIO_printf (bio_err, "-rc2-40        encrypt with RC2-40 (default)\n");
609183234Ssimon		BIO_printf (bio_err, "-rc2-64        encrypt with RC2-64\n");
610183234Ssimon		BIO_printf (bio_err, "-rc2-128       encrypt with RC2-128\n");
611183234Ssimon#endif
612183234Ssimon#ifndef OPENSSL_NO_AES
613183234Ssimon		BIO_printf (bio_err, "-aes128, -aes192, -aes256\n");
614183234Ssimon		BIO_printf (bio_err, "               encrypt PEM output with cbc aes\n");
615183234Ssimon#endif
616183234Ssimon#ifndef OPENSSL_NO_CAMELLIA
617183234Ssimon		BIO_printf (bio_err, "-camellia128, -camellia192, -camellia256\n");
618183234Ssimon		BIO_printf (bio_err, "               encrypt PEM output with cbc camellia\n");
619183234Ssimon#endif
620183234Ssimon		BIO_printf (bio_err, "-nointern      don't search certificates in message for signer\n");
621183234Ssimon		BIO_printf (bio_err, "-nosigs        don't verify message signature\n");
622183234Ssimon		BIO_printf (bio_err, "-noverify      don't verify signers certificate\n");
623183234Ssimon		BIO_printf (bio_err, "-nocerts       don't include signers certificate when signing\n");
624183234Ssimon		BIO_printf (bio_err, "-nodetach      use opaque signing\n");
625183234Ssimon		BIO_printf (bio_err, "-noattr        don't include any signed attributes\n");
626183234Ssimon		BIO_printf (bio_err, "-binary        don't translate message to text\n");
627183234Ssimon		BIO_printf (bio_err, "-certfile file other certificates file\n");
628183234Ssimon		BIO_printf (bio_err, "-certsout file certificate output file\n");
629183234Ssimon		BIO_printf (bio_err, "-signer file   signer certificate file\n");
630183234Ssimon		BIO_printf (bio_err, "-recip  file   recipient certificate file for decryption\n");
631237657Sjkim		BIO_printf (bio_err, "-keyid         use subject key identifier\n");
632183234Ssimon		BIO_printf (bio_err, "-in file       input file\n");
633183234Ssimon		BIO_printf (bio_err, "-inform arg    input format SMIME (default), PEM or DER\n");
634183234Ssimon		BIO_printf (bio_err, "-inkey file    input private key (if not signer or recipient)\n");
635183234Ssimon		BIO_printf (bio_err, "-keyform arg   input private key format (PEM or ENGINE)\n");
636183234Ssimon		BIO_printf (bio_err, "-out file      output file\n");
637183234Ssimon		BIO_printf (bio_err, "-outform arg   output format SMIME (default), PEM or DER\n");
638183234Ssimon		BIO_printf (bio_err, "-content file  supply or override content for detached signature\n");
639183234Ssimon		BIO_printf (bio_err, "-to addr       to address\n");
640183234Ssimon		BIO_printf (bio_err, "-from ad       from address\n");
641183234Ssimon		BIO_printf (bio_err, "-subject s     subject\n");
642183234Ssimon		BIO_printf (bio_err, "-text          include or delete text MIME headers\n");
643183234Ssimon		BIO_printf (bio_err, "-CApath dir    trusted certificates directory\n");
644183234Ssimon		BIO_printf (bio_err, "-CAfile file   trusted certificates file\n");
645183234Ssimon		BIO_printf (bio_err, "-crl_check     check revocation status of signer's certificate using CRLs\n");
646183234Ssimon		BIO_printf (bio_err, "-crl_check_all check revocation status of signer's certificate chain using CRLs\n");
647183234Ssimon#ifndef OPENSSL_NO_ENGINE
648183234Ssimon		BIO_printf (bio_err, "-engine e      use engine e, possibly a hardware device.\n");
649183234Ssimon#endif
650183234Ssimon		BIO_printf (bio_err, "-passin arg    input file pass phrase source\n");
651183234Ssimon		BIO_printf(bio_err,  "-rand file%cfile%c...\n", LIST_SEPARATOR_CHAR, LIST_SEPARATOR_CHAR);
652183234Ssimon		BIO_printf(bio_err,  "               load the file (or the files in the directory) into\n");
653183234Ssimon		BIO_printf(bio_err,  "               the random number generator\n");
654183234Ssimon		BIO_printf (bio_err, "cert.pem       recipient certificate(s) for encryption\n");
655183234Ssimon		goto end;
656183234Ssimon		}
657183234Ssimon
658183234Ssimon#ifndef OPENSSL_NO_ENGINE
659183234Ssimon        e = setup_engine(bio_err, engine, 0);
660183234Ssimon#endif
661183234Ssimon
662183234Ssimon	if (!app_passwd(bio_err, passargin, NULL, &passin, NULL))
663183234Ssimon		{
664183234Ssimon		BIO_printf(bio_err, "Error getting password\n");
665183234Ssimon		goto end;
666183234Ssimon		}
667183234Ssimon
668183234Ssimon	if (need_rand)
669183234Ssimon		{
670183234Ssimon		app_RAND_load_file(NULL, bio_err, (inrand != NULL));
671183234Ssimon		if (inrand != NULL)
672183234Ssimon			BIO_printf(bio_err,"%ld semi-random bytes loaded\n",
673183234Ssimon				app_RAND_load_files(inrand));
674183234Ssimon		}
675183234Ssimon
676183234Ssimon	ret = 2;
677183234Ssimon
678183234Ssimon	if (!(operation & SMIME_SIGNERS))
679183234Ssimon		flags &= ~CMS_DETACHED;
680183234Ssimon
681183234Ssimon	if (operation & SMIME_OP)
682183234Ssimon		{
683183234Ssimon		if (outformat == FORMAT_ASN1)
684183234Ssimon			outmode = "wb";
685183234Ssimon		}
686183234Ssimon	else
687183234Ssimon		{
688183234Ssimon		if (flags & CMS_BINARY)
689183234Ssimon			outmode = "wb";
690183234Ssimon		}
691183234Ssimon
692183234Ssimon	if (operation & SMIME_IP)
693183234Ssimon		{
694183234Ssimon		if (informat == FORMAT_ASN1)
695183234Ssimon			inmode = "rb";
696183234Ssimon		}
697183234Ssimon	else
698183234Ssimon		{
699183234Ssimon		if (flags & CMS_BINARY)
700183234Ssimon			inmode = "rb";
701183234Ssimon		}
702183234Ssimon
703183234Ssimon	if (operation == SMIME_ENCRYPT)
704183234Ssimon		{
705183234Ssimon		if (!cipher)
706183234Ssimon			{
707183234Ssimon#ifndef OPENSSL_NO_DES
708183234Ssimon			cipher = EVP_des_ede3_cbc();
709183234Ssimon#else
710183234Ssimon			BIO_printf(bio_err, "No cipher selected\n");
711183234Ssimon			goto end;
712183234Ssimon#endif
713183234Ssimon			}
714183234Ssimon
715183234Ssimon		if (secret_key && !secret_keyid)
716183234Ssimon			{
717238405Sjkim			BIO_printf(bio_err, "No secret key id\n");
718183234Ssimon			goto end;
719183234Ssimon			}
720183234Ssimon
721183234Ssimon		if (*args)
722183234Ssimon			encerts = sk_X509_new_null();
723183234Ssimon		while (*args)
724183234Ssimon			{
725183234Ssimon			if (!(cert = load_cert(bio_err,*args,FORMAT_PEM,
726183234Ssimon				NULL, e, "recipient certificate file")))
727183234Ssimon				goto end;
728183234Ssimon			sk_X509_push(encerts, cert);
729183234Ssimon			cert = NULL;
730183234Ssimon			args++;
731183234Ssimon			}
732183234Ssimon		}
733183234Ssimon
734183234Ssimon	if (certfile)
735183234Ssimon		{
736183234Ssimon		if (!(other = load_certs(bio_err,certfile,FORMAT_PEM, NULL,
737183234Ssimon			e, "certificate file")))
738183234Ssimon			{
739183234Ssimon			ERR_print_errors(bio_err);
740183234Ssimon			goto end;
741183234Ssimon			}
742183234Ssimon		}
743183234Ssimon
744183234Ssimon	if (recipfile && (operation == SMIME_DECRYPT))
745183234Ssimon		{
746183234Ssimon		if (!(recip = load_cert(bio_err,recipfile,FORMAT_PEM,NULL,
747183234Ssimon			e, "recipient certificate file")))
748183234Ssimon			{
749183234Ssimon			ERR_print_errors(bio_err);
750183234Ssimon			goto end;
751183234Ssimon			}
752183234Ssimon		}
753183234Ssimon
754183234Ssimon	if (operation == SMIME_SIGN_RECEIPT)
755183234Ssimon		{
756183234Ssimon		if (!(signer = load_cert(bio_err,signerfile,FORMAT_PEM,NULL,
757183234Ssimon			e, "receipt signer certificate file")))
758183234Ssimon			{
759183234Ssimon			ERR_print_errors(bio_err);
760183234Ssimon			goto end;
761183234Ssimon			}
762183234Ssimon		}
763183234Ssimon
764183234Ssimon	if (operation == SMIME_DECRYPT)
765183234Ssimon		{
766183234Ssimon		if (!keyfile)
767183234Ssimon			keyfile = recipfile;
768183234Ssimon		}
769183234Ssimon	else if ((operation == SMIME_SIGN) || (operation == SMIME_SIGN_RECEIPT))
770183234Ssimon		{
771183234Ssimon		if (!keyfile)
772183234Ssimon			keyfile = signerfile;
773183234Ssimon		}
774183234Ssimon	else keyfile = NULL;
775183234Ssimon
776183234Ssimon	if (keyfile)
777183234Ssimon		{
778183234Ssimon		key = load_key(bio_err, keyfile, keyform, 0, passin, e,
779183234Ssimon			       "signing key file");
780183234Ssimon		if (!key)
781183234Ssimon			goto end;
782183234Ssimon		}
783183234Ssimon
784183234Ssimon	if (infile)
785183234Ssimon		{
786183234Ssimon		if (!(in = BIO_new_file(infile, inmode)))
787183234Ssimon			{
788183234Ssimon			BIO_printf (bio_err,
789183234Ssimon				 "Can't open input file %s\n", infile);
790183234Ssimon			goto end;
791183234Ssimon			}
792183234Ssimon		}
793183234Ssimon	else
794183234Ssimon		in = BIO_new_fp(stdin, BIO_NOCLOSE);
795183234Ssimon
796183234Ssimon	if (operation & SMIME_IP)
797183234Ssimon		{
798183234Ssimon		if (informat == FORMAT_SMIME)
799183234Ssimon			cms = SMIME_read_CMS(in, &indata);
800183234Ssimon		else if (informat == FORMAT_PEM)
801183234Ssimon			cms = PEM_read_bio_CMS(in, NULL, NULL, NULL);
802183234Ssimon		else if (informat == FORMAT_ASN1)
803183234Ssimon			cms = d2i_CMS_bio(in, NULL);
804183234Ssimon		else
805183234Ssimon			{
806183234Ssimon			BIO_printf(bio_err, "Bad input format for CMS file\n");
807183234Ssimon			goto end;
808183234Ssimon			}
809183234Ssimon
810183234Ssimon		if (!cms)
811183234Ssimon			{
812183234Ssimon			BIO_printf(bio_err, "Error reading S/MIME message\n");
813183234Ssimon			goto end;
814183234Ssimon			}
815183234Ssimon		if (contfile)
816183234Ssimon			{
817183234Ssimon			BIO_free(indata);
818183234Ssimon			if (!(indata = BIO_new_file(contfile, "rb")))
819183234Ssimon				{
820183234Ssimon				BIO_printf(bio_err, "Can't read content file %s\n", contfile);
821183234Ssimon				goto end;
822183234Ssimon				}
823183234Ssimon			}
824183234Ssimon		if (certsoutfile)
825183234Ssimon			{
826183234Ssimon			STACK_OF(X509) *allcerts;
827183234Ssimon			allcerts = CMS_get1_certs(cms);
828183234Ssimon			if (!save_certs(certsoutfile, allcerts))
829183234Ssimon				{
830183234Ssimon				BIO_printf(bio_err,
831183234Ssimon						"Error writing certs to %s\n",
832183234Ssimon								certsoutfile);
833183234Ssimon				ret = 5;
834183234Ssimon				goto end;
835183234Ssimon				}
836183234Ssimon			sk_X509_pop_free(allcerts, X509_free);
837183234Ssimon			}
838183234Ssimon		}
839183234Ssimon
840183234Ssimon	if (rctfile)
841183234Ssimon		{
842183234Ssimon		char *rctmode = (rctformat == FORMAT_ASN1) ? "rb" : "r";
843183234Ssimon		if (!(rctin = BIO_new_file(rctfile, rctmode)))
844183234Ssimon			{
845183234Ssimon			BIO_printf (bio_err,
846183234Ssimon				 "Can't open receipt file %s\n", rctfile);
847183234Ssimon			goto end;
848183234Ssimon			}
849183234Ssimon
850183234Ssimon		if (rctformat == FORMAT_SMIME)
851183234Ssimon			rcms = SMIME_read_CMS(rctin, NULL);
852183234Ssimon		else if (rctformat == FORMAT_PEM)
853183234Ssimon			rcms = PEM_read_bio_CMS(rctin, NULL, NULL, NULL);
854183234Ssimon		else if (rctformat == FORMAT_ASN1)
855183234Ssimon			rcms = d2i_CMS_bio(rctin, NULL);
856183234Ssimon		else
857183234Ssimon			{
858183234Ssimon			BIO_printf(bio_err, "Bad input format for receipt\n");
859183234Ssimon			goto end;
860183234Ssimon			}
861183234Ssimon
862183234Ssimon		if (!rcms)
863183234Ssimon			{
864183234Ssimon			BIO_printf(bio_err, "Error reading receipt\n");
865183234Ssimon			goto end;
866183234Ssimon			}
867183234Ssimon		}
868183234Ssimon
869183234Ssimon	if (outfile)
870183234Ssimon		{
871183234Ssimon		if (!(out = BIO_new_file(outfile, outmode)))
872183234Ssimon			{
873183234Ssimon			BIO_printf (bio_err,
874183234Ssimon				 "Can't open output file %s\n", outfile);
875183234Ssimon			goto end;
876183234Ssimon			}
877183234Ssimon		}
878183234Ssimon	else
879183234Ssimon		{
880183234Ssimon		out = BIO_new_fp(stdout, BIO_NOCLOSE);
881183234Ssimon#ifdef OPENSSL_SYS_VMS
882183234Ssimon		{
883183234Ssimon		    BIO *tmpbio = BIO_new(BIO_f_linebuffer());
884183234Ssimon		    out = BIO_push(tmpbio, out);
885183234Ssimon		}
886183234Ssimon#endif
887183234Ssimon		}
888183234Ssimon
889183234Ssimon	if ((operation == SMIME_VERIFY) || (operation == SMIME_VERIFY_RECEIPT))
890183234Ssimon		{
891183234Ssimon		if (!(store = setup_verify(bio_err, CAfile, CApath)))
892183234Ssimon			goto end;
893238405Sjkim		X509_STORE_set_verify_cb(store, cms_cb);
894183234Ssimon		if (vpm)
895183234Ssimon			X509_STORE_set1_param(store, vpm);
896183234Ssimon		}
897183234Ssimon
898183234Ssimon
899183234Ssimon	ret = 3;
900183234Ssimon
901183234Ssimon	if (operation == SMIME_DATA_CREATE)
902183234Ssimon		{
903183234Ssimon		cms = CMS_data_create(in, flags);
904183234Ssimon		}
905183234Ssimon	else if (operation == SMIME_DIGEST_CREATE)
906183234Ssimon		{
907183234Ssimon		cms = CMS_digest_create(in, sign_md, flags);
908183234Ssimon		}
909183234Ssimon	else if (operation == SMIME_COMPRESS)
910183234Ssimon		{
911183234Ssimon		cms = CMS_compress(in, -1, flags);
912183234Ssimon		}
913183234Ssimon	else if (operation == SMIME_ENCRYPT)
914183234Ssimon		{
915183234Ssimon		flags |= CMS_PARTIAL;
916183234Ssimon		cms = CMS_encrypt(encerts, in, cipher, flags);
917183234Ssimon		if (!cms)
918183234Ssimon			goto end;
919183234Ssimon		if (secret_key)
920183234Ssimon			{
921183234Ssimon			if (!CMS_add0_recipient_key(cms, NID_undef,
922183234Ssimon						secret_key, secret_keylen,
923183234Ssimon						secret_keyid, secret_keyidlen,
924183234Ssimon						NULL, NULL, NULL))
925183234Ssimon				goto end;
926183234Ssimon			/* NULL these because call absorbs them */
927183234Ssimon			secret_key = NULL;
928183234Ssimon			secret_keyid = NULL;
929183234Ssimon			}
930238405Sjkim		if (pwri_pass)
931238405Sjkim			{
932238405Sjkim			pwri_tmp = (unsigned char *)BUF_strdup((char *)pwri_pass);
933238405Sjkim			if (!pwri_tmp)
934238405Sjkim				goto end;
935238405Sjkim			if (!CMS_add0_recipient_password(cms,
936238405Sjkim						-1, NID_undef, NID_undef,
937238405Sjkim						 pwri_tmp, -1, NULL))
938238405Sjkim				goto end;
939238405Sjkim			pwri_tmp = NULL;
940238405Sjkim			}
941183234Ssimon		if (!(flags & CMS_STREAM))
942183234Ssimon			{
943183234Ssimon			if (!CMS_final(cms, in, NULL, flags))
944183234Ssimon				goto end;
945183234Ssimon			}
946183234Ssimon		}
947183234Ssimon	else if (operation == SMIME_ENCRYPTED_ENCRYPT)
948183234Ssimon		{
949183234Ssimon		cms = CMS_EncryptedData_encrypt(in, cipher,
950183234Ssimon						secret_key, secret_keylen,
951183234Ssimon						flags);
952183234Ssimon
953183234Ssimon		}
954183234Ssimon	else if (operation == SMIME_SIGN_RECEIPT)
955183234Ssimon		{
956183234Ssimon		CMS_ContentInfo *srcms = NULL;
957183234Ssimon		STACK_OF(CMS_SignerInfo) *sis;
958183234Ssimon		CMS_SignerInfo *si;
959183234Ssimon		sis = CMS_get0_SignerInfos(cms);
960183234Ssimon		if (!sis)
961183234Ssimon			goto end;
962183234Ssimon		si = sk_CMS_SignerInfo_value(sis, 0);
963183234Ssimon		srcms = CMS_sign_receipt(si, signer, key, other, flags);
964183234Ssimon		if (!srcms)
965183234Ssimon			goto end;
966183234Ssimon		CMS_ContentInfo_free(cms);
967183234Ssimon		cms = srcms;
968183234Ssimon		}
969183234Ssimon	else if (operation & SMIME_SIGNERS)
970183234Ssimon		{
971183234Ssimon		int i;
972183234Ssimon		/* If detached data content we enable streaming if
973183234Ssimon		 * S/MIME output format.
974183234Ssimon		 */
975183234Ssimon		if (operation == SMIME_SIGN)
976183234Ssimon			{
977183234Ssimon
978183234Ssimon			if (flags & CMS_DETACHED)
979183234Ssimon				{
980183234Ssimon				if (outformat == FORMAT_SMIME)
981183234Ssimon					flags |= CMS_STREAM;
982183234Ssimon				}
983183234Ssimon			flags |= CMS_PARTIAL;
984183234Ssimon			cms = CMS_sign(NULL, NULL, other, in, flags);
985183234Ssimon			if (!cms)
986183234Ssimon				goto end;
987183234Ssimon			if (econtent_type)
988183234Ssimon				CMS_set1_eContentType(cms, econtent_type);
989183234Ssimon
990183234Ssimon			if (rr_to)
991183234Ssimon				{
992183234Ssimon				rr = make_receipt_request(rr_to, rr_allorfirst,
993183234Ssimon								rr_from);
994183234Ssimon				if (!rr)
995183234Ssimon					{
996183234Ssimon					BIO_puts(bio_err,
997183234Ssimon				"Signed Receipt Request Creation Error\n");
998183234Ssimon					goto end;
999183234Ssimon					}
1000183234Ssimon				}
1001183234Ssimon			}
1002183234Ssimon		else
1003183234Ssimon			flags |= CMS_REUSE_DIGEST;
1004238405Sjkim		for (i = 0; i < sk_OPENSSL_STRING_num(sksigners); i++)
1005183234Ssimon			{
1006183234Ssimon			CMS_SignerInfo *si;
1007238405Sjkim			signerfile = sk_OPENSSL_STRING_value(sksigners, i);
1008238405Sjkim			keyfile = sk_OPENSSL_STRING_value(skkeys, i);
1009183234Ssimon			signer = load_cert(bio_err, signerfile,FORMAT_PEM, NULL,
1010183234Ssimon					e, "signer certificate");
1011183234Ssimon			if (!signer)
1012183234Ssimon				goto end;
1013183234Ssimon			key = load_key(bio_err, keyfile, keyform, 0, passin, e,
1014183234Ssimon			       "signing key file");
1015183234Ssimon			if (!key)
1016183234Ssimon				goto end;
1017183234Ssimon			si = CMS_add1_signer(cms, signer, key, sign_md, flags);
1018183234Ssimon			if (!si)
1019183234Ssimon				goto end;
1020183234Ssimon			if (rr && !CMS_add1_ReceiptRequest(si, rr))
1021183234Ssimon				goto end;
1022183234Ssimon			X509_free(signer);
1023183234Ssimon			signer = NULL;
1024183234Ssimon			EVP_PKEY_free(key);
1025183234Ssimon			key = NULL;
1026183234Ssimon			}
1027183234Ssimon		/* If not streaming or resigning finalize structure */
1028183234Ssimon		if ((operation == SMIME_SIGN) && !(flags & CMS_STREAM))
1029183234Ssimon			{
1030183234Ssimon			if (!CMS_final(cms, in, NULL, flags))
1031183234Ssimon				goto end;
1032183234Ssimon			}
1033183234Ssimon		}
1034183234Ssimon
1035183234Ssimon	if (!cms)
1036183234Ssimon		{
1037183234Ssimon		BIO_printf(bio_err, "Error creating CMS structure\n");
1038183234Ssimon		goto end;
1039183234Ssimon		}
1040183234Ssimon
1041183234Ssimon	ret = 4;
1042183234Ssimon	if (operation == SMIME_DECRYPT)
1043183234Ssimon		{
1044246772Sjkim		if (flags & CMS_DEBUG_DECRYPT)
1045246772Sjkim			CMS_decrypt(cms, NULL, NULL, NULL, NULL, flags);
1046183234Ssimon
1047183234Ssimon		if (secret_key)
1048183234Ssimon			{
1049183234Ssimon			if (!CMS_decrypt_set1_key(cms,
1050183234Ssimon						secret_key, secret_keylen,
1051183234Ssimon						secret_keyid, secret_keyidlen))
1052183234Ssimon				{
1053183234Ssimon				BIO_puts(bio_err,
1054183234Ssimon					"Error decrypting CMS using secret key\n");
1055183234Ssimon				goto end;
1056183234Ssimon				}
1057183234Ssimon			}
1058183234Ssimon
1059183234Ssimon		if (key)
1060183234Ssimon			{
1061183234Ssimon			if (!CMS_decrypt_set1_pkey(cms, key, recip))
1062183234Ssimon				{
1063183234Ssimon				BIO_puts(bio_err,
1064183234Ssimon					"Error decrypting CMS using private key\n");
1065183234Ssimon				goto end;
1066183234Ssimon				}
1067183234Ssimon			}
1068183234Ssimon
1069238405Sjkim		if (pwri_pass)
1070238405Sjkim			{
1071238405Sjkim			if (!CMS_decrypt_set1_password(cms, pwri_pass, -1))
1072238405Sjkim				{
1073238405Sjkim				BIO_puts(bio_err,
1074238405Sjkim					"Error decrypting CMS using password\n");
1075238405Sjkim				goto end;
1076238405Sjkim				}
1077238405Sjkim			}
1078238405Sjkim
1079183234Ssimon		if (!CMS_decrypt(cms, NULL, NULL, indata, out, flags))
1080183234Ssimon			{
1081183234Ssimon			BIO_printf(bio_err, "Error decrypting CMS structure\n");
1082183234Ssimon			goto end;
1083183234Ssimon			}
1084183234Ssimon		}
1085183234Ssimon	else if (operation == SMIME_DATAOUT)
1086183234Ssimon		{
1087183234Ssimon		if (!CMS_data(cms, out, flags))
1088183234Ssimon			goto end;
1089183234Ssimon		}
1090183234Ssimon	else if (operation == SMIME_UNCOMPRESS)
1091183234Ssimon		{
1092183234Ssimon		if (!CMS_uncompress(cms, indata, out, flags))
1093183234Ssimon			goto end;
1094183234Ssimon		}
1095183234Ssimon	else if (operation == SMIME_DIGEST_VERIFY)
1096183234Ssimon		{
1097183234Ssimon		if (CMS_digest_verify(cms, indata, out, flags) > 0)
1098183234Ssimon			BIO_printf(bio_err, "Verification successful\n");
1099183234Ssimon		else
1100183234Ssimon			{
1101183234Ssimon			BIO_printf(bio_err, "Verification failure\n");
1102183234Ssimon			goto end;
1103183234Ssimon			}
1104183234Ssimon		}
1105183234Ssimon	else if (operation == SMIME_ENCRYPTED_DECRYPT)
1106183234Ssimon		{
1107183234Ssimon		if (!CMS_EncryptedData_decrypt(cms, secret_key, secret_keylen,
1108183234Ssimon						indata, out, flags))
1109183234Ssimon			goto end;
1110183234Ssimon		}
1111183234Ssimon	else if (operation == SMIME_VERIFY)
1112183234Ssimon		{
1113183234Ssimon		if (CMS_verify(cms, other, store, indata, out, flags) > 0)
1114183234Ssimon			BIO_printf(bio_err, "Verification successful\n");
1115183234Ssimon		else
1116183234Ssimon			{
1117183234Ssimon			BIO_printf(bio_err, "Verification failure\n");
1118238405Sjkim			if (verify_retcode)
1119238405Sjkim				ret = verify_err + 32;
1120183234Ssimon			goto end;
1121183234Ssimon			}
1122183234Ssimon		if (signerfile)
1123183234Ssimon			{
1124183234Ssimon			STACK_OF(X509) *signers;
1125183234Ssimon			signers = CMS_get0_signers(cms);
1126183234Ssimon			if (!save_certs(signerfile, signers))
1127183234Ssimon				{
1128183234Ssimon				BIO_printf(bio_err,
1129183234Ssimon						"Error writing signers to %s\n",
1130183234Ssimon								signerfile);
1131183234Ssimon				ret = 5;
1132183234Ssimon				goto end;
1133183234Ssimon				}
1134183234Ssimon			sk_X509_free(signers);
1135183234Ssimon			}
1136183234Ssimon		if (rr_print)
1137183234Ssimon			receipt_request_print(bio_err, cms);
1138183234Ssimon
1139183234Ssimon		}
1140183234Ssimon	else if (operation == SMIME_VERIFY_RECEIPT)
1141183234Ssimon		{
1142183234Ssimon		if (CMS_verify_receipt(rcms, cms, other, store, flags) > 0)
1143183234Ssimon			BIO_printf(bio_err, "Verification successful\n");
1144183234Ssimon		else
1145183234Ssimon			{
1146183234Ssimon			BIO_printf(bio_err, "Verification failure\n");
1147183234Ssimon			goto end;
1148183234Ssimon			}
1149183234Ssimon		}
1150183234Ssimon	else
1151183234Ssimon		{
1152238405Sjkim		if (noout)
1153183234Ssimon			{
1154238405Sjkim			if (print)
1155238405Sjkim				CMS_ContentInfo_print_ctx(out, cms, 0, NULL);
1156238405Sjkim			}
1157238405Sjkim		else if (outformat == FORMAT_SMIME)
1158238405Sjkim			{
1159183234Ssimon			if (to)
1160183234Ssimon				BIO_printf(out, "To: %s\n", to);
1161183234Ssimon			if (from)
1162183234Ssimon				BIO_printf(out, "From: %s\n", from);
1163183234Ssimon			if (subject)
1164183234Ssimon				BIO_printf(out, "Subject: %s\n", subject);
1165183234Ssimon			if (operation == SMIME_RESIGN)
1166183234Ssimon				ret = SMIME_write_CMS(out, cms, indata, flags);
1167183234Ssimon			else
1168183234Ssimon				ret = SMIME_write_CMS(out, cms, in, flags);
1169183234Ssimon			}
1170183234Ssimon		else if (outformat == FORMAT_PEM)
1171238405Sjkim			ret = PEM_write_bio_CMS_stream(out, cms, in, flags);
1172183234Ssimon		else if (outformat == FORMAT_ASN1)
1173238405Sjkim			ret = i2d_CMS_bio_stream(out,cms, in, flags);
1174183234Ssimon		else
1175183234Ssimon			{
1176183234Ssimon			BIO_printf(bio_err, "Bad output format for CMS file\n");
1177183234Ssimon			goto end;
1178183234Ssimon			}
1179183234Ssimon		if (ret <= 0)
1180183234Ssimon			{
1181183234Ssimon			ret = 6;
1182183234Ssimon			goto end;
1183183234Ssimon			}
1184183234Ssimon		}
1185183234Ssimon	ret = 0;
1186183234Ssimonend:
1187183234Ssimon	if (ret)
1188183234Ssimon		ERR_print_errors(bio_err);
1189183234Ssimon	if (need_rand)
1190183234Ssimon		app_RAND_write_file(NULL, bio_err);
1191183234Ssimon	sk_X509_pop_free(encerts, X509_free);
1192183234Ssimon	sk_X509_pop_free(other, X509_free);
1193183234Ssimon	if (vpm)
1194183234Ssimon		X509_VERIFY_PARAM_free(vpm);
1195183234Ssimon	if (sksigners)
1196238405Sjkim		sk_OPENSSL_STRING_free(sksigners);
1197183234Ssimon	if (skkeys)
1198238405Sjkim		sk_OPENSSL_STRING_free(skkeys);
1199183234Ssimon	if (secret_key)
1200183234Ssimon		OPENSSL_free(secret_key);
1201183234Ssimon	if (secret_keyid)
1202183234Ssimon		OPENSSL_free(secret_keyid);
1203238405Sjkim	if (pwri_tmp)
1204238405Sjkim		OPENSSL_free(pwri_tmp);
1205183234Ssimon	if (econtent_type)
1206183234Ssimon		ASN1_OBJECT_free(econtent_type);
1207183234Ssimon	if (rr)
1208183234Ssimon		CMS_ReceiptRequest_free(rr);
1209183234Ssimon	if (rr_to)
1210238405Sjkim		sk_OPENSSL_STRING_free(rr_to);
1211183234Ssimon	if (rr_from)
1212238405Sjkim		sk_OPENSSL_STRING_free(rr_from);
1213183234Ssimon	X509_STORE_free(store);
1214183234Ssimon	X509_free(cert);
1215183234Ssimon	X509_free(recip);
1216183234Ssimon	X509_free(signer);
1217183234Ssimon	EVP_PKEY_free(key);
1218183234Ssimon	CMS_ContentInfo_free(cms);
1219183234Ssimon	CMS_ContentInfo_free(rcms);
1220183234Ssimon	BIO_free(rctin);
1221183234Ssimon	BIO_free(in);
1222183234Ssimon	BIO_free(indata);
1223183234Ssimon	BIO_free_all(out);
1224183234Ssimon	if (passin) OPENSSL_free(passin);
1225183234Ssimon	return (ret);
1226183234Ssimon}
1227183234Ssimon
1228183234Ssimonstatic int save_certs(char *signerfile, STACK_OF(X509) *signers)
1229183234Ssimon	{
1230183234Ssimon	int i;
1231183234Ssimon	BIO *tmp;
1232183234Ssimon	if (!signerfile)
1233183234Ssimon		return 1;
1234183234Ssimon	tmp = BIO_new_file(signerfile, "w");
1235183234Ssimon	if (!tmp) return 0;
1236183234Ssimon	for(i = 0; i < sk_X509_num(signers); i++)
1237183234Ssimon		PEM_write_bio_X509(tmp, sk_X509_value(signers, i));
1238183234Ssimon	BIO_free(tmp);
1239183234Ssimon	return 1;
1240183234Ssimon	}
1241183234Ssimon
1242183234Ssimon
1243183234Ssimon/* Minimal callback just to output policy info (if any) */
1244183234Ssimon
1245183234Ssimonstatic int cms_cb(int ok, X509_STORE_CTX *ctx)
1246183234Ssimon	{
1247183234Ssimon	int error;
1248183234Ssimon
1249183234Ssimon	error = X509_STORE_CTX_get_error(ctx);
1250183234Ssimon
1251238405Sjkim	verify_err = error;
1252238405Sjkim
1253183234Ssimon	if ((error != X509_V_ERR_NO_EXPLICIT_POLICY)
1254183234Ssimon		&& ((error != X509_V_OK) || (ok != 2)))
1255183234Ssimon		return ok;
1256183234Ssimon
1257183234Ssimon	policies_print(NULL, ctx);
1258183234Ssimon
1259183234Ssimon	return ok;
1260183234Ssimon
1261183234Ssimon	}
1262183234Ssimon
1263183234Ssimonstatic void gnames_stack_print(BIO *out, STACK_OF(GENERAL_NAMES) *gns)
1264183234Ssimon	{
1265183234Ssimon	STACK_OF(GENERAL_NAME) *gens;
1266183234Ssimon	GENERAL_NAME *gen;
1267183234Ssimon	int i, j;
1268183234Ssimon	for (i = 0; i < sk_GENERAL_NAMES_num(gns); i++)
1269183234Ssimon		{
1270183234Ssimon		gens = sk_GENERAL_NAMES_value(gns, i);
1271183234Ssimon		for (j = 0; j < sk_GENERAL_NAME_num(gens); j++)
1272183234Ssimon			{
1273183234Ssimon			gen = sk_GENERAL_NAME_value(gens, j);
1274183234Ssimon			BIO_puts(out, "    ");
1275183234Ssimon			GENERAL_NAME_print(out, gen);
1276183234Ssimon			BIO_puts(out, "\n");
1277183234Ssimon			}
1278183234Ssimon		}
1279183234Ssimon	return;
1280183234Ssimon	}
1281183234Ssimon
1282183234Ssimonstatic void receipt_request_print(BIO *out, CMS_ContentInfo *cms)
1283183234Ssimon	{
1284183234Ssimon	STACK_OF(CMS_SignerInfo) *sis;
1285183234Ssimon	CMS_SignerInfo *si;
1286183234Ssimon	CMS_ReceiptRequest *rr;
1287183234Ssimon	int allorfirst;
1288183234Ssimon	STACK_OF(GENERAL_NAMES) *rto, *rlist;
1289183234Ssimon	ASN1_STRING *scid;
1290183234Ssimon	int i, rv;
1291183234Ssimon	sis = CMS_get0_SignerInfos(cms);
1292183234Ssimon	for (i = 0; i < sk_CMS_SignerInfo_num(sis); i++)
1293183234Ssimon		{
1294183234Ssimon		si = sk_CMS_SignerInfo_value(sis, i);
1295183234Ssimon		rv = CMS_get1_ReceiptRequest(si, &rr);
1296183234Ssimon		BIO_printf(bio_err, "Signer %d:\n", i + 1);
1297183234Ssimon		if (rv == 0)
1298183234Ssimon			BIO_puts(bio_err, "  No Receipt Request\n");
1299183234Ssimon		else if (rv < 0)
1300183234Ssimon			{
1301183234Ssimon			BIO_puts(bio_err, "  Receipt Request Parse Error\n");
1302183234Ssimon			ERR_print_errors(bio_err);
1303183234Ssimon			}
1304183234Ssimon		else
1305183234Ssimon			{
1306183234Ssimon			char *id;
1307183234Ssimon			int idlen;
1308183234Ssimon			CMS_ReceiptRequest_get0_values(rr, &scid, &allorfirst,
1309183234Ssimon							&rlist, &rto);
1310183234Ssimon			BIO_puts(out, "  Signed Content ID:\n");
1311183234Ssimon			idlen = ASN1_STRING_length(scid);
1312183234Ssimon			id = (char *)ASN1_STRING_data(scid);
1313183234Ssimon			BIO_dump_indent(out, id, idlen, 4);
1314183234Ssimon			BIO_puts(out, "  Receipts From");
1315183234Ssimon			if (rlist)
1316183234Ssimon				{
1317183234Ssimon				BIO_puts(out, " List:\n");
1318183234Ssimon				gnames_stack_print(out, rlist);
1319183234Ssimon				}
1320183234Ssimon			else if (allorfirst == 1)
1321183234Ssimon				BIO_puts(out, ": First Tier\n");
1322183234Ssimon			else if (allorfirst == 0)
1323183234Ssimon				BIO_puts(out, ": All\n");
1324183234Ssimon			else
1325183234Ssimon				BIO_printf(out, " Unknown (%d)\n", allorfirst);
1326183234Ssimon			BIO_puts(out, "  Receipts To:\n");
1327183234Ssimon			gnames_stack_print(out, rto);
1328183234Ssimon			}
1329183234Ssimon		if (rr)
1330183234Ssimon			CMS_ReceiptRequest_free(rr);
1331183234Ssimon		}
1332183234Ssimon	}
1333183234Ssimon
1334238405Sjkimstatic STACK_OF(GENERAL_NAMES) *make_names_stack(STACK_OF(OPENSSL_STRING) *ns)
1335183234Ssimon	{
1336183234Ssimon	int i;
1337183234Ssimon	STACK_OF(GENERAL_NAMES) *ret;
1338183234Ssimon	GENERAL_NAMES *gens = NULL;
1339183234Ssimon	GENERAL_NAME *gen = NULL;
1340183234Ssimon	ret = sk_GENERAL_NAMES_new_null();
1341183234Ssimon	if (!ret)
1342183234Ssimon		goto err;
1343238405Sjkim	for (i = 0; i < sk_OPENSSL_STRING_num(ns); i++)
1344183234Ssimon		{
1345238405Sjkim		char *str = sk_OPENSSL_STRING_value(ns, i);
1346238405Sjkim		gen = a2i_GENERAL_NAME(NULL, NULL, NULL, GEN_EMAIL, str, 0);
1347183234Ssimon		if (!gen)
1348183234Ssimon			goto err;
1349183234Ssimon		gens = GENERAL_NAMES_new();
1350183234Ssimon		if (!gens)
1351183234Ssimon			goto err;
1352183234Ssimon		if (!sk_GENERAL_NAME_push(gens, gen))
1353183234Ssimon			goto err;
1354183234Ssimon		gen = NULL;
1355183234Ssimon		if (!sk_GENERAL_NAMES_push(ret, gens))
1356183234Ssimon			goto err;
1357183234Ssimon		gens = NULL;
1358183234Ssimon		}
1359183234Ssimon
1360183234Ssimon	return ret;
1361183234Ssimon
1362183234Ssimon	err:
1363183234Ssimon	if (ret)
1364183234Ssimon		sk_GENERAL_NAMES_pop_free(ret, GENERAL_NAMES_free);
1365183234Ssimon	if (gens)
1366183234Ssimon		GENERAL_NAMES_free(gens);
1367183234Ssimon	if (gen)
1368183234Ssimon		GENERAL_NAME_free(gen);
1369183234Ssimon	return NULL;
1370183234Ssimon	}
1371183234Ssimon
1372183234Ssimon
1373238405Sjkimstatic CMS_ReceiptRequest *make_receipt_request(STACK_OF(OPENSSL_STRING) *rr_to,
1374238405Sjkim						int rr_allorfirst,
1375238405Sjkim						STACK_OF(OPENSSL_STRING) *rr_from)
1376183234Ssimon	{
1377183234Ssimon	STACK_OF(GENERAL_NAMES) *rct_to, *rct_from;
1378183234Ssimon	CMS_ReceiptRequest *rr;
1379183234Ssimon	rct_to = make_names_stack(rr_to);
1380183234Ssimon	if (!rct_to)
1381183234Ssimon		goto err;
1382183234Ssimon	if (rr_from)
1383183234Ssimon		{
1384183234Ssimon		rct_from = make_names_stack(rr_from);
1385183234Ssimon		if (!rct_from)
1386183234Ssimon			goto err;
1387183234Ssimon		}
1388183234Ssimon	else
1389183234Ssimon		rct_from = NULL;
1390183234Ssimon	rr = CMS_ReceiptRequest_create0(NULL, -1, rr_allorfirst, rct_from,
1391183234Ssimon						rct_to);
1392183234Ssimon	return rr;
1393183234Ssimon	err:
1394183234Ssimon	return NULL;
1395183234Ssimon	}
1396183234Ssimon
1397183234Ssimon#endif
1398