Root/package/platform/lantiq/ltq-deu/src/ifxmips_arc4.c

1/******************************************************************************
2**
3** FILE NAME : ifxmips_arc4.c
4** PROJECT : IFX UEIP
5** MODULES : DEU Module
6**
7** DATE : September 8, 2009
8** AUTHOR : Mohammad Firdaus
9** DESCRIPTION : Data Encryption Unit Driver for ARC4 Algorithm
10** COPYRIGHT : Copyright (c) 2009
11** Infineon Technologies AG
12** Am Campeon 1-12, 85579 Neubiberg, Germany
13**
14** This program is free software; you can redistribute it and/or modify
15** it under the terms of the GNU General Public License as published by
16** the Free Software Foundation; either version 2 of the License, or
17** (at your option) any later version.
18**
19** HISTORY
20** $Date $Author $Comment
21** 08 Sept 2009 Mohammad Firdaus Initial UEIP release
22*******************************************************************************/
23
24/*!
25  \defgroup IFX_DEU IFX_DEU_DRIVERS
26  \ingroup API
27  \brief ifx deu driver module
28*/
29
30/*!
31  \file ifxmips_arc4.c
32  \ingroup IFX_DEU
33  \brief ARC4 encryption DEU driver file
34*/
35
36/*!
37  \defgroup IFX_ARC4_FUNCTIONS IFX_ARC4_FUNCTIONS
38  \ingroup IFX_DEU
39  \brief IFX deu driver functions
40*/
41
42/* Project header */
43#include <linux/version.h>
44#include <linux/module.h>
45#include <linux/init.h>
46#include <linux/types.h>
47#include <linux/errno.h>
48#include <linux/crypto.h>
49#include <crypto/algapi.h>
50#include <linux/interrupt.h>
51#include <asm/byteorder.h>
52#include <linux/delay.h>
53
54/* Board specific header files */
55#ifdef CONFIG_AR9
56#include "ifxmips_deu_ar9.h"
57#endif
58#ifdef CONFIG_VR9
59#include "ifxmips_deu_vr9.h"
60#endif
61 
62static spinlock_t lock;
63#define CRTCL_SECT_INIT spin_lock_init(&lock)
64#define CRTCL_SECT_START spin_lock_irqsave(&lock, flag)
65#define CRTCL_SECT_END spin_unlock_irqrestore(&lock, flag)
66
67/* Preprocessor declerations */
68#define ARC4_MIN_KEY_SIZE 1
69//#define ARC4_MAX_KEY_SIZE 256
70#define ARC4_MAX_KEY_SIZE 16
71#define ARC4_BLOCK_SIZE 1
72#define ARC4_START IFX_ARC4_CON
73#ifdef CRYPTO_DEBUG
74extern char debug_level;
75#define DPRINTF(level, format, args...) if (level < debug_level) printk(KERN_INFO "[%s %s %d]: " format, __FILE__, __func__, __LINE__, ##args);
76#else
77#define DPRINTF(level, format, args...)
78#endif
79
80/*
81 * \brief arc4 private structure
82*/
83struct arc4_ctx {
84        int key_length;
85        u8 buf[120];
86};
87
88extern int disable_deudma;
89extern int disable_multiblock;
90
91
92/*! \fn static void _deu_arc4 (void *ctx_arg, u8 *out_arg, const u8 *in_arg, u8 *iv_arg, u32 nbytes, int encdec, int mode)
93    \ingroup IFX_ARC4_FUNCTIONS
94    \brief main interface to ARC4 hardware
95    \param ctx_arg crypto algo context
96    \param out_arg output bytestream
97    \param in_arg input bytestream
98    \param iv_arg initialization vector
99    \param nbytes length of bytestream
100    \param encdec 1 for encrypt; 0 for decrypt
101    \param mode operation mode such as ebc, cbc, ctr
102*/
103static void _deu_arc4 (void *ctx_arg, u8 *out_arg, const u8 *in_arg,
104            u8 *iv_arg, u32 nbytes, int encdec, int mode)
105{
106        volatile struct arc4_t *arc4 = (struct arc4_t *) ARC4_START;
107        
108        int i = 0;
109        unsigned long flag;
110        
111#if 1 // need to handle nbytes not multiple of 16
112        volatile u32 tmp_array32[4];
113        volatile u8 *tmp_ptr8;
114        int remaining_bytes, j;
115#endif
116
117        CRTCL_SECT_START;
118
119        arc4->IDLEN = nbytes;
120
121#if 1
122        while (i < nbytes) {
123                arc4->ID3R = *((u32 *) in_arg + (i>>2) + 0);
124                arc4->ID2R = *((u32 *) in_arg + (i>>2) + 1);
125                arc4->ID1R = *((u32 *) in_arg + (i>>2) + 2);
126                arc4->ID0R = *((u32 *) in_arg + (i>>2) + 3);
127                
128                arc4->controlr.GO = 1;
129                
130                while (arc4->controlr.BUS) {
131                      // this will not take long
132                }
133
134#if 1
135                // need to handle nbytes not multiple of 16
136                tmp_array32[0] = arc4->OD3R;
137                tmp_array32[1] = arc4->OD2R;
138                tmp_array32[2] = arc4->OD1R;
139                tmp_array32[3] = arc4->OD0R;
140
141                remaining_bytes = nbytes - i;
142                if (remaining_bytes > 16)
143                     remaining_bytes = 16;
144                
145                tmp_ptr8 = (u8 *)&tmp_array32[0];
146                for (j = 0; j < remaining_bytes; j++)
147                     *out_arg++ = *tmp_ptr8++;
148#else
149                *((u32 *) out_arg + (i>>2) + 0) = arc4->OD3R;
150                *((u32 *) out_arg + (i>>2) + 1) = arc4->OD2R;
151                *((u32 *) out_arg + (i>>2) + 2) = arc4->OD1R;
152                *((u32 *) out_arg + (i>>2) + 3) = arc4->OD0R;
153#endif
154
155                i += 16;
156        }
157#else // dma
158
159#endif // dma
160
161        CRTCL_SECT_END;
162}
163
164/*! \fn arc4_chip_init (void)
165    \ingroup IFX_ARC4_FUNCTIONS
166    \brief initialize arc4 hardware
167*/
168static void arc4_chip_init (void)
169{
170        //do nothing
171}
172
173/*! \fn static int arc4_set_key(struct crypto_tfm *tfm, const u8 *in_key, unsigned int key_len)
174    \ingroup IFX_ARC4_FUNCTIONS
175    \brief sets ARC4 key
176    \param tfm linux crypto algo transform
177    \param in_key input key
178    \param key_len key lengths less than or equal to 16 bytes supported
179*/
180static int arc4_set_key(struct crypto_tfm *tfm, const u8 *inkey,
181                       unsigned int key_len)
182{
183        //struct arc4_ctx *ctx = crypto_tfm_ctx(tfm);
184        volatile struct arc4_t *arc4 = (struct arc4_t *) ARC4_START;
185        u32 *in_key = (u32 *)inkey;
186                
187        // must program all bits at one go?!!!
188//#if 1
189        *IFX_ARC4_CON = ( (1<<31) | ((key_len - 1)<<27) | (1<<26) | (3<<16) );
190        //NDC=1,ENDI=1,GO=0,KSAE=1,SM=0
191
192        arc4->K3R = *((u32 *) in_key + 0);
193        arc4->K2R = *((u32 *) in_key + 1);
194        arc4->K1R = *((u32 *) in_key + 2);
195        arc4->K0R = *((u32 *) in_key + 3);
196
197#if 0 // arc4 is a ugly state machine, KSAE can only be set once per session
198        ctx->key_length = key_len;
199
200        memcpy ((u8 *) (ctx->buf), in_key, key_len);
201#endif
202
203        return 0;
204}
205
206/*! \fn static void _deu_arc4_ecb(void *ctx, uint8_t *dst, const uint8_t *src, uint8_t *iv, size_t nbytes, int encdec, int inplace)
207    \ingroup IFX_ARC4_FUNCTIONS
208    \brief sets ARC4 hardware to ECB mode
209    \param ctx crypto algo context
210    \param dst output bytestream
211    \param src input bytestream
212    \param iv initialization vector
213    \param nbytes length of bytestream
214    \param encdec 1 for encrypt; 0 for decrypt
215    \param inplace not used
216*/
217static void _deu_arc4_ecb(void *ctx, uint8_t *dst, const uint8_t *src,
218                uint8_t *iv, size_t nbytes, int encdec, int inplace)
219{
220        _deu_arc4 (ctx, dst, src, NULL, nbytes, encdec, 0);
221}
222
223/*! \fn static void arc4_crypt(struct crypto_tfm *tfm, u8 *out, const u8 *in)
224    \ingroup IFX_ARC4_FUNCTIONS
225    \brief encrypt/decrypt ARC4_BLOCK_SIZE of data
226    \param tfm linux crypto algo transform
227    \param out output bytestream
228    \param in input bytestream
229*/
230static void arc4_crypt(struct crypto_tfm *tfm, u8 *out, const u8 *in)
231{
232        struct arc4_ctx *ctx = crypto_tfm_ctx(tfm);
233
234        _deu_arc4 (ctx, out, in, NULL, ARC4_BLOCK_SIZE,
235                    CRYPTO_DIR_DECRYPT, 0);
236
237}
238
239/*
240 * \brief ARC4 function mappings
241*/
242static struct crypto_alg ifxdeu_arc4_alg = {
243        .cra_name = "arc4",
244        .cra_driver_name = "ifxdeu-arc4",
245        .cra_flags = CRYPTO_ALG_TYPE_CIPHER,
246        .cra_blocksize = ARC4_BLOCK_SIZE,
247        .cra_ctxsize = sizeof(struct arc4_ctx),
248        .cra_module = THIS_MODULE,
249        .cra_list = LIST_HEAD_INIT(ifxdeu_arc4_alg.cra_list),
250        .cra_u = {
251                .cipher = {
252                        .cia_min_keysize = ARC4_MIN_KEY_SIZE,
253                        .cia_max_keysize = ARC4_MAX_KEY_SIZE,
254                        .cia_setkey = arc4_set_key,
255                        .cia_encrypt = arc4_crypt,
256                        .cia_decrypt = arc4_crypt,
257                }
258        }
259};
260
261/*! \fn static int ecb_arc4_encrypt(struct blkcipher_desc *desc, struct scatterlist *dst, struct scatterlist *src, unsigned int nbytes)
262    \ingroup IFX_ARC4_FUNCTIONS
263    \brief ECB ARC4 encrypt using linux crypto blkcipher
264    \param desc blkcipher descriptor
265    \param dst output scatterlist
266    \param src input scatterlist
267    \param nbytes data size in bytes
268*/
269static int ecb_arc4_encrypt(struct blkcipher_desc *desc,
270                           struct scatterlist *dst, struct scatterlist *src,
271                           unsigned int nbytes)
272{
273        struct arc4_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
274        struct blkcipher_walk walk;
275        int err;
276
277        DPRINTF(1, "\n");
278        blkcipher_walk_init(&walk, dst, src, nbytes);
279        err = blkcipher_walk_virt(desc, &walk);
280
281        while ((nbytes = walk.nbytes)) {
282                _deu_arc4_ecb(ctx, walk.dst.virt.addr, walk.src.virt.addr,
283                               NULL, nbytes, CRYPTO_DIR_ENCRYPT, 0);
284                nbytes &= ARC4_BLOCK_SIZE - 1;
285                err = blkcipher_walk_done(desc, &walk, nbytes);
286        }
287
288        return err;
289}
290
291/*! \fn static int ecb_arc4_decrypt(struct blkcipher_desc *desc, struct scatterlist *dst, struct scatterlist *src, unsigned int nbytes)
292    \ingroup IFX_ARC4_FUNCTIONS
293    \brief ECB ARC4 decrypt using linux crypto blkcipher
294    \param desc blkcipher descriptor
295    \param dst output scatterlist
296    \param src input scatterlist
297    \param nbytes data size in bytes
298*/
299static int ecb_arc4_decrypt(struct blkcipher_desc *desc,
300                           struct scatterlist *dst, struct scatterlist *src,
301                           unsigned int nbytes)
302{
303        struct arc4_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
304        struct blkcipher_walk walk;
305        int err;
306
307        DPRINTF(1, "\n");
308        blkcipher_walk_init(&walk, dst, src, nbytes);
309        err = blkcipher_walk_virt(desc, &walk);
310
311        while ((nbytes = walk.nbytes)) {
312                _deu_arc4_ecb(ctx, walk.dst.virt.addr, walk.src.virt.addr,
313                               NULL, nbytes, CRYPTO_DIR_DECRYPT, 0);
314                nbytes &= ARC4_BLOCK_SIZE - 1;
315                err = blkcipher_walk_done(desc, &walk, nbytes);
316        }
317
318        return err;
319}
320
321/*
322 * \brief ARC4 function mappings
323*/
324static struct crypto_alg ifxdeu_ecb_arc4_alg = {
325        .cra_name = "ecb(arc4)",
326        .cra_driver_name = "ifxdeu-ecb(arc4)",
327        .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER,
328        .cra_blocksize = ARC4_BLOCK_SIZE,
329        .cra_ctxsize = sizeof(struct arc4_ctx),
330        .cra_type = &crypto_blkcipher_type,
331        .cra_module = THIS_MODULE,
332        .cra_list = LIST_HEAD_INIT(ifxdeu_ecb_arc4_alg.cra_list),
333        .cra_u = {
334                .blkcipher = {
335                        .min_keysize = ARC4_MIN_KEY_SIZE,
336                        .max_keysize = ARC4_MAX_KEY_SIZE,
337                        .setkey = arc4_set_key,
338                        .encrypt = ecb_arc4_encrypt,
339                        .decrypt = ecb_arc4_decrypt,
340                }
341        }
342};
343
344/*! \fn int __init ifxdeu_init_arc4(void)
345    \ingroup IFX_ARC4_FUNCTIONS
346    \brief initialize arc4 driver
347*/
348int __init ifxdeu_init_arc4(void)
349{
350    int ret = -ENOSYS;
351
352
353        if ((ret = crypto_register_alg(&ifxdeu_arc4_alg)))
354                goto arc4_err;
355
356        if ((ret = crypto_register_alg(&ifxdeu_ecb_arc4_alg)))
357                goto ecb_arc4_err;
358
359        arc4_chip_init ();
360
361        CRTCL_SECT_INIT;
362
363        printk (KERN_NOTICE "IFX DEU ARC4 initialized%s%s.\n", disable_multiblock ? "" : " (multiblock)", disable_deudma ? "" : " (DMA)");
364        return ret;
365
366arc4_err:
367        crypto_unregister_alg(&ifxdeu_arc4_alg);
368        printk(KERN_ERR "IFX arc4 initialization failed!\n");
369        return ret;
370ecb_arc4_err:
371        crypto_unregister_alg(&ifxdeu_ecb_arc4_alg);
372        printk (KERN_ERR "IFX ecb_arc4 initialization failed!\n");
373        return ret;
374
375}
376
377/*! \fn void __exit ifxdeu_fini_arc4(void)
378    \ingroup IFX_ARC4_FUNCTIONS
379    \brief unregister arc4 driver
380*/
381void __exit ifxdeu_fini_arc4(void)
382{
383        crypto_unregister_alg (&ifxdeu_arc4_alg);
384        crypto_unregister_alg (&ifxdeu_ecb_arc4_alg);
385
386
387}
388
389
390

Archive Download this file



interactive