Root/drivers/crypto/atmel-tdes.c

1/*
2 * Cryptographic API.
3 *
4 * Support for ATMEL DES/TDES HW acceleration.
5 *
6 * Copyright (c) 2012 Eukréa Electromatique - ATMEL
7 * Author: Nicolas Royer <nicolas@eukrea.com>
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License version 2 as published
11 * by the Free Software Foundation.
12 *
13 * Some ideas are from omap-aes.c drivers.
14 */
15
16
17#include <linux/kernel.h>
18#include <linux/module.h>
19#include <linux/slab.h>
20#include <linux/err.h>
21#include <linux/clk.h>
22#include <linux/io.h>
23#include <linux/hw_random.h>
24#include <linux/platform_device.h>
25
26#include <linux/device.h>
27#include <linux/module.h>
28#include <linux/init.h>
29#include <linux/errno.h>
30#include <linux/interrupt.h>
31#include <linux/kernel.h>
32#include <linux/clk.h>
33#include <linux/irq.h>
34#include <linux/io.h>
35#include <linux/platform_device.h>
36#include <linux/scatterlist.h>
37#include <linux/dma-mapping.h>
38#include <linux/delay.h>
39#include <linux/crypto.h>
40#include <linux/cryptohash.h>
41#include <crypto/scatterwalk.h>
42#include <crypto/algapi.h>
43#include <crypto/des.h>
44#include <crypto/hash.h>
45#include <crypto/internal/hash.h>
46#include "atmel-tdes-regs.h"
47
48/* TDES flags */
49#define TDES_FLAGS_MODE_MASK 0x007f
50#define TDES_FLAGS_ENCRYPT BIT(0)
51#define TDES_FLAGS_CBC BIT(1)
52#define TDES_FLAGS_CFB BIT(2)
53#define TDES_FLAGS_CFB8 BIT(3)
54#define TDES_FLAGS_CFB16 BIT(4)
55#define TDES_FLAGS_CFB32 BIT(5)
56#define TDES_FLAGS_OFB BIT(6)
57
58#define TDES_FLAGS_INIT BIT(16)
59#define TDES_FLAGS_FAST BIT(17)
60#define TDES_FLAGS_BUSY BIT(18)
61
62#define ATMEL_TDES_QUEUE_LENGTH 1
63
64#define CFB8_BLOCK_SIZE 1
65#define CFB16_BLOCK_SIZE 2
66#define CFB32_BLOCK_SIZE 4
67#define CFB64_BLOCK_SIZE 8
68
69
70struct atmel_tdes_dev;
71
72struct atmel_tdes_ctx {
73    struct atmel_tdes_dev *dd;
74
75    int keylen;
76    u32 key[3*DES_KEY_SIZE / sizeof(u32)];
77    unsigned long flags;
78};
79
80struct atmel_tdes_reqctx {
81    unsigned long mode;
82};
83
84struct atmel_tdes_dev {
85    struct list_head list;
86    unsigned long phys_base;
87    void __iomem *io_base;
88
89    struct atmel_tdes_ctx *ctx;
90    struct device *dev;
91    struct clk *iclk;
92    int irq;
93
94    unsigned long flags;
95    int err;
96
97    spinlock_t lock;
98    struct crypto_queue queue;
99
100    struct tasklet_struct done_task;
101    struct tasklet_struct queue_task;
102
103    struct ablkcipher_request *req;
104    size_t total;
105
106    struct scatterlist *in_sg;
107    size_t in_offset;
108    struct scatterlist *out_sg;
109    size_t out_offset;
110
111    size_t buflen;
112    size_t dma_size;
113
114    void *buf_in;
115    int dma_in;
116    dma_addr_t dma_addr_in;
117
118    void *buf_out;
119    int dma_out;
120    dma_addr_t dma_addr_out;
121};
122
123struct atmel_tdes_drv {
124    struct list_head dev_list;
125    spinlock_t lock;
126};
127
128static struct atmel_tdes_drv atmel_tdes = {
129    .dev_list = LIST_HEAD_INIT(atmel_tdes.dev_list),
130    .lock = __SPIN_LOCK_UNLOCKED(atmel_tdes.lock),
131};
132
133static int atmel_tdes_sg_copy(struct scatterlist **sg, size_t *offset,
134            void *buf, size_t buflen, size_t total, int out)
135{
136    unsigned int count, off = 0;
137
138    while (buflen && total) {
139        count = min((*sg)->length - *offset, total);
140        count = min(count, buflen);
141
142        if (!count)
143            return off;
144
145        scatterwalk_map_and_copy(buf + off, *sg, *offset, count, out);
146
147        off += count;
148        buflen -= count;
149        *offset += count;
150        total -= count;
151
152        if (*offset == (*sg)->length) {
153            *sg = sg_next(*sg);
154            if (*sg)
155                *offset = 0;
156            else
157                total = 0;
158        }
159    }
160
161    return off;
162}
163
164static inline u32 atmel_tdes_read(struct atmel_tdes_dev *dd, u32 offset)
165{
166    return readl_relaxed(dd->io_base + offset);
167}
168
169static inline void atmel_tdes_write(struct atmel_tdes_dev *dd,
170                    u32 offset, u32 value)
171{
172    writel_relaxed(value, dd->io_base + offset);
173}
174
175static void atmel_tdes_write_n(struct atmel_tdes_dev *dd, u32 offset,
176                    u32 *value, int count)
177{
178    for (; count--; value++, offset += 4)
179        atmel_tdes_write(dd, offset, *value);
180}
181
182static struct atmel_tdes_dev *atmel_tdes_find_dev(struct atmel_tdes_ctx *ctx)
183{
184    struct atmel_tdes_dev *tdes_dd = NULL;
185    struct atmel_tdes_dev *tmp;
186
187    spin_lock_bh(&atmel_tdes.lock);
188    if (!ctx->dd) {
189        list_for_each_entry(tmp, &atmel_tdes.dev_list, list) {
190            tdes_dd = tmp;
191            break;
192        }
193        ctx->dd = tdes_dd;
194    } else {
195        tdes_dd = ctx->dd;
196    }
197    spin_unlock_bh(&atmel_tdes.lock);
198
199    return tdes_dd;
200}
201
202static int atmel_tdes_hw_init(struct atmel_tdes_dev *dd)
203{
204    clk_prepare_enable(dd->iclk);
205
206    if (!(dd->flags & TDES_FLAGS_INIT)) {
207        atmel_tdes_write(dd, TDES_CR, TDES_CR_SWRST);
208        dd->flags |= TDES_FLAGS_INIT;
209        dd->err = 0;
210    }
211
212    return 0;
213}
214
215static int atmel_tdes_write_ctrl(struct atmel_tdes_dev *dd)
216{
217    int err;
218    u32 valcr = 0, valmr = TDES_MR_SMOD_PDC;
219
220    err = atmel_tdes_hw_init(dd);
221
222    if (err)
223        return err;
224
225    atmel_tdes_write(dd, TDES_PTCR, TDES_PTCR_TXTDIS|TDES_PTCR_RXTDIS);
226
227    /* MR register must be set before IV registers */
228    if (dd->ctx->keylen > (DES_KEY_SIZE << 1)) {
229        valmr |= TDES_MR_KEYMOD_3KEY;
230        valmr |= TDES_MR_TDESMOD_TDES;
231    } else if (dd->ctx->keylen > DES_KEY_SIZE) {
232        valmr |= TDES_MR_KEYMOD_2KEY;
233        valmr |= TDES_MR_TDESMOD_TDES;
234    } else {
235        valmr |= TDES_MR_TDESMOD_DES;
236    }
237
238    if (dd->flags & TDES_FLAGS_CBC) {
239        valmr |= TDES_MR_OPMOD_CBC;
240    } else if (dd->flags & TDES_FLAGS_CFB) {
241        valmr |= TDES_MR_OPMOD_CFB;
242
243        if (dd->flags & TDES_FLAGS_CFB8)
244            valmr |= TDES_MR_CFBS_8b;
245        else if (dd->flags & TDES_FLAGS_CFB16)
246            valmr |= TDES_MR_CFBS_16b;
247        else if (dd->flags & TDES_FLAGS_CFB32)
248            valmr |= TDES_MR_CFBS_32b;
249    } else if (dd->flags & TDES_FLAGS_OFB) {
250        valmr |= TDES_MR_OPMOD_OFB;
251    }
252
253    if ((dd->flags & TDES_FLAGS_ENCRYPT) || (dd->flags & TDES_FLAGS_OFB))
254        valmr |= TDES_MR_CYPHER_ENC;
255
256    atmel_tdes_write(dd, TDES_CR, valcr);
257    atmel_tdes_write(dd, TDES_MR, valmr);
258
259    atmel_tdes_write_n(dd, TDES_KEY1W1R, dd->ctx->key,
260                        dd->ctx->keylen >> 2);
261
262    if (((dd->flags & TDES_FLAGS_CBC) || (dd->flags & TDES_FLAGS_CFB) ||
263        (dd->flags & TDES_FLAGS_OFB)) && dd->req->info) {
264        atmel_tdes_write_n(dd, TDES_IV1R, dd->req->info, 2);
265    }
266
267    return 0;
268}
269
270static int atmel_tdes_crypt_dma_stop(struct atmel_tdes_dev *dd)
271{
272    int err = 0;
273    size_t count;
274
275    atmel_tdes_write(dd, TDES_PTCR, TDES_PTCR_TXTDIS|TDES_PTCR_RXTDIS);
276
277    if (dd->flags & TDES_FLAGS_FAST) {
278        dma_unmap_sg(dd->dev, dd->out_sg, 1, DMA_FROM_DEVICE);
279        dma_unmap_sg(dd->dev, dd->in_sg, 1, DMA_TO_DEVICE);
280    } else {
281        dma_sync_single_for_device(dd->dev, dd->dma_addr_out,
282                       dd->dma_size, DMA_FROM_DEVICE);
283
284        /* copy data */
285        count = atmel_tdes_sg_copy(&dd->out_sg, &dd->out_offset,
286                dd->buf_out, dd->buflen, dd->dma_size, 1);
287        if (count != dd->dma_size) {
288            err = -EINVAL;
289            pr_err("not all data converted: %u\n", count);
290        }
291    }
292
293    return err;
294}
295
296static int atmel_tdes_dma_init(struct atmel_tdes_dev *dd)
297{
298    int err = -ENOMEM;
299
300    dd->buf_in = (void *)__get_free_pages(GFP_KERNEL, 0);
301    dd->buf_out = (void *)__get_free_pages(GFP_KERNEL, 0);
302    dd->buflen = PAGE_SIZE;
303    dd->buflen &= ~(DES_BLOCK_SIZE - 1);
304
305    if (!dd->buf_in || !dd->buf_out) {
306        dev_err(dd->dev, "unable to alloc pages.\n");
307        goto err_alloc;
308    }
309
310    /* MAP here */
311    dd->dma_addr_in = dma_map_single(dd->dev, dd->buf_in,
312                    dd->buflen, DMA_TO_DEVICE);
313    if (dma_mapping_error(dd->dev, dd->dma_addr_in)) {
314        dev_err(dd->dev, "dma %d bytes error\n", dd->buflen);
315        err = -EINVAL;
316        goto err_map_in;
317    }
318
319    dd->dma_addr_out = dma_map_single(dd->dev, dd->buf_out,
320                    dd->buflen, DMA_FROM_DEVICE);
321    if (dma_mapping_error(dd->dev, dd->dma_addr_out)) {
322        dev_err(dd->dev, "dma %d bytes error\n", dd->buflen);
323        err = -EINVAL;
324        goto err_map_out;
325    }
326
327    return 0;
328
329err_map_out:
330    dma_unmap_single(dd->dev, dd->dma_addr_in, dd->buflen,
331        DMA_TO_DEVICE);
332err_map_in:
333    free_page((unsigned long)dd->buf_out);
334    free_page((unsigned long)dd->buf_in);
335err_alloc:
336    if (err)
337        pr_err("error: %d\n", err);
338    return err;
339}
340
341static void atmel_tdes_dma_cleanup(struct atmel_tdes_dev *dd)
342{
343    dma_unmap_single(dd->dev, dd->dma_addr_out, dd->buflen,
344             DMA_FROM_DEVICE);
345    dma_unmap_single(dd->dev, dd->dma_addr_in, dd->buflen,
346        DMA_TO_DEVICE);
347    free_page((unsigned long)dd->buf_out);
348    free_page((unsigned long)dd->buf_in);
349}
350
351static int atmel_tdes_crypt_dma(struct crypto_tfm *tfm, dma_addr_t dma_addr_in,
352                   dma_addr_t dma_addr_out, int length)
353{
354    struct atmel_tdes_ctx *ctx = crypto_tfm_ctx(tfm);
355    struct atmel_tdes_dev *dd = ctx->dd;
356    int len32;
357
358    dd->dma_size = length;
359
360    if (!(dd->flags & TDES_FLAGS_FAST)) {
361        dma_sync_single_for_device(dd->dev, dma_addr_in, length,
362                       DMA_TO_DEVICE);
363    }
364
365    if ((dd->flags & TDES_FLAGS_CFB) && (dd->flags & TDES_FLAGS_CFB8))
366        len32 = DIV_ROUND_UP(length, sizeof(u8));
367    else if ((dd->flags & TDES_FLAGS_CFB) && (dd->flags & TDES_FLAGS_CFB16))
368        len32 = DIV_ROUND_UP(length, sizeof(u16));
369    else
370        len32 = DIV_ROUND_UP(length, sizeof(u32));
371
372    atmel_tdes_write(dd, TDES_PTCR, TDES_PTCR_TXTDIS|TDES_PTCR_RXTDIS);
373    atmel_tdes_write(dd, TDES_TPR, dma_addr_in);
374    atmel_tdes_write(dd, TDES_TCR, len32);
375    atmel_tdes_write(dd, TDES_RPR, dma_addr_out);
376    atmel_tdes_write(dd, TDES_RCR, len32);
377
378    /* Enable Interrupt */
379    atmel_tdes_write(dd, TDES_IER, TDES_INT_ENDRX);
380
381    /* Start DMA transfer */
382    atmel_tdes_write(dd, TDES_PTCR, TDES_PTCR_TXTEN | TDES_PTCR_RXTEN);
383
384    return 0;
385}
386
387static int atmel_tdes_crypt_dma_start(struct atmel_tdes_dev *dd)
388{
389    struct crypto_tfm *tfm = crypto_ablkcipher_tfm(
390                    crypto_ablkcipher_reqtfm(dd->req));
391    int err, fast = 0, in, out;
392    size_t count;
393    dma_addr_t addr_in, addr_out;
394
395    if (sg_is_last(dd->in_sg) && sg_is_last(dd->out_sg)) {
396        /* check for alignment */
397        in = IS_ALIGNED((u32)dd->in_sg->offset, sizeof(u32));
398        out = IS_ALIGNED((u32)dd->out_sg->offset, sizeof(u32));
399
400        fast = in && out;
401    }
402
403    if (fast) {
404        count = min(dd->total, sg_dma_len(dd->in_sg));
405        count = min(count, sg_dma_len(dd->out_sg));
406
407        if (count != dd->total) {
408            pr_err("request length != buffer length\n");
409            return -EINVAL;
410        }
411
412        err = dma_map_sg(dd->dev, dd->in_sg, 1, DMA_TO_DEVICE);
413        if (!err) {
414            dev_err(dd->dev, "dma_map_sg() error\n");
415            return -EINVAL;
416        }
417
418        err = dma_map_sg(dd->dev, dd->out_sg, 1,
419                DMA_FROM_DEVICE);
420        if (!err) {
421            dev_err(dd->dev, "dma_map_sg() error\n");
422            dma_unmap_sg(dd->dev, dd->in_sg, 1,
423                DMA_TO_DEVICE);
424            return -EINVAL;
425        }
426
427        addr_in = sg_dma_address(dd->in_sg);
428        addr_out = sg_dma_address(dd->out_sg);
429
430        dd->flags |= TDES_FLAGS_FAST;
431
432    } else {
433        /* use cache buffers */
434        count = atmel_tdes_sg_copy(&dd->in_sg, &dd->in_offset,
435                dd->buf_in, dd->buflen, dd->total, 0);
436
437        addr_in = dd->dma_addr_in;
438        addr_out = dd->dma_addr_out;
439
440        dd->flags &= ~TDES_FLAGS_FAST;
441
442    }
443
444    dd->total -= count;
445
446    err = atmel_tdes_crypt_dma(tfm, addr_in, addr_out, count);
447    if (err) {
448        dma_unmap_sg(dd->dev, dd->in_sg, 1, DMA_TO_DEVICE);
449        dma_unmap_sg(dd->dev, dd->out_sg, 1, DMA_TO_DEVICE);
450    }
451
452    return err;
453}
454
455
456static void atmel_tdes_finish_req(struct atmel_tdes_dev *dd, int err)
457{
458    struct ablkcipher_request *req = dd->req;
459
460    clk_disable_unprepare(dd->iclk);
461
462    dd->flags &= ~TDES_FLAGS_BUSY;
463
464    req->base.complete(&req->base, err);
465}
466
467static int atmel_tdes_handle_queue(struct atmel_tdes_dev *dd,
468                   struct ablkcipher_request *req)
469{
470    struct crypto_async_request *async_req, *backlog;
471    struct atmel_tdes_ctx *ctx;
472    struct atmel_tdes_reqctx *rctx;
473    unsigned long flags;
474    int err, ret = 0;
475
476    spin_lock_irqsave(&dd->lock, flags);
477    if (req)
478        ret = ablkcipher_enqueue_request(&dd->queue, req);
479    if (dd->flags & TDES_FLAGS_BUSY) {
480        spin_unlock_irqrestore(&dd->lock, flags);
481        return ret;
482    }
483    backlog = crypto_get_backlog(&dd->queue);
484    async_req = crypto_dequeue_request(&dd->queue);
485    if (async_req)
486        dd->flags |= TDES_FLAGS_BUSY;
487    spin_unlock_irqrestore(&dd->lock, flags);
488
489    if (!async_req)
490        return ret;
491
492    if (backlog)
493        backlog->complete(backlog, -EINPROGRESS);
494
495    req = ablkcipher_request_cast(async_req);
496
497    /* assign new request to device */
498    dd->req = req;
499    dd->total = req->nbytes;
500    dd->in_offset = 0;
501    dd->in_sg = req->src;
502    dd->out_offset = 0;
503    dd->out_sg = req->dst;
504
505    rctx = ablkcipher_request_ctx(req);
506    ctx = crypto_ablkcipher_ctx(crypto_ablkcipher_reqtfm(req));
507    rctx->mode &= TDES_FLAGS_MODE_MASK;
508    dd->flags = (dd->flags & ~TDES_FLAGS_MODE_MASK) | rctx->mode;
509    dd->ctx = ctx;
510    ctx->dd = dd;
511
512    err = atmel_tdes_write_ctrl(dd);
513    if (!err)
514        err = atmel_tdes_crypt_dma_start(dd);
515    if (err) {
516        /* des_task will not finish it, so do it here */
517        atmel_tdes_finish_req(dd, err);
518        tasklet_schedule(&dd->queue_task);
519    }
520
521    return ret;
522}
523
524
525static int atmel_tdes_crypt(struct ablkcipher_request *req, unsigned long mode)
526{
527    struct atmel_tdes_ctx *ctx = crypto_ablkcipher_ctx(
528            crypto_ablkcipher_reqtfm(req));
529    struct atmel_tdes_reqctx *rctx = ablkcipher_request_ctx(req);
530    struct atmel_tdes_dev *dd;
531
532    if (mode & TDES_FLAGS_CFB8) {
533        if (!IS_ALIGNED(req->nbytes, CFB8_BLOCK_SIZE)) {
534            pr_err("request size is not exact amount of CFB8 blocks\n");
535            return -EINVAL;
536        }
537    } else if (mode & TDES_FLAGS_CFB16) {
538        if (!IS_ALIGNED(req->nbytes, CFB16_BLOCK_SIZE)) {
539            pr_err("request size is not exact amount of CFB16 blocks\n");
540            return -EINVAL;
541        }
542    } else if (mode & TDES_FLAGS_CFB32) {
543        if (!IS_ALIGNED(req->nbytes, CFB32_BLOCK_SIZE)) {
544            pr_err("request size is not exact amount of CFB32 blocks\n");
545            return -EINVAL;
546        }
547    } else if (!IS_ALIGNED(req->nbytes, DES_BLOCK_SIZE)) {
548        pr_err("request size is not exact amount of DES blocks\n");
549        return -EINVAL;
550    }
551
552    dd = atmel_tdes_find_dev(ctx);
553    if (!dd)
554        return -ENODEV;
555
556    rctx->mode = mode;
557
558    return atmel_tdes_handle_queue(dd, req);
559}
560
561static int atmel_des_setkey(struct crypto_ablkcipher *tfm, const u8 *key,
562               unsigned int keylen)
563{
564    u32 tmp[DES_EXPKEY_WORDS];
565    int err;
566    struct crypto_tfm *ctfm = crypto_ablkcipher_tfm(tfm);
567
568    struct atmel_tdes_ctx *ctx = crypto_ablkcipher_ctx(tfm);
569
570    if (keylen != DES_KEY_SIZE) {
571        crypto_ablkcipher_set_flags(tfm, CRYPTO_TFM_RES_BAD_KEY_LEN);
572        return -EINVAL;
573    }
574
575    err = des_ekey(tmp, key);
576    if (err == 0 && (ctfm->crt_flags & CRYPTO_TFM_REQ_WEAK_KEY)) {
577        ctfm->crt_flags |= CRYPTO_TFM_RES_WEAK_KEY;
578        return -EINVAL;
579    }
580
581    memcpy(ctx->key, key, keylen);
582    ctx->keylen = keylen;
583
584    return 0;
585}
586
587static int atmel_tdes_setkey(struct crypto_ablkcipher *tfm, const u8 *key,
588               unsigned int keylen)
589{
590    struct atmel_tdes_ctx *ctx = crypto_ablkcipher_ctx(tfm);
591    const char *alg_name;
592
593    alg_name = crypto_tfm_alg_name(crypto_ablkcipher_tfm(tfm));
594
595    /*
596     * HW bug in cfb 3-keys mode.
597     */
598    if (strstr(alg_name, "cfb") && (keylen != 2*DES_KEY_SIZE)) {
599        crypto_ablkcipher_set_flags(tfm, CRYPTO_TFM_RES_BAD_KEY_LEN);
600        return -EINVAL;
601    } else if ((keylen != 2*DES_KEY_SIZE) && (keylen != 3*DES_KEY_SIZE)) {
602        crypto_ablkcipher_set_flags(tfm, CRYPTO_TFM_RES_BAD_KEY_LEN);
603        return -EINVAL;
604    }
605
606    memcpy(ctx->key, key, keylen);
607    ctx->keylen = keylen;
608
609    return 0;
610}
611
612static int atmel_tdes_ecb_encrypt(struct ablkcipher_request *req)
613{
614    return atmel_tdes_crypt(req, TDES_FLAGS_ENCRYPT);
615}
616
617static int atmel_tdes_ecb_decrypt(struct ablkcipher_request *req)
618{
619    return atmel_tdes_crypt(req, 0);
620}
621
622static int atmel_tdes_cbc_encrypt(struct ablkcipher_request *req)
623{
624    return atmel_tdes_crypt(req, TDES_FLAGS_ENCRYPT | TDES_FLAGS_CBC);
625}
626
627static int atmel_tdes_cbc_decrypt(struct ablkcipher_request *req)
628{
629    return atmel_tdes_crypt(req, TDES_FLAGS_CBC);
630}
631static int atmel_tdes_cfb_encrypt(struct ablkcipher_request *req)
632{
633    return atmel_tdes_crypt(req, TDES_FLAGS_ENCRYPT | TDES_FLAGS_CFB);
634}
635
636static int atmel_tdes_cfb_decrypt(struct ablkcipher_request *req)
637{
638    return atmel_tdes_crypt(req, TDES_FLAGS_CFB);
639}
640
641static int atmel_tdes_cfb8_encrypt(struct ablkcipher_request *req)
642{
643    return atmel_tdes_crypt(req, TDES_FLAGS_ENCRYPT | TDES_FLAGS_CFB |
644                        TDES_FLAGS_CFB8);
645}
646
647static int atmel_tdes_cfb8_decrypt(struct ablkcipher_request *req)
648{
649    return atmel_tdes_crypt(req, TDES_FLAGS_CFB | TDES_FLAGS_CFB8);
650}
651
652static int atmel_tdes_cfb16_encrypt(struct ablkcipher_request *req)
653{
654    return atmel_tdes_crypt(req, TDES_FLAGS_ENCRYPT | TDES_FLAGS_CFB |
655                        TDES_FLAGS_CFB16);
656}
657
658static int atmel_tdes_cfb16_decrypt(struct ablkcipher_request *req)
659{
660    return atmel_tdes_crypt(req, TDES_FLAGS_CFB | TDES_FLAGS_CFB16);
661}
662
663static int atmel_tdes_cfb32_encrypt(struct ablkcipher_request *req)
664{
665    return atmel_tdes_crypt(req, TDES_FLAGS_ENCRYPT | TDES_FLAGS_CFB |
666                        TDES_FLAGS_CFB32);
667}
668
669static int atmel_tdes_cfb32_decrypt(struct ablkcipher_request *req)
670{
671    return atmel_tdes_crypt(req, TDES_FLAGS_CFB | TDES_FLAGS_CFB32);
672}
673
674static int atmel_tdes_ofb_encrypt(struct ablkcipher_request *req)
675{
676    return atmel_tdes_crypt(req, TDES_FLAGS_ENCRYPT | TDES_FLAGS_OFB);
677}
678
679static int atmel_tdes_ofb_decrypt(struct ablkcipher_request *req)
680{
681    return atmel_tdes_crypt(req, TDES_FLAGS_OFB);
682}
683
684static int atmel_tdes_cra_init(struct crypto_tfm *tfm)
685{
686    tfm->crt_ablkcipher.reqsize = sizeof(struct atmel_tdes_reqctx);
687
688    return 0;
689}
690
691static void atmel_tdes_cra_exit(struct crypto_tfm *tfm)
692{
693}
694
695static struct crypto_alg tdes_algs[] = {
696{
697    .cra_name = "ecb(des)",
698    .cra_driver_name = "atmel-ecb-des",
699    .cra_priority = 100,
700    .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
701    .cra_blocksize = DES_BLOCK_SIZE,
702    .cra_ctxsize = sizeof(struct atmel_tdes_ctx),
703    .cra_alignmask = 0,
704    .cra_type = &crypto_ablkcipher_type,
705    .cra_module = THIS_MODULE,
706    .cra_init = atmel_tdes_cra_init,
707    .cra_exit = atmel_tdes_cra_exit,
708    .cra_u.ablkcipher = {
709        .min_keysize = DES_KEY_SIZE,
710        .max_keysize = DES_KEY_SIZE,
711        .setkey = atmel_des_setkey,
712        .encrypt = atmel_tdes_ecb_encrypt,
713        .decrypt = atmel_tdes_ecb_decrypt,
714    }
715},
716{
717    .cra_name = "cbc(des)",
718    .cra_driver_name = "atmel-cbc-des",
719    .cra_priority = 100,
720    .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
721    .cra_blocksize = DES_BLOCK_SIZE,
722    .cra_ctxsize = sizeof(struct atmel_tdes_ctx),
723    .cra_alignmask = 0,
724    .cra_type = &crypto_ablkcipher_type,
725    .cra_module = THIS_MODULE,
726    .cra_init = atmel_tdes_cra_init,
727    .cra_exit = atmel_tdes_cra_exit,
728    .cra_u.ablkcipher = {
729        .min_keysize = DES_KEY_SIZE,
730        .max_keysize = DES_KEY_SIZE,
731        .ivsize = DES_BLOCK_SIZE,
732        .setkey = atmel_des_setkey,
733        .encrypt = atmel_tdes_cbc_encrypt,
734        .decrypt = atmel_tdes_cbc_decrypt,
735    }
736},
737{
738    .cra_name = "cfb(des)",
739    .cra_driver_name = "atmel-cfb-des",
740    .cra_priority = 100,
741    .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
742    .cra_blocksize = DES_BLOCK_SIZE,
743    .cra_ctxsize = sizeof(struct atmel_tdes_ctx),
744    .cra_alignmask = 0,
745    .cra_type = &crypto_ablkcipher_type,
746    .cra_module = THIS_MODULE,
747    .cra_init = atmel_tdes_cra_init,
748    .cra_exit = atmel_tdes_cra_exit,
749    .cra_u.ablkcipher = {
750        .min_keysize = DES_KEY_SIZE,
751        .max_keysize = DES_KEY_SIZE,
752        .ivsize = DES_BLOCK_SIZE,
753        .setkey = atmel_des_setkey,
754        .encrypt = atmel_tdes_cfb_encrypt,
755        .decrypt = atmel_tdes_cfb_decrypt,
756    }
757},
758{
759    .cra_name = "cfb8(des)",
760    .cra_driver_name = "atmel-cfb8-des",
761    .cra_priority = 100,
762    .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
763    .cra_blocksize = CFB8_BLOCK_SIZE,
764    .cra_ctxsize = sizeof(struct atmel_tdes_ctx),
765    .cra_alignmask = 0,
766    .cra_type = &crypto_ablkcipher_type,
767    .cra_module = THIS_MODULE,
768    .cra_init = atmel_tdes_cra_init,
769    .cra_exit = atmel_tdes_cra_exit,
770    .cra_u.ablkcipher = {
771        .min_keysize = DES_KEY_SIZE,
772        .max_keysize = DES_KEY_SIZE,
773        .ivsize = DES_BLOCK_SIZE,
774        .setkey = atmel_des_setkey,
775        .encrypt = atmel_tdes_cfb8_encrypt,
776        .decrypt = atmel_tdes_cfb8_decrypt,
777    }
778},
779{
780    .cra_name = "cfb16(des)",
781    .cra_driver_name = "atmel-cfb16-des",
782    .cra_priority = 100,
783    .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
784    .cra_blocksize = CFB16_BLOCK_SIZE,
785    .cra_ctxsize = sizeof(struct atmel_tdes_ctx),
786    .cra_alignmask = 0,
787    .cra_type = &crypto_ablkcipher_type,
788    .cra_module = THIS_MODULE,
789    .cra_init = atmel_tdes_cra_init,
790    .cra_exit = atmel_tdes_cra_exit,
791    .cra_u.ablkcipher = {
792        .min_keysize = DES_KEY_SIZE,
793        .max_keysize = DES_KEY_SIZE,
794        .ivsize = DES_BLOCK_SIZE,
795        .setkey = atmel_des_setkey,
796        .encrypt = atmel_tdes_cfb16_encrypt,
797        .decrypt = atmel_tdes_cfb16_decrypt,
798    }
799},
800{
801    .cra_name = "cfb32(des)",
802    .cra_driver_name = "atmel-cfb32-des",
803    .cra_priority = 100,
804    .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
805    .cra_blocksize = CFB32_BLOCK_SIZE,
806    .cra_ctxsize = sizeof(struct atmel_tdes_ctx),
807    .cra_alignmask = 0,
808    .cra_type = &crypto_ablkcipher_type,
809    .cra_module = THIS_MODULE,
810    .cra_init = atmel_tdes_cra_init,
811    .cra_exit = atmel_tdes_cra_exit,
812    .cra_u.ablkcipher = {
813        .min_keysize = DES_KEY_SIZE,
814        .max_keysize = DES_KEY_SIZE,
815        .ivsize = DES_BLOCK_SIZE,
816        .setkey = atmel_des_setkey,
817        .encrypt = atmel_tdes_cfb32_encrypt,
818        .decrypt = atmel_tdes_cfb32_decrypt,
819    }
820},
821{
822    .cra_name = "ofb(des)",
823    .cra_driver_name = "atmel-ofb-des",
824    .cra_priority = 100,
825    .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
826    .cra_blocksize = DES_BLOCK_SIZE,
827    .cra_ctxsize = sizeof(struct atmel_tdes_ctx),
828    .cra_alignmask = 0,
829    .cra_type = &crypto_ablkcipher_type,
830    .cra_module = THIS_MODULE,
831    .cra_init = atmel_tdes_cra_init,
832    .cra_exit = atmel_tdes_cra_exit,
833    .cra_u.ablkcipher = {
834        .min_keysize = DES_KEY_SIZE,
835        .max_keysize = DES_KEY_SIZE,
836        .ivsize = DES_BLOCK_SIZE,
837        .setkey = atmel_des_setkey,
838        .encrypt = atmel_tdes_ofb_encrypt,
839        .decrypt = atmel_tdes_ofb_decrypt,
840    }
841},
842{
843    .cra_name = "ecb(des3_ede)",
844    .cra_driver_name = "atmel-ecb-tdes",
845    .cra_priority = 100,
846    .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
847    .cra_blocksize = DES_BLOCK_SIZE,
848    .cra_ctxsize = sizeof(struct atmel_tdes_ctx),
849    .cra_alignmask = 0,
850    .cra_type = &crypto_ablkcipher_type,
851    .cra_module = THIS_MODULE,
852    .cra_init = atmel_tdes_cra_init,
853    .cra_exit = atmel_tdes_cra_exit,
854    .cra_u.ablkcipher = {
855        .min_keysize = 2 * DES_KEY_SIZE,
856        .max_keysize = 3 * DES_KEY_SIZE,
857        .setkey = atmel_tdes_setkey,
858        .encrypt = atmel_tdes_ecb_encrypt,
859        .decrypt = atmel_tdes_ecb_decrypt,
860    }
861},
862{
863    .cra_name = "cbc(des3_ede)",
864    .cra_driver_name = "atmel-cbc-tdes",
865    .cra_priority = 100,
866    .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
867    .cra_blocksize = DES_BLOCK_SIZE,
868    .cra_ctxsize = sizeof(struct atmel_tdes_ctx),
869    .cra_alignmask = 0,
870    .cra_type = &crypto_ablkcipher_type,
871    .cra_module = THIS_MODULE,
872    .cra_init = atmel_tdes_cra_init,
873    .cra_exit = atmel_tdes_cra_exit,
874    .cra_u.ablkcipher = {
875        .min_keysize = 2*DES_KEY_SIZE,
876        .max_keysize = 3*DES_KEY_SIZE,
877        .ivsize = DES_BLOCK_SIZE,
878        .setkey = atmel_tdes_setkey,
879        .encrypt = atmel_tdes_cbc_encrypt,
880        .decrypt = atmel_tdes_cbc_decrypt,
881    }
882},
883{
884    .cra_name = "cfb(des3_ede)",
885    .cra_driver_name = "atmel-cfb-tdes",
886    .cra_priority = 100,
887    .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
888    .cra_blocksize = DES_BLOCK_SIZE,
889    .cra_ctxsize = sizeof(struct atmel_tdes_ctx),
890    .cra_alignmask = 0,
891    .cra_type = &crypto_ablkcipher_type,
892    .cra_module = THIS_MODULE,
893    .cra_init = atmel_tdes_cra_init,
894    .cra_exit = atmel_tdes_cra_exit,
895    .cra_u.ablkcipher = {
896        .min_keysize = 2*DES_KEY_SIZE,
897        .max_keysize = 2*DES_KEY_SIZE,
898        .ivsize = DES_BLOCK_SIZE,
899        .setkey = atmel_tdes_setkey,
900        .encrypt = atmel_tdes_cfb_encrypt,
901        .decrypt = atmel_tdes_cfb_decrypt,
902    }
903},
904{
905    .cra_name = "cfb8(des3_ede)",
906    .cra_driver_name = "atmel-cfb8-tdes",
907    .cra_priority = 100,
908    .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
909    .cra_blocksize = CFB8_BLOCK_SIZE,
910    .cra_ctxsize = sizeof(struct atmel_tdes_ctx),
911    .cra_alignmask = 0,
912    .cra_type = &crypto_ablkcipher_type,
913    .cra_module = THIS_MODULE,
914    .cra_init = atmel_tdes_cra_init,
915    .cra_exit = atmel_tdes_cra_exit,
916    .cra_u.ablkcipher = {
917        .min_keysize = 2*DES_KEY_SIZE,
918        .max_keysize = 2*DES_KEY_SIZE,
919        .ivsize = DES_BLOCK_SIZE,
920        .setkey = atmel_tdes_setkey,
921        .encrypt = atmel_tdes_cfb8_encrypt,
922        .decrypt = atmel_tdes_cfb8_decrypt,
923    }
924},
925{
926    .cra_name = "cfb16(des3_ede)",
927    .cra_driver_name = "atmel-cfb16-tdes",
928    .cra_priority = 100,
929    .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
930    .cra_blocksize = CFB16_BLOCK_SIZE,
931    .cra_ctxsize = sizeof(struct atmel_tdes_ctx),
932    .cra_alignmask = 0,
933    .cra_type = &crypto_ablkcipher_type,
934    .cra_module = THIS_MODULE,
935    .cra_init = atmel_tdes_cra_init,
936    .cra_exit = atmel_tdes_cra_exit,
937    .cra_u.ablkcipher = {
938        .min_keysize = 2*DES_KEY_SIZE,
939        .max_keysize = 2*DES_KEY_SIZE,
940        .ivsize = DES_BLOCK_SIZE,
941        .setkey = atmel_tdes_setkey,
942        .encrypt = atmel_tdes_cfb16_encrypt,
943        .decrypt = atmel_tdes_cfb16_decrypt,
944    }
945},
946{
947    .cra_name = "cfb32(des3_ede)",
948    .cra_driver_name = "atmel-cfb32-tdes",
949    .cra_priority = 100,
950    .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
951    .cra_blocksize = CFB32_BLOCK_SIZE,
952    .cra_ctxsize = sizeof(struct atmel_tdes_ctx),
953    .cra_alignmask = 0,
954    .cra_type = &crypto_ablkcipher_type,
955    .cra_module = THIS_MODULE,
956    .cra_init = atmel_tdes_cra_init,
957    .cra_exit = atmel_tdes_cra_exit,
958    .cra_u.ablkcipher = {
959        .min_keysize = 2*DES_KEY_SIZE,
960        .max_keysize = 2*DES_KEY_SIZE,
961        .ivsize = DES_BLOCK_SIZE,
962        .setkey = atmel_tdes_setkey,
963        .encrypt = atmel_tdes_cfb32_encrypt,
964        .decrypt = atmel_tdes_cfb32_decrypt,
965    }
966},
967{
968    .cra_name = "ofb(des3_ede)",
969    .cra_driver_name = "atmel-ofb-tdes",
970    .cra_priority = 100,
971    .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
972    .cra_blocksize = DES_BLOCK_SIZE,
973    .cra_ctxsize = sizeof(struct atmel_tdes_ctx),
974    .cra_alignmask = 0,
975    .cra_type = &crypto_ablkcipher_type,
976    .cra_module = THIS_MODULE,
977    .cra_init = atmel_tdes_cra_init,
978    .cra_exit = atmel_tdes_cra_exit,
979    .cra_u.ablkcipher = {
980        .min_keysize = 2*DES_KEY_SIZE,
981        .max_keysize = 3*DES_KEY_SIZE,
982        .ivsize = DES_BLOCK_SIZE,
983        .setkey = atmel_tdes_setkey,
984        .encrypt = atmel_tdes_ofb_encrypt,
985        .decrypt = atmel_tdes_ofb_decrypt,
986    }
987},
988};
989
990static void atmel_tdes_queue_task(unsigned long data)
991{
992    struct atmel_tdes_dev *dd = (struct atmel_tdes_dev *)data;
993
994    atmel_tdes_handle_queue(dd, NULL);
995}
996
997static void atmel_tdes_done_task(unsigned long data)
998{
999    struct atmel_tdes_dev *dd = (struct atmel_tdes_dev *) data;
1000    int err;
1001
1002    err = atmel_tdes_crypt_dma_stop(dd);
1003
1004    err = dd->err ? : err;
1005
1006    if (dd->total && !err) {
1007        err = atmel_tdes_crypt_dma_start(dd);
1008        if (!err)
1009            return;
1010    }
1011
1012    atmel_tdes_finish_req(dd, err);
1013    atmel_tdes_handle_queue(dd, NULL);
1014}
1015
1016static irqreturn_t atmel_tdes_irq(int irq, void *dev_id)
1017{
1018    struct atmel_tdes_dev *tdes_dd = dev_id;
1019    u32 reg;
1020
1021    reg = atmel_tdes_read(tdes_dd, TDES_ISR);
1022    if (reg & atmel_tdes_read(tdes_dd, TDES_IMR)) {
1023        atmel_tdes_write(tdes_dd, TDES_IDR, reg);
1024        if (TDES_FLAGS_BUSY & tdes_dd->flags)
1025            tasklet_schedule(&tdes_dd->done_task);
1026        else
1027            dev_warn(tdes_dd->dev, "TDES interrupt when no active requests.\n");
1028        return IRQ_HANDLED;
1029    }
1030
1031    return IRQ_NONE;
1032}
1033
1034static void atmel_tdes_unregister_algs(struct atmel_tdes_dev *dd)
1035{
1036    int i;
1037
1038    for (i = 0; i < ARRAY_SIZE(tdes_algs); i++)
1039        crypto_unregister_alg(&tdes_algs[i]);
1040}
1041
1042static int atmel_tdes_register_algs(struct atmel_tdes_dev *dd)
1043{
1044    int err, i, j;
1045
1046    for (i = 0; i < ARRAY_SIZE(tdes_algs); i++) {
1047        INIT_LIST_HEAD(&tdes_algs[i].cra_list);
1048        err = crypto_register_alg(&tdes_algs[i]);
1049        if (err)
1050            goto err_tdes_algs;
1051    }
1052
1053    return 0;
1054
1055err_tdes_algs:
1056    for (j = 0; j < i; j++)
1057        crypto_unregister_alg(&tdes_algs[j]);
1058
1059    return err;
1060}
1061
1062static int __devinit atmel_tdes_probe(struct platform_device *pdev)
1063{
1064    struct atmel_tdes_dev *tdes_dd;
1065    struct device *dev = &pdev->dev;
1066    struct resource *tdes_res;
1067    unsigned long tdes_phys_size;
1068    int err;
1069
1070    tdes_dd = kzalloc(sizeof(struct atmel_tdes_dev), GFP_KERNEL);
1071    if (tdes_dd == NULL) {
1072        dev_err(dev, "unable to alloc data struct.\n");
1073        err = -ENOMEM;
1074        goto tdes_dd_err;
1075    }
1076
1077    tdes_dd->dev = dev;
1078
1079    platform_set_drvdata(pdev, tdes_dd);
1080
1081    INIT_LIST_HEAD(&tdes_dd->list);
1082
1083    tasklet_init(&tdes_dd->done_task, atmel_tdes_done_task,
1084                    (unsigned long)tdes_dd);
1085    tasklet_init(&tdes_dd->queue_task, atmel_tdes_queue_task,
1086                    (unsigned long)tdes_dd);
1087
1088    crypto_init_queue(&tdes_dd->queue, ATMEL_TDES_QUEUE_LENGTH);
1089
1090    tdes_dd->irq = -1;
1091
1092    /* Get the base address */
1093    tdes_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1094    if (!tdes_res) {
1095        dev_err(dev, "no MEM resource info\n");
1096        err = -ENODEV;
1097        goto res_err;
1098    }
1099    tdes_dd->phys_base = tdes_res->start;
1100    tdes_phys_size = resource_size(tdes_res);
1101
1102    /* Get the IRQ */
1103    tdes_dd->irq = platform_get_irq(pdev, 0);
1104    if (tdes_dd->irq < 0) {
1105        dev_err(dev, "no IRQ resource info\n");
1106        err = tdes_dd->irq;
1107        goto res_err;
1108    }
1109
1110    err = request_irq(tdes_dd->irq, atmel_tdes_irq, IRQF_SHARED,
1111            "atmel-tdes", tdes_dd);
1112    if (err) {
1113        dev_err(dev, "unable to request tdes irq.\n");
1114        goto tdes_irq_err;
1115    }
1116
1117    /* Initializing the clock */
1118    tdes_dd->iclk = clk_get(&pdev->dev, NULL);
1119    if (IS_ERR(tdes_dd->iclk)) {
1120        dev_err(dev, "clock intialization failed.\n");
1121        err = PTR_ERR(tdes_dd->iclk);
1122        goto clk_err;
1123    }
1124
1125    tdes_dd->io_base = ioremap(tdes_dd->phys_base, tdes_phys_size);
1126    if (!tdes_dd->io_base) {
1127        dev_err(dev, "can't ioremap\n");
1128        err = -ENOMEM;
1129        goto tdes_io_err;
1130    }
1131
1132    err = atmel_tdes_dma_init(tdes_dd);
1133    if (err)
1134        goto err_tdes_dma;
1135
1136    spin_lock(&atmel_tdes.lock);
1137    list_add_tail(&tdes_dd->list, &atmel_tdes.dev_list);
1138    spin_unlock(&atmel_tdes.lock);
1139
1140    err = atmel_tdes_register_algs(tdes_dd);
1141    if (err)
1142        goto err_algs;
1143
1144    dev_info(dev, "Atmel DES/TDES\n");
1145
1146    return 0;
1147
1148err_algs:
1149    spin_lock(&atmel_tdes.lock);
1150    list_del(&tdes_dd->list);
1151    spin_unlock(&atmel_tdes.lock);
1152    atmel_tdes_dma_cleanup(tdes_dd);
1153err_tdes_dma:
1154    iounmap(tdes_dd->io_base);
1155tdes_io_err:
1156    clk_put(tdes_dd->iclk);
1157clk_err:
1158    free_irq(tdes_dd->irq, tdes_dd);
1159tdes_irq_err:
1160res_err:
1161    tasklet_kill(&tdes_dd->done_task);
1162    tasklet_kill(&tdes_dd->queue_task);
1163    kfree(tdes_dd);
1164    tdes_dd = NULL;
1165tdes_dd_err:
1166    dev_err(dev, "initialization failed.\n");
1167
1168    return err;
1169}
1170
1171static int __devexit atmel_tdes_remove(struct platform_device *pdev)
1172{
1173    static struct atmel_tdes_dev *tdes_dd;
1174
1175    tdes_dd = platform_get_drvdata(pdev);
1176    if (!tdes_dd)
1177        return -ENODEV;
1178    spin_lock(&atmel_tdes.lock);
1179    list_del(&tdes_dd->list);
1180    spin_unlock(&atmel_tdes.lock);
1181
1182    atmel_tdes_unregister_algs(tdes_dd);
1183
1184    tasklet_kill(&tdes_dd->done_task);
1185    tasklet_kill(&tdes_dd->queue_task);
1186
1187    atmel_tdes_dma_cleanup(tdes_dd);
1188
1189    iounmap(tdes_dd->io_base);
1190
1191    clk_put(tdes_dd->iclk);
1192
1193    if (tdes_dd->irq >= 0)
1194        free_irq(tdes_dd->irq, tdes_dd);
1195
1196    kfree(tdes_dd);
1197    tdes_dd = NULL;
1198
1199    return 0;
1200}
1201
1202static struct platform_driver atmel_tdes_driver = {
1203    .probe = atmel_tdes_probe,
1204    .remove = __devexit_p(atmel_tdes_remove),
1205    .driver = {
1206        .name = "atmel_tdes",
1207        .owner = THIS_MODULE,
1208    },
1209};
1210
1211module_platform_driver(atmel_tdes_driver);
1212
1213MODULE_DESCRIPTION("Atmel DES/TDES hw acceleration support.");
1214MODULE_LICENSE("GPL v2");
1215MODULE_AUTHOR("Nicolas Royer - Eukréa Electromatique");
1216

Archive Download this file



interactive