1 /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL 2 * project 2006. 3 */ 4 /* ==================================================================== 5 * Copyright (c) 2006 The OpenSSL Project. All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in 16 * the documentation and/or other materials provided with the 17 * distribution. 18 * 19 * 3. All advertising materials mentioning features or use of this 20 * software must display the following acknowledgment: 21 * "This product includes software developed by the OpenSSL Project 22 * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" 23 * 24 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 25 * endorse or promote products derived from this software without 26 * prior written permission. For written permission, please contact 27 * licensing@OpenSSL.org. 28 * 29 * 5. Products derived from this software may not be called "OpenSSL" 30 * nor may "OpenSSL" appear in their names without prior written 31 * permission of the OpenSSL Project. 32 * 33 * 6. Redistributions of any form whatsoever must retain the following 34 * acknowledgment: 35 * "This product includes software developed by the OpenSSL Project 36 * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" 37 * 38 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 39 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 40 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 41 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 42 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 43 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 44 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 45 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 46 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 47 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 48 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 49 * OF THE POSSIBILITY OF SUCH DAMAGE. 50 * ==================================================================== 51 * 52 * This product includes cryptographic software written by Eric Young 53 * (eay@cryptsoft.com). This product includes software written by Tim 54 * Hudson (tjh@cryptsoft.com). 55 * 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 char *keyfile, int keyform, int key_type, 77 char *passargin, int pkey_op, ENGINE *e); 78 79 static int setup_peer(BIO *err, EVP_PKEY_CTX *ctx, int peerform, 80 const char *file); 81 82 static int do_keyop(EVP_PKEY_CTX *ctx, int pkey_op, 83 unsigned char *out, size_t *poutlen, 84 unsigned char *in, size_t inlen); 85 86 int MAIN(int argc, char **); 87 88 int MAIN(int argc, char **argv) 89 { 90 BIO *in = NULL, *out = NULL; 91 char *infile = NULL, *outfile = NULL, *sigfile = NULL; 92 ENGINE *e = NULL; 93 int pkey_op = EVP_PKEY_OP_SIGN, key_type = KEY_PRIVKEY; 94 int keyform = FORMAT_PEM, peerform = FORMAT_PEM; 95 char badarg = 0, rev = 0; 96 char hexdump = 0, asn1parse = 0; 97 EVP_PKEY_CTX *ctx = NULL; 98 char *passargin = NULL; 99 int keysize = -1; 100 101 unsigned char *buf_in = NULL, *buf_out = NULL, *sig = NULL; 102 size_t buf_outlen; 103 int buf_inlen = 0, siglen = -1; 104 105 int ret = 1, rv = -1; 106 107 argc--; 108 argv++; 109 110 if(!bio_err) bio_err = BIO_new_fp(stderr, BIO_NOCLOSE); 111 112 if (!load_config(bio_err, NULL)) 113 goto end; 114 ERR_load_crypto_strings(); 115 OpenSSL_add_all_algorithms(); 116 117 while(argc >= 1) 118 { 119 if (!strcmp(*argv,"-in")) 120 { 121 if (--argc < 1) badarg = 1; 122 else infile= *(++argv); 123 } 124 else if (!strcmp(*argv,"-out")) 125 { 126 if (--argc < 1) badarg = 1; 127 else outfile= *(++argv); 128 } 129 else if (!strcmp(*argv,"-sigfile")) 130 { 131 if (--argc < 1) badarg = 1; 132 else sigfile= *(++argv); 133 } 134 else if(!strcmp(*argv, "-inkey")) 135 { 136 if (--argc < 1) 137 badarg = 1; 138 else 139 { 140 ctx = init_ctx(&keysize, 141 *(++argv), keyform, key_type, 142 passargin, pkey_op, e); 143 if (!ctx) 144 { 145 BIO_puts(bio_err, 146 "Error initializing context\n"); 147 ERR_print_errors(bio_err); 148 badarg = 1; 149 } 150 } 151 } 152 else if (!strcmp(*argv,"-peerkey")) 153 { 154 if (--argc < 1) 155 badarg = 1; 156 else if (!setup_peer(bio_err, ctx, peerform, *(++argv))) 157 badarg = 1; 158 } 159 else if (!strcmp(*argv,"-passin")) 160 { 161 if (--argc < 1) badarg = 1; 162 else passargin= *(++argv); 163 } 164 else if (strcmp(*argv,"-peerform") == 0) 165 { 166 if (--argc < 1) badarg = 1; 167 else peerform=str2fmt(*(++argv)); 168 } 169 else if (strcmp(*argv,"-keyform") == 0) 170 { 171 if (--argc < 1) badarg = 1; 172 else keyform=str2fmt(*(++argv)); 173 } 174 #ifndef OPENSSL_NO_ENGINE 175 else if(!strcmp(*argv, "-engine")) 176 { 177 if (--argc < 1) 178 badarg = 1; 179 else 180 e = setup_engine(bio_err, *(++argv), 0); 181 } 182 #endif 183 else if(!strcmp(*argv, "-pubin")) 184 key_type = KEY_PUBKEY; 185 else if(!strcmp(*argv, "-certin")) 186 key_type = KEY_CERT; 187 else if(!strcmp(*argv, "-asn1parse")) 188 asn1parse = 1; 189 else if(!strcmp(*argv, "-hexdump")) 190 hexdump = 1; 191 else if(!strcmp(*argv, "-sign")) 192 pkey_op = EVP_PKEY_OP_SIGN; 193 else if(!strcmp(*argv, "-verify")) 194 pkey_op = EVP_PKEY_OP_VERIFY; 195 else if(!strcmp(*argv, "-verifyrecover")) 196 pkey_op = EVP_PKEY_OP_VERIFYRECOVER; 197 else if(!strcmp(*argv, "-rev")) 198 rev = 1; 199 else if(!strcmp(*argv, "-encrypt")) 200 pkey_op = EVP_PKEY_OP_ENCRYPT; 201 else if(!strcmp(*argv, "-decrypt")) 202 pkey_op = EVP_PKEY_OP_DECRYPT; 203 else if(!strcmp(*argv, "-derive")) 204 pkey_op = EVP_PKEY_OP_DERIVE; 205 else if (strcmp(*argv,"-pkeyopt") == 0) 206 { 207 if (--argc < 1) 208 badarg = 1; 209 else if (!ctx) 210 { 211 BIO_puts(bio_err, 212 "-pkeyopt command before -inkey\n"); 213 badarg = 1; 214 } 215 else if (pkey_ctrl_string(ctx, *(++argv)) <= 0) 216 { 217 BIO_puts(bio_err, "parameter setting error\n"); 218 ERR_print_errors(bio_err); 219 goto end; 220 } 221 } 222 else badarg = 1; 223 if(badarg) 224 { 225 usage(); 226 goto end; 227 } 228 argc--; 229 argv++; 230 } 231 232 if (!ctx) 233 { 234 usage(); 235 goto end; 236 } 237 238 if (sigfile && (pkey_op != EVP_PKEY_OP_VERIFY)) 239 { 240 BIO_puts(bio_err, "Signature file specified for non verify\n"); 241 goto end; 242 } 243 244 if (!sigfile && (pkey_op == EVP_PKEY_OP_VERIFY)) 245 { 246 BIO_puts(bio_err, "No signature file specified for verify\n"); 247 goto end; 248 } 249 250 /* FIXME: seed PRNG only if needed */ 251 app_RAND_load_file(NULL, bio_err, 0); 252 253 if (pkey_op != EVP_PKEY_OP_DERIVE) 254 { 255 if(infile) 256 { 257 if(!(in = BIO_new_file(infile, "rb"))) 258 { 259 BIO_puts(bio_err, 260 "Error Opening Input File\n"); 261 ERR_print_errors(bio_err); 262 goto end; 263 } 264 } 265 else 266 in = BIO_new_fp(stdin, BIO_NOCLOSE); 267 } 268 269 if(outfile) 270 { 271 if(!(out = BIO_new_file(outfile, "wb"))) 272 { 273 BIO_printf(bio_err, "Error Creating Output File\n"); 274 ERR_print_errors(bio_err); 275 goto end; 276 } 277 } 278 else 279 { 280 out = BIO_new_fp(stdout, BIO_NOCLOSE); 281 #ifdef OPENSSL_SYS_VMS 282 { 283 BIO *tmpbio = BIO_new(BIO_f_linebuffer()); 284 out = BIO_push(tmpbio, out); 285 } 286 #endif 287 } 288 289 if (sigfile) 290 { 291 BIO *sigbio = BIO_new_file(sigfile, "rb"); 292 if (!sigbio) 293 { 294 BIO_printf(bio_err, "Can't open signature file %s\n", 295 sigfile); 296 goto end; 297 } 298 siglen = bio_to_mem(&sig, keysize * 10, sigbio); 299 BIO_free(sigbio); 300 if (siglen <= 0) 301 { 302 BIO_printf(bio_err, "Error reading signature data\n"); 303 goto end; 304 } 305 } 306 307 if (in) 308 { 309 /* Read the input data */ 310 buf_inlen = bio_to_mem(&buf_in, keysize * 10, in); 311 if(buf_inlen <= 0) 312 { 313 BIO_printf(bio_err, "Error reading input Data\n"); 314 exit(1); 315 } 316 if(rev) 317 { 318 size_t i; 319 unsigned char ctmp; 320 size_t l = (size_t)buf_inlen; 321 for(i = 0; i < l/2; i++) 322 { 323 ctmp = buf_in[i]; 324 buf_in[i] = buf_in[l - 1 - i]; 325 buf_in[l - 1 - i] = ctmp; 326 } 327 } 328 } 329 330 if(pkey_op == EVP_PKEY_OP_VERIFY) 331 { 332 rv = EVP_PKEY_verify(ctx, sig, (size_t)siglen, 333 buf_in, (size_t)buf_inlen); 334 if (rv == 0) 335 BIO_puts(out, "Signature Verification Failure\n"); 336 else if (rv == 1) 337 BIO_puts(out, "Signature Verified Successfully\n"); 338 if (rv >= 0) 339 goto end; 340 } 341 else 342 { 343 rv = do_keyop(ctx, pkey_op, NULL, (size_t *)&buf_outlen, 344 buf_in, (size_t)buf_inlen); 345 if (rv > 0) 346 { 347 buf_out = OPENSSL_malloc(buf_outlen); 348 if (!buf_out) 349 rv = -1; 350 else 351 rv = do_keyop(ctx, pkey_op, 352 buf_out, (size_t *)&buf_outlen, 353 buf_in, (size_t)buf_inlen); 354 } 355 } 356 357 if(rv <= 0) 358 { 359 BIO_printf(bio_err, "Public Key operation error\n"); 360 ERR_print_errors(bio_err); 361 goto end; 362 } 363 ret = 0; 364 if(asn1parse) 365 { 366 if(!ASN1_parse_dump(out, buf_out, buf_outlen, 1, -1)) 367 ERR_print_errors(bio_err); 368 } 369 else if(hexdump) 370 BIO_dump(out, (char *)buf_out, buf_outlen); 371 else 372 BIO_write(out, buf_out, buf_outlen); 373 374 end: 375 if (ctx) 376 EVP_PKEY_CTX_free(ctx); 377 BIO_free(in); 378 BIO_free_all(out); 379 if (buf_in) 380 OPENSSL_free(buf_in); 381 if (buf_out) 382 OPENSSL_free(buf_out); 383 if (sig) 384 OPENSSL_free(sig); 385 return ret; 386 } 387 388 static void usage() 389 { 390 BIO_printf(bio_err, "Usage: pkeyutl [options]\n"); 391 BIO_printf(bio_err, "-in file input file\n"); 392 BIO_printf(bio_err, "-out file output file\n"); 393 BIO_printf(bio_err, "-sigfile file signature file (verify operation only)\n"); 394 BIO_printf(bio_err, "-inkey file input key\n"); 395 BIO_printf(bio_err, "-keyform arg private key format - default PEM\n"); 396 BIO_printf(bio_err, "-pubin input is a public key\n"); 397 BIO_printf(bio_err, "-certin input is a certificate carrying a public key\n"); 398 BIO_printf(bio_err, "-pkeyopt X:Y public key options\n"); 399 BIO_printf(bio_err, "-sign sign with private key\n"); 400 BIO_printf(bio_err, "-verify verify with public key\n"); 401 BIO_printf(bio_err, "-verifyrecover verify with public key, recover original data\n"); 402 BIO_printf(bio_err, "-encrypt encrypt with public key\n"); 403 BIO_printf(bio_err, "-decrypt decrypt with private key\n"); 404 BIO_printf(bio_err, "-derive derive shared secret\n"); 405 BIO_printf(bio_err, "-hexdump hex dump output\n"); 406 #ifndef OPENSSL_NO_ENGINE 407 BIO_printf(bio_err, "-engine e use engine e, possibly a hardware device.\n"); 408 #endif 409 BIO_printf(bio_err, "-passin arg pass phrase source\n"); 410 411 } 412 413 static EVP_PKEY_CTX *init_ctx(int *pkeysize, 414 char *keyfile, int keyform, int key_type, 415 char *passargin, int pkey_op, ENGINE *e) 416 { 417 EVP_PKEY *pkey = NULL; 418 EVP_PKEY_CTX *ctx = NULL; 419 char *passin = NULL; 420 int rv = -1; 421 X509 *x; 422 if(((pkey_op == EVP_PKEY_OP_SIGN) || (pkey_op == EVP_PKEY_OP_DECRYPT) 423 || (pkey_op == EVP_PKEY_OP_DERIVE)) 424 && (key_type != KEY_PRIVKEY)) 425 { 426 BIO_printf(bio_err, "A private key is needed for this operation\n"); 427 goto end; 428 } 429 if(!app_passwd(bio_err, passargin, NULL, &passin, NULL)) 430 { 431 BIO_printf(bio_err, "Error getting password\n"); 432 goto end; 433 } 434 switch(key_type) 435 { 436 case KEY_PRIVKEY: 437 pkey = load_key(bio_err, keyfile, keyform, 0, 438 passin, e, "Private Key"); 439 break; 440 441 case KEY_PUBKEY: 442 pkey = load_pubkey(bio_err, keyfile, keyform, 0, 443 NULL, e, "Public Key"); 444 break; 445 446 case KEY_CERT: 447 x = load_cert(bio_err, keyfile, keyform, 448 NULL, e, "Certificate"); 449 if(x) 450 { 451 pkey = X509_get_pubkey(x); 452 X509_free(x); 453 } 454 break; 455 456 } 457 458 *pkeysize = EVP_PKEY_size(pkey); 459 460 if (!pkey) 461 goto end; 462 463 ctx = EVP_PKEY_CTX_new(pkey, e); 464 465 EVP_PKEY_free(pkey); 466 467 if (!ctx) 468 goto end; 469 470 switch(pkey_op) 471 { 472 case EVP_PKEY_OP_SIGN: 473 rv = EVP_PKEY_sign_init(ctx); 474 break; 475 476 case EVP_PKEY_OP_VERIFY: 477 rv = EVP_PKEY_verify_init(ctx); 478 break; 479 480 case EVP_PKEY_OP_VERIFYRECOVER: 481 rv = EVP_PKEY_verify_recover_init(ctx); 482 break; 483 484 case EVP_PKEY_OP_ENCRYPT: 485 rv = EVP_PKEY_encrypt_init(ctx); 486 break; 487 488 case EVP_PKEY_OP_DECRYPT: 489 rv = EVP_PKEY_decrypt_init(ctx); 490 break; 491 492 case EVP_PKEY_OP_DERIVE: 493 rv = EVP_PKEY_derive_init(ctx); 494 break; 495 } 496 497 if (rv <= 0) 498 { 499 EVP_PKEY_CTX_free(ctx); 500 ctx = NULL; 501 } 502 503 end: 504 505 if (passin) 506 OPENSSL_free(passin); 507 508 return ctx; 509 510 511 } 512 513 static int setup_peer(BIO *err, EVP_PKEY_CTX *ctx, int peerform, 514 const char *file) 515 { 516 EVP_PKEY *peer = NULL; 517 int ret; 518 if (!ctx) 519 { 520 BIO_puts(err, "-peerkey command before -inkey\n"); 521 return 0; 522 } 523 524 peer = load_pubkey(bio_err, file, peerform, 0, NULL, NULL, "Peer Key"); 525 526 if (!peer) 527 { 528 BIO_printf(bio_err, "Error reading peer key %s\n", file); 529 ERR_print_errors(err); 530 return 0; 531 } 532 533 ret = EVP_PKEY_derive_set_peer(ctx, peer); 534 535 EVP_PKEY_free(peer); 536 if (ret <= 0) 537 ERR_print_errors(err); 538 return ret; 539 } 540 541 static int do_keyop(EVP_PKEY_CTX *ctx, int pkey_op, 542 unsigned char *out, size_t *poutlen, 543 unsigned char *in, size_t inlen) 544 { 545 int rv = 0; 546 switch(pkey_op) 547 { 548 case EVP_PKEY_OP_VERIFYRECOVER: 549 rv = EVP_PKEY_verify_recover(ctx, out, poutlen, in, inlen); 550 break; 551 552 case EVP_PKEY_OP_SIGN: 553 rv = EVP_PKEY_sign(ctx, out, poutlen, in, inlen); 554 break; 555 556 case EVP_PKEY_OP_ENCRYPT: 557 rv = EVP_PKEY_encrypt(ctx, out, poutlen, in, inlen); 558 break; 559 560 case EVP_PKEY_OP_DECRYPT: 561 rv = EVP_PKEY_decrypt(ctx, out, poutlen, in, inlen); 562 break; 563 564 case EVP_PKEY_OP_DERIVE: 565 rv = EVP_PKEY_derive(ctx, out, poutlen); 566 break; 567 568 } 569 return rv; 570 } 571