crypto: xts - consolidate sanity check for keys
authorStephan Mueller <smueller@chronox.de>
Tue, 9 Feb 2016 14:37:47 +0000 (15:37 +0100)
committerHerbert Xu <herbert@gondor.apana.org.au>
Tue, 16 Feb 2016 20:07:51 +0000 (04:07 +0800)
The patch centralizes the XTS key check logic into the service function
xts_check_key which is invoked from the different XTS implementations.
With this, the XTS implementations in ARM, ARM64, PPC and S390 have now
a sanity check for the XTS keys similar to the other arches.

In addition, this service function received a check to ensure that the
key != the tweak key which is mandated by FIPS 140-2 IG A.9. As the
check is not present in the standards defining XTS, it is only enforced
in FIPS mode of the kernel.

Signed-off-by: Stephan Mueller <smueller@chronox.de>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
13 files changed:
arch/arm/crypto/aes-ce-glue.c
arch/arm/crypto/aesbs-glue.c
arch/arm64/crypto/aes-glue.c
arch/powerpc/crypto/aes-spe-glue.c
arch/s390/crypto/aes_s390.c
arch/x86/crypto/aesni-intel_glue.c
arch/x86/crypto/camellia_glue.c
arch/x86/crypto/cast6_avx_glue.c
arch/x86/crypto/serpent_avx_glue.c
arch/x86/crypto/serpent_sse2_glue.c
arch/x86/crypto/twofish_glue_3way.c
crypto/xts.c
include/crypto/xts.h

