[PATCH 5.9 14/15] crypto: bcm - Verify GCM/CCM key length in setkey

From: Greg Kroah-Hartman
Date: Fri Oct 16 2020 - 05:12:10 EST


From: Herbert Xu <herbert@xxxxxxxxxxxxxxxxxxx>

commit 10a2f0b311094ffd45463a529a410a51ca025f27 upstream.

The setkey function for GCM/CCM algorithms didn't verify the key
length before copying the key and subtracting the salt length.

This patch delays the copying of the key til after the verification
has been done. It also adds checks on the key length to ensure
that it's at least as long as the salt.

Fixes: 9d12ba86f818 ("crypto: brcm - Add Broadcom SPU driver")
Cc: <stable@xxxxxxxxxxxxxxx>
Reported-by: kiyin(尹亮) <kiyin@xxxxxxxxxxx>
Signed-off-by: Herbert Xu <herbert@xxxxxxxxxxxxxxxxxxx>
Signed-off-by: Greg Kroah-Hartman <gregkh@xxxxxxxxxxxxxxxxxxx>

---
drivers/crypto/bcm/cipher.c | 15 ++++++++++++++-
1 file changed, 14 insertions(+), 1 deletion(-)

--- a/drivers/crypto/bcm/cipher.c
+++ b/drivers/crypto/bcm/cipher.c
@@ -2930,7 +2930,6 @@ static int aead_gcm_ccm_setkey(struct cr

ctx->enckeylen = keylen;
ctx->authkeylen = 0;
- memcpy(ctx->enckey, key, ctx->enckeylen);

switch (ctx->enckeylen) {
case AES_KEYSIZE_128:
@@ -2946,6 +2945,8 @@ static int aead_gcm_ccm_setkey(struct cr
goto badkey;
}

+ memcpy(ctx->enckey, key, ctx->enckeylen);
+
flow_log(" enckeylen:%u authkeylen:%u\n", ctx->enckeylen,
ctx->authkeylen);
flow_dump(" enc: ", ctx->enckey, ctx->enckeylen);
@@ -3000,6 +3001,10 @@ static int aead_gcm_esp_setkey(struct cr
struct iproc_ctx_s *ctx = crypto_aead_ctx(cipher);

flow_log("%s\n", __func__);
+
+ if (keylen < GCM_ESP_SALT_SIZE)
+ return -EINVAL;
+
ctx->salt_len = GCM_ESP_SALT_SIZE;
ctx->salt_offset = GCM_ESP_SALT_OFFSET;
memcpy(ctx->salt, key + keylen - GCM_ESP_SALT_SIZE, GCM_ESP_SALT_SIZE);
@@ -3028,6 +3033,10 @@ static int rfc4543_gcm_esp_setkey(struct
struct iproc_ctx_s *ctx = crypto_aead_ctx(cipher);

flow_log("%s\n", __func__);
+
+ if (keylen < GCM_ESP_SALT_SIZE)
+ return -EINVAL;
+
ctx->salt_len = GCM_ESP_SALT_SIZE;
ctx->salt_offset = GCM_ESP_SALT_OFFSET;
memcpy(ctx->salt, key + keylen - GCM_ESP_SALT_SIZE, GCM_ESP_SALT_SIZE);
@@ -3057,6 +3066,10 @@ static int aead_ccm_esp_setkey(struct cr
struct iproc_ctx_s *ctx = crypto_aead_ctx(cipher);

flow_log("%s\n", __func__);
+
+ if (keylen < CCM_ESP_SALT_SIZE)
+ return -EINVAL;
+
ctx->salt_len = CCM_ESP_SALT_SIZE;
ctx->salt_offset = CCM_ESP_SALT_OFFSET;
memcpy(ctx->salt, key + keylen - CCM_ESP_SALT_SIZE, CCM_ESP_SALT_SIZE);