| From 10a2f0b311094ffd45463a529a410a51ca025f27 Mon Sep 17 00:00:00 2001 |
| From: Herbert Xu <herbert@gondor.apana.org.au> |
| Date: Fri, 2 Oct 2020 17:55:22 +1000 |
| Subject: crypto: bcm - Verify GCM/CCM key length in setkey |
| MIME-Version: 1.0 |
| Content-Type: text/plain; charset=UTF-8 |
| Content-Transfer-Encoding: 8bit |
| |
| From: Herbert Xu <herbert@gondor.apana.org.au> |
| |
| 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@vger.kernel.org> |
| Reported-by: kiyin(尹亮) <kiyin@tencent.com> |
| Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| 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 |
| @@ -2980,7 +2980,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: |
| @@ -2996,6 +2995,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); |
| @@ -3056,6 +3057,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); |
| @@ -3084,6 +3089,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); |
| @@ -3113,6 +3122,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); |