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 b445a5d56f4342b71540e40c1ce298e0ad786688..85ff69b551c2c730a59953fee9bf04721908ad05 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 6d685298690ed228b416c7cf67c58e8b6d6f2909..d004bd143e6a9bbb7f048eaf3f9db63127d9878f 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 05d9e16c0dfdd81a8a6ffe141e5c6f5cc96b3e7e..c963d75ac605043667ea681ca77fc989a9e27104 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 93ee046d12cde4f15dabcc6b6ae1b657920353c3..160807977abe041a806e50a1a81beeabd124129c 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 0b9b95f3c7037e6fcad08a5dd6453852c60d4180..3f1a1a4e81fee97a65c97075fc80e27c67bcab05 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 3633ad6145c5229a57f40ccf30421916872d4f2a..064c7e2bd7c8e8b9c10e709273217625a17ac6fe 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 5c8b6266a394b45d4317d91b05adb6cc12b15219..aa76cad9d26295b87f0e6c9beb992d85cf55a1ef 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 fca459578c355d8104654bad9d06e88c136e2f61..50e684768c555e95e57023ee781bc64418af93ef 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 5dc37026c7ce6d78407cd04cea618a10d14174a8..6f778d3daa229987b695c4f262d09071917157ac 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 3643dd508f45aa7a1a37fdf7f100358977d07830..8943407e8917a343658c0a3c81ed9ec0dc6b1735 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 56d8a08ee47908d06c80975428655629b5749c24..2ebb5e9789f3790b06aa93286932c70c1dabb676 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 f6fd43f100c8c68c7150cad5224fafc5dc61db2c..26ba5833b9944039ad1b172534e5afb09a7902eb 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 72c09eb56437b262f7bcd9739b152fae08cc7912..ede6b97b24cc3cf513874d5b598faafd7a1d13d9 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 */