1126385Smlaier/* 2126385Smlaier * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project 3126385Smlaier * 2006. 4126385Smlaier */ 5126385Smlaier/* ==================================================================== 6126385Smlaier * Copyright (c) 2006 The OpenSSL Project. All rights reserved. 7126385Smlaier * 8126385Smlaier * Redistribution and use in source and binary forms, with or without 9126385Smlaier * modification, are permitted provided that the following conditions 10126385Smlaier * are met: 11126385Smlaier * 12126385Smlaier * 1. Redistributions of source code must retain the above copyright 13126385Smlaier * notice, this list of conditions and the following disclaimer. 14126385Smlaier * 15126385Smlaier * 2. Redistributions in binary form must reproduce the above copyright 16126385Smlaier * notice, this list of conditions and the following disclaimer in 17126385Smlaier * the documentation and/or other materials provided with the 18126385Smlaier * distribution. 19126385Smlaier * 20126385Smlaier * 3. All advertising materials mentioning features or use of this 21126385Smlaier * software must display the following acknowledgment: 22126385Smlaier * "This product includes software developed by the OpenSSL Project 23126385Smlaier * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" 24126385Smlaier * 25126385Smlaier * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 26126385Smlaier * endorse or promote products derived from this software without 27126385Smlaier * prior written permission. For written permission, please contact 28126385Smlaier * licensing@OpenSSL.org. 29126385Smlaier * 30126385Smlaier * 5. Products derived from this software may not be called "OpenSSL" 31126385Smlaier * nor may "OpenSSL" appear in their names without prior written 32126385Smlaier * permission of the OpenSSL Project. 33126385Smlaier * 34126385Smlaier * 6. Redistributions of any form whatsoever must retain the following 35126385Smlaier * acknowledgment: 36126385Smlaier * "This product includes software developed by the OpenSSL Project 37126385Smlaier * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" 38126385Smlaier * 39126385Smlaier * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 40126385Smlaier * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 41126385Smlaier * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 42126385Smlaier * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 43126385Smlaier * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 44126385Smlaier * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 45126385Smlaier * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 46126385Smlaier * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 47126385Smlaier * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 48126385Smlaier * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 49126385Smlaier * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 50126385Smlaier * OF THE POSSIBILITY OF SUCH DAMAGE. 51126385Smlaier * ==================================================================== 52126385Smlaier * 53126385Smlaier * This product includes cryptographic software written by Eric Young 54126385Smlaier * (eay@cryptsoft.com). This product includes software written by Tim 55126385Smlaier * Hudson (tjh@cryptsoft.com). 56126385Smlaier * 57126385Smlaier */ 58126385Smlaier 59126385Smlaier#include "apps.h" 60126385Smlaier#include <string.h> 61126385Smlaier#include <openssl/err.h> 62126385Smlaier#include <openssl/pem.h> 63126385Smlaier#include <openssl/evp.h> 64126385Smlaier 65126385Smlaier#define KEY_PRIVKEY 1 66126385Smlaier#define KEY_PUBKEY 2 67126385Smlaier#define KEY_CERT 3 68126385Smlaier 69126385Smlaierstatic void usage(void); 70126385Smlaier 71126385Smlaier#undef PROG 72126385Smlaier 73126385Smlaier#define PROG pkeyutl_main 74126385Smlaier 75126385Smlaierstatic EVP_PKEY_CTX *init_ctx(int *pkeysize, 76126385Smlaier char *keyfile, int keyform, int key_type, 77126385Smlaier char *passargin, int pkey_op, ENGINE *e); 78126385Smlaier 79126385Smlaierstatic int setup_peer(BIO *err, EVP_PKEY_CTX *ctx, int peerform, 80126385Smlaier const char *file); 81126385Smlaier 82126385Smlaierstatic int do_keyop(EVP_PKEY_CTX *ctx, int pkey_op, 83126385Smlaier unsigned char *out, size_t *poutlen, 84126385Smlaier unsigned char *in, size_t inlen); 85126385Smlaier 86126385Smlaierint MAIN(int argc, char **); 87126385Smlaier 88126385Smlaierint MAIN(int argc, char **argv) 89126385Smlaier{ 90126385Smlaier BIO *in = NULL, *out = NULL; 91126385Smlaier char *infile = NULL, *outfile = NULL, *sigfile = NULL; 92126385Smlaier ENGINE *e = NULL; 93126385Smlaier int pkey_op = EVP_PKEY_OP_SIGN, key_type = KEY_PRIVKEY; 94126385Smlaier int keyform = FORMAT_PEM, peerform = FORMAT_PEM; 95126385Smlaier char badarg = 0, rev = 0; 96126385Smlaier char hexdump = 0, asn1parse = 0; 97126385Smlaier EVP_PKEY_CTX *ctx = NULL; 98126385Smlaier char *passargin = NULL; 99126385Smlaier int keysize = -1; 100126385Smlaier 101126385Smlaier unsigned char *buf_in = NULL, *buf_out = NULL, *sig = NULL; 102126385Smlaier size_t buf_outlen; 103126385Smlaier int buf_inlen = 0, siglen = -1; 104126385Smlaier 105126385Smlaier int ret = 1, rv = -1; 106126385Smlaier 107126385Smlaier argc--; 108126385Smlaier argv++; 109126385Smlaier 110126385Smlaier if (!bio_err) 111126385Smlaier bio_err = BIO_new_fp(stderr, BIO_NOCLOSE); 112126385Smlaier 113126385Smlaier if (!load_config(bio_err, NULL)) 114126385Smlaier goto end; 115126385Smlaier ERR_load_crypto_strings(); 116126385Smlaier OpenSSL_add_all_algorithms(); 117126385Smlaier 118126385Smlaier while (argc >= 1) { 119126385Smlaier if (!strcmp(*argv, "-in")) { 120126385Smlaier if (--argc < 1) 121126385Smlaier badarg = 1; 122126385Smlaier else 123126385Smlaier infile = *(++argv); 124126385Smlaier } else if (!strcmp(*argv, "-out")) { 125126385Smlaier if (--argc < 1) 126126385Smlaier badarg = 1; 127126385Smlaier else 128126385Smlaier outfile = *(++argv); 129126385Smlaier } else if (!strcmp(*argv, "-sigfile")) { 130126385Smlaier if (--argc < 1) 131126385Smlaier badarg = 1; 132126385Smlaier else 133126385Smlaier sigfile = *(++argv); 134126385Smlaier } else if (!strcmp(*argv, "-inkey")) { 135126385Smlaier if (--argc < 1) 136126385Smlaier badarg = 1; 137126385Smlaier else { 138126385Smlaier ctx = init_ctx(&keysize, 139126385Smlaier *(++argv), keyform, key_type, 140126385Smlaier passargin, pkey_op, e); 141126385Smlaier if (!ctx) { 142126385Smlaier BIO_puts(bio_err, "Error initializing context\n"); 143126385Smlaier ERR_print_errors(bio_err); 144126385Smlaier badarg = 1; 145126385Smlaier } 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 348static 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 377static 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 469static 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 495static 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