crypto: ecdsa - Fix NIST P521 key size reported by KEYCTL_PKEY_QUERY

When user space issues a KEYCTL_PKEY_QUERY system call for a NIST P521
key, the key_size is incorrectly reported as 528 bits instead of 521.

That's because the key size obtained through crypto_sig_keysize() is in
bytes and software_key_query() multiplies by 8 to yield the size in bits.
The underlying assumption is that the key size is always a multiple of 8.
With the recent addition of NIST P521, that's no longer the case.

Fix by returning the key_size in bits from crypto_sig_keysize() and
adjusting the calculations in software_key_query().

The ->key_size() callbacks of sig_alg algorithms now return the size in
bits, whereas the ->digest_size() and ->max_size() callbacks return the
size in bytes.  This matches with the units in struct keyctl_pkey_query.

Fixes: a7d45ba77d ("crypto: ecdsa - Register NIST P521 and extend test suite")
Signed-off-by: Lukas Wunner <lukas@wunner.de>
Reviewed-by: Stefan Berger <stefanb@linux.ibm.com>
Reviewed-by: Ignat Korchagin <ignat@cloudflare.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
This commit is contained in:
Lukas Wunner 2025-04-07 21:32:42 +02:00 committed by Herbert Xu
parent 3828485e1c
commit 6b7f9397c9
8 changed files with 22 additions and 14 deletions

View file

@ -205,6 +205,7 @@ static int software_key_query(const struct kernel_pkey_params *params,
goto error_free_tfm; goto error_free_tfm;
len = crypto_sig_keysize(sig); len = crypto_sig_keysize(sig);
info->key_size = len;
info->max_sig_size = crypto_sig_maxsize(sig); info->max_sig_size = crypto_sig_maxsize(sig);
info->max_data_size = crypto_sig_digestsize(sig); info->max_data_size = crypto_sig_digestsize(sig);
@ -213,8 +214,8 @@ static int software_key_query(const struct kernel_pkey_params *params,
info->supported_ops |= KEYCTL_SUPPORTS_SIGN; info->supported_ops |= KEYCTL_SUPPORTS_SIGN;
if (strcmp(params->encoding, "pkcs1") == 0) { if (strcmp(params->encoding, "pkcs1") == 0) {
info->max_enc_size = len; info->max_enc_size = len / BITS_PER_BYTE;
info->max_dec_size = len; info->max_dec_size = len / BITS_PER_BYTE;
info->supported_ops |= KEYCTL_SUPPORTS_ENCRYPT; info->supported_ops |= KEYCTL_SUPPORTS_ENCRYPT;
if (pkey->key_is_private) if (pkey->key_is_private)
@ -235,6 +236,7 @@ static int software_key_query(const struct kernel_pkey_params *params,
goto error_free_tfm; goto error_free_tfm;
len = crypto_akcipher_maxsize(tfm); len = crypto_akcipher_maxsize(tfm);
info->key_size = len * BITS_PER_BYTE;
info->max_sig_size = len; info->max_sig_size = len;
info->max_data_size = len; info->max_data_size = len;
info->max_enc_size = len; info->max_enc_size = len;
@ -245,8 +247,6 @@ static int software_key_query(const struct kernel_pkey_params *params,
info->supported_ops |= KEYCTL_SUPPORTS_DECRYPT; info->supported_ops |= KEYCTL_SUPPORTS_DECRYPT;
} }
info->key_size = len * 8;
ret = 0; ret = 0;
error_free_tfm: error_free_tfm:

View file

@ -21,7 +21,8 @@ static int ecdsa_p1363_verify(struct crypto_sig *tfm,
const void *digest, unsigned int dlen) const void *digest, unsigned int dlen)
{ {
struct ecdsa_p1363_ctx *ctx = crypto_sig_ctx(tfm); struct ecdsa_p1363_ctx *ctx = crypto_sig_ctx(tfm);
unsigned int keylen = crypto_sig_keysize(ctx->child); unsigned int keylen = DIV_ROUND_UP_POW2(crypto_sig_keysize(ctx->child),
BITS_PER_BYTE);
unsigned int ndigits = DIV_ROUND_UP_POW2(keylen, sizeof(u64)); unsigned int ndigits = DIV_ROUND_UP_POW2(keylen, sizeof(u64));
struct ecdsa_raw_sig sig; struct ecdsa_raw_sig sig;
@ -45,7 +46,8 @@ static unsigned int ecdsa_p1363_max_size(struct crypto_sig *tfm)
{ {
struct ecdsa_p1363_ctx *ctx = crypto_sig_ctx(tfm); struct ecdsa_p1363_ctx *ctx = crypto_sig_ctx(tfm);
return 2 * crypto_sig_keysize(ctx->child); return 2 * DIV_ROUND_UP_POW2(crypto_sig_keysize(ctx->child),
BITS_PER_BYTE);
} }
static unsigned int ecdsa_p1363_digest_size(struct crypto_sig *tfm) static unsigned int ecdsa_p1363_digest_size(struct crypto_sig *tfm)

View file

@ -82,7 +82,7 @@ static int ecdsa_x962_verify(struct crypto_sig *tfm,
int err; int err;
sig_ctx.ndigits = DIV_ROUND_UP_POW2(crypto_sig_keysize(ctx->child), sig_ctx.ndigits = DIV_ROUND_UP_POW2(crypto_sig_keysize(ctx->child),
sizeof(u64)); sizeof(u64) * BITS_PER_BYTE);
err = asn1_ber_decoder(&ecdsasignature_decoder, &sig_ctx, src, slen); err = asn1_ber_decoder(&ecdsasignature_decoder, &sig_ctx, src, slen);
if (err < 0) if (err < 0)
@ -103,7 +103,8 @@ static unsigned int ecdsa_x962_max_size(struct crypto_sig *tfm)
{ {
struct ecdsa_x962_ctx *ctx = crypto_sig_ctx(tfm); struct ecdsa_x962_ctx *ctx = crypto_sig_ctx(tfm);
struct sig_alg *alg = crypto_sig_alg(ctx->child); struct sig_alg *alg = crypto_sig_alg(ctx->child);
int slen = crypto_sig_keysize(ctx->child); int slen = DIV_ROUND_UP_POW2(crypto_sig_keysize(ctx->child),
BITS_PER_BYTE);
/* /*
* Verify takes ECDSA-Sig-Value (described in RFC 5480) as input, * Verify takes ECDSA-Sig-Value (described in RFC 5480) as input,

View file

@ -167,7 +167,7 @@ static unsigned int ecdsa_key_size(struct crypto_sig *tfm)
{ {
struct ecc_ctx *ctx = crypto_sig_ctx(tfm); struct ecc_ctx *ctx = crypto_sig_ctx(tfm);
return DIV_ROUND_UP(ctx->curve->nbits, 8); return ctx->curve->nbits;
} }
static unsigned int ecdsa_digest_size(struct crypto_sig *tfm) static unsigned int ecdsa_digest_size(struct crypto_sig *tfm)

View file

@ -249,7 +249,7 @@ static unsigned int ecrdsa_key_size(struct crypto_sig *tfm)
* Verify doesn't need any output, so it's just informational * Verify doesn't need any output, so it's just informational
* for keyctl to determine the key bit size. * for keyctl to determine the key bit size.
*/ */
return ctx->pub_key.ndigits * sizeof(u64); return ctx->pub_key.ndigits * sizeof(u64) * BITS_PER_BYTE;
} }
static unsigned int ecrdsa_max_size(struct crypto_sig *tfm) static unsigned int ecrdsa_max_size(struct crypto_sig *tfm)

View file

@ -301,7 +301,7 @@ static unsigned int rsassa_pkcs1_key_size(struct crypto_sig *tfm)
{ {
struct rsassa_pkcs1_ctx *ctx = crypto_sig_ctx(tfm); struct rsassa_pkcs1_ctx *ctx = crypto_sig_ctx(tfm);
return ctx->key_size; return ctx->key_size * BITS_PER_BYTE;
} }
static int rsassa_pkcs1_set_pub_key(struct crypto_sig *tfm, static int rsassa_pkcs1_set_pub_key(struct crypto_sig *tfm,

View file

@ -102,6 +102,11 @@ static int sig_default_set_key(struct crypto_sig *tfm,
return -ENOSYS; return -ENOSYS;
} }
static unsigned int sig_default_size(struct crypto_sig *tfm)
{
return DIV_ROUND_UP_POW2(crypto_sig_keysize(tfm), BITS_PER_BYTE);
}
static int sig_prepare_alg(struct sig_alg *alg) static int sig_prepare_alg(struct sig_alg *alg)
{ {
struct crypto_alg *base = &alg->base; struct crypto_alg *base = &alg->base;
@ -117,9 +122,9 @@ static int sig_prepare_alg(struct sig_alg *alg)
if (!alg->key_size) if (!alg->key_size)
return -EINVAL; return -EINVAL;
if (!alg->max_size) if (!alg->max_size)
alg->max_size = alg->key_size; alg->max_size = sig_default_size;
if (!alg->digest_size) if (!alg->digest_size)
alg->digest_size = alg->key_size; alg->digest_size = sig_default_size;
base->cra_type = &crypto_sig_type; base->cra_type = &crypto_sig_type;
base->cra_flags &= ~CRYPTO_ALG_TYPE_MASK; base->cra_flags &= ~CRYPTO_ALG_TYPE_MASK;

View file

@ -128,7 +128,7 @@ static inline void crypto_free_sig(struct crypto_sig *tfm)
/** /**
* crypto_sig_keysize() - Get key size * crypto_sig_keysize() - Get key size
* *
* Function returns the key size in bytes. * Function returns the key size in bits.
* Function assumes that the key is already set in the transformation. If this * Function assumes that the key is already set in the transformation. If this
* function is called without a setkey or with a failed setkey, you may end up * function is called without a setkey or with a failed setkey, you may end up
* in a NULL dereference. * in a NULL dereference.