index b445a5d..85ff69b 100644 (file)
@@ -152,6 +152,10 @@ static int xts_set_key(struct crypto_tfm *tfm, const u8 *in_key,
        struct crypto_aes_xts_ctx *ctx = crypto_tfm_ctx(tfm);
        int ret;
 
+       ret = xts_check_key(tfm, in_key, key_len);
+       if (ret)
+               return ret;
+
        ret = ce_aes_expandkey(&ctx->key1, in_key, key_len / 2);
        if (!ret)
                ret = ce_aes_expandkey(&ctx->key2, &in_key[key_len / 2],
index 6d68529..d004bd1 100644 (file)
@@ -89,6 +89,11 @@ static int aesbs_xts_set_key(struct crypto_tfm *tfm, const u8 *in_key,
 {
        struct aesbs_xts_ctx *ctx = crypto_tfm_ctx(tfm);
        int bits = key_len * 4;
+       int err;
+
+       err = xts_check_key(tfm, in_key, key_len);
+       if (err)
+               return err;
 
        if (private_AES_set_encrypt_key(in_key, bits, &ctx->enc.rk)) {
                tfm->crt_flags |= CRYPTO_TFM_RES_BAD_KEY_LEN;
index 05d9e16..c963d75 100644 (file)
@@ -85,6 +85,10 @@ static int xts_set_key(struct crypto_tfm *tfm, const u8 *in_key,
        struct crypto_aes_xts_ctx *ctx = crypto_tfm_ctx(tfm);
        int ret;
 
+       ret = xts_check_key(tfm, in_key, key_len);
+       if (ret)
+               return ret;
+
        ret = aes_expandkey(&ctx->key1, in_key, key_len / 2);
        if (!ret)
                ret = aes_expandkey(&ctx->key2, &in_key[key_len / 2],
index 93ee046..1608079 100644 (file)
@@ -126,6 +126,11 @@ static int ppc_xts_setkey(struct crypto_tfm *tfm, const u8 *in_key,
                   unsigned int key_len)
 {
        struct ppc_xts_ctx *ctx = crypto_tfm_ctx(tfm);
+       int err;
+
+       err = xts_check_key(tfm, in_key, key_len);
+       if (err)
+               return err;
 
        key_len >>= 1;
 
index 0b9b95f..3f1a1a4 100644 (file)
@@ -587,6 +587,11 @@ static int xts_aes_set_key(struct crypto_tfm *tfm, const u8 *in_key,
 {
        struct s390_xts_ctx *xts_ctx = crypto_tfm_ctx(tfm);
        u32 *flags = &tfm->crt_flags;
+       int err;
+
+       err = xts_check_key(tfm, in_key, key_len);
+       if (err)
+               return err;
 
        switch (key_len) {
        case 32:
index 3633ad6..064c7e2 100644 (file)
@@ -639,16 +639,11 @@ static int xts_aesni_setkey(struct crypto_tfm *tfm, const u8 *key,
                            unsigned int keylen)
 {
        struct aesni_xts_ctx *ctx = crypto_tfm_ctx(tfm);
-       u32 *flags = &tfm->crt_flags;
        int err;
 
-       /* key consists of keys of equal size concatenated, therefore
-        * the length must be even
-        */
-       if (keylen % 2) {
-               *flags |= CRYPTO_TFM_RES_BAD_KEY_LEN;
-               return -EINVAL;
-       }
+       err = xts_check_key(tfm, key, keylen);
+       if (err)
+               return err;
 
        /* first half of xts-key is for crypt */
        err = aes_set_key_common(tfm, ctx->raw_crypt_ctx, key, keylen / 2);
index 5c8b626..aa76cad 100644 (file)
@@ -1503,13 +1503,9 @@ int xts_camellia_setkey(struct crypto_tfm *tfm, const u8 *key,
        u32 *flags = &tfm->crt_flags;
        int err;
 
-       /* key consists of keys of equal size concatenated, therefore
-        * the length must be even
-        */
-       if (keylen % 2) {
-               *flags |= CRYPTO_TFM_RES_BAD_KEY_LEN;
-               return -EINVAL;
-       }
+       err = xts_check_key(tfm, key, keylen);
+       if (err)
+               return err;
 
        /* first half of xts-key is for crypt */
        err = __camellia_setkey(&ctx->crypt_ctx, key, keylen / 2, flags);
index fca4595..50e6847 100644 (file)
@@ -329,13 +329,9 @@ static int xts_cast6_setkey(struct crypto_tfm *tfm, const u8 *key,
        u32 *flags = &tfm->crt_flags;
        int err;
 
-       /* key consists of keys of equal size concatenated, therefore
-        * the length must be even
-        */
-       if (keylen % 2) {
-               *flags |= CRYPTO_TFM_RES_BAD_KEY_LEN;
-               return -EINVAL;
-       }
+       err = xts_check_key(tfm, key, keylen);
+       if (err)
+               return err;
 
        /* first half of xts-key is for crypt */
        err = __cast6_setkey(&ctx->crypt_ctx, key, keylen / 2, flags);
index 5dc3702..6f778d3 100644 (file)
@@ -332,16 +332,11 @@ int xts_serpent_setkey(struct crypto_tfm *tfm, const u8 *key,
                       unsigned int keylen)
 {
        struct serpent_xts_ctx *ctx = crypto_tfm_ctx(tfm);
-       u32 *flags = &tfm->crt_flags;
        int err;
 
-       /* key consists of keys of equal size concatenated, therefore
-        * the length must be even
-        */
-       if (keylen % 2) {
-               *flags |= CRYPTO_TFM_RES_BAD_KEY_LEN;
-               return -EINVAL;
-       }
+       err = xts_check_key(tfm, key, keylen);
+       if (err)
+               return err;
 
        /* first half of xts-key is for crypt */
        err = __serpent_setkey(&ctx->crypt_ctx, key, keylen / 2);
index 3643dd5..8943407 100644 (file)
@@ -309,16 +309,11 @@ static int xts_serpent_setkey(struct crypto_tfm *tfm, const u8 *key,
                              unsigned int keylen)
 {
        struct serpent_xts_ctx *ctx = crypto_tfm_ctx(tfm);
-       u32 *flags = &tfm->crt_flags;
        int err;
 
-       /* key consists of keys of equal size concatenated, therefore
-        * the length must be even
-        */
-       if (keylen % 2) {
-               *flags |= CRYPTO_TFM_RES_BAD_KEY_LEN;
-               return -EINVAL;
-       }
+       err = xts_check_key(tfm, key, keylen);
+       if (err)
+               return err;
 
        /* first half of xts-key is for crypt */
        err = __serpent_setkey(&ctx->crypt_ctx, key, keylen / 2);
index 56d8a08..2ebb5e9 100644 (file)
@@ -277,13 +277,9 @@ int xts_twofish_setkey(struct crypto_tfm *tfm, const u8 *key,
        u32 *flags = &tfm->crt_flags;
        int err;
 
-       /* key consists of keys of equal size concatenated, therefore
-        * the length must be even
-        */
-       if (keylen % 2) {
-               *flags |= CRYPTO_TFM_RES_BAD_KEY_LEN;
-               return -EINVAL;
-       }
+       err = xts_check_key(tfm, key, keylen);
+       if (err)
+               return err;
 
        /* first half of xts-key is for crypt */
        err = __twofish_setkey(&ctx->crypt_ctx, key, keylen / 2, flags);
index f6fd43f..26ba583 100644 (file)
@@ -35,16 +35,11 @@ static int setkey(struct crypto_tfm *parent, const u8 *key,
 {
        struct priv *ctx = crypto_tfm_ctx(parent);
        struct crypto_cipher *child = ctx->tweak;
-       u32 *flags = &parent->crt_flags;
        int err;
 
-       /* key consists of keys of equal size concatenated, therefore
-        * the length must be even */
-       if (keylen % 2) {
-               /* tell the user why there was an error */
-               *flags |= CRYPTO_TFM_RES_BAD_KEY_LEN;
-               return -EINVAL;
-       }
+       err = xts_check_key(parent, key, keylen);
+       if (err)
+               return err;
 
        /* we need two cipher instances: one to compute the initial 'tweak'
         * by encrypting the IV (usually the 'plain' iv) and the other
index 72c09eb..ede6b97 100644 (file)
@@ -2,6 +2,9 @@
 #define _CRYPTO_XTS_H
 
 #include <crypto/b128ops.h>
+#include <linux/crypto.h>
+#include <crypto/algapi.h>
+#include <linux/fips.h>
 
 struct scatterlist;
 struct blkcipher_desc;
@@ -24,4 +27,28 @@ int xts_crypt(struct blkcipher_desc *desc, struct scatterlist *dst,
              struct scatterlist *src, unsigned int nbytes,
              struct xts_crypt_req *req);
 
+static inline int xts_check_key(struct crypto_tfm *tfm,
+                               const u8 *key, unsigned int keylen)
+{
+       u32 *flags = &tfm->crt_flags;
+
+       /*
+        * key consists of keys of equal size concatenated, therefore
+        * the length must be even.
+        */
+       if (keylen % 2) {
+               *flags |= CRYPTO_TFM_RES_BAD_KEY_LEN;
+               return -EINVAL;
+       }
+
+       /* ensure that the AES and tweak key are not identical */
+       if (fips_enabled &&
+           !crypto_memneq(key, key + (keylen / 2), keylen / 2)) {
+               *flags |= CRYPTO_TFM_RES_WEAK_KEY;
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
 #endif  /* _CRYPTO_XTS_H */