-/* 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.
*/
/* ====================================================================
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 **);
{
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;
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;
if (!strcmp(*argv,"-in"))
{
if (--argc < 1) badarg = 1;
- infile= *(++argv);
+ else infile= *(++argv);
}
else if (!strcmp(*argv,"-out"))
{
if (--argc < 1) badarg = 1;
- outfile= *(++argv);
+ else outfile= *(++argv);
}
else if (!strcmp(*argv,"-sigfile"))
{
if (--argc < 1) badarg = 1;
- sigfile= *(++argv);
+ else sigfile= *(++argv);
}
else if(!strcmp(*argv, "-inkey"))
{
{
ctx = init_ctx(&keysize,
*(++argv), keyform, key_type,
- passargin, pkey_op, engine);
+ passargin, pkey_op, e);
if (!ctx)
{
BIO_puts(bio_err,
}
}
}
+ 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 passargin= *(++argv);
+ }
+ else if (strcmp(*argv,"-peerform") == 0)
+ {
+ if (--argc < 1) badarg = 1;
+ else peerform=str2fmt(*(++argv));
}
else if (strcmp(*argv,"-keyform") == 0)
{
if (--argc < 1) badarg = 1;
- keyform=str2fmt(*(++argv));
+ else keyform=str2fmt(*(++argv));
}
#ifndef OPENSSL_NO_ENGINE
else if(!strcmp(*argv, "-engine"))
if (--argc < 1)
badarg = 1;
else
- engine = *(++argv);
+ e = setup_engine(bio_err, *(++argv), 0);
}
#endif
else if(!strcmp(*argv, "-pubin"))
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)
/* 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)
{
}
}
- 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)
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");
if (!pkey)
goto end;
- ctx = EVP_PKEY_CTX_new(pkey);
+ ctx = EVP_PKEY_CTX_new(pkey, e);
EVP_PKEY_free(pkey);
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)
}
+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;
+ }