diff options
author | Lukas Wunner <lukas@wunner.de> | 2024-10-14 11:43:01 +0200 |
---|---|---|
committer | Herbert Xu <herbert@gondor.apana.org.au> | 2024-10-26 14:41:59 +0800 |
commit | b358f23ab11ad8534ed0f2096cbb2411ea62f8d3 (patch) | |
tree | 241a1f6c209b75246f786bc1b3193e4b7bef3b19 | |
parent | 84dd048cf89557e1e4badd20c9522f7aaa0275fe (diff) |
crypto: sig - Fix oops on KEYCTL_PKEY_QUERY for RSA keys
Commit a2471684dae2 ("crypto: ecdsa - Move X9.62 signature size
calculation into template") introduced ->max_size() and ->digest_size()
callbacks to struct sig_alg. They return an algorithm's maximum
signature size and digest size, respectively.
For algorithms which lack these callbacks, crypto_register_sig() was
amended to use the ->key_size() callback instead.
However the commit neglected to also amend sig_register_instance().
As a result, the ->max_size() and ->digest_size() callbacks remain NULL
pointers if instances do not define them. A KEYCTL_PKEY_QUERY system
call results in an oops for such instances:
BUG: kernel NULL pointer dereference, address: 0000000000000000
Call Trace:
software_key_query+0x169/0x370
query_asymmetric_key+0x67/0x90
keyctl_pkey_query+0x86/0x120
__do_sys_keyctl+0x428/0x480
do_syscall_64+0x4b/0x110
The only instances affected by this are "pkcs1(rsa, ...)".
Fix by moving the callback checks from crypto_register_sig() to
sig_prepare_alg(), which is also invoked by sig_register_instance().
Change the return type of sig_prepare_alg() from void to int to be able
to return errors. This matches other algorithm types, see e.g.
aead_prepare_alg() or ahash_prepare_alg().
Fixes: a2471684dae2 ("crypto: ecdsa - Move X9.62 signature size calculation into template")
Signed-off-by: Lukas Wunner <lukas@wunner.de>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
-rw-r--r-- | crypto/sig.c | 36 |
1 files changed, 24 insertions, 12 deletions
diff --git a/crypto/sig.c b/crypto/sig.c index be5ac0e59384..5e1f1f739da2 100644 --- a/crypto/sig.c +++ b/crypto/sig.c @@ -84,15 +84,6 @@ struct crypto_sig *crypto_alloc_sig(const char *alg_name, u32 type, u32 mask) } EXPORT_SYMBOL_GPL(crypto_alloc_sig); -static void sig_prepare_alg(struct sig_alg *alg) -{ - struct crypto_alg *base = &alg->base; - - base->cra_type = &crypto_sig_type; - base->cra_flags &= ~CRYPTO_ALG_TYPE_MASK; - base->cra_flags |= CRYPTO_ALG_TYPE_SIG; -} - static int sig_default_sign(struct crypto_sig *tfm, const void *src, unsigned int slen, void *dst, unsigned int dlen) @@ -113,7 +104,7 @@ static int sig_default_set_key(struct crypto_sig *tfm, return -ENOSYS; } -int crypto_register_sig(struct sig_alg *alg) +static int sig_prepare_alg(struct sig_alg *alg) { struct crypto_alg *base = &alg->base; @@ -132,7 +123,22 @@ int crypto_register_sig(struct sig_alg *alg) if (!alg->digest_size) alg->digest_size = alg->key_size; - sig_prepare_alg(alg); + base->cra_type = &crypto_sig_type; + base->cra_flags &= ~CRYPTO_ALG_TYPE_MASK; + base->cra_flags |= CRYPTO_ALG_TYPE_SIG; + + return 0; +} + +int crypto_register_sig(struct sig_alg *alg) +{ + struct crypto_alg *base = &alg->base; + int err; + + err = sig_prepare_alg(alg); + if (err) + return err; + return crypto_register_alg(base); } EXPORT_SYMBOL_GPL(crypto_register_sig); @@ -146,9 +152,15 @@ EXPORT_SYMBOL_GPL(crypto_unregister_sig); int sig_register_instance(struct crypto_template *tmpl, struct sig_instance *inst) { + int err; + if (WARN_ON(!inst->free)) return -EINVAL; - sig_prepare_alg(&inst->alg); + + err = sig_prepare_alg(&inst->alg); + if (err) + return err; + return crypto_register_instance(tmpl, sig_crypto_instance(inst)); } EXPORT_SYMBOL_GPL(sig_register_instance); |