lantiq: Tune the XWAY subtarget cflags
[openwrt.git] / 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  
62 static 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
74 extern 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 */
83 struct arc4_ctx {
84         int key_length;
85         u8 buf[120];
86 };
87
88 extern int disable_deudma;
89 extern 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 */                                 
103 static 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 */                                 
168 static 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 */    
180 static 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 */                               
217 static 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 */     
230 static 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 */
242 static 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 */                                     
269 static 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 */                                     
299 static 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 */
324 static 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 */                                 
348 int __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
366 arc4_err:
367         crypto_unregister_alg(&ifxdeu_arc4_alg);
368         printk(KERN_ERR "IFX arc4 initialization failed!\n");
369         return ret;
370 ecb_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 */                                 
381 void __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