ltq-deu: remove compiler warning and shorten locked sections
[openwrt/openwrt.git] / package / kernel / 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 <crypto/internal/skcipher.h>
51 #include <linux/interrupt.h>
52 #include <asm/byteorder.h>
53 #include <linux/delay.h>
54
55 /* Board specific header files */
56 #ifdef CONFIG_AR9
57 #include "ifxmips_deu_ar9.h"
58 #endif
59 #ifdef CONFIG_VR9
60 #include "ifxmips_deu_vr9.h"
61 #endif
62
63 static spinlock_t lock;
64 #define CRTCL_SECT_INIT spin_lock_init(&lock)
65 #define CRTCL_SECT_START spin_lock_irqsave(&lock, flag)
66 #define CRTCL_SECT_END spin_unlock_irqrestore(&lock, flag)
67
68 /* Preprocessor declerations */
69 #define ARC4_MIN_KEY_SIZE 1
70 //#define ARC4_MAX_KEY_SIZE 256
71 #define ARC4_MAX_KEY_SIZE 16
72 #define ARC4_BLOCK_SIZE 1
73 #define ARC4_START IFX_ARC4_CON
74 #ifdef CRYPTO_DEBUG
75 extern char debug_level;
76 #define DPRINTF(level, format, args...) if (level < debug_level) printk(KERN_INFO "[%s %s %d]: " format, __FILE__, __func__, __LINE__, ##args);
77 #else
78 #define DPRINTF(level, format, args...)
79 #endif
80
81 /*
82 * \brief arc4 private structure
83 */
84 struct arc4_ctx {
85 int key_length;
86 u8 buf[120];
87 };
88
89 extern int disable_deudma;
90 extern int disable_multiblock;
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 int arc4_set_key_skcipher(struct crypto_skcipher *tfm, const u8 *in_key, unsigned int key_len)
207 \ingroup IFX_ARC4_FUNCTIONS
208 \brief sets ARC4 key
209 \param tfm linux crypto skcipher
210 \param in_key input key
211 \param key_len key lengths less than or equal to 16 bytes supported
212 */
213 static int arc4_set_key_skcipher(struct crypto_skcipher *tfm, const u8 *inkey,
214 unsigned int key_len)
215 {
216 return arc4_set_key(crypto_skcipher_ctx(tfm), inkey, key_len);
217 }
218
219 /*! \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)
220 \ingroup IFX_ARC4_FUNCTIONS
221 \brief sets ARC4 hardware to ECB mode
222 \param ctx crypto algo context
223 \param dst output bytestream
224 \param src input bytestream
225 \param iv initialization vector
226 \param nbytes length of bytestream
227 \param encdec 1 for encrypt; 0 for decrypt
228 \param inplace not used
229 */
230 static void _deu_arc4_ecb(void *ctx, uint8_t *dst, const uint8_t *src,
231 uint8_t *iv, size_t nbytes, int encdec, int inplace)
232 {
233 _deu_arc4 (ctx, dst, src, NULL, nbytes, encdec, 0);
234 }
235
236 /*! \fn static void arc4_crypt(struct crypto_tfm *tfm, u8 *out, const u8 *in)
237 \ingroup IFX_ARC4_FUNCTIONS
238 \brief encrypt/decrypt ARC4_BLOCK_SIZE of data
239 \param tfm linux crypto algo transform
240 \param out output bytestream
241 \param in input bytestream
242 */
243 static void arc4_crypt(struct crypto_tfm *tfm, u8 *out, const u8 *in)
244 {
245 struct arc4_ctx *ctx = crypto_tfm_ctx(tfm);
246
247 _deu_arc4 (ctx, out, in, NULL, ARC4_BLOCK_SIZE,
248 CRYPTO_DIR_DECRYPT, 0);
249
250 }
251
252 /*
253 * \brief ARC4 function mappings
254 */
255 static struct crypto_alg ifxdeu_arc4_alg = {
256 .cra_name = "arc4",
257 .cra_driver_name = "ifxdeu-arc4",
258 .cra_priority = 300,
259 .cra_flags = CRYPTO_ALG_TYPE_CIPHER | CRYPTO_ALG_KERN_DRIVER_ONLY,
260 .cra_blocksize = ARC4_BLOCK_SIZE,
261 .cra_ctxsize = sizeof(struct arc4_ctx),
262 .cra_module = THIS_MODULE,
263 .cra_list = LIST_HEAD_INIT(ifxdeu_arc4_alg.cra_list),
264 .cra_u = {
265 .cipher = {
266 .cia_min_keysize = ARC4_MIN_KEY_SIZE,
267 .cia_max_keysize = ARC4_MAX_KEY_SIZE,
268 .cia_setkey = arc4_set_key,
269 .cia_encrypt = arc4_crypt,
270 .cia_decrypt = arc4_crypt,
271 }
272 }
273 };
274
275 /*! \fn static int ecb_arc4_encrypt(struct skcipher_request *req)
276 \ingroup IFX_ARC4_FUNCTIONS
277 \brief ECB ARC4 encrypt using linux crypto skcipher
278 \param req skcipher_request
279 */
280 static int ecb_arc4_encrypt(struct skcipher_request *req)
281 {
282 struct arc4_ctx *ctx = crypto_tfm_ctx(req->base.tfm);
283 struct skcipher_walk walk;
284 unsigned int nbytes;
285 int err;
286
287 DPRINTF(1, "\n");
288 err = skcipher_walk_virt(&walk, req, false);
289
290 while ((nbytes = walk.nbytes)) {
291 _deu_arc4_ecb(ctx, walk.dst.virt.addr, walk.src.virt.addr,
292 NULL, nbytes, CRYPTO_DIR_ENCRYPT, 0);
293 nbytes &= ARC4_BLOCK_SIZE - 1;
294 err = skcipher_walk_done(&walk, nbytes);
295 }
296
297 return err;
298 }
299
300 /*! \fn static int ecb_arc4_decrypt(struct skcipher_request *req)
301 \ingroup IFX_ARC4_FUNCTIONS
302 \brief ECB ARC4 decrypt using linux crypto skcipher
303 \param desc skcipher_request
304 */
305 static int ecb_arc4_decrypt(struct skcipher_request *req)
306 {
307 struct arc4_ctx *ctx = crypto_tfm_ctx(req->base.tfm);
308 struct skcipher_walk walk;
309 unsigned int nbytes;
310 int err;
311
312 DPRINTF(1, "\n");
313 err = skcipher_walk_virt(&walk, req, false);
314
315 while ((nbytes = walk.nbytes)) {
316 _deu_arc4_ecb(ctx, walk.dst.virt.addr, walk.src.virt.addr,
317 NULL, nbytes, CRYPTO_DIR_DECRYPT, 0);
318 nbytes &= ARC4_BLOCK_SIZE - 1;
319 err = skcipher_walk_done(&walk, nbytes);
320 }
321
322 return err;
323 }
324
325 /*
326 * \brief ARC4 function mappings
327 */
328 static struct skcipher_alg ifxdeu_ecb_arc4_alg = {
329 .base.cra_name = "ecb(arc4)",
330 .base.cra_driver_name = "ifxdeu-ecb(arc4)",
331 .base.cra_priority = 400,
332 .base.cra_flags = CRYPTO_ALG_TYPE_SKCIPHER | CRYPTO_ALG_KERN_DRIVER_ONLY,
333 .base.cra_blocksize = ARC4_BLOCK_SIZE,
334 .base.cra_ctxsize = sizeof(struct arc4_ctx),
335 .base.cra_module = THIS_MODULE,
336 .base.cra_list = LIST_HEAD_INIT(ifxdeu_ecb_arc4_alg.base.cra_list),
337 .min_keysize = ARC4_MIN_KEY_SIZE,
338 .max_keysize = ARC4_MAX_KEY_SIZE,
339 .setkey = arc4_set_key_skcipher,
340 .encrypt = ecb_arc4_encrypt,
341 .decrypt = ecb_arc4_decrypt,
342 };
343
344 /*! \fn int ifxdeu_init_arc4(void)
345 \ingroup IFX_ARC4_FUNCTIONS
346 \brief initialize arc4 driver
347 */
348 int 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_skcipher(&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_skcipher(&ifxdeu_ecb_arc4_alg);
372 printk (KERN_ERR "IFX ecb_arc4 initialization failed!\n");
373 return ret;
374
375 }
376
377 /*! \fn void ifxdeu_fini_arc4(void)
378 \ingroup IFX_ARC4_FUNCTIONS
379 \brief unregister arc4 driver
380 */
381 void ifxdeu_fini_arc4(void)
382 {
383 crypto_unregister_alg (&ifxdeu_arc4_alg);
384 crypto_unregister_skcipher (&ifxdeu_ecb_arc4_alg);
385
386
387 }