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