]> rtime.felk.cvut.cz Git - zynq/linux.git/blob - drivers/crypto/zynqmp-aes.c
f9f938fb3b7053f1126d4b541a20d4faa1899d08
[zynq/linux.git] / drivers / crypto / zynqmp-aes.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Xilinx ZynqMP AES Driver.
4  * Copyright (c) 2018 Xilinx Inc.
5  */
6
7 #include <crypto/aes.h>
8 #include <crypto/scatterwalk.h>
9 #include <linux/kernel.h>
10 #include <linux/module.h>
11 #include <linux/of_device.h>
12 #include <linux/scatterlist.h>
13 #include <linux/spinlock.h>
14 #include <linux/firmware/xilinx/zynqmp/firmware.h>
15
16 #define ZYNQMP_AES_QUEUE_LENGTH                 1
17 #define ZYNQMP_AES_IV_SIZE                      12
18 #define ZYNQMP_AES_GCM_SIZE                     16
19 #define ZYNQMP_AES_KEY_SIZE                     32
20
21 #define ZYNQMP_AES_DECRYPT                      0
22 #define ZYNQMP_AES_ENCRYPT                      1
23
24 #define ZYNQMP_AES_KUP_KEY                      0
25
26 #define ZYNQMP_AES_GCM_TAG_MISMATCH_ERR         0x01
27 #define ZYNQMP_AES_SIZE_ERR                     0x06
28 #define ZYNQMP_AES_WRONG_KEY_SRC_ERR            0x13
29
30 #define ZYNQMP_AES_BLOCKSIZE                    0x04
31
32 struct zynqmp_aes_dev {
33         struct list_head list;
34         struct device *dev;
35         /* the lock protects queue and dev list */
36         spinlock_t lock;
37         struct crypto_queue queue;
38 };
39
40 struct zynqmp_aes_op {
41         struct zynqmp_aes_dev *dd;
42         void *src;
43         void *dst;
44         int len;
45         u8 key[ZYNQMP_AES_KEY_SIZE];
46         u8 *iv;
47         u32 keylen;
48         u32 keytype;
49 };
50
51 struct zynqmp_aes_data {
52         u64 src;
53         u64 iv;
54         u64 key;
55         u64 dst;
56         u64 size;
57         u64 optype;
58         u64 keysrc;
59 };
60
61 struct zynqmp_aes_drv {
62         struct list_head dev_list;
63         /* the lock protects dev list */
64         spinlock_t lock;
65 };
66
67 static struct zynqmp_aes_drv zynqmp_aes = {
68         .dev_list = LIST_HEAD_INIT(zynqmp_aes.dev_list),
69         .lock = __SPIN_LOCK_UNLOCKED(zynqmp_aes.lock),
70 };
71
72 static struct zynqmp_aes_dev *zynqmp_aes_find_dev(struct zynqmp_aes_op *ctx)
73 {
74         struct zynqmp_aes_dev *aes_dd = NULL;
75         struct zynqmp_aes_dev *tmp;
76
77         spin_lock_bh(&zynqmp_aes.lock);
78         if (!ctx->dd) {
79                 list_for_each_entry(tmp, &zynqmp_aes.dev_list, list) {
80                         aes_dd = tmp;
81                         break;
82                 }
83                 ctx->dd = aes_dd;
84         } else {
85                 aes_dd = ctx->dd;
86         }
87         spin_unlock_bh(&zynqmp_aes.lock);
88
89         return aes_dd;
90 }
91
92 static int zynqmp_setkey_blk(struct crypto_tfm *tfm, const u8 *key,
93                              unsigned int len)
94 {
95         struct zynqmp_aes_op *op = crypto_tfm_ctx(tfm);
96
97         op->keylen = len;
98         memcpy(op->key, key, len);
99
100         return 0;
101 }
102
103 static int zynqmp_setkeytype(struct crypto_tfm *tfm, const u8 *keytype,
104                              unsigned int len)
105 {
106         struct zynqmp_aes_op *op = crypto_tfm_ctx(tfm);
107
108         op->keytype = (u32)(*keytype);
109
110         return 0;
111 }
112
113 static int zynqmp_aes_xcrypt(struct blkcipher_desc *desc,
114                              struct scatterlist *dst,
115                              struct scatterlist *src,
116                              unsigned int nbytes,
117                              unsigned int flags)
118 {
119         struct zynqmp_aes_op *op = crypto_blkcipher_ctx(desc->tfm);
120         struct zynqmp_aes_dev *dd = zynqmp_aes_find_dev(op);
121         const struct zynqmp_eemi_ops *eemi_ops = zynqmp_pm_get_eemi_ops();
122         int err, ret, copy_bytes, src_data = 0, dst_data = 0;
123         dma_addr_t dma_addr, dma_addr_buf;
124         struct zynqmp_aes_data *abuf;
125         struct blkcipher_walk walk;
126         unsigned int data_size;
127         size_t dma_size;
128         char *kbuf;
129
130         if (!eemi_ops || !eemi_ops->aes)
131                 return -ENOTSUPP;
132
133         if (op->keytype == ZYNQMP_AES_KUP_KEY)
134                 dma_size = nbytes + ZYNQMP_AES_KEY_SIZE
135                         + ZYNQMP_AES_IV_SIZE;
136         else
137                 dma_size = nbytes + ZYNQMP_AES_IV_SIZE;
138
139         kbuf = dma_alloc_coherent(dd->dev, dma_size, &dma_addr, GFP_KERNEL);
140         if (!kbuf)
141                 return -ENOMEM;
142
143         abuf = dma_alloc_coherent(dd->dev, sizeof(struct zynqmp_aes_data),
144                                   &dma_addr_buf, GFP_KERNEL);
145         if (!abuf) {
146                 dma_free_coherent(dd->dev, dma_size, kbuf, dma_addr);
147                 return -ENOMEM;
148         }
149
150         data_size = nbytes;
151         blkcipher_walk_init(&walk, dst, src, data_size);
152         err = blkcipher_walk_virt(desc, &walk);
153         op->iv = walk.iv;
154
155         while ((nbytes = walk.nbytes)) {
156                 op->src = walk.src.virt.addr;
157                 memcpy(kbuf + src_data, op->src, nbytes);
158                 src_data = src_data + nbytes;
159                 nbytes &= (ZYNQMP_AES_BLOCKSIZE - 1);
160                 err = blkcipher_walk_done(desc, &walk, nbytes);
161         }
162         memcpy(kbuf + data_size, op->iv, ZYNQMP_AES_IV_SIZE);
163         abuf->src = dma_addr;
164         abuf->dst = dma_addr;
165         abuf->iv = abuf->src + data_size;
166         abuf->size = data_size - ZYNQMP_AES_GCM_SIZE;
167         abuf->optype = flags;
168         abuf->keysrc = op->keytype;
169
170         if (op->keytype == ZYNQMP_AES_KUP_KEY) {
171                 memcpy(kbuf + data_size + ZYNQMP_AES_IV_SIZE,
172                        op->key, ZYNQMP_AES_KEY_SIZE);
173
174                 abuf->key = abuf->src + data_size + ZYNQMP_AES_IV_SIZE;
175         } else {
176                 abuf->key = 0;
177         }
178         eemi_ops->aes(dma_addr_buf, &ret);
179
180         if (ret != 0) {
181                 switch (ret) {
182                 case ZYNQMP_AES_GCM_TAG_MISMATCH_ERR:
183                         dev_err(dd->dev, "ERROR: Gcm Tag mismatch\n\r");
184                         break;
185                 case ZYNQMP_AES_SIZE_ERR:
186                         dev_err(dd->dev, "ERROR : Non word aligned data\n\r");
187                         break;
188                 case ZYNQMP_AES_WRONG_KEY_SRC_ERR:
189                         dev_err(dd->dev, "ERROR: Wrong KeySrc, enable secure mode\n\r");
190                         break;
191                 default:
192                         dev_err(dd->dev, "ERROR: Invalid");
193                         break;
194                 }
195                 goto END;
196         }
197         if (flags)
198                 copy_bytes = data_size;
199         else
200                 copy_bytes = data_size - ZYNQMP_AES_GCM_SIZE;
201
202         blkcipher_walk_init(&walk, dst, src, copy_bytes);
203         err = blkcipher_walk_virt(desc, &walk);
204
205         while ((nbytes = walk.nbytes)) {
206                 memcpy(walk.dst.virt.addr, kbuf + dst_data, nbytes);
207                 dst_data = dst_data + nbytes;
208                 nbytes &= (ZYNQMP_AES_BLOCKSIZE - 1);
209                 err = blkcipher_walk_done(desc, &walk, nbytes);
210         }
211 END:
212         dma_free_coherent(dd->dev, dma_size, kbuf, dma_addr);
213         dma_free_coherent(dd->dev, sizeof(struct zynqmp_aes_data),
214                           abuf, dma_addr_buf);
215         return err;
216 }
217
218 static int zynqmp_aes_decrypt(struct blkcipher_desc *desc,
219                               struct scatterlist *dst,
220                               struct scatterlist *src,
221                               unsigned int nbytes)
222 {
223         return zynqmp_aes_xcrypt(desc, dst, src, nbytes, ZYNQMP_AES_DECRYPT);
224 }
225
226 static int zynqmp_aes_encrypt(struct blkcipher_desc *desc,
227                               struct scatterlist *dst,
228                               struct scatterlist *src,
229                               unsigned int nbytes)
230 {
231         return zynqmp_aes_xcrypt(desc, dst, src, nbytes, ZYNQMP_AES_ENCRYPT);
232 }
233
234 static struct crypto_alg zynqmp_alg = {
235         .cra_name               =       "xilinx-zynqmp-aes",
236         .cra_driver_name        =       "zynqmp-aes",
237         .cra_priority           =       400,
238         .cra_flags              =       CRYPTO_ALG_TYPE_BLKCIPHER |
239                                         CRYPTO_ALG_KERN_DRIVER_ONLY,
240         .cra_blocksize          =       ZYNQMP_AES_BLOCKSIZE,
241         .cra_ctxsize            =       sizeof(struct zynqmp_aes_op),
242         .cra_alignmask          =       15,
243         .cra_type               =       &crypto_blkcipher_type,
244         .cra_module             =       THIS_MODULE,
245         .cra_u                  =       {
246         .blkcipher      =       {
247                         .min_keysize    =       0,
248                         .max_keysize    =       ZYNQMP_AES_KEY_SIZE,
249                         .setkey         =       zynqmp_setkey_blk,
250                         .setkeytype     =       zynqmp_setkeytype,
251                         .encrypt        =       zynqmp_aes_encrypt,
252                         .decrypt        =       zynqmp_aes_decrypt,
253                         .ivsize         =       ZYNQMP_AES_IV_SIZE,
254                 }
255         }
256 };
257
258 static const struct of_device_id zynqmp_aes_dt_ids[] = {
259         { .compatible = "xlnx,zynqmp-aes" },
260         { /* sentinel */ }
261 };
262 MODULE_DEVICE_TABLE(of, zynqmp_aes_dt_ids);
263
264 static int zynqmp_aes_probe(struct platform_device *pdev)
265 {
266         struct zynqmp_aes_dev *aes_dd;
267         struct device *dev = &pdev->dev;
268         int ret;
269
270         aes_dd = devm_kzalloc(dev, sizeof(*aes_dd), GFP_KERNEL);
271         if (!aes_dd)
272                 return -ENOMEM;
273
274         aes_dd->dev = dev;
275         platform_set_drvdata(pdev, aes_dd);
276
277         ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(44));
278         if (ret < 0) {
279                 dev_err(dev, "no usable DMA configuration");
280                 return ret;
281         }
282
283         INIT_LIST_HEAD(&aes_dd->list);
284         crypto_init_queue(&aes_dd->queue, ZYNQMP_AES_QUEUE_LENGTH);
285         list_add_tail(&aes_dd->list, &zynqmp_aes.dev_list);
286
287         ret = crypto_register_alg(&zynqmp_alg);
288         if (ret)
289                 goto err_algs;
290
291         dev_info(dev, "AES Successfully Registered\n\r");
292         return 0;
293
294 err_algs:
295         list_del(&aes_dd->list);
296         dev_err(dev, "initialization failed.\n");
297
298         return ret;
299 }
300
301 static int zynqmp_aes_remove(struct platform_device *pdev)
302 {
303         struct zynqmp_aes_dev *aes_dd;
304
305         aes_dd = platform_get_drvdata(pdev);
306         if (!aes_dd)
307                 return -ENODEV;
308         list_del(&aes_dd->list);
309         crypto_unregister_alg(&zynqmp_alg);
310         return 0;
311 }
312
313 static struct platform_driver xilinx_aes_driver = {
314         .probe = zynqmp_aes_probe,
315         .remove = zynqmp_aes_remove,
316         .driver = {
317                 .name = "zynqmp_aes",
318                 .of_match_table = of_match_ptr(zynqmp_aes_dt_ids),
319         },
320 };
321
322 module_platform_driver(xilinx_aes_driver);
323
324 MODULE_DESCRIPTION("Xilinx ZynqMP AES hw acceleration support.");
325 MODULE_LICENSE("GPL v2");
326 MODULE_AUTHOR("Nava kishore Manne <nava.manne@xilinx.com>");
327 MODULE_AUTHOR("Kalyani Akula <kalyani.akula@xilinx.com>");