diff options
Diffstat (limited to 'apps')
-rw-r--r-- | apps/pkeyutl.c | 127 |
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"); |