Commit 10a2f0b3 authored by Herbert Xu's avatar Herbert Xu

crypto: bcm - Verify GCM/CCM key length in setkey

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: 9d12ba86 ("crypto: brcm - Add Broadcom SPU driver")
Cc: <stable@vger.kernel.org>
Reported-by: default avatarkiyin(尹亮) <kiyin@tencent.com>
Signed-off-by: default avatarHerbert Xu <herbert@gondor.apana.org.au>
parent 789f900b
...@@ -2867,7 +2867,6 @@ static int aead_gcm_ccm_setkey(struct crypto_aead *cipher, ...@@ -2867,7 +2867,6 @@ static int aead_gcm_ccm_setkey(struct crypto_aead *cipher,
ctx->enckeylen = keylen; ctx->enckeylen = keylen;
ctx->authkeylen = 0; ctx->authkeylen = 0;
memcpy(ctx->enckey, key, ctx->enckeylen);
switch (ctx->enckeylen) { switch (ctx->enckeylen) {
case AES_KEYSIZE_128: case AES_KEYSIZE_128:
...@@ -2883,6 +2882,8 @@ static int aead_gcm_ccm_setkey(struct crypto_aead *cipher, ...@@ -2883,6 +2882,8 @@ static int aead_gcm_ccm_setkey(struct crypto_aead *cipher,
goto badkey; goto badkey;
} }
memcpy(ctx->enckey, key, ctx->enckeylen);
flow_log(" enckeylen:%u authkeylen:%u\n", ctx->enckeylen, flow_log(" enckeylen:%u authkeylen:%u\n", ctx->enckeylen,
ctx->authkeylen); ctx->authkeylen);
flow_dump(" enc: ", ctx->enckey, ctx->enckeylen); flow_dump(" enc: ", ctx->enckey, ctx->enckeylen);
...@@ -2937,6 +2938,10 @@ static int aead_gcm_esp_setkey(struct crypto_aead *cipher, ...@@ -2937,6 +2938,10 @@ static int aead_gcm_esp_setkey(struct crypto_aead *cipher,
struct iproc_ctx_s *ctx = crypto_aead_ctx(cipher); struct iproc_ctx_s *ctx = crypto_aead_ctx(cipher);
flow_log("%s\n", __func__); flow_log("%s\n", __func__);
if (keylen < GCM_ESP_SALT_SIZE)
return -EINVAL;
ctx->salt_len = GCM_ESP_SALT_SIZE; ctx->salt_len = GCM_ESP_SALT_SIZE;
ctx->salt_offset = GCM_ESP_SALT_OFFSET; ctx->salt_offset = GCM_ESP_SALT_OFFSET;
memcpy(ctx->salt, key + keylen - GCM_ESP_SALT_SIZE, GCM_ESP_SALT_SIZE); memcpy(ctx->salt, key + keylen - GCM_ESP_SALT_SIZE, GCM_ESP_SALT_SIZE);
...@@ -2965,6 +2970,10 @@ static int rfc4543_gcm_esp_setkey(struct crypto_aead *cipher, ...@@ -2965,6 +2970,10 @@ static int rfc4543_gcm_esp_setkey(struct crypto_aead *cipher,
struct iproc_ctx_s *ctx = crypto_aead_ctx(cipher); struct iproc_ctx_s *ctx = crypto_aead_ctx(cipher);
flow_log("%s\n", __func__); flow_log("%s\n", __func__);
if (keylen < GCM_ESP_SALT_SIZE)
return -EINVAL;
ctx->salt_len = GCM_ESP_SALT_SIZE; ctx->salt_len = GCM_ESP_SALT_SIZE;
ctx->salt_offset = GCM_ESP_SALT_OFFSET; ctx->salt_offset = GCM_ESP_SALT_OFFSET;
memcpy(ctx->salt, key + keylen - GCM_ESP_SALT_SIZE, GCM_ESP_SALT_SIZE); memcpy(ctx->salt, key + keylen - GCM_ESP_SALT_SIZE, GCM_ESP_SALT_SIZE);
...@@ -2994,6 +3003,10 @@ static int aead_ccm_esp_setkey(struct crypto_aead *cipher, ...@@ -2994,6 +3003,10 @@ static int aead_ccm_esp_setkey(struct crypto_aead *cipher,
struct iproc_ctx_s *ctx = crypto_aead_ctx(cipher); struct iproc_ctx_s *ctx = crypto_aead_ctx(cipher);
flow_log("%s\n", __func__); flow_log("%s\n", __func__);
if (keylen < CCM_ESP_SALT_SIZE)
return -EINVAL;
ctx->salt_len = CCM_ESP_SALT_SIZE; ctx->salt_len = CCM_ESP_SALT_SIZE;
ctx->salt_offset = CCM_ESP_SALT_OFFSET; ctx->salt_offset = CCM_ESP_SALT_OFFSET;
memcpy(ctx->salt, key + keylen - CCM_ESP_SALT_SIZE, CCM_ESP_SALT_SIZE); memcpy(ctx->salt, key + keylen - CCM_ESP_SALT_SIZE, CCM_ESP_SALT_SIZE);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment