crypto: xts - consolidate sanity check for keys
Subsystems (7)
PATCH v2 1/1 crypto: xts - consolidate sanity check for keys
Hi,
Changes v2: remove comment and remove FIPS ifdefs as requested by Ard Biesheuvel
---8<---
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.
--- arch/arm/crypto/aes-ce-glue.c | 4 ++++ arch/arm/crypto/aesbs-glue.c | 5 +++++ arch/arm64/crypto/aes-glue.c | 4 ++++ arch/powerpc/crypto/aes-spe-glue.c | 5 +++++ arch/s390/crypto/aes_s390.c | 5 +++++ arch/x86/crypto/aesni-intel_glue.c | 11 +++-------- arch/x86/crypto/camellia_glue.c | 10 +++------- arch/x86/crypto/cast6_avx_glue.c | 10 +++------- arch/x86/crypto/serpent_avx_glue.c | 11 +++-------- arch/x86/crypto/serpent_sse2_glue.c | 11 +++-------- arch/x86/crypto/twofish_glue_3way.c | 10 +++------- crypto/xts.c | 11 +++-------- include/crypto/xts.h | 27 +++++++++++++++++++++++++++ 13 files changed, 71 insertions(+), 53 deletions(-)
arch/arm/crypto/aes-ce-glue.c +4 -0
@@ -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],
arch/arm/crypto/aesbs-glue.c +5 -0
@@ -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 ;
arch/arm64/crypto/aes-glue.c +4 -0
@@ -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],
arch/powerpc/crypto/aes-spe-glue.c +5 -0
@@ -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 ;
arch/s390/crypto/aes_s390.c +5 -0
@@ -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 :
arch/x86/crypto/aesni-intel_glue.c +3 -8
@@ -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 );
arch/x86/crypto/camellia_glue.c +3 -7
@@ -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);
arch/x86/crypto/cast6_avx_glue.c +3 -7
@@ -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);
arch/x86/crypto/serpent_avx_glue.c +3 -8
@@ -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 );
arch/x86/crypto/serpent_sse2_glue.c +3 -8
@@ -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 );
arch/x86/crypto/twofish_glue_3way.c +3 -7
@@ -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);
crypto/xts.c +3 -8
@@ -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
include/crypto/xts.h +27 -0
@@ -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 */
Signature · 1 line
2.5.0
Quoted 4 lines · Stephan Mueller
Hi,
Changes v2: remove comment and remove FIPS ifdefs as requested by Ard Biesheuvel
Applied.
Signature · 3 lines
Email: Herbert Xu <[email protected]> Home Page: http://gondor.apana.org.au/~herbert/ PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt