lantiq: Tune the XWAY subtarget cflags
[openwrt.git] / package / platform / lantiq / ltq-deu / src / ifxmips_sha1.c
1 /******************************************************************************
2 **
3 ** FILE NAME    : ifxmips_sha1.c
4 ** PROJECT      : IFX UEIP
5 ** MODULES      : DEU Module for Danube
6 **
7 ** DATE         : September 8, 2009
8 ** AUTHOR       : Mohammad Firdaus
9 ** DESCRIPTION  : Data Encryption Unit Driver
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   \defgroup IFX_DEU IFX_DEU_DRIVERS
25   \ingroup API
26   \brief ifx deu driver module
27 */
28
29 /*!
30   \file ifxmips_sha1.c
31   \ingroup IFX_DEU
32   \brief SHA1 encryption deu driver file
33 */
34
35 /*!
36   \defgroup IFX_SHA1_FUNCTIONS IFX_SHA1_FUNCTIONS
37   \ingroup IFX_DEU
38   \brief ifx deu sha1 functions
39 */
40
41
42 /* Project header */
43 #include <linux/init.h>
44 #include <linux/module.h>
45 #include <linux/mm.h>
46 #include <linux/crypto.h>
47 #include <linux/cryptohash.h>
48 #include <crypto/sha.h>
49 #include <crypto/internal/hash.h>
50 #include <linux/types.h>
51 #include <asm/scatterlist.h>
52 #include <asm/byteorder.h>
53
54 #if defined(CONFIG_DANUBE)
55 #include "ifxmips_deu_danube.h"
56 #elif defined(CONFIG_AR9)
57 #include "ifxmips_deu_ar9.h"
58 #elif defined(CONFIG_VR9) || defined(CONFIG_AR10)
59 #include "ifxmips_deu_vr9.h"
60 #else
61 #error "Plaform Unknwon!"
62 #endif
63
64 #define SHA1_DIGEST_SIZE    20
65 #define SHA1_HMAC_BLOCK_SIZE    64
66 #define HASH_START   IFX_HASH_CON
67
68 static spinlock_t lock;
69 #define CRTCL_SECT_INIT        spin_lock_init(&lock)
70 #define CRTCL_SECT_START       spin_lock_irqsave(&lock, flag)
71 #define CRTCL_SECT_END         spin_unlock_irqrestore(&lock, flag)
72
73 //#define CRYPTO_DEBUG
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 SHA1 private structure
83 */
84 struct sha1_ctx {
85         int started;
86         u64 count;
87         u32 hash[5];
88         u32 state[5];
89         u8 buffer[64];
90 };
91
92 extern int disable_deudma;
93
94
95 /*! \fn static void sha1_transform (u32 *state, const u32 *in)
96  *  \ingroup IFX_SHA1_FUNCTIONS
97  *  \brief main interface to sha1 hardware   
98  *  \param state current state 
99  *  \param in 64-byte block of input  
100 */                                 
101 static void sha1_transform (struct sha1_ctx *sctx, u32 *state, const u32 *in)
102 {
103     int i = 0;
104     volatile struct deu_hash_t *hashs = (struct deu_hash_t *) HASH_START;
105     unsigned long flag;
106
107     CRTCL_SECT_START;
108
109     /* For context switching purposes, the previous hash output
110      * is loaded back into the output register 
111     */
112     if (sctx->started) {
113         hashs->D1R = *((u32 *) sctx->hash + 0);
114         hashs->D2R = *((u32 *) sctx->hash + 1);
115         hashs->D3R = *((u32 *) sctx->hash + 2);
116         hashs->D4R = *((u32 *) sctx->hash + 3);
117         hashs->D5R = *((u32 *) sctx->hash + 4);
118     }
119
120     for (i = 0; i < 16; i++) {
121         hashs->MR = in[i];
122     };
123
124     //wait for processing
125     while (hashs->controlr.BSY) {
126         // this will not take long
127     }
128    
129     /* For context switching purposes, the output is saved into a 
130      * context struct which can be used later on 
131     */
132     *((u32 *) sctx->hash + 0) = hashs->D1R;
133     *((u32 *) sctx->hash + 1) = hashs->D2R;
134     *((u32 *) sctx->hash + 2) = hashs->D3R;
135     *((u32 *) sctx->hash + 3) = hashs->D4R;
136     *((u32 *) sctx->hash + 4) = hashs->D5R;
137
138     sctx->started = 1;
139
140     CRTCL_SECT_END;
141 }
142
143 /*! \fn static void sha1_init(struct crypto_tfm *tfm)
144  *  \ingroup IFX_SHA1_FUNCTIONS
145  *  \brief initialize sha1 hardware   
146  *  \param tfm linux crypto algo transform  
147 */                                 
148 static int sha1_init(struct shash_desc *desc)
149 {
150     struct sha1_ctx *sctx = shash_desc_ctx(desc);
151     
152     SHA_HASH_INIT;
153
154     sctx->started = 0;
155     sctx->count = 0;
156     return 0;
157 }
158
159 /*! \fn static void sha1_update(struct crypto_tfm *tfm, const u8 *data, unsigned int len)
160  *  \ingroup IFX_SHA1_FUNCTIONS
161  *  \brief on-the-fly sha1 computation   
162  *  \param tfm linux crypto algo transform  
163  *  \param data input data  
164  *  \param len size of input data  
165 */                                 
166 static int sha1_update(struct shash_desc * desc, const u8 *data,
167             unsigned int len)
168 {
169     struct sha1_ctx *sctx = shash_desc_ctx(desc);
170     unsigned int i, j;
171
172     j = (sctx->count >> 3) & 0x3f;
173     sctx->count += len << 3;
174
175     if ((j + len) > 63) {
176         memcpy (&sctx->buffer[j], data, (i = 64 - j));
177         sha1_transform (sctx, sctx->state, (const u32 *)sctx->buffer);
178         for (; i + 63 < len; i += 64) {
179             sha1_transform (sctx, sctx->state, (const u32 *)&data[i]);
180         }
181
182         j = 0;
183     }
184     else
185         i = 0;
186
187     memcpy (&sctx->buffer[j], &data[i], len - i);
188     return 0;
189 }
190
191 /*! \fn static void sha1_final(struct crypto_tfm *tfm, u8 *out)
192  *  \ingroup IFX_SHA1_FUNCTIONS
193  *  \brief compute final sha1 value   
194  *  \param tfm linux crypto algo transform  
195  *  \param out final md5 output value  
196 */                                 
197 static int sha1_final(struct shash_desc *desc, u8 *out)
198 {
199     struct sha1_ctx *sctx = shash_desc_ctx(desc);
200     u32 index, padlen;
201     u64 t;
202     u8 bits[8] = { 0, };
203     static const u8 padding[64] = { 0x80, };
204     volatile struct deu_hash_t *hashs = (struct deu_hash_t *) HASH_START;
205     unsigned long flag;
206
207     t = sctx->count;
208     bits[7] = 0xff & t;
209     t >>= 8;
210     bits[6] = 0xff & t;
211     t >>= 8;
212     bits[5] = 0xff & t;
213     t >>= 8;
214     bits[4] = 0xff & t;
215     t >>= 8;
216     bits[3] = 0xff & t;
217     t >>= 8;
218     bits[2] = 0xff & t;
219     t >>= 8;
220     bits[1] = 0xff & t;
221     t >>= 8;
222     bits[0] = 0xff & t;
223
224     /* Pad out to 56 mod 64 */
225     index = (sctx->count >> 3) & 0x3f;
226     padlen = (index < 56) ? (56 - index) : ((64 + 56) - index);
227     sha1_update (desc, padding, padlen);
228
229     /* Append length */
230     sha1_update (desc, bits, sizeof bits);
231
232     CRTCL_SECT_START;
233
234     *((u32 *) out + 0) = hashs->D1R;
235     *((u32 *) out + 1) = hashs->D2R;
236     *((u32 *) out + 2) = hashs->D3R;
237     *((u32 *) out + 3) = hashs->D4R;
238     *((u32 *) out + 4) = hashs->D5R;
239
240     CRTCL_SECT_END;
241
242     // Wipe context
243     memset (sctx, 0, sizeof *sctx);
244
245     return 0;
246 }
247
248 /* 
249  * \brief SHA1 function mappings
250 */
251 static struct shash_alg ifxdeu_sha1_alg = {
252         .digestsize     =       SHA1_DIGEST_SIZE,
253         .init           =       sha1_init,
254         .update         =       sha1_update,
255         .final          =       sha1_final,
256         .descsize       =       sizeof(struct sha1_ctx),
257         .statesize      =       sizeof(struct sha1_state),
258         .base           =       {
259                 .cra_name       =       "sha1",
260                 .cra_driver_name=       "ifxdeu-sha1",
261                 .cra_flags      =       CRYPTO_ALG_TYPE_DIGEST,
262                 .cra_blocksize  =       SHA1_HMAC_BLOCK_SIZE,
263                 .cra_module     =       THIS_MODULE,
264         }
265 };
266
267
268 /*! \fn int __init ifxdeu_init_sha1 (void)
269  *  \ingroup IFX_SHA1_FUNCTIONS
270  *  \brief initialize sha1 driver    
271 */                                 
272 int __init ifxdeu_init_sha1 (void)
273 {
274     int ret = -ENOSYS;
275
276
277     if ((ret = crypto_register_shash(&ifxdeu_sha1_alg)))
278         goto sha1_err;
279
280     CRTCL_SECT_INIT;
281
282     printk (KERN_NOTICE "IFX DEU SHA1 initialized%s.\n", disable_deudma ? "" : " (DMA)");
283     return ret;
284
285 sha1_err:
286     printk(KERN_ERR "IFX DEU SHA1 initialization failed!\n");
287     return ret;
288 }
289
290 /*! \fn void __exit ifxdeu_fini_sha1 (void)
291  *  \ingroup IFX_SHA1_FUNCTIONS
292  *  \brief unregister sha1 driver   
293 */                                 
294 void __exit ifxdeu_fini_sha1 (void)
295 {
296     crypto_unregister_shash(&ifxdeu_sha1_alg);
297
298
299 }
300
301