Am Sonntag, 7. Februar 2016, 14:41:22 schrieb Ard Biesheuvel: Hi Ard, > Hi Stephan, > > On 7 February 2016 at 14:05, Stephan Mueller <smueller@xxxxxxxxxx> wrote: > > Hi, > > > > I only have an x86 system for testing. May I ask the owners for the other > > architectures to review and test? > > > > ---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. > > > > Signed-off-by: Stephan Mueller <smueller@xxxxxxxxxx> > > One remark below (and a nit). With that fixed: > > Reviewed-by: Ard Biesheuvel <ard.biesheuvel@xxxxxxxxxx> Thank you. > > > --- > > > > 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 | 29 +++++++++++++++++++++++++++++ > > 13 files changed, 73 insertions(+), 53 deletions(-) > > > > diff --git a/arch/arm/crypto/aes-ce-glue.c b/arch/arm/crypto/aes-ce-glue.c > > index b445a5d..85ff69b 100644 > > --- a/arch/arm/crypto/aes-ce-glue.c > > +++ b/arch/arm/crypto/aes-ce-glue.c > > @@ -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], > > > > diff --git a/arch/arm/crypto/aesbs-glue.c b/arch/arm/crypto/aesbs-glue.c > > index 6d68529..d004bd1 100644 > > --- a/arch/arm/crypto/aesbs-glue.c > > +++ b/arch/arm/crypto/aesbs-glue.c > > @@ -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; > > > > diff --git a/arch/arm64/crypto/aes-glue.c b/arch/arm64/crypto/aes-glue.c > > index 05d9e16..c963d75 100644 > > --- a/arch/arm64/crypto/aes-glue.c > > +++ b/arch/arm64/crypto/aes-glue.c > > @@ -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], > > > > diff --git a/arch/powerpc/crypto/aes-spe-glue.c > > b/arch/powerpc/crypto/aes-spe-glue.c index 93ee046..1608079 100644 > > --- a/arch/powerpc/crypto/aes-spe-glue.c > > +++ b/arch/powerpc/crypto/aes-spe-glue.c > > @@ -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; > > > > diff --git a/arch/s390/crypto/aes_s390.c b/arch/s390/crypto/aes_s390.c > > index 0b9b95f..3f1a1a4 100644 > > --- a/arch/s390/crypto/aes_s390.c > > +++ b/arch/s390/crypto/aes_s390.c > > @@ -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: > > diff --git a/arch/x86/crypto/aesni-intel_glue.c > > b/arch/x86/crypto/aesni-intel_glue.c index 3633ad6..064c7e2 100644 > > --- a/arch/x86/crypto/aesni-intel_glue.c > > +++ b/arch/x86/crypto/aesni-intel_glue.c > > @@ -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); > > > > diff --git a/arch/x86/crypto/camellia_glue.c > > b/arch/x86/crypto/camellia_glue.c index 5c8b626..aa76cad 100644 > > --- a/arch/x86/crypto/camellia_glue.c > > +++ b/arch/x86/crypto/camellia_glue.c > > @@ -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); > > > > diff --git a/arch/x86/crypto/cast6_avx_glue.c > > b/arch/x86/crypto/cast6_avx_glue.c index fca4595..50e6847 100644 > > --- a/arch/x86/crypto/cast6_avx_glue.c > > +++ b/arch/x86/crypto/cast6_avx_glue.c > > @@ -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); > > > > diff --git a/arch/x86/crypto/serpent_avx_glue.c > > b/arch/x86/crypto/serpent_avx_glue.c index 5dc3702..6f778d3 100644 > > --- a/arch/x86/crypto/serpent_avx_glue.c > > +++ b/arch/x86/crypto/serpent_avx_glue.c > > @@ -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); > > > > diff --git a/arch/x86/crypto/serpent_sse2_glue.c > > b/arch/x86/crypto/serpent_sse2_glue.c index 3643dd5..8943407 100644 > > --- a/arch/x86/crypto/serpent_sse2_glue.c > > +++ b/arch/x86/crypto/serpent_sse2_glue.c > > @@ -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); > > > > diff --git a/arch/x86/crypto/twofish_glue_3way.c > > b/arch/x86/crypto/twofish_glue_3way.c index 56d8a08..2ebb5e9 100644 > > --- a/arch/x86/crypto/twofish_glue_3way.c > > +++ b/arch/x86/crypto/twofish_glue_3way.c > > @@ -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); > > > > diff --git a/crypto/xts.c b/crypto/xts.c > > index f6fd43f..26ba583 100644 > > --- a/crypto/xts.c > > +++ b/crypto/xts.c > > @@ -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 > > > > diff --git a/include/crypto/xts.h b/include/crypto/xts.h > > index 72c09eb..41d936e 100644 > > --- a/include/crypto/xts.h > > +++ b/include/crypto/xts.h > > @@ -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,30 @@ 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) { > > + /* tell the user why there was an error */ > > Nit: I don't think this comment adds anything useful tbh I just copied it from the x86 code -- I will remove it. > > > + *flags |= CRYPTO_TFM_RES_BAD_KEY_LEN; > > + return -EINVAL; > > + } > > + > > +#ifdef CONFIG_CRYPTO_FIPS > > + /* ensure that the AES and tweak key are not identical */ > > + if (fips_enabled && > > This is redundant. 'fips_enabled' is #defined to 0 if CRYPTO_FIPS=n so > you can lose the #ifdef entirely. I would concur. But then we have an additional check which is not really required in the "normal" use case. As I have seen that all FIPS related stuff is encapsulated with the FIPS ifdef, I thought this is warranted here too. I am fine either way though. Herbert, what do you think? > > > + !crypto_memneq(key, key + (keylen / 2), keylen / 2)) { > > + *flags |= CRYPTO_TFM_RES_WEAK_KEY; > > + return -EINVAL; > > + } > > +#endif > > + return 0; > > +} > > + > > > > #endif /* _CRYPTO_XTS_H */ > > > > -- > > 2.5.0 Ciao Stephan -- To unsubscribe from this list: send the line "unsubscribe linux-crypto" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html