diff options
author | Tero Kristo <t-kristo@ti.com> | 2017-05-24 03:35:31 -0400 |
---|---|---|
committer | Herbert Xu <herbert@gondor.apana.org.au> | 2017-06-10 00:04:19 -0400 |
commit | ad18cc9d0f911928704cdc37f4d126853daa9e4e (patch) | |
tree | 1a16791b6ee2b5fdbe468743c529869c81bb15bc | |
parent | d695bfd6f02adf362511a6d0139e7f7e6342d3e8 (diff) |
crypto: omap-aes - Add support for GCM mode
OMAP AES hw supports AES-GCM mode. This patch adds support for GCM and
RFC4106 GCM mode in omap-aes driver. The GCM implementation is mostly
written into its own source file, which gets built into the same driver
binary as the existing AES support.
Signed-off-by: Lokesh Vutla <lokeshvutla@ti.com>
[t-kristo@ti.com: forward port to latest upstream kernel, conversion to use
omap-crypto lib and some additional fixes]
Signed-off-by: Tero Kristo <t-kristo@ti.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
-rw-r--r-- | drivers/crypto/Kconfig | 1 | ||||
-rw-r--r-- | drivers/crypto/Makefile | 3 | ||||
-rw-r--r-- | drivers/crypto/omap-aes-gcm.c | 408 | ||||
-rw-r--r-- | drivers/crypto/omap-aes.c | 159 | ||||
-rw-r--r-- | drivers/crypto/omap-aes.h | 54 |
5 files changed, 612 insertions, 13 deletions
diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig index 64171cad735d..4e6591b0b128 100644 --- a/drivers/crypto/Kconfig +++ b/drivers/crypto/Kconfig | |||
@@ -344,6 +344,7 @@ config CRYPTO_DEV_OMAP_AES | |||
344 | select CRYPTO_CBC | 344 | select CRYPTO_CBC |
345 | select CRYPTO_ECB | 345 | select CRYPTO_ECB |
346 | select CRYPTO_CTR | 346 | select CRYPTO_CTR |
347 | select CRYPTO_AEAD | ||
347 | help | 348 | help |
348 | OMAP processors have AES module accelerator. Select this if you | 349 | OMAP processors have AES module accelerator. Select this if you |
349 | want to use the OMAP module for AES algorithms. | 350 | want to use the OMAP module for AES algorithms. |
diff --git a/drivers/crypto/Makefile b/drivers/crypto/Makefile index 8fd11510f6b9..8177388f5c85 100644 --- a/drivers/crypto/Makefile +++ b/drivers/crypto/Makefile | |||
@@ -21,7 +21,8 @@ obj-$(CONFIG_CRYPTO_DEV_NIAGARA2) += n2_crypto.o | |||
21 | n2_crypto-y := n2_core.o n2_asm.o | 21 | n2_crypto-y := n2_core.o n2_asm.o |
22 | obj-$(CONFIG_CRYPTO_DEV_NX) += nx/ | 22 | obj-$(CONFIG_CRYPTO_DEV_NX) += nx/ |
23 | obj-$(CONFIG_CRYPTO_DEV_OMAP) += omap-crypto.o | 23 | obj-$(CONFIG_CRYPTO_DEV_OMAP) += omap-crypto.o |
24 | obj-$(CONFIG_CRYPTO_DEV_OMAP_AES) += omap-aes.o | 24 | obj-$(CONFIG_CRYPTO_DEV_OMAP_AES) += omap-aes-driver.o |
25 | omap-aes-driver-objs := omap-aes.o omap-aes-gcm.o | ||
25 | obj-$(CONFIG_CRYPTO_DEV_OMAP_DES) += omap-des.o | 26 | obj-$(CONFIG_CRYPTO_DEV_OMAP_DES) += omap-des.o |
26 | obj-$(CONFIG_CRYPTO_DEV_OMAP_SHAM) += omap-sham.o | 27 | obj-$(CONFIG_CRYPTO_DEV_OMAP_SHAM) += omap-sham.o |
27 | obj-$(CONFIG_CRYPTO_DEV_PADLOCK_AES) += padlock-aes.o | 28 | obj-$(CONFIG_CRYPTO_DEV_PADLOCK_AES) += padlock-aes.o |
diff --git a/drivers/crypto/omap-aes-gcm.c b/drivers/crypto/omap-aes-gcm.c new file mode 100644 index 000000000000..521a310ea699 --- /dev/null +++ b/drivers/crypto/omap-aes-gcm.c | |||
@@ -0,0 +1,408 @@ | |||
1 | /* | ||
2 | * Cryptographic API. | ||
3 | * | ||
4 | * Support for OMAP AES GCM HW acceleration. | ||
5 | * | ||
6 | * Copyright (c) 2016 Texas Instruments Incorporated | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as published | ||
10 | * by the Free Software Foundation. | ||
11 | * | ||
12 | */ | ||
13 | |||
14 | #include <linux/errno.h> | ||
15 | #include <linux/scatterlist.h> | ||
16 | #include <linux/dma-mapping.h> | ||
17 | #include <linux/dmaengine.h> | ||
18 | #include <linux/omap-dma.h> | ||
19 | #include <linux/interrupt.h> | ||
20 | #include <crypto/aes.h> | ||
21 | #include <crypto/scatterwalk.h> | ||
22 | #include <crypto/skcipher.h> | ||
23 | #include <crypto/internal/aead.h> | ||
24 | |||
25 | #include "omap-crypto.h" | ||
26 | #include "omap-aes.h" | ||
27 | |||
28 | static int omap_aes_gcm_handle_queue(struct omap_aes_dev *dd, | ||
29 | struct aead_request *req); | ||
30 | |||
31 | static void omap_aes_gcm_finish_req(struct omap_aes_dev *dd, int ret) | ||
32 | { | ||
33 | struct aead_request *req = dd->aead_req; | ||
34 | |||
35 | dd->flags &= ~FLAGS_BUSY; | ||
36 | dd->in_sg = NULL; | ||
37 | dd->out_sg = NULL; | ||
38 | |||
39 | req->base.complete(&req->base, ret); | ||
40 | } | ||
41 | |||
42 | static void omap_aes_gcm_done_task(struct omap_aes_dev *dd) | ||
43 | { | ||
44 | u8 *tag; | ||
45 | int alen, clen, i, ret = 0, nsg; | ||
46 | struct omap_aes_reqctx *rctx; | ||
47 | |||
48 | alen = ALIGN(dd->assoc_len, AES_BLOCK_SIZE); | ||
49 | clen = ALIGN(dd->total, AES_BLOCK_SIZE); | ||
50 | rctx = aead_request_ctx(dd->aead_req); | ||
51 | |||
52 | nsg = !!(dd->assoc_len && dd->total); | ||
53 | |||
54 | dma_sync_sg_for_device(dd->dev, dd->out_sg, dd->out_sg_len, | ||
55 | DMA_FROM_DEVICE); | ||
56 | dma_unmap_sg(dd->dev, dd->in_sg, dd->in_sg_len, DMA_TO_DEVICE); | ||
57 | dma_unmap_sg(dd->dev, dd->out_sg, dd->out_sg_len, DMA_FROM_DEVICE); | ||
58 | omap_aes_crypt_dma_stop(dd); | ||
59 | |||
60 | omap_crypto_cleanup(dd->out_sg, dd->orig_out, | ||
61 | dd->aead_req->assoclen, dd->total, | ||
62 | FLAGS_OUT_DATA_ST_SHIFT, dd->flags); | ||
63 | |||
64 | if (dd->flags & FLAGS_ENCRYPT) | ||
65 | scatterwalk_map_and_copy(rctx->auth_tag, | ||
66 | dd->aead_req->dst, | ||
67 | dd->total + dd->aead_req->assoclen, | ||
68 | dd->authsize, 1); | ||
69 | |||
70 | omap_crypto_cleanup(&dd->in_sgl[0], NULL, 0, alen, | ||
71 | FLAGS_ASSOC_DATA_ST_SHIFT, dd->flags); | ||
72 | |||
73 | omap_crypto_cleanup(&dd->in_sgl[nsg], NULL, 0, clen, | ||
74 | FLAGS_IN_DATA_ST_SHIFT, dd->flags); | ||
75 | |||
76 | if (!(dd->flags & FLAGS_ENCRYPT)) { | ||
77 | tag = (u8 *)rctx->auth_tag; | ||
78 | for (i = 0; i < dd->authsize; i++) { | ||
79 | if (tag[i]) { | ||
80 | dev_err(dd->dev, "GCM decryption: Tag Message is wrong\n"); | ||
81 | ret = -EBADMSG; | ||
82 | } | ||
83 | } | ||
84 | } | ||
85 | |||
86 | omap_aes_gcm_finish_req(dd, ret); | ||
87 | omap_aes_gcm_handle_queue(dd, NULL); | ||
88 | } | ||
89 | |||
90 | static int omap_aes_gcm_copy_buffers(struct omap_aes_dev *dd, | ||
91 | struct aead_request *req) | ||
92 | { | ||
93 | int alen, clen, cryptlen, assoclen, ret; | ||
94 | struct crypto_aead *aead = crypto_aead_reqtfm(req); | ||
95 | unsigned int authlen = crypto_aead_authsize(aead); | ||
96 | struct scatterlist *tmp, sg_arr[2]; | ||
97 | int nsg; | ||
98 | u16 flags; | ||
99 | |||
100 | assoclen = req->assoclen; | ||
101 | cryptlen = req->cryptlen; | ||
102 | |||
103 | if (dd->flags & FLAGS_RFC4106_GCM) | ||
104 | assoclen -= 8; | ||
105 | |||
106 | if (!(dd->flags & FLAGS_ENCRYPT)) | ||
107 | cryptlen -= authlen; | ||
108 | |||
109 | alen = ALIGN(assoclen, AES_BLOCK_SIZE); | ||
110 | clen = ALIGN(cryptlen, AES_BLOCK_SIZE); | ||
111 | |||
112 | nsg = !!(assoclen && cryptlen); | ||
113 | |||
114 | omap_aes_clear_copy_flags(dd); | ||
115 | |||
116 | sg_init_table(dd->in_sgl, nsg + 1); | ||
117 | if (assoclen) { | ||
118 | tmp = req->src; | ||
119 | ret = omap_crypto_align_sg(&tmp, assoclen, | ||
120 | AES_BLOCK_SIZE, dd->in_sgl, | ||
121 | OMAP_CRYPTO_COPY_DATA | | ||
122 | OMAP_CRYPTO_ZERO_BUF | | ||
123 | OMAP_CRYPTO_FORCE_SINGLE_ENTRY, | ||
124 | FLAGS_ASSOC_DATA_ST_SHIFT, | ||
125 | &dd->flags); | ||
126 | } | ||
127 | |||
128 | if (cryptlen) { | ||
129 | tmp = scatterwalk_ffwd(sg_arr, req->src, req->assoclen); | ||
130 | |||
131 | ret = omap_crypto_align_sg(&tmp, cryptlen, | ||
132 | AES_BLOCK_SIZE, &dd->in_sgl[nsg], | ||
133 | OMAP_CRYPTO_COPY_DATA | | ||
134 | OMAP_CRYPTO_ZERO_BUF | | ||
135 | OMAP_CRYPTO_FORCE_SINGLE_ENTRY, | ||
136 | FLAGS_IN_DATA_ST_SHIFT, | ||
137 | &dd->flags); | ||
138 | } | ||
139 | |||
140 | dd->in_sg = dd->in_sgl; | ||
141 | dd->total = cryptlen; | ||
142 | dd->assoc_len = assoclen; | ||
143 | dd->authsize = authlen; | ||
144 | |||
145 | dd->out_sg = req->dst; | ||
146 | dd->orig_out = req->dst; | ||
147 | |||
148 | dd->out_sg = scatterwalk_ffwd(sg_arr, req->dst, assoclen); | ||
149 | |||
150 | flags = 0; | ||
151 | if (req->src == req->dst || dd->out_sg == sg_arr) | ||
152 | flags |= OMAP_CRYPTO_FORCE_COPY; | ||
153 | |||
154 | ret = omap_crypto_align_sg(&dd->out_sg, cryptlen, | ||
155 | AES_BLOCK_SIZE, &dd->out_sgl, | ||
156 | flags, | ||
157 | FLAGS_OUT_DATA_ST_SHIFT, &dd->flags); | ||
158 | if (ret) | ||
159 | return ret; | ||
160 | |||
161 | dd->in_sg_len = sg_nents_for_len(dd->in_sg, alen + clen); | ||
162 | dd->out_sg_len = sg_nents_for_len(dd->out_sg, clen); | ||
163 | |||
164 | return 0; | ||
165 | } | ||
166 | |||
167 | static void omap_aes_gcm_complete(struct crypto_async_request *req, int err) | ||
168 | { | ||
169 | struct omap_aes_gcm_result *res = req->data; | ||
170 | |||
171 | if (err == -EINPROGRESS) | ||
172 | return; | ||
173 | |||
174 | res->err = err; | ||
175 | complete(&res->completion); | ||
176 | } | ||
177 | |||
178 | static int do_encrypt_iv(struct aead_request *req, u32 *tag, u32 *iv) | ||
179 | { | ||
180 | struct scatterlist iv_sg, tag_sg; | ||
181 | struct skcipher_request *sk_req; | ||
182 | struct omap_aes_gcm_result result; | ||
183 | struct omap_aes_ctx *ctx = crypto_aead_ctx(crypto_aead_reqtfm(req)); | ||
184 | int ret = 0; | ||
185 | |||
186 | sk_req = skcipher_request_alloc(ctx->ctr, GFP_KERNEL); | ||
187 | if (!sk_req) { | ||
188 | pr_err("skcipher: Failed to allocate request\n"); | ||
189 | return -1; | ||
190 | } | ||
191 | |||
192 | init_completion(&result.completion); | ||
193 | |||
194 | sg_init_one(&iv_sg, iv, AES_BLOCK_SIZE); | ||
195 | sg_init_one(&tag_sg, tag, AES_BLOCK_SIZE); | ||
196 | skcipher_request_set_callback(sk_req, CRYPTO_TFM_REQ_MAY_BACKLOG, | ||
197 | omap_aes_gcm_complete, &result); | ||
198 | ret = crypto_skcipher_setkey(ctx->ctr, (u8 *)ctx->key, ctx->keylen); | ||
199 | skcipher_request_set_crypt(sk_req, &iv_sg, &tag_sg, AES_BLOCK_SIZE, | ||
200 | NULL); | ||
201 | ret = crypto_skcipher_encrypt(sk_req); | ||
202 | switch (ret) { | ||
203 | case 0: | ||
204 | break; | ||
205 | case -EINPROGRESS: | ||
206 | case -EBUSY: | ||
207 | ret = wait_for_completion_interruptible(&result.completion); | ||
208 | if (!ret) { | ||
209 | ret = result.err; | ||
210 | if (!ret) { | ||
211 | reinit_completion(&result.completion); | ||
212 | break; | ||
213 | } | ||
214 | } | ||
215 | /* fall through */ | ||
216 | default: | ||
217 | pr_err("Encryptio of IV failed for GCM mode"); | ||
218 | break; | ||
219 | } | ||
220 | |||
221 | skcipher_request_free(sk_req); | ||
222 | return ret; | ||
223 | } | ||
224 | |||
225 | void omap_aes_gcm_dma_out_callback(void *data) | ||
226 | { | ||
227 | struct omap_aes_dev *dd = data; | ||
228 | struct omap_aes_reqctx *rctx; | ||
229 | int i, val; | ||
230 | u32 *auth_tag, tag[4]; | ||
231 | |||
232 | if (!(dd->flags & FLAGS_ENCRYPT)) | ||
233 | scatterwalk_map_and_copy(tag, dd->aead_req->src, | ||
234 | dd->total + dd->aead_req->assoclen, | ||
235 | dd->authsize, 0); | ||
236 | |||
237 | rctx = aead_request_ctx(dd->aead_req); | ||
238 | auth_tag = (u32 *)rctx->auth_tag; | ||
239 | for (i = 0; i < 4; i++) { | ||
240 | val = omap_aes_read(dd, AES_REG_TAG_N(dd, i)); | ||
241 | auth_tag[i] = val ^ auth_tag[i]; | ||
242 | if (!(dd->flags & FLAGS_ENCRYPT)) | ||
243 | auth_tag[i] = auth_tag[i] ^ tag[i]; | ||
244 | } | ||
245 | |||
246 | omap_aes_gcm_done_task(dd); | ||
247 | } | ||
248 | |||
249 | static int omap_aes_gcm_handle_queue(struct omap_aes_dev *dd, | ||
250 | struct aead_request *req) | ||
251 | { | ||
252 | struct omap_aes_ctx *ctx; | ||
253 | struct aead_request *backlog; | ||
254 | struct omap_aes_reqctx *rctx; | ||
255 | unsigned long flags; | ||
256 | int err, ret = 0; | ||
257 | |||
258 | spin_lock_irqsave(&dd->lock, flags); | ||
259 | if (req) | ||
260 | ret = aead_enqueue_request(&dd->aead_queue, req); | ||
261 | if (dd->flags & FLAGS_BUSY) { | ||
262 | spin_unlock_irqrestore(&dd->lock, flags); | ||
263 | return ret; | ||
264 | } | ||
265 | |||
266 | backlog = aead_get_backlog(&dd->aead_queue); | ||
267 | req = aead_dequeue_request(&dd->aead_queue); | ||
268 | if (req) | ||
269 | dd->flags |= FLAGS_BUSY; | ||
270 | spin_unlock_irqrestore(&dd->lock, flags); | ||
271 | |||
272 | if (!req) | ||
273 | return ret; | ||
274 | |||
275 | if (backlog) | ||
276 | backlog->base.complete(&backlog->base, -EINPROGRESS); | ||
277 | |||
278 | ctx = crypto_aead_ctx(crypto_aead_reqtfm(req)); | ||
279 | rctx = aead_request_ctx(req); | ||
280 | |||
281 | dd->ctx = ctx; | ||
282 | rctx->dd = dd; | ||
283 | dd->aead_req = req; | ||
284 | |||
285 | rctx->mode &= FLAGS_MODE_MASK; | ||
286 | dd->flags = (dd->flags & ~FLAGS_MODE_MASK) | rctx->mode; | ||
287 | |||
288 | err = omap_aes_gcm_copy_buffers(dd, req); | ||
289 | if (err) | ||
290 | return err; | ||
291 | |||
292 | err = omap_aes_write_ctrl(dd); | ||
293 | if (!err) | ||
294 | err = omap_aes_crypt_dma_start(dd); | ||
295 | |||
296 | if (err) { | ||
297 | omap_aes_gcm_finish_req(dd, err); | ||
298 | omap_aes_gcm_handle_queue(dd, NULL); | ||
299 | } | ||
300 | |||
301 | return ret; | ||
302 | } | ||
303 | |||
304 | static int omap_aes_gcm_crypt(struct aead_request *req, unsigned long mode) | ||
305 | { | ||
306 | struct omap_aes_reqctx *rctx = aead_request_ctx(req); | ||
307 | struct crypto_aead *aead = crypto_aead_reqtfm(req); | ||
308 | unsigned int authlen = crypto_aead_authsize(aead); | ||
309 | struct omap_aes_dev *dd; | ||
310 | __be32 counter = cpu_to_be32(1); | ||
311 | int err, assoclen; | ||
312 | |||
313 | memset(rctx->auth_tag, 0, sizeof(rctx->auth_tag)); | ||
314 | memcpy(rctx->iv + 12, &counter, 4); | ||
315 | |||
316 | err = do_encrypt_iv(req, (u32 *)rctx->auth_tag, (u32 *)rctx->iv); | ||
317 | if (err) | ||
318 | return err; | ||
319 | |||
320 | if (mode & FLAGS_RFC4106_GCM) | ||
321 | assoclen = req->assoclen - 8; | ||
322 | else | ||
323 | assoclen = req->assoclen; | ||
324 | if (assoclen + req->cryptlen == 0) { | ||
325 | scatterwalk_map_and_copy(rctx->auth_tag, req->dst, 0, authlen, | ||
326 | 1); | ||
327 | return 0; | ||
328 | } | ||
329 | |||
330 | dd = omap_aes_find_dev(rctx); | ||
331 | if (!dd) | ||
332 | return -ENODEV; | ||
333 | rctx->mode = mode; | ||
334 | |||
335 | return omap_aes_gcm_handle_queue(dd, req); | ||
336 | } | ||
337 | |||
338 | int omap_aes_gcm_encrypt(struct aead_request *req) | ||
339 | { | ||
340 | struct omap_aes_reqctx *rctx = aead_request_ctx(req); | ||
341 | |||
342 | memcpy(rctx->iv, req->iv, 12); | ||
343 | return omap_aes_gcm_crypt(req, FLAGS_ENCRYPT | FLAGS_GCM); | ||
344 | } | ||
345 | |||
346 | int omap_aes_gcm_decrypt(struct aead_request *req) | ||
347 | { | ||
348 | struct omap_aes_reqctx *rctx = aead_request_ctx(req); | ||
349 | |||
350 | memcpy(rctx->iv, req->iv, 12); | ||
351 | return omap_aes_gcm_crypt(req, FLAGS_GCM); | ||
352 | } | ||
353 | |||
354 | int omap_aes_4106gcm_encrypt(struct aead_request *req) | ||
355 | { | ||
356 | struct omap_aes_ctx *ctx = crypto_aead_ctx(crypto_aead_reqtfm(req)); | ||
357 | struct omap_aes_reqctx *rctx = aead_request_ctx(req); | ||
358 | |||
359 | memcpy(rctx->iv, ctx->nonce, 4); | ||
360 | memcpy(rctx->iv + 4, req->iv, 8); | ||
361 | return omap_aes_gcm_crypt(req, FLAGS_ENCRYPT | FLAGS_GCM | | ||
362 | FLAGS_RFC4106_GCM); | ||
363 | } | ||
364 | |||
365 | int omap_aes_4106gcm_decrypt(struct aead_request *req) | ||
366 | { | ||
367 | struct omap_aes_ctx *ctx = crypto_aead_ctx(crypto_aead_reqtfm(req)); | ||
368 | struct omap_aes_reqctx *rctx = aead_request_ctx(req); | ||
369 | |||
370 | memcpy(rctx->iv, ctx->nonce, 4); | ||
371 | memcpy(rctx->iv + 4, req->iv, 8); | ||
372 | return omap_aes_gcm_crypt(req, FLAGS_GCM | FLAGS_RFC4106_GCM); | ||
373 | } | ||
374 | |||
375 | int omap_aes_gcm_setkey(struct crypto_aead *tfm, const u8 *key, | ||
376 | unsigned int keylen) | ||
377 | { | ||
378 | struct omap_aes_ctx *ctx = crypto_aead_ctx(tfm); | ||
379 | |||
380 | if (keylen != AES_KEYSIZE_128 && keylen != AES_KEYSIZE_192 && | ||
381 | keylen != AES_KEYSIZE_256) | ||
382 | return -EINVAL; | ||
383 | |||
384 | memcpy(ctx->key, key, keylen); | ||
385 | ctx->keylen = keylen; | ||
386 | |||
387 | return 0; | ||
388 | } | ||
389 | |||
390 | int omap_aes_4106gcm_setkey(struct crypto_aead *tfm, const u8 *key, | ||
391 | unsigned int keylen) | ||
392 | { | ||
393 | struct omap_aes_ctx *ctx = crypto_aead_ctx(tfm); | ||
394 | |||
395 | if (keylen < 4) | ||
396 | return -EINVAL; | ||
397 | |||
398 | keylen -= 4; | ||
399 | if (keylen != AES_KEYSIZE_128 && keylen != AES_KEYSIZE_192 && | ||
400 | keylen != AES_KEYSIZE_256) | ||
401 | return -EINVAL; | ||
402 | |||
403 | memcpy(ctx->key, key, keylen); | ||
404 | memcpy(ctx->nonce, key + keylen, 4); | ||
405 | ctx->keylen = keylen; | ||
406 | |||
407 | return 0; | ||
408 | } | ||
diff --git a/drivers/crypto/omap-aes.c b/drivers/crypto/omap-aes.c index bf3b27d9dc33..5120a17731d0 100644 --- a/drivers/crypto/omap-aes.c +++ b/drivers/crypto/omap-aes.c | |||
@@ -37,6 +37,7 @@ | |||
37 | #include <crypto/aes.h> | 37 | #include <crypto/aes.h> |
38 | #include <crypto/engine.h> | 38 | #include <crypto/engine.h> |
39 | #include <crypto/internal/skcipher.h> | 39 | #include <crypto/internal/skcipher.h> |
40 | #include <crypto/internal/aead.h> | ||
40 | 41 | ||
41 | #include "omap-crypto.h" | 42 | #include "omap-crypto.h" |
42 | #include "omap-aes.h" | 43 | #include "omap-aes.h" |
@@ -112,8 +113,16 @@ static int omap_aes_hw_init(struct omap_aes_dev *dd) | |||
112 | return 0; | 113 | return 0; |
113 | } | 114 | } |
114 | 115 | ||
116 | void omap_aes_clear_copy_flags(struct omap_aes_dev *dd) | ||
117 | { | ||
118 | dd->flags &= ~(OMAP_CRYPTO_COPY_MASK << FLAGS_IN_DATA_ST_SHIFT); | ||
119 | dd->flags &= ~(OMAP_CRYPTO_COPY_MASK << FLAGS_OUT_DATA_ST_SHIFT); | ||
120 | dd->flags &= ~(OMAP_CRYPTO_COPY_MASK << FLAGS_ASSOC_DATA_ST_SHIFT); | ||
121 | } | ||
122 | |||
115 | int omap_aes_write_ctrl(struct omap_aes_dev *dd) | 123 | int omap_aes_write_ctrl(struct omap_aes_dev *dd) |
116 | { | 124 | { |
125 | struct omap_aes_reqctx *rctx; | ||
117 | unsigned int key32; | 126 | unsigned int key32; |
118 | int i, err; | 127 | int i, err; |
119 | u32 val; | 128 | u32 val; |
@@ -124,7 +133,11 @@ int omap_aes_write_ctrl(struct omap_aes_dev *dd) | |||
124 | 133 | ||
125 | key32 = dd->ctx->keylen / sizeof(u32); | 134 | key32 = dd->ctx->keylen / sizeof(u32); |
126 | 135 | ||
127 | /* it seems a key should always be set even if it has not changed */ | 136 | /* RESET the key as previous HASH keys should not get affected*/ |
137 | if (dd->flags & FLAGS_GCM) | ||
138 | for (i = 0; i < 0x40; i = i + 4) | ||
139 | omap_aes_write(dd, i, 0x0); | ||
140 | |||
128 | for (i = 0; i < key32; i++) { | 141 | for (i = 0; i < key32; i++) { |
129 | omap_aes_write(dd, AES_REG_KEY(dd, i), | 142 | omap_aes_write(dd, AES_REG_KEY(dd, i), |
130 | __le32_to_cpu(dd->ctx->key[i])); | 143 | __le32_to_cpu(dd->ctx->key[i])); |
@@ -133,12 +146,21 @@ int omap_aes_write_ctrl(struct omap_aes_dev *dd) | |||
133 | if ((dd->flags & (FLAGS_CBC | FLAGS_CTR)) && dd->req->info) | 146 | if ((dd->flags & (FLAGS_CBC | FLAGS_CTR)) && dd->req->info) |
134 | omap_aes_write_n(dd, AES_REG_IV(dd, 0), dd->req->info, 4); | 147 | omap_aes_write_n(dd, AES_REG_IV(dd, 0), dd->req->info, 4); |
135 | 148 | ||
149 | if ((dd->flags & (FLAGS_GCM)) && dd->aead_req->iv) { | ||
150 | rctx = aead_request_ctx(dd->aead_req); | ||
151 | omap_aes_write_n(dd, AES_REG_IV(dd, 0), (u32 *)rctx->iv, 4); | ||
152 | } | ||
153 | |||
136 | val = FLD_VAL(((dd->ctx->keylen >> 3) - 1), 4, 3); | 154 | val = FLD_VAL(((dd->ctx->keylen >> 3) - 1), 4, 3); |
137 | if (dd->flags & FLAGS_CBC) | 155 | if (dd->flags & FLAGS_CBC) |
138 | val |= AES_REG_CTRL_CBC; | 156 | val |= AES_REG_CTRL_CBC; |
139 | if (dd->flags & FLAGS_CTR) | 157 | |
158 | if (dd->flags & (FLAGS_CTR | FLAGS_GCM)) | ||
140 | val |= AES_REG_CTRL_CTR | AES_REG_CTRL_CTR_WIDTH_128; | 159 | val |= AES_REG_CTRL_CTR | AES_REG_CTRL_CTR_WIDTH_128; |
141 | 160 | ||
161 | if (dd->flags & FLAGS_GCM) | ||
162 | val |= AES_REG_CTRL_GCM; | ||
163 | |||
142 | if (dd->flags & FLAGS_ENCRYPT) | 164 | if (dd->flags & FLAGS_ENCRYPT) |
143 | val |= AES_REG_CTRL_DIRECTION; | 165 | val |= AES_REG_CTRL_DIRECTION; |
144 | 166 | ||
@@ -169,6 +191,8 @@ static void omap_aes_dma_trigger_omap4(struct omap_aes_dev *dd, int length) | |||
169 | { | 191 | { |
170 | omap_aes_write(dd, AES_REG_LENGTH_N(0), length); | 192 | omap_aes_write(dd, AES_REG_LENGTH_N(0), length); |
171 | omap_aes_write(dd, AES_REG_LENGTH_N(1), 0); | 193 | omap_aes_write(dd, AES_REG_LENGTH_N(1), 0); |
194 | if (dd->flags & FLAGS_GCM) | ||
195 | omap_aes_write(dd, AES_REG_A_LEN, dd->assoc_len); | ||
172 | 196 | ||
173 | omap_aes_dma_trigger_omap2(dd, length); | 197 | omap_aes_dma_trigger_omap2(dd, length); |
174 | } | 198 | } |
@@ -306,7 +330,10 @@ static int omap_aes_crypt_dma(struct omap_aes_dev *dd, | |||
306 | return -EINVAL; | 330 | return -EINVAL; |
307 | } | 331 | } |
308 | 332 | ||
309 | tx_out->callback = omap_aes_dma_out_callback; | 333 | if (dd->flags & FLAGS_GCM) |
334 | tx_out->callback = omap_aes_gcm_dma_out_callback; | ||
335 | else | ||
336 | tx_out->callback = omap_aes_dma_out_callback; | ||
310 | tx_out->callback_param = dd; | 337 | tx_out->callback_param = dd; |
311 | 338 | ||
312 | dmaengine_submit(tx_in); | 339 | dmaengine_submit(tx_in); |
@@ -411,7 +438,7 @@ static int omap_aes_prepare_req(struct crypto_engine *engine, | |||
411 | flags |= OMAP_CRYPTO_FORCE_COPY; | 438 | flags |= OMAP_CRYPTO_FORCE_COPY; |
412 | 439 | ||
413 | ret = omap_crypto_align_sg(&dd->in_sg, dd->total, AES_BLOCK_SIZE, | 440 | ret = omap_crypto_align_sg(&dd->in_sg, dd->total, AES_BLOCK_SIZE, |
414 | &dd->in_sgl, flags, | 441 | dd->in_sgl, flags, |
415 | FLAGS_IN_DATA_ST_SHIFT, &dd->flags); | 442 | FLAGS_IN_DATA_ST_SHIFT, &dd->flags); |
416 | if (ret) | 443 | if (ret) |
417 | return ret; | 444 | return ret; |
@@ -466,7 +493,7 @@ static void omap_aes_done_task(unsigned long data) | |||
466 | omap_aes_crypt_dma_stop(dd); | 493 | omap_aes_crypt_dma_stop(dd); |
467 | } | 494 | } |
468 | 495 | ||
469 | omap_crypto_cleanup(&dd->in_sgl, NULL, 0, dd->total_save, | 496 | omap_crypto_cleanup(dd->in_sgl, NULL, 0, dd->total_save, |
470 | FLAGS_IN_DATA_ST_SHIFT, dd->flags); | 497 | FLAGS_IN_DATA_ST_SHIFT, dd->flags); |
471 | 498 | ||
472 | omap_crypto_cleanup(&dd->out_sgl, dd->orig_out, 0, dd->total_save, | 499 | omap_crypto_cleanup(&dd->out_sgl, dd->orig_out, 0, dd->total_save, |
@@ -591,6 +618,36 @@ static int omap_aes_cra_init(struct crypto_tfm *tfm) | |||
591 | return 0; | 618 | return 0; |
592 | } | 619 | } |
593 | 620 | ||
621 | static int omap_aes_gcm_cra_init(struct crypto_aead *tfm) | ||
622 | { | ||
623 | struct omap_aes_dev *dd = NULL; | ||
624 | struct omap_aes_ctx *ctx = crypto_aead_ctx(tfm); | ||
625 | int err; | ||
626 | |||
627 | /* Find AES device, currently picks the first device */ | ||
628 | spin_lock_bh(&list_lock); | ||
629 | list_for_each_entry(dd, &dev_list, list) { | ||
630 | break; | ||
631 | } | ||
632 | spin_unlock_bh(&list_lock); | ||
633 | |||
634 | err = pm_runtime_get_sync(dd->dev); | ||
635 | if (err < 0) { | ||
636 | dev_err(dd->dev, "%s: failed to get_sync(%d)\n", | ||
637 | __func__, err); | ||
638 | return err; | ||
639 | } | ||
640 | |||
641 | tfm->reqsize = sizeof(struct omap_aes_reqctx); | ||
642 | ctx->ctr = crypto_alloc_skcipher("ecb(aes)", 0, 0); | ||
643 | if (IS_ERR(ctx->ctr)) { | ||
644 | pr_warn("could not load aes driver for encrypting IV\n"); | ||
645 | return PTR_ERR(ctx->ctr); | ||
646 | } | ||
647 | |||
648 | return 0; | ||
649 | } | ||
650 | |||
594 | static void omap_aes_cra_exit(struct crypto_tfm *tfm) | 651 | static void omap_aes_cra_exit(struct crypto_tfm *tfm) |
595 | { | 652 | { |
596 | struct omap_aes_ctx *ctx = crypto_tfm_ctx(tfm); | 653 | struct omap_aes_ctx *ctx = crypto_tfm_ctx(tfm); |
@@ -601,6 +658,16 @@ static void omap_aes_cra_exit(struct crypto_tfm *tfm) | |||
601 | ctx->fallback = NULL; | 658 | ctx->fallback = NULL; |
602 | } | 659 | } |
603 | 660 | ||
661 | static void omap_aes_gcm_cra_exit(struct crypto_aead *tfm) | ||
662 | { | ||
663 | struct omap_aes_ctx *ctx = crypto_aead_ctx(tfm); | ||
664 | |||
665 | omap_aes_cra_exit(crypto_aead_tfm(tfm)); | ||
666 | |||
667 | if (ctx->ctr) | ||
668 | crypto_free_skcipher(ctx->ctr); | ||
669 | } | ||
670 | |||
604 | /* ********************** ALGS ************************************ */ | 671 | /* ********************** ALGS ************************************ */ |
605 | 672 | ||
606 | static struct crypto_alg algs_ecb_cbc[] = { | 673 | static struct crypto_alg algs_ecb_cbc[] = { |
@@ -685,6 +752,54 @@ static struct omap_aes_algs_info omap_aes_algs_info_ecb_cbc[] = { | |||
685 | }, | 752 | }, |
686 | }; | 753 | }; |
687 | 754 | ||
755 | static struct aead_alg algs_aead_gcm[] = { | ||
756 | { | ||
757 | .base = { | ||
758 | .cra_name = "gcm(aes)", | ||
759 | .cra_driver_name = "gcm-aes-omap", | ||
760 | .cra_priority = 300, | ||
761 | .cra_flags = CRYPTO_ALG_ASYNC | | ||
762 | CRYPTO_ALG_KERN_DRIVER_ONLY, | ||
763 | .cra_blocksize = 1, | ||
764 | .cra_ctxsize = sizeof(struct omap_aes_ctx), | ||
765 | .cra_alignmask = 0xf, | ||
766 | .cra_module = THIS_MODULE, | ||
767 | }, | ||
768 | .init = omap_aes_gcm_cra_init, | ||
769 | .exit = omap_aes_gcm_cra_exit, | ||
770 | .ivsize = 12, | ||
771 | .maxauthsize = AES_BLOCK_SIZE, | ||
772 | .setkey = omap_aes_gcm_setkey, | ||
773 | .encrypt = omap_aes_gcm_encrypt, | ||
774 | .decrypt = omap_aes_gcm_decrypt, | ||
775 | }, | ||
776 | { | ||
777 | .base = { | ||
778 | .cra_name = "rfc4106(gcm(aes))", | ||
779 | .cra_driver_name = "rfc4106-gcm-aes-omap", | ||
780 | .cra_priority = 300, | ||
781 | .cra_flags = CRYPTO_ALG_ASYNC | | ||
782 | CRYPTO_ALG_KERN_DRIVER_ONLY, | ||
783 | .cra_blocksize = 1, | ||
784 | .cra_ctxsize = sizeof(struct omap_aes_ctx), | ||
785 | .cra_alignmask = 0xf, | ||
786 | .cra_module = THIS_MODULE, | ||
787 | }, | ||
788 | .init = omap_aes_gcm_cra_init, | ||
789 | .exit = omap_aes_gcm_cra_exit, | ||
790 | .maxauthsize = AES_BLOCK_SIZE, | ||
791 | .ivsize = 8, | ||
792 | .setkey = omap_aes_4106gcm_setkey, | ||
793 | .encrypt = omap_aes_4106gcm_encrypt, | ||
794 | .decrypt = omap_aes_4106gcm_decrypt, | ||
795 | }, | ||
796 | }; | ||
797 | |||
798 | static struct omap_aes_aead_algs omap_aes_aead_info = { | ||
799 | .algs_list = algs_aead_gcm, | ||
800 | .size = ARRAY_SIZE(algs_aead_gcm), | ||
801 | }; | ||
802 | |||
688 | static const struct omap_aes_pdata omap_aes_pdata_omap2 = { | 803 | static const struct omap_aes_pdata omap_aes_pdata_omap2 = { |
689 | .algs_info = omap_aes_algs_info_ecb_cbc, | 804 | .algs_info = omap_aes_algs_info_ecb_cbc, |
690 | .algs_info_size = ARRAY_SIZE(omap_aes_algs_info_ecb_cbc), | 805 | .algs_info_size = ARRAY_SIZE(omap_aes_algs_info_ecb_cbc), |
@@ -738,6 +853,7 @@ static const struct omap_aes_pdata omap_aes_pdata_omap3 = { | |||
738 | static const struct omap_aes_pdata omap_aes_pdata_omap4 = { | 853 | static const struct omap_aes_pdata omap_aes_pdata_omap4 = { |
739 | .algs_info = omap_aes_algs_info_ecb_cbc_ctr, | 854 | .algs_info = omap_aes_algs_info_ecb_cbc_ctr, |
740 | .algs_info_size = ARRAY_SIZE(omap_aes_algs_info_ecb_cbc_ctr), | 855 | .algs_info_size = ARRAY_SIZE(omap_aes_algs_info_ecb_cbc_ctr), |
856 | .aead_algs_info = &omap_aes_aead_info, | ||
741 | .trigger = omap_aes_dma_trigger_omap4, | 857 | .trigger = omap_aes_dma_trigger_omap4, |
742 | .key_ofs = 0x3c, | 858 | .key_ofs = 0x3c, |
743 | .iv_ofs = 0x40, | 859 | .iv_ofs = 0x40, |
@@ -920,6 +1036,7 @@ static int omap_aes_probe(struct platform_device *pdev) | |||
920 | struct device *dev = &pdev->dev; | 1036 | struct device *dev = &pdev->dev; |
921 | struct omap_aes_dev *dd; | 1037 | struct omap_aes_dev *dd; |
922 | struct crypto_alg *algp; | 1038 | struct crypto_alg *algp; |
1039 | struct aead_alg *aalg; | ||
923 | struct resource res; | 1040 | struct resource res; |
924 | int err = -ENOMEM, i, j, irq = -1; | 1041 | int err = -ENOMEM, i, j, irq = -1; |
925 | u32 reg; | 1042 | u32 reg; |
@@ -932,6 +1049,8 @@ static int omap_aes_probe(struct platform_device *pdev) | |||
932 | dd->dev = dev; | 1049 | dd->dev = dev; |
933 | platform_set_drvdata(pdev, dd); | 1050 | platform_set_drvdata(pdev, dd); |
934 | 1051 | ||
1052 | aead_init_queue(&dd->aead_queue, OMAP_AES_QUEUE_LENGTH); | ||
1053 | |||
935 | err = (dev->of_node) ? omap_aes_get_res_of(dd, dev, &res) : | 1054 | err = (dev->of_node) ? omap_aes_get_res_of(dd, dev, &res) : |
936 | omap_aes_get_res_pdev(dd, pdev, &res); | 1055 | omap_aes_get_res_pdev(dd, pdev, &res); |
937 | if (err) | 1056 | if (err) |
@@ -987,6 +1106,7 @@ static int omap_aes_probe(struct platform_device *pdev) | |||
987 | } | 1106 | } |
988 | } | 1107 | } |
989 | 1108 | ||
1109 | spin_lock_init(&dd->lock); | ||
990 | 1110 | ||
991 | INIT_LIST_HEAD(&dd->list); | 1111 | INIT_LIST_HEAD(&dd->list); |
992 | spin_lock(&list_lock); | 1112 | spin_lock(&list_lock); |
@@ -1023,7 +1143,29 @@ static int omap_aes_probe(struct platform_device *pdev) | |||
1023 | } | 1143 | } |
1024 | } | 1144 | } |
1025 | 1145 | ||
1146 | if (dd->pdata->aead_algs_info && | ||
1147 | !dd->pdata->aead_algs_info->registered) { | ||
1148 | for (i = 0; i < dd->pdata->aead_algs_info->size; i++) { | ||
1149 | aalg = &dd->pdata->aead_algs_info->algs_list[i]; | ||
1150 | algp = &aalg->base; | ||
1151 | |||
1152 | pr_debug("reg alg: %s\n", algp->cra_name); | ||
1153 | INIT_LIST_HEAD(&algp->cra_list); | ||
1154 | |||
1155 | err = crypto_register_aead(aalg); | ||
1156 | if (err) | ||
1157 | goto err_aead_algs; | ||
1158 | |||
1159 | dd->pdata->aead_algs_info->registered++; | ||
1160 | } | ||
1161 | } | ||
1162 | |||
1026 | return 0; | 1163 | return 0; |
1164 | err_aead_algs: | ||
1165 | for (i = dd->pdata->aead_algs_info->registered - 1; i >= 0; i--) { | ||
1166 | aalg = &dd->pdata->aead_algs_info->algs_list[i]; | ||
1167 | crypto_unregister_aead(aalg); | ||
1168 | } | ||
1027 | err_algs: | 1169 | err_algs: |
1028 | for (i = dd->pdata->algs_info_size - 1; i >= 0; i--) | 1170 | for (i = dd->pdata->algs_info_size - 1; i >= 0; i--) |
1029 | for (j = dd->pdata->algs_info[i].registered - 1; j >= 0; j--) | 1171 | for (j = dd->pdata->algs_info[i].registered - 1; j >= 0; j--) |
@@ -1048,6 +1190,7 @@ err_data: | |||
1048 | static int omap_aes_remove(struct platform_device *pdev) | 1190 | static int omap_aes_remove(struct platform_device *pdev) |
1049 | { | 1191 | { |
1050 | struct omap_aes_dev *dd = platform_get_drvdata(pdev); | 1192 | struct omap_aes_dev *dd = platform_get_drvdata(pdev); |
1193 | struct aead_alg *aalg; | ||
1051 | int i, j; | 1194 | int i, j; |
1052 | 1195 | ||
1053 | if (!dd) | 1196 | if (!dd) |
@@ -1062,7 +1205,13 @@ static int omap_aes_remove(struct platform_device *pdev) | |||
1062 | crypto_unregister_alg( | 1205 | crypto_unregister_alg( |
1063 | &dd->pdata->algs_info[i].algs_list[j]); | 1206 | &dd->pdata->algs_info[i].algs_list[j]); |
1064 | 1207 | ||
1208 | for (i = dd->pdata->aead_algs_info->size - 1; i >= 0; i--) { | ||
1209 | aalg = &dd->pdata->aead_algs_info->algs_list[i]; | ||
1210 | crypto_unregister_aead(aalg); | ||
1211 | } | ||
1212 | |||
1065 | crypto_engine_exit(dd->engine); | 1213 | crypto_engine_exit(dd->engine); |
1214 | |||
1066 | tasklet_kill(&dd->done_task); | 1215 | tasklet_kill(&dd->done_task); |
1067 | omap_aes_dma_cleanup(dd); | 1216 | omap_aes_dma_cleanup(dd); |
1068 | pm_runtime_disable(dd->dev); | 1217 | pm_runtime_disable(dd->dev); |
diff --git a/drivers/crypto/omap-aes.h b/drivers/crypto/omap-aes.h index 11e1784cc4a5..8906342e2b9a 100644 --- a/drivers/crypto/omap-aes.h +++ b/drivers/crypto/omap-aes.h | |||
@@ -30,11 +30,13 @@ | |||
30 | #define AES_REG_IV(dd, x) ((dd)->pdata->iv_ofs + ((x) * 0x04)) | 30 | #define AES_REG_IV(dd, x) ((dd)->pdata->iv_ofs + ((x) * 0x04)) |
31 | 31 | ||
32 | #define AES_REG_CTRL(dd) ((dd)->pdata->ctrl_ofs) | 32 | #define AES_REG_CTRL(dd) ((dd)->pdata->ctrl_ofs) |
33 | #define AES_REG_CTRL_CONTEXT_READY BIT(31) | ||
33 | #define AES_REG_CTRL_CTR_WIDTH_MASK GENMASK(8, 7) | 34 | #define AES_REG_CTRL_CTR_WIDTH_MASK GENMASK(8, 7) |
34 | #define AES_REG_CTRL_CTR_WIDTH_32 0 | 35 | #define AES_REG_CTRL_CTR_WIDTH_32 0 |
35 | #define AES_REG_CTRL_CTR_WIDTH_64 BIT(7) | 36 | #define AES_REG_CTRL_CTR_WIDTH_64 BIT(7) |
36 | #define AES_REG_CTRL_CTR_WIDTH_96 BIT(8) | 37 | #define AES_REG_CTRL_CTR_WIDTH_96 BIT(8) |
37 | #define AES_REG_CTRL_CTR_WIDTH_128 GENMASK(8, 7) | 38 | #define AES_REG_CTRL_CTR_WIDTH_128 GENMASK(8, 7) |
39 | #define AES_REG_CTRL_GCM GENMASK(17, 16) | ||
38 | #define AES_REG_CTRL_CTR BIT(6) | 40 | #define AES_REG_CTRL_CTR BIT(6) |
39 | #define AES_REG_CTRL_CBC BIT(5) | 41 | #define AES_REG_CTRL_CBC BIT(5) |
40 | #define AES_REG_CTRL_KEY_SIZE GENMASK(4, 3) | 42 | #define AES_REG_CTRL_KEY_SIZE GENMASK(4, 3) |
@@ -43,7 +45,12 @@ | |||
43 | #define AES_REG_CTRL_OUTPUT_READY BIT(0) | 45 | #define AES_REG_CTRL_OUTPUT_READY BIT(0) |
44 | #define AES_REG_CTRL_MASK GENMASK(24, 2) | 46 | #define AES_REG_CTRL_MASK GENMASK(24, 2) |
45 | 47 | ||
48 | #define AES_REG_C_LEN_0 0x54 | ||
49 | #define AES_REG_C_LEN_1 0x58 | ||
50 | #define AES_REG_A_LEN 0x5C | ||
51 | |||
46 | #define AES_REG_DATA_N(dd, x) ((dd)->pdata->data_ofs + ((x) * 0x04)) | 52 | #define AES_REG_DATA_N(dd, x) ((dd)->pdata->data_ofs + ((x) * 0x04)) |
53 | #define AES_REG_TAG_N(dd, x) (0x70 + ((x) * 0x04)) | ||
47 | 54 | ||
48 | #define AES_REG_REV(dd) ((dd)->pdata->rev_ofs) | 55 | #define AES_REG_REV(dd) ((dd)->pdata->rev_ofs) |
49 | 56 | ||
@@ -65,30 +72,41 @@ | |||
65 | 72 | ||
66 | #define DEFAULT_AUTOSUSPEND_DELAY 1000 | 73 | #define DEFAULT_AUTOSUSPEND_DELAY 1000 |
67 | 74 | ||
68 | #define FLAGS_MODE_MASK 0x000f | 75 | #define FLAGS_MODE_MASK 0x001f |
69 | #define FLAGS_ENCRYPT BIT(0) | 76 | #define FLAGS_ENCRYPT BIT(0) |
70 | #define FLAGS_CBC BIT(1) | 77 | #define FLAGS_CBC BIT(1) |
71 | #define FLAGS_GIV BIT(2) | 78 | #define FLAGS_CTR BIT(2) |
72 | #define FLAGS_CTR BIT(3) | 79 | #define FLAGS_GCM BIT(3) |
80 | #define FLAGS_RFC4106_GCM BIT(4) | ||
73 | 81 | ||
74 | #define FLAGS_INIT BIT(4) | 82 | #define FLAGS_INIT BIT(5) |
75 | #define FLAGS_FAST BIT(5) | 83 | #define FLAGS_FAST BIT(6) |
76 | #define FLAGS_BUSY BIT(6) | 84 | #define FLAGS_BUSY BIT(7) |
77 | 85 | ||
78 | #define FLAGS_IN_DATA_ST_SHIFT 8 | 86 | #define FLAGS_IN_DATA_ST_SHIFT 8 |
79 | #define FLAGS_OUT_DATA_ST_SHIFT 10 | 87 | #define FLAGS_OUT_DATA_ST_SHIFT 10 |
88 | #define FLAGS_ASSOC_DATA_ST_SHIFT 12 | ||
80 | 89 | ||
81 | #define AES_BLOCK_WORDS (AES_BLOCK_SIZE >> 2) | 90 | #define AES_BLOCK_WORDS (AES_BLOCK_SIZE >> 2) |
82 | 91 | ||
92 | struct omap_aes_gcm_result { | ||
93 | struct completion completion; | ||
94 | int err; | ||
95 | }; | ||
96 | |||
83 | struct omap_aes_ctx { | 97 | struct omap_aes_ctx { |
84 | int keylen; | 98 | int keylen; |
85 | u32 key[AES_KEYSIZE_256 / sizeof(u32)]; | 99 | u32 key[AES_KEYSIZE_256 / sizeof(u32)]; |
100 | u8 nonce[4]; | ||
86 | struct crypto_skcipher *fallback; | 101 | struct crypto_skcipher *fallback; |
102 | struct crypto_skcipher *ctr; | ||
87 | }; | 103 | }; |
88 | 104 | ||
89 | struct omap_aes_reqctx { | 105 | struct omap_aes_reqctx { |
90 | struct omap_aes_dev *dd; | 106 | struct omap_aes_dev *dd; |
91 | unsigned long mode; | 107 | unsigned long mode; |
108 | u8 iv[AES_BLOCK_SIZE]; | ||
109 | u32 auth_tag[AES_BLOCK_SIZE / sizeof(u32)]; | ||
92 | }; | 110 | }; |
93 | 111 | ||
94 | #define OMAP_AES_QUEUE_LENGTH 1 | 112 | #define OMAP_AES_QUEUE_LENGTH 1 |
@@ -100,9 +118,16 @@ struct omap_aes_algs_info { | |||
100 | unsigned int registered; | 118 | unsigned int registered; |
101 | }; | 119 | }; |
102 | 120 | ||
121 | struct omap_aes_aead_algs { | ||
122 | struct aead_alg *algs_list; | ||
123 | unsigned int size; | ||
124 | unsigned int registered; | ||
125 | }; | ||
126 | |||
103 | struct omap_aes_pdata { | 127 | struct omap_aes_pdata { |
104 | struct omap_aes_algs_info *algs_info; | 128 | struct omap_aes_algs_info *algs_info; |
105 | unsigned int algs_info_size; | 129 | unsigned int algs_info_size; |
130 | struct omap_aes_aead_algs *aead_algs_info; | ||
106 | 131 | ||
107 | void (*trigger)(struct omap_aes_dev *dd, int length); | 132 | void (*trigger)(struct omap_aes_dev *dd, int length); |
108 | 133 | ||
@@ -135,8 +160,11 @@ struct omap_aes_dev { | |||
135 | int err; | 160 | int err; |
136 | 161 | ||
137 | struct tasklet_struct done_task; | 162 | struct tasklet_struct done_task; |
163 | struct aead_queue aead_queue; | ||
164 | spinlock_t lock; | ||
138 | 165 | ||
139 | struct ablkcipher_request *req; | 166 | struct ablkcipher_request *req; |
167 | struct aead_request *aead_req; | ||
140 | struct crypto_engine *engine; | 168 | struct crypto_engine *engine; |
141 | 169 | ||
142 | /* | 170 | /* |
@@ -145,12 +173,14 @@ struct omap_aes_dev { | |||
145 | */ | 173 | */ |
146 | size_t total; | 174 | size_t total; |
147 | size_t total_save; | 175 | size_t total_save; |
176 | size_t assoc_len; | ||
177 | size_t authsize; | ||
148 | 178 | ||
149 | struct scatterlist *in_sg; | 179 | struct scatterlist *in_sg; |
150 | struct scatterlist *out_sg; | 180 | struct scatterlist *out_sg; |
151 | 181 | ||
152 | /* Buffers for copying for unaligned cases */ | 182 | /* Buffers for copying for unaligned cases */ |
153 | struct scatterlist in_sgl; | 183 | struct scatterlist in_sgl[2]; |
154 | struct scatterlist out_sgl; | 184 | struct scatterlist out_sgl; |
155 | struct scatterlist *orig_out; | 185 | struct scatterlist *orig_out; |
156 | 186 | ||
@@ -167,8 +197,18 @@ struct omap_aes_dev { | |||
167 | u32 omap_aes_read(struct omap_aes_dev *dd, u32 offset); | 197 | u32 omap_aes_read(struct omap_aes_dev *dd, u32 offset); |
168 | void omap_aes_write(struct omap_aes_dev *dd, u32 offset, u32 value); | 198 | void omap_aes_write(struct omap_aes_dev *dd, u32 offset, u32 value); |
169 | struct omap_aes_dev *omap_aes_find_dev(struct omap_aes_reqctx *rctx); | 199 | struct omap_aes_dev *omap_aes_find_dev(struct omap_aes_reqctx *rctx); |
200 | int omap_aes_gcm_setkey(struct crypto_aead *tfm, const u8 *key, | ||
201 | unsigned int keylen); | ||
202 | int omap_aes_4106gcm_setkey(struct crypto_aead *tfm, const u8 *key, | ||
203 | unsigned int keylen); | ||
204 | int omap_aes_gcm_encrypt(struct aead_request *req); | ||
205 | int omap_aes_gcm_decrypt(struct aead_request *req); | ||
206 | int omap_aes_4106gcm_encrypt(struct aead_request *req); | ||
207 | int omap_aes_4106gcm_decrypt(struct aead_request *req); | ||
170 | int omap_aes_write_ctrl(struct omap_aes_dev *dd); | 208 | int omap_aes_write_ctrl(struct omap_aes_dev *dd); |
171 | int omap_aes_crypt_dma_start(struct omap_aes_dev *dd); | 209 | int omap_aes_crypt_dma_start(struct omap_aes_dev *dd); |
172 | int omap_aes_crypt_dma_stop(struct omap_aes_dev *dd); | 210 | int omap_aes_crypt_dma_stop(struct omap_aes_dev *dd); |
211 | void omap_aes_gcm_dma_out_callback(void *data); | ||
212 | void omap_aes_clear_copy_flags(struct omap_aes_dev *dd); | ||
173 | 213 | ||
174 | #endif | 214 | #endif |