aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArd Biesheuvel <ard.biesheuvel@linaro.org>2019-08-15 05:00:43 -0400
committerHerbert Xu <herbert@gondor.apana.org.au>2019-08-22 00:39:37 -0400
commit6ee41e5420d0afa8cddf09aa7384dabe570f8dc7 (patch)
treeadaf9488cfc99fde2a383fdb077c1fb55a3a4bc0
parent220f67917ae649336b5fef4dec8024fed4b177f3 (diff)
crypto: des/3des_ede - add new helpers to verify keys
The recently added helper routine to perform key strength validation of triple DES keys is slightly inadequate, since it comes in two versions, neither of which are highly useful for anything other than skciphers (and many drivers still use the older blkcipher interfaces). So let's add a new helper and, considering that this is a helper function that is only intended to be used by crypto code itself, put it in a new des.h header under crypto/internal. While at it, implement a similar helper for single DES, so that we can start replacing the pattern of calling des_ekey() into a temp buffer that occurs in many drivers in drivers/crypto. Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org> Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
-rw-r--r--crypto/des_generic.c13
-rw-r--r--include/crypto/internal/des.h141
2 files changed, 141 insertions, 13 deletions
diff --git a/crypto/des_generic.c b/crypto/des_generic.c
index dc085514408a..c4d8ecda4ddf 100644
--- a/crypto/des_generic.c
+++ b/crypto/des_generic.c
@@ -841,19 +841,6 @@ static void des_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
841 d[1] = cpu_to_le32(L); 841 d[1] = cpu_to_le32(L);
842} 842}
843 843
844/*
845 * RFC2451:
846 *
847 * For DES-EDE3, there is no known need to reject weak or
848 * complementation keys. Any weakness is obviated by the use of
849 * multiple keys.
850 *
851 * However, if the first two or last two independent 64-bit keys are
852 * equal (k1 == k2 or k2 == k3), then the DES3 operation is simply the
853 * same as DES. Implementers MUST reject keys that exhibit this
854 * property.
855 *
856 */
857int __des3_ede_setkey(u32 *expkey, u32 *flags, const u8 *key, 844int __des3_ede_setkey(u32 *expkey, u32 *flags, const u8 *key,
858 unsigned int keylen) 845 unsigned int keylen)
859{ 846{
diff --git a/include/crypto/internal/des.h b/include/crypto/internal/des.h
new file mode 100644
index 000000000000..f5d2e696522e
--- /dev/null
+++ b/include/crypto/internal/des.h
@@ -0,0 +1,141 @@
1/* SPDX-License-Identifier: GPL-2.0 */
2/*
3 * DES & Triple DES EDE key verification helpers
4 */
5
6#ifndef __CRYPTO_INTERNAL_DES_H
7#define __CRYPTO_INTERNAL_DES_H
8
9#include <linux/crypto.h>
10#include <linux/fips.h>
11#include <crypto/des.h>
12#include <crypto/aead.h>
13#include <crypto/skcipher.h>
14
15/**
16 * crypto_des_verify_key - Check whether a DES key is weak
17 * @tfm: the crypto algo
18 * @key: the key buffer
19 *
20 * Returns -EINVAL if the key is weak and the crypto TFM does not permit weak
21 * keys. Otherwise, 0 is returned.
22 *
23 * It is the job of the caller to ensure that the size of the key equals
24 * DES_KEY_SIZE.
25 */
26static inline int crypto_des_verify_key(struct crypto_tfm *tfm, const u8 *key)
27{
28 u32 tmp[DES_EXPKEY_WORDS];
29 int err = 0;
30
31 if (!(crypto_tfm_get_flags(tfm) & CRYPTO_TFM_REQ_FORBID_WEAK_KEYS))
32 return 0;
33
34 if (!des_ekey(tmp, key)) {
35 crypto_tfm_set_flags(tfm, CRYPTO_TFM_RES_WEAK_KEY);
36 err = -EINVAL;
37 }
38
39 memzero_explicit(tmp, sizeof(tmp));
40 return err;
41}
42
43/*
44 * RFC2451:
45 *
46 * For DES-EDE3, there is no known need to reject weak or
47 * complementation keys. Any weakness is obviated by the use of
48 * multiple keys.
49 *
50 * However, if the first two or last two independent 64-bit keys are
51 * equal (k1 == k2 or k2 == k3), then the DES3 operation is simply the
52 * same as DES. Implementers MUST reject keys that exhibit this
53 * property.
54 *
55 */
56
57/**
58 * crypto_des3_ede_verify_key - Check whether a DES3-EDE key is weak
59 * @tfm: the crypto algo
60 * @key: the key buffer
61 *
62 * Returns -EINVAL if the key is weak and the crypto TFM does not permit weak
63 * keys or when running in FIPS mode. Otherwise, 0 is returned. Note that some
64 * keys are rejected in FIPS mode even if weak keys are permitted by the TFM
65 * flags.
66 *
67 * It is the job of the caller to ensure that the size of the key equals
68 * DES3_EDE_KEY_SIZE.
69 */
70static inline int crypto_des3_ede_verify_key(struct crypto_tfm *tfm,
71 const u8 *key)
72{
73 int err = -EINVAL;
74 u32 K[6];
75
76 memcpy(K, key, DES3_EDE_KEY_SIZE);
77
78 if ((!((K[0] ^ K[2]) | (K[1] ^ K[3])) ||
79 !((K[2] ^ K[4]) | (K[3] ^ K[5]))) &&
80 (fips_enabled || (crypto_tfm_get_flags(tfm) &
81 CRYPTO_TFM_REQ_FORBID_WEAK_KEYS)))
82 goto bad;
83
84 if ((!((K[0] ^ K[4]) | (K[1] ^ K[5]))) && fips_enabled)
85 goto bad;
86
87 err = 0;
88out:
89 memzero_explicit(K, DES3_EDE_KEY_SIZE);
90 return err;
91
92bad:
93 crypto_tfm_set_flags(tfm, CRYPTO_TFM_RES_WEAK_KEY);
94 goto out;
95}
96
97static inline int verify_skcipher_des_key(struct crypto_skcipher *tfm,
98 const u8 *key)
99{
100 return crypto_des_verify_key(crypto_skcipher_tfm(tfm), key);
101}
102
103static inline int verify_skcipher_des3_key(struct crypto_skcipher *tfm,
104 const u8 *key)
105{
106 return crypto_des3_ede_verify_key(crypto_skcipher_tfm(tfm), key);
107}
108
109static inline int verify_ablkcipher_des_key(struct crypto_ablkcipher *tfm,
110 const u8 *key)
111{
112 return crypto_des_verify_key(crypto_ablkcipher_tfm(tfm), key);
113}
114
115static inline int verify_ablkcipher_des3_key(struct crypto_ablkcipher *tfm,
116 const u8 *key)
117{
118 return crypto_des3_ede_verify_key(crypto_ablkcipher_tfm(tfm), key);
119}
120
121static inline int verify_aead_des_key(struct crypto_aead *tfm, const u8 *key,
122 int keylen)
123{
124 if (keylen != DES_KEY_SIZE) {
125 crypto_aead_set_flags(tfm, CRYPTO_TFM_RES_BAD_KEY_LEN);
126 return -EINVAL;
127 }
128 return crypto_des_verify_key(crypto_aead_tfm(tfm), key);
129}
130
131static inline int verify_aead_des3_key(struct crypto_aead *tfm, const u8 *key,
132 int keylen)
133{
134 if (keylen != DES3_EDE_KEY_SIZE) {
135 crypto_aead_set_flags(tfm, CRYPTO_TFM_RES_BAD_KEY_LEN);
136 return -EINVAL;
137 }
138 return crypto_des3_ede_verify_key(crypto_aead_tfm(tfm), key);
139}
140
141#endif /* __CRYPTO_INTERNAL_DES_H */