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