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