ecdsa KEYCTL_PKEY_QUERY fixes
Subsystems (6)
Lukas Wunner
maintainerv2 cover ecdsa KEYCTL_PKEY_QUERY fixes
Here are two patches for ecdsa to avoid reporting nonsensical values for enc/dec size and -- for P521 keys -- also the key size in response to KEYCTL_PKEY_QUERY system calls.
Resending as requested by Herbert:
https://lore.kernel.org/r/[email protected]/
Link to the original submission:
https://lore.kernel.org/r/[email protected]/
Although these are technically fixes, the issues they address are not critical, so I recommend not applying as fixes for v6.15, but rather let the patches soak in linux-next for v6.16.
Lukas Wunner (2):
crypto: ecdsa - Fix enc/dec size reported by KEYCTL_PKEY_QUERY
crypto: ecdsa - Fix NIST P521 key size reported by KEYCTL_PKEY_QUERY
crypto/asymmetric_keys/public_key.c | 13 +++++++++---- crypto/ecdsa-p1363.c | 6 ++++-- crypto/ecdsa-x962.c | 5 +++-- crypto/ecdsa.c | 2 +- crypto/ecrdsa.c | 2 +- crypto/rsassa-pkcs1.c | 2 +- crypto/sig.c | 9 +++++++-- include/crypto/sig.h | 2 +- 8 files changed, 27 insertions(+), 14 deletions(-)
Signature · 1 line
2.43.0
Lukas Wunner
maintainerPATCH RESEND v2 1/2 crypto: ecdsa - Fix enc/dec size reported by KEYCTL_PKEY_QUERY
KEYCTL_PKEY_QUERY system calls for ecdsa keys return the key size as max_enc_size and max_dec_size, even though such keys cannot be used for encryption/decryption. They're exclusively for signature generation or verification.
Only rsa keys with pkcs1 encoding can also be used for encryption or decryption.
Return 0 instead for ecdsa keys (as well as ecrdsa keys).
--- crypto/asymmetric_keys/public_key.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-)
crypto/asymmetric_keys/public_key.c +7 -2
@@ -188,6 +188,8 @@ static int software_key_query(const struct kernel_pkey_params *params, ptr =pkey_pack_u32 (ptr, pkey->paramlen);memcpy (ptr, pkey->params, pkey->paramlen); +memset (info,0 ,sizeof (*info)); +if (issig) { sig =crypto_alloc_sig (alg_name,0 ,0 );if (IS_ERR (sig)) {
@@ -211,6 +213,9 @@ 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->supported_ops |=KEYCTL_SUPPORTS_ENCRYPT ;if (pkey->key_is_private) info->supported_ops |=KEYCTL_SUPPORTS_DECRYPT ;
@@ -232,6 +237,8 @@ static int software_key_query(const struct kernel_pkey_params *params, len =crypto_akcipher_maxsize (tfm); info->max_sig_size = len; info->max_data_size = len; + info->max_enc_size = len; + info->max_dec_size = len; info->supported_ops =KEYCTL_SUPPORTS_ENCRYPT ;if (pkey->key_is_private)
@@ -239,8 +246,6 @@ static int software_key_query(const struct kernel_pkey_params *params, } info->key_size = len *8 ; - info->max_enc_size = len; - info->max_dec_size = len; ret =0 ;
Signature · 1 line
2.43.0
Re: [PATCH RESEND v2 1/2] crypto: ecdsa - Fix enc/dec size reported by KEYCTL_PKEY_QUERY
Quoted 6 lines · Lukas Wunner
KEYCTL_PKEY_QUERYsystem calls for ecdsa keys return the key size asmax_enc_sizeandmax_dec_size, even though such keys cannot be used for encryption/decryption. They're exclusively for signature generation or verification.
Quoted 7 lines
Only rsa keys with pkcs1 encoding can also be used for encryption or decryption.
Return 0 instead for ecdsa keys (as well as ecrdsa keys).
Signed-off-by Lukas Wunner <[email protected]>Reviewed-by Stefan Berger <[email protected]>
Quoted 48 lines
--- crypto/asymmetric_keys/public_key.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-)crypto/asymmetric_keys/public_key.c +7
-3@@ -188,6 +188,8 @@ static int software_key_query(const struct kernel_pkey_params *params, ptr =pkey_pack_u32 (ptr, pkey->paramlen);memcpy (ptr, pkey->params, pkey->paramlen); +memset (info,0 ,sizeof (*info)); +if (issig) { sig =crypto_alloc_sig (alg_name,0 ,0 );if (IS_ERR (sig)) {@@ -211,6 +213,9 @@ 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->supported_ops |=KEYCTL_SUPPORTS_ENCRYPT ;if (pkey->key_is_private) info->supported_ops |=KEYCTL_SUPPORTS_DECRYPT ;@@ -232,6 +237,8 @@ static int software_key_query(const struct kernel_pkey_params *params, len =crypto_akcipher_maxsize (tfm); info->max_sig_size = len; info->max_data_size = len; + info->max_enc_size = len; + info->max_dec_size = len; info->supported_ops =KEYCTL_SUPPORTS_ENCRYPT ;if (pkey->key_is_private)@@ -239,8 +246,6 @@ static int software_key_query(const struct kernel_pkey_params *params, } info->key_size = len *8 ; - info->max_enc_size = len; - info->max_dec_size = len; ret =0 ; --2.43.0
Lukas Wunner
maintainerPATCH RESEND v2 2/2 crypto: ecdsa - Fix NIST P521 key size reported by KEYCTL_PKEY_QUERY
In reply to Lukas WunnerWhen 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.
--- crypto/asymmetric_keys/public_key.c | 8 ++++---- crypto/ecdsa-p1363.c | 6 ++++-- crypto/ecdsa-x962.c | 5 +++-- crypto/ecdsa.c | 2 +- crypto/ecrdsa.c | 2 +- crypto/rsassa-pkcs1.c | 2 +- crypto/sig.c | 9 +++++++-- include/crypto/sig.h | 2 +- 8 files changed, 22 insertions(+), 14 deletions(-)
crypto/asymmetric_keys/public_key.c +4 -4
@@ -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:
crypto/ecdsa-p1363.c +4 -2
@@ -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)
crypto/ecdsa-x962.c +3 -2
@@ -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,
crypto/ecdsa.c +1 -1
@@ -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)
crypto/ecrdsa.c +1 -1
@@ -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)
crypto/rsassa-pkcs1.c +1 -1
@@ -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,
crypto/sig.c +7 -2
@@ -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 ;
include/crypto/sig.h +1 -1
@@ -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.
Signature · 1 line
2.43.0
Re: [PATCH RESEND v2 2/2] crypto: ecdsa - Fix NIST P521 key size reported by KEYCTL_PKEY_QUERY
Quoted 12 lines · Lukas Wunner
When user space issues a
KEYCTL_PKEY_QUERYsystem call for a NIST P521 key, thekey_sizeis incorrectly reported as 528 bits instead of 521.That's because the key size obtained through
crypto_sig_keysize()is in bytes andsoftware_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_sizein bits fromcrypto_sig_keysize()and adjusting the calculations insoftware_key_query().
Quoted 7 lines
The ->key_size() callbacks of
sig_algalgorithms 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 structkeyctl_pkey_query.Fixes a7d45ba77d3d ("crypto: ecdsa - Register NIST P521 and extend test suite")Signed-off-by Lukas Wunner <[email protected]>Reviewed-by Stefan Berger <[email protected]>
Quoted 181 lines
--- crypto/asymmetric_keys/public_key.c | 8 ++++---- crypto/ecdsa-p1363.c | 6 ++++-- crypto/ecdsa-x962.c | 5 +++-- crypto/ecdsa.c | 2 +- crypto/ecrdsa.c | 2 +- crypto/rsassa-pkcs1.c | 2 +- crypto/sig.c | 9 +++++++-- include/crypto/sig.h | 2 +- 8 files changed, 22 insertions(+), 14 deletions(-)crypto/asymmetric_keys/public_key.c +4
-4@@ -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:crypto/ecdsa-p1363.c +4
-2@@ -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)crypto/ecdsa-x962.c +3
-2@@ -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, crypto/ecdsa.c +1
-1@@ -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)crypto/ecrdsa.c +1
-1@@ -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)crypto/rsassa-pkcs1.c +1
-1@@ -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,crypto/sig.c +7
-2@@ -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 ;include/crypto/sig.h +1
-2@@ -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. -- 2.43.0
Herbert Xu
maintainerQuoted 21 lines · Lukas Wunner
Here are two patches for ecdsa to avoid reporting nonsensical values for enc/dec size and -- for P521 keys -- also the key size in response to
KEYCTL_PKEY_QUERYsystem calls.Resending as requested by Herbert:
https://lore.kernel.org/r/[email protected]/
Link to the original submission:
https://lore.kernel.org/r/[email protected]/
Although these are technically fixes, the issues they address are not critical, so I recommend not applying as fixes for v6.15, but rather let the patches soak in linux-next for v6.16.
Lukas Wunner (2):
crypto: ecdsa - Fix enc/dec size reported byKEYCTL_PKEY_QUERY
crypto: ecdsa - Fix NIST P521 key size reported byKEYCTL_PKEY_QUERY
Quoted 12 lines
crypto/asymmetric_keys/public_key.c | 13 +++++++++---- crypto/ecdsa-p1363.c | 6 ++++-- crypto/ecdsa-x962.c | 5 +++-- crypto/ecdsa.c | 2 +- crypto/ecrdsa.c | 2 +- crypto/rsassa-pkcs1.c | 2 +- crypto/sig.c | 9 +++++++-- include/crypto/sig.h | 2 +- 8 files changed, 27 insertions(+), 14 deletions(-)Signature · 1 line
2.43.0
All applied. Thanks.
Signature · 3 lines
Email: Herbert Xu <[email protected]> Home Page: http://gondor.apana.org.au/~herbert/ PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt