hc
2024-08-16 a24a44ff9ca902811b99aa9663d697cf452e08ef
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
/* SPDX-License-Identifier: GPL-2.0 */
/*
 * DES & Triple DES EDE key verification helpers
 */
 
#ifndef __CRYPTO_INTERNAL_DES_H
#define __CRYPTO_INTERNAL_DES_H
 
#include <linux/crypto.h>
#include <linux/fips.h>
#include <crypto/des.h>
#include <crypto/aead.h>
#include <crypto/skcipher.h>
 
/**
 * crypto_des_verify_key - Check whether a DES key is weak
 * @tfm: the crypto algo
 * @key: the key buffer
 *
 * Returns -EINVAL if the key is weak and the crypto TFM does not permit weak
 * keys. Otherwise, 0 is returned.
 *
 * It is the job of the caller to ensure that the size of the key equals
 * DES_KEY_SIZE.
 */
static inline int crypto_des_verify_key(struct crypto_tfm *tfm, const u8 *key)
{
   struct des_ctx tmp;
   int err;
 
   err = des_expand_key(&tmp, key, DES_KEY_SIZE);
   if (err == -ENOKEY) {
       if (crypto_tfm_get_flags(tfm) & CRYPTO_TFM_REQ_FORBID_WEAK_KEYS)
           err = -EINVAL;
       else
           err = 0;
   }
   memzero_explicit(&tmp, sizeof(tmp));
   return err;
}
 
/*
 * RFC2451:
 *
 *   For DES-EDE3, there is no known need to reject weak or
 *   complementation keys.  Any weakness is obviated by the use of
 *   multiple keys.
 *
 *   However, if the first two or last two independent 64-bit keys are
 *   equal (k1 == k2 or k2 == k3), then the DES3 operation is simply the
 *   same as DES.  Implementers MUST reject keys that exhibit this
 *   property.
 *
 */
static inline int des3_ede_verify_key(const u8 *key, unsigned int key_len,
                     bool check_weak)
{
   int ret = fips_enabled ? -EINVAL : -ENOKEY;
   u32 K[6];
 
   memcpy(K, key, DES3_EDE_KEY_SIZE);
 
   if ((!((K[0] ^ K[2]) | (K[1] ^ K[3])) ||
        !((K[2] ^ K[4]) | (K[3] ^ K[5]))) &&
       (fips_enabled || check_weak))
       goto bad;
 
   if ((!((K[0] ^ K[4]) | (K[1] ^ K[5]))) && fips_enabled)
       goto bad;
 
   ret = 0;
bad:
   memzero_explicit(K, DES3_EDE_KEY_SIZE);
 
   return ret;
}
 
/**
 * crypto_des3_ede_verify_key - Check whether a DES3-EDE key is weak
 * @tfm: the crypto algo
 * @key: the key buffer
 *
 * Returns -EINVAL if the key is weak and the crypto TFM does not permit weak
 * keys or when running in FIPS mode. Otherwise, 0 is returned. Note that some
 * keys are rejected in FIPS mode even if weak keys are permitted by the TFM
 * flags.
 *
 * It is the job of the caller to ensure that the size of the key equals
 * DES3_EDE_KEY_SIZE.
 */
static inline int crypto_des3_ede_verify_key(struct crypto_tfm *tfm,
                        const u8 *key)
{
   return des3_ede_verify_key(key, DES3_EDE_KEY_SIZE,
                  crypto_tfm_get_flags(tfm) &
                  CRYPTO_TFM_REQ_FORBID_WEAK_KEYS);
}
 
static inline int verify_skcipher_des_key(struct crypto_skcipher *tfm,
                     const u8 *key)
{
   return crypto_des_verify_key(crypto_skcipher_tfm(tfm), key);
}
 
static inline int verify_skcipher_des3_key(struct crypto_skcipher *tfm,
                      const u8 *key)
{
   return crypto_des3_ede_verify_key(crypto_skcipher_tfm(tfm), key);
}
 
static inline int verify_aead_des_key(struct crypto_aead *tfm, const u8 *key,
                     int keylen)
{
   if (keylen != DES_KEY_SIZE)
       return -EINVAL;
   return crypto_des_verify_key(crypto_aead_tfm(tfm), key);
}
 
static inline int verify_aead_des3_key(struct crypto_aead *tfm, const u8 *key,
                      int keylen)
{
   if (keylen != DES3_EDE_KEY_SIZE)
       return -EINVAL;
   return crypto_des3_ede_verify_key(crypto_aead_tfm(tfm), key);
}
 
#endif /* __CRYPTO_INTERNAL_DES_H */