X-Git-Url: https://git.openssl.org/gitweb/?p=openssl.git;a=blobdiff_plain;f=apps%2Fpkeyutl.c;h=22a6c4bf397fe9253d3d51cbf0874bc3be2c5764;hp=1ecde3cd858e1e3f64de390d365f1e69052d418d;hb=637f374ad49d5f6d4f81d87d7cdd226428aa470c;hpb=f5cda4cbb17c908ceef33f4f52d94e8e04b7c1ab diff --git a/apps/pkeyutl.c b/apps/pkeyutl.c index 1ecde3cd85..22a6c4bf39 100644 --- a/apps/pkeyutl.c +++ b/apps/pkeyutl.c @@ -1,4 +1,4 @@ -/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL +/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL * project 2006. */ /* ==================================================================== @@ -74,7 +74,14 @@ static void usage(void); static EVP_PKEY_CTX *init_ctx(int *pkeysize, char *keyfile, int keyform, int key_type, - char *passargin, int pkey_op, char *engine); + char *passargin, int pkey_op, ENGINE *e); + +static int setup_peer(BIO *err, EVP_PKEY_CTX *ctx, int peerform, + const char *file); + +static int do_keyop(EVP_PKEY_CTX *ctx, int pkey_op, + unsigned char *out, size_t *poutlen, + unsigned char *in, size_t inlen); int MAIN(int argc, char **); @@ -82,9 +89,9 @@ int MAIN(int argc, char **argv) { BIO *in = NULL, *out = NULL; char *infile = NULL, *outfile = NULL, *sigfile = NULL; - char *engine = NULL; + ENGINE *e = NULL; int pkey_op = EVP_PKEY_OP_SIGN, key_type = KEY_PRIVKEY; - int keyform = FORMAT_PEM; + int keyform = FORMAT_PEM, peerform = FORMAT_PEM; char badarg = 0, rev = 0; char hexdump = 0, asn1parse = 0; EVP_PKEY_CTX *ctx = NULL; @@ -92,7 +99,8 @@ int MAIN(int argc, char **argv) int keysize = -1; unsigned char *buf_in = NULL, *buf_out = NULL, *sig = NULL; - int buf_inlen, buf_outlen, siglen = -1; + size_t buf_outlen; + int buf_inlen = 0, siglen = -1; int ret = 1, rv = -1; @@ -131,7 +139,7 @@ int MAIN(int argc, char **argv) { ctx = init_ctx(&keysize, *(++argv), keyform, key_type, - passargin, pkey_op, engine); + passargin, pkey_op, e); if (!ctx) { BIO_puts(bio_err, @@ -141,11 +149,23 @@ int MAIN(int argc, char **argv) } } } + else if (!strcmp(*argv,"-peerkey")) + { + if (--argc < 1) + badarg = 1; + else if (!setup_peer(bio_err, ctx, peerform, *(++argv))) + badarg = 1; + } else if (!strcmp(*argv,"-passin")) { if (--argc < 1) badarg = 1; passargin= *(++argv); } + else if (strcmp(*argv,"-peerform") == 0) + { + if (--argc < 1) badarg = 1; + peerform=str2fmt(*(++argv)); + } else if (strcmp(*argv,"-keyform") == 0) { if (--argc < 1) badarg = 1; @@ -157,7 +177,7 @@ int MAIN(int argc, char **argv) if (--argc < 1) badarg = 1; else - engine = *(++argv); + e = setup_engine(bio_err, *(++argv), 0); } #endif else if(!strcmp(*argv, "-pubin")) @@ -180,14 +200,16 @@ int MAIN(int argc, char **argv) pkey_op = EVP_PKEY_OP_ENCRYPT; else if(!strcmp(*argv, "-decrypt")) pkey_op = EVP_PKEY_OP_DECRYPT; - else if (strcmp(*argv,"-param") == 0) + else if(!strcmp(*argv, "-derive")) + pkey_op = EVP_PKEY_OP_DERIVE; + else if (strcmp(*argv,"-pkeyopt") == 0) { if (--argc < 1) badarg = 1; - if (!ctx) + else if (!ctx) { BIO_puts(bio_err, - "-param command before -inkey\n"); + "-pkeyopt command before -inkey\n"); badarg = 1; } else if (pkey_ctrl_string(ctx, *(++argv)) <= 0) @@ -228,17 +250,21 @@ int MAIN(int argc, char **argv) /* FIXME: seed PRNG only if needed */ app_RAND_load_file(NULL, bio_err, 0); - if(infile) + if (pkey_op != EVP_PKEY_OP_DERIVE) { - if(!(in = BIO_new_file(infile, "rb"))) + if(infile) { - BIO_printf(bio_err, "Error Reading Input File\n"); - ERR_print_errors(bio_err); - goto end; + if(!(in = BIO_new_file(infile, "rb"))) + { + BIO_puts(bio_err, + "Error Opening Input File\n"); + ERR_print_errors(bio_err); + goto end; + } } + else + in = BIO_new_fp(stdin, BIO_NOCLOSE); } - else - in = BIO_new_fp(stdin, BIO_NOCLOSE); if(outfile) { @@ -278,58 +304,54 @@ int MAIN(int argc, char **argv) } } - buf_out = OPENSSL_malloc(keysize); - - /* Read the input data */ - buf_inlen = bio_to_mem(&buf_in, keysize * 10, in); - if(buf_inlen <= 0) - { - BIO_printf(bio_err, "Error reading input Data\n"); - exit(1); - } - if(rev) + if (in) { - int i; - unsigned char ctmp; - for(i = 0; i < buf_inlen/2; i++) + /* Read the input data */ + buf_inlen = bio_to_mem(&buf_in, keysize * 10, in); + if(buf_inlen <= 0) { - ctmp = buf_in[i]; - buf_in[i] = buf_in[buf_inlen - 1 - i]; - buf_in[buf_inlen - 1 - i] = ctmp; + BIO_printf(bio_err, "Error reading input Data\n"); + exit(1); + } + if(rev) + { + size_t i; + unsigned char ctmp; + size_t l = (size_t)buf_inlen; + for(i = 0; i < l/2; i++) + { + ctmp = buf_in[i]; + buf_in[i] = buf_in[l - 1 - i]; + buf_in[l - 1 - i] = ctmp; + } } } - switch(pkey_op) - { - case EVP_PKEY_OP_VERIFYRECOVER: - rv = EVP_PKEY_verify_recover(ctx, buf_out, &buf_outlen, - buf_in, buf_inlen); - break; - - case EVP_PKEY_OP_SIGN: - rv = EVP_PKEY_sign(ctx, buf_out, &buf_outlen, - buf_in, buf_inlen); - break; - case EVP_PKEY_OP_ENCRYPT: - rv = EVP_PKEY_encrypt(ctx, buf_out, &buf_outlen, - buf_in, buf_inlen); - break; - - case EVP_PKEY_OP_DECRYPT: - rv = EVP_PKEY_decrypt(ctx, buf_out, &buf_outlen, - buf_in, buf_inlen); - break; - - case EVP_PKEY_OP_VERIFY: - rv = EVP_PKEY_verify(ctx, sig, siglen, buf_in, buf_inlen); + if(pkey_op == EVP_PKEY_OP_VERIFY) + { + rv = EVP_PKEY_verify(ctx, sig, (size_t)siglen, + buf_in, (size_t)buf_inlen); if (rv == 0) BIO_puts(out, "Signature Verification Failure\n"); else if (rv == 1) BIO_puts(out, "Signature Verified Successfully\n"); if (rv >= 0) goto end; - break; - + } + else + { + rv = do_keyop(ctx, pkey_op, NULL, (size_t *)&buf_outlen, + buf_in, (size_t)buf_inlen); + if (rv > 0) + { + buf_out = OPENSSL_malloc(buf_outlen); + if (!buf_out) + rv = -1; + else + rv = do_keyop(ctx, pkey_op, + buf_out, (size_t *)&buf_outlen, + buf_in, (size_t)buf_inlen); + } } if(rv <= 0) @@ -368,34 +390,37 @@ static void usage() BIO_printf(bio_err, "Usage: pkeyutl [options]\n"); BIO_printf(bio_err, "-in file input file\n"); BIO_printf(bio_err, "-out file output file\n"); + BIO_printf(bio_err, "-sigfile file signature file (verify operation only)\n"); BIO_printf(bio_err, "-inkey file input key\n"); BIO_printf(bio_err, "-keyform arg private key format - default PEM\n"); - BIO_printf(bio_err, "-pubin input is an RSA public\n"); - BIO_printf(bio_err, "-certin input is a certificate carrying an RSA public key\n"); - BIO_printf(bio_err, "-ctrl X:Y control parameters\n"); + BIO_printf(bio_err, "-pubin input is a public key\n"); + BIO_printf(bio_err, "-certin input is a certificate carrying a public key\n"); + BIO_printf(bio_err, "-pkeyopt X:Y public key options\n"); BIO_printf(bio_err, "-sign sign with private key\n"); BIO_printf(bio_err, "-verify verify with public key\n"); + BIO_printf(bio_err, "-verifyrecover verify with public key, recover original data\n"); BIO_printf(bio_err, "-encrypt encrypt with public key\n"); BIO_printf(bio_err, "-decrypt decrypt with private key\n"); + BIO_printf(bio_err, "-derive derive shared secret\n"); BIO_printf(bio_err, "-hexdump hex dump output\n"); #ifndef OPENSSL_NO_ENGINE BIO_printf(bio_err, "-engine e use engine e, possibly a hardware device.\n"); - BIO_printf(bio_err, "-passin arg pass phrase source\n"); #endif + BIO_printf(bio_err, "-passin arg pass phrase source\n"); } static EVP_PKEY_CTX *init_ctx(int *pkeysize, char *keyfile, int keyform, int key_type, - char *passargin, int pkey_op, char *engine) + char *passargin, int pkey_op, ENGINE *e) { - ENGINE *e = NULL; EVP_PKEY *pkey = NULL; EVP_PKEY_CTX *ctx = NULL; char *passin = NULL; int rv = -1; X509 *x; - if(((pkey_op == EVP_PKEY_OP_SIGN) || (pkey_op == EVP_PKEY_OP_DECRYPT)) + if(((pkey_op == EVP_PKEY_OP_SIGN) || (pkey_op == EVP_PKEY_OP_DECRYPT) + || (pkey_op == EVP_PKEY_OP_DERIVE)) && (key_type != KEY_PRIVKEY)) { BIO_printf(bio_err, "A private key is needed for this operation\n"); @@ -435,7 +460,7 @@ static EVP_PKEY_CTX *init_ctx(int *pkeysize, if (!pkey) goto end; - ctx = EVP_PKEY_CTX_new(pkey, NULL); + ctx = EVP_PKEY_CTX_new(pkey, e); EVP_PKEY_free(pkey); @@ -463,6 +488,10 @@ static EVP_PKEY_CTX *init_ctx(int *pkeysize, case EVP_PKEY_OP_DECRYPT: rv = EVP_PKEY_decrypt_init(ctx); break; + + case EVP_PKEY_OP_DERIVE: + rv = EVP_PKEY_derive_init(ctx); + break; } if (rv <= 0) @@ -481,3 +510,61 @@ static EVP_PKEY_CTX *init_ctx(int *pkeysize, } +static int setup_peer(BIO *err, EVP_PKEY_CTX *ctx, int peerform, + const char *file) + { + EVP_PKEY *peer = NULL; + int ret; + if (!ctx) + { + BIO_puts(err, "-peerkey command before -inkey\n"); + return 0; + } + + peer = load_pubkey(bio_err, file, peerform, 0, NULL, NULL, "Peer Key"); + + if (!peer) + { + BIO_printf(bio_err, "Error reading peer key %s\n", file); + ERR_print_errors(err); + return 0; + } + + ret = EVP_PKEY_derive_set_peer(ctx, peer); + + EVP_PKEY_free(peer); + if (ret <= 0) + ERR_print_errors(err); + return ret; + } + +static int do_keyop(EVP_PKEY_CTX *ctx, int pkey_op, + unsigned char *out, size_t *poutlen, + unsigned char *in, size_t inlen) + { + int rv = 0; + switch(pkey_op) + { + case EVP_PKEY_OP_VERIFYRECOVER: + rv = EVP_PKEY_verify_recover(ctx, out, poutlen, in, inlen); + break; + + case EVP_PKEY_OP_SIGN: + rv = EVP_PKEY_sign(ctx, out, poutlen, in, inlen); + break; + + case EVP_PKEY_OP_ENCRYPT: + rv = EVP_PKEY_encrypt(ctx, out, poutlen, in, inlen); + break; + + case EVP_PKEY_OP_DECRYPT: + rv = EVP_PKEY_decrypt(ctx, out, poutlen, in, inlen); + break; + + case EVP_PKEY_OP_DERIVE: + rv = EVP_PKEY_derive(ctx, out, poutlen); + break; + + } + return rv; + }