/
0024-Add-xtsproxy-Crypto-API-module.patch
188 lines (184 loc) · 5.8 KB
/
0024-Add-xtsproxy-Crypto-API-module.patch
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
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
From 354d7a8febaa440dd3244466670315ed2805764e Mon Sep 17 00:00:00 2001
From: Ignat Korchagin <ignat@cloudflare.com>
Date: Wed, 4 Dec 2019 16:53:46 +0000
Subject: [PATCH] Add xtsproxy Crypto API module
This module implements a Crypto API AES-XTS synchronous driver, which uses
AES NI implementation as a backend and falls back to generic AES implementation,
when FPU is not usable.
---
crypto/Kconfig | 10 ++++
crypto/Makefile | 1 +
crypto/xtsproxy.c | 131 ++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 142 insertions(+)
create mode 100644 crypto/xtsproxy.c
diff --git a/crypto/Kconfig b/crypto/Kconfig
index 094ef56ab7b4..9964667cef85 100644
--- a/crypto/Kconfig
+++ b/crypto/Kconfig
@@ -457,6 +457,16 @@ config CRYPTO_XTS
key size 256, 384 or 512 bits. This implementation currently
can't handle a sectorsize which is not a multiple of 16 bytes.
+config CRYPTO_XTS_AES_SYNC
+ tristate "XTS AES synchronous implementation"
+ depends on X86 && 64BIT
+ select CRYPTO_AES
+ select CRYPTO_AES_NI_INTEL
+ help
+ A synchronous AES-XTS implementaion, which uses AES NI as a
+ backend implementation and falls back to generic implementation,
+ when FPU is not usable.
+
config CRYPTO_KEYWRAP
tristate "Key wrapping support"
select CRYPTO_SKCIPHER
diff --git a/crypto/Makefile b/crypto/Makefile
index b279483fba50..4f6ddcbdc6d4 100644
--- a/crypto/Makefile
+++ b/crypto/Makefile
@@ -90,6 +90,7 @@ obj-$(CONFIG_CRYPTO_PCBC) += pcbc.o
obj-$(CONFIG_CRYPTO_CTS) += cts.o
obj-$(CONFIG_CRYPTO_LRW) += lrw.o
obj-$(CONFIG_CRYPTO_XTS) += xts.o
+obj-$(CONFIG_CRYPTO_XTS_AES_SYNC) += xtsproxy.o
obj-$(CONFIG_CRYPTO_CTR) += ctr.o
obj-$(CONFIG_CRYPTO_KEYWRAP) += keywrap.o
obj-$(CONFIG_CRYPTO_ADIANTUM) += adiantum.o
diff --git a/crypto/xtsproxy.c b/crypto/xtsproxy.c
new file mode 100644
index 000000000000..51ecfb7b4891
--- /dev/null
+++ b/crypto/xtsproxy.c
@@ -0,0 +1,131 @@
+#include <linux/module.h>
+#include <linux/crypto.h>
+#include <linux/err.h>
+#include <crypto/internal/skcipher.h>
+#include <crypto/aes.h>
+#include <asm/fpu/api.h>
+
+struct xtsproxy_ctx {
+ struct crypto_skcipher *xts_aesni;
+ struct crypto_skcipher *xts_generic;
+};
+
+static int xtsproxy_skcipher_init(struct crypto_skcipher *tfm)
+{
+ struct xtsproxy_ctx *ctx = crypto_skcipher_ctx(tfm);
+
+ /* AESNI based XTS implementation, requires FPU to be available */
+ ctx->xts_aesni = crypto_alloc_skcipher("__xts-aes-aesni", CRYPTO_ALG_INTERNAL, 0);
+ if (IS_ERR(ctx->xts_aesni))
+ return PTR_ERR(ctx->xts_aesni);
+
+ /* generic XTS implementation based on generic FPU-less AES */
+ /* there is also aes-aesni implementation, which falls back to aes-generic */
+ /* but we're doing FPU checks in our code, so no need to repeat those */
+ /* as we will always fallback to aes-generic in this case */
+ ctx->xts_generic = crypto_alloc_skcipher("xts(ecb(aes-generic))", 0, 0);
+ if (IS_ERR(ctx->xts_generic))
+ return PTR_ERR(ctx->xts_generic);
+
+ /* make sure we allocate enough request memory for both implementations */
+ crypto_skcipher_set_reqsize(tfm, max(crypto_skcipher_reqsize(ctx->xts_aesni), crypto_skcipher_reqsize(ctx->xts_generic)));
+
+ return 0;
+}
+
+static void xtsproxy_skcipher_exit(struct crypto_skcipher *tfm)
+{
+ struct xtsproxy_ctx *ctx = crypto_skcipher_ctx(tfm);
+
+ if (!IS_ERR_OR_NULL(ctx->xts_generic)) {
+ crypto_free_skcipher(ctx->xts_generic);
+ ctx->xts_generic = NULL;
+ }
+
+ if (!IS_ERR_OR_NULL(ctx->xts_aesni)) {
+ crypto_free_skcipher(ctx->xts_aesni);
+ ctx->xts_aesni = NULL;
+ }
+}
+
+static int xtsproxy_setkey(struct crypto_skcipher *tfm, const u8 *key,
+ unsigned int keylen)
+{
+ struct xtsproxy_ctx *ctx = crypto_skcipher_ctx(tfm);
+ int err;
+
+ err = crypto_skcipher_setkey(ctx->xts_aesni, key, keylen);
+ if (err)
+ return err;
+
+ return crypto_skcipher_setkey(ctx->xts_generic, key, keylen);
+}
+
+static int xtsproxy_encrypt(struct skcipher_request *req)
+{
+ struct xtsproxy_ctx *ctx = crypto_skcipher_ctx(crypto_skcipher_reqtfm(req));
+
+ if (irq_fpu_usable())
+ skcipher_request_set_tfm(req, ctx->xts_aesni);
+ else
+ skcipher_request_set_tfm(req, ctx->xts_generic);
+
+ /* underlying implementations should not try to sleep */
+ req->base.flags &= ~(CRYPTO_TFM_REQ_MAY_SLEEP | CRYPTO_TFM_REQ_MAY_BACKLOG);
+
+ return crypto_skcipher_encrypt(req);
+}
+
+static int xtsproxy_decrypt(struct skcipher_request *req)
+{
+ struct xtsproxy_ctx *ctx = crypto_skcipher_ctx(crypto_skcipher_reqtfm(req));
+
+ if (irq_fpu_usable())
+ skcipher_request_set_tfm(req, ctx->xts_aesni);
+ else
+ skcipher_request_set_tfm(req, ctx->xts_generic);
+
+ /* underlying implementations should not try to sleep */
+ req->base.flags &= ~(CRYPTO_TFM_REQ_MAY_SLEEP | CRYPTO_TFM_REQ_MAY_BACKLOG);
+
+ return crypto_skcipher_decrypt(req);
+}
+
+static struct skcipher_alg xtsproxy_skcipher = {
+ .base = {
+ .cra_name = "xts(aes)",
+ .cra_driver_name = "xts-aes-xtsproxy",
+ /* make sure we don't use it unless requested explicitly */
+ .cra_priority = 0,
+ /* .cra_flags = CRYPTO_ALG_INTERNAL, */
+ .cra_blocksize = AES_BLOCK_SIZE,
+ .cra_ctxsize = sizeof(struct xtsproxy_ctx),
+ .cra_module = THIS_MODULE,
+ },
+ .min_keysize = 2 * AES_MIN_KEY_SIZE,
+ .max_keysize = 2 * AES_MAX_KEY_SIZE,
+ .ivsize = AES_BLOCK_SIZE,
+ .init = xtsproxy_skcipher_init,
+ .exit = xtsproxy_skcipher_exit,
+ .setkey = xtsproxy_setkey,
+ .encrypt = xtsproxy_encrypt,
+ .decrypt = xtsproxy_decrypt,
+};
+
+static int __init xtsproxy_init(void)
+{
+ return crypto_register_skcipher(&xtsproxy_skcipher);
+}
+
+static void __exit xtsproxy_fini(void)
+{
+ crypto_unregister_skcipher(&xtsproxy_skcipher);
+}
+
+module_init(xtsproxy_init);
+module_exit(xtsproxy_fini);
+
+MODULE_DESCRIPTION("XTS-AES using AESNI implementation with generic AES fallback");
+MODULE_AUTHOR("Ignat Korchagin <ignat@cloudflare.com>");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS_CRYPTO("xts(aes)");
--
2.29.1