1 1.2 christos /* 2 1.3 christos * Copyright 1999-2025 The OpenSSL Project Authors. All Rights Reserved. 3 1.1 christos * 4 1.2 christos * Licensed under the Apache License 2.0 (the "License"). You may not use 5 1.2 christos * this file except in compliance with the License. You can obtain a copy 6 1.2 christos * in the file LICENSE in the source distribution or at 7 1.2 christos * https://www.openssl.org/source/license.html 8 1.1 christos */ 9 1.1 christos 10 1.1 christos /* S/MIME utility function */ 11 1.1 christos 12 1.1 christos #include <stdio.h> 13 1.1 christos #include <string.h> 14 1.1 christos #include "apps.h" 15 1.2 christos #include "progs.h" 16 1.1 christos #include <openssl/crypto.h> 17 1.1 christos #include <openssl/pem.h> 18 1.1 christos #include <openssl/err.h> 19 1.1 christos #include <openssl/x509_vfy.h> 20 1.1 christos #include <openssl/x509v3.h> 21 1.1 christos 22 1.1 christos static int save_certs(char *signerfile, STACK_OF(X509) *signers); 23 1.1 christos static int smime_cb(int ok, X509_STORE_CTX *ctx); 24 1.1 christos 25 1.2 christos #define SMIME_OP 0x10 26 1.2 christos #define SMIME_IP 0x20 27 1.2 christos #define SMIME_SIGNERS 0x40 28 1.2 christos #define SMIME_ENCRYPT (1 | SMIME_OP) 29 1.2 christos #define SMIME_DECRYPT (2 | SMIME_IP) 30 1.2 christos #define SMIME_SIGN (3 | SMIME_OP | SMIME_SIGNERS) 31 1.2 christos #define SMIME_VERIFY (4 | SMIME_IP) 32 1.2 christos #define SMIME_PK7OUT (5 | SMIME_IP | SMIME_OP) 33 1.2 christos #define SMIME_RESIGN (6 | SMIME_IP | SMIME_OP | SMIME_SIGNERS) 34 1.2 christos 35 1.2 christos typedef enum OPTION_choice { 36 1.2 christos OPT_COMMON, 37 1.2 christos OPT_ENCRYPT, OPT_DECRYPT, OPT_SIGN, OPT_RESIGN, OPT_VERIFY, 38 1.2 christos OPT_PK7OUT, OPT_TEXT, OPT_NOINTERN, OPT_NOVERIFY, OPT_NOCHAIN, 39 1.2 christos OPT_NOCERTS, OPT_NOATTR, OPT_NODETACH, OPT_NOSMIMECAP, 40 1.2 christos OPT_BINARY, OPT_NOSIGS, OPT_STREAM, OPT_INDEF, OPT_NOINDEF, 41 1.2 christos OPT_CRLFEOL, OPT_ENGINE, OPT_PASSIN, 42 1.2 christos OPT_TO, OPT_FROM, OPT_SUBJECT, OPT_SIGNER, OPT_RECIP, OPT_MD, 43 1.2 christos OPT_CIPHER, OPT_INKEY, OPT_KEYFORM, OPT_CERTFILE, OPT_CAFILE, 44 1.2 christos OPT_CAPATH, OPT_CASTORE, OPT_NOCAFILE, OPT_NOCAPATH, OPT_NOCASTORE, 45 1.2 christos OPT_R_ENUM, OPT_PROV_ENUM, OPT_CONFIG, 46 1.2 christos OPT_V_ENUM, 47 1.2 christos OPT_IN, OPT_INFORM, OPT_OUT, 48 1.2 christos OPT_OUTFORM, OPT_CONTENT 49 1.2 christos } OPTION_CHOICE; 50 1.2 christos 51 1.2 christos const OPTIONS smime_options[] = { 52 1.2 christos {OPT_HELP_STR, 1, '-', "Usage: %s [options] [cert...]\n"}, 53 1.2 christos 54 1.2 christos OPT_SECTION("General"), 55 1.2 christos {"help", OPT_HELP, '-', "Display this summary"}, 56 1.2 christos {"in", OPT_IN, '<', "Input file"}, 57 1.2 christos {"inform", OPT_INFORM, 'c', "Input format SMIME (default), PEM or DER"}, 58 1.2 christos {"out", OPT_OUT, '>', "Output file"}, 59 1.2 christos {"outform", OPT_OUTFORM, 'c', 60 1.2 christos "Output format SMIME (default), PEM or DER"}, 61 1.2 christos {"inkey", OPT_INKEY, 's', 62 1.2 christos "Input private key (if not signer or recipient)"}, 63 1.2 christos {"keyform", OPT_KEYFORM, 'f', "Input private key format (ENGINE, other values ignored)"}, 64 1.1 christos #ifndef OPENSSL_NO_ENGINE 65 1.2 christos {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"}, 66 1.1 christos #endif 67 1.2 christos {"stream", OPT_STREAM, '-', "Enable CMS streaming" }, 68 1.2 christos {"indef", OPT_INDEF, '-', "Same as -stream" }, 69 1.2 christos {"noindef", OPT_NOINDEF, '-', "Disable CMS streaming"}, 70 1.2 christos OPT_CONFIG_OPTION, 71 1.2 christos 72 1.2 christos OPT_SECTION("Action"), 73 1.2 christos {"encrypt", OPT_ENCRYPT, '-', "Encrypt message"}, 74 1.2 christos {"decrypt", OPT_DECRYPT, '-', "Decrypt encrypted message"}, 75 1.2 christos {"sign", OPT_SIGN, '-', "Sign message"}, 76 1.2 christos {"resign", OPT_RESIGN, '-', "Resign a signed message"}, 77 1.2 christos {"verify", OPT_VERIFY, '-', "Verify signed message"}, 78 1.2 christos 79 1.2 christos OPT_SECTION("Signing/Encryption"), 80 1.2 christos {"passin", OPT_PASSIN, 's', "Input file pass phrase source"}, 81 1.2 christos {"md", OPT_MD, 's', "Digest algorithm to use when signing or resigning"}, 82 1.2 christos {"", OPT_CIPHER, '-', "Any supported cipher"}, 83 1.2 christos {"pk7out", OPT_PK7OUT, '-', "Output PKCS#7 structure"}, 84 1.2 christos {"nointern", OPT_NOINTERN, '-', 85 1.2 christos "Don't search certificates in message for signer"}, 86 1.2 christos {"nodetach", OPT_NODETACH, '-', "Use opaque signing"}, 87 1.2 christos {"noattr", OPT_NOATTR, '-', "Don't include any signed attributes"}, 88 1.2 christos {"binary", OPT_BINARY, '-', "Don't translate message to text"}, 89 1.2 christos {"signer", OPT_SIGNER, 's', "Signer certificate file"}, 90 1.2 christos {"content", OPT_CONTENT, '<', 91 1.2 christos "Supply or override content for detached signature"}, 92 1.2 christos {"nocerts", OPT_NOCERTS, '-', 93 1.2 christos "Don't include signers certificate when signing"}, 94 1.2 christos 95 1.2 christos OPT_SECTION("Verification/Decryption"), 96 1.2 christos {"nosigs", OPT_NOSIGS, '-', "Don't verify message signature"}, 97 1.2 christos {"noverify", OPT_NOVERIFY, '-', "Don't verify signers certificate"}, 98 1.2 christos 99 1.2 christos {"certfile", OPT_CERTFILE, '<', "Other certificates file"}, 100 1.2 christos {"recip", OPT_RECIP, '<', "Recipient certificate file for decryption"}, 101 1.2 christos 102 1.2 christos OPT_SECTION("Email"), 103 1.2 christos {"to", OPT_TO, 's', "To address"}, 104 1.2 christos {"from", OPT_FROM, 's', "From address"}, 105 1.2 christos {"subject", OPT_SUBJECT, 's', "Subject"}, 106 1.2 christos {"text", OPT_TEXT, '-', "Include or delete text MIME headers"}, 107 1.2 christos {"nosmimecap", OPT_NOSMIMECAP, '-', "Omit the SMIMECapabilities attribute"}, 108 1.2 christos 109 1.2 christos OPT_SECTION("Certificate chain"), 110 1.2 christos {"CApath", OPT_CAPATH, '/', "Trusted certificates directory"}, 111 1.2 christos {"CAfile", OPT_CAFILE, '<', "Trusted certificates file"}, 112 1.2 christos {"CAstore", OPT_CASTORE, ':', "Trusted certificates store URI"}, 113 1.2 christos {"no-CAfile", OPT_NOCAFILE, '-', 114 1.2 christos "Do not load the default certificates file"}, 115 1.2 christos {"no-CApath", OPT_NOCAPATH, '-', 116 1.2 christos "Do not load certificates from the default certificates directory"}, 117 1.2 christos {"no-CAstore", OPT_NOCASTORE, '-', 118 1.2 christos "Do not load certificates from the default certificates store"}, 119 1.2 christos {"nochain", OPT_NOCHAIN, '-', 120 1.2 christos "set PKCS7_NOCHAIN so certificates contained in the message are not used as untrusted CAs" }, 121 1.2 christos {"crlfeol", OPT_CRLFEOL, '-', "Use CRLF as EOL termination instead of LF only"}, 122 1.2 christos 123 1.2 christos OPT_R_OPTIONS, 124 1.2 christos OPT_V_OPTIONS, 125 1.2 christos OPT_PROV_OPTIONS, 126 1.2 christos 127 1.2 christos OPT_PARAMETERS(), 128 1.2 christos {"cert", 0, 0, "Recipient certs, used when encrypting"}, 129 1.2 christos {NULL} 130 1.2 christos }; 131 1.2 christos 132 1.2 christos int smime_main(int argc, char **argv) 133 1.2 christos { 134 1.2 christos CONF *conf = NULL; 135 1.2 christos BIO *in = NULL, *out = NULL, *indata = NULL; 136 1.2 christos EVP_PKEY *key = NULL; 137 1.2 christos PKCS7 *p7 = NULL; 138 1.2 christos STACK_OF(OPENSSL_STRING) *sksigners = NULL, *skkeys = NULL; 139 1.2 christos STACK_OF(X509) *encerts = NULL, *other = NULL; 140 1.2 christos X509 *cert = NULL, *recip = NULL, *signer = NULL; 141 1.2 christos X509_STORE *store = NULL; 142 1.2 christos X509_VERIFY_PARAM *vpm = NULL; 143 1.2 christos EVP_CIPHER *cipher = NULL; 144 1.2 christos EVP_MD *sign_md = NULL; 145 1.2 christos const char *CAfile = NULL, *CApath = NULL, *CAstore = NULL, *prog = NULL; 146 1.2 christos char *certfile = NULL, *keyfile = NULL, *contfile = NULL; 147 1.2 christos char *infile = NULL, *outfile = NULL, *signerfile = NULL, *recipfile = NULL; 148 1.2 christos char *passinarg = NULL, *passin = NULL, *to = NULL, *from = NULL; 149 1.2 christos char *subject = NULL, *digestname = NULL, *ciphername = NULL; 150 1.2 christos OPTION_CHOICE o; 151 1.2 christos int noCApath = 0, noCAfile = 0, noCAstore = 0; 152 1.2 christos int flags = PKCS7_DETACHED, operation = 0, ret = 0, indef = 0; 153 1.2 christos int informat = FORMAT_SMIME, outformat = FORMAT_SMIME, keyform = 154 1.2 christos FORMAT_UNDEF; 155 1.2 christos int vpmtouched = 0, rv = 0; 156 1.2 christos ENGINE *e = NULL; 157 1.2 christos const char *mime_eol = "\n"; 158 1.2 christos OSSL_LIB_CTX *libctx = app_get0_libctx(); 159 1.2 christos 160 1.2 christos if ((vpm = X509_VERIFY_PARAM_new()) == NULL) 161 1.2 christos return 1; 162 1.2 christos 163 1.2 christos prog = opt_init(argc, argv, smime_options); 164 1.2 christos while ((o = opt_next()) != OPT_EOF) { 165 1.2 christos switch (o) { 166 1.2 christos case OPT_EOF: 167 1.2 christos case OPT_ERR: 168 1.2 christos opthelp: 169 1.2 christos BIO_printf(bio_err, "%s: Use -help for summary.\n", prog); 170 1.2 christos goto end; 171 1.2 christos case OPT_HELP: 172 1.2 christos opt_help(smime_options); 173 1.2 christos ret = 0; 174 1.2 christos goto end; 175 1.2 christos case OPT_INFORM: 176 1.2 christos if (!opt_format(opt_arg(), OPT_FMT_PDS, &informat)) 177 1.2 christos goto opthelp; 178 1.2 christos break; 179 1.2 christos case OPT_IN: 180 1.2 christos infile = opt_arg(); 181 1.2 christos break; 182 1.2 christos case OPT_OUTFORM: 183 1.2 christos if (!opt_format(opt_arg(), OPT_FMT_PDS, &outformat)) 184 1.2 christos goto opthelp; 185 1.2 christos break; 186 1.2 christos case OPT_OUT: 187 1.2 christos outfile = opt_arg(); 188 1.2 christos break; 189 1.2 christos case OPT_ENCRYPT: 190 1.2 christos operation = SMIME_ENCRYPT; 191 1.2 christos break; 192 1.2 christos case OPT_DECRYPT: 193 1.2 christos operation = SMIME_DECRYPT; 194 1.2 christos break; 195 1.2 christos case OPT_SIGN: 196 1.2 christos operation = SMIME_SIGN; 197 1.2 christos break; 198 1.2 christos case OPT_RESIGN: 199 1.2 christos operation = SMIME_RESIGN; 200 1.2 christos break; 201 1.2 christos case OPT_VERIFY: 202 1.2 christos operation = SMIME_VERIFY; 203 1.2 christos break; 204 1.2 christos case OPT_PK7OUT: 205 1.2 christos operation = SMIME_PK7OUT; 206 1.2 christos break; 207 1.2 christos case OPT_TEXT: 208 1.2 christos flags |= PKCS7_TEXT; 209 1.2 christos break; 210 1.2 christos case OPT_NOINTERN: 211 1.2 christos flags |= PKCS7_NOINTERN; 212 1.2 christos break; 213 1.2 christos case OPT_NOVERIFY: 214 1.2 christos flags |= PKCS7_NOVERIFY; 215 1.2 christos break; 216 1.2 christos case OPT_NOCHAIN: 217 1.2 christos flags |= PKCS7_NOCHAIN; 218 1.2 christos break; 219 1.2 christos case OPT_NOCERTS: 220 1.2 christos flags |= PKCS7_NOCERTS; 221 1.2 christos break; 222 1.2 christos case OPT_NOATTR: 223 1.2 christos flags |= PKCS7_NOATTR; 224 1.2 christos break; 225 1.2 christos case OPT_NODETACH: 226 1.2 christos flags &= ~PKCS7_DETACHED; 227 1.2 christos break; 228 1.2 christos case OPT_NOSMIMECAP: 229 1.2 christos flags |= PKCS7_NOSMIMECAP; 230 1.2 christos break; 231 1.2 christos case OPT_BINARY: 232 1.2 christos flags |= PKCS7_BINARY; 233 1.2 christos break; 234 1.2 christos case OPT_NOSIGS: 235 1.2 christos flags |= PKCS7_NOSIGS; 236 1.2 christos break; 237 1.2 christos case OPT_STREAM: 238 1.2 christos case OPT_INDEF: 239 1.2 christos indef = 1; 240 1.2 christos break; 241 1.2 christos case OPT_NOINDEF: 242 1.2 christos indef = 0; 243 1.2 christos break; 244 1.2 christos case OPT_CRLFEOL: 245 1.2 christos flags |= PKCS7_CRLFEOL; 246 1.2 christos mime_eol = "\r\n"; 247 1.2 christos break; 248 1.2 christos case OPT_R_CASES: 249 1.2 christos if (!opt_rand(o)) 250 1.2 christos goto end; 251 1.2 christos break; 252 1.2 christos case OPT_PROV_CASES: 253 1.2 christos if (!opt_provider(o)) 254 1.2 christos goto end; 255 1.2 christos break; 256 1.2 christos case OPT_CONFIG: 257 1.2 christos conf = app_load_config_modules(opt_arg()); 258 1.2 christos if (conf == NULL) 259 1.2 christos goto end; 260 1.2 christos break; 261 1.2 christos case OPT_ENGINE: 262 1.2 christos e = setup_engine(opt_arg(), 0); 263 1.2 christos break; 264 1.2 christos case OPT_PASSIN: 265 1.2 christos passinarg = opt_arg(); 266 1.2 christos break; 267 1.2 christos case OPT_TO: 268 1.2 christos to = opt_arg(); 269 1.2 christos break; 270 1.2 christos case OPT_FROM: 271 1.2 christos from = opt_arg(); 272 1.2 christos break; 273 1.2 christos case OPT_SUBJECT: 274 1.2 christos subject = opt_arg(); 275 1.2 christos break; 276 1.2 christos case OPT_SIGNER: 277 1.2 christos /* If previous -signer argument add signer to list */ 278 1.2 christos if (signerfile != NULL) { 279 1.2 christos if (sksigners == NULL 280 1.2 christos && (sksigners = sk_OPENSSL_STRING_new_null()) == NULL) 281 1.2 christos goto end; 282 1.3 christos if (sk_OPENSSL_STRING_push(sksigners, signerfile) <= 0) 283 1.3 christos goto end; 284 1.2 christos if (keyfile == NULL) 285 1.2 christos keyfile = signerfile; 286 1.2 christos if (skkeys == NULL 287 1.2 christos && (skkeys = sk_OPENSSL_STRING_new_null()) == NULL) 288 1.2 christos goto end; 289 1.3 christos if (sk_OPENSSL_STRING_push(skkeys, keyfile) <= 0) 290 1.3 christos goto end; 291 1.2 christos keyfile = NULL; 292 1.2 christos } 293 1.2 christos signerfile = opt_arg(); 294 1.2 christos break; 295 1.2 christos case OPT_RECIP: 296 1.2 christos recipfile = opt_arg(); 297 1.2 christos break; 298 1.2 christos case OPT_MD: 299 1.2 christos digestname = opt_arg(); 300 1.2 christos break; 301 1.2 christos case OPT_CIPHER: 302 1.2 christos ciphername = opt_unknown(); 303 1.2 christos break; 304 1.2 christos case OPT_INKEY: 305 1.2 christos /* If previous -inkey argument add signer to list */ 306 1.2 christos if (keyfile != NULL) { 307 1.2 christos if (signerfile == NULL) { 308 1.2 christos BIO_printf(bio_err, 309 1.2 christos "%s: Must have -signer before -inkey\n", prog); 310 1.2 christos goto opthelp; 311 1.2 christos } 312 1.2 christos if (sksigners == NULL 313 1.2 christos && (sksigners = sk_OPENSSL_STRING_new_null()) == NULL) 314 1.2 christos goto end; 315 1.3 christos if (sk_OPENSSL_STRING_push(sksigners, signerfile) <= 0) 316 1.3 christos goto end; 317 1.2 christos signerfile = NULL; 318 1.2 christos if (skkeys == NULL 319 1.2 christos && (skkeys = sk_OPENSSL_STRING_new_null()) == NULL) 320 1.2 christos goto end; 321 1.3 christos if (sk_OPENSSL_STRING_push(skkeys, keyfile) <= 0) 322 1.3 christos goto end; 323 1.2 christos } 324 1.2 christos keyfile = opt_arg(); 325 1.2 christos break; 326 1.2 christos case OPT_KEYFORM: 327 1.2 christos if (!opt_format(opt_arg(), OPT_FMT_ANY, &keyform)) 328 1.2 christos goto opthelp; 329 1.2 christos break; 330 1.2 christos case OPT_CERTFILE: 331 1.2 christos certfile = opt_arg(); 332 1.2 christos break; 333 1.2 christos case OPT_CAFILE: 334 1.2 christos CAfile = opt_arg(); 335 1.2 christos break; 336 1.2 christos case OPT_CAPATH: 337 1.2 christos CApath = opt_arg(); 338 1.2 christos break; 339 1.2 christos case OPT_CASTORE: 340 1.2 christos CAstore = opt_arg(); 341 1.2 christos break; 342 1.2 christos case OPT_NOCAFILE: 343 1.2 christos noCAfile = 1; 344 1.2 christos break; 345 1.2 christos case OPT_NOCAPATH: 346 1.2 christos noCApath = 1; 347 1.2 christos break; 348 1.2 christos case OPT_NOCASTORE: 349 1.2 christos noCAstore = 1; 350 1.2 christos break; 351 1.2 christos case OPT_CONTENT: 352 1.2 christos contfile = opt_arg(); 353 1.2 christos break; 354 1.2 christos case OPT_V_CASES: 355 1.2 christos if (!opt_verify(o, vpm)) 356 1.2 christos goto opthelp; 357 1.2 christos vpmtouched++; 358 1.2 christos break; 359 1.2 christos } 360 1.2 christos } 361 1.2 christos 362 1.2 christos /* Extra arguments are files with recipient keys. */ 363 1.2 christos argc = opt_num_rest(); 364 1.2 christos argv = opt_rest(); 365 1.2 christos 366 1.2 christos if (!app_RAND_load()) 367 1.2 christos goto end; 368 1.2 christos 369 1.2 christos if (digestname != NULL) { 370 1.2 christos if (!opt_md(digestname, &sign_md)) 371 1.2 christos goto opthelp; 372 1.2 christos } 373 1.2 christos if (ciphername != NULL) { 374 1.2 christos if (!opt_cipher_any(ciphername, &cipher)) 375 1.2 christos goto opthelp; 376 1.2 christos } 377 1.2 christos if (!(operation & SMIME_SIGNERS) && (skkeys != NULL || sksigners != NULL)) { 378 1.2 christos BIO_puts(bio_err, "Multiple signers or keys not allowed\n"); 379 1.2 christos goto opthelp; 380 1.2 christos } 381 1.2 christos if (!operation) { 382 1.2 christos BIO_puts(bio_err, 383 1.2 christos "No operation (-encrypt|-sign|...) specified\n"); 384 1.2 christos goto opthelp; 385 1.2 christos } 386 1.2 christos 387 1.2 christos if (operation & SMIME_SIGNERS) { 388 1.2 christos /* Check to see if any final signer needs to be appended */ 389 1.2 christos if (keyfile && !signerfile) { 390 1.2 christos BIO_puts(bio_err, "Illegal -inkey without -signer\n"); 391 1.2 christos goto opthelp; 392 1.2 christos } 393 1.2 christos if (signerfile != NULL) { 394 1.2 christos if (sksigners == NULL 395 1.2 christos && (sksigners = sk_OPENSSL_STRING_new_null()) == NULL) 396 1.2 christos goto end; 397 1.3 christos if (sk_OPENSSL_STRING_push(sksigners, signerfile) <= 0) 398 1.3 christos goto end; 399 1.2 christos if (!skkeys && (skkeys = sk_OPENSSL_STRING_new_null()) == NULL) 400 1.2 christos goto end; 401 1.2 christos if (!keyfile) 402 1.2 christos keyfile = signerfile; 403 1.3 christos if (sk_OPENSSL_STRING_push(skkeys, keyfile) <= 0) 404 1.3 christos goto end; 405 1.2 christos } 406 1.2 christos if (sksigners == NULL) { 407 1.2 christos BIO_printf(bio_err, "No signer certificate specified\n"); 408 1.2 christos goto opthelp; 409 1.2 christos } 410 1.2 christos signerfile = NULL; 411 1.2 christos keyfile = NULL; 412 1.2 christos } else if (operation == SMIME_DECRYPT) { 413 1.2 christos if (recipfile == NULL && keyfile == NULL) { 414 1.2 christos BIO_printf(bio_err, 415 1.2 christos "No recipient certificate or key specified\n"); 416 1.2 christos goto opthelp; 417 1.2 christos } 418 1.2 christos } else if (operation == SMIME_ENCRYPT) { 419 1.2 christos if (argc == 0) { 420 1.2 christos BIO_printf(bio_err, "No recipient(s) certificate(s) specified\n"); 421 1.2 christos goto opthelp; 422 1.2 christos } 423 1.2 christos } 424 1.2 christos 425 1.2 christos if (!app_passwd(passinarg, NULL, &passin, NULL)) { 426 1.2 christos BIO_printf(bio_err, "Error getting password\n"); 427 1.2 christos goto end; 428 1.2 christos } 429 1.2 christos 430 1.2 christos ret = 2; 431 1.2 christos 432 1.2 christos if (!(operation & SMIME_SIGNERS)) 433 1.2 christos flags &= ~PKCS7_DETACHED; 434 1.2 christos 435 1.2 christos if (!(operation & SMIME_OP)) { 436 1.2 christos if (flags & PKCS7_BINARY) 437 1.2 christos outformat = FORMAT_BINARY; 438 1.2 christos } 439 1.2 christos 440 1.2 christos if (!(operation & SMIME_IP)) { 441 1.2 christos if (flags & PKCS7_BINARY) 442 1.2 christos informat = FORMAT_BINARY; 443 1.2 christos } 444 1.1 christos 445 1.2 christos if (operation == SMIME_ENCRYPT) { 446 1.2 christos if (cipher == NULL) { 447 1.1 christos #ifndef OPENSSL_NO_DES 448 1.2 christos cipher = (EVP_CIPHER *)EVP_des_ede3_cbc(); 449 1.1 christos #else 450 1.2 christos BIO_printf(bio_err, "No cipher selected\n"); 451 1.2 christos goto end; 452 1.1 christos #endif 453 1.2 christos } 454 1.2 christos encerts = sk_X509_new_null(); 455 1.2 christos if (encerts == NULL) 456 1.2 christos goto end; 457 1.2 christos while (*argv != NULL) { 458 1.2 christos cert = load_cert(*argv, FORMAT_UNDEF, 459 1.2 christos "recipient certificate file"); 460 1.2 christos if (cert == NULL) 461 1.2 christos goto end; 462 1.2 christos if (!sk_X509_push(encerts, cert)) 463 1.2 christos goto end; 464 1.2 christos cert = NULL; 465 1.2 christos argv++; 466 1.2 christos } 467 1.2 christos } 468 1.2 christos 469 1.2 christos if (certfile != NULL) { 470 1.2 christos if (!load_certs(certfile, 0, &other, NULL, "certificates")) { 471 1.2 christos ERR_print_errors(bio_err); 472 1.2 christos goto end; 473 1.2 christos } 474 1.2 christos } 475 1.2 christos 476 1.2 christos if (recipfile != NULL && (operation == SMIME_DECRYPT)) { 477 1.2 christos if ((recip = load_cert(recipfile, FORMAT_UNDEF, 478 1.2 christos "recipient certificate file")) == NULL) { 479 1.2 christos ERR_print_errors(bio_err); 480 1.2 christos goto end; 481 1.2 christos } 482 1.2 christos } 483 1.2 christos 484 1.2 christos if (operation == SMIME_DECRYPT) { 485 1.2 christos if (keyfile == NULL) 486 1.2 christos keyfile = recipfile; 487 1.2 christos } else if (operation == SMIME_SIGN) { 488 1.2 christos if (keyfile == NULL) 489 1.2 christos keyfile = signerfile; 490 1.2 christos } else { 491 1.2 christos keyfile = NULL; 492 1.2 christos } 493 1.2 christos 494 1.2 christos if (keyfile != NULL) { 495 1.2 christos key = load_key(keyfile, keyform, 0, passin, e, "signing key"); 496 1.2 christos if (key == NULL) 497 1.2 christos goto end; 498 1.2 christos } 499 1.2 christos 500 1.2 christos in = bio_open_default(infile, 'r', informat); 501 1.2 christos if (in == NULL) 502 1.2 christos goto end; 503 1.2 christos 504 1.2 christos if (operation & SMIME_IP) { 505 1.2 christos PKCS7 *p7_in = NULL; 506 1.2 christos 507 1.2 christos p7 = PKCS7_new_ex(libctx, app_get0_propq()); 508 1.2 christos if (p7 == NULL) { 509 1.2 christos BIO_printf(bio_err, "Error allocating PKCS7 object\n"); 510 1.2 christos goto end; 511 1.2 christos } 512 1.2 christos if (informat == FORMAT_SMIME) { 513 1.2 christos p7_in = SMIME_read_PKCS7_ex(in, &indata, &p7); 514 1.2 christos } else if (informat == FORMAT_PEM) { 515 1.2 christos p7_in = PEM_read_bio_PKCS7(in, &p7, NULL, NULL); 516 1.2 christos } else if (informat == FORMAT_ASN1) { 517 1.2 christos p7_in = d2i_PKCS7_bio(in, &p7); 518 1.2 christos } else { 519 1.2 christos BIO_printf(bio_err, "Bad input format for PKCS#7 file\n"); 520 1.2 christos goto end; 521 1.2 christos } 522 1.2 christos 523 1.2 christos if (p7_in == NULL) { 524 1.2 christos BIO_printf(bio_err, "Error reading S/MIME message\n"); 525 1.2 christos goto end; 526 1.2 christos } 527 1.2 christos if (contfile != NULL) { 528 1.2 christos BIO_free(indata); 529 1.2 christos if ((indata = BIO_new_file(contfile, "rb")) == NULL) { 530 1.2 christos BIO_printf(bio_err, "Can't read content file %s\n", contfile); 531 1.2 christos goto end; 532 1.2 christos } 533 1.2 christos } 534 1.2 christos } 535 1.2 christos 536 1.2 christos out = bio_open_default(outfile, 'w', outformat); 537 1.2 christos if (out == NULL) 538 1.2 christos goto end; 539 1.2 christos 540 1.2 christos if (operation == SMIME_VERIFY) { 541 1.2 christos if ((store = setup_verify(CAfile, noCAfile, CApath, noCApath, 542 1.2 christos CAstore, noCAstore)) == NULL) 543 1.2 christos goto end; 544 1.2 christos X509_STORE_set_verify_cb(store, smime_cb); 545 1.2 christos if (vpmtouched) 546 1.2 christos X509_STORE_set1_param(store, vpm); 547 1.2 christos } 548 1.2 christos 549 1.2 christos ret = 3; 550 1.2 christos 551 1.2 christos if (operation == SMIME_ENCRYPT) { 552 1.2 christos if (indef) 553 1.2 christos flags |= PKCS7_STREAM; 554 1.2 christos p7 = PKCS7_encrypt_ex(encerts, in, cipher, flags, libctx, app_get0_propq()); 555 1.2 christos } else if (operation & SMIME_SIGNERS) { 556 1.2 christos int i; 557 1.2 christos /* 558 1.2 christos * If detached data content we only enable streaming if S/MIME output 559 1.2 christos * format. 560 1.2 christos */ 561 1.2 christos if (operation == SMIME_SIGN) { 562 1.2 christos if (flags & PKCS7_DETACHED) { 563 1.2 christos if (outformat == FORMAT_SMIME) 564 1.2 christos flags |= PKCS7_STREAM; 565 1.2 christos } else if (indef) { 566 1.2 christos flags |= PKCS7_STREAM; 567 1.2 christos } 568 1.2 christos flags |= PKCS7_PARTIAL; 569 1.2 christos p7 = PKCS7_sign_ex(NULL, NULL, other, in, flags, libctx, app_get0_propq()); 570 1.2 christos if (p7 == NULL) 571 1.2 christos goto end; 572 1.2 christos if (flags & PKCS7_NOCERTS) { 573 1.2 christos for (i = 0; i < sk_X509_num(other); i++) { 574 1.2 christos X509 *x = sk_X509_value(other, i); 575 1.2 christos PKCS7_add_certificate(p7, x); 576 1.2 christos } 577 1.2 christos } 578 1.2 christos } else { 579 1.2 christos flags |= PKCS7_REUSE_DIGEST; 580 1.2 christos } 581 1.2 christos for (i = 0; i < sk_OPENSSL_STRING_num(sksigners); i++) { 582 1.2 christos signerfile = sk_OPENSSL_STRING_value(sksigners, i); 583 1.2 christos keyfile = sk_OPENSSL_STRING_value(skkeys, i); 584 1.2 christos signer = load_cert(signerfile, FORMAT_UNDEF, "signer certificate"); 585 1.2 christos if (signer == NULL) 586 1.2 christos goto end; 587 1.2 christos key = load_key(keyfile, keyform, 0, passin, e, "signing key"); 588 1.2 christos if (key == NULL) 589 1.2 christos goto end; 590 1.2 christos 591 1.2 christos if (!PKCS7_sign_add_signer(p7, signer, key, sign_md, flags)) 592 1.2 christos goto end; 593 1.2 christos X509_free(signer); 594 1.2 christos signer = NULL; 595 1.2 christos EVP_PKEY_free(key); 596 1.2 christos key = NULL; 597 1.2 christos } 598 1.2 christos /* If not streaming or resigning finalize structure */ 599 1.2 christos if ((operation == SMIME_SIGN) && !(flags & PKCS7_STREAM)) { 600 1.2 christos if (!PKCS7_final(p7, in, flags)) 601 1.2 christos goto end; 602 1.2 christos } 603 1.2 christos } 604 1.2 christos 605 1.2 christos if (p7 == NULL) { 606 1.2 christos BIO_printf(bio_err, "Error creating PKCS#7 structure\n"); 607 1.2 christos goto end; 608 1.2 christos } 609 1.2 christos 610 1.2 christos ret = 4; 611 1.2 christos if (operation == SMIME_DECRYPT) { 612 1.2 christos if (!PKCS7_decrypt(p7, key, recip, out, flags)) { 613 1.2 christos BIO_printf(bio_err, "Error decrypting PKCS#7 structure\n"); 614 1.2 christos goto end; 615 1.2 christos } 616 1.2 christos } else if (operation == SMIME_VERIFY) { 617 1.2 christos STACK_OF(X509) *signers; 618 1.2 christos if (PKCS7_verify(p7, other, store, indata, out, flags)) 619 1.2 christos BIO_printf(bio_err, "Verification successful\n"); 620 1.2 christos else { 621 1.2 christos BIO_printf(bio_err, "Verification failure\n"); 622 1.2 christos goto end; 623 1.2 christos } 624 1.2 christos signers = PKCS7_get0_signers(p7, other, flags); 625 1.2 christos if (!save_certs(signerfile, signers)) { 626 1.2 christos BIO_printf(bio_err, "Error writing signers to %s\n", signerfile); 627 1.2 christos ret = 5; 628 1.2 christos goto end; 629 1.2 christos } 630 1.2 christos sk_X509_free(signers); 631 1.2 christos } else if (operation == SMIME_PK7OUT) { 632 1.2 christos PEM_write_bio_PKCS7(out, p7); 633 1.2 christos } else { 634 1.2 christos if (to) 635 1.2 christos BIO_printf(out, "To: %s%s", to, mime_eol); 636 1.2 christos if (from) 637 1.2 christos BIO_printf(out, "From: %s%s", from, mime_eol); 638 1.2 christos if (subject) 639 1.2 christos BIO_printf(out, "Subject: %s%s", subject, mime_eol); 640 1.2 christos if (outformat == FORMAT_SMIME) { 641 1.2 christos if (operation == SMIME_RESIGN) 642 1.2 christos rv = SMIME_write_PKCS7(out, p7, indata, flags); 643 1.2 christos else 644 1.2 christos rv = SMIME_write_PKCS7(out, p7, in, flags); 645 1.2 christos } else if (outformat == FORMAT_PEM) { 646 1.2 christos rv = PEM_write_bio_PKCS7_stream(out, p7, in, flags); 647 1.2 christos } else if (outformat == FORMAT_ASN1) { 648 1.2 christos rv = i2d_PKCS7_bio_stream(out, p7, in, flags); 649 1.2 christos } else { 650 1.2 christos BIO_printf(bio_err, "Bad output format for PKCS#7 file\n"); 651 1.2 christos goto end; 652 1.2 christos } 653 1.2 christos if (rv == 0) { 654 1.2 christos BIO_printf(bio_err, "Error writing output\n"); 655 1.2 christos ret = 3; 656 1.2 christos goto end; 657 1.2 christos } 658 1.2 christos } 659 1.2 christos ret = 0; 660 1.2 christos end: 661 1.2 christos if (ret) 662 1.2 christos ERR_print_errors(bio_err); 663 1.2 christos sk_X509_pop_free(encerts, X509_free); 664 1.2 christos sk_X509_pop_free(other, X509_free); 665 1.2 christos X509_VERIFY_PARAM_free(vpm); 666 1.2 christos sk_OPENSSL_STRING_free(sksigners); 667 1.2 christos sk_OPENSSL_STRING_free(skkeys); 668 1.2 christos X509_STORE_free(store); 669 1.2 christos X509_free(cert); 670 1.2 christos X509_free(recip); 671 1.2 christos X509_free(signer); 672 1.2 christos EVP_PKEY_free(key); 673 1.2 christos EVP_MD_free(sign_md); 674 1.2 christos EVP_CIPHER_free(cipher); 675 1.2 christos PKCS7_free(p7); 676 1.2 christos release_engine(e); 677 1.2 christos BIO_free(in); 678 1.2 christos BIO_free(indata); 679 1.2 christos BIO_free_all(out); 680 1.2 christos OPENSSL_free(passin); 681 1.2 christos NCONF_free(conf); 682 1.2 christos return ret; 683 1.1 christos } 684 1.1 christos 685 1.1 christos static int save_certs(char *signerfile, STACK_OF(X509) *signers) 686 1.2 christos { 687 1.2 christos int i; 688 1.2 christos BIO *tmp; 689 1.2 christos 690 1.2 christos if (signerfile == NULL) 691 1.2 christos return 1; 692 1.2 christos tmp = BIO_new_file(signerfile, "w"); 693 1.2 christos if (tmp == NULL) 694 1.2 christos return 0; 695 1.2 christos for (i = 0; i < sk_X509_num(signers); i++) 696 1.2 christos PEM_write_bio_X509(tmp, sk_X509_value(signers, i)); 697 1.2 christos BIO_free(tmp); 698 1.2 christos return 1; 699 1.2 christos } 700 1.1 christos 701 1.1 christos /* Minimal callback just to output policy info (if any) */ 702 1.1 christos 703 1.1 christos static int smime_cb(int ok, X509_STORE_CTX *ctx) 704 1.2 christos { 705 1.2 christos int error; 706 1.1 christos 707 1.2 christos error = X509_STORE_CTX_get_error(ctx); 708 1.1 christos 709 1.2 christos if ((error != X509_V_ERR_NO_EXPLICIT_POLICY) 710 1.2 christos && ((error != X509_V_OK) || (ok != 2))) 711 1.2 christos return ok; 712 1.1 christos 713 1.2 christos policies_print(ctx); 714 1.1 christos 715 1.2 christos return ok; 716 1.2 christos } 717