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 if (rv >= 0) 328 goto end; 329 } else { 330 rv = do_keyop(ctx, pkey_op, NULL, (size_t *)&buf_outlen, 331 buf_in, (size_t)buf_inlen); 332 if (rv > 0 && buf_outlen != 0) { 333 buf_out = OPENSSL_malloc(buf_outlen); 334 if (!buf_out) 335 rv = -1; 336 else 337 rv = do_keyop(ctx, pkey_op, 338 buf_out, (size_t *)&buf_outlen, 339 buf_in, (size_t)buf_inlen); 340 } 341 } 342 343 if (rv <= 0) { 344 BIO_printf(bio_err, "Public Key operation error\n"); 345 ERR_print_errors(bio_err); 346 goto end; 347 } 348 ret = 0; 349 if (asn1parse) { 350 if (!ASN1_parse_dump(out, buf_out, buf_outlen, 1, -1)) 351 ERR_print_errors(bio_err); 352 } else if (hexdump) 353 BIO_dump(out, (char *)buf_out, buf_outlen); 354 else 355 BIO_write(out, buf_out, buf_outlen); 356 357 end: 358 if (ctx) 359 EVP_PKEY_CTX_free(ctx); 360 release_engine(e); 361 BIO_free(in); 362 BIO_free_all(out); 363 if (buf_in != NULL) 364 OPENSSL_free(buf_in); 365 if (buf_out != NULL) 366 OPENSSL_free(buf_out); 367 if (sig != NULL) 368 OPENSSL_free(sig); 369 if (pkeyopts != NULL) 370 sk_OPENSSL_STRING_free(pkeyopts); 371 return ret; 372 } 373 374 static void usage() 375 { 376 BIO_printf(bio_err, "Usage: pkeyutl [options]\n"); 377 BIO_printf(bio_err, "-in file input file\n"); 378 BIO_printf(bio_err, "-out file output file\n"); 379 BIO_printf(bio_err, 380 "-sigfile file signature file (verify operation only)\n"); 381 BIO_printf(bio_err, "-inkey file input key\n"); 382 BIO_printf(bio_err, "-keyform arg private key format - default PEM\n"); 383 BIO_printf(bio_err, "-pubin input is a public key\n"); 384 BIO_printf(bio_err, 385 "-certin input is a certificate carrying a public key\n"); 386 BIO_printf(bio_err, "-pkeyopt X:Y public key options\n"); 387 BIO_printf(bio_err, "-sign sign with private key\n"); 388 BIO_printf(bio_err, "-verify verify with public key\n"); 389 BIO_printf(bio_err, 390 "-verifyrecover verify with public key, recover original data\n"); 391 BIO_printf(bio_err, "-encrypt encrypt with public key\n"); 392 BIO_printf(bio_err, "-decrypt decrypt with private key\n"); 393 BIO_printf(bio_err, "-derive derive shared secret\n"); 394 BIO_printf(bio_err, "-hexdump hex dump output\n"); 395 #ifndef OPENSSL_NO_ENGINE 396 BIO_printf(bio_err, 397 "-engine e use engine e, maybe a hardware device, for loading keys.\n"); 398 BIO_printf(bio_err, "-engine_impl also use engine given by -engine for crypto operations\n"); 399 #endif 400 BIO_printf(bio_err, "-passin arg pass phrase source\n"); 401 402 } 403 404 static EVP_PKEY_CTX *init_ctx(int *pkeysize, 405 const char *keyfile, int keyform, int key_type, 406 char *passargin, int pkey_op, ENGINE *e, 407 int engine_impl) 408 { 409 EVP_PKEY *pkey = NULL; 410 EVP_PKEY_CTX *ctx = NULL; 411 ENGINE *impl = NULL; 412 char *passin = NULL; 413 int rv = -1; 414 X509 *x; 415 if (((pkey_op == EVP_PKEY_OP_SIGN) || (pkey_op == EVP_PKEY_OP_DECRYPT) 416 || (pkey_op == EVP_PKEY_OP_DERIVE)) 417 && (key_type != KEY_PRIVKEY)) { 418 BIO_printf(bio_err, "A private key is needed for this operation\n"); 419 goto end; 420 } 421 if (!app_passwd(bio_err, passargin, NULL, &passin, NULL)) { 422 BIO_printf(bio_err, "Error getting password\n"); 423 goto end; 424 } 425 switch (key_type) { 426 case KEY_PRIVKEY: 427 pkey = load_key(bio_err, keyfile, keyform, 0, 428 passin, e, "Private Key"); 429 break; 430 431 case KEY_PUBKEY: 432 pkey = load_pubkey(bio_err, keyfile, keyform, 0, 433 NULL, e, "Public Key"); 434 break; 435 436 case KEY_CERT: 437 x = load_cert(bio_err, keyfile, keyform, NULL, e, "Certificate"); 438 if (x) { 439 pkey = X509_get_pubkey(x); 440 X509_free(x); 441 } 442 break; 443 444 } 445 446 *pkeysize = EVP_PKEY_size(pkey); 447 448 if (!pkey) 449 goto end; 450 451 #ifndef OPENSSL_NO_ENGINE 452 if (engine_impl) 453 impl = e; 454 #endif 455 456 ctx = EVP_PKEY_CTX_new(pkey, impl); 457 458 EVP_PKEY_free(pkey); 459 460 if (!ctx) 461 goto end; 462 463 switch (pkey_op) { 464 case EVP_PKEY_OP_SIGN: 465 rv = EVP_PKEY_sign_init(ctx); 466 break; 467 468 case EVP_PKEY_OP_VERIFY: 469 rv = EVP_PKEY_verify_init(ctx); 470 break; 471 472 case EVP_PKEY_OP_VERIFYRECOVER: 473 rv = EVP_PKEY_verify_recover_init(ctx); 474 break; 475 476 case EVP_PKEY_OP_ENCRYPT: 477 rv = EVP_PKEY_encrypt_init(ctx); 478 break; 479 480 case EVP_PKEY_OP_DECRYPT: 481 rv = EVP_PKEY_decrypt_init(ctx); 482 break; 483 484 case EVP_PKEY_OP_DERIVE: 485 rv = EVP_PKEY_derive_init(ctx); 486 break; 487 } 488 489 if (rv <= 0) { 490 EVP_PKEY_CTX_free(ctx); 491 ctx = NULL; 492 } 493 494 end: 495 496 if (passin) 497 OPENSSL_free(passin); 498 499 return ctx; 500 501 } 502 503 static int setup_peer(BIO *err, EVP_PKEY_CTX *ctx, int peerform, 504 const char *file, ENGINE* e) 505 { 506 EVP_PKEY *peer = NULL; 507 ENGINE* engine = NULL; 508 int ret; 509 510 if (peerform == FORMAT_ENGINE) 511 engine = e; 512 peer = load_pubkey(bio_err, file, peerform, 0, NULL, engine, "Peer Key"); 513 514 if (!peer) { 515 BIO_printf(bio_err, "Error reading peer key %s\n", file); 516 ERR_print_errors(err); 517 return 0; 518 } 519 520 ret = EVP_PKEY_derive_set_peer(ctx, peer); 521 522 EVP_PKEY_free(peer); 523 if (ret <= 0) 524 ERR_print_errors(err); 525 return ret; 526 } 527 528 static int do_keyop(EVP_PKEY_CTX *ctx, int pkey_op, 529 unsigned char *out, size_t *poutlen, 530 unsigned char *in, size_t inlen) 531 { 532 int rv = 0; 533 switch (pkey_op) { 534 case EVP_PKEY_OP_VERIFYRECOVER: 535 rv = EVP_PKEY_verify_recover(ctx, out, poutlen, in, inlen); 536 break; 537 538 case EVP_PKEY_OP_SIGN: 539 rv = EVP_PKEY_sign(ctx, out, poutlen, in, inlen); 540 break; 541 542 case EVP_PKEY_OP_ENCRYPT: 543 rv = EVP_PKEY_encrypt(ctx, out, poutlen, in, inlen); 544 break; 545 546 case EVP_PKEY_OP_DECRYPT: 547 rv = EVP_PKEY_decrypt(ctx, out, poutlen, in, inlen); 548 break; 549 550 case EVP_PKEY_OP_DERIVE: 551 rv = EVP_PKEY_derive(ctx, out, poutlen); 552 break; 553 554 } 555 return rv; 556 } 557