mirror of
https://github.com/QuasarApp/openssl.git
synced 2025-04-29 03:04:37 +00:00
Fix -pkeyopt handling in apps/pkeyutl -rawin
The EVP_DigestSignInit and EVP_DigestVerifyInit actually have to be initialized before EVP_PKEY_CTX_ctrl_str is invoked. Otherwise, when the ctx not initialized, the ctrl command fails. Reviewed-by: Dmitry Belyavskiy <beldmit@gmail.com> Reviewed-by: Tomas Mraz <tomas@openssl.org> (Merged from https://github.com/openssl/openssl/pull/13828)
This commit is contained in:
parent
7f90026b3f
commit
6ceaf67257
@ -24,7 +24,8 @@ 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,
|
||||
OSSL_LIB_CTX *libctx);
|
||||
EVP_MD_CTX *mctx, const char *digestname,
|
||||
OSSL_LIB_CTX *libctx, const char *propq);
|
||||
|
||||
static int setup_peer(EVP_PKEY_CTX *ctx, int peerform, const char *file,
|
||||
ENGINE *e);
|
||||
@ -33,8 +34,8 @@ static int do_keyop(EVP_PKEY_CTX *ctx, int pkey_op,
|
||||
unsigned char *out, size_t *poutlen,
|
||||
const unsigned char *in, size_t inlen);
|
||||
|
||||
static int do_raw_keyop(int pkey_op, EVP_PKEY_CTX *ctx,
|
||||
const EVP_MD *md, EVP_PKEY *pkey, BIO *in,
|
||||
static int do_raw_keyop(int pkey_op, EVP_MD_CTX *mctx,
|
||||
EVP_PKEY *pkey, BIO *in,
|
||||
int filesize, unsigned char *sig, int siglen,
|
||||
unsigned char **out, size_t *poutlen);
|
||||
|
||||
@ -122,7 +123,7 @@ int pkeyutl_main(int argc, char **argv)
|
||||
STACK_OF(OPENSSL_STRING) *pkeyopts = NULL;
|
||||
STACK_OF(OPENSSL_STRING) *pkeyopts_passin = NULL;
|
||||
int rawin = 0;
|
||||
const EVP_MD *md = NULL;
|
||||
EVP_MD_CTX *mctx = NULL;
|
||||
int filesize = -1;
|
||||
OSSL_LIB_CTX *libctx = app_get0_libctx();
|
||||
|
||||
@ -255,10 +256,6 @@ int pkeyutl_main(int argc, char **argv)
|
||||
goto opthelp;
|
||||
|
||||
app_RAND_load();
|
||||
if (digestname != NULL) {
|
||||
if (!opt_md(digestname, &md))
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (rawin && pkey_op != EVP_PKEY_OP_SIGN && pkey_op != EVP_PKEY_OP_VERIFY) {
|
||||
BIO_printf(bio_err,
|
||||
@ -267,7 +264,7 @@ int pkeyutl_main(int argc, char **argv)
|
||||
goto opthelp;
|
||||
}
|
||||
|
||||
if (md != NULL && !rawin) {
|
||||
if (digestname != NULL && !rawin) {
|
||||
BIO_printf(bio_err,
|
||||
"%s: -digest can only be used with -rawin\n",
|
||||
prog);
|
||||
@ -295,9 +292,16 @@ int pkeyutl_main(int argc, char **argv)
|
||||
"%s: no peer key given (-peerkey parameter).\n", prog);
|
||||
goto opthelp;
|
||||
}
|
||||
|
||||
if (rawin) {
|
||||
if ((mctx = EVP_MD_CTX_new()) == NULL) {
|
||||
BIO_printf(bio_err, "Error: out of memory\n");
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
ctx = init_ctx(kdfalg, &keysize, inkey, keyform, key_type,
|
||||
passinarg, pkey_op, e, engine_impl, rawin, &pkey,
|
||||
libctx);
|
||||
mctx, digestname, libctx, app_get0_propq());
|
||||
if (ctx == NULL) {
|
||||
BIO_printf(bio_err, "%s: Error initializing context\n", prog);
|
||||
ERR_print_errors(bio_err);
|
||||
@ -446,7 +450,7 @@ int pkeyutl_main(int argc, char **argv)
|
||||
|
||||
if (pkey_op == EVP_PKEY_OP_VERIFY) {
|
||||
if (rawin) {
|
||||
rv = do_raw_keyop(pkey_op, ctx, md, pkey, in, filesize, sig, siglen,
|
||||
rv = do_raw_keyop(pkey_op, mctx, pkey, in, filesize, sig, siglen,
|
||||
NULL, 0);
|
||||
} else {
|
||||
rv = EVP_PKEY_verify(ctx, sig, (size_t)siglen,
|
||||
@ -466,7 +470,7 @@ int pkeyutl_main(int argc, char **argv)
|
||||
} else {
|
||||
if (rawin) {
|
||||
/* rawin allocates the buffer in do_raw_keyop() */
|
||||
rv = do_raw_keyop(pkey_op, ctx, md, pkey, in, filesize, NULL, 0,
|
||||
rv = do_raw_keyop(pkey_op, mctx, pkey, in, filesize, NULL, 0,
|
||||
&buf_out, (size_t *)&buf_outlen);
|
||||
} else {
|
||||
rv = do_keyop(ctx, pkey_op, NULL, (size_t *)&buf_outlen,
|
||||
@ -500,6 +504,7 @@ int pkeyutl_main(int argc, char **argv)
|
||||
}
|
||||
|
||||
end:
|
||||
EVP_MD_CTX_free(mctx);
|
||||
EVP_PKEY_CTX_free(ctx);
|
||||
release_engine(e);
|
||||
BIO_free(in);
|
||||
@ -517,8 +522,8 @@ 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,
|
||||
OSSL_LIB_CTX *libctx)
|
||||
EVP_PKEY **ppkey, EVP_MD_CTX *mctx, const char *digestname,
|
||||
OSSL_LIB_CTX *libctx, const char *propq)
|
||||
{
|
||||
EVP_PKEY *pkey = NULL;
|
||||
EVP_PKEY_CTX *ctx = NULL;
|
||||
@ -578,7 +583,7 @@ static EVP_PKEY_CTX *init_ctx(const char *kdfalg, int *pkeysize,
|
||||
if (impl != NULL)
|
||||
ctx = EVP_PKEY_CTX_new_id(kdfnid, impl);
|
||||
else
|
||||
ctx = EVP_PKEY_CTX_new_from_name(libctx, kdfalg, app_get0_propq());
|
||||
ctx = EVP_PKEY_CTX_new_from_name(libctx, kdfalg, propq);
|
||||
} else {
|
||||
if (pkey == NULL)
|
||||
goto end;
|
||||
@ -587,7 +592,7 @@ static EVP_PKEY_CTX *init_ctx(const char *kdfalg, int *pkeysize,
|
||||
if (impl != NULL)
|
||||
ctx = EVP_PKEY_CTX_new(pkey, impl);
|
||||
else
|
||||
ctx = EVP_PKEY_CTX_new_from_pkey(libctx, pkey, app_get0_propq());
|
||||
ctx = EVP_PKEY_CTX_new_from_pkey(libctx, pkey, propq);
|
||||
if (ppkey != NULL)
|
||||
*ppkey = pkey;
|
||||
EVP_PKEY_free(pkey);
|
||||
@ -596,13 +601,19 @@ static EVP_PKEY_CTX *init_ctx(const char *kdfalg, int *pkeysize,
|
||||
if (ctx == NULL)
|
||||
goto end;
|
||||
|
||||
/*
|
||||
* If rawin then we don't need to actually initialise the EVP_PKEY_CTX
|
||||
* itself. That will get initialised during EVP_DigestSignInit or
|
||||
* EVP_DigestVerifyInit.
|
||||
*/
|
||||
if (rawin) {
|
||||
rv = 1;
|
||||
EVP_MD_CTX_set_pkey_ctx(mctx, ctx);
|
||||
|
||||
switch (pkey_op) {
|
||||
case EVP_PKEY_OP_SIGN:
|
||||
rv = EVP_DigestSignInit_ex(mctx, NULL, digestname, libctx, propq, pkey);
|
||||
break;
|
||||
|
||||
case EVP_PKEY_OP_VERIFY:
|
||||
rv = EVP_DigestVerifyInit_ex(mctx, NULL, digestname, libctx, propq, pkey);
|
||||
break;
|
||||
}
|
||||
|
||||
} else {
|
||||
switch (pkey_op) {
|
||||
case EVP_PKEY_OP_SIGN:
|
||||
@ -698,23 +709,16 @@ static int do_keyop(EVP_PKEY_CTX *ctx, int pkey_op,
|
||||
|
||||
#define TBUF_MAXSIZE 2048
|
||||
|
||||
static int do_raw_keyop(int pkey_op, EVP_PKEY_CTX *ctx,
|
||||
const EVP_MD *md, EVP_PKEY *pkey, BIO *in,
|
||||
static int do_raw_keyop(int pkey_op, EVP_MD_CTX *mctx,
|
||||
EVP_PKEY *pkey, BIO *in,
|
||||
int filesize, unsigned char *sig, int siglen,
|
||||
unsigned char **out, size_t *poutlen)
|
||||
{
|
||||
int rv = 0;
|
||||
EVP_MD_CTX *mctx = NULL;
|
||||
unsigned char tbuf[TBUF_MAXSIZE];
|
||||
unsigned char *mbuf = NULL;
|
||||
int buf_len = 0;
|
||||
|
||||
if ((mctx = EVP_MD_CTX_new()) == NULL) {
|
||||
BIO_printf(bio_err, "Error: out of memory\n");
|
||||
return rv;
|
||||
}
|
||||
EVP_MD_CTX_set_pkey_ctx(mctx, ctx);
|
||||
|
||||
/* Some algorithms only support oneshot digests */
|
||||
if (EVP_PKEY_id(pkey) == EVP_PKEY_ED25519
|
||||
|| EVP_PKEY_id(pkey) == EVP_PKEY_ED448) {
|
||||
@ -726,8 +730,6 @@ static int do_raw_keyop(int pkey_op, EVP_PKEY_CTX *ctx,
|
||||
mbuf = app_malloc(filesize, "oneshot sign/verify buffer");
|
||||
switch(pkey_op) {
|
||||
case EVP_PKEY_OP_VERIFY:
|
||||
if (EVP_DigestVerifyInit(mctx, NULL, md, NULL, pkey) != 1)
|
||||
goto end;
|
||||
buf_len = BIO_read(in, mbuf, filesize);
|
||||
if (buf_len != filesize) {
|
||||
BIO_printf(bio_err, "Error reading raw input data\n");
|
||||
@ -736,8 +738,6 @@ static int do_raw_keyop(int pkey_op, EVP_PKEY_CTX *ctx,
|
||||
rv = EVP_DigestVerify(mctx, sig, (size_t)siglen, mbuf, buf_len);
|
||||
break;
|
||||
case EVP_PKEY_OP_SIGN:
|
||||
if (EVP_DigestSignInit(mctx, NULL, md, NULL, pkey) != 1)
|
||||
goto end;
|
||||
buf_len = BIO_read(in, mbuf, filesize);
|
||||
if (buf_len != filesize) {
|
||||
BIO_printf(bio_err, "Error reading raw input data\n");
|
||||
@ -755,8 +755,6 @@ static int do_raw_keyop(int pkey_op, EVP_PKEY_CTX *ctx,
|
||||
|
||||
switch(pkey_op) {
|
||||
case EVP_PKEY_OP_VERIFY:
|
||||
if (EVP_DigestVerifyInit(mctx, NULL, md, NULL, pkey) != 1)
|
||||
goto end;
|
||||
for (;;) {
|
||||
buf_len = BIO_read(in, tbuf, TBUF_MAXSIZE);
|
||||
if (buf_len == 0)
|
||||
@ -774,8 +772,6 @@ static int do_raw_keyop(int pkey_op, EVP_PKEY_CTX *ctx,
|
||||
rv = EVP_DigestVerifyFinal(mctx, sig, (size_t)siglen);
|
||||
break;
|
||||
case EVP_PKEY_OP_SIGN:
|
||||
if (EVP_DigestSignInit(mctx, NULL, md, NULL, pkey) != 1)
|
||||
goto end;
|
||||
for (;;) {
|
||||
buf_len = BIO_read(in, tbuf, TBUF_MAXSIZE);
|
||||
if (buf_len == 0)
|
||||
@ -800,6 +796,5 @@ static int do_raw_keyop(int pkey_op, EVP_PKEY_CTX *ctx,
|
||||
|
||||
end:
|
||||
OPENSSL_free(mbuf);
|
||||
EVP_MD_CTX_free(mctx);
|
||||
return rv;
|
||||
}
|
||||
|
@ -16,7 +16,7 @@ use OpenSSL::Test::Utils;
|
||||
|
||||
setup("test_pkeyutl");
|
||||
|
||||
plan tests => 11;
|
||||
plan tests => 12;
|
||||
|
||||
# For the tests below we use the cert itself as the TBS file
|
||||
|
||||
@ -125,6 +125,14 @@ SKIP: {
|
||||
srctop_file("test","testrsapub.pem"),
|
||||
"-rawin", "-digest", "sha256");
|
||||
};
|
||||
|
||||
subtest "RSA CLI signature and verification with pkeyopt" => sub {
|
||||
tsignverify("RSA",
|
||||
srctop_file("test","testrsa.pem"),
|
||||
srctop_file("test","testrsapub.pem"),
|
||||
"-rawin", "-digest", "sha256",
|
||||
"-pkeyopt", "rsa_padding_mode:pss");
|
||||
};
|
||||
}
|
||||
|
||||
SKIP: {
|
||||
|
Loading…
x
Reference in New Issue
Block a user