Commit 6b7f9397 authored by Lukas Wunner's avatar Lukas Wunner Committed by Herbert Xu
Browse files

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: a7d45ba7 ("crypto: ecdsa - Register NIST P521 and extend test suite")
Signed-off-by: default avatarLukas Wunner <lukas@wunner.de>
Reviewed-by: default avatarStefan Berger <stefanb@linux.ibm.com>
Reviewed-by: default avatarIgnat Korchagin <ignat@cloudflare.com>
Signed-off-by: default avatarHerbert Xu <herbert@gondor.apana.org.au>
parent 3828485e
Loading
Loading
Loading
Loading
+4 −4
Original line number Diff line number Diff line
@@ -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:
+4 −2
Original line number Diff line number Diff line
@@ -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)
+3 −2
Original line number Diff line number Diff line
@@ -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,
+1 −1
Original line number Diff line number Diff line
@@ -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)
+1 −1
Original line number Diff line number Diff line
@@ -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)
Loading