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