|
1 /* |
|
2 * Copyright (c) 2001-2006 Nokia Corporation and/or its subsidiary(-ies). |
|
3 * All rights reserved. |
|
4 * This component and the accompanying materials are made available |
|
5 * under the terms of the License "Eclipse Public License v1.0" |
|
6 * which accompanies this distribution, and is available |
|
7 * at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
8 * |
|
9 * Initial Contributors: |
|
10 * Nokia Corporation - initial contribution. |
|
11 * |
|
12 * Contributors: |
|
13 * |
|
14 * Description: EAP and WLAN authentication protocols. |
|
15 * |
|
16 */ |
|
17 |
|
18 |
|
19 // This is enumeration of EAPOL source code. |
|
20 #if defined(USE_EAP_MINIMUM_RELEASE_TRACES) |
|
21 #undef EAP_FILE_NUMBER_ENUM |
|
22 #define EAP_FILE_NUMBER_ENUM 4 |
|
23 #undef EAP_FILE_NUMBER_DATE |
|
24 #define EAP_FILE_NUMBER_DATE 1127594498 |
|
25 #endif //#if defined(USE_EAP_MINIMUM_RELEASE_TRACES) |
|
26 |
|
27 |
|
28 |
|
29 #include "eap_am_memory.h" |
|
30 #include "eap_am_crypto_md4.h" |
|
31 |
|
32 //-------------------------------------------------- |
|
33 |
|
34 #if 1 |
|
35 #define EAP_MD4_TRACE_DEBUG EAP_TRACE_DEBUG |
|
36 #else |
|
37 #define EAP_MD4_TRACE_DEBUG(tools, flags, params) |
|
38 #endif |
|
39 |
|
40 #if defined(USE_EAP_TRACE) |
|
41 static const u32_t EAP_TRACE_MASK_MD4 = eap_am_tools_c::eap_trace_mask_crypto_md4; |
|
42 #endif //#if defined(USE_EAP_TRACE) |
|
43 |
|
44 //-------------------------------------------------- |
|
45 |
|
46 EAP_FUNC_EXPORT eap_am_crypto_md4_c::~eap_am_crypto_md4_c() |
|
47 { |
|
48 hash_cleanup(); |
|
49 } |
|
50 |
|
51 //-------------------------------------------------- |
|
52 |
|
53 EAP_FUNC_EXPORT eap_am_crypto_md4_c::eap_am_crypto_md4_c( |
|
54 abs_eap_am_tools_c * const tools) |
|
55 : m_am_tools(tools) |
|
56 , m_saved_data(tools) |
|
57 , m_full_hashed_data_length(0ul) |
|
58 , m_is_valid(false) |
|
59 { |
|
60 m_H[0] = 0; |
|
61 m_W_in_host_order[0] = 0; |
|
62 |
|
63 if (m_saved_data.get_is_valid() == false) |
|
64 { |
|
65 return; |
|
66 } |
|
67 |
|
68 eap_status_e status = hash_init(); |
|
69 if (status != eap_status_ok) |
|
70 { |
|
71 return; |
|
72 } |
|
73 |
|
74 set_is_valid(); |
|
75 } |
|
76 |
|
77 |
|
78 //------------------------------------------------------------ |
|
79 |
|
80 /** |
|
81 * The set_is_invalid() function sets the state of the eap_am_crypto_md4_c |
|
82 * object invalid. |
|
83 * The eap_am_crypto_md4_c object calls this function after it is initialized. |
|
84 */ |
|
85 EAP_FUNC_EXPORT void eap_am_crypto_md4_c::set_is_invalid() |
|
86 { |
|
87 m_is_valid = false; |
|
88 } |
|
89 |
|
90 //------------------------------------------------------------ |
|
91 |
|
92 /** |
|
93 * The set_is_valid() function sets the state of the eap_am_crypto_md4_c |
|
94 * object valid. |
|
95 * The eap_am_crypto_md4_c object calls this function after it is initialized. |
|
96 */ |
|
97 EAP_FUNC_EXPORT void eap_am_crypto_md4_c::set_is_valid() |
|
98 { |
|
99 m_is_valid = true; |
|
100 } |
|
101 |
|
102 //------------------------------------------------------------ |
|
103 |
|
104 /** |
|
105 * The get_is_valid() function returns the status of the eap_am_crypto_md4_c |
|
106 * object. |
|
107 * True indicates the object is allocated successfully. |
|
108 */ |
|
109 EAP_FUNC_EXPORT bool eap_am_crypto_md4_c::get_is_valid() |
|
110 { |
|
111 return m_is_valid; |
|
112 } |
|
113 |
|
114 //-------------------------------------------------- |
|
115 |
|
116 inline u32_t eap_am_crypto_md4_c::eap_md4_rotate_left( |
|
117 const u32_t value, |
|
118 const u32_t shift |
|
119 ) |
|
120 { |
|
121 return (value << shift) | (value >> (32ul - shift)); |
|
122 } |
|
123 |
|
124 //-------------------------------------------------- |
|
125 |
|
126 inline void eap_am_crypto_md4_c::eap_md4_FF( |
|
127 const u32_t index, |
|
128 u32_t * const A, |
|
129 const u32_t B, |
|
130 const u32_t C, |
|
131 const u32_t D, |
|
132 const u32_t X, |
|
133 const u32_t S |
|
134 ) |
|
135 { |
|
136 EAP_UNREFERENCED_PARAMETER(index); |
|
137 |
|
138 *A += eap_md4_F(B, C, D) + X; |
|
139 *A = eap_md4_rotate_left(*A, S); |
|
140 |
|
141 EAP_MD4_TRACE_DEBUG(m_am_tools, EAP_TRACE_MASK_MD4, |
|
142 (EAPL("MD4: t=%d\t%08x\t%08x\t%08x\t%08x\t%08x\t% 8d\n"), |
|
143 index, *A, B, C, D, X, S)); |
|
144 } |
|
145 |
|
146 //-------------------------------------------------- |
|
147 |
|
148 inline void eap_am_crypto_md4_c::eap_md4_GG( |
|
149 const u32_t index, |
|
150 u32_t * const A, |
|
151 const u32_t B, |
|
152 const u32_t C, |
|
153 const u32_t D, |
|
154 const u32_t X, |
|
155 const u32_t S |
|
156 ) |
|
157 { |
|
158 EAP_UNREFERENCED_PARAMETER(index); |
|
159 |
|
160 *A += eap_md4_G(B, C, D) + X + 0x5a827999; |
|
161 *A = eap_md4_rotate_left(*A, S); |
|
162 |
|
163 EAP_MD4_TRACE_DEBUG(m_am_tools, EAP_TRACE_MASK_MD4, |
|
164 (EAPL("MD4: t=%d\t%08x\t%08x\t%08x\t%08x\t%08x\t% 8d\n"), |
|
165 index, *A, B, C, D, X, S)); |
|
166 } |
|
167 |
|
168 //-------------------------------------------------- |
|
169 |
|
170 inline void eap_am_crypto_md4_c::eap_md4_HH( |
|
171 const u32_t index, |
|
172 u32_t * const A, |
|
173 const u32_t B, |
|
174 const u32_t C, |
|
175 const u32_t D, |
|
176 const u32_t X, |
|
177 const u32_t S |
|
178 ) |
|
179 { |
|
180 EAP_UNREFERENCED_PARAMETER(index); |
|
181 |
|
182 *A += eap_md4_H(B, C, D) + X + 0x6ed9eba1; |
|
183 *A = eap_md4_rotate_left(*A, S); |
|
184 |
|
185 EAP_MD4_TRACE_DEBUG(m_am_tools, EAP_TRACE_MASK_MD4, |
|
186 (EAPL("MD4: t=%d\t%08x\t%08x\t%08x\t%08x\t%08x\t% 8d\n"), |
|
187 index, *A, B, C, D, X, S)); |
|
188 } |
|
189 |
|
190 //-------------------------------------------------- |
|
191 |
|
192 inline u32_t eap_am_crypto_md4_c::eap_md4_F( |
|
193 const u32_t X, |
|
194 const u32_t Y, |
|
195 const u32_t Z |
|
196 ) |
|
197 { |
|
198 return (X & Y) | ((~X) & Z); |
|
199 } |
|
200 |
|
201 //-------------------------------------------------- |
|
202 |
|
203 inline u32_t eap_am_crypto_md4_c::eap_md4_G( |
|
204 const u32_t X, |
|
205 const u32_t Y, |
|
206 const u32_t Z |
|
207 ) |
|
208 { |
|
209 return (X & Y) | (X & Z) | (Y & Z); |
|
210 } |
|
211 |
|
212 |
|
213 //-------------------------------------------------- |
|
214 |
|
215 inline u32_t eap_am_crypto_md4_c::eap_md4_H( |
|
216 const u32_t X, |
|
217 const u32_t Y, |
|
218 const u32_t Z |
|
219 ) |
|
220 { |
|
221 return (X ^ Y ^ Z); |
|
222 } |
|
223 |
|
224 |
|
225 //-------------------------------------------------- |
|
226 |
|
227 EAP_FUNC_EXPORT eap_status_e eap_am_crypto_md4_c::eap_md4_process_data( |
|
228 const u32_t * const W, |
|
229 const u32_t W_count |
|
230 ) |
|
231 { |
|
232 if (W == 0 |
|
233 //|| (reinterpret_cast<u32_t>(W) % sizeof(u32_t)) != 0 |
|
234 || W_count == 0 |
|
235 || (W_count % EAP_AM_CRYPTO_MD4_BLOCK_u32_COUNT) != 0) |
|
236 { |
|
237 EAP_ASSERT_ANYWAY; |
|
238 EAP_SYSTEM_DEBUG_BREAK(); |
|
239 return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_parameter); |
|
240 } |
|
241 |
|
242 |
|
243 eap_status_e status = eap_status_ok; |
|
244 |
|
245 // Array of 16 temporary 32-bit unsigned integers. |
|
246 u32_t count = W_count / EAP_AM_CRYPTO_MD4_BLOCK_u32_COUNT; |
|
247 |
|
248 for (u32_t ind = 0ul; ind < count; ind++) |
|
249 { |
|
250 for (u32_t ind_W = 0ul; ind_W < EAP_AM_CRYPTO_MD4_BLOCK_u32_COUNT |
|
251 ; ind_W++) |
|
252 { |
|
253 // Here we must read data in 8-bit blocks bacause W can be aligned at any position. |
|
254 const u8_t * const data = reinterpret_cast<const u8_t *>(&W[ind*EAP_AM_CRYPTO_MD4_BLOCK_u32_COUNT+ind_W]); |
|
255 m_W_in_host_order[ind_W] |
|
256 = (data[0] << 0) |
|
257 | (data[1] << 8) |
|
258 | (data[2] << 16) |
|
259 | (data[3] << 24); |
|
260 } // for() |
|
261 |
|
262 status = eap_md4_transform_host_order( |
|
263 m_W_in_host_order, |
|
264 EAP_AM_CRYPTO_MD4_BLOCK_u32_COUNT); |
|
265 if (status != eap_status_ok) |
|
266 { |
|
267 return EAP_STATUS_RETURN(m_am_tools, status); |
|
268 } |
|
269 |
|
270 } // for() |
|
271 |
|
272 return EAP_STATUS_RETURN(m_am_tools, status); |
|
273 } |
|
274 |
|
275 //-------------------------------------------------- |
|
276 |
|
277 EAP_FUNC_EXPORT eap_status_e eap_am_crypto_md4_c::eap_md4_transform_host_order( |
|
278 const u32_t * const W, |
|
279 const u32_t W_count |
|
280 ) |
|
281 { |
|
282 u32_t A = m_H[0]; |
|
283 u32_t B = m_H[1]; |
|
284 u32_t C = m_H[2]; |
|
285 u32_t D = m_H[3]; |
|
286 |
|
287 if (W == 0 |
|
288 //|| (reinterpret_cast<u32_t>(W) % sizeof(u32_t)) != 0 |
|
289 || W_count != EAP_AM_CRYPTO_MD4_BLOCK_u32_COUNT) |
|
290 { |
|
291 EAP_ASSERT_ANYWAY; |
|
292 EAP_SYSTEM_DEBUG_BREAK(); |
|
293 return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_parameter); |
|
294 } |
|
295 |
|
296 const u32_t * const X = W; |
|
297 |
|
298 #if defined(_DEBUG) |
|
299 |
|
300 EAP_MD4_TRACE_DEBUG(m_am_tools, EAP_TRACE_MASK_MD4, |
|
301 (EAPL("MD4: A=%08x\tB=%08x\tC=%08x\tD=%08x\n"), |
|
302 A, B, C, D)); |
|
303 |
|
304 u32_t ind; |
|
305 for (ind = 0ul; ind < W_count; ind++) |
|
306 { |
|
307 EAP_MD4_TRACE_DEBUG(m_am_tools, EAP_TRACE_MASK_MD4, |
|
308 (EAPL("MD4: W[%d]=%08x\n"), |
|
309 ind, |
|
310 W[ind])); |
|
311 } // for() |
|
312 |
|
313 EAP_MD4_TRACE_DEBUG(m_am_tools, EAP_TRACE_MASK_MD4, |
|
314 (EAPL("MD4: \n"))); |
|
315 |
|
316 for (ind = 0ul; ind < sizeof(X)/sizeof(X[0]); ind++) |
|
317 { |
|
318 EAP_MD4_TRACE_DEBUG(m_am_tools, EAP_TRACE_MASK_MD4, |
|
319 (EAPL("MD4: X[%d]=%08x\n"), |
|
320 ind, |
|
321 X[ind])); |
|
322 } // for() |
|
323 |
|
324 EAP_MD4_TRACE_DEBUG(m_am_tools, EAP_TRACE_MASK_MD4, |
|
325 (EAPL("MD4: % 5s\t% 8s\t% 8s\t% 8s\t% 8s\t% 8s\t% 8s\n"), |
|
326 "index", "A", "B", "C", "D", "X", "shift")); |
|
327 |
|
328 #endif //#if defined(_DEBUG) |
|
329 |
|
330 |
|
331 eap_md4_FF( 1, &A, B, C, D, X[ 0], eap_md4_const_S11); |
|
332 eap_md4_FF( 2, &D, A, B, C, X[ 1], eap_md4_const_S12); |
|
333 eap_md4_FF( 3, &C, D, A, B, X[ 2], eap_md4_const_S13); |
|
334 eap_md4_FF( 4, &B, C, D, A, X[ 3], eap_md4_const_S14); |
|
335 eap_md4_FF( 5, &A, B, C, D, X[ 4], eap_md4_const_S11); |
|
336 eap_md4_FF( 6, &D, A, B, C, X[ 5], eap_md4_const_S12); |
|
337 eap_md4_FF( 7, &C, D, A, B, X[ 6], eap_md4_const_S13); |
|
338 eap_md4_FF( 8, &B, C, D, A, X[ 7], eap_md4_const_S14); |
|
339 eap_md4_FF( 9, &A, B, C, D, X[ 8], eap_md4_const_S11); |
|
340 eap_md4_FF(10, &D, A, B, C, X[ 9], eap_md4_const_S12); |
|
341 eap_md4_FF(11, &C, D, A, B, X[10], eap_md4_const_S13); |
|
342 eap_md4_FF(12, &B, C, D, A, X[11], eap_md4_const_S14); |
|
343 eap_md4_FF(13, &A, B, C, D, X[12], eap_md4_const_S11); |
|
344 eap_md4_FF(14, &D, A, B, C, X[13], eap_md4_const_S12); |
|
345 eap_md4_FF(15, &C, D, A, B, X[14], eap_md4_const_S13); |
|
346 eap_md4_FF(16, &B, C, D, A, X[15], eap_md4_const_S14); |
|
347 |
|
348 eap_md4_GG(17, &A, B, C, D, X[ 0], eap_md4_const_S21); |
|
349 eap_md4_GG(18, &D, A, B, C, X[ 4], eap_md4_const_S22); |
|
350 eap_md4_GG(19, &C, D, A, B, X[ 8], eap_md4_const_S23); |
|
351 eap_md4_GG(20, &B, C, D, A, X[12], eap_md4_const_S24); |
|
352 eap_md4_GG(21, &A, B, C, D, X[ 1], eap_md4_const_S21); |
|
353 eap_md4_GG(22, &D, A, B, C, X[ 5], eap_md4_const_S22); |
|
354 eap_md4_GG(23, &C, D, A, B, X[ 9], eap_md4_const_S23); |
|
355 eap_md4_GG(24, &B, C, D, A, X[13], eap_md4_const_S24); |
|
356 eap_md4_GG(25, &A, B, C, D, X[ 2], eap_md4_const_S21); |
|
357 eap_md4_GG(26, &D, A, B, C, X[ 6], eap_md4_const_S22); |
|
358 eap_md4_GG(27, &C, D, A, B, X[10], eap_md4_const_S23); |
|
359 eap_md4_GG(28, &B, C, D, A, X[14], eap_md4_const_S24); |
|
360 eap_md4_GG(29, &A, B, C, D, X[ 3], eap_md4_const_S21); |
|
361 eap_md4_GG(30, &D, A, B, C, X[ 7], eap_md4_const_S22); |
|
362 eap_md4_GG(31, &C, D, A, B, X[11], eap_md4_const_S23); |
|
363 eap_md4_GG(32, &B, C, D, A, X[15], eap_md4_const_S24); |
|
364 |
|
365 eap_md4_HH(33, &A, B, C, D, X[ 0], eap_md4_const_S31); |
|
366 eap_md4_HH(34, &D, A, B, C, X[ 8], eap_md4_const_S32); |
|
367 eap_md4_HH(35, &C, D, A, B, X[ 4], eap_md4_const_S33); |
|
368 eap_md4_HH(36, &B, C, D, A, X[12], eap_md4_const_S34); |
|
369 eap_md4_HH(37, &A, B, C, D, X[ 2], eap_md4_const_S31); |
|
370 eap_md4_HH(38, &D, A, B, C, X[10], eap_md4_const_S32); |
|
371 eap_md4_HH(39, &C, D, A, B, X[ 6], eap_md4_const_S33); |
|
372 eap_md4_HH(40, &B, C, D, A, X[14], eap_md4_const_S34); |
|
373 eap_md4_HH(41, &A, B, C, D, X[ 1], eap_md4_const_S31); |
|
374 eap_md4_HH(42, &D, A, B, C, X[ 9], eap_md4_const_S32); |
|
375 eap_md4_HH(43, &C, D, A, B, X[ 5], eap_md4_const_S33); |
|
376 eap_md4_HH(44, &B, C, D, A, X[13], eap_md4_const_S34); |
|
377 eap_md4_HH(45, &A, B, C, D, X[ 3], eap_md4_const_S31); |
|
378 eap_md4_HH(46, &D, A, B, C, X[11], eap_md4_const_S32); |
|
379 eap_md4_HH(47, &C, D, A, B, X[ 7], eap_md4_const_S33); |
|
380 eap_md4_HH(48, &B, C, D, A, X[15], eap_md4_const_S34); |
|
381 |
|
382 m_H[0] += A; |
|
383 m_H[1] += B; |
|
384 m_H[2] += C; |
|
385 m_H[3] += D; |
|
386 |
|
387 EAP_MD4_TRACE_DEBUG(m_am_tools, EAP_TRACE_MASK_MD4, |
|
388 (EAPL("MD4: digest=\t%08x\t%08x\t%08x\t%08x\n"), |
|
389 m_H[0], m_H[1], m_H[2], m_H[3])); |
|
390 |
|
391 return EAP_STATUS_RETURN(m_am_tools, eap_status_ok); |
|
392 } |
|
393 |
|
394 //-------------------------------------------------- |
|
395 |
|
396 EAP_FUNC_EXPORT eap_status_e eap_am_crypto_md4_c::copy_message_digest( |
|
397 void * const output, |
|
398 u32_t * const max_output_size) |
|
399 { |
|
400 if (output == 0 |
|
401 || max_output_size == 0 |
|
402 || *max_output_size < EAP_AM_CRYPTO_MD4_DIGEST_BUFFER_BYTE_SIZE) |
|
403 { |
|
404 return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_parameter); |
|
405 } |
|
406 |
|
407 #if defined(EAP_LITTLE_ENDIAN) |
|
408 |
|
409 m_am_tools->memmove(output, m_H, EAP_AM_CRYPTO_MD4_DIGEST_BUFFER_BYTE_SIZE); |
|
410 |
|
411 #elif defined(EAP_BIG_ENDIAN) |
|
412 |
|
413 // We must change the data from host order to network order. |
|
414 u32_t * const tmp_H = static_cast<u32_t *>(output); |
|
415 for (u32_t ind = 0ul; ind < EAP_AM_CRYPTO_MD4_DIGEST_BUFFER_u32_COUNT |
|
416 ; ind++) |
|
417 { |
|
418 tmp_H[ind] = eap_htonl(m_H[ind]); |
|
419 } // for() |
|
420 |
|
421 #else |
|
422 #error ERROR: define EAP_LITTLE_ENDIAN (byte 0 is least significant \ |
|
423 (i386)) or EAP_BIG_ENDIAN (byte 0 is most significant (mc68k)). |
|
424 #endif |
|
425 |
|
426 *max_output_size = EAP_AM_CRYPTO_MD4_DIGEST_BUFFER_BYTE_SIZE; |
|
427 |
|
428 return EAP_STATUS_RETURN(m_am_tools, eap_status_ok); |
|
429 } |
|
430 |
|
431 |
|
432 //-------------------------------------------------- |
|
433 |
|
434 /** |
|
435 * This function returns the size of message digest of HASH-algorithm. |
|
436 */ |
|
437 EAP_FUNC_EXPORT u32_t eap_am_crypto_md4_c::get_digest_length() |
|
438 { |
|
439 return EAP_AM_CRYPTO_MD4_DIGEST_BUFFER_BYTE_SIZE; |
|
440 } |
|
441 |
|
442 //-------------------------------------------------- |
|
443 |
|
444 /** |
|
445 * This function returns the size of block of HASH-algorithm. |
|
446 */ |
|
447 EAP_FUNC_EXPORT u32_t eap_am_crypto_md4_c::get_block_size() |
|
448 { |
|
449 return EAP_AM_CRYPTO_MD4_BLOCK_BYTE_SIZE; |
|
450 } |
|
451 |
|
452 //-------------------------------------------------- |
|
453 |
|
454 /** |
|
455 * This function initializes the context of MD4-algorithm. |
|
456 */ |
|
457 EAP_FUNC_EXPORT eap_status_e eap_am_crypto_md4_c::hash_init() |
|
458 { |
|
459 m_full_hashed_data_length = 0ul; |
|
460 |
|
461 m_H[0] = static_cast<u32_t>(EAP_MD4_INIT_H0); |
|
462 m_H[1] = static_cast<u32_t>(EAP_MD4_INIT_H1); |
|
463 m_H[2] = static_cast<u32_t>(EAP_MD4_INIT_H2); |
|
464 m_H[3] = static_cast<u32_t>(EAP_MD4_INIT_H3); |
|
465 |
|
466 return EAP_STATUS_RETURN(m_am_tools, eap_status_ok); |
|
467 } |
|
468 |
|
469 //-------------------------------------------------- |
|
470 |
|
471 /** |
|
472 * This function updates the context of MD4-algorithm with data. |
|
473 */ |
|
474 EAP_FUNC_EXPORT eap_status_e eap_am_crypto_md4_c::hash_update( |
|
475 const void * const data, |
|
476 const u32_t data_length) |
|
477 { |
|
478 eap_status_e status = eap_status_ok; |
|
479 u32_t prosessed_data_length = 0ul; |
|
480 |
|
481 m_full_hashed_data_length += data_length; |
|
482 |
|
483 EAP_MD4_TRACE_DEBUG(m_am_tools, EAP_TRACE_MASK_MD4, |
|
484 (EAPL("MD4: Processed data length %u\n"), |
|
485 m_full_hashed_data_length)); |
|
486 |
|
487 if (m_saved_data.get_is_valid_data() == true |
|
488 && m_saved_data.get_data_length() > 0ul) |
|
489 { |
|
490 // Here we have remaining data to process from previous call |
|
491 // of hash_update(). |
|
492 u32_t needed_data_length = EAP_AM_CRYPTO_MD4_BLOCK_BYTE_SIZE |
|
493 - m_saved_data.get_data_length(); |
|
494 if (needed_data_length > data_length) |
|
495 { |
|
496 // Not enough input data. |
|
497 needed_data_length = data_length; |
|
498 } |
|
499 |
|
500 prosessed_data_length = needed_data_length; |
|
501 status = m_saved_data.add_data(data, needed_data_length); |
|
502 if (status != eap_status_ok) |
|
503 { |
|
504 return EAP_STATUS_RETURN(m_am_tools, status); |
|
505 } |
|
506 |
|
507 if (m_saved_data.get_data_length() |
|
508 == EAP_AM_CRYPTO_MD4_BLOCK_BYTE_SIZE) |
|
509 { |
|
510 // Enough data to process. |
|
511 // Just one block of integers in W array. |
|
512 status = eap_md4_process_data( |
|
513 reinterpret_cast<const u32_t *>( |
|
514 m_saved_data.get_data( |
|
515 m_saved_data.get_data_length())), |
|
516 EAP_AM_CRYPTO_MD4_BLOCK_u32_COUNT |
|
517 ); |
|
518 if (status != eap_status_ok) |
|
519 { |
|
520 return EAP_STATUS_RETURN(m_am_tools, status); |
|
521 } |
|
522 |
|
523 m_saved_data.reset(); |
|
524 } |
|
525 |
|
526 EAP_ASSERT(m_saved_data.get_is_valid_data() == false |
|
527 || m_saved_data.get_data_length() |
|
528 <= EAP_AM_CRYPTO_MD4_BLOCK_BYTE_SIZE); |
|
529 } |
|
530 |
|
531 u32_t remaining_data_length = data_length - prosessed_data_length; |
|
532 u32_t full_block_count = remaining_data_length |
|
533 / EAP_AM_CRYPTO_MD4_BLOCK_BYTE_SIZE; |
|
534 |
|
535 if (full_block_count > 0ul) |
|
536 { |
|
537 // Here we have full blocks to process. |
|
538 status = eap_md4_process_data( |
|
539 reinterpret_cast<const u32_t *>( |
|
540 static_cast<const u8_t *>(data)+prosessed_data_length), |
|
541 full_block_count * EAP_AM_CRYPTO_MD4_BLOCK_u32_COUNT |
|
542 ); |
|
543 if (status != eap_status_ok) |
|
544 { |
|
545 return EAP_STATUS_RETURN(m_am_tools, status); |
|
546 } |
|
547 |
|
548 prosessed_data_length += sizeof(u32_t) * full_block_count |
|
549 * EAP_AM_CRYPTO_MD4_BLOCK_u32_COUNT; |
|
550 } |
|
551 |
|
552 if (data_length > prosessed_data_length) |
|
553 { |
|
554 // Save the remaining data. |
|
555 status = m_saved_data.add_data( |
|
556 static_cast<const u8_t *>(data)+prosessed_data_length, |
|
557 data_length-prosessed_data_length); |
|
558 if (status != eap_status_ok) |
|
559 { |
|
560 return EAP_STATUS_RETURN(m_am_tools, status); |
|
561 } |
|
562 } |
|
563 |
|
564 return EAP_STATUS_RETURN(m_am_tools, status); |
|
565 } |
|
566 |
|
567 //-------------------------------------------------- |
|
568 |
|
569 /** |
|
570 * This function writes the message digest to buffer. |
|
571 * @param Length is set if md_length_or_null is non-NULL. |
|
572 */ |
|
573 EAP_FUNC_EXPORT eap_status_e eap_am_crypto_md4_c::hash_final( |
|
574 void * const message_digest, |
|
575 u32_t *md_length_or_null) |
|
576 { |
|
577 eap_status_e status = eap_status_ok; |
|
578 |
|
579 if (message_digest == 0) |
|
580 { |
|
581 return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_parameter); |
|
582 } |
|
583 |
|
584 // First add the one bit. We use one byte 0x80. |
|
585 u8_t bit_pad = 0x80; |
|
586 status = m_saved_data.add_data(&bit_pad, sizeof(bit_pad)); |
|
587 if (status != eap_status_ok) |
|
588 { |
|
589 return EAP_STATUS_RETURN(m_am_tools, status); |
|
590 } |
|
591 |
|
592 // Here we may have remaining data to process from previous call |
|
593 // of hash_update(). |
|
594 u32_t min_data_length = m_saved_data.get_data_length() + sizeof(u64_t); |
|
595 u32_t padding_zero_count = 0ul; |
|
596 u32_t block_count = min_data_length / EAP_AM_CRYPTO_MD4_BLOCK_BYTE_SIZE; |
|
597 if ((min_data_length % EAP_AM_CRYPTO_MD4_BLOCK_BYTE_SIZE) != 0) |
|
598 { |
|
599 // Last block is not full. |
|
600 ++block_count; |
|
601 } |
|
602 padding_zero_count = (block_count*EAP_AM_CRYPTO_MD4_BLOCK_BYTE_SIZE) |
|
603 - min_data_length; |
|
604 |
|
605 // Now we need to pad the remaining data. |
|
606 u32_t data_length = m_saved_data.get_data_length(); |
|
607 status = m_saved_data.set_buffer_length(data_length+padding_zero_count); |
|
608 if (status != eap_status_ok) |
|
609 { |
|
610 return EAP_STATUS_RETURN(m_am_tools, status); |
|
611 } |
|
612 m_saved_data.set_data_length(data_length+padding_zero_count); |
|
613 |
|
614 u8_t * const padding = m_saved_data.get_data_offset(data_length, padding_zero_count); |
|
615 if (padding == 0) |
|
616 { |
|
617 return EAP_STATUS_RETURN(m_am_tools, eap_status_buffer_too_short); |
|
618 } |
|
619 |
|
620 m_am_tools->memset( |
|
621 padding, |
|
622 0, |
|
623 padding_zero_count); |
|
624 |
|
625 // And finally the length of the hashed data is added to block. |
|
626 // Note the length is in bits. |
|
627 |
|
628 #if defined(EAP_LITTLE_ENDIAN) |
|
629 u64_t full_hashed_data_length = eap_shift_left_64_bit(m_full_hashed_data_length, 3ul); |
|
630 #elif defined(EAP_BIG_ENDIAN) |
|
631 u64_t full_hashed_data_length = eap_htonll(eap_shift_left_64_bit(m_full_hashed_data_length, 3ul)); |
|
632 #else |
|
633 #error ERROR: define EAP_LITTLE_ENDIAN (byte 0 is least significant (i386)) \ |
|
634 or EAP_BIG_ENDIAN (byte 0 is most significant (mc68k)). |
|
635 #endif |
|
636 status = m_saved_data.add_data( |
|
637 &full_hashed_data_length, |
|
638 sizeof(full_hashed_data_length)); |
|
639 if (status != eap_status_ok) |
|
640 { |
|
641 return EAP_STATUS_RETURN(m_am_tools, status); |
|
642 } |
|
643 |
|
644 EAP_ASSERT(m_saved_data.get_data_length() |
|
645 >= EAP_AM_CRYPTO_MD4_BLOCK_BYTE_SIZE |
|
646 && (m_saved_data.get_data_length() |
|
647 % EAP_AM_CRYPTO_MD4_BLOCK_BYTE_SIZE) == 0); |
|
648 |
|
649 u32_t full_block_count = m_saved_data.get_data_length() |
|
650 / EAP_AM_CRYPTO_MD4_BLOCK_BYTE_SIZE; |
|
651 |
|
652 status = eap_md4_process_data( |
|
653 reinterpret_cast<const u32_t *>( |
|
654 m_saved_data.get_data( |
|
655 m_saved_data.get_data_length())), |
|
656 full_block_count * EAP_AM_CRYPTO_MD4_BLOCK_u32_COUNT |
|
657 ); |
|
658 if (status != eap_status_ok) |
|
659 { |
|
660 return EAP_STATUS_RETURN(m_am_tools, status); |
|
661 } |
|
662 |
|
663 m_saved_data.reset(); |
|
664 |
|
665 |
|
666 u32_t output_length = 0ul; |
|
667 if (md_length_or_null == 0) |
|
668 { |
|
669 // Let's use temporary length variable. |
|
670 output_length = EAP_AM_CRYPTO_MD4_DIGEST_BUFFER_BYTE_SIZE; |
|
671 md_length_or_null = &output_length; |
|
672 } |
|
673 |
|
674 status = copy_message_digest( |
|
675 message_digest, |
|
676 md_length_or_null); |
|
677 if (status != eap_status_ok) |
|
678 { |
|
679 return EAP_STATUS_RETURN(m_am_tools, status); |
|
680 } |
|
681 |
|
682 return EAP_STATUS_RETURN(m_am_tools, eap_status_ok); |
|
683 } |
|
684 |
|
685 //-------------------------------------------------- |
|
686 |
|
687 /** |
|
688 * This function cleans up the MD4 context. |
|
689 */ |
|
690 EAP_FUNC_EXPORT eap_status_e eap_am_crypto_md4_c::hash_cleanup() |
|
691 { |
|
692 m_saved_data.reset(); |
|
693 m_full_hashed_data_length = 0ul; |
|
694 m_am_tools->memset(m_H, 0, EAP_AM_CRYPTO_MD4_DIGEST_BUFFER_BYTE_SIZE); |
|
695 |
|
696 return EAP_STATUS_RETURN(m_am_tools, eap_status_ok); |
|
697 } |
|
698 |
|
699 //-------------------------------------------------- |
|
700 |
|
701 /** |
|
702 * This function copies the context of MD4. |
|
703 */ |
|
704 EAP_FUNC_EXPORT eap_status_e eap_am_crypto_md4_c::copy_context( |
|
705 const eap_variable_data_c * const saved_data, |
|
706 const u64_t full_hashed_data_length, |
|
707 const u32_t * const H, |
|
708 const u32_t * const W_in_host_order) |
|
709 { |
|
710 if (saved_data->get_is_valid_data() == true) |
|
711 { |
|
712 eap_status_e status = m_saved_data.set_copy_of_buffer(saved_data); |
|
713 if (status != eap_status_ok) |
|
714 { |
|
715 return EAP_STATUS_RETURN(m_am_tools, status); |
|
716 } |
|
717 } |
|
718 else |
|
719 { |
|
720 // No saved data. Just reset. |
|
721 m_saved_data.reset(); |
|
722 } |
|
723 |
|
724 m_full_hashed_data_length = full_hashed_data_length; |
|
725 |
|
726 m_am_tools->memmove(m_H, H, sizeof(m_H)); |
|
727 |
|
728 m_am_tools->memmove(m_W_in_host_order, W_in_host_order, sizeof(m_W_in_host_order)); |
|
729 |
|
730 return EAP_STATUS_RETURN(m_am_tools, eap_status_ok); |
|
731 } |
|
732 |
|
733 //-------------------------------------------------- |
|
734 |
|
735 /** |
|
736 * This function copies the context of MD4. |
|
737 */ |
|
738 EAP_FUNC_EXPORT eap_am_crypto_md4_c * eap_am_crypto_md4_c::copy() |
|
739 { |
|
740 eap_am_crypto_md4_c * const md4 = new eap_am_crypto_md4_c(m_am_tools); |
|
741 if (md4 == 0 |
|
742 || md4->get_is_valid() == false) |
|
743 { |
|
744 delete md4; |
|
745 return 0; |
|
746 } |
|
747 |
|
748 eap_status_e status = md4->copy_context(&m_saved_data, m_full_hashed_data_length, m_H, m_W_in_host_order); |
|
749 if (status != eap_status_ok) |
|
750 { |
|
751 delete md4; |
|
752 return 0; |
|
753 } |
|
754 |
|
755 return md4; |
|
756 } |
|
757 |
|
758 //-------------------------------------------------- |
|
759 |
|
760 |
|
761 |
|
762 // End. |