mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02:00 
			
		
		
		
	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>
This commit is contained in:
		
							parent
							
								
									730d02e276
								
							
						
					
					
						commit
						28856a9e52
					
				
					 13 changed files with 71 additions and 53 deletions
				
			
		| 
						 | 
					@ -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);
 | 
						struct crypto_aes_xts_ctx *ctx = crypto_tfm_ctx(tfm);
 | 
				
			||||||
	int ret;
 | 
						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);
 | 
						ret = ce_aes_expandkey(&ctx->key1, in_key, key_len / 2);
 | 
				
			||||||
	if (!ret)
 | 
						if (!ret)
 | 
				
			||||||
		ret = ce_aes_expandkey(&ctx->key2, &in_key[key_len / 2],
 | 
							ret = ce_aes_expandkey(&ctx->key2, &in_key[key_len / 2],
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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);
 | 
						struct aesbs_xts_ctx *ctx = crypto_tfm_ctx(tfm);
 | 
				
			||||||
	int bits = key_len * 4;
 | 
						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)) {
 | 
						if (private_AES_set_encrypt_key(in_key, bits, &ctx->enc.rk)) {
 | 
				
			||||||
		tfm->crt_flags |= CRYPTO_TFM_RES_BAD_KEY_LEN;
 | 
							tfm->crt_flags |= CRYPTO_TFM_RES_BAD_KEY_LEN;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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);
 | 
						struct crypto_aes_xts_ctx *ctx = crypto_tfm_ctx(tfm);
 | 
				
			||||||
	int ret;
 | 
						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);
 | 
						ret = aes_expandkey(&ctx->key1, in_key, key_len / 2);
 | 
				
			||||||
	if (!ret)
 | 
						if (!ret)
 | 
				
			||||||
		ret = aes_expandkey(&ctx->key2, &in_key[key_len / 2],
 | 
							ret = aes_expandkey(&ctx->key2, &in_key[key_len / 2],
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -126,6 +126,11 @@ static int ppc_xts_setkey(struct crypto_tfm *tfm, const u8 *in_key,
 | 
				
			||||||
		   unsigned int key_len)
 | 
							   unsigned int key_len)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct ppc_xts_ctx *ctx = crypto_tfm_ctx(tfm);
 | 
						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;
 | 
						key_len >>= 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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);
 | 
						struct s390_xts_ctx *xts_ctx = crypto_tfm_ctx(tfm);
 | 
				
			||||||
	u32 *flags = &tfm->crt_flags;
 | 
						u32 *flags = &tfm->crt_flags;
 | 
				
			||||||
 | 
						int err;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						err = xts_check_key(tfm, in_key, key_len);
 | 
				
			||||||
 | 
						if (err)
 | 
				
			||||||
 | 
							return err;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	switch (key_len) {
 | 
						switch (key_len) {
 | 
				
			||||||
	case 32:
 | 
						case 32:
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -639,16 +639,11 @@ static int xts_aesni_setkey(struct crypto_tfm *tfm, const u8 *key,
 | 
				
			||||||
			    unsigned int keylen)
 | 
								    unsigned int keylen)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct aesni_xts_ctx *ctx = crypto_tfm_ctx(tfm);
 | 
						struct aesni_xts_ctx *ctx = crypto_tfm_ctx(tfm);
 | 
				
			||||||
	u32 *flags = &tfm->crt_flags;
 | 
					 | 
				
			||||||
	int err;
 | 
						int err;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* key consists of keys of equal size concatenated, therefore
 | 
						err = xts_check_key(tfm, key, keylen);
 | 
				
			||||||
	 * the length must be even
 | 
						if (err)
 | 
				
			||||||
	 */
 | 
							return err;
 | 
				
			||||||
	if (keylen % 2) {
 | 
					 | 
				
			||||||
		*flags |= CRYPTO_TFM_RES_BAD_KEY_LEN;
 | 
					 | 
				
			||||||
		return -EINVAL;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* first half of xts-key is for crypt */
 | 
						/* first half of xts-key is for crypt */
 | 
				
			||||||
	err = aes_set_key_common(tfm, ctx->raw_crypt_ctx, key, keylen / 2);
 | 
						err = aes_set_key_common(tfm, ctx->raw_crypt_ctx, key, keylen / 2);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1503,13 +1503,9 @@ int xts_camellia_setkey(struct crypto_tfm *tfm, const u8 *key,
 | 
				
			||||||
	u32 *flags = &tfm->crt_flags;
 | 
						u32 *flags = &tfm->crt_flags;
 | 
				
			||||||
	int err;
 | 
						int err;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* key consists of keys of equal size concatenated, therefore
 | 
						err = xts_check_key(tfm, key, keylen);
 | 
				
			||||||
	 * the length must be even
 | 
						if (err)
 | 
				
			||||||
	 */
 | 
							return err;
 | 
				
			||||||
	if (keylen % 2) {
 | 
					 | 
				
			||||||
		*flags |= CRYPTO_TFM_RES_BAD_KEY_LEN;
 | 
					 | 
				
			||||||
		return -EINVAL;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* first half of xts-key is for crypt */
 | 
						/* first half of xts-key is for crypt */
 | 
				
			||||||
	err = __camellia_setkey(&ctx->crypt_ctx, key, keylen / 2, flags);
 | 
						err = __camellia_setkey(&ctx->crypt_ctx, key, keylen / 2, flags);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -329,13 +329,9 @@ static int xts_cast6_setkey(struct crypto_tfm *tfm, const u8 *key,
 | 
				
			||||||
	u32 *flags = &tfm->crt_flags;
 | 
						u32 *flags = &tfm->crt_flags;
 | 
				
			||||||
	int err;
 | 
						int err;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* key consists of keys of equal size concatenated, therefore
 | 
						err = xts_check_key(tfm, key, keylen);
 | 
				
			||||||
	 * the length must be even
 | 
						if (err)
 | 
				
			||||||
	 */
 | 
							return err;
 | 
				
			||||||
	if (keylen % 2) {
 | 
					 | 
				
			||||||
		*flags |= CRYPTO_TFM_RES_BAD_KEY_LEN;
 | 
					 | 
				
			||||||
		return -EINVAL;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* first half of xts-key is for crypt */
 | 
						/* first half of xts-key is for crypt */
 | 
				
			||||||
	err = __cast6_setkey(&ctx->crypt_ctx, key, keylen / 2, flags);
 | 
						err = __cast6_setkey(&ctx->crypt_ctx, key, keylen / 2, flags);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -332,16 +332,11 @@ int xts_serpent_setkey(struct crypto_tfm *tfm, const u8 *key,
 | 
				
			||||||
		       unsigned int keylen)
 | 
							       unsigned int keylen)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct serpent_xts_ctx *ctx = crypto_tfm_ctx(tfm);
 | 
						struct serpent_xts_ctx *ctx = crypto_tfm_ctx(tfm);
 | 
				
			||||||
	u32 *flags = &tfm->crt_flags;
 | 
					 | 
				
			||||||
	int err;
 | 
						int err;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* key consists of keys of equal size concatenated, therefore
 | 
						err = xts_check_key(tfm, key, keylen);
 | 
				
			||||||
	 * the length must be even
 | 
						if (err)
 | 
				
			||||||
	 */
 | 
							return err;
 | 
				
			||||||
	if (keylen % 2) {
 | 
					 | 
				
			||||||
		*flags |= CRYPTO_TFM_RES_BAD_KEY_LEN;
 | 
					 | 
				
			||||||
		return -EINVAL;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* first half of xts-key is for crypt */
 | 
						/* first half of xts-key is for crypt */
 | 
				
			||||||
	err = __serpent_setkey(&ctx->crypt_ctx, key, keylen / 2);
 | 
						err = __serpent_setkey(&ctx->crypt_ctx, key, keylen / 2);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -309,16 +309,11 @@ static int xts_serpent_setkey(struct crypto_tfm *tfm, const u8 *key,
 | 
				
			||||||
			      unsigned int keylen)
 | 
								      unsigned int keylen)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct serpent_xts_ctx *ctx = crypto_tfm_ctx(tfm);
 | 
						struct serpent_xts_ctx *ctx = crypto_tfm_ctx(tfm);
 | 
				
			||||||
	u32 *flags = &tfm->crt_flags;
 | 
					 | 
				
			||||||
	int err;
 | 
						int err;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* key consists of keys of equal size concatenated, therefore
 | 
						err = xts_check_key(tfm, key, keylen);
 | 
				
			||||||
	 * the length must be even
 | 
						if (err)
 | 
				
			||||||
	 */
 | 
							return err;
 | 
				
			||||||
	if (keylen % 2) {
 | 
					 | 
				
			||||||
		*flags |= CRYPTO_TFM_RES_BAD_KEY_LEN;
 | 
					 | 
				
			||||||
		return -EINVAL;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* first half of xts-key is for crypt */
 | 
						/* first half of xts-key is for crypt */
 | 
				
			||||||
	err = __serpent_setkey(&ctx->crypt_ctx, key, keylen / 2);
 | 
						err = __serpent_setkey(&ctx->crypt_ctx, key, keylen / 2);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -277,13 +277,9 @@ int xts_twofish_setkey(struct crypto_tfm *tfm, const u8 *key,
 | 
				
			||||||
	u32 *flags = &tfm->crt_flags;
 | 
						u32 *flags = &tfm->crt_flags;
 | 
				
			||||||
	int err;
 | 
						int err;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* key consists of keys of equal size concatenated, therefore
 | 
						err = xts_check_key(tfm, key, keylen);
 | 
				
			||||||
	 * the length must be even
 | 
						if (err)
 | 
				
			||||||
	 */
 | 
							return err;
 | 
				
			||||||
	if (keylen % 2) {
 | 
					 | 
				
			||||||
		*flags |= CRYPTO_TFM_RES_BAD_KEY_LEN;
 | 
					 | 
				
			||||||
		return -EINVAL;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* first half of xts-key is for crypt */
 | 
						/* first half of xts-key is for crypt */
 | 
				
			||||||
	err = __twofish_setkey(&ctx->crypt_ctx, key, keylen / 2, flags);
 | 
						err = __twofish_setkey(&ctx->crypt_ctx, key, keylen / 2, flags);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										11
									
								
								crypto/xts.c
									
									
									
									
									
								
							
							
						
						
									
										11
									
								
								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 priv *ctx = crypto_tfm_ctx(parent);
 | 
				
			||||||
	struct crypto_cipher *child = ctx->tweak;
 | 
						struct crypto_cipher *child = ctx->tweak;
 | 
				
			||||||
	u32 *flags = &parent->crt_flags;
 | 
					 | 
				
			||||||
	int err;
 | 
						int err;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* key consists of keys of equal size concatenated, therefore
 | 
						err = xts_check_key(parent, key, keylen);
 | 
				
			||||||
	 * the length must be even */
 | 
						if (err)
 | 
				
			||||||
	if (keylen % 2) {
 | 
							return err;
 | 
				
			||||||
		/* tell the user why there was an error */
 | 
					 | 
				
			||||||
		*flags |= CRYPTO_TFM_RES_BAD_KEY_LEN;
 | 
					 | 
				
			||||||
		return -EINVAL;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* we need two cipher instances: one to compute the initial 'tweak'
 | 
						/* we need two cipher instances: one to compute the initial 'tweak'
 | 
				
			||||||
	 * by encrypting the IV (usually the 'plain' iv) and the other
 | 
						 * by encrypting the IV (usually the 'plain' iv) and the other
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2,6 +2,9 @@
 | 
				
			||||||
#define _CRYPTO_XTS_H
 | 
					#define _CRYPTO_XTS_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <crypto/b128ops.h>
 | 
					#include <crypto/b128ops.h>
 | 
				
			||||||
 | 
					#include <linux/crypto.h>
 | 
				
			||||||
 | 
					#include <crypto/algapi.h>
 | 
				
			||||||
 | 
					#include <linux/fips.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct scatterlist;
 | 
					struct scatterlist;
 | 
				
			||||||
struct blkcipher_desc;
 | 
					struct blkcipher_desc;
 | 
				
			||||||
| 
						 | 
					@ -24,4 +27,28 @@ int xts_crypt(struct blkcipher_desc *desc, struct scatterlist *dst,
 | 
				
			||||||
	      struct scatterlist *src, unsigned int nbytes,
 | 
						      struct scatterlist *src, unsigned int nbytes,
 | 
				
			||||||
	      struct xts_crypt_req *req);
 | 
						      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 */
 | 
					#endif  /* _CRYPTO_XTS_H */
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue