1 /******************************************************************************
3 ** FILE NAME : ifxmips_arc4.c
5 ** MODULES : DEU Module
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
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.
20 ** $Date $Author $Comment
21 ** 08 Sept 2009 Mohammad Firdaus Initial UEIP release
22 *******************************************************************************/
25 \defgroup IFX_DEU IFX_DEU_DRIVERS
27 \brief ifx deu driver module
33 \brief ARC4 encryption DEU driver file
37 \defgroup IFX_ARC4_FUNCTIONS IFX_ARC4_FUNCTIONS
39 \brief IFX deu driver functions
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>
54 /* Board specific header files */
56 #include "ifxmips_deu_ar9.h"
59 #include "ifxmips_deu_vr9.h"
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)
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
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);
77 #define DPRINTF(level, format, args...)
81 * \brief arc4 private structure
88 extern int disable_deudma
;
89 extern int disable_multiblock
;
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
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
)
106 volatile struct arc4_t
*arc4
= (struct arc4_t
*) ARC4_START
;
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
;
119 arc4
->IDLEN
= 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);
128 arc4
->controlr
.GO
= 1;
130 while (arc4
->controlr
.BUS
) {
131 // this will not take long
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
;
141 remaining_bytes
= nbytes
- i
;
142 if (remaining_bytes
> 16)
143 remaining_bytes
= 16;
145 tmp_ptr8
= (u8
*)&tmp_array32
[0];
146 for (j
= 0; j
< remaining_bytes
; j
++)
147 *out_arg
++ = *tmp_ptr8
++;
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
;
164 /*! \fn arc4_chip_init (void)
165 \ingroup IFX_ARC4_FUNCTIONS
166 \brief initialize arc4 hardware
168 static void arc4_chip_init (void)
173 /*! \fn static int arc4_set_key(struct crypto_tfm *tfm, const u8 *in_key, unsigned int key_len)
174 \ingroup IFX_ARC4_FUNCTIONS
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
180 static int arc4_set_key(struct crypto_tfm
*tfm
, const u8
*inkey
,
181 unsigned int key_len
)
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
;
187 // must program all bits at one go?!!!
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
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);
197 #if 0 // arc4 is a ugly state machine, KSAE can only be set once per session
198 ctx
->key_length
= key_len
;
200 memcpy ((u8
*) (ctx
->buf
), in_key
, key_len
);
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
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
)
220 _deu_arc4 (ctx
, dst
, src
, NULL
, nbytes
, encdec
, 0);
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
230 static void arc4_crypt(struct crypto_tfm
*tfm
, u8
*out
, const u8
*in
)
232 struct arc4_ctx
*ctx
= crypto_tfm_ctx(tfm
);
234 _deu_arc4 (ctx
, out
, in
, NULL
, ARC4_BLOCK_SIZE
,
235 CRYPTO_DIR_DECRYPT
, 0);
240 * \brief ARC4 function mappings
242 static struct crypto_alg ifxdeu_arc4_alg
= {
244 .cra_driver_name
= "ifxdeu-arc4",
246 .cra_flags
= CRYPTO_ALG_TYPE_CIPHER
,
247 .cra_blocksize
= ARC4_BLOCK_SIZE
,
248 .cra_ctxsize
= sizeof(struct arc4_ctx
),
249 .cra_module
= THIS_MODULE
,
250 .cra_list
= LIST_HEAD_INIT(ifxdeu_arc4_alg
.cra_list
),
253 .cia_min_keysize
= ARC4_MIN_KEY_SIZE
,
254 .cia_max_keysize
= ARC4_MAX_KEY_SIZE
,
255 .cia_setkey
= arc4_set_key
,
256 .cia_encrypt
= arc4_crypt
,
257 .cia_decrypt
= arc4_crypt
,
262 /*! \fn static int ecb_arc4_encrypt(struct blkcipher_desc *desc, struct scatterlist *dst, struct scatterlist *src, unsigned int nbytes)
263 \ingroup IFX_ARC4_FUNCTIONS
264 \brief ECB ARC4 encrypt using linux crypto blkcipher
265 \param desc blkcipher descriptor
266 \param dst output scatterlist
267 \param src input scatterlist
268 \param nbytes data size in bytes
270 static int ecb_arc4_encrypt(struct blkcipher_desc
*desc
,
271 struct scatterlist
*dst
, struct scatterlist
*src
,
274 struct arc4_ctx
*ctx
= crypto_blkcipher_ctx(desc
->tfm
);
275 struct blkcipher_walk walk
;
279 blkcipher_walk_init(&walk
, dst
, src
, nbytes
);
280 err
= blkcipher_walk_virt(desc
, &walk
);
282 while ((nbytes
= walk
.nbytes
)) {
283 _deu_arc4_ecb(ctx
, walk
.dst
.virt
.addr
, walk
.src
.virt
.addr
,
284 NULL
, nbytes
, CRYPTO_DIR_ENCRYPT
, 0);
285 nbytes
&= ARC4_BLOCK_SIZE
- 1;
286 err
= blkcipher_walk_done(desc
, &walk
, nbytes
);
292 /*! \fn static int ecb_arc4_decrypt(struct blkcipher_desc *desc, struct scatterlist *dst, struct scatterlist *src, unsigned int nbytes)
293 \ingroup IFX_ARC4_FUNCTIONS
294 \brief ECB ARC4 decrypt using linux crypto blkcipher
295 \param desc blkcipher descriptor
296 \param dst output scatterlist
297 \param src input scatterlist
298 \param nbytes data size in bytes
300 static int ecb_arc4_decrypt(struct blkcipher_desc
*desc
,
301 struct scatterlist
*dst
, struct scatterlist
*src
,
304 struct arc4_ctx
*ctx
= crypto_blkcipher_ctx(desc
->tfm
);
305 struct blkcipher_walk walk
;
309 blkcipher_walk_init(&walk
, dst
, src
, nbytes
);
310 err
= blkcipher_walk_virt(desc
, &walk
);
312 while ((nbytes
= walk
.nbytes
)) {
313 _deu_arc4_ecb(ctx
, walk
.dst
.virt
.addr
, walk
.src
.virt
.addr
,
314 NULL
, nbytes
, CRYPTO_DIR_DECRYPT
, 0);
315 nbytes
&= ARC4_BLOCK_SIZE
- 1;
316 err
= blkcipher_walk_done(desc
, &walk
, nbytes
);
323 * \brief ARC4 function mappings
325 static struct crypto_alg ifxdeu_ecb_arc4_alg
= {
326 .cra_name
= "ecb(arc4)",
327 .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
),
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
,
346 /*! \fn int __init ifxdeu_init_arc4(void)
347 \ingroup IFX_ARC4_FUNCTIONS
348 \brief initialize arc4 driver
350 int __init
ifxdeu_init_arc4(void)
355 if ((ret
= crypto_register_alg(&ifxdeu_arc4_alg
)))
358 if ((ret
= crypto_register_alg(&ifxdeu_ecb_arc4_alg
)))
365 printk (KERN_NOTICE
"IFX DEU ARC4 initialized%s%s.\n", disable_multiblock
? "" : " (multiblock)", disable_deudma
? "" : " (DMA)");
369 crypto_unregister_alg(&ifxdeu_arc4_alg
);
370 printk(KERN_ERR
"IFX arc4 initialization failed!\n");
373 crypto_unregister_alg(&ifxdeu_ecb_arc4_alg
);
374 printk (KERN_ERR
"IFX ecb_arc4 initialization failed!\n");
379 /*! \fn void __exit ifxdeu_fini_arc4(void)
380 \ingroup IFX_ARC4_FUNCTIONS
381 \brief unregister arc4 driver
383 void __exit
ifxdeu_fini_arc4(void)
385 crypto_unregister_alg (&ifxdeu_arc4_alg
);
386 crypto_unregister_alg (&ifxdeu_ecb_arc4_alg
);