1 /* 2 * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project 3 * 2006. 4 */ 5 /* ==================================================================== 6 * Copyright (c) 2006 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 #include "apps.h" 60 #include <string.h> 61 #include <openssl/err.h> 62 #include <openssl/pem.h> 63 #include <openssl/evp.h> 64 65 #define KEY_PRIVKEY 1 66 #define KEY_PUBKEY 2 67 #define KEY_CERT 3 68 69 static void usage(void); 70 71 #undef PROG 72 73 #define PROG pkeyutl_main 74 75 static EVP_PKEY_CTX *init_ctx(int *pkeysize, 76 const char *keyfile, int keyform, int key_type, 77 char *passargin, int pkey_op, ENGINE *e, 78 int impl); 79 80 static int setup_peer(BIO *err, EVP_PKEY_CTX *ctx, int peerform, 81 const char *file, ENGINE* e); 82 83 static int do_keyop(EVP_PKEY_CTX *ctx, int pkey_op, 84 unsigned char *out, size_t *poutlen, 85 unsigned char *in, size_t inlen); 86 87 int MAIN(int argc, char **); 88 89 int MAIN(int argc, char **argv) 90 { 91 BIO *in = NULL, *out = NULL; 92 char *infile = NULL, *outfile = NULL, *sigfile = NULL; 93 ENGINE *e = NULL; 94 int pkey_op = EVP_PKEY_OP_SIGN, key_type = KEY_PRIVKEY; 95 int keyform = FORMAT_PEM, peerform = FORMAT_PEM; 96 char badarg = 0, rev = 0; 97 char hexdump = 0, asn1parse = 0; 98 EVP_PKEY_CTX *ctx = NULL; 99 char *passargin = NULL; 100 int keysize = -1; 101 int engine_impl = 0; 102 unsigned char *buf_in = NULL, *buf_out = NULL, *sig = NULL; 103 size_t buf_outlen = 0; 104 int buf_inlen = 0, siglen = -1; 105 const char *inkey = NULL; 106 const char *peerkey = NULL; 107 STACK_OF(OPENSSL_STRING) *pkeyopts = NULL; 108 109 int ret = 1, rv = -1; 110 111 argc--; 112 argv++; 113 114 if (!bio_err) 115 bio_err = BIO_new_fp(stderr, BIO_NOCLOSE); 116 117 if (!load_config(bio_err, NULL)) 118 goto end; 119 ERR_load_crypto_strings(); 120 OpenSSL_add_all_algorithms(); 121 122 while (argc >= 1) { 123 if (!strcmp(*argv, "-in")) { 124 if (--argc < 1) 125 badarg = 1; 126 else 127 infile = *(++argv); 128 } else if (!strcmp(*argv, "-out")) { 129 if (--argc < 1) 130 badarg = 1; 131 else 132 outfile = *(++argv); 133 } else if (!strcmp(*argv, "-sigfile")) { 134 if (--argc < 1) 135 badarg = 1; 136 else 137 sigfile = *(++argv); 138 } else if (!strcmp(*argv, "-inkey")) { 139 if (--argc < 1) 140 badarg = 1; 141 else 142 inkey = *++argv; 143 } else if (!strcmp(*argv, "-peerkey")) { 144 if (--argc < 1) 145 badarg = 1; 146 else 147 peerkey = *++argv; 148 } else if (!strcmp(*argv, "-passin")) { 149 if (--argc < 1) 150 badarg = 1; 151 else 152 passargin = *(++argv); 153 } else if (strcmp(*argv, "-peerform") == 0) { 154 if (--argc < 1) 155 badarg = 1; 156 else 157 peerform = str2fmt(*(++argv)); 158 } else if (strcmp(*argv, "-keyform") == 0) { 159 if (--argc < 1) 160 badarg = 1; 161 else 162 keyform = str2fmt(*(++argv)); 163 } 164 #ifndef OPENSSL_NO_ENGINE 165 else if (!strcmp(*argv, "-engine")) { 166 if (--argc < 1) 167 badarg = 1; 168 else 169 e = setup_engine(bio_err, *(++argv), 0); 170 } else if (!strcmp(*argv, "-engine_impl")) { 171 engine_impl = 1; 172 } 173 #endif 174 else if (!strcmp(*argv, "-pubin")) 175 key_type = KEY_PUBKEY; 176 else if (!strcmp(*argv, "-certin")) 177 key_type = KEY_CERT; 178 else if (!strcmp(*argv, "-asn1parse")) 179 asn1parse = 1; 180 else if (!strcmp(*argv, "-hexdump")) 181 hexdump = 1; 182 else if (!strcmp(*argv, "-sign")) 183 pkey_op = EVP_PKEY_OP_SIGN; 184 else if (!strcmp(*argv, "-verify")) 185 pkey_op = EVP_PKEY_OP_VERIFY; 186 else if (!strcmp(*argv, "-verifyrecover")) 187 pkey_op = EVP_PKEY_OP_VERIFYRECOVER; 188 else if (!strcmp(*argv, "-encrypt")) 189 pkey_op = EVP_PKEY_OP_ENCRYPT; 190 else if (!strcmp(*argv, "-decrypt")) 191 pkey_op = EVP_PKEY_OP_DECRYPT; 192 else if (!strcmp(*argv, "-derive")) 193 pkey_op = EVP_PKEY_OP_DERIVE; 194 else if (!strcmp(*argv, "-rev")) 195 rev = 1; 196 else if (strcmp(*argv, "-pkeyopt") == 0) { 197 if (--argc < 1) 198 badarg = 1; 199 else if ((pkeyopts == NULL && 200 (pkeyopts = sk_OPENSSL_STRING_new_null()) == NULL) || 201 sk_OPENSSL_STRING_push(pkeyopts, *++argv) == 0) { 202 BIO_puts(bio_err, "out of memory\n"); 203 goto end; 204 } 205 } else 206 badarg = 1; 207 if (badarg) { 208 usage(); 209 goto end; 210 } 211 argc--; 212 argv++; 213 } 214 215 if (inkey == NULL || 216 (peerkey != NULL && pkey_op != EVP_PKEY_OP_DERIVE)) { 217 usage(); 218 goto end; 219 } 220 ctx = init_ctx(&keysize, inkey, keyform, key_type, 221 passargin, pkey_op, e, engine_impl); 222 if (!ctx) { 223 BIO_puts(bio_err, "Error initializing context\n"); 224 ERR_print_errors(bio_err); 225 goto end; 226 } 227 if (peerkey != NULL && !setup_peer(bio_err, ctx, peerform, peerkey, e)) { 228 BIO_puts(bio_err, "Error setting up peer key\n"); 229 ERR_print_errors(bio_err); 230 goto end; 231 } 232 if (pkeyopts != NULL) { 233 int num = sk_OPENSSL_STRING_num(pkeyopts); 234 int i; 235 236 for (i = 0; i < num; ++i) { 237 const char *opt = sk_OPENSSL_STRING_value(pkeyopts, i); 238 239 if (pkey_ctrl_string(ctx, opt) <= 0) { 240 BIO_puts(bio_err, "parameter setting error\n"); 241 ERR_print_errors(bio_err); 242 goto end; 243 } 244 } 245 } 246 247 if (sigfile && (pkey_op != EVP_PKEY_OP_VERIFY)) { 248 BIO_puts(bio_err, "Signature file specified for non verify\n"); 249 goto end; 250 } 251 252 if (!sigfile && (pkey_op == EVP_PKEY_OP_VERIFY)) { 253 BIO_puts(bio_err, "No signature file specified for verify\n"); 254 goto end; 255 } 256 257 /* FIXME: seed PRNG only if needed */ 258 app_RAND_load_file(NULL, bio_err, 0); 259 260 if (pkey_op != EVP_PKEY_OP_DERIVE) { 261 if (infile) { 262 if (!(in = BIO_new_file(infile, "rb"))) { 263 BIO_puts(bio_err, "Error Opening Input File\n"); 264 ERR_print_errors(bio_err); 265 goto end; 266 } 267 } else 268 in = BIO_new_fp(stdin, BIO_NOCLOSE); 269 } 270 271 if (outfile) { 272 if (!(out = BIO_new_file(outfile, "wb"))) { 273 BIO_printf(bio_err, "Error Creating Output File\n"); 274 ERR_print_errors(bio_err); 275 goto end; 276 } 277 } else { 278 out = BIO_new_fp(stdout, BIO_NOCLOSE); 279 #ifdef OPENSSL_SYS_VMS 280 { 281 BIO *tmpbio = BIO_new(BIO_f_linebuffer()); 282 out = BIO_push(tmpbio, out); 283 } 284 #endif 285 } 286 287 if (sigfile) { 288 BIO *sigbio = BIO_new_file(sigfile, "rb"); 289 if (!sigbio) { 290 BIO_printf(bio_err, "Can't open signature file %s\n", sigfile); 291 goto end; 292 } 293 siglen = bio_to_mem(&sig, keysize * 10, sigbio); 294 BIO_free(sigbio); 295 if (siglen < 0) { 296 BIO_printf(bio_err, "Error reading signature data\n"); 297 goto end; 298 } 299 } 300 301 if (in) { 302 /* Read the input data */ 303 buf_inlen = bio_to_mem(&buf_in, keysize * 10, in); 304 if (buf_inlen < 0) { 305 BIO_printf(bio_err, "Error reading input Data\n"); 306 exit(1); 307 } 308 if (rev) { 309 size_t i; 310 unsigned char ctmp; 311 size_t l = (size_t)buf_inlen; 312 for (i = 0; i < l / 2; i++) { 313 ctmp = buf_in[i]; 314 buf_in[i] = buf_in[l - 1 - i]; 315 buf_in[l - 1 - i] = ctmp; 316 } 317 } 318 } 319 320 if (pkey_op == EVP_PKEY_OP_VERIFY) { 321 rv = EVP_PKEY_verify(ctx, sig, (size_t)siglen, 322 buf_in, (size_t)buf_inlen); 323 if (rv == 0) 324 BIO_puts(out, "Signature Verification Failure\n"); 325 else if (rv == 1) { 326 BIO_puts(out, "Signature Verified Successfully\n"); 327 ret = 0; 328 } 329 if (rv >= 0) 330 goto end; 331 } else { 332 rv = do_keyop(ctx, pkey_op, NULL, (size_t *)&buf_outlen, 333 buf_in, (size_t)buf_inlen); 334 if (rv > 0 && buf_outlen != 0) { 335 buf_out = OPENSSL_malloc(buf_outlen); 336 if (!buf_out) 337 rv = -1; 338 else 339 rv = do_keyop(ctx, pkey_op, 340 buf_out, (size_t *)&buf_outlen, 341 buf_in, (size_t)buf_inlen); 342 } 343 } 344 345 if (rv <= 0) { 346 BIO_printf(bio_err, "Public Key operation error\n"); 347 ERR_print_errors(bio_err); 348 goto end; 349 } 350 ret = 0; 351 if (asn1parse) { 352 if (!ASN1_parse_dump(out, buf_out, buf_outlen, 1, -1)) 353 ERR_print_errors(bio_err); 354 } else if (hexdump) 355 BIO_dump(out, (char *)buf_out, buf_outlen); 356 else 357 BIO_write(out, buf_out, buf_outlen); 358 359 end: 360 if (ctx) 361 EVP_PKEY_CTX_free(ctx); 362 release_engine(e); 363 BIO_free(in); 364 BIO_free_all(out); 365 if (buf_in != NULL) 366 OPENSSL_free(buf_in); 367 if (buf_out != NULL) 368 OPENSSL_free(buf_out); 369 if (sig != NULL) 370 OPENSSL_free(sig); 371 if (pkeyopts != NULL) 372 sk_OPENSSL_STRING_free(pkeyopts); 373 return ret; 374 } 375 376 static void usage() 377 { 378 BIO_printf(bio_err, "Usage: pkeyutl [options]\n"); 379 BIO_printf(bio_err, "-in file input file\n"); 380 BIO_printf(bio_err, "-out file output file\n"); 381 BIO_printf(bio_err, 382 "-sigfile file signature file (verify operation only)\n"); 383 BIO_printf(bio_err, "-inkey file input key\n"); 384 BIO_printf(bio_err, "-keyform arg private key format - default PEM\n"); 385 BIO_printf(bio_err, "-pubin input is a public key\n"); 386 BIO_printf(bio_err, 387 "-certin input is a certificate carrying a public key\n"); 388 BIO_printf(bio_err, "-pkeyopt X:Y public key options\n"); 389 BIO_printf(bio_err, "-sign sign with private key\n"); 390 BIO_printf(bio_err, "-verify verify with public key\n"); 391 BIO_printf(bio_err, 392 "-verifyrecover verify with public key, recover original data\n"); 393 BIO_printf(bio_err, "-encrypt encrypt with public key\n"); 394 BIO_printf(bio_err, "-decrypt decrypt with private key\n"); 395 BIO_printf(bio_err, "-derive derive shared secret\n"); 396 BIO_printf(bio_err, "-hexdump hex dump output\n"); 397 #ifndef OPENSSL_NO_ENGINE 398 BIO_printf(bio_err, 399 "-engine e use engine e, maybe a hardware device, for loading keys.\n"); 400 BIO_printf(bio_err, "-engine_impl also use engine given by -engine for crypto operations\n"); 401 #endif 402 BIO_printf(bio_err, "-passin arg pass phrase source\n"); 403 404 } 405 406 static EVP_PKEY_CTX *init_ctx(int *pkeysize, 407 const char *keyfile, int keyform, int key_type, 408 char *passargin, int pkey_op, ENGINE *e, 409 int engine_impl) 410 { 411 EVP_PKEY *pkey = NULL; 412 EVP_PKEY_CTX *ctx = NULL; 413 ENGINE *impl = NULL; 414 char *passin = NULL; 415 int rv = -1; 416 X509 *x; 417 if (((pkey_op == EVP_PKEY_OP_SIGN) || (pkey_op == EVP_PKEY_OP_DECRYPT) 418 || (pkey_op == EVP_PKEY_OP_DERIVE)) 419 && (key_type != KEY_PRIVKEY)) { 420 BIO_printf(bio_err, "A private key is needed for this operation\n"); 421 goto end; 422 } 423 if (!app_passwd(bio_err, passargin, NULL, &passin, NULL)) { 424 BIO_printf(bio_err, "Error getting password\n"); 425 goto end; 426 } 427 switch (key_type) { 428 case KEY_PRIVKEY: 429 pkey = load_key(bio_err, keyfile, keyform, 0, 430 passin, e, "Private Key"); 431 break; 432 433 case KEY_PUBKEY: 434 pkey = load_pubkey(bio_err, keyfile, keyform, 0, 435 NULL, e, "Public Key"); 436 break; 437 438 case KEY_CERT: 439 x = load_cert(bio_err, keyfile, keyform, NULL, e, "Certificate"); 440 if (x) { 441 pkey = X509_get_pubkey(x); 442 X509_free(x); 443 } 444 break; 445 446 } 447 448 *pkeysize = EVP_PKEY_size(pkey); 449 450 if (!pkey) 451 goto end; 452 453 #ifndef OPENSSL_NO_ENGINE 454 if (engine_impl) 455 impl = e; 456 #endif 457 458 ctx = EVP_PKEY_CTX_new(pkey, impl); 459 460 EVP_PKEY_free(pkey); 461 462 if (!ctx) 463 goto end; 464 465 switch (pkey_op) { 466 case EVP_PKEY_OP_SIGN: 467 rv = EVP_PKEY_sign_init(ctx); 468 break; 469 470 case EVP_PKEY_OP_VERIFY: 471 rv = EVP_PKEY_verify_init(ctx); 472 break; 473 474 case EVP_PKEY_OP_VERIFYRECOVER: 475 rv = EVP_PKEY_verify_recover_init(ctx); 476 break; 477 478 case EVP_PKEY_OP_ENCRYPT: 479 rv = EVP_PKEY_encrypt_init(ctx); 480 break; 481 482 case EVP_PKEY_OP_DECRYPT: 483 rv = EVP_PKEY_decrypt_init(ctx); 484 break; 485 486 case EVP_PKEY_OP_DERIVE: 487 rv = EVP_PKEY_derive_init(ctx); 488 break; 489 } 490 491 if (rv <= 0) { 492 EVP_PKEY_CTX_free(ctx); 493 ctx = NULL; 494 } 495 496 end: 497 498 if (passin) 499 OPENSSL_free(passin); 500 501 return ctx; 502 503 } 504 505 static int setup_peer(BIO *err, EVP_PKEY_CTX *ctx, int peerform, 506 const char *file, ENGINE* e) 507 { 508 EVP_PKEY *peer = NULL; 509 ENGINE* engine = NULL; 510 int ret; 511 512 if (peerform == FORMAT_ENGINE) 513 engine = e; 514 peer = load_pubkey(bio_err, file, peerform, 0, NULL, engine, "Peer Key"); 515 516 if (!peer) { 517 BIO_printf(bio_err, "Error reading peer key %s\n", file); 518 ERR_print_errors(err); 519 return 0; 520 } 521 522 ret = EVP_PKEY_derive_set_peer(ctx, peer); 523 524 EVP_PKEY_free(peer); 525 if (ret <= 0) 526 ERR_print_errors(err); 527 return ret; 528 } 529 530 static int do_keyop(EVP_PKEY_CTX *ctx, int pkey_op, 531 unsigned char *out, size_t *poutlen, 532 unsigned char *in, size_t inlen) 533 { 534 int rv = 0; 535 switch (pkey_op) { 536 case EVP_PKEY_OP_VERIFYRECOVER: 537 rv = EVP_PKEY_verify_recover(ctx, out, poutlen, in, inlen); 538 break; 539 540 case EVP_PKEY_OP_SIGN: 541 rv = EVP_PKEY_sign(ctx, out, poutlen, in, inlen); 542 break; 543 544 case EVP_PKEY_OP_ENCRYPT: 545 rv = EVP_PKEY_encrypt(ctx, out, poutlen, in, inlen); 546 break; 547 548 case EVP_PKEY_OP_DECRYPT: 549 rv = EVP_PKEY_decrypt(ctx, out, poutlen, in, inlen); 550 break; 551 552 case EVP_PKEY_OP_DERIVE: 553 rv = EVP_PKEY_derive(ctx, out, poutlen); 554 break; 555 556 } 557 return rv; 558 } 559