1183234Ssimon/* apps/cms.c */ 2296341Sdelphij/* 3296341Sdelphij * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL 4183234Ssimon * project. 5183234Ssimon */ 6183234Ssimon/* ==================================================================== 7183234Ssimon * Copyright (c) 2008 The OpenSSL Project. All rights reserved. 8183234Ssimon * 9183234Ssimon * Redistribution and use in source and binary forms, with or without 10183234Ssimon * modification, are permitted provided that the following conditions 11183234Ssimon * are met: 12183234Ssimon * 13183234Ssimon * 1. Redistributions of source code must retain the above copyright 14296341Sdelphij * notice, this list of conditions and the following disclaimer. 15183234Ssimon * 16183234Ssimon * 2. Redistributions in binary form must reproduce the above copyright 17183234Ssimon * notice, this list of conditions and the following disclaimer in 18183234Ssimon * the documentation and/or other materials provided with the 19183234Ssimon * distribution. 20183234Ssimon * 21183234Ssimon * 3. All advertising materials mentioning features or use of this 22183234Ssimon * software must display the following acknowledgment: 23183234Ssimon * "This product includes software developed by the OpenSSL Project 24183234Ssimon * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" 25183234Ssimon * 26183234Ssimon * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 27183234Ssimon * endorse or promote products derived from this software without 28183234Ssimon * prior written permission. For written permission, please contact 29183234Ssimon * licensing@OpenSSL.org. 30183234Ssimon * 31183234Ssimon * 5. Products derived from this software may not be called "OpenSSL" 32183234Ssimon * nor may "OpenSSL" appear in their names without prior written 33183234Ssimon * permission of the OpenSSL Project. 34183234Ssimon * 35183234Ssimon * 6. Redistributions of any form whatsoever must retain the following 36183234Ssimon * acknowledgment: 37183234Ssimon * "This product includes software developed by the OpenSSL Project 38183234Ssimon * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" 39183234Ssimon * 40183234Ssimon * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 41183234Ssimon * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 42183234Ssimon * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 43183234Ssimon * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 44183234Ssimon * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 45183234Ssimon * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 46183234Ssimon * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 47183234Ssimon * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 48183234Ssimon * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 49183234Ssimon * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 50183234Ssimon * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 51183234Ssimon * OF THE POSSIBILITY OF SUCH DAMAGE. 52183234Ssimon * ==================================================================== 53183234Ssimon */ 54183234Ssimon 55183234Ssimon/* CMS utility function */ 56183234Ssimon 57183234Ssimon#include <stdio.h> 58183234Ssimon#include <string.h> 59183234Ssimon#include "apps.h" 60183234Ssimon 61183234Ssimon#ifndef OPENSSL_NO_CMS 62183234Ssimon 63296341Sdelphij# include <openssl/crypto.h> 64296341Sdelphij# include <openssl/pem.h> 65296341Sdelphij# include <openssl/err.h> 66296341Sdelphij# include <openssl/x509_vfy.h> 67296341Sdelphij# include <openssl/x509v3.h> 68296341Sdelphij# include <openssl/cms.h> 69183234Ssimon 70296341Sdelphij# undef PROG 71296341Sdelphij# define PROG cms_main 72183234Ssimonstatic int save_certs(char *signerfile, STACK_OF(X509) *signers); 73183234Ssimonstatic int cms_cb(int ok, X509_STORE_CTX *ctx); 74183234Ssimonstatic void receipt_request_print(BIO *out, CMS_ContentInfo *cms); 75296341Sdelphijstatic CMS_ReceiptRequest *make_receipt_request(STACK_OF(OPENSSL_STRING) 76296341Sdelphij *rr_to, int rr_allorfirst, STACK_OF(OPENSSL_STRING) 77296341Sdelphij *rr_from); 78183234Ssimon 79296341Sdelphij# define SMIME_OP 0x10 80296341Sdelphij# define SMIME_IP 0x20 81296341Sdelphij# define SMIME_SIGNERS 0x40 82296341Sdelphij# define SMIME_ENCRYPT (1 | SMIME_OP) 83296341Sdelphij# define SMIME_DECRYPT (2 | SMIME_IP) 84296341Sdelphij# define SMIME_SIGN (3 | SMIME_OP | SMIME_SIGNERS) 85296341Sdelphij# define SMIME_VERIFY (4 | SMIME_IP) 86296341Sdelphij# define SMIME_CMSOUT (5 | SMIME_IP | SMIME_OP) 87296341Sdelphij# define SMIME_RESIGN (6 | SMIME_IP | SMIME_OP | SMIME_SIGNERS) 88296341Sdelphij# define SMIME_DATAOUT (7 | SMIME_IP) 89296341Sdelphij# define SMIME_DATA_CREATE (8 | SMIME_OP) 90296341Sdelphij# define SMIME_DIGEST_VERIFY (9 | SMIME_IP) 91296341Sdelphij# define SMIME_DIGEST_CREATE (10 | SMIME_OP) 92296341Sdelphij# define SMIME_UNCOMPRESS (11 | SMIME_IP) 93296341Sdelphij# define SMIME_COMPRESS (12 | SMIME_OP) 94296341Sdelphij# define SMIME_ENCRYPTED_DECRYPT (13 | SMIME_IP) 95296341Sdelphij# define SMIME_ENCRYPTED_ENCRYPT (14 | SMIME_OP) 96296341Sdelphij# define SMIME_SIGN_RECEIPT (15 | SMIME_IP | SMIME_OP) 97296341Sdelphij# define SMIME_VERIFY_RECEIPT (16 | SMIME_IP) 98183234Ssimon 99238405Sjkimint verify_err = 0; 100238405Sjkim 101183234Ssimonint MAIN(int, char **); 102183234Ssimon 103183234Ssimonint MAIN(int argc, char **argv) 104296341Sdelphij{ 105296341Sdelphij ENGINE *e = NULL; 106296341Sdelphij int operation = 0; 107296341Sdelphij int ret = 0; 108296341Sdelphij char **args; 109296341Sdelphij const char *inmode = "r", *outmode = "w"; 110296341Sdelphij char *infile = NULL, *outfile = NULL, *rctfile = NULL; 111296341Sdelphij char *signerfile = NULL, *recipfile = NULL; 112296341Sdelphij STACK_OF(OPENSSL_STRING) *sksigners = NULL, *skkeys = NULL; 113296341Sdelphij char *certfile = NULL, *keyfile = NULL, *contfile = NULL; 114296341Sdelphij char *certsoutfile = NULL; 115296341Sdelphij const EVP_CIPHER *cipher = NULL; 116296341Sdelphij CMS_ContentInfo *cms = NULL, *rcms = NULL; 117296341Sdelphij X509_STORE *store = NULL; 118296341Sdelphij X509 *cert = NULL, *recip = NULL, *signer = NULL; 119296341Sdelphij EVP_PKEY *key = NULL; 120296341Sdelphij STACK_OF(X509) *encerts = NULL, *other = NULL; 121296341Sdelphij BIO *in = NULL, *out = NULL, *indata = NULL, *rctin = NULL; 122296341Sdelphij int badarg = 0; 123296341Sdelphij int flags = CMS_DETACHED, noout = 0, print = 0; 124296341Sdelphij int verify_retcode = 0; 125296341Sdelphij int rr_print = 0, rr_allorfirst = -1; 126296341Sdelphij STACK_OF(OPENSSL_STRING) *rr_to = NULL, *rr_from = NULL; 127296341Sdelphij CMS_ReceiptRequest *rr = NULL; 128296341Sdelphij char *to = NULL, *from = NULL, *subject = NULL; 129296341Sdelphij char *CAfile = NULL, *CApath = NULL; 130296341Sdelphij char *passargin = NULL, *passin = NULL; 131296341Sdelphij char *inrand = NULL; 132296341Sdelphij int need_rand = 0; 133296341Sdelphij const EVP_MD *sign_md = NULL; 134296341Sdelphij int informat = FORMAT_SMIME, outformat = FORMAT_SMIME; 135296341Sdelphij int rctformat = FORMAT_SMIME, keyform = FORMAT_PEM; 136296341Sdelphij# ifndef OPENSSL_NO_ENGINE 137296341Sdelphij char *engine = NULL; 138296341Sdelphij# endif 139296341Sdelphij unsigned char *secret_key = NULL, *secret_keyid = NULL; 140296341Sdelphij unsigned char *pwri_pass = NULL, *pwri_tmp = NULL; 141296341Sdelphij size_t secret_keylen = 0, secret_keyidlen = 0; 142183234Ssimon 143296341Sdelphij ASN1_OBJECT *econtent_type = NULL; 144183234Ssimon 145296341Sdelphij X509_VERIFY_PARAM *vpm = NULL; 146183234Ssimon 147296341Sdelphij args = argv + 1; 148296341Sdelphij ret = 1; 149183234Ssimon 150296341Sdelphij apps_startup(); 151183234Ssimon 152296341Sdelphij if (bio_err == NULL) { 153296341Sdelphij if ((bio_err = BIO_new(BIO_s_file())) != NULL) 154296341Sdelphij BIO_set_fp(bio_err, stderr, BIO_NOCLOSE | BIO_FP_TEXT); 155296341Sdelphij } 156183234Ssimon 157296341Sdelphij if (!load_config(bio_err, NULL)) 158296341Sdelphij goto end; 159183234Ssimon 160296341Sdelphij while (!badarg && *args && *args[0] == '-') { 161296341Sdelphij if (!strcmp(*args, "-encrypt")) 162296341Sdelphij operation = SMIME_ENCRYPT; 163296341Sdelphij else if (!strcmp(*args, "-decrypt")) 164296341Sdelphij operation = SMIME_DECRYPT; 165296341Sdelphij else if (!strcmp(*args, "-sign")) 166296341Sdelphij operation = SMIME_SIGN; 167296341Sdelphij else if (!strcmp(*args, "-sign_receipt")) 168296341Sdelphij operation = SMIME_SIGN_RECEIPT; 169296341Sdelphij else if (!strcmp(*args, "-resign")) 170296341Sdelphij operation = SMIME_RESIGN; 171296341Sdelphij else if (!strcmp(*args, "-verify")) 172296341Sdelphij operation = SMIME_VERIFY; 173296341Sdelphij else if (!strcmp(*args, "-verify_retcode")) 174296341Sdelphij verify_retcode = 1; 175296341Sdelphij else if (!strcmp(*args, "-verify_receipt")) { 176296341Sdelphij operation = SMIME_VERIFY_RECEIPT; 177296341Sdelphij if (!args[1]) 178296341Sdelphij goto argerr; 179296341Sdelphij args++; 180296341Sdelphij rctfile = *args; 181296341Sdelphij } else if (!strcmp(*args, "-cmsout")) 182296341Sdelphij operation = SMIME_CMSOUT; 183296341Sdelphij else if (!strcmp(*args, "-data_out")) 184296341Sdelphij operation = SMIME_DATAOUT; 185296341Sdelphij else if (!strcmp(*args, "-data_create")) 186296341Sdelphij operation = SMIME_DATA_CREATE; 187296341Sdelphij else if (!strcmp(*args, "-digest_verify")) 188296341Sdelphij operation = SMIME_DIGEST_VERIFY; 189296341Sdelphij else if (!strcmp(*args, "-digest_create")) 190296341Sdelphij operation = SMIME_DIGEST_CREATE; 191296341Sdelphij else if (!strcmp(*args, "-compress")) 192296341Sdelphij operation = SMIME_COMPRESS; 193296341Sdelphij else if (!strcmp(*args, "-uncompress")) 194296341Sdelphij operation = SMIME_UNCOMPRESS; 195296341Sdelphij else if (!strcmp(*args, "-EncryptedData_decrypt")) 196296341Sdelphij operation = SMIME_ENCRYPTED_DECRYPT; 197296341Sdelphij else if (!strcmp(*args, "-EncryptedData_encrypt")) 198296341Sdelphij operation = SMIME_ENCRYPTED_ENCRYPT; 199296341Sdelphij# ifndef OPENSSL_NO_DES 200296341Sdelphij else if (!strcmp(*args, "-des3")) 201296341Sdelphij cipher = EVP_des_ede3_cbc(); 202296341Sdelphij else if (!strcmp(*args, "-des")) 203296341Sdelphij cipher = EVP_des_cbc(); 204296341Sdelphij# endif 205296341Sdelphij# ifndef OPENSSL_NO_SEED 206296341Sdelphij else if (!strcmp(*args, "-seed")) 207296341Sdelphij cipher = EVP_seed_cbc(); 208296341Sdelphij# endif 209296341Sdelphij# ifndef OPENSSL_NO_RC2 210296341Sdelphij else if (!strcmp(*args, "-rc2-40")) 211296341Sdelphij cipher = EVP_rc2_40_cbc(); 212296341Sdelphij else if (!strcmp(*args, "-rc2-128")) 213296341Sdelphij cipher = EVP_rc2_cbc(); 214296341Sdelphij else if (!strcmp(*args, "-rc2-64")) 215296341Sdelphij cipher = EVP_rc2_64_cbc(); 216296341Sdelphij# endif 217296341Sdelphij# ifndef OPENSSL_NO_AES 218296341Sdelphij else if (!strcmp(*args, "-aes128")) 219296341Sdelphij cipher = EVP_aes_128_cbc(); 220296341Sdelphij else if (!strcmp(*args, "-aes192")) 221296341Sdelphij cipher = EVP_aes_192_cbc(); 222296341Sdelphij else if (!strcmp(*args, "-aes256")) 223296341Sdelphij cipher = EVP_aes_256_cbc(); 224296341Sdelphij# endif 225296341Sdelphij# ifndef OPENSSL_NO_CAMELLIA 226296341Sdelphij else if (!strcmp(*args, "-camellia128")) 227296341Sdelphij cipher = EVP_camellia_128_cbc(); 228296341Sdelphij else if (!strcmp(*args, "-camellia192")) 229296341Sdelphij cipher = EVP_camellia_192_cbc(); 230296341Sdelphij else if (!strcmp(*args, "-camellia256")) 231296341Sdelphij cipher = EVP_camellia_256_cbc(); 232296341Sdelphij# endif 233296341Sdelphij else if (!strcmp(*args, "-debug_decrypt")) 234296341Sdelphij flags |= CMS_DEBUG_DECRYPT; 235296341Sdelphij else if (!strcmp(*args, "-text")) 236296341Sdelphij flags |= CMS_TEXT; 237296341Sdelphij else if (!strcmp(*args, "-nointern")) 238296341Sdelphij flags |= CMS_NOINTERN; 239296341Sdelphij else if (!strcmp(*args, "-noverify") 240296341Sdelphij || !strcmp(*args, "-no_signer_cert_verify")) 241296341Sdelphij flags |= CMS_NO_SIGNER_CERT_VERIFY; 242296341Sdelphij else if (!strcmp(*args, "-nocerts")) 243296341Sdelphij flags |= CMS_NOCERTS; 244296341Sdelphij else if (!strcmp(*args, "-noattr")) 245296341Sdelphij flags |= CMS_NOATTR; 246296341Sdelphij else if (!strcmp(*args, "-nodetach")) 247296341Sdelphij flags &= ~CMS_DETACHED; 248296341Sdelphij else if (!strcmp(*args, "-nosmimecap")) 249296341Sdelphij flags |= CMS_NOSMIMECAP; 250296341Sdelphij else if (!strcmp(*args, "-binary")) 251296341Sdelphij flags |= CMS_BINARY; 252296341Sdelphij else if (!strcmp(*args, "-keyid")) 253296341Sdelphij flags |= CMS_USE_KEYID; 254296341Sdelphij else if (!strcmp(*args, "-nosigs")) 255296341Sdelphij flags |= CMS_NOSIGS; 256296341Sdelphij else if (!strcmp(*args, "-no_content_verify")) 257296341Sdelphij flags |= CMS_NO_CONTENT_VERIFY; 258296341Sdelphij else if (!strcmp(*args, "-no_attr_verify")) 259296341Sdelphij flags |= CMS_NO_ATTR_VERIFY; 260296341Sdelphij else if (!strcmp(*args, "-stream")) 261296341Sdelphij flags |= CMS_STREAM; 262296341Sdelphij else if (!strcmp(*args, "-indef")) 263296341Sdelphij flags |= CMS_STREAM; 264296341Sdelphij else if (!strcmp(*args, "-noindef")) 265296341Sdelphij flags &= ~CMS_STREAM; 266296341Sdelphij else if (!strcmp(*args, "-nooldmime")) 267296341Sdelphij flags |= CMS_NOOLDMIMETYPE; 268296341Sdelphij else if (!strcmp(*args, "-crlfeol")) 269296341Sdelphij flags |= CMS_CRLFEOL; 270296341Sdelphij else if (!strcmp(*args, "-noout")) 271296341Sdelphij noout = 1; 272296341Sdelphij else if (!strcmp(*args, "-receipt_request_print")) 273296341Sdelphij rr_print = 1; 274296341Sdelphij else if (!strcmp(*args, "-receipt_request_all")) 275296341Sdelphij rr_allorfirst = 0; 276296341Sdelphij else if (!strcmp(*args, "-receipt_request_first")) 277296341Sdelphij rr_allorfirst = 1; 278296341Sdelphij else if (!strcmp(*args, "-receipt_request_from")) { 279296341Sdelphij if (!args[1]) 280296341Sdelphij goto argerr; 281296341Sdelphij args++; 282296341Sdelphij if (!rr_from) 283296341Sdelphij rr_from = sk_OPENSSL_STRING_new_null(); 284296341Sdelphij sk_OPENSSL_STRING_push(rr_from, *args); 285296341Sdelphij } else if (!strcmp(*args, "-receipt_request_to")) { 286296341Sdelphij if (!args[1]) 287296341Sdelphij goto argerr; 288296341Sdelphij args++; 289296341Sdelphij if (!rr_to) 290296341Sdelphij rr_to = sk_OPENSSL_STRING_new_null(); 291296341Sdelphij sk_OPENSSL_STRING_push(rr_to, *args); 292296341Sdelphij } else if (!strcmp(*args, "-print")) { 293296341Sdelphij noout = 1; 294296341Sdelphij print = 1; 295296341Sdelphij } else if (!strcmp(*args, "-secretkey")) { 296296341Sdelphij long ltmp; 297296341Sdelphij if (!args[1]) 298296341Sdelphij goto argerr; 299296341Sdelphij args++; 300296341Sdelphij secret_key = string_to_hex(*args, <mp); 301296341Sdelphij if (!secret_key) { 302296341Sdelphij BIO_printf(bio_err, "Invalid key %s\n", *args); 303296341Sdelphij goto argerr; 304296341Sdelphij } 305296341Sdelphij secret_keylen = (size_t)ltmp; 306296341Sdelphij } else if (!strcmp(*args, "-secretkeyid")) { 307296341Sdelphij long ltmp; 308296341Sdelphij if (!args[1]) 309296341Sdelphij goto argerr; 310296341Sdelphij args++; 311296341Sdelphij secret_keyid = string_to_hex(*args, <mp); 312296341Sdelphij if (!secret_keyid) { 313296341Sdelphij BIO_printf(bio_err, "Invalid id %s\n", *args); 314296341Sdelphij goto argerr; 315296341Sdelphij } 316296341Sdelphij secret_keyidlen = (size_t)ltmp; 317296341Sdelphij } else if (!strcmp(*args, "-pwri_password")) { 318296341Sdelphij if (!args[1]) 319296341Sdelphij goto argerr; 320296341Sdelphij args++; 321296341Sdelphij pwri_pass = (unsigned char *)*args; 322296341Sdelphij } else if (!strcmp(*args, "-econtent_type")) { 323296341Sdelphij if (!args[1]) 324296341Sdelphij goto argerr; 325296341Sdelphij args++; 326296341Sdelphij econtent_type = OBJ_txt2obj(*args, 0); 327296341Sdelphij if (!econtent_type) { 328296341Sdelphij BIO_printf(bio_err, "Invalid OID %s\n", *args); 329296341Sdelphij goto argerr; 330296341Sdelphij } 331296341Sdelphij } else if (!strcmp(*args, "-rand")) { 332296341Sdelphij if (!args[1]) 333296341Sdelphij goto argerr; 334296341Sdelphij args++; 335296341Sdelphij inrand = *args; 336296341Sdelphij need_rand = 1; 337296341Sdelphij } 338296341Sdelphij# ifndef OPENSSL_NO_ENGINE 339296341Sdelphij else if (!strcmp(*args, "-engine")) { 340296341Sdelphij if (!args[1]) 341296341Sdelphij goto argerr; 342296341Sdelphij engine = *++args; 343296341Sdelphij } 344296341Sdelphij# endif 345296341Sdelphij else if (!strcmp(*args, "-passin")) { 346296341Sdelphij if (!args[1]) 347296341Sdelphij goto argerr; 348296341Sdelphij passargin = *++args; 349296341Sdelphij } else if (!strcmp(*args, "-to")) { 350296341Sdelphij if (!args[1]) 351296341Sdelphij goto argerr; 352296341Sdelphij to = *++args; 353296341Sdelphij } else if (!strcmp(*args, "-from")) { 354296341Sdelphij if (!args[1]) 355296341Sdelphij goto argerr; 356296341Sdelphij from = *++args; 357296341Sdelphij } else if (!strcmp(*args, "-subject")) { 358296341Sdelphij if (!args[1]) 359296341Sdelphij goto argerr; 360296341Sdelphij subject = *++args; 361296341Sdelphij } else if (!strcmp(*args, "-signer")) { 362296341Sdelphij if (!args[1]) 363296341Sdelphij goto argerr; 364296341Sdelphij /* If previous -signer argument add signer to list */ 365183234Ssimon 366296341Sdelphij if (signerfile) { 367296341Sdelphij if (!sksigners) 368296341Sdelphij sksigners = sk_OPENSSL_STRING_new_null(); 369296341Sdelphij sk_OPENSSL_STRING_push(sksigners, signerfile); 370296341Sdelphij if (!keyfile) 371296341Sdelphij keyfile = signerfile; 372296341Sdelphij if (!skkeys) 373296341Sdelphij skkeys = sk_OPENSSL_STRING_new_null(); 374296341Sdelphij sk_OPENSSL_STRING_push(skkeys, keyfile); 375296341Sdelphij keyfile = NULL; 376296341Sdelphij } 377296341Sdelphij signerfile = *++args; 378296341Sdelphij } else if (!strcmp(*args, "-recip")) { 379296341Sdelphij if (!args[1]) 380296341Sdelphij goto argerr; 381296341Sdelphij recipfile = *++args; 382296341Sdelphij } else if (!strcmp(*args, "-certsout")) { 383296341Sdelphij if (!args[1]) 384296341Sdelphij goto argerr; 385296341Sdelphij certsoutfile = *++args; 386296341Sdelphij } else if (!strcmp(*args, "-md")) { 387296341Sdelphij if (!args[1]) 388296341Sdelphij goto argerr; 389296341Sdelphij sign_md = EVP_get_digestbyname(*++args); 390296341Sdelphij if (sign_md == NULL) { 391296341Sdelphij BIO_printf(bio_err, "Unknown digest %s\n", *args); 392296341Sdelphij goto argerr; 393296341Sdelphij } 394296341Sdelphij } else if (!strcmp(*args, "-inkey")) { 395296341Sdelphij if (!args[1]) 396296341Sdelphij goto argerr; 397296341Sdelphij /* If previous -inkey arument add signer to list */ 398296341Sdelphij if (keyfile) { 399296341Sdelphij if (!signerfile) { 400296341Sdelphij BIO_puts(bio_err, "Illegal -inkey without -signer\n"); 401296341Sdelphij goto argerr; 402296341Sdelphij } 403296341Sdelphij if (!sksigners) 404296341Sdelphij sksigners = sk_OPENSSL_STRING_new_null(); 405296341Sdelphij sk_OPENSSL_STRING_push(sksigners, signerfile); 406296341Sdelphij signerfile = NULL; 407296341Sdelphij if (!skkeys) 408296341Sdelphij skkeys = sk_OPENSSL_STRING_new_null(); 409296341Sdelphij sk_OPENSSL_STRING_push(skkeys, keyfile); 410296341Sdelphij } 411296341Sdelphij keyfile = *++args; 412296341Sdelphij } else if (!strcmp(*args, "-keyform")) { 413296341Sdelphij if (!args[1]) 414296341Sdelphij goto argerr; 415296341Sdelphij keyform = str2fmt(*++args); 416296341Sdelphij } else if (!strcmp(*args, "-rctform")) { 417296341Sdelphij if (!args[1]) 418296341Sdelphij goto argerr; 419296341Sdelphij rctformat = str2fmt(*++args); 420296341Sdelphij } else if (!strcmp(*args, "-certfile")) { 421296341Sdelphij if (!args[1]) 422296341Sdelphij goto argerr; 423296341Sdelphij certfile = *++args; 424296341Sdelphij } else if (!strcmp(*args, "-CAfile")) { 425296341Sdelphij if (!args[1]) 426296341Sdelphij goto argerr; 427296341Sdelphij CAfile = *++args; 428296341Sdelphij } else if (!strcmp(*args, "-CApath")) { 429296341Sdelphij if (!args[1]) 430296341Sdelphij goto argerr; 431296341Sdelphij CApath = *++args; 432296341Sdelphij } else if (!strcmp(*args, "-in")) { 433296341Sdelphij if (!args[1]) 434296341Sdelphij goto argerr; 435296341Sdelphij infile = *++args; 436296341Sdelphij } else if (!strcmp(*args, "-inform")) { 437296341Sdelphij if (!args[1]) 438296341Sdelphij goto argerr; 439296341Sdelphij informat = str2fmt(*++args); 440296341Sdelphij } else if (!strcmp(*args, "-outform")) { 441296341Sdelphij if (!args[1]) 442296341Sdelphij goto argerr; 443296341Sdelphij outformat = str2fmt(*++args); 444296341Sdelphij } else if (!strcmp(*args, "-out")) { 445296341Sdelphij if (!args[1]) 446296341Sdelphij goto argerr; 447296341Sdelphij outfile = *++args; 448296341Sdelphij } else if (!strcmp(*args, "-content")) { 449296341Sdelphij if (!args[1]) 450296341Sdelphij goto argerr; 451296341Sdelphij contfile = *++args; 452296341Sdelphij } else if (args_verify(&args, NULL, &badarg, bio_err, &vpm)) 453296341Sdelphij continue; 454296341Sdelphij else if ((cipher = EVP_get_cipherbyname(*args + 1)) == NULL) 455296341Sdelphij badarg = 1; 456296341Sdelphij args++; 457296341Sdelphij } 458183234Ssimon 459296341Sdelphij if (((rr_allorfirst != -1) || rr_from) && !rr_to) { 460296341Sdelphij BIO_puts(bio_err, "No Signed Receipts Recipients\n"); 461296341Sdelphij goto argerr; 462296341Sdelphij } 463183234Ssimon 464296341Sdelphij if (!(operation & SMIME_SIGNERS) && (rr_to || rr_from)) { 465296341Sdelphij BIO_puts(bio_err, "Signed receipts only allowed with -sign\n"); 466296341Sdelphij goto argerr; 467296341Sdelphij } 468296341Sdelphij if (!(operation & SMIME_SIGNERS) && (skkeys || sksigners)) { 469296341Sdelphij BIO_puts(bio_err, "Multiple signers or keys not allowed\n"); 470296341Sdelphij goto argerr; 471296341Sdelphij } 472183234Ssimon 473296341Sdelphij if (operation & SMIME_SIGNERS) { 474296341Sdelphij if (keyfile && !signerfile) { 475296341Sdelphij BIO_puts(bio_err, "Illegal -inkey without -signer\n"); 476296341Sdelphij goto argerr; 477296341Sdelphij } 478296341Sdelphij /* Check to see if any final signer needs to be appended */ 479296341Sdelphij if (signerfile) { 480296341Sdelphij if (!sksigners) 481296341Sdelphij sksigners = sk_OPENSSL_STRING_new_null(); 482296341Sdelphij sk_OPENSSL_STRING_push(sksigners, signerfile); 483296341Sdelphij if (!skkeys) 484296341Sdelphij skkeys = sk_OPENSSL_STRING_new_null(); 485296341Sdelphij if (!keyfile) 486296341Sdelphij keyfile = signerfile; 487296341Sdelphij sk_OPENSSL_STRING_push(skkeys, keyfile); 488296341Sdelphij } 489296341Sdelphij if (!sksigners) { 490296341Sdelphij BIO_printf(bio_err, "No signer certificate specified\n"); 491296341Sdelphij badarg = 1; 492296341Sdelphij } 493296341Sdelphij signerfile = NULL; 494296341Sdelphij keyfile = NULL; 495296341Sdelphij need_rand = 1; 496296341Sdelphij } 497183234Ssimon 498296341Sdelphij else if (operation == SMIME_DECRYPT) { 499296341Sdelphij if (!recipfile && !keyfile && !secret_key && !pwri_pass) { 500296341Sdelphij BIO_printf(bio_err, 501296341Sdelphij "No recipient certificate or key specified\n"); 502296341Sdelphij badarg = 1; 503296341Sdelphij } 504296341Sdelphij } else if (operation == SMIME_ENCRYPT) { 505296341Sdelphij if (!*args && !secret_key && !pwri_pass) { 506296341Sdelphij BIO_printf(bio_err, "No recipient(s) certificate(s) specified\n"); 507296341Sdelphij badarg = 1; 508296341Sdelphij } 509296341Sdelphij need_rand = 1; 510296341Sdelphij } else if (!operation) 511296341Sdelphij badarg = 1; 512183234Ssimon 513296341Sdelphij if (badarg) { 514296341Sdelphij argerr: 515296341Sdelphij BIO_printf(bio_err, "Usage cms [options] cert.pem ...\n"); 516296341Sdelphij BIO_printf(bio_err, "where options are\n"); 517296341Sdelphij BIO_printf(bio_err, "-encrypt encrypt message\n"); 518296341Sdelphij BIO_printf(bio_err, "-decrypt decrypt encrypted message\n"); 519296341Sdelphij BIO_printf(bio_err, "-sign sign message\n"); 520296341Sdelphij BIO_printf(bio_err, "-verify verify signed message\n"); 521296341Sdelphij BIO_printf(bio_err, "-cmsout output CMS structure\n"); 522296341Sdelphij# ifndef OPENSSL_NO_DES 523296341Sdelphij BIO_printf(bio_err, "-des3 encrypt with triple DES\n"); 524296341Sdelphij BIO_printf(bio_err, "-des encrypt with DES\n"); 525296341Sdelphij# endif 526296341Sdelphij# ifndef OPENSSL_NO_SEED 527296341Sdelphij BIO_printf(bio_err, "-seed encrypt with SEED\n"); 528296341Sdelphij# endif 529296341Sdelphij# ifndef OPENSSL_NO_RC2 530296341Sdelphij BIO_printf(bio_err, "-rc2-40 encrypt with RC2-40 (default)\n"); 531296341Sdelphij BIO_printf(bio_err, "-rc2-64 encrypt with RC2-64\n"); 532296341Sdelphij BIO_printf(bio_err, "-rc2-128 encrypt with RC2-128\n"); 533296341Sdelphij# endif 534296341Sdelphij# ifndef OPENSSL_NO_AES 535296341Sdelphij BIO_printf(bio_err, "-aes128, -aes192, -aes256\n"); 536296341Sdelphij BIO_printf(bio_err, 537296341Sdelphij " encrypt PEM output with cbc aes\n"); 538296341Sdelphij# endif 539296341Sdelphij# ifndef OPENSSL_NO_CAMELLIA 540296341Sdelphij BIO_printf(bio_err, "-camellia128, -camellia192, -camellia256\n"); 541296341Sdelphij BIO_printf(bio_err, 542296341Sdelphij " encrypt PEM output with cbc camellia\n"); 543296341Sdelphij# endif 544296341Sdelphij BIO_printf(bio_err, 545296341Sdelphij "-nointern don't search certificates in message for signer\n"); 546296341Sdelphij BIO_printf(bio_err, 547296341Sdelphij "-nosigs don't verify message signature\n"); 548296341Sdelphij BIO_printf(bio_err, 549296341Sdelphij "-noverify don't verify signers certificate\n"); 550296341Sdelphij BIO_printf(bio_err, 551296341Sdelphij "-nocerts don't include signers certificate when signing\n"); 552296341Sdelphij BIO_printf(bio_err, "-nodetach use opaque signing\n"); 553296341Sdelphij BIO_printf(bio_err, 554296341Sdelphij "-noattr don't include any signed attributes\n"); 555296341Sdelphij BIO_printf(bio_err, 556296341Sdelphij "-binary don't translate message to text\n"); 557296341Sdelphij BIO_printf(bio_err, "-certfile file other certificates file\n"); 558296341Sdelphij BIO_printf(bio_err, "-certsout file certificate output file\n"); 559296341Sdelphij BIO_printf(bio_err, "-signer file signer certificate file\n"); 560296341Sdelphij BIO_printf(bio_err, 561296341Sdelphij "-recip file recipient certificate file for decryption\n"); 562296341Sdelphij BIO_printf(bio_err, "-keyid use subject key identifier\n"); 563296341Sdelphij BIO_printf(bio_err, "-in file input file\n"); 564296341Sdelphij BIO_printf(bio_err, 565296341Sdelphij "-inform arg input format SMIME (default), PEM or DER\n"); 566296341Sdelphij BIO_printf(bio_err, 567296341Sdelphij "-inkey file input private key (if not signer or recipient)\n"); 568296341Sdelphij BIO_printf(bio_err, 569296341Sdelphij "-keyform arg input private key format (PEM or ENGINE)\n"); 570296341Sdelphij BIO_printf(bio_err, "-out file output file\n"); 571296341Sdelphij BIO_printf(bio_err, 572296341Sdelphij "-outform arg output format SMIME (default), PEM or DER\n"); 573296341Sdelphij BIO_printf(bio_err, 574296341Sdelphij "-content file supply or override content for detached signature\n"); 575296341Sdelphij BIO_printf(bio_err, "-to addr to address\n"); 576296341Sdelphij BIO_printf(bio_err, "-from ad from address\n"); 577296341Sdelphij BIO_printf(bio_err, "-subject s subject\n"); 578296341Sdelphij BIO_printf(bio_err, 579296341Sdelphij "-text include or delete text MIME headers\n"); 580296341Sdelphij BIO_printf(bio_err, 581296341Sdelphij "-CApath dir trusted certificates directory\n"); 582296341Sdelphij BIO_printf(bio_err, "-CAfile file trusted certificates file\n"); 583296341Sdelphij BIO_printf(bio_err, 584296341Sdelphij "-no_alt_chains only ever use the first certificate chain found\n"); 585296341Sdelphij BIO_printf(bio_err, 586296341Sdelphij "-crl_check check revocation status of signer's certificate using CRLs\n"); 587296341Sdelphij BIO_printf(bio_err, 588296341Sdelphij "-crl_check_all check revocation status of signer's certificate chain using CRLs\n"); 589296341Sdelphij# ifndef OPENSSL_NO_ENGINE 590296341Sdelphij BIO_printf(bio_err, 591296341Sdelphij "-engine e use engine e, possibly a hardware device.\n"); 592296341Sdelphij# endif 593296341Sdelphij BIO_printf(bio_err, "-passin arg input file pass phrase source\n"); 594296341Sdelphij BIO_printf(bio_err, "-rand file%cfile%c...\n", LIST_SEPARATOR_CHAR, 595296341Sdelphij LIST_SEPARATOR_CHAR); 596296341Sdelphij BIO_printf(bio_err, 597296341Sdelphij " load the file (or the files in the directory) into\n"); 598296341Sdelphij BIO_printf(bio_err, " the random number generator\n"); 599296341Sdelphij BIO_printf(bio_err, 600296341Sdelphij "cert.pem recipient certificate(s) for encryption\n"); 601296341Sdelphij goto end; 602296341Sdelphij } 603296341Sdelphij# ifndef OPENSSL_NO_ENGINE 604296341Sdelphij e = setup_engine(bio_err, engine, 0); 605296341Sdelphij# endif 606183234Ssimon 607296341Sdelphij if (!app_passwd(bio_err, passargin, NULL, &passin, NULL)) { 608296341Sdelphij BIO_printf(bio_err, "Error getting password\n"); 609296341Sdelphij goto end; 610296341Sdelphij } 611183234Ssimon 612296341Sdelphij if (need_rand) { 613296341Sdelphij app_RAND_load_file(NULL, bio_err, (inrand != NULL)); 614296341Sdelphij if (inrand != NULL) 615296341Sdelphij BIO_printf(bio_err, "%ld semi-random bytes loaded\n", 616296341Sdelphij app_RAND_load_files(inrand)); 617296341Sdelphij } 618183234Ssimon 619296341Sdelphij ret = 2; 620183234Ssimon 621296341Sdelphij if (!(operation & SMIME_SIGNERS)) 622296341Sdelphij flags &= ~CMS_DETACHED; 623183234Ssimon 624296341Sdelphij if (operation & SMIME_OP) { 625296341Sdelphij if (outformat == FORMAT_ASN1) 626296341Sdelphij outmode = "wb"; 627296341Sdelphij } else { 628296341Sdelphij if (flags & CMS_BINARY) 629296341Sdelphij outmode = "wb"; 630296341Sdelphij } 631183234Ssimon 632296341Sdelphij if (operation & SMIME_IP) { 633296341Sdelphij if (informat == FORMAT_ASN1) 634296341Sdelphij inmode = "rb"; 635296341Sdelphij } else { 636296341Sdelphij if (flags & CMS_BINARY) 637296341Sdelphij inmode = "rb"; 638296341Sdelphij } 639183234Ssimon 640296341Sdelphij if (operation == SMIME_ENCRYPT) { 641296341Sdelphij if (!cipher) { 642296341Sdelphij# ifndef OPENSSL_NO_DES 643296341Sdelphij cipher = EVP_des_ede3_cbc(); 644296341Sdelphij# else 645296341Sdelphij BIO_printf(bio_err, "No cipher selected\n"); 646296341Sdelphij goto end; 647296341Sdelphij# endif 648296341Sdelphij } 649183234Ssimon 650296341Sdelphij if (secret_key && !secret_keyid) { 651296341Sdelphij BIO_printf(bio_err, "No secret key id\n"); 652296341Sdelphij goto end; 653296341Sdelphij } 654183234Ssimon 655296341Sdelphij if (*args) 656296341Sdelphij encerts = sk_X509_new_null(); 657296341Sdelphij while (*args) { 658296341Sdelphij if (!(cert = load_cert(bio_err, *args, FORMAT_PEM, 659296341Sdelphij NULL, e, "recipient certificate file"))) 660296341Sdelphij goto end; 661296341Sdelphij sk_X509_push(encerts, cert); 662296341Sdelphij cert = NULL; 663296341Sdelphij args++; 664296341Sdelphij } 665296341Sdelphij } 666183234Ssimon 667296341Sdelphij if (certfile) { 668296341Sdelphij if (!(other = load_certs(bio_err, certfile, FORMAT_PEM, NULL, 669296341Sdelphij e, "certificate file"))) { 670296341Sdelphij ERR_print_errors(bio_err); 671296341Sdelphij goto end; 672296341Sdelphij } 673296341Sdelphij } 674183234Ssimon 675296341Sdelphij if (recipfile && (operation == SMIME_DECRYPT)) { 676296341Sdelphij if (!(recip = load_cert(bio_err, recipfile, FORMAT_PEM, NULL, 677296341Sdelphij e, "recipient certificate file"))) { 678296341Sdelphij ERR_print_errors(bio_err); 679296341Sdelphij goto end; 680296341Sdelphij } 681296341Sdelphij } 682183234Ssimon 683296341Sdelphij if (operation == SMIME_SIGN_RECEIPT) { 684296341Sdelphij if (!(signer = load_cert(bio_err, signerfile, FORMAT_PEM, NULL, 685296341Sdelphij e, "receipt signer certificate file"))) { 686296341Sdelphij ERR_print_errors(bio_err); 687296341Sdelphij goto end; 688296341Sdelphij } 689296341Sdelphij } 690183234Ssimon 691296341Sdelphij if (operation == SMIME_DECRYPT) { 692296341Sdelphij if (!keyfile) 693296341Sdelphij keyfile = recipfile; 694296341Sdelphij } else if ((operation == SMIME_SIGN) || (operation == SMIME_SIGN_RECEIPT)) { 695296341Sdelphij if (!keyfile) 696296341Sdelphij keyfile = signerfile; 697296341Sdelphij } else 698296341Sdelphij keyfile = NULL; 699183234Ssimon 700296341Sdelphij if (keyfile) { 701296341Sdelphij key = load_key(bio_err, keyfile, keyform, 0, passin, e, 702296341Sdelphij "signing key file"); 703296341Sdelphij if (!key) 704296341Sdelphij goto end; 705296341Sdelphij } 706183234Ssimon 707296341Sdelphij if (infile) { 708296341Sdelphij if (!(in = BIO_new_file(infile, inmode))) { 709296341Sdelphij BIO_printf(bio_err, "Can't open input file %s\n", infile); 710296341Sdelphij goto end; 711296341Sdelphij } 712296341Sdelphij } else 713296341Sdelphij in = BIO_new_fp(stdin, BIO_NOCLOSE); 714183234Ssimon 715296341Sdelphij if (operation & SMIME_IP) { 716296341Sdelphij if (informat == FORMAT_SMIME) 717296341Sdelphij cms = SMIME_read_CMS(in, &indata); 718296341Sdelphij else if (informat == FORMAT_PEM) 719296341Sdelphij cms = PEM_read_bio_CMS(in, NULL, NULL, NULL); 720296341Sdelphij else if (informat == FORMAT_ASN1) 721296341Sdelphij cms = d2i_CMS_bio(in, NULL); 722296341Sdelphij else { 723296341Sdelphij BIO_printf(bio_err, "Bad input format for CMS file\n"); 724296341Sdelphij goto end; 725296341Sdelphij } 726183234Ssimon 727296341Sdelphij if (!cms) { 728296341Sdelphij BIO_printf(bio_err, "Error reading S/MIME message\n"); 729296341Sdelphij goto end; 730296341Sdelphij } 731296341Sdelphij if (contfile) { 732296341Sdelphij BIO_free(indata); 733296341Sdelphij if (!(indata = BIO_new_file(contfile, "rb"))) { 734296341Sdelphij BIO_printf(bio_err, "Can't read content file %s\n", contfile); 735296341Sdelphij goto end; 736296341Sdelphij } 737296341Sdelphij } 738296341Sdelphij if (certsoutfile) { 739296341Sdelphij STACK_OF(X509) *allcerts; 740296341Sdelphij allcerts = CMS_get1_certs(cms); 741296341Sdelphij if (!save_certs(certsoutfile, allcerts)) { 742296341Sdelphij BIO_printf(bio_err, 743296341Sdelphij "Error writing certs to %s\n", certsoutfile); 744296341Sdelphij ret = 5; 745296341Sdelphij goto end; 746296341Sdelphij } 747296341Sdelphij sk_X509_pop_free(allcerts, X509_free); 748296341Sdelphij } 749296341Sdelphij } 750183234Ssimon 751296341Sdelphij if (rctfile) { 752296341Sdelphij char *rctmode = (rctformat == FORMAT_ASN1) ? "rb" : "r"; 753296341Sdelphij if (!(rctin = BIO_new_file(rctfile, rctmode))) { 754296341Sdelphij BIO_printf(bio_err, "Can't open receipt file %s\n", rctfile); 755296341Sdelphij goto end; 756296341Sdelphij } 757183234Ssimon 758296341Sdelphij if (rctformat == FORMAT_SMIME) 759296341Sdelphij rcms = SMIME_read_CMS(rctin, NULL); 760296341Sdelphij else if (rctformat == FORMAT_PEM) 761296341Sdelphij rcms = PEM_read_bio_CMS(rctin, NULL, NULL, NULL); 762296341Sdelphij else if (rctformat == FORMAT_ASN1) 763296341Sdelphij rcms = d2i_CMS_bio(rctin, NULL); 764296341Sdelphij else { 765296341Sdelphij BIO_printf(bio_err, "Bad input format for receipt\n"); 766296341Sdelphij goto end; 767296341Sdelphij } 768183234Ssimon 769296341Sdelphij if (!rcms) { 770296341Sdelphij BIO_printf(bio_err, "Error reading receipt\n"); 771296341Sdelphij goto end; 772296341Sdelphij } 773296341Sdelphij } 774183234Ssimon 775296341Sdelphij if (outfile) { 776296341Sdelphij if (!(out = BIO_new_file(outfile, outmode))) { 777296341Sdelphij BIO_printf(bio_err, "Can't open output file %s\n", outfile); 778296341Sdelphij goto end; 779296341Sdelphij } 780296341Sdelphij } else { 781296341Sdelphij out = BIO_new_fp(stdout, BIO_NOCLOSE); 782296341Sdelphij# ifdef OPENSSL_SYS_VMS 783296341Sdelphij { 784296341Sdelphij BIO *tmpbio = BIO_new(BIO_f_linebuffer()); 785296341Sdelphij out = BIO_push(tmpbio, out); 786296341Sdelphij } 787296341Sdelphij# endif 788296341Sdelphij } 789183234Ssimon 790296341Sdelphij if ((operation == SMIME_VERIFY) || (operation == SMIME_VERIFY_RECEIPT)) { 791296341Sdelphij if (!(store = setup_verify(bio_err, CAfile, CApath))) 792296341Sdelphij goto end; 793296341Sdelphij X509_STORE_set_verify_cb(store, cms_cb); 794296341Sdelphij if (vpm) 795296341Sdelphij X509_STORE_set1_param(store, vpm); 796296341Sdelphij } 797183234Ssimon 798296341Sdelphij ret = 3; 799183234Ssimon 800296341Sdelphij if (operation == SMIME_DATA_CREATE) { 801296341Sdelphij cms = CMS_data_create(in, flags); 802296341Sdelphij } else if (operation == SMIME_DIGEST_CREATE) { 803296341Sdelphij cms = CMS_digest_create(in, sign_md, flags); 804296341Sdelphij } else if (operation == SMIME_COMPRESS) { 805296341Sdelphij cms = CMS_compress(in, -1, flags); 806296341Sdelphij } else if (operation == SMIME_ENCRYPT) { 807296341Sdelphij flags |= CMS_PARTIAL; 808296341Sdelphij cms = CMS_encrypt(encerts, in, cipher, flags); 809296341Sdelphij if (!cms) 810296341Sdelphij goto end; 811296341Sdelphij if (secret_key) { 812296341Sdelphij if (!CMS_add0_recipient_key(cms, NID_undef, 813296341Sdelphij secret_key, secret_keylen, 814296341Sdelphij secret_keyid, secret_keyidlen, 815296341Sdelphij NULL, NULL, NULL)) 816296341Sdelphij goto end; 817296341Sdelphij /* NULL these because call absorbs them */ 818296341Sdelphij secret_key = NULL; 819296341Sdelphij secret_keyid = NULL; 820296341Sdelphij } 821296341Sdelphij if (pwri_pass) { 822296341Sdelphij pwri_tmp = (unsigned char *)BUF_strdup((char *)pwri_pass); 823296341Sdelphij if (!pwri_tmp) 824296341Sdelphij goto end; 825296341Sdelphij if (!CMS_add0_recipient_password(cms, 826296341Sdelphij -1, NID_undef, NID_undef, 827296341Sdelphij pwri_tmp, -1, NULL)) 828296341Sdelphij goto end; 829296341Sdelphij pwri_tmp = NULL; 830296341Sdelphij } 831296341Sdelphij if (!(flags & CMS_STREAM)) { 832296341Sdelphij if (!CMS_final(cms, in, NULL, flags)) 833296341Sdelphij goto end; 834296341Sdelphij } 835296341Sdelphij } else if (operation == SMIME_ENCRYPTED_ENCRYPT) { 836296341Sdelphij cms = CMS_EncryptedData_encrypt(in, cipher, 837296341Sdelphij secret_key, secret_keylen, flags); 838183234Ssimon 839296341Sdelphij } else if (operation == SMIME_SIGN_RECEIPT) { 840296341Sdelphij CMS_ContentInfo *srcms = NULL; 841296341Sdelphij STACK_OF(CMS_SignerInfo) *sis; 842296341Sdelphij CMS_SignerInfo *si; 843296341Sdelphij sis = CMS_get0_SignerInfos(cms); 844296341Sdelphij if (!sis) 845296341Sdelphij goto end; 846296341Sdelphij si = sk_CMS_SignerInfo_value(sis, 0); 847296341Sdelphij srcms = CMS_sign_receipt(si, signer, key, other, flags); 848296341Sdelphij if (!srcms) 849296341Sdelphij goto end; 850296341Sdelphij CMS_ContentInfo_free(cms); 851296341Sdelphij cms = srcms; 852296341Sdelphij } else if (operation & SMIME_SIGNERS) { 853296341Sdelphij int i; 854296341Sdelphij /* 855296341Sdelphij * If detached data content we enable streaming if S/MIME output 856296341Sdelphij * format. 857296341Sdelphij */ 858296341Sdelphij if (operation == SMIME_SIGN) { 859183234Ssimon 860296341Sdelphij if (flags & CMS_DETACHED) { 861296341Sdelphij if (outformat == FORMAT_SMIME) 862296341Sdelphij flags |= CMS_STREAM; 863296341Sdelphij } 864296341Sdelphij flags |= CMS_PARTIAL; 865296341Sdelphij cms = CMS_sign(NULL, NULL, other, in, flags); 866296341Sdelphij if (!cms) 867296341Sdelphij goto end; 868296341Sdelphij if (econtent_type) 869296341Sdelphij CMS_set1_eContentType(cms, econtent_type); 870183234Ssimon 871296341Sdelphij if (rr_to) { 872296341Sdelphij rr = make_receipt_request(rr_to, rr_allorfirst, rr_from); 873296341Sdelphij if (!rr) { 874296341Sdelphij BIO_puts(bio_err, 875296341Sdelphij "Signed Receipt Request Creation Error\n"); 876296341Sdelphij goto end; 877296341Sdelphij } 878296341Sdelphij } 879296341Sdelphij } else 880296341Sdelphij flags |= CMS_REUSE_DIGEST; 881296341Sdelphij for (i = 0; i < sk_OPENSSL_STRING_num(sksigners); i++) { 882296341Sdelphij CMS_SignerInfo *si; 883296341Sdelphij signerfile = sk_OPENSSL_STRING_value(sksigners, i); 884296341Sdelphij keyfile = sk_OPENSSL_STRING_value(skkeys, i); 885296341Sdelphij signer = load_cert(bio_err, signerfile, FORMAT_PEM, NULL, 886296341Sdelphij e, "signer certificate"); 887296341Sdelphij if (!signer) 888296341Sdelphij goto end; 889296341Sdelphij key = load_key(bio_err, keyfile, keyform, 0, passin, e, 890296341Sdelphij "signing key file"); 891296341Sdelphij if (!key) 892296341Sdelphij goto end; 893296341Sdelphij si = CMS_add1_signer(cms, signer, key, sign_md, flags); 894296341Sdelphij if (!si) 895296341Sdelphij goto end; 896296341Sdelphij if (rr && !CMS_add1_ReceiptRequest(si, rr)) 897296341Sdelphij goto end; 898296341Sdelphij X509_free(signer); 899296341Sdelphij signer = NULL; 900296341Sdelphij EVP_PKEY_free(key); 901296341Sdelphij key = NULL; 902296341Sdelphij } 903296341Sdelphij /* If not streaming or resigning finalize structure */ 904296341Sdelphij if ((operation == SMIME_SIGN) && !(flags & CMS_STREAM)) { 905296341Sdelphij if (!CMS_final(cms, in, NULL, flags)) 906296341Sdelphij goto end; 907296341Sdelphij } 908296341Sdelphij } 909183234Ssimon 910296341Sdelphij if (!cms) { 911296341Sdelphij BIO_printf(bio_err, "Error creating CMS structure\n"); 912296341Sdelphij goto end; 913296341Sdelphij } 914183234Ssimon 915296341Sdelphij ret = 4; 916296341Sdelphij if (operation == SMIME_DECRYPT) { 917296341Sdelphij if (flags & CMS_DEBUG_DECRYPT) 918296341Sdelphij CMS_decrypt(cms, NULL, NULL, NULL, NULL, flags); 919183234Ssimon 920296341Sdelphij if (secret_key) { 921296341Sdelphij if (!CMS_decrypt_set1_key(cms, 922296341Sdelphij secret_key, secret_keylen, 923296341Sdelphij secret_keyid, secret_keyidlen)) { 924296341Sdelphij BIO_puts(bio_err, "Error decrypting CMS using secret key\n"); 925296341Sdelphij goto end; 926296341Sdelphij } 927296341Sdelphij } 928183234Ssimon 929296341Sdelphij if (key) { 930296341Sdelphij if (!CMS_decrypt_set1_pkey(cms, key, recip)) { 931296341Sdelphij BIO_puts(bio_err, "Error decrypting CMS using private key\n"); 932296341Sdelphij goto end; 933296341Sdelphij } 934296341Sdelphij } 935183234Ssimon 936296341Sdelphij if (pwri_pass) { 937296341Sdelphij if (!CMS_decrypt_set1_password(cms, pwri_pass, -1)) { 938296341Sdelphij BIO_puts(bio_err, "Error decrypting CMS using password\n"); 939296341Sdelphij goto end; 940296341Sdelphij } 941296341Sdelphij } 942238405Sjkim 943296341Sdelphij if (!CMS_decrypt(cms, NULL, NULL, indata, out, flags)) { 944296341Sdelphij BIO_printf(bio_err, "Error decrypting CMS structure\n"); 945296341Sdelphij goto end; 946296341Sdelphij } 947296341Sdelphij } else if (operation == SMIME_DATAOUT) { 948296341Sdelphij if (!CMS_data(cms, out, flags)) 949296341Sdelphij goto end; 950296341Sdelphij } else if (operation == SMIME_UNCOMPRESS) { 951296341Sdelphij if (!CMS_uncompress(cms, indata, out, flags)) 952296341Sdelphij goto end; 953296341Sdelphij } else if (operation == SMIME_DIGEST_VERIFY) { 954296341Sdelphij if (CMS_digest_verify(cms, indata, out, flags) > 0) 955296341Sdelphij BIO_printf(bio_err, "Verification successful\n"); 956296341Sdelphij else { 957296341Sdelphij BIO_printf(bio_err, "Verification failure\n"); 958296341Sdelphij goto end; 959296341Sdelphij } 960296341Sdelphij } else if (operation == SMIME_ENCRYPTED_DECRYPT) { 961296341Sdelphij if (!CMS_EncryptedData_decrypt(cms, secret_key, secret_keylen, 962296341Sdelphij indata, out, flags)) 963296341Sdelphij goto end; 964296341Sdelphij } else if (operation == SMIME_VERIFY) { 965296341Sdelphij if (CMS_verify(cms, other, store, indata, out, flags) > 0) 966296341Sdelphij BIO_printf(bio_err, "Verification successful\n"); 967296341Sdelphij else { 968296341Sdelphij BIO_printf(bio_err, "Verification failure\n"); 969296341Sdelphij if (verify_retcode) 970296341Sdelphij ret = verify_err + 32; 971296341Sdelphij goto end; 972296341Sdelphij } 973296341Sdelphij if (signerfile) { 974296341Sdelphij STACK_OF(X509) *signers; 975296341Sdelphij signers = CMS_get0_signers(cms); 976296341Sdelphij if (!save_certs(signerfile, signers)) { 977296341Sdelphij BIO_printf(bio_err, 978296341Sdelphij "Error writing signers to %s\n", signerfile); 979296341Sdelphij ret = 5; 980296341Sdelphij goto end; 981296341Sdelphij } 982296341Sdelphij sk_X509_free(signers); 983296341Sdelphij } 984296341Sdelphij if (rr_print) 985296341Sdelphij receipt_request_print(bio_err, cms); 986296341Sdelphij 987296341Sdelphij } else if (operation == SMIME_VERIFY_RECEIPT) { 988296341Sdelphij if (CMS_verify_receipt(rcms, cms, other, store, flags) > 0) 989296341Sdelphij BIO_printf(bio_err, "Verification successful\n"); 990296341Sdelphij else { 991296341Sdelphij BIO_printf(bio_err, "Verification failure\n"); 992296341Sdelphij goto end; 993296341Sdelphij } 994296341Sdelphij } else { 995296341Sdelphij if (noout) { 996296341Sdelphij if (print) 997296341Sdelphij CMS_ContentInfo_print_ctx(out, cms, 0, NULL); 998296341Sdelphij } else if (outformat == FORMAT_SMIME) { 999296341Sdelphij if (to) 1000296341Sdelphij BIO_printf(out, "To: %s\n", to); 1001296341Sdelphij if (from) 1002296341Sdelphij BIO_printf(out, "From: %s\n", from); 1003296341Sdelphij if (subject) 1004296341Sdelphij BIO_printf(out, "Subject: %s\n", subject); 1005296341Sdelphij if (operation == SMIME_RESIGN) 1006296341Sdelphij ret = SMIME_write_CMS(out, cms, indata, flags); 1007296341Sdelphij else 1008296341Sdelphij ret = SMIME_write_CMS(out, cms, in, flags); 1009296341Sdelphij } else if (outformat == FORMAT_PEM) 1010296341Sdelphij ret = PEM_write_bio_CMS_stream(out, cms, in, flags); 1011296341Sdelphij else if (outformat == FORMAT_ASN1) 1012296341Sdelphij ret = i2d_CMS_bio_stream(out, cms, in, flags); 1013296341Sdelphij else { 1014296341Sdelphij BIO_printf(bio_err, "Bad output format for CMS file\n"); 1015296341Sdelphij goto end; 1016296341Sdelphij } 1017296341Sdelphij if (ret <= 0) { 1018296341Sdelphij ret = 6; 1019296341Sdelphij goto end; 1020296341Sdelphij } 1021296341Sdelphij } 1022296341Sdelphij ret = 0; 1023296341Sdelphij end: 1024296341Sdelphij if (ret) 1025296341Sdelphij ERR_print_errors(bio_err); 1026296341Sdelphij if (need_rand) 1027296341Sdelphij app_RAND_write_file(NULL, bio_err); 1028296341Sdelphij sk_X509_pop_free(encerts, X509_free); 1029296341Sdelphij sk_X509_pop_free(other, X509_free); 1030296341Sdelphij if (vpm) 1031296341Sdelphij X509_VERIFY_PARAM_free(vpm); 1032296341Sdelphij if (sksigners) 1033296341Sdelphij sk_OPENSSL_STRING_free(sksigners); 1034296341Sdelphij if (skkeys) 1035296341Sdelphij sk_OPENSSL_STRING_free(skkeys); 1036296341Sdelphij if (secret_key) 1037296341Sdelphij OPENSSL_free(secret_key); 1038296341Sdelphij if (secret_keyid) 1039296341Sdelphij OPENSSL_free(secret_keyid); 1040296341Sdelphij if (pwri_tmp) 1041296341Sdelphij OPENSSL_free(pwri_tmp); 1042296341Sdelphij if (econtent_type) 1043296341Sdelphij ASN1_OBJECT_free(econtent_type); 1044296341Sdelphij if (rr) 1045296341Sdelphij CMS_ReceiptRequest_free(rr); 1046296341Sdelphij if (rr_to) 1047296341Sdelphij sk_OPENSSL_STRING_free(rr_to); 1048296341Sdelphij if (rr_from) 1049296341Sdelphij sk_OPENSSL_STRING_free(rr_from); 1050296341Sdelphij X509_STORE_free(store); 1051296341Sdelphij X509_free(cert); 1052296341Sdelphij X509_free(recip); 1053296341Sdelphij X509_free(signer); 1054296341Sdelphij EVP_PKEY_free(key); 1055296341Sdelphij CMS_ContentInfo_free(cms); 1056296341Sdelphij CMS_ContentInfo_free(rcms); 1057296341Sdelphij BIO_free(rctin); 1058296341Sdelphij BIO_free(in); 1059296341Sdelphij BIO_free(indata); 1060296341Sdelphij BIO_free_all(out); 1061296341Sdelphij if (passin) 1062296341Sdelphij OPENSSL_free(passin); 1063296341Sdelphij return (ret); 1064183234Ssimon} 1065183234Ssimon 1066183234Ssimonstatic int save_certs(char *signerfile, STACK_OF(X509) *signers) 1067296341Sdelphij{ 1068296341Sdelphij int i; 1069296341Sdelphij BIO *tmp; 1070296341Sdelphij if (!signerfile) 1071296341Sdelphij return 1; 1072296341Sdelphij tmp = BIO_new_file(signerfile, "w"); 1073296341Sdelphij if (!tmp) 1074296341Sdelphij return 0; 1075296341Sdelphij for (i = 0; i < sk_X509_num(signers); i++) 1076296341Sdelphij PEM_write_bio_X509(tmp, sk_X509_value(signers, i)); 1077296341Sdelphij BIO_free(tmp); 1078296341Sdelphij return 1; 1079296341Sdelphij} 1080183234Ssimon 1081183234Ssimon/* Minimal callback just to output policy info (if any) */ 1082183234Ssimon 1083183234Ssimonstatic int cms_cb(int ok, X509_STORE_CTX *ctx) 1084296341Sdelphij{ 1085296341Sdelphij int error; 1086183234Ssimon 1087296341Sdelphij error = X509_STORE_CTX_get_error(ctx); 1088183234Ssimon 1089296341Sdelphij verify_err = error; 1090238405Sjkim 1091296341Sdelphij if ((error != X509_V_ERR_NO_EXPLICIT_POLICY) 1092296341Sdelphij && ((error != X509_V_OK) || (ok != 2))) 1093296341Sdelphij return ok; 1094183234Ssimon 1095296341Sdelphij policies_print(NULL, ctx); 1096183234Ssimon 1097296341Sdelphij return ok; 1098183234Ssimon 1099296341Sdelphij} 1100183234Ssimon 1101183234Ssimonstatic void gnames_stack_print(BIO *out, STACK_OF(GENERAL_NAMES) *gns) 1102296341Sdelphij{ 1103296341Sdelphij STACK_OF(GENERAL_NAME) *gens; 1104296341Sdelphij GENERAL_NAME *gen; 1105296341Sdelphij int i, j; 1106296341Sdelphij for (i = 0; i < sk_GENERAL_NAMES_num(gns); i++) { 1107296341Sdelphij gens = sk_GENERAL_NAMES_value(gns, i); 1108296341Sdelphij for (j = 0; j < sk_GENERAL_NAME_num(gens); j++) { 1109296341Sdelphij gen = sk_GENERAL_NAME_value(gens, j); 1110296341Sdelphij BIO_puts(out, " "); 1111296341Sdelphij GENERAL_NAME_print(out, gen); 1112296341Sdelphij BIO_puts(out, "\n"); 1113296341Sdelphij } 1114296341Sdelphij } 1115296341Sdelphij return; 1116296341Sdelphij} 1117183234Ssimon 1118183234Ssimonstatic void receipt_request_print(BIO *out, CMS_ContentInfo *cms) 1119296341Sdelphij{ 1120296341Sdelphij STACK_OF(CMS_SignerInfo) *sis; 1121296341Sdelphij CMS_SignerInfo *si; 1122296341Sdelphij CMS_ReceiptRequest *rr; 1123296341Sdelphij int allorfirst; 1124296341Sdelphij STACK_OF(GENERAL_NAMES) *rto, *rlist; 1125296341Sdelphij ASN1_STRING *scid; 1126296341Sdelphij int i, rv; 1127296341Sdelphij sis = CMS_get0_SignerInfos(cms); 1128296341Sdelphij for (i = 0; i < sk_CMS_SignerInfo_num(sis); i++) { 1129296341Sdelphij si = sk_CMS_SignerInfo_value(sis, i); 1130296341Sdelphij rv = CMS_get1_ReceiptRequest(si, &rr); 1131296341Sdelphij BIO_printf(bio_err, "Signer %d:\n", i + 1); 1132296341Sdelphij if (rv == 0) 1133296341Sdelphij BIO_puts(bio_err, " No Receipt Request\n"); 1134296341Sdelphij else if (rv < 0) { 1135296341Sdelphij BIO_puts(bio_err, " Receipt Request Parse Error\n"); 1136296341Sdelphij ERR_print_errors(bio_err); 1137296341Sdelphij } else { 1138296341Sdelphij char *id; 1139296341Sdelphij int idlen; 1140296341Sdelphij CMS_ReceiptRequest_get0_values(rr, &scid, &allorfirst, 1141296341Sdelphij &rlist, &rto); 1142296341Sdelphij BIO_puts(out, " Signed Content ID:\n"); 1143296341Sdelphij idlen = ASN1_STRING_length(scid); 1144296341Sdelphij id = (char *)ASN1_STRING_data(scid); 1145296341Sdelphij BIO_dump_indent(out, id, idlen, 4); 1146296341Sdelphij BIO_puts(out, " Receipts From"); 1147296341Sdelphij if (rlist) { 1148296341Sdelphij BIO_puts(out, " List:\n"); 1149296341Sdelphij gnames_stack_print(out, rlist); 1150296341Sdelphij } else if (allorfirst == 1) 1151296341Sdelphij BIO_puts(out, ": First Tier\n"); 1152296341Sdelphij else if (allorfirst == 0) 1153296341Sdelphij BIO_puts(out, ": All\n"); 1154296341Sdelphij else 1155296341Sdelphij BIO_printf(out, " Unknown (%d)\n", allorfirst); 1156296341Sdelphij BIO_puts(out, " Receipts To:\n"); 1157296341Sdelphij gnames_stack_print(out, rto); 1158296341Sdelphij } 1159296341Sdelphij if (rr) 1160296341Sdelphij CMS_ReceiptRequest_free(rr); 1161296341Sdelphij } 1162296341Sdelphij} 1163183234Ssimon 1164238405Sjkimstatic STACK_OF(GENERAL_NAMES) *make_names_stack(STACK_OF(OPENSSL_STRING) *ns) 1165296341Sdelphij{ 1166296341Sdelphij int i; 1167296341Sdelphij STACK_OF(GENERAL_NAMES) *ret; 1168296341Sdelphij GENERAL_NAMES *gens = NULL; 1169296341Sdelphij GENERAL_NAME *gen = NULL; 1170296341Sdelphij ret = sk_GENERAL_NAMES_new_null(); 1171296341Sdelphij if (!ret) 1172296341Sdelphij goto err; 1173296341Sdelphij for (i = 0; i < sk_OPENSSL_STRING_num(ns); i++) { 1174296341Sdelphij char *str = sk_OPENSSL_STRING_value(ns, i); 1175296341Sdelphij gen = a2i_GENERAL_NAME(NULL, NULL, NULL, GEN_EMAIL, str, 0); 1176296341Sdelphij if (!gen) 1177296341Sdelphij goto err; 1178296341Sdelphij gens = GENERAL_NAMES_new(); 1179296341Sdelphij if (!gens) 1180296341Sdelphij goto err; 1181296341Sdelphij if (!sk_GENERAL_NAME_push(gens, gen)) 1182296341Sdelphij goto err; 1183296341Sdelphij gen = NULL; 1184296341Sdelphij if (!sk_GENERAL_NAMES_push(ret, gens)) 1185296341Sdelphij goto err; 1186296341Sdelphij gens = NULL; 1187296341Sdelphij } 1188183234Ssimon 1189296341Sdelphij return ret; 1190183234Ssimon 1191296341Sdelphij err: 1192296341Sdelphij if (ret) 1193296341Sdelphij sk_GENERAL_NAMES_pop_free(ret, GENERAL_NAMES_free); 1194296341Sdelphij if (gens) 1195296341Sdelphij GENERAL_NAMES_free(gens); 1196296341Sdelphij if (gen) 1197296341Sdelphij GENERAL_NAME_free(gen); 1198296341Sdelphij return NULL; 1199296341Sdelphij} 1200183234Ssimon 1201296341Sdelphijstatic CMS_ReceiptRequest *make_receipt_request(STACK_OF(OPENSSL_STRING) 1202296341Sdelphij *rr_to, int rr_allorfirst, STACK_OF(OPENSSL_STRING) 1203296341Sdelphij *rr_from) 1204296341Sdelphij{ 1205296341Sdelphij STACK_OF(GENERAL_NAMES) *rct_to, *rct_from; 1206296341Sdelphij CMS_ReceiptRequest *rr; 1207296341Sdelphij rct_to = make_names_stack(rr_to); 1208296341Sdelphij if (!rct_to) 1209296341Sdelphij goto err; 1210296341Sdelphij if (rr_from) { 1211296341Sdelphij rct_from = make_names_stack(rr_from); 1212296341Sdelphij if (!rct_from) 1213296341Sdelphij goto err; 1214296341Sdelphij } else 1215296341Sdelphij rct_from = NULL; 1216296341Sdelphij rr = CMS_ReceiptRequest_create0(NULL, -1, rr_allorfirst, rct_from, 1217296341Sdelphij rct_to); 1218296341Sdelphij return rr; 1219296341Sdelphij err: 1220296341Sdelphij return NULL; 1221296341Sdelphij} 1222183234Ssimon 1223183234Ssimon#endif 1224