xref: /openbmc/linux/drivers/crypto/vmx/aes_xts.c (revision 8be98d2f2a0a262f8bf8a0bc1fdf522b3c7aab17)
127ba4debSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
2*dbb153c0SAditya Srivastava /*
3c07f5d3dSLeonidas S. Barbosa  * AES XTS routines supporting VMX In-core instructions on Power 8
4c07f5d3dSLeonidas S. Barbosa  *
5c07f5d3dSLeonidas S. Barbosa  * Copyright (C) 2015 International Business Machines Inc.
6c07f5d3dSLeonidas S. Barbosa  *
7c07f5d3dSLeonidas S. Barbosa  * Author: Leonidas S. Barbosa <leosilva@linux.vnet.ibm.com>
8c07f5d3dSLeonidas S. Barbosa  */
9c07f5d3dSLeonidas S. Barbosa 
10626ddb2fSEric Biggers #include <asm/simd.h>
11c07f5d3dSLeonidas S. Barbosa #include <asm/switch_to.h>
12c07f5d3dSLeonidas S. Barbosa #include <crypto/aes.h>
13626ddb2fSEric Biggers #include <crypto/internal/simd.h>
142621a869SEric Biggers #include <crypto/internal/skcipher.h>
15c07f5d3dSLeonidas S. Barbosa #include <crypto/xts.h>
16c07f5d3dSLeonidas S. Barbosa 
17c07f5d3dSLeonidas S. Barbosa #include "aesp8-ppc.h"
18c07f5d3dSLeonidas S. Barbosa 
19c07f5d3dSLeonidas S. Barbosa struct p8_aes_xts_ctx {
202621a869SEric Biggers 	struct crypto_skcipher *fallback;
21c07f5d3dSLeonidas S. Barbosa 	struct aes_key enc_key;
22c07f5d3dSLeonidas S. Barbosa 	struct aes_key dec_key;
23c07f5d3dSLeonidas S. Barbosa 	struct aes_key tweak_key;
24c07f5d3dSLeonidas S. Barbosa };
25c07f5d3dSLeonidas S. Barbosa 
p8_aes_xts_init(struct crypto_skcipher * tfm)262621a869SEric Biggers static int p8_aes_xts_init(struct crypto_skcipher *tfm)
27c07f5d3dSLeonidas S. Barbosa {
282621a869SEric Biggers 	struct p8_aes_xts_ctx *ctx = crypto_skcipher_ctx(tfm);
292621a869SEric Biggers 	struct crypto_skcipher *fallback;
30c07f5d3dSLeonidas S. Barbosa 
312621a869SEric Biggers 	fallback = crypto_alloc_skcipher("xts(aes)", 0,
322621a869SEric Biggers 					 CRYPTO_ALG_NEED_FALLBACK |
332621a869SEric Biggers 					 CRYPTO_ALG_ASYNC);
34c07f5d3dSLeonidas S. Barbosa 	if (IS_ERR(fallback)) {
352621a869SEric Biggers 		pr_err("Failed to allocate xts(aes) fallback: %ld\n",
362621a869SEric Biggers 		       PTR_ERR(fallback));
37c07f5d3dSLeonidas S. Barbosa 		return PTR_ERR(fallback);
38c07f5d3dSLeonidas S. Barbosa 	}
39c07f5d3dSLeonidas S. Barbosa 
402621a869SEric Biggers 	crypto_skcipher_set_reqsize(tfm, sizeof(struct skcipher_request) +
412621a869SEric Biggers 				    crypto_skcipher_reqsize(fallback));
42c07f5d3dSLeonidas S. Barbosa 	ctx->fallback = fallback;
43c07f5d3dSLeonidas S. Barbosa 	return 0;
44c07f5d3dSLeonidas S. Barbosa }
45c07f5d3dSLeonidas S. Barbosa 
p8_aes_xts_exit(struct crypto_skcipher * tfm)462621a869SEric Biggers static void p8_aes_xts_exit(struct crypto_skcipher *tfm)
47c07f5d3dSLeonidas S. Barbosa {
482621a869SEric Biggers 	struct p8_aes_xts_ctx *ctx = crypto_skcipher_ctx(tfm);
49c07f5d3dSLeonidas S. Barbosa 
502621a869SEric Biggers 	crypto_free_skcipher(ctx->fallback);
51c07f5d3dSLeonidas S. Barbosa }
52c07f5d3dSLeonidas S. Barbosa 
p8_aes_xts_setkey(struct crypto_skcipher * tfm,const u8 * key,unsigned int keylen)532621a869SEric Biggers static int p8_aes_xts_setkey(struct crypto_skcipher *tfm, const u8 *key,
54c07f5d3dSLeonidas S. Barbosa 			     unsigned int keylen)
55c07f5d3dSLeonidas S. Barbosa {
562621a869SEric Biggers 	struct p8_aes_xts_ctx *ctx = crypto_skcipher_ctx(tfm);
57c07f5d3dSLeonidas S. Barbosa 	int ret;
58c07f5d3dSLeonidas S. Barbosa 
592621a869SEric Biggers 	ret = xts_verify_key(tfm, key, keylen);
60c07f5d3dSLeonidas S. Barbosa 	if (ret)
61c07f5d3dSLeonidas S. Barbosa 		return ret;
62c07f5d3dSLeonidas S. Barbosa 
63c07f5d3dSLeonidas S. Barbosa 	preempt_disable();
64c07f5d3dSLeonidas S. Barbosa 	pagefault_disable();
65c07f5d3dSLeonidas S. Barbosa 	enable_kernel_vsx();
66c07f5d3dSLeonidas S. Barbosa 	ret = aes_p8_set_encrypt_key(key + keylen/2, (keylen/2) * 8, &ctx->tweak_key);
67694e0db6SEric Biggers 	ret |= aes_p8_set_encrypt_key(key, (keylen/2) * 8, &ctx->enc_key);
68694e0db6SEric Biggers 	ret |= aes_p8_set_decrypt_key(key, (keylen/2) * 8, &ctx->dec_key);
69c07f5d3dSLeonidas S. Barbosa 	disable_kernel_vsx();
70c07f5d3dSLeonidas S. Barbosa 	pagefault_enable();
71c07f5d3dSLeonidas S. Barbosa 	preempt_enable();
72c07f5d3dSLeonidas S. Barbosa 
732621a869SEric Biggers 	ret |= crypto_skcipher_setkey(ctx->fallback, key, keylen);
74694e0db6SEric Biggers 
75694e0db6SEric Biggers 	return ret ? -EINVAL : 0;
76c07f5d3dSLeonidas S. Barbosa }
77c07f5d3dSLeonidas S. Barbosa 
p8_aes_xts_crypt(struct skcipher_request * req,int enc)782621a869SEric Biggers static int p8_aes_xts_crypt(struct skcipher_request *req, int enc)
79c07f5d3dSLeonidas S. Barbosa {
802621a869SEric Biggers 	struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
812621a869SEric Biggers 	const struct p8_aes_xts_ctx *ctx = crypto_skcipher_ctx(tfm);
822621a869SEric Biggers 	struct skcipher_walk walk;
832621a869SEric Biggers 	unsigned int nbytes;
84c07f5d3dSLeonidas S. Barbosa 	u8 tweak[AES_BLOCK_SIZE];
852621a869SEric Biggers 	int ret;
86c07f5d3dSLeonidas S. Barbosa 
871372a51bSDaniel Axtens 	if (req->cryptlen < AES_BLOCK_SIZE)
881372a51bSDaniel Axtens 		return -EINVAL;
891372a51bSDaniel Axtens 
9023966841SArd Biesheuvel 	if (!crypto_simd_usable() || (req->cryptlen % XTS_BLOCK_SIZE) != 0) {
912621a869SEric Biggers 		struct skcipher_request *subreq = skcipher_request_ctx(req);
920522236dSOndrej Mosnacek 
932621a869SEric Biggers 		*subreq = *req;
942621a869SEric Biggers 		skcipher_request_set_tfm(subreq, ctx->fallback);
952621a869SEric Biggers 		return enc ? crypto_skcipher_encrypt(subreq) :
962621a869SEric Biggers 			     crypto_skcipher_decrypt(subreq);
972621a869SEric Biggers 	}
982621a869SEric Biggers 
992621a869SEric Biggers 	ret = skcipher_walk_virt(&walk, req, false);
1002621a869SEric Biggers 	if (ret)
1012621a869SEric Biggers 		return ret;
1020522236dSOndrej Mosnacek 
103c07f5d3dSLeonidas S. Barbosa 	preempt_disable();
104c07f5d3dSLeonidas S. Barbosa 	pagefault_disable();
105c07f5d3dSLeonidas S. Barbosa 	enable_kernel_vsx();
106c07f5d3dSLeonidas S. Barbosa 
1072621a869SEric Biggers 	aes_p8_encrypt(walk.iv, tweak, &ctx->tweak_key);
108c07f5d3dSLeonidas S. Barbosa 
1090522236dSOndrej Mosnacek 	disable_kernel_vsx();
1100522236dSOndrej Mosnacek 	pagefault_enable();
1110522236dSOndrej Mosnacek 	preempt_enable();
1120522236dSOndrej Mosnacek 
1132621a869SEric Biggers 	while ((nbytes = walk.nbytes) != 0) {
1140522236dSOndrej Mosnacek 		preempt_disable();
1150522236dSOndrej Mosnacek 		pagefault_disable();
1160522236dSOndrej Mosnacek 		enable_kernel_vsx();
117c07f5d3dSLeonidas S. Barbosa 		if (enc)
1182621a869SEric Biggers 			aes_p8_xts_encrypt(walk.src.virt.addr,
1192621a869SEric Biggers 					   walk.dst.virt.addr,
1202621a869SEric Biggers 					   round_down(nbytes, AES_BLOCK_SIZE),
1212621a869SEric Biggers 					   &ctx->enc_key, NULL, tweak);
122c07f5d3dSLeonidas S. Barbosa 		else
1232621a869SEric Biggers 			aes_p8_xts_decrypt(walk.src.virt.addr,
1242621a869SEric Biggers 					   walk.dst.virt.addr,
1252621a869SEric Biggers 					   round_down(nbytes, AES_BLOCK_SIZE),
1262621a869SEric Biggers 					   &ctx->dec_key, NULL, tweak);
1270522236dSOndrej Mosnacek 		disable_kernel_vsx();
1280522236dSOndrej Mosnacek 		pagefault_enable();
1290522236dSOndrej Mosnacek 		preempt_enable();
130c07f5d3dSLeonidas S. Barbosa 
1312621a869SEric Biggers 		ret = skcipher_walk_done(&walk, nbytes % AES_BLOCK_SIZE);
132c07f5d3dSLeonidas S. Barbosa 	}
133c07f5d3dSLeonidas S. Barbosa 	return ret;
134c07f5d3dSLeonidas S. Barbosa }
135c07f5d3dSLeonidas S. Barbosa 
p8_aes_xts_encrypt(struct skcipher_request * req)1362621a869SEric Biggers static int p8_aes_xts_encrypt(struct skcipher_request *req)
137c07f5d3dSLeonidas S. Barbosa {
1382621a869SEric Biggers 	return p8_aes_xts_crypt(req, 1);
139c07f5d3dSLeonidas S. Barbosa }
140c07f5d3dSLeonidas S. Barbosa 
p8_aes_xts_decrypt(struct skcipher_request * req)1412621a869SEric Biggers static int p8_aes_xts_decrypt(struct skcipher_request *req)
142c07f5d3dSLeonidas S. Barbosa {
1432621a869SEric Biggers 	return p8_aes_xts_crypt(req, 0);
144c07f5d3dSLeonidas S. Barbosa }
145c07f5d3dSLeonidas S. Barbosa 
1462621a869SEric Biggers struct skcipher_alg p8_aes_xts_alg = {
1472621a869SEric Biggers 	.base.cra_name = "xts(aes)",
1482621a869SEric Biggers 	.base.cra_driver_name = "p8_aes_xts",
1492621a869SEric Biggers 	.base.cra_module = THIS_MODULE,
1502621a869SEric Biggers 	.base.cra_priority = 2000,
1512621a869SEric Biggers 	.base.cra_flags = CRYPTO_ALG_NEED_FALLBACK,
1522621a869SEric Biggers 	.base.cra_blocksize = AES_BLOCK_SIZE,
1532621a869SEric Biggers 	.base.cra_ctxsize = sizeof(struct p8_aes_xts_ctx),
154c07f5d3dSLeonidas S. Barbosa 	.setkey = p8_aes_xts_setkey,
155c07f5d3dSLeonidas S. Barbosa 	.encrypt = p8_aes_xts_encrypt,
156c07f5d3dSLeonidas S. Barbosa 	.decrypt = p8_aes_xts_decrypt,
1572621a869SEric Biggers 	.init = p8_aes_xts_init,
1582621a869SEric Biggers 	.exit = p8_aes_xts_exit,
1592621a869SEric Biggers 	.min_keysize = 2 * AES_MIN_KEY_SIZE,
1602621a869SEric Biggers 	.max_keysize = 2 * AES_MAX_KEY_SIZE,
1612621a869SEric Biggers 	.ivsize = AES_BLOCK_SIZE,
162c07f5d3dSLeonidas S. Barbosa };
163