summaryrefslogtreecommitdiff
path: root/crypto/rsassa-pkcs1.c
diff options
context:
space:
mode:
Diffstat (limited to 'crypto/rsassa-pkcs1.c')
-rw-r--r--crypto/rsassa-pkcs1.c20
1 files changed, 19 insertions, 1 deletions
diff --git a/crypto/rsassa-pkcs1.c b/crypto/rsassa-pkcs1.c
index 779c080fc013..8f42a5712806 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 */