mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02:00 
			
		
		
		
	crypto: keywrap - simplify code
The code is simplified by using two __be64 values for the operation instead of using two arrays of u8. This allows to get rid of the memory alignment code. In addition, the crypto_xor can be replaced with a native XOR operation. Finally, the definition of the variables is re-arranged such that the data structures come before simple variables to potentially reduce memory space. Signed-off-by: Stephan Mueller <smueller@chronox.de> Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
This commit is contained in:
		
							parent
							
								
									5b3f3a8bed
								
							
						
					
					
						commit
						9e49451d7a
					
				
					 1 changed files with 26 additions and 58 deletions
				
			
		| 
						 | 
				
			
			@ -93,18 +93,10 @@ struct crypto_kw_ctx {
 | 
			
		|||
 | 
			
		||||
struct crypto_kw_block {
 | 
			
		||||
#define SEMIBSIZE 8
 | 
			
		||||
	u8 A[SEMIBSIZE];
 | 
			
		||||
	u8 R[SEMIBSIZE];
 | 
			
		||||
	__be64 A;
 | 
			
		||||
	__be64 R;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* convert 64 bit integer into its string representation */
 | 
			
		||||
static inline void crypto_kw_cpu_to_be64(u64 val, u8 *buf)
 | 
			
		||||
{
 | 
			
		||||
	__be64 *a = (__be64 *)buf;
 | 
			
		||||
 | 
			
		||||
	*a = cpu_to_be64(val);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Fast forward the SGL to the "end" length minus SEMIBSIZE.
 | 
			
		||||
 * The start in the SGL defined by the fast-forward is returned with
 | 
			
		||||
| 
						 | 
				
			
			@ -139,17 +131,10 @@ static int crypto_kw_decrypt(struct blkcipher_desc *desc,
 | 
			
		|||
	struct crypto_blkcipher *tfm = desc->tfm;
 | 
			
		||||
	struct crypto_kw_ctx *ctx = crypto_blkcipher_ctx(tfm);
 | 
			
		||||
	struct crypto_cipher *child = ctx->child;
 | 
			
		||||
 | 
			
		||||
	unsigned long alignmask = max_t(unsigned long, SEMIBSIZE,
 | 
			
		||||
					crypto_cipher_alignmask(child));
 | 
			
		||||
	unsigned int i;
 | 
			
		||||
 | 
			
		||||
	u8 blockbuf[sizeof(struct crypto_kw_block) + alignmask];
 | 
			
		||||
	struct crypto_kw_block *block = (struct crypto_kw_block *)
 | 
			
		||||
					PTR_ALIGN(blockbuf + 0, alignmask + 1);
 | 
			
		||||
 | 
			
		||||
	u64 t = 6 * ((nbytes) >> 3);
 | 
			
		||||
	struct crypto_kw_block block;
 | 
			
		||||
	struct scatterlist *lsrc, *ldst;
 | 
			
		||||
	u64 t = 6 * ((nbytes) >> 3);
 | 
			
		||||
	unsigned int i;
 | 
			
		||||
	int ret = 0;
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
| 
						 | 
				
			
			@ -160,7 +145,7 @@ static int crypto_kw_decrypt(struct blkcipher_desc *desc,
 | 
			
		|||
		return -EINVAL;
 | 
			
		||||
 | 
			
		||||
	/* Place the IV into block A */
 | 
			
		||||
	memcpy(block->A, desc->info, SEMIBSIZE);
 | 
			
		||||
	memcpy(&block.A, desc->info, SEMIBSIZE);
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * src scatterlist is read-only. dst scatterlist is r/w. During the
 | 
			
		||||
| 
						 | 
				
			
			@ -171,32 +156,27 @@ static int crypto_kw_decrypt(struct blkcipher_desc *desc,
 | 
			
		|||
	ldst = dst;
 | 
			
		||||
 | 
			
		||||
	for (i = 0; i < 6; i++) {
 | 
			
		||||
		u8 tbe_buffer[SEMIBSIZE + alignmask];
 | 
			
		||||
		/* alignment for the crypto_xor and the _to_be64 operation */
 | 
			
		||||
		u8 *tbe = PTR_ALIGN(tbe_buffer + 0, alignmask + 1);
 | 
			
		||||
		unsigned int tmp_nbytes = nbytes;
 | 
			
		||||
		struct scatter_walk src_walk, dst_walk;
 | 
			
		||||
		unsigned int tmp_nbytes = nbytes;
 | 
			
		||||
 | 
			
		||||
		while (tmp_nbytes) {
 | 
			
		||||
			/* move pointer by tmp_nbytes in the SGL */
 | 
			
		||||
			crypto_kw_scatterlist_ff(&src_walk, lsrc, tmp_nbytes);
 | 
			
		||||
			/* get the source block */
 | 
			
		||||
			scatterwalk_copychunks(block->R, &src_walk, SEMIBSIZE,
 | 
			
		||||
			scatterwalk_copychunks(&block.R, &src_walk, SEMIBSIZE,
 | 
			
		||||
					       false);
 | 
			
		||||
 | 
			
		||||
			/* perform KW operation: get counter as byte string */
 | 
			
		||||
			crypto_kw_cpu_to_be64(t, tbe);
 | 
			
		||||
			/* perform KW operation: modify IV with counter */
 | 
			
		||||
			crypto_xor(block->A, tbe, SEMIBSIZE);
 | 
			
		||||
			block.A ^= cpu_to_be64(t);
 | 
			
		||||
			t--;
 | 
			
		||||
			/* perform KW operation: decrypt block */
 | 
			
		||||
			crypto_cipher_decrypt_one(child, (u8*)block,
 | 
			
		||||
						  (u8*)block);
 | 
			
		||||
			crypto_cipher_decrypt_one(child, (u8*)&block,
 | 
			
		||||
						  (u8*)&block);
 | 
			
		||||
 | 
			
		||||
			/* move pointer by tmp_nbytes in the SGL */
 | 
			
		||||
			crypto_kw_scatterlist_ff(&dst_walk, ldst, tmp_nbytes);
 | 
			
		||||
			/* Copy block->R into place */
 | 
			
		||||
			scatterwalk_copychunks(block->R, &dst_walk, SEMIBSIZE,
 | 
			
		||||
			scatterwalk_copychunks(&block.R, &dst_walk, SEMIBSIZE,
 | 
			
		||||
					       true);
 | 
			
		||||
 | 
			
		||||
			tmp_nbytes -= SEMIBSIZE;
 | 
			
		||||
| 
						 | 
				
			
			@ -208,11 +188,10 @@ static int crypto_kw_decrypt(struct blkcipher_desc *desc,
 | 
			
		|||
	}
 | 
			
		||||
 | 
			
		||||
	/* Perform authentication check */
 | 
			
		||||
	if (crypto_memneq("\xA6\xA6\xA6\xA6\xA6\xA6\xA6\xA6", block->A,
 | 
			
		||||
			  SEMIBSIZE))
 | 
			
		||||
	if (block.A != cpu_to_be64(0xa6a6a6a6a6a6a6a6))
 | 
			
		||||
		ret = -EBADMSG;
 | 
			
		||||
 | 
			
		||||
	memzero_explicit(block, sizeof(struct crypto_kw_block));
 | 
			
		||||
	memzero_explicit(&block, sizeof(struct crypto_kw_block));
 | 
			
		||||
 | 
			
		||||
	return ret;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -224,17 +203,10 @@ static int crypto_kw_encrypt(struct blkcipher_desc *desc,
 | 
			
		|||
	struct crypto_blkcipher *tfm = desc->tfm;
 | 
			
		||||
	struct crypto_kw_ctx *ctx = crypto_blkcipher_ctx(tfm);
 | 
			
		||||
	struct crypto_cipher *child = ctx->child;
 | 
			
		||||
 | 
			
		||||
	unsigned long alignmask = max_t(unsigned long, SEMIBSIZE,
 | 
			
		||||
					crypto_cipher_alignmask(child));
 | 
			
		||||
	unsigned int i;
 | 
			
		||||
 | 
			
		||||
	u8 blockbuf[sizeof(struct crypto_kw_block) + alignmask];
 | 
			
		||||
	struct crypto_kw_block *block = (struct crypto_kw_block *)
 | 
			
		||||
					PTR_ALIGN(blockbuf + 0, alignmask + 1);
 | 
			
		||||
 | 
			
		||||
	u64 t = 1;
 | 
			
		||||
	struct crypto_kw_block block;
 | 
			
		||||
	struct scatterlist *lsrc, *ldst;
 | 
			
		||||
	u64 t = 1;
 | 
			
		||||
	unsigned int i;
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * Require at least 2 semiblocks (note, the 3rd semiblock that is
 | 
			
		||||
| 
						 | 
				
			
			@ -249,7 +221,7 @@ static int crypto_kw_encrypt(struct blkcipher_desc *desc,
 | 
			
		|||
	 * Place the predefined IV into block A -- for encrypt, the caller
 | 
			
		||||
	 * does not need to provide an IV, but he needs to fetch the final IV.
 | 
			
		||||
	 */
 | 
			
		||||
	memcpy(block->A, "\xA6\xA6\xA6\xA6\xA6\xA6\xA6\xA6", SEMIBSIZE);
 | 
			
		||||
	block.A = cpu_to_be64(0xa6a6a6a6a6a6a6a6);
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * src scatterlist is read-only. dst scatterlist is r/w. During the
 | 
			
		||||
| 
						 | 
				
			
			@ -260,30 +232,26 @@ static int crypto_kw_encrypt(struct blkcipher_desc *desc,
 | 
			
		|||
	ldst = dst;
 | 
			
		||||
 | 
			
		||||
	for (i = 0; i < 6; i++) {
 | 
			
		||||
		u8 tbe_buffer[SEMIBSIZE + alignmask];
 | 
			
		||||
		u8 *tbe = PTR_ALIGN(tbe_buffer + 0, alignmask + 1);
 | 
			
		||||
		unsigned int tmp_nbytes = nbytes;
 | 
			
		||||
		struct scatter_walk src_walk, dst_walk;
 | 
			
		||||
		unsigned int tmp_nbytes = nbytes;
 | 
			
		||||
 | 
			
		||||
		scatterwalk_start(&src_walk, lsrc);
 | 
			
		||||
		scatterwalk_start(&dst_walk, ldst);
 | 
			
		||||
 | 
			
		||||
		while (tmp_nbytes) {
 | 
			
		||||
			/* get the source block */
 | 
			
		||||
			scatterwalk_copychunks(block->R, &src_walk, SEMIBSIZE,
 | 
			
		||||
			scatterwalk_copychunks(&block.R, &src_walk, SEMIBSIZE,
 | 
			
		||||
					       false);
 | 
			
		||||
 | 
			
		||||
			/* perform KW operation: encrypt block */
 | 
			
		||||
			crypto_cipher_encrypt_one(child, (u8 *)block,
 | 
			
		||||
						  (u8 *)block);
 | 
			
		||||
			/* perform KW operation: get counter as byte string */
 | 
			
		||||
			crypto_kw_cpu_to_be64(t, tbe);
 | 
			
		||||
			crypto_cipher_encrypt_one(child, (u8 *)&block,
 | 
			
		||||
						  (u8 *)&block);
 | 
			
		||||
			/* perform KW operation: modify IV with counter */
 | 
			
		||||
			crypto_xor(block->A, tbe, SEMIBSIZE);
 | 
			
		||||
			block.A ^= cpu_to_be64(t);
 | 
			
		||||
			t++;
 | 
			
		||||
 | 
			
		||||
			/* Copy block->R into place */
 | 
			
		||||
			scatterwalk_copychunks(block->R, &dst_walk, SEMIBSIZE,
 | 
			
		||||
			scatterwalk_copychunks(&block.R, &dst_walk, SEMIBSIZE,
 | 
			
		||||
					       true);
 | 
			
		||||
 | 
			
		||||
			tmp_nbytes -= SEMIBSIZE;
 | 
			
		||||
| 
						 | 
				
			
			@ -295,9 +263,9 @@ static int crypto_kw_encrypt(struct blkcipher_desc *desc,
 | 
			
		|||
	}
 | 
			
		||||
 | 
			
		||||
	/* establish the IV for the caller to pick up */
 | 
			
		||||
	memcpy(desc->info, block->A, SEMIBSIZE);
 | 
			
		||||
	memcpy(desc->info, &block.A, SEMIBSIZE);
 | 
			
		||||
 | 
			
		||||
	memzero_explicit(block, sizeof(struct crypto_kw_block));
 | 
			
		||||
	memzero_explicit(&block, sizeof(struct crypto_kw_block));
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue