OpenWrt – Blame information for rev 1
?pathlinks?
Rev | Author | Line No. | Line |
---|---|---|---|
1 | office | 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 <linux/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_priority = 300, |
||
262 | .cra_flags = CRYPTO_ALG_TYPE_DIGEST, |
||
263 | .cra_blocksize = SHA1_HMAC_BLOCK_SIZE, |
||
264 | .cra_module = THIS_MODULE, |
||
265 | } |
||
266 | }; |
||
267 | |||
268 | |||
269 | /*! \fn int ifxdeu_init_sha1 (void) |
||
270 | * \ingroup IFX_SHA1_FUNCTIONS |
||
271 | * \brief initialize sha1 driver |
||
272 | */ |
||
273 | int ifxdeu_init_sha1 (void) |
||
274 | { |
||
275 | int ret = -ENOSYS; |
||
276 | |||
277 | |||
278 | if ((ret = crypto_register_shash(&ifxdeu_sha1_alg))) |
||
279 | goto sha1_err; |
||
280 | |||
281 | CRTCL_SECT_INIT; |
||
282 | |||
283 | printk (KERN_NOTICE "IFX DEU SHA1 initialized%s.\n", disable_deudma ? "" : " (DMA)"); |
||
284 | return ret; |
||
285 | |||
286 | sha1_err: |
||
287 | printk(KERN_ERR "IFX DEU SHA1 initialization failed!\n"); |
||
288 | return ret; |
||
289 | } |
||
290 | |||
291 | /*! \fn void ifxdeu_fini_sha1 (void) |
||
292 | * \ingroup IFX_SHA1_FUNCTIONS |
||
293 | * \brief unregister sha1 driver |
||
294 | */ |
||
295 | void ifxdeu_fini_sha1 (void) |
||
296 | { |
||
297 | crypto_unregister_shash(&ifxdeu_sha1_alg); |
||
298 | |||
299 | |||
300 | } |
||
301 | |||
302 |