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