summaryrefslogtreecommitdiffstats
path: root/apps
diff options
context:
space:
mode:
Diffstat (limited to 'apps')
-rw-r--r--apps/pkeyutl.c127
1 files changed, 80 insertions, 47 deletions
diff --git a/apps/pkeyutl.c b/apps/pkeyutl.c
index b73ef3297b..961a2f7650 100644
--- a/apps/pkeyutl.c
+++ b/apps/pkeyutl.c
@@ -20,12 +20,15 @@
#define KEY_PUBKEY 2
#define KEY_CERT 3
+static EVP_PKEY *get_pkey(const char *kdfalg,
+ const char *keyfile, int keyform, int key_type,
+ char *passinarg, int pkey_op, ENGINE *e);
static EVP_PKEY_CTX *init_ctx(const char *kdfalg, int *pkeysize,
- const char *keyfile, int keyform, int key_type,
- char *passinarg, int pkey_op, ENGINE *e,
- const int impl, int rawin, EVP_PKEY **ppkey,
- EVP_MD_CTX *mctx, const char *digestname, const char *kemop,
- OSSL_LIB_CTX *libctx, const char *propq);
+ int pkey_op, ENGINE *e,
+ const int engine_impl, int rawin,
+ EVP_PKEY *pkey /* ownership is passed to ctx */,
+ EVP_MD_CTX *mctx, const char *digestname,
+ const char *kemop, OSSL_LIB_CTX *libctx, const char *propq);
static int setup_peer(EVP_PKEY_CTX *ctx, int peerform, const char *file,
ENGINE *e);
@@ -40,6 +43,14 @@ static int do_raw_keyop(int pkey_op, EVP_MD_CTX *mctx,
int filesize, unsigned char *sig, int siglen,
unsigned char **out, size_t *poutlen);
+static int only_rawin(const EVP_PKEY *pkey)
+{
+ if (pkey == NULL)
+ return 0;
+ return EVP_PKEY_is_a(pkey, "ED25519")
+ || EVP_PKEY_is_a(pkey, "ED448");
+}
+
typedef enum OPTION_choice {
OPT_COMMON,
OPT_ENGINE, OPT_ENGINE_IMPL, OPT_IN, OPT_OUT,
@@ -72,7 +83,7 @@ const OPTIONS pkeyutl_options[] = {
OPT_SECTION("Input"),
{"in", OPT_IN, '<', "Input file - default stdin"},
- {"rawin", OPT_RAWIN, '-', "Indicate the input data is in raw form"},
+ {"rawin", OPT_RAWIN, '-', "Indicate that signature input data is not hashed"},
{"inkey", OPT_INKEY, 's', "Input key, by default private key"},
{"pubin", OPT_PUBIN, '-', "Input key is a public key"},
{"passin", OPT_PASSIN, 's', "Input file pass phrase source"},
@@ -277,26 +288,6 @@ int pkeyutl_main(int argc, char **argv)
if (!app_RAND_load())
goto end;
- if (rawin && pkey_op != EVP_PKEY_OP_SIGN && pkey_op != EVP_PKEY_OP_VERIFY) {
- BIO_printf(bio_err,
- "%s: -rawin can only be used with -sign or -verify\n",
- prog);
- goto opthelp;
- }
-
- if (digestname != NULL && !rawin) {
- BIO_printf(bio_err,
- "%s: -digest can only be used with -rawin\n",
- prog);
- goto opthelp;
- }
-
- if (rawin && rev) {
- BIO_printf(bio_err, "%s: -rev cannot be used with raw input\n",
- prog);
- goto opthelp;
- }
-
if (kdfalg != NULL) {
if (kdflen == 0) {
BIO_printf(bio_err,
@@ -313,14 +304,45 @@ int pkeyutl_main(int argc, char **argv)
goto opthelp;
}
+ pkey = get_pkey(kdfalg, inkey, keyform, key_type, passinarg, pkey_op, e);
+ if (pkey_op == EVP_PKEY_OP_SIGN || pkey_op == EVP_PKEY_OP_VERIFY) {
+ if (only_rawin(pkey)) {
+ if ((EVP_PKEY_is_a(pkey, "ED25519") || EVP_PKEY_is_a(pkey, "ED448"))
+ && digestname != NULL) {
+ BIO_printf(bio_err,
+ "%s: -digest (prehash) is not supported with EdDSA\n", prog);
+ EVP_PKEY_free(pkey);
+ goto end;
+ }
+ rawin = 1; /* implied for Ed25519(ph) and Ed448(ph) and maybe others in the future */
+ }
+ } else if (rawin) {
+ BIO_printf(bio_err,
+ "%s: -rawin can only be used with -sign or -verify\n", prog);
+ EVP_PKEY_free(pkey);
+ goto opthelp;
+ }
+ if (digestname != NULL && !rawin) {
+ BIO_printf(bio_err,
+ "%s: -digest can only be used with -rawin\n", prog);
+ EVP_PKEY_free(pkey);
+ goto opthelp;
+ }
+
+ if (rawin && rev) {
+ BIO_printf(bio_err, "%s: -rev cannot be used with raw input\n", prog);
+ EVP_PKEY_free(pkey);
+ goto opthelp;
+ }
+
if (rawin) {
if ((mctx = EVP_MD_CTX_new()) == NULL) {
BIO_printf(bio_err, "Error: out of memory\n");
+ EVP_PKEY_free(pkey);
goto end;
}
}
- ctx = init_ctx(kdfalg, &keysize, inkey, keyform, key_type,
- passinarg, pkey_op, e, engine_impl, rawin, &pkey,
+ ctx = init_ctx(kdfalg, &keysize, pkey_op, e, engine_impl, rawin, pkey,
mctx, digestname, kemop, libctx, app_get0_propq());
if (ctx == NULL) {
BIO_printf(bio_err, "%s: Error initializing context\n", prog);
@@ -374,8 +396,10 @@ int pkeyutl_main(int argc, char **argv)
goto end;
}
} else {
- /* Get password as a passin argument: First split option name
- * and passphrase argument into two strings */
+ /*
+ * Get password as a passin argument: First split option name
+ * and passphrase argument into two strings
+ */
*passin = 0;
passin++;
if (app_passwd(passin, NULL, &passwd, NULL) == 0) {
@@ -457,6 +481,7 @@ int pkeyutl_main(int argc, char **argv)
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];
@@ -553,29 +578,23 @@ int pkeyutl_main(int argc, char **argv)
return ret;
}
-static EVP_PKEY_CTX *init_ctx(const char *kdfalg, int *pkeysize,
- const char *keyfile, int keyform, int key_type,
- char *passinarg, int pkey_op, ENGINE *e,
- const int engine_impl, int rawin,
- EVP_PKEY **ppkey, EVP_MD_CTX *mctx, const char *digestname,
- const char *kemop, OSSL_LIB_CTX *libctx, const char *propq)
+static EVP_PKEY *get_pkey(const char *kdfalg,
+ const char *keyfile, int keyform, int key_type,
+ char *passinarg, int pkey_op, ENGINE *e)
{
EVP_PKEY *pkey = NULL;
- EVP_PKEY_CTX *ctx = NULL;
- ENGINE *impl = NULL;
char *passin = NULL;
- int rv = -1;
X509 *x;
if (((pkey_op == EVP_PKEY_OP_SIGN) || (pkey_op == EVP_PKEY_OP_DECRYPT)
|| (pkey_op == EVP_PKEY_OP_DERIVE))
&& (key_type != KEY_PRIVKEY && kdfalg == NULL)) {
BIO_printf(bio_err, "A private key is needed for this operation\n");
- goto end;
+ return NULL;
}
if (!app_passwd(passinarg, NULL, &passin, NULL)) {
BIO_printf(bio_err, "Error getting password\n");
- goto end;
+ return NULL;
}
switch (key_type) {
case KEY_PRIVKEY:
@@ -598,6 +617,20 @@ static EVP_PKEY_CTX *init_ctx(const char *kdfalg, int *pkeysize,
break;
}
+ OPENSSL_free(passin);
+ return pkey;
+}
+
+static EVP_PKEY_CTX *init_ctx(const char *kdfalg, int *pkeysize,
+ int pkey_op, ENGINE *e,
+ const int engine_impl, int rawin,
+ EVP_PKEY *pkey /* ownership is passed to ctx */,
+ EVP_MD_CTX *mctx, const char *digestname,
+ const char *kemop, OSSL_LIB_CTX *libctx, const char *propq)
+{
+ EVP_PKEY_CTX *ctx = NULL;
+ ENGINE *impl = NULL;
+ int rv = -1;
#ifndef OPENSSL_NO_ENGINE
if (engine_impl)
@@ -628,9 +661,8 @@ static EVP_PKEY_CTX *init_ctx(const char *kdfalg, int *pkeysize,
ctx = EVP_PKEY_CTX_new(pkey, impl);
else
ctx = EVP_PKEY_CTX_new_from_pkey(libctx, pkey, propq);
- if (ppkey != NULL)
- *ppkey = pkey;
EVP_PKEY_free(pkey);
+ pkey = NULL;
}
if (ctx == NULL)
@@ -696,10 +728,11 @@ static EVP_PKEY_CTX *init_ctx(const char *kdfalg, int *pkeysize,
ctx = NULL;
}
- end:
- OPENSSL_free(passin);
return ctx;
+ end:
+ EVP_PKEY_free(pkey);
+ return NULL;
}
static int setup_peer(EVP_PKEY_CTX *ctx, int peerform, const char *file,
@@ -729,6 +762,7 @@ static int do_keyop(EVP_PKEY_CTX *ctx, int pkey_op,
unsigned char *secret, size_t *pseclen)
{
int rv = 0;
+
switch (pkey_op) {
case EVP_PKEY_OP_VERIFYRECOVER:
rv = EVP_PKEY_verify_recover(ctx, out, poutlen, in, inlen);
@@ -775,8 +809,7 @@ static int do_raw_keyop(int pkey_op, EVP_MD_CTX *mctx,
int buf_len = 0;
/* Some algorithms only support oneshot digests */
- if (EVP_PKEY_get_id(pkey) == EVP_PKEY_ED25519
- || EVP_PKEY_get_id(pkey) == EVP_PKEY_ED448) {
+ if (only_rawin(pkey)) {
if (filesize < 0) {
BIO_printf(bio_err,
"Error: unable to determine file size for oneshot operation\n");