1 /* $OpenBSD: pkeyutl.c,v 1.9 2015/10/17 07:51:10 semarie Exp $ */ 2 /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL 3 * project 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 <string.h> 60 61 #include "apps.h" 62 63 #include <openssl/err.h> 64 #include <openssl/evp.h> 65 #include <openssl/pem.h> 66 67 #define KEY_PRIVKEY 1 68 #define KEY_PUBKEY 2 69 #define KEY_CERT 3 70 71 static void usage(void); 72 73 static EVP_PKEY_CTX *init_ctx(int *pkeysize, 74 char *keyfile, int keyform, int key_type, 75 char *passargin, int pkey_op); 76 77 static int setup_peer(BIO * err, EVP_PKEY_CTX * ctx, int peerform, 78 const char *file); 79 80 static int do_keyop(EVP_PKEY_CTX * ctx, int pkey_op, 81 unsigned char *out, size_t * poutlen, 82 unsigned char *in, size_t inlen); 83 84 int 85 pkeyutl_main(int argc, char **argv) 86 { 87 BIO *in = NULL, *out = NULL; 88 char *infile = NULL, *outfile = NULL, *sigfile = NULL; 89 int pkey_op = EVP_PKEY_OP_SIGN, key_type = KEY_PRIVKEY; 90 int keyform = FORMAT_PEM, peerform = FORMAT_PEM; 91 char badarg = 0, rev = 0; 92 char hexdump = 0, asn1parse = 0; 93 EVP_PKEY_CTX *ctx = NULL; 94 char *passargin = NULL; 95 int keysize = -1; 96 97 unsigned char *buf_in = NULL, *buf_out = NULL, *sig = NULL; 98 size_t buf_outlen; 99 int buf_inlen = 0, siglen = -1; 100 101 int ret = 1, rv = -1; 102 103 if (single_execution) { 104 if (pledge("stdio rpath wpath cpath tty", NULL) == -1) { 105 perror("pledge"); 106 exit(1); 107 } 108 } 109 110 argc--; 111 argv++; 112 113 while (argc >= 1) { 114 if (!strcmp(*argv, "-in")) { 115 if (--argc < 1) 116 badarg = 1; 117 else 118 infile = *(++argv); 119 } else if (!strcmp(*argv, "-out")) { 120 if (--argc < 1) 121 badarg = 1; 122 else 123 outfile = *(++argv); 124 } else if (!strcmp(*argv, "-sigfile")) { 125 if (--argc < 1) 126 badarg = 1; 127 else 128 sigfile = *(++argv); 129 } else if (!strcmp(*argv, "-inkey")) { 130 if (--argc < 1) 131 badarg = 1; 132 else { 133 ctx = init_ctx(&keysize, 134 *(++argv), keyform, key_type, 135 passargin, pkey_op); 136 if (!ctx) { 137 BIO_puts(bio_err, 138 "Error initializing context\n"); 139 ERR_print_errors(bio_err); 140 badarg = 1; 141 } 142 } 143 } else if (!strcmp(*argv, "-peerkey")) { 144 if (--argc < 1) 145 badarg = 1; 146 else if (!setup_peer(bio_err, ctx, peerform, *(++argv))) 147 badarg = 1; 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 else if (!strcmp(*argv, "-pubin")) 165 key_type = KEY_PUBKEY; 166 else if (!strcmp(*argv, "-certin")) 167 key_type = KEY_CERT; 168 else if (!strcmp(*argv, "-asn1parse")) 169 asn1parse = 1; 170 else if (!strcmp(*argv, "-hexdump")) 171 hexdump = 1; 172 else if (!strcmp(*argv, "-sign")) 173 pkey_op = EVP_PKEY_OP_SIGN; 174 else if (!strcmp(*argv, "-verify")) 175 pkey_op = EVP_PKEY_OP_VERIFY; 176 else if (!strcmp(*argv, "-verifyrecover")) 177 pkey_op = EVP_PKEY_OP_VERIFYRECOVER; 178 else if (!strcmp(*argv, "-rev")) 179 rev = 1; 180 else if (!strcmp(*argv, "-encrypt")) 181 pkey_op = EVP_PKEY_OP_ENCRYPT; 182 else if (!strcmp(*argv, "-decrypt")) 183 pkey_op = EVP_PKEY_OP_DECRYPT; 184 else if (!strcmp(*argv, "-derive")) 185 pkey_op = EVP_PKEY_OP_DERIVE; 186 else if (strcmp(*argv, "-pkeyopt") == 0) { 187 if (--argc < 1) 188 badarg = 1; 189 else if (!ctx) { 190 BIO_puts(bio_err, 191 "-pkeyopt command before -inkey\n"); 192 badarg = 1; 193 } else if (pkey_ctrl_string(ctx, *(++argv)) <= 0) { 194 BIO_puts(bio_err, "parameter setting error\n"); 195 ERR_print_errors(bio_err); 196 goto end; 197 } 198 } else 199 badarg = 1; 200 if (badarg) { 201 usage(); 202 goto end; 203 } 204 argc--; 205 argv++; 206 } 207 208 if (!ctx) { 209 usage(); 210 goto end; 211 } 212 if (sigfile && (pkey_op != EVP_PKEY_OP_VERIFY)) { 213 BIO_puts(bio_err, "Signature file specified for non verify\n"); 214 goto end; 215 } 216 if (!sigfile && (pkey_op == EVP_PKEY_OP_VERIFY)) { 217 BIO_puts(bio_err, "No signature file specified for verify\n"); 218 goto end; 219 } 220 221 if (pkey_op != EVP_PKEY_OP_DERIVE) { 222 if (infile) { 223 if (!(in = BIO_new_file(infile, "rb"))) { 224 BIO_puts(bio_err, 225 "Error Opening Input File\n"); 226 ERR_print_errors(bio_err); 227 goto end; 228 } 229 } else 230 in = BIO_new_fp(stdin, BIO_NOCLOSE); 231 } 232 if (outfile) { 233 if (!(out = BIO_new_file(outfile, "wb"))) { 234 BIO_printf(bio_err, "Error Creating Output File\n"); 235 ERR_print_errors(bio_err); 236 goto end; 237 } 238 } else { 239 out = BIO_new_fp(stdout, BIO_NOCLOSE); 240 } 241 242 if (sigfile) { 243 BIO *sigbio = BIO_new_file(sigfile, "rb"); 244 if (!sigbio) { 245 BIO_printf(bio_err, "Can't open signature file %s\n", 246 sigfile); 247 goto end; 248 } 249 siglen = bio_to_mem(&sig, keysize * 10, sigbio); 250 BIO_free(sigbio); 251 if (siglen <= 0) { 252 BIO_printf(bio_err, "Error reading signature data\n"); 253 goto end; 254 } 255 } 256 if (in) { 257 /* Read the input data */ 258 buf_inlen = bio_to_mem(&buf_in, keysize * 10, in); 259 if (buf_inlen <= 0) { 260 BIO_printf(bio_err, "Error reading input Data\n"); 261 exit(1); 262 } 263 if (rev) { 264 size_t i; 265 unsigned char ctmp; 266 size_t l = (size_t) buf_inlen; 267 for (i = 0; i < l / 2; i++) { 268 ctmp = buf_in[i]; 269 buf_in[i] = buf_in[l - 1 - i]; 270 buf_in[l - 1 - i] = ctmp; 271 } 272 } 273 } 274 if (pkey_op == EVP_PKEY_OP_VERIFY) { 275 rv = EVP_PKEY_verify(ctx, sig, (size_t) siglen, 276 buf_in, (size_t) buf_inlen); 277 if (rv == 1) { 278 BIO_puts(out, "Signature Verified Successfully\n"); 279 ret = 0; 280 } else 281 BIO_puts(out, "Signature Verification Failure\n"); 282 if (rv >= 0) 283 goto end; 284 } else { 285 rv = do_keyop(ctx, pkey_op, NULL, (size_t *)&buf_outlen, 286 buf_in, (size_t) buf_inlen); 287 if (rv > 0) { 288 buf_out = malloc(buf_outlen); 289 if (!buf_out) 290 rv = -1; 291 else 292 rv = do_keyop(ctx, pkey_op, 293 buf_out, (size_t *) & buf_outlen, 294 buf_in, (size_t) buf_inlen); 295 } 296 } 297 298 if (rv <= 0) { 299 BIO_printf(bio_err, "Public Key operation error\n"); 300 ERR_print_errors(bio_err); 301 goto end; 302 } 303 ret = 0; 304 if (asn1parse) { 305 if (!ASN1_parse_dump(out, buf_out, buf_outlen, 1, -1)) 306 ERR_print_errors(bio_err); 307 } else if (hexdump) 308 BIO_dump(out, (char *) buf_out, buf_outlen); 309 else 310 BIO_write(out, buf_out, buf_outlen); 311 312 end: 313 if (ctx) 314 EVP_PKEY_CTX_free(ctx); 315 BIO_free(in); 316 BIO_free_all(out); 317 free(buf_in); 318 free(buf_out); 319 free(sig); 320 321 return ret; 322 } 323 324 static void 325 usage() 326 { 327 BIO_printf(bio_err, "Usage: pkeyutl [options]\n"); 328 BIO_printf(bio_err, "-in file input file\n"); 329 BIO_printf(bio_err, "-out file output file\n"); 330 BIO_printf(bio_err, "-sigfile file signature file (verify operation only)\n"); 331 BIO_printf(bio_err, "-inkey file input key\n"); 332 BIO_printf(bio_err, "-keyform arg private key format - default PEM\n"); 333 BIO_printf(bio_err, "-pubin input is a public key\n"); 334 BIO_printf(bio_err, "-certin input is a certificate carrying a public key\n"); 335 BIO_printf(bio_err, "-pkeyopt X:Y public key options\n"); 336 BIO_printf(bio_err, "-sign sign with private key\n"); 337 BIO_printf(bio_err, "-verify verify with public key\n"); 338 BIO_printf(bio_err, "-verifyrecover verify with public key, recover original data\n"); 339 BIO_printf(bio_err, "-encrypt encrypt with public key\n"); 340 BIO_printf(bio_err, "-decrypt decrypt with private key\n"); 341 BIO_printf(bio_err, "-derive derive shared secret\n"); 342 BIO_printf(bio_err, "-hexdump hex dump output\n"); 343 BIO_printf(bio_err, "-passin arg pass phrase source\n"); 344 345 } 346 347 static EVP_PKEY_CTX * 348 init_ctx(int *pkeysize, 349 char *keyfile, int keyform, int key_type, 350 char *passargin, int pkey_op) 351 { 352 EVP_PKEY *pkey = NULL; 353 EVP_PKEY_CTX *ctx = NULL; 354 char *passin = NULL; 355 int rv = -1; 356 X509 *x; 357 if (((pkey_op == EVP_PKEY_OP_SIGN) || (pkey_op == EVP_PKEY_OP_DECRYPT) 358 || (pkey_op == EVP_PKEY_OP_DERIVE)) 359 && (key_type != KEY_PRIVKEY)) { 360 BIO_printf(bio_err, "A private key is needed for this operation\n"); 361 goto end; 362 } 363 if (!app_passwd(bio_err, passargin, NULL, &passin, NULL)) { 364 BIO_printf(bio_err, "Error getting password\n"); 365 goto end; 366 } 367 switch (key_type) { 368 case KEY_PRIVKEY: 369 pkey = load_key(bio_err, keyfile, keyform, 0, 370 passin, "Private Key"); 371 break; 372 373 case KEY_PUBKEY: 374 pkey = load_pubkey(bio_err, keyfile, keyform, 0, 375 NULL, "Public Key"); 376 break; 377 378 case KEY_CERT: 379 x = load_cert(bio_err, keyfile, keyform, 380 NULL, "Certificate"); 381 if (x) { 382 pkey = X509_get_pubkey(x); 383 X509_free(x); 384 } 385 break; 386 387 } 388 389 *pkeysize = EVP_PKEY_size(pkey); 390 391 if (!pkey) 392 goto end; 393 394 ctx = EVP_PKEY_CTX_new(pkey, NULL); 395 396 EVP_PKEY_free(pkey); 397 398 if (!ctx) 399 goto end; 400 401 switch (pkey_op) { 402 case EVP_PKEY_OP_SIGN: 403 rv = EVP_PKEY_sign_init(ctx); 404 break; 405 406 case EVP_PKEY_OP_VERIFY: 407 rv = EVP_PKEY_verify_init(ctx); 408 break; 409 410 case EVP_PKEY_OP_VERIFYRECOVER: 411 rv = EVP_PKEY_verify_recover_init(ctx); 412 break; 413 414 case EVP_PKEY_OP_ENCRYPT: 415 rv = EVP_PKEY_encrypt_init(ctx); 416 break; 417 418 case EVP_PKEY_OP_DECRYPT: 419 rv = EVP_PKEY_decrypt_init(ctx); 420 break; 421 422 case EVP_PKEY_OP_DERIVE: 423 rv = EVP_PKEY_derive_init(ctx); 424 break; 425 } 426 427 if (rv <= 0) { 428 EVP_PKEY_CTX_free(ctx); 429 ctx = NULL; 430 } 431 end: 432 433 free(passin); 434 435 return ctx; 436 437 438 } 439 440 static int 441 setup_peer(BIO * err, EVP_PKEY_CTX * ctx, int peerform, 442 const char *file) 443 { 444 EVP_PKEY *peer = NULL; 445 int ret; 446 if (!ctx) { 447 BIO_puts(err, "-peerkey command before -inkey\n"); 448 return 0; 449 } 450 peer = load_pubkey(bio_err, file, peerform, 0, NULL, "Peer Key"); 451 452 if (!peer) { 453 BIO_printf(bio_err, "Error reading peer key %s\n", file); 454 ERR_print_errors(err); 455 return 0; 456 } 457 ret = EVP_PKEY_derive_set_peer(ctx, peer); 458 459 EVP_PKEY_free(peer); 460 if (ret <= 0) 461 ERR_print_errors(err); 462 return ret; 463 } 464 465 static int 466 do_keyop(EVP_PKEY_CTX * ctx, int pkey_op, 467 unsigned char *out, size_t * poutlen, 468 unsigned char *in, size_t inlen) 469 { 470 int rv = 0; 471 switch (pkey_op) { 472 case EVP_PKEY_OP_VERIFYRECOVER: 473 rv = EVP_PKEY_verify_recover(ctx, out, poutlen, in, inlen); 474 break; 475 476 case EVP_PKEY_OP_SIGN: 477 rv = EVP_PKEY_sign(ctx, out, poutlen, in, inlen); 478 break; 479 480 case EVP_PKEY_OP_ENCRYPT: 481 rv = EVP_PKEY_encrypt(ctx, out, poutlen, in, inlen); 482 break; 483 484 case EVP_PKEY_OP_DECRYPT: 485 rv = EVP_PKEY_decrypt(ctx, out, poutlen, in, inlen); 486 break; 487 488 case EVP_PKEY_OP_DERIVE: 489 rv = EVP_PKEY_derive(ctx, out, poutlen); 490 break; 491 492 } 493 return rv; 494 } 495