Commit 28856a9e52c7cac712af6c143de04766617535dc

Authored by Stephan Mueller
Committed by Herbert Xu
1 parent 730d02e276

crypto: xts - consolidate sanity check for keys

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>

Showing 13 changed files with 71 additions and 53 deletions Side-by-side Diff

arch/arm/crypto/aes-ce-glue.c
... ... @@ -152,6 +152,10 @@
152 152 struct crypto_aes_xts_ctx *ctx = crypto_tfm_ctx(tfm);
153 153 int ret;
154 154  
  155 + ret = xts_check_key(tfm, in_key, key_len);
  156 + if (ret)
  157 + return ret;
  158 +
155 159 ret = ce_aes_expandkey(&ctx->key1, in_key, key_len / 2);
156 160 if (!ret)
157 161 ret = ce_aes_expandkey(&ctx->key2, &in_key[key_len / 2],
arch/arm/crypto/aesbs-glue.c
... ... @@ -89,6 +89,11 @@
89 89 {
90 90 struct aesbs_xts_ctx *ctx = crypto_tfm_ctx(tfm);
91 91 int bits = key_len * 4;
  92 + int err;
  93 +
  94 + err = xts_check_key(tfm, in_key, key_len);
  95 + if (err)
  96 + return err;
92 97  
93 98 if (private_AES_set_encrypt_key(in_key, bits, &ctx->enc.rk)) {
94 99 tfm->crt_flags |= CRYPTO_TFM_RES_BAD_KEY_LEN;
arch/arm64/crypto/aes-glue.c
... ... @@ -85,6 +85,10 @@
85 85 struct crypto_aes_xts_ctx *ctx = crypto_tfm_ctx(tfm);
86 86 int ret;
87 87  
  88 + ret = xts_check_key(tfm, in_key, key_len);
  89 + if (ret)
  90 + return ret;
  91 +
88 92 ret = aes_expandkey(&ctx->key1, in_key, key_len / 2);
89 93 if (!ret)
90 94 ret = aes_expandkey(&ctx->key2, &in_key[key_len / 2],
arch/powerpc/crypto/aes-spe-glue.c
... ... @@ -126,6 +126,11 @@
126 126 unsigned int key_len)
127 127 {
128 128 struct ppc_xts_ctx *ctx = crypto_tfm_ctx(tfm);
  129 + int err;
  130 +
  131 + err = xts_check_key(tfm, in_key, key_len);
  132 + if (err)
  133 + return err;
129 134  
130 135 key_len >>= 1;
131 136  
arch/s390/crypto/aes_s390.c
... ... @@ -587,6 +587,11 @@
587 587 {
588 588 struct s390_xts_ctx *xts_ctx = crypto_tfm_ctx(tfm);
589 589 u32 *flags = &tfm->crt_flags;
  590 + int err;
  591 +
  592 + err = xts_check_key(tfm, in_key, key_len);
  593 + if (err)
  594 + return err;
590 595  
591 596 switch (key_len) {
592 597 case 32:
arch/x86/crypto/aesni-intel_glue.c
... ... @@ -639,16 +639,11 @@
639 639 unsigned int keylen)
640 640 {
641 641 struct aesni_xts_ctx *ctx = crypto_tfm_ctx(tfm);
642   - u32 *flags = &tfm->crt_flags;
643 642 int err;
644 643  
645   - /* key consists of keys of equal size concatenated, therefore
646   - * the length must be even
647   - */
648   - if (keylen % 2) {
649   - *flags |= CRYPTO_TFM_RES_BAD_KEY_LEN;
650   - return -EINVAL;
651   - }
  644 + err = xts_check_key(tfm, key, keylen);
  645 + if (err)
  646 + return err;
652 647  
653 648 /* first half of xts-key is for crypt */
654 649 err = aes_set_key_common(tfm, ctx->raw_crypt_ctx, key, keylen / 2);
arch/x86/crypto/camellia_glue.c
... ... @@ -1503,13 +1503,9 @@
1503 1503 u32 *flags = &tfm->crt_flags;
1504 1504 int err;
1505 1505  
1506   - /* key consists of keys of equal size concatenated, therefore
1507   - * the length must be even
1508   - */
1509   - if (keylen % 2) {
1510   - *flags |= CRYPTO_TFM_RES_BAD_KEY_LEN;
1511   - return -EINVAL;
1512   - }
  1506 + err = xts_check_key(tfm, key, keylen);
  1507 + if (err)
  1508 + return err;
1513 1509  
1514 1510 /* first half of xts-key is for crypt */
1515 1511 err = __camellia_setkey(&ctx->crypt_ctx, key, keylen / 2, flags);
arch/x86/crypto/cast6_avx_glue.c
... ... @@ -329,13 +329,9 @@
329 329 u32 *flags = &tfm->crt_flags;
330 330 int err;
331 331  
332   - /* key consists of keys of equal size concatenated, therefore
333   - * the length must be even
334   - */
335   - if (keylen % 2) {
336   - *flags |= CRYPTO_TFM_RES_BAD_KEY_LEN;
337   - return -EINVAL;
338   - }
  332 + err = xts_check_key(tfm, key, keylen);
  333 + if (err)
  334 + return err;
339 335  
340 336 /* first half of xts-key is for crypt */
341 337 err = __cast6_setkey(&ctx->crypt_ctx, key, keylen / 2, flags);
arch/x86/crypto/serpent_avx_glue.c
... ... @@ -332,16 +332,11 @@
332 332 unsigned int keylen)
333 333 {
334 334 struct serpent_xts_ctx *ctx = crypto_tfm_ctx(tfm);
335   - u32 *flags = &tfm->crt_flags;
336 335 int err;
337 336  
338   - /* key consists of keys of equal size concatenated, therefore
339   - * the length must be even
340   - */
341   - if (keylen % 2) {
342   - *flags |= CRYPTO_TFM_RES_BAD_KEY_LEN;
343   - return -EINVAL;
344   - }
  337 + err = xts_check_key(tfm, key, keylen);
  338 + if (err)
  339 + return err;
345 340  
346 341 /* first half of xts-key is for crypt */
347 342 err = __serpent_setkey(&ctx->crypt_ctx, key, keylen / 2);
arch/x86/crypto/serpent_sse2_glue.c
... ... @@ -309,16 +309,11 @@
309 309 unsigned int keylen)
310 310 {
311 311 struct serpent_xts_ctx *ctx = crypto_tfm_ctx(tfm);
312   - u32 *flags = &tfm->crt_flags;
313 312 int err;
314 313  
315   - /* key consists of keys of equal size concatenated, therefore
316   - * the length must be even
317   - */
318   - if (keylen % 2) {
319   - *flags |= CRYPTO_TFM_RES_BAD_KEY_LEN;
320   - return -EINVAL;
321   - }
  314 + err = xts_check_key(tfm, key, keylen);
  315 + if (err)
  316 + return err;
322 317  
323 318 /* first half of xts-key is for crypt */
324 319 err = __serpent_setkey(&ctx->crypt_ctx, key, keylen / 2);
arch/x86/crypto/twofish_glue_3way.c
... ... @@ -277,13 +277,9 @@
277 277 u32 *flags = &tfm->crt_flags;
278 278 int err;
279 279  
280   - /* key consists of keys of equal size concatenated, therefore
281   - * the length must be even
282   - */
283   - if (keylen % 2) {
284   - *flags |= CRYPTO_TFM_RES_BAD_KEY_LEN;
285   - return -EINVAL;
286   - }
  280 + err = xts_check_key(tfm, key, keylen);
  281 + if (err)
  282 + return err;
287 283  
288 284 /* first half of xts-key is for crypt */
289 285 err = __twofish_setkey(&ctx->crypt_ctx, key, keylen / 2, flags);
... ... @@ -35,16 +35,11 @@
35 35 {
36 36 struct priv *ctx = crypto_tfm_ctx(parent);
37 37 struct crypto_cipher *child = ctx->tweak;
38   - u32 *flags = &parent->crt_flags;
39 38 int err;
40 39  
41   - /* key consists of keys of equal size concatenated, therefore
42   - * the length must be even */
43   - if (keylen % 2) {
44   - /* tell the user why there was an error */
45   - *flags |= CRYPTO_TFM_RES_BAD_KEY_LEN;
46   - return -EINVAL;
47   - }
  40 + err = xts_check_key(parent, key, keylen);
  41 + if (err)
  42 + return err;
48 43  
49 44 /* we need two cipher instances: one to compute the initial 'tweak'
50 45 * by encrypting the IV (usually the 'plain' iv) and the other
include/crypto/xts.h
... ... @@ -2,6 +2,9 @@
2 2 #define _CRYPTO_XTS_H
3 3  
4 4 #include <crypto/b128ops.h>
  5 +#include <linux/crypto.h>
  6 +#include <crypto/algapi.h>
  7 +#include <linux/fips.h>
5 8  
6 9 struct scatterlist;
7 10 struct blkcipher_desc;
... ... @@ -23,6 +26,30 @@
23 26 int xts_crypt(struct blkcipher_desc *desc, struct scatterlist *dst,
24 27 struct scatterlist *src, unsigned int nbytes,
25 28 struct xts_crypt_req *req);
  29 +
  30 +static inline int xts_check_key(struct crypto_tfm *tfm,
  31 + const u8 *key, unsigned int keylen)
  32 +{
  33 + u32 *flags = &tfm->crt_flags;
  34 +
  35 + /*
  36 + * key consists of keys of equal size concatenated, therefore
  37 + * the length must be even.
  38 + */
  39 + if (keylen % 2) {
  40 + *flags |= CRYPTO_TFM_RES_BAD_KEY_LEN;
  41 + return -EINVAL;
  42 + }
  43 +
  44 + /* ensure that the AES and tweak key are not identical */
  45 + if (fips_enabled &&
  46 + !crypto_memneq(key, key + (keylen / 2), keylen / 2)) {
  47 + *flags |= CRYPTO_TFM_RES_WEAK_KEY;
  48 + return -EINVAL;
  49 + }
  50 +
  51 + return 0;
  52 +}
26 53  
27 54 #endif /* _CRYPTO_XTS_H */