1 // SPDX-License-Identifier: GPL-2.0
3 * Xilinx ZynqMP AES Driver.
4 * Copyright (c) 2018 Xilinx Inc.
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>
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
21 #define ZYNQMP_AES_DECRYPT 0
22 #define ZYNQMP_AES_ENCRYPT 1
24 #define ZYNQMP_AES_KUP_KEY 0
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
30 #define ZYNQMP_AES_BLOCKSIZE 0x04
32 struct zynqmp_aes_dev {
33 struct list_head list;
35 /* the lock protects queue and dev list */
37 struct crypto_queue queue;
40 struct zynqmp_aes_op {
41 struct zynqmp_aes_dev *dd;
45 u8 key[ZYNQMP_AES_KEY_SIZE];
51 struct zynqmp_aes_data {
61 struct zynqmp_aes_drv {
62 struct list_head dev_list;
63 /* the lock protects dev list */
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),
72 static struct zynqmp_aes_dev *zynqmp_aes_find_dev(struct zynqmp_aes_op *ctx)
74 struct zynqmp_aes_dev *aes_dd = NULL;
75 struct zynqmp_aes_dev *tmp;
77 spin_lock_bh(&zynqmp_aes.lock);
79 list_for_each_entry(tmp, &zynqmp_aes.dev_list, list) {
87 spin_unlock_bh(&zynqmp_aes.lock);
92 static int zynqmp_setkey_blk(struct crypto_tfm *tfm, const u8 *key,
95 struct zynqmp_aes_op *op = crypto_tfm_ctx(tfm);
98 memcpy(op->key, key, len);
103 static int zynqmp_setkeytype(struct crypto_tfm *tfm, const u8 *keytype,
106 struct zynqmp_aes_op *op = crypto_tfm_ctx(tfm);
108 op->keytype = (u32)(*keytype);
113 static int zynqmp_aes_xcrypt(struct blkcipher_desc *desc,
114 struct scatterlist *dst,
115 struct scatterlist *src,
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;
130 if (!eemi_ops || !eemi_ops->aes)
133 if (op->keytype == ZYNQMP_AES_KUP_KEY)
134 dma_size = nbytes + ZYNQMP_AES_KEY_SIZE
135 + ZYNQMP_AES_IV_SIZE;
137 dma_size = nbytes + ZYNQMP_AES_IV_SIZE;
139 kbuf = dma_alloc_coherent(dd->dev, dma_size, &dma_addr, GFP_KERNEL);
143 abuf = dma_alloc_coherent(dd->dev, sizeof(struct zynqmp_aes_data),
144 &dma_addr_buf, GFP_KERNEL);
146 dma_free_coherent(dd->dev, dma_size, kbuf, dma_addr);
151 blkcipher_walk_init(&walk, dst, src, data_size);
152 err = blkcipher_walk_virt(desc, &walk);
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);
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;
170 if (op->keytype == ZYNQMP_AES_KUP_KEY) {
171 memcpy(kbuf + data_size + ZYNQMP_AES_IV_SIZE,
172 op->key, ZYNQMP_AES_KEY_SIZE);
174 abuf->key = abuf->src + data_size + ZYNQMP_AES_IV_SIZE;
178 eemi_ops->aes(dma_addr_buf, &ret);
182 case ZYNQMP_AES_GCM_TAG_MISMATCH_ERR:
183 dev_err(dd->dev, "ERROR: Gcm Tag mismatch\n\r");
185 case ZYNQMP_AES_SIZE_ERR:
186 dev_err(dd->dev, "ERROR : Non word aligned data\n\r");
188 case ZYNQMP_AES_WRONG_KEY_SRC_ERR:
189 dev_err(dd->dev, "ERROR: Wrong KeySrc, enable secure mode\n\r");
192 dev_err(dd->dev, "ERROR: Invalid");
198 copy_bytes = data_size;
200 copy_bytes = data_size - ZYNQMP_AES_GCM_SIZE;
202 blkcipher_walk_init(&walk, dst, src, copy_bytes);
203 err = blkcipher_walk_virt(desc, &walk);
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);
212 dma_free_coherent(dd->dev, dma_size, kbuf, dma_addr);
213 dma_free_coherent(dd->dev, sizeof(struct zynqmp_aes_data),
218 static int zynqmp_aes_decrypt(struct blkcipher_desc *desc,
219 struct scatterlist *dst,
220 struct scatterlist *src,
223 return zynqmp_aes_xcrypt(desc, dst, src, nbytes, ZYNQMP_AES_DECRYPT);
226 static int zynqmp_aes_encrypt(struct blkcipher_desc *desc,
227 struct scatterlist *dst,
228 struct scatterlist *src,
231 return zynqmp_aes_xcrypt(desc, dst, src, nbytes, ZYNQMP_AES_ENCRYPT);
234 static struct crypto_alg zynqmp_alg = {
235 .cra_name = "xilinx-zynqmp-aes",
236 .cra_driver_name = "zynqmp-aes",
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),
243 .cra_type = &crypto_blkcipher_type,
244 .cra_module = THIS_MODULE,
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,
258 static const struct of_device_id zynqmp_aes_dt_ids[] = {
259 { .compatible = "xlnx,zynqmp-aes" },
262 MODULE_DEVICE_TABLE(of, zynqmp_aes_dt_ids);
264 static int zynqmp_aes_probe(struct platform_device *pdev)
266 struct zynqmp_aes_dev *aes_dd;
267 struct device *dev = &pdev->dev;
270 aes_dd = devm_kzalloc(dev, sizeof(*aes_dd), GFP_KERNEL);
275 platform_set_drvdata(pdev, aes_dd);
277 ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(44));
279 dev_err(dev, "no usable DMA configuration");
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);
287 ret = crypto_register_alg(&zynqmp_alg);
291 dev_info(dev, "AES Successfully Registered\n\r");
295 list_del(&aes_dd->list);
296 dev_err(dev, "initialization failed.\n");
301 static int zynqmp_aes_remove(struct platform_device *pdev)
303 struct zynqmp_aes_dev *aes_dd;
305 aes_dd = platform_get_drvdata(pdev);
308 list_del(&aes_dd->list);
309 crypto_unregister_alg(&zynqmp_alg);
313 static struct platform_driver xilinx_aes_driver = {
314 .probe = zynqmp_aes_probe,
315 .remove = zynqmp_aes_remove,
317 .name = "zynqmp_aes",
318 .of_match_table = of_match_ptr(zynqmp_aes_dt_ids),
322 module_platform_driver(xilinx_aes_driver);
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>");