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, <mp); 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, <mp); 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