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
29 #define ZYNQMP_AES_PUF_NOT_PROGRAMMED 0xE300
31 #define ZYNQMP_AES_BLOCKSIZE 0x04
33 struct zynqmp_aes_dev {
34 struct list_head list;
36 /* the lock protects queue and dev list */
38 struct crypto_queue queue;
41 struct zynqmp_aes_op {
42 struct zynqmp_aes_dev *dd;
46 u8 key[ZYNQMP_AES_KEY_SIZE];
52 struct zynqmp_aes_data {
62 struct zynqmp_aes_drv {
63 struct list_head dev_list;
64 /* the lock protects dev list */
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),
73 static struct zynqmp_aes_dev *zynqmp_aes_find_dev(struct zynqmp_aes_op *ctx)
75 struct zynqmp_aes_dev *aes_dd = NULL;
76 struct zynqmp_aes_dev *tmp;
78 spin_lock_bh(&zynqmp_aes.lock);
80 list_for_each_entry(tmp, &zynqmp_aes.dev_list, list) {
88 spin_unlock_bh(&zynqmp_aes.lock);
93 static int zynqmp_setkey_blk(struct crypto_tfm *tfm, const u8 *key,
96 struct zynqmp_aes_op *op = crypto_tfm_ctx(tfm);
99 memcpy(op->key, key, len);
104 static int zynqmp_setkeytype(struct crypto_tfm *tfm, const u8 *keytype,
107 struct zynqmp_aes_op *op = crypto_tfm_ctx(tfm);
109 op->keytype = (u32)(*keytype);
114 static int zynqmp_aes_xcrypt(struct blkcipher_desc *desc,
115 struct scatterlist *dst,
116 struct scatterlist *src,
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;
131 if (!eemi_ops || !eemi_ops->aes)
134 if (op->keytype == ZYNQMP_AES_KUP_KEY)
135 dma_size = nbytes + ZYNQMP_AES_KEY_SIZE
136 + ZYNQMP_AES_IV_SIZE;
138 dma_size = nbytes + ZYNQMP_AES_IV_SIZE;
140 kbuf = dma_alloc_coherent(dd->dev, dma_size, &dma_addr, GFP_KERNEL);
144 abuf = dma_alloc_coherent(dd->dev, sizeof(struct zynqmp_aes_data),
145 &dma_addr_buf, GFP_KERNEL);
147 dma_free_coherent(dd->dev, dma_size, kbuf, dma_addr);
152 blkcipher_walk_init(&walk, dst, src, data_size);
153 err = blkcipher_walk_virt(desc, &walk);
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);
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;
171 if (op->keytype == ZYNQMP_AES_KUP_KEY) {
172 memcpy(kbuf + data_size + ZYNQMP_AES_IV_SIZE,
173 op->key, ZYNQMP_AES_KEY_SIZE);
175 abuf->key = abuf->src + data_size + ZYNQMP_AES_IV_SIZE;
179 eemi_ops->aes(dma_addr_buf, &ret);
183 case ZYNQMP_AES_GCM_TAG_MISMATCH_ERR:
184 dev_err(dd->dev, "ERROR: Gcm Tag mismatch\n\r");
186 case ZYNQMP_AES_SIZE_ERR:
187 dev_err(dd->dev, "ERROR : Non word aligned data\n\r");
189 case ZYNQMP_AES_WRONG_KEY_SRC_ERR:
190 dev_err(dd->dev, "ERROR: Wrong KeySrc, enable secure mode\n\r");
192 case ZYNQMP_AES_PUF_NOT_PROGRAMMED:
193 dev_err(dd->dev, "ERROR: PUF is not registered\r\n");
196 dev_err(dd->dev, "ERROR: Invalid");
202 copy_bytes = data_size;
204 copy_bytes = data_size - ZYNQMP_AES_GCM_SIZE;
206 blkcipher_walk_init(&walk, dst, src, copy_bytes);
207 err = blkcipher_walk_virt(desc, &walk);
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);
216 dma_free_coherent(dd->dev, dma_size, kbuf, dma_addr);
217 dma_free_coherent(dd->dev, sizeof(struct zynqmp_aes_data),
222 static int zynqmp_aes_decrypt(struct blkcipher_desc *desc,
223 struct scatterlist *dst,
224 struct scatterlist *src,
227 return zynqmp_aes_xcrypt(desc, dst, src, nbytes, ZYNQMP_AES_DECRYPT);
230 static int zynqmp_aes_encrypt(struct blkcipher_desc *desc,
231 struct scatterlist *dst,
232 struct scatterlist *src,
235 return zynqmp_aes_xcrypt(desc, dst, src, nbytes, ZYNQMP_AES_ENCRYPT);
238 static struct crypto_alg zynqmp_alg = {
239 .cra_name = "xilinx-zynqmp-aes",
240 .cra_driver_name = "zynqmp-aes",
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),
247 .cra_type = &crypto_blkcipher_type,
248 .cra_module = THIS_MODULE,
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,
262 static const struct of_device_id zynqmp_aes_dt_ids[] = {
263 { .compatible = "xlnx,zynqmp-aes" },
266 MODULE_DEVICE_TABLE(of, zynqmp_aes_dt_ids);
268 static int zynqmp_aes_probe(struct platform_device *pdev)
270 struct zynqmp_aes_dev *aes_dd;
271 struct device *dev = &pdev->dev;
274 aes_dd = devm_kzalloc(dev, sizeof(*aes_dd), GFP_KERNEL);
279 platform_set_drvdata(pdev, aes_dd);
281 ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(44));
283 dev_err(dev, "no usable DMA configuration");
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);
291 ret = crypto_register_alg(&zynqmp_alg);
295 dev_info(dev, "AES Successfully Registered\n\r");
299 list_del(&aes_dd->list);
300 dev_err(dev, "initialization failed.\n");
305 static int zynqmp_aes_remove(struct platform_device *pdev)
307 struct zynqmp_aes_dev *aes_dd;
309 aes_dd = platform_get_drvdata(pdev);
312 list_del(&aes_dd->list);
313 crypto_unregister_alg(&zynqmp_alg);
317 static struct platform_driver xilinx_aes_driver = {
318 .probe = zynqmp_aes_probe,
319 .remove = zynqmp_aes_remove,
321 .name = "zynqmp_aes",
322 .of_match_table = of_match_ptr(zynqmp_aes_dt_ids),
326 module_platform_driver(xilinx_aes_driver);
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>");