On 2/2/22 01:59, Vitaly Chikunov wrote:
Rarely used `keyctl pkey_verify' can verify raw signatures, but was
failing, because ECDSA/EC-RDSA signature sizes are twice key sizes which
does not pass in/out sizes check in keyctl_pkey_params_get_2.
This in turn because these values cannot be distinguished by a single
`max_size' callback return value.
Also, `keyctl pkey_query` displays incorrect `max_sig_size' about these
algorithms.
Signed-off-by: Vitaly Chikunov <vt@xxxxxxxxxxxx>
---
crypto/asymmetric_keys/public_key.c | 15 +++++++++++++--
1 file changed, 13 insertions(+), 2 deletions(-)
diff --git a/crypto/asymmetric_keys/public_key.c b/crypto/asymmetric_keys/public_key.c
index 4fefb219bfdc..3ffbab07ed2a 100644
--- a/crypto/asymmetric_keys/public_key.c
+++ b/crypto/asymmetric_keys/public_key.c
@@ -143,8 +143,19 @@ static int software_key_query(const struct kernel_pkey_params *params,
len = crypto_akcipher_maxsize(tfm);
info->key_size = len * 8;
- info->max_data_size = len;
- info->max_sig_size = len;
+ if (strcmp(alg_name, "ecrdsa") == 0 ||
+ strncmp(alg_name, "ecdsa-", 6) == 0) {
+ /*
+ * For these algos sig size is twice key size.
+ * keyctl uses max_sig_size as minimum input size, and
+ * max_data_size as minimum output size for a signature.
+ */
+ info->max_data_size = len * 2;
+ info->max_sig_size = len * 2;
I don't know about the data size but following my tests this is not
enough for ECDSA signature size. In ECDSA case the r and s components of
the signature are encode in asn.1, not 'raw'. So there are 2 bytes at
the beginning for sequence identifier , 2 bytes asn.1 for the r
component, 1 additional 0-byte to make the r component always a positive
number, then the r component, then 2 bytes asn.1 for the s component, 1
addition 0-byte to make the s component a positive number, then the s
component. Phew.
info->max_sig_size = 2 + (2 + 1 + len) * 2;
so for NIST P384 it's: 2 + (2+1+48) * 2 = 104
Then it works for me as well.
+ } else {
+ info->max_data_size = len;
+ info->max_sig_size = len;
+ }
info->max_enc_size = len;
info->max_dec_size = len;
info->supported_ops = (KEYCTL_SUPPORTS_ENCRYPT |