]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
crypto: ecdsa - Fix NIST P521 key size reported by KEYCTL_PKEY_QUERY
authorLukas Wunner <lukas@wunner.de>
Mon, 7 Apr 2025 19:32:42 +0000 (21:32 +0200)
committerHerbert Xu <herbert@gondor.apana.org.au>
Wed, 16 Apr 2025 07:16:21 +0000 (15:16 +0800)
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: a7d45ba77d3d ("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>
crypto/asymmetric_keys/public_key.c
crypto/ecdsa-p1363.c
crypto/ecdsa-x962.c
crypto/ecdsa.c
crypto/ecrdsa.c
crypto/rsassa-pkcs1.c
crypto/sig.c
include/crypto/sig.h

index dd44a966947fb820d7442993557f5de28b65dc77..89dc887d2c5c7e3463f9efa5633edb9adb88fd14 100644 (file)
@@ -205,6 +205,7 @@ static int software_key_query(const struct kernel_pkey_params *params,
                        goto error_free_tfm;
 
                len = crypto_sig_keysize(sig);
+               info->key_size = len;
                info->max_sig_size = crypto_sig_maxsize(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;
 
                if (strcmp(params->encoding, "pkcs1") == 0) {
-                       info->max_enc_size = len;
-                       info->max_dec_size = len;
+                       info->max_enc_size = len / BITS_PER_BYTE;
+                       info->max_dec_size = len / BITS_PER_BYTE;
 
                        info->supported_ops |= KEYCTL_SUPPORTS_ENCRYPT;
                        if (pkey->key_is_private)
@@ -235,6 +236,7 @@ static int software_key_query(const struct kernel_pkey_params *params,
                        goto error_free_tfm;
 
                len = crypto_akcipher_maxsize(tfm);
+               info->key_size = len * BITS_PER_BYTE;
                info->max_sig_size = len;
                info->max_data_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->key_size = len * 8;
-
        ret = 0;
 
 error_free_tfm:
index 4454f1f8f33f58fa6f6f17de5f6c78faf895309f..e0c55c64711c83aa07dd18139bd855e1ec226494 100644 (file)
@@ -21,7 +21,8 @@ static int ecdsa_p1363_verify(struct crypto_sig *tfm,
                              const void *digest, unsigned int dlen)
 {
        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));
        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);
 
-       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)
index 90a04f4b9a2f55b2fb825971961e4dc66ff85554..ee71594d10a06934f43098766ee30990408ac897 100644 (file)
@@ -82,7 +82,7 @@ static int ecdsa_x962_verify(struct crypto_sig *tfm,
        int err;
 
        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);
        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 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,
index 117526d15ddebf5793cd38fdd38280960680c247..a70b60a90a3c76ebae1ac056902eabf45ccc6c83 100644 (file)
@@ -167,7 +167,7 @@ static unsigned int ecdsa_key_size(struct crypto_sig *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)
index b3dd8a3ddeb796593be70b690c61c0befd93be7e..2c0602f0cd406f56a7b0be3ad9f50cbcdf6858eb 100644 (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
         * 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)
index d01ac75635e00881b9b7a10356dd72d9fc6184c2..94fa5e9600e79d5f0d626abf46c4b934e755c40c 100644 (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);
 
-       return ctx->key_size;
+       return ctx->key_size * BITS_PER_BYTE;
 }
 
 static int rsassa_pkcs1_set_pub_key(struct crypto_sig *tfm,
index dfc7cae9080282f31277e6ed8fb10ffac40c2342..53a3dd6fbe3fe656b3fbd7622d672d6a6983fb2e 100644 (file)
@@ -102,6 +102,11 @@ static int sig_default_set_key(struct crypto_sig *tfm,
        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)
 {
        struct crypto_alg *base = &alg->base;
@@ -117,9 +122,9 @@ static int sig_prepare_alg(struct sig_alg *alg)
        if (!alg->key_size)
                return -EINVAL;
        if (!alg->max_size)
-               alg->max_size = alg->key_size;
+               alg->max_size = sig_default_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_flags &= ~CRYPTO_ALG_TYPE_MASK;
index 11024708c06929b401b6108fb976a996d9d48639..fa6dafafab3f0dfc94e254456d66e560658abe0f 100644 (file)
@@ -128,7 +128,7 @@ static inline void crypto_free_sig(struct crypto_sig *tfm)
 /**
  * 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 is called without a setkey or with a failed setkey, you may end up
  * in a NULL dereference.