diff --git a/crypto/rsassa-pkcs1.c b/crypto/rsassa-pkcs1.c index 779c080fc013630e94c2cf0465ef7346dfc2ddf1..8f42a571280633aeeb13bee7b0716b09ee54d86b 100644 --- a/crypto/rsassa-pkcs1.c +++ b/crypto/rsassa-pkcs1.c @@ -11,6 +11,7 @@ #include <linux/scatterlist.h> #include <crypto/akcipher.h> #include <crypto/algapi.h> +#include <crypto/hash.h> #include <crypto/sig.h> #include <crypto/internal/akcipher.h> #include <crypto/internal/rsa.h> @@ -118,6 +119,20 @@ static const struct hash_prefix *rsassa_pkcs1_find_hash_prefix(const char *name) return NULL; } +static unsigned int rsassa_pkcs1_hash_len(const struct hash_prefix *p) +{ + /* + * The final byte of the Full Hash Prefix encodes the hash length. + * + * This needs to be revisited should hash algorithms with more than + * 1016 bits (127 bytes * 8) ever be added. The length would then + * be encoded into more than one byte by ASN.1. + */ + static_assert(HASH_MAX_DIGESTSIZE <= 127); + + return p->data[p->size - 1]; +} + struct rsassa_pkcs1_ctx { struct crypto_akcipher *child; unsigned int key_size; @@ -152,6 +167,9 @@ static int rsassa_pkcs1_sign(struct crypto_sig *tfm, if (dlen < ctx->key_size) return -EOVERFLOW; + if (slen != rsassa_pkcs1_hash_len(hash_prefix)) + return -EINVAL; + if (slen + hash_prefix->size > ctx->key_size - 11) return -EOVERFLOW; @@ -217,7 +235,7 @@ static int rsassa_pkcs1_verify(struct crypto_sig *tfm, /* RFC 8017 sec 8.2.2 step 1 - length checking */ if (!ctx->key_size || slen != ctx->key_size || - !dlen) + dlen != rsassa_pkcs1_hash_len(hash_prefix)) return -EINVAL; /* RFC 8017 sec 8.2.2 step 2 - RSA verification */