[ifxmips]:
[openwrt/svn-archive/archive.git] / target / linux / ifxmips / files / 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