crypto: bcm - convert to use crypto_authenc_extractkeys()
authorEric Biggers <ebiggers@google.com>
Mon, 17 Dec 2018 07:23:23 +0000 (23:23 -0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 23 Jan 2019 07:09:47 +0000 (08:09 +0100)
commit ab57b33525c3221afaebd391458fa0cbcd56903d upstream.

Convert the bcm crypto driver to use crypto_authenc_extractkeys() so
that it picks up the fix for broken validation of rtattr::rta_len.

This also fixes the DES weak key check to actually be done on the right
key. (It was checking the authentication key, not the encryption key...)

Fixes: 9d12ba86f818 ("crypto: brcm - Add Broadcom SPU driver")
Cc: <stable@vger.kernel.org> # v4.11+
Signed-off-by: Eric Biggers <ebiggers@google.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/crypto/Kconfig
drivers/crypto/bcm/cipher.c

index 143f8bc..342bc77 100644 (file)
@@ -679,6 +679,7 @@ config CRYPTO_DEV_BCM_SPU
        depends on ARCH_BCM_IPROC
        depends on MAILBOX
        default m
+       select CRYPTO_AUTHENC
        select CRYPTO_DES
        select CRYPTO_MD5
        select CRYPTO_SHA1
index ee52c35..b6be383 100644 (file)
@@ -2846,44 +2846,28 @@ static int aead_authenc_setkey(struct crypto_aead *cipher,
        struct spu_hw *spu = &iproc_priv.spu;
        struct iproc_ctx_s *ctx = crypto_aead_ctx(cipher);
        struct crypto_tfm *tfm = crypto_aead_tfm(cipher);
-       struct rtattr *rta = (void *)key;
-       struct crypto_authenc_key_param *param;
-       const u8 *origkey = key;
-       const unsigned int origkeylen = keylen;
-
-       int ret = 0;
+       struct crypto_authenc_keys keys;
+       int ret;
 
        flow_log("%s() aead:%p key:%p keylen:%u\n", __func__, cipher, key,
                 keylen);
        flow_dump("  key: ", key, keylen);
 
-       if (!RTA_OK(rta, keylen))
-               goto badkey;
-       if (rta->rta_type != CRYPTO_AUTHENC_KEYA_PARAM)
-               goto badkey;
-       if (RTA_PAYLOAD(rta) < sizeof(*param))
+       ret = crypto_authenc_extractkeys(&keys, key, keylen);
+       if (ret)
                goto badkey;
 
-       param = RTA_DATA(rta);
-       ctx->enckeylen = be32_to_cpu(param->enckeylen);
-
-       key += RTA_ALIGN(rta->rta_len);
-       keylen -= RTA_ALIGN(rta->rta_len);
-
-       if (keylen < ctx->enckeylen)
-               goto badkey;
-       if (ctx->enckeylen > MAX_KEY_SIZE)
+       if (keys.enckeylen > MAX_KEY_SIZE ||
+           keys.authkeylen > MAX_KEY_SIZE)
                goto badkey;
 
-       ctx->authkeylen = keylen - ctx->enckeylen;
-
-       if (ctx->authkeylen > MAX_KEY_SIZE)
-               goto badkey;
+       ctx->enckeylen = keys.enckeylen;
+       ctx->authkeylen = keys.authkeylen;
 
-       memcpy(ctx->enckey, key + ctx->authkeylen, ctx->enckeylen);
+       memcpy(ctx->enckey, keys.enckey, keys.enckeylen);
        /* May end up padding auth key. So make sure it's zeroed. */
        memset(ctx->authkey, 0, sizeof(ctx->authkey));
-       memcpy(ctx->authkey, key, ctx->authkeylen);
+       memcpy(ctx->authkey, keys.authkey, keys.authkeylen);
 
        switch (ctx->alg->cipher_info.alg) {
        case CIPHER_ALG_DES:
@@ -2891,7 +2875,7 @@ static int aead_authenc_setkey(struct crypto_aead *cipher,
                        u32 tmp[DES_EXPKEY_WORDS];
                        u32 flags = CRYPTO_TFM_RES_WEAK_KEY;
 
-                       if (des_ekey(tmp, key) == 0) {
+                       if (des_ekey(tmp, keys.enckey) == 0) {
                                if (crypto_aead_get_flags(cipher) &
                                    CRYPTO_TFM_REQ_WEAK_KEY) {
                                        crypto_aead_set_flags(cipher, flags);
@@ -2906,7 +2890,7 @@ static int aead_authenc_setkey(struct crypto_aead *cipher,
                break;
        case CIPHER_ALG_3DES:
                if (ctx->enckeylen == (DES_KEY_SIZE * 3)) {
-                       const u32 *K = (const u32 *)key;
+                       const u32 *K = (const u32 *)keys.enckey;
                        u32 flags = CRYPTO_TFM_RES_BAD_KEY_SCHED;
 
                        if (!((K[0] ^ K[2]) | (K[1] ^ K[3])) ||
@@ -2957,9 +2941,7 @@ static int aead_authenc_setkey(struct crypto_aead *cipher,
                ctx->fallback_cipher->base.crt_flags &= ~CRYPTO_TFM_REQ_MASK;
                ctx->fallback_cipher->base.crt_flags |=
                    tfm->crt_flags & CRYPTO_TFM_REQ_MASK;
-               ret =
-                   crypto_aead_setkey(ctx->fallback_cipher, origkey,
-                                      origkeylen);
+               ret = crypto_aead_setkey(ctx->fallback_cipher, key, keylen);
                if (ret) {
                        flow_log("  fallback setkey() returned:%d\n", ret);
                        tfm->crt_flags &= ~CRYPTO_TFM_RES_MASK;