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