Commit 65d0042b authored by Ard Biesheuvel's avatar Ard Biesheuvel Committed by Herbert Xu
Browse files

crypto: arm64/aes-cts-cbc - factor out CBC en/decryption of a walk



The plain CBC driver and the CTS one share some code that iterates over
a scatterwalk and invokes the CBC asm code to do the processing. The
upcoming ESSIV/CBC mode will clone that pattern for the third time, so
let's factor it out first.

Signed-off-by: default avatarArd Biesheuvel <ard.biesheuvel@linaro.org>
Signed-off-by: default avatarHerbert Xu <herbert@gondor.apana.org.au>
parent f975abb2
Loading
Loading
Loading
Loading
+40 −42
Original line number Diff line number Diff line
@@ -186,44 +186,62 @@ static int ecb_decrypt(struct skcipher_request *req)
	return err;
}

static int cbc_encrypt(struct skcipher_request *req)
static int cbc_encrypt_walk(struct skcipher_request *req,
			    struct skcipher_walk *walk)
{
	struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
	struct crypto_aes_ctx *ctx = crypto_skcipher_ctx(tfm);
	int err, rounds = 6 + ctx->key_length / 4;
	struct skcipher_walk walk;
	int err = 0, rounds = 6 + ctx->key_length / 4;
	unsigned int blocks;

	err = skcipher_walk_virt(&walk, req, false);

	while ((blocks = (walk.nbytes / AES_BLOCK_SIZE))) {
	while ((blocks = (walk->nbytes / AES_BLOCK_SIZE))) {
		kernel_neon_begin();
		aes_cbc_encrypt(walk.dst.virt.addr, walk.src.virt.addr,
				ctx->key_enc, rounds, blocks, walk.iv);
		aes_cbc_encrypt(walk->dst.virt.addr, walk->src.virt.addr,
				ctx->key_enc, rounds, blocks, walk->iv);
		kernel_neon_end();
		err = skcipher_walk_done(&walk, walk.nbytes % AES_BLOCK_SIZE);
		err = skcipher_walk_done(walk, walk->nbytes % AES_BLOCK_SIZE);
	}
	return err;
}

static int cbc_decrypt(struct skcipher_request *req)
static int cbc_encrypt(struct skcipher_request *req)
{
	struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
	struct crypto_aes_ctx *ctx = crypto_skcipher_ctx(tfm);
	int err, rounds = 6 + ctx->key_length / 4;
	struct skcipher_walk walk;
	unsigned int blocks;
	int err;

	err = skcipher_walk_virt(&walk, req, false);
	if (err)
		return err;
	return cbc_encrypt_walk(req, &walk);
}

	while ((blocks = (walk.nbytes / AES_BLOCK_SIZE))) {
static int cbc_decrypt_walk(struct skcipher_request *req,
			    struct skcipher_walk *walk)
{
	struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
	struct crypto_aes_ctx *ctx = crypto_skcipher_ctx(tfm);
	int err = 0, rounds = 6 + ctx->key_length / 4;
	unsigned int blocks;

	while ((blocks = (walk->nbytes / AES_BLOCK_SIZE))) {
		kernel_neon_begin();
		aes_cbc_decrypt(walk.dst.virt.addr, walk.src.virt.addr,
				ctx->key_dec, rounds, blocks, walk.iv);
		aes_cbc_decrypt(walk->dst.virt.addr, walk->src.virt.addr,
				ctx->key_dec, rounds, blocks, walk->iv);
		kernel_neon_end();
		err = skcipher_walk_done(&walk, walk.nbytes % AES_BLOCK_SIZE);
		err = skcipher_walk_done(walk, walk->nbytes % AES_BLOCK_SIZE);
	}
	return err;
}

static int cbc_decrypt(struct skcipher_request *req)
{
	struct skcipher_walk walk;
	int err;

	err = skcipher_walk_virt(&walk, req, false);
	if (err)
		return err;
	return cbc_decrypt_walk(req, &walk);
}

static int cts_cbc_init_tfm(struct crypto_skcipher *tfm)
@@ -251,22 +269,12 @@ static int cts_cbc_encrypt(struct skcipher_request *req)
	}

	if (cbc_blocks > 0) {
		unsigned int blocks;

		skcipher_request_set_crypt(&rctx->subreq, req->src, req->dst,
					   cbc_blocks * AES_BLOCK_SIZE,
					   req->iv);

		err = skcipher_walk_virt(&walk, &rctx->subreq, false);

		while ((blocks = (walk.nbytes / AES_BLOCK_SIZE))) {
			kernel_neon_begin();
			aes_cbc_encrypt(walk.dst.virt.addr, walk.src.virt.addr,
					ctx->key_enc, rounds, blocks, walk.iv);
			kernel_neon_end();
			err = skcipher_walk_done(&walk,
						 walk.nbytes % AES_BLOCK_SIZE);
		}
		err = skcipher_walk_virt(&walk, &rctx->subreq, false) ?:
		      cbc_encrypt_walk(&rctx->subreq, &walk);
		if (err)
			return err;

@@ -316,22 +324,12 @@ static int cts_cbc_decrypt(struct skcipher_request *req)
	}

	if (cbc_blocks > 0) {
		unsigned int blocks;

		skcipher_request_set_crypt(&rctx->subreq, req->src, req->dst,
					   cbc_blocks * AES_BLOCK_SIZE,
					   req->iv);

		err = skcipher_walk_virt(&walk, &rctx->subreq, false);

		while ((blocks = (walk.nbytes / AES_BLOCK_SIZE))) {
			kernel_neon_begin();
			aes_cbc_decrypt(walk.dst.virt.addr, walk.src.virt.addr,
					ctx->key_dec, rounds, blocks, walk.iv);
			kernel_neon_end();
			err = skcipher_walk_done(&walk,
						 walk.nbytes % AES_BLOCK_SIZE);
		}
		err = skcipher_walk_virt(&walk, &rctx->subreq, false) ?:
		      cbc_decrypt_walk(&rctx->subreq, &walk);
		if (err)
			return err;