1 /* smime.c */ 2 /* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL 3 * project 1999. 4 */ 5 /* ==================================================================== 6 * Copyright (c) 1999 The OpenSSL Project. All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in 17 * the documentation and/or other materials provided with the 18 * distribution. 19 * 20 * 3. All advertising materials mentioning features or use of this 21 * software must display the following acknowledgment: 22 * "This product includes software developed by the OpenSSL Project 23 * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" 24 * 25 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 26 * endorse or promote products derived from this software without 27 * prior written permission. For written permission, please contact 28 * licensing@OpenSSL.org. 29 * 30 * 5. Products derived from this software may not be called "OpenSSL" 31 * nor may "OpenSSL" appear in their names without prior written 32 * permission of the OpenSSL Project. 33 * 34 * 6. Redistributions of any form whatsoever must retain the following 35 * acknowledgment: 36 * "This product includes software developed by the OpenSSL Project 37 * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" 38 * 39 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 40 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 41 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 42 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 43 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 44 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 45 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 46 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 47 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 48 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 49 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 50 * OF THE POSSIBILITY OF SUCH DAMAGE. 51 * ==================================================================== 52 * 53 * This product includes cryptographic software written by Eric Young 54 * (eay@cryptsoft.com). This product includes software written by Tim 55 * Hudson (tjh@cryptsoft.com). 56 * 57 */ 58 59 /* S/MIME utility function */ 60 61 #include <stdio.h> 62 #include <string.h> 63 #include "apps.h" 64 #include <openssl/crypto.h> 65 #include <openssl/pem.h> 66 #include <openssl/err.h> 67 68 #undef PROG 69 #define PROG smime_main 70 static int save_certs(char *signerfile, STACK_OF(X509) *signers); 71 72 #define SMIME_OP 0x10 73 #define SMIME_ENCRYPT (1 | SMIME_OP) 74 #define SMIME_DECRYPT 2 75 #define SMIME_SIGN (3 | SMIME_OP) 76 #define SMIME_VERIFY 4 77 #define SMIME_PK7OUT 5 78 79 int MAIN(int, char **); 80 81 int MAIN(int argc, char **argv) 82 { 83 ENGINE *e = NULL; 84 int operation = 0; 85 int ret = 0; 86 char **args; 87 char *inmode = "r", *outmode = "w"; 88 char *infile = NULL, *outfile = NULL; 89 char *signerfile = NULL, *recipfile = NULL; 90 char *certfile = NULL, *keyfile = NULL, *contfile=NULL; 91 const EVP_CIPHER *cipher = NULL; 92 PKCS7 *p7 = NULL; 93 X509_STORE *store = NULL; 94 X509 *cert = NULL, *recip = NULL, *signer = NULL; 95 EVP_PKEY *key = NULL; 96 STACK_OF(X509) *encerts = NULL, *other = NULL; 97 BIO *in = NULL, *out = NULL, *indata = NULL; 98 int badarg = 0; 99 int flags = PKCS7_DETACHED, store_flags = 0; 100 char *to = NULL, *from = NULL, *subject = NULL; 101 char *CAfile = NULL, *CApath = NULL; 102 char *passargin = NULL, *passin = NULL; 103 char *inrand = NULL; 104 int need_rand = 0; 105 int informat = FORMAT_SMIME, outformat = FORMAT_SMIME; 106 int keyform = FORMAT_PEM; 107 char *engine=NULL; 108 109 args = argv + 1; 110 ret = 1; 111 112 apps_startup(); 113 114 if (bio_err == NULL) 115 if ((bio_err = BIO_new(BIO_s_file())) != NULL) 116 BIO_set_fp(bio_err, stderr, BIO_NOCLOSE|BIO_FP_TEXT); 117 118 if (!load_config(bio_err, NULL)) 119 goto end; 120 121 while (!badarg && *args && *args[0] == '-') { 122 if (!strcmp (*args, "-encrypt")) operation = SMIME_ENCRYPT; 123 else if (!strcmp (*args, "-decrypt")) operation = SMIME_DECRYPT; 124 else if (!strcmp (*args, "-sign")) operation = SMIME_SIGN; 125 else if (!strcmp (*args, "-verify")) operation = SMIME_VERIFY; 126 else if (!strcmp (*args, "-pk7out")) operation = SMIME_PK7OUT; 127 #ifndef OPENSSL_NO_DES 128 else if (!strcmp (*args, "-des3")) 129 cipher = EVP_des_ede3_cbc(); 130 else if (!strcmp (*args, "-des")) 131 cipher = EVP_des_cbc(); 132 #endif 133 #ifndef OPENSSL_NO_RC2 134 else if (!strcmp (*args, "-rc2-40")) 135 cipher = EVP_rc2_40_cbc(); 136 else if (!strcmp (*args, "-rc2-128")) 137 cipher = EVP_rc2_cbc(); 138 else if (!strcmp (*args, "-rc2-64")) 139 cipher = EVP_rc2_64_cbc(); 140 #endif 141 #ifndef OPENSSL_NO_AES 142 else if (!strcmp(*args,"-aes128")) 143 cipher = EVP_aes_128_cbc(); 144 else if (!strcmp(*args,"-aes192")) 145 cipher = EVP_aes_192_cbc(); 146 else if (!strcmp(*args,"-aes256")) 147 cipher = EVP_aes_256_cbc(); 148 #endif 149 else if (!strcmp (*args, "-text")) 150 flags |= PKCS7_TEXT; 151 else if (!strcmp (*args, "-nointern")) 152 flags |= PKCS7_NOINTERN; 153 else if (!strcmp (*args, "-noverify")) 154 flags |= PKCS7_NOVERIFY; 155 else if (!strcmp (*args, "-nochain")) 156 flags |= PKCS7_NOCHAIN; 157 else if (!strcmp (*args, "-nocerts")) 158 flags |= PKCS7_NOCERTS; 159 else if (!strcmp (*args, "-noattr")) 160 flags |= PKCS7_NOATTR; 161 else if (!strcmp (*args, "-nodetach")) 162 flags &= ~PKCS7_DETACHED; 163 else if (!strcmp (*args, "-nosmimecap")) 164 flags |= PKCS7_NOSMIMECAP; 165 else if (!strcmp (*args, "-binary")) 166 flags |= PKCS7_BINARY; 167 else if (!strcmp (*args, "-nosigs")) 168 flags |= PKCS7_NOSIGS; 169 else if (!strcmp (*args, "-crl_check")) 170 store_flags |= X509_V_FLAG_CRL_CHECK; 171 else if (!strcmp (*args, "-crl_check_all")) 172 store_flags |= X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL; 173 else if (!strcmp(*args,"-rand")) { 174 if (args[1]) { 175 args++; 176 inrand = *args; 177 } else badarg = 1; 178 need_rand = 1; 179 } else if (!strcmp(*args,"-engine")) { 180 if (args[1]) { 181 args++; 182 engine = *args; 183 } else badarg = 1; 184 } else if (!strcmp(*args,"-passin")) { 185 if (args[1]) { 186 args++; 187 passargin = *args; 188 } else badarg = 1; 189 } else if (!strcmp (*args, "-to")) { 190 if (args[1]) { 191 args++; 192 to = *args; 193 } else badarg = 1; 194 } else if (!strcmp (*args, "-from")) { 195 if (args[1]) { 196 args++; 197 from = *args; 198 } else badarg = 1; 199 } else if (!strcmp (*args, "-subject")) { 200 if (args[1]) { 201 args++; 202 subject = *args; 203 } else badarg = 1; 204 } else if (!strcmp (*args, "-signer")) { 205 if (args[1]) { 206 args++; 207 signerfile = *args; 208 } else badarg = 1; 209 } else if (!strcmp (*args, "-recip")) { 210 if (args[1]) { 211 args++; 212 recipfile = *args; 213 } else badarg = 1; 214 } else if (!strcmp (*args, "-inkey")) { 215 if (args[1]) { 216 args++; 217 keyfile = *args; 218 } else badarg = 1; 219 } else if (!strcmp (*args, "-keyform")) { 220 if (args[1]) { 221 args++; 222 keyform = str2fmt(*args); 223 } else badarg = 1; 224 } else if (!strcmp (*args, "-certfile")) { 225 if (args[1]) { 226 args++; 227 certfile = *args; 228 } else badarg = 1; 229 } else if (!strcmp (*args, "-CAfile")) { 230 if (args[1]) { 231 args++; 232 CAfile = *args; 233 } else badarg = 1; 234 } else if (!strcmp (*args, "-CApath")) { 235 if (args[1]) { 236 args++; 237 CApath = *args; 238 } else badarg = 1; 239 } else if (!strcmp (*args, "-in")) { 240 if (args[1]) { 241 args++; 242 infile = *args; 243 } else badarg = 1; 244 } else if (!strcmp (*args, "-inform")) { 245 if (args[1]) { 246 args++; 247 informat = str2fmt(*args); 248 } else badarg = 1; 249 } else if (!strcmp (*args, "-outform")) { 250 if (args[1]) { 251 args++; 252 outformat = str2fmt(*args); 253 } else badarg = 1; 254 } else if (!strcmp (*args, "-out")) { 255 if (args[1]) { 256 args++; 257 outfile = *args; 258 } else badarg = 1; 259 } else if (!strcmp (*args, "-content")) { 260 if (args[1]) { 261 args++; 262 contfile = *args; 263 } else badarg = 1; 264 } else badarg = 1; 265 args++; 266 } 267 268 if(operation == SMIME_SIGN) { 269 if(!signerfile) { 270 BIO_printf(bio_err, "No signer certificate specified\n"); 271 badarg = 1; 272 } 273 need_rand = 1; 274 } else if(operation == SMIME_DECRYPT) { 275 if(!recipfile) { 276 BIO_printf(bio_err, "No recipient certificate and key specified\n"); 277 badarg = 1; 278 } 279 } else if(operation == SMIME_ENCRYPT) { 280 if(!*args) { 281 BIO_printf(bio_err, "No recipient(s) certificate(s) specified\n"); 282 badarg = 1; 283 } 284 need_rand = 1; 285 } else if(!operation) badarg = 1; 286 287 if (badarg) { 288 BIO_printf (bio_err, "Usage smime [options] cert.pem ...\n"); 289 BIO_printf (bio_err, "where options are\n"); 290 BIO_printf (bio_err, "-encrypt encrypt message\n"); 291 BIO_printf (bio_err, "-decrypt decrypt encrypted message\n"); 292 BIO_printf (bio_err, "-sign sign message\n"); 293 BIO_printf (bio_err, "-verify verify signed message\n"); 294 BIO_printf (bio_err, "-pk7out output PKCS#7 structure\n"); 295 #ifndef OPENSSL_NO_DES 296 BIO_printf (bio_err, "-des3 encrypt with triple DES\n"); 297 BIO_printf (bio_err, "-des encrypt with DES\n"); 298 #endif 299 #ifndef OPENSSL_NO_RC2 300 BIO_printf (bio_err, "-rc2-40 encrypt with RC2-40 (default)\n"); 301 BIO_printf (bio_err, "-rc2-64 encrypt with RC2-64\n"); 302 BIO_printf (bio_err, "-rc2-128 encrypt with RC2-128\n"); 303 #endif 304 #ifndef OPENSSL_NO_AES 305 BIO_printf (bio_err, "-aes128, -aes192, -aes256\n"); 306 BIO_printf (bio_err, " encrypt PEM output with cbc aes\n"); 307 #endif 308 BIO_printf (bio_err, "-nointern don't search certificates in message for signer\n"); 309 BIO_printf (bio_err, "-nosigs don't verify message signature\n"); 310 BIO_printf (bio_err, "-noverify don't verify signers certificate\n"); 311 BIO_printf (bio_err, "-nocerts don't include signers certificate when signing\n"); 312 BIO_printf (bio_err, "-nodetach use opaque signing\n"); 313 BIO_printf (bio_err, "-noattr don't include any signed attributes\n"); 314 BIO_printf (bio_err, "-binary don't translate message to text\n"); 315 BIO_printf (bio_err, "-certfile file other certificates file\n"); 316 BIO_printf (bio_err, "-signer file signer certificate file\n"); 317 BIO_printf (bio_err, "-recip file recipient certificate file for decryption\n"); 318 BIO_printf (bio_err, "-in file input file\n"); 319 BIO_printf (bio_err, "-inform arg input format SMIME (default), PEM or DER\n"); 320 BIO_printf (bio_err, "-inkey file input private key (if not signer or recipient)\n"); 321 BIO_printf (bio_err, "-keyform arg input private key format (PEM or ENGINE)\n"); 322 BIO_printf (bio_err, "-out file output file\n"); 323 BIO_printf (bio_err, "-outform arg output format SMIME (default), PEM or DER\n"); 324 BIO_printf (bio_err, "-content file supply or override content for detached signature\n"); 325 BIO_printf (bio_err, "-to addr to address\n"); 326 BIO_printf (bio_err, "-from ad from address\n"); 327 BIO_printf (bio_err, "-subject s subject\n"); 328 BIO_printf (bio_err, "-text include or delete text MIME headers\n"); 329 BIO_printf (bio_err, "-CApath dir trusted certificates directory\n"); 330 BIO_printf (bio_err, "-CAfile file trusted certificates file\n"); 331 BIO_printf (bio_err, "-crl_check check revocation status of signer's certificate using CRLs\n"); 332 BIO_printf (bio_err, "-crl_check_all check revocation status of signer's certificate chain using CRLs\n"); 333 BIO_printf (bio_err, "-engine e use engine e, possibly a hardware device.\n"); 334 BIO_printf (bio_err, "-passin arg input file pass phrase source\n"); 335 BIO_printf(bio_err, "-rand file%cfile%c...\n", LIST_SEPARATOR_CHAR, LIST_SEPARATOR_CHAR); 336 BIO_printf(bio_err, " load the file (or the files in the directory) into\n"); 337 BIO_printf(bio_err, " the random number generator\n"); 338 BIO_printf (bio_err, "cert.pem recipient certificate(s) for encryption\n"); 339 goto end; 340 } 341 342 e = setup_engine(bio_err, engine, 0); 343 344 if(!app_passwd(bio_err, passargin, NULL, &passin, NULL)) { 345 BIO_printf(bio_err, "Error getting password\n"); 346 goto end; 347 } 348 349 if (need_rand) { 350 app_RAND_load_file(NULL, bio_err, (inrand != NULL)); 351 if (inrand != NULL) 352 BIO_printf(bio_err,"%ld semi-random bytes loaded\n", 353 app_RAND_load_files(inrand)); 354 } 355 356 ret = 2; 357 358 if(operation != SMIME_SIGN) flags &= ~PKCS7_DETACHED; 359 360 if(operation & SMIME_OP) { 361 if(flags & PKCS7_BINARY) inmode = "rb"; 362 if(outformat == FORMAT_ASN1) outmode = "wb"; 363 } else { 364 if(flags & PKCS7_BINARY) outmode = "wb"; 365 if(informat == FORMAT_ASN1) inmode = "rb"; 366 } 367 368 if(operation == SMIME_ENCRYPT) { 369 if (!cipher) { 370 #ifndef OPENSSL_NO_RC2 371 cipher = EVP_rc2_40_cbc(); 372 #else 373 BIO_printf(bio_err, "No cipher selected\n"); 374 goto end; 375 #endif 376 } 377 encerts = sk_X509_new_null(); 378 while (*args) { 379 if(!(cert = load_cert(bio_err,*args,FORMAT_PEM, 380 NULL, e, "recipient certificate file"))) { 381 #if 0 /* An appropriate message is already printed */ 382 BIO_printf(bio_err, "Can't read recipient certificate file %s\n", *args); 383 #endif 384 goto end; 385 } 386 sk_X509_push(encerts, cert); 387 cert = NULL; 388 args++; 389 } 390 } 391 392 if(signerfile && (operation == SMIME_SIGN)) { 393 if(!(signer = load_cert(bio_err,signerfile,FORMAT_PEM, NULL, 394 e, "signer certificate"))) { 395 #if 0 /* An appropri message has already been printed */ 396 BIO_printf(bio_err, "Can't read signer certificate file %s\n", signerfile); 397 #endif 398 goto end; 399 } 400 } 401 402 if(certfile) { 403 if(!(other = load_certs(bio_err,certfile,FORMAT_PEM, NULL, 404 e, "certificate file"))) { 405 #if 0 /* An appropriate message has already been printed */ 406 BIO_printf(bio_err, "Can't read certificate file %s\n", certfile); 407 #endif 408 ERR_print_errors(bio_err); 409 goto end; 410 } 411 } 412 413 if(recipfile && (operation == SMIME_DECRYPT)) { 414 if(!(recip = load_cert(bio_err,recipfile,FORMAT_PEM,NULL, 415 e, "recipient certificate file"))) { 416 #if 0 /* An appropriate message has alrady been printed */ 417 BIO_printf(bio_err, "Can't read recipient certificate file %s\n", recipfile); 418 #endif 419 ERR_print_errors(bio_err); 420 goto end; 421 } 422 } 423 424 if(operation == SMIME_DECRYPT) { 425 if(!keyfile) keyfile = recipfile; 426 } else if(operation == SMIME_SIGN) { 427 if(!keyfile) keyfile = signerfile; 428 } else keyfile = NULL; 429 430 if(keyfile) { 431 key = load_key(bio_err, keyfile, keyform, 0, passin, e, 432 "signing key file"); 433 if (!key) { 434 goto end; 435 } 436 } 437 438 if (infile) { 439 if (!(in = BIO_new_file(infile, inmode))) { 440 BIO_printf (bio_err, 441 "Can't open input file %s\n", infile); 442 goto end; 443 } 444 } else in = BIO_new_fp(stdin, BIO_NOCLOSE); 445 446 if (outfile) { 447 if (!(out = BIO_new_file(outfile, outmode))) { 448 BIO_printf (bio_err, 449 "Can't open output file %s\n", outfile); 450 goto end; 451 } 452 } else { 453 out = BIO_new_fp(stdout, BIO_NOCLOSE); 454 #ifdef OPENSSL_SYS_VMS 455 { 456 BIO *tmpbio = BIO_new(BIO_f_linebuffer()); 457 out = BIO_push(tmpbio, out); 458 } 459 #endif 460 } 461 462 if(operation == SMIME_VERIFY) { 463 if(!(store = setup_verify(bio_err, CAfile, CApath))) goto end; 464 X509_STORE_set_flags(store, store_flags); 465 } 466 467 468 ret = 3; 469 470 if(operation == SMIME_ENCRYPT) { 471 p7 = PKCS7_encrypt(encerts, in, cipher, flags); 472 } else if(operation == SMIME_SIGN) { 473 p7 = PKCS7_sign(signer, key, other, in, flags); 474 if (BIO_reset(in) != 0 && (flags & PKCS7_DETACHED)) { 475 BIO_printf(bio_err, "Can't rewind input file\n"); 476 goto end; 477 } 478 } else { 479 if(informat == FORMAT_SMIME) 480 p7 = SMIME_read_PKCS7(in, &indata); 481 else if(informat == FORMAT_PEM) 482 p7 = PEM_read_bio_PKCS7(in, NULL, NULL, NULL); 483 else if(informat == FORMAT_ASN1) 484 p7 = d2i_PKCS7_bio(in, NULL); 485 else { 486 BIO_printf(bio_err, "Bad input format for PKCS#7 file\n"); 487 goto end; 488 } 489 490 if(!p7) { 491 BIO_printf(bio_err, "Error reading S/MIME message\n"); 492 goto end; 493 } 494 if(contfile) { 495 BIO_free(indata); 496 if(!(indata = BIO_new_file(contfile, "rb"))) { 497 BIO_printf(bio_err, "Can't read content file %s\n", contfile); 498 goto end; 499 } 500 } 501 } 502 503 if(!p7) { 504 BIO_printf(bio_err, "Error creating PKCS#7 structure\n"); 505 goto end; 506 } 507 508 ret = 4; 509 if(operation == SMIME_DECRYPT) { 510 if(!PKCS7_decrypt(p7, key, recip, out, flags)) { 511 BIO_printf(bio_err, "Error decrypting PKCS#7 structure\n"); 512 goto end; 513 } 514 } else if(operation == SMIME_VERIFY) { 515 STACK_OF(X509) *signers; 516 if(PKCS7_verify(p7, other, store, indata, out, flags)) { 517 BIO_printf(bio_err, "Verification successful\n"); 518 } else { 519 BIO_printf(bio_err, "Verification failure\n"); 520 goto end; 521 } 522 signers = PKCS7_get0_signers(p7, other, flags); 523 if(!save_certs(signerfile, signers)) { 524 BIO_printf(bio_err, "Error writing signers to %s\n", 525 signerfile); 526 ret = 5; 527 goto end; 528 } 529 sk_X509_free(signers); 530 } else if(operation == SMIME_PK7OUT) { 531 PEM_write_bio_PKCS7(out, p7); 532 } else { 533 if(to) BIO_printf(out, "To: %s\n", to); 534 if(from) BIO_printf(out, "From: %s\n", from); 535 if(subject) BIO_printf(out, "Subject: %s\n", subject); 536 if(outformat == FORMAT_SMIME) 537 SMIME_write_PKCS7(out, p7, in, flags); 538 else if(outformat == FORMAT_PEM) 539 PEM_write_bio_PKCS7(out,p7); 540 else if(outformat == FORMAT_ASN1) 541 i2d_PKCS7_bio(out,p7); 542 else { 543 BIO_printf(bio_err, "Bad output format for PKCS#7 file\n"); 544 goto end; 545 } 546 } 547 ret = 0; 548 end: 549 if (need_rand) 550 app_RAND_write_file(NULL, bio_err); 551 if(ret) ERR_print_errors(bio_err); 552 sk_X509_pop_free(encerts, X509_free); 553 sk_X509_pop_free(other, X509_free); 554 X509_STORE_free(store); 555 X509_free(cert); 556 X509_free(recip); 557 X509_free(signer); 558 EVP_PKEY_free(key); 559 PKCS7_free(p7); 560 BIO_free(in); 561 BIO_free(indata); 562 BIO_free_all(out); 563 if(passin) OPENSSL_free(passin); 564 return (ret); 565 } 566 567 static int save_certs(char *signerfile, STACK_OF(X509) *signers) 568 { 569 int i; 570 BIO *tmp; 571 if(!signerfile) return 1; 572 tmp = BIO_new_file(signerfile, "w"); 573 if(!tmp) return 0; 574 for(i = 0; i < sk_X509_num(signers); i++) 575 PEM_write_bio_X509(tmp, sk_X509_value(signers, i)); 576 BIO_free(tmp); 577 return 1; 578 } 579 580