eapol/eapol_framework/eapol_common/am/common/crypto/sha1/eap_am_crypto_sha1.cpp
changeset 0 c8830336c852
child 2 1c7bc153c08e
equal deleted inserted replaced
-1:000000000000 0:c8830336c852
       
     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 7 
       
    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_sha1.h"
       
    31 
       
    32 //--------------------------------------------------
       
    33 
       
    34 #if 1
       
    35 	#define EAP_SHA1_TRACE_DEBUG EAP_TRACE_DEBUG
       
    36 	#define EAP_SHA1_TRACE_DATA_DEBUG EAP_TRACE_DATA_DEBUG
       
    37 #else
       
    38 	#define EAP_SHA1_TRACE_DEBUG(tools, flags, params)
       
    39 	#define EAP_SHA1_TRACE_DATA_DEBUG(object_name, flags, _parameter_list_)
       
    40 #endif
       
    41 
       
    42 #if defined(USE_EAP_TRACE)	
       
    43 	static const u32_t EAP_TRACE_MASK_SHA1 = eap_am_tools_c::eap_trace_mask_crypto_sha1;
       
    44 #endif //#if defined(USE_EAP_TRACE)	
       
    45 
       
    46 //--------------------------------------------------
       
    47 
       
    48 EAP_FUNC_EXPORT eap_am_crypto_sha1_c::~eap_am_crypto_sha1_c()
       
    49 {
       
    50 	hash_cleanup();
       
    51 }
       
    52 
       
    53 //--------------------------------------------------
       
    54 
       
    55 EAP_FUNC_EXPORT eap_am_crypto_sha1_c::eap_am_crypto_sha1_c(
       
    56 	abs_eap_am_tools_c * const tools)
       
    57 	: m_am_tools(tools)
       
    58 	, m_saved_data(tools)
       
    59 	, m_full_hashed_data_length(0ul)
       
    60 	, m_is_valid(false)
       
    61 {
       
    62 	m_H[0] = 0;
       
    63 	m_T[0] = 0;
       
    64 	m_W_in_host_order[0] = 0;
       
    65 
       
    66 	if (m_saved_data.get_is_valid() == false)
       
    67 	{
       
    68 		return;
       
    69 	}
       
    70 
       
    71 	eap_status_e status = hash_init();
       
    72 	if (status != eap_status_ok)
       
    73 	{
       
    74 		return;
       
    75 	}
       
    76 
       
    77 	set_is_valid();
       
    78 }
       
    79 
       
    80 //------------------------------------------------------------
       
    81 
       
    82 /**
       
    83  * The set_is_invalid() function sets the state of the eap_am_crypto_sha1_c
       
    84  * object invalid. 
       
    85  * The eap_am_crypto_sha1_c object calls this function after it is initialized.
       
    86  */
       
    87 EAP_FUNC_EXPORT void eap_am_crypto_sha1_c::set_is_invalid()
       
    88 {
       
    89 	m_is_valid = false;
       
    90 }
       
    91 
       
    92 //------------------------------------------------------------
       
    93 
       
    94 /**
       
    95  * The set_is_valid() function sets the state of the eap_am_crypto_sha1_c
       
    96  * object valid. 
       
    97  * The eap_am_crypto_sha1_c object calls this function after it is initialized.
       
    98  */
       
    99 EAP_FUNC_EXPORT void eap_am_crypto_sha1_c::set_is_valid()
       
   100 {
       
   101 	m_is_valid = true;
       
   102 }
       
   103 
       
   104 //------------------------------------------------------------
       
   105 
       
   106 /**
       
   107  * The get_is_valid() function returns the status of the eap_am_crypto_sha1_c
       
   108  * object. 
       
   109  * True indicates the object is allocated successfully.
       
   110  */
       
   111 EAP_FUNC_EXPORT bool eap_am_crypto_sha1_c::get_is_valid()
       
   112 {
       
   113 	return m_is_valid;
       
   114 }
       
   115 
       
   116 //--------------------------------------------------
       
   117 
       
   118 inline u32_t eap_am_crypto_sha1_c::eap_sha1_rotate(
       
   119 	const u32_t value,
       
   120 	const u32_t shift
       
   121 	)
       
   122 {
       
   123 	return (value << shift) | (value >> (32ul - shift));
       
   124 }
       
   125 
       
   126 //--------------------------------------------------
       
   127 
       
   128 inline u32_t eap_am_crypto_sha1_c::eap_sha1_b_substitution(
       
   129 	const u32_t Wt_3,
       
   130 	const u32_t Wt_8,
       
   131 	const u32_t Wt_14,
       
   132 	const u32_t Wt_16
       
   133 	)
       
   134 {
       
   135 	return eap_sha1_rotate(Wt_3 ^ Wt_8 ^ Wt_14 ^ Wt_16, 1ul);
       
   136 }
       
   137 
       
   138 //--------------------------------------------------
       
   139 
       
   140 inline u32_t eap_am_crypto_sha1_c::eap_sha1_ft_0_19(
       
   141 	const u32_t B,
       
   142 	const u32_t C,
       
   143 	const u32_t D
       
   144 	)
       
   145 {
       
   146 	return (((C ^ D) & B) ^ D);
       
   147 }
       
   148 
       
   149 //--------------------------------------------------
       
   150 
       
   151 inline u32_t eap_am_crypto_sha1_c::eap_sha1_ft_20_39(
       
   152 	const u32_t B,
       
   153 	const u32_t C,
       
   154 	const u32_t D
       
   155 	)
       
   156 {
       
   157 	return (B ^ C ^ D);
       
   158 }
       
   159 
       
   160 //--------------------------------------------------
       
   161 
       
   162 inline u32_t eap_am_crypto_sha1_c::eap_sha1_ft_40_59(
       
   163 	const u32_t B,
       
   164 	const u32_t C,
       
   165 	const u32_t D
       
   166 	)
       
   167 {
       
   168 	return ((B & C) | ((B | C) & D));
       
   169 }
       
   170 
       
   171 //--------------------------------------------------
       
   172 
       
   173 inline u32_t eap_am_crypto_sha1_c::eap_sha1_ft_60_79(
       
   174 	const u32_t B,
       
   175 	const u32_t C,
       
   176 	const u32_t D
       
   177 	)
       
   178 {
       
   179 	return eap_sha1_ft_20_39(B, C, D);
       
   180 }
       
   181 
       
   182 //--------------------------------------------------
       
   183 
       
   184 inline void eap_am_crypto_sha1_c::d_substitution(
       
   185 	u32_t * const A,
       
   186 	u32_t * const B,
       
   187 	u32_t * const C,
       
   188 	u32_t * const D,
       
   189 	u32_t * const E,
       
   190 	const u32_t temp
       
   191 	)
       
   192 {
       
   193 	*E = *D;
       
   194 	*D = *C;
       
   195 	*C = eap_sha1_rotate(*B, 30ul);
       
   196 	*B = *A;
       
   197 	*A = temp;
       
   198 }
       
   199 
       
   200 //--------------------------------------------------
       
   201 
       
   202 inline void eap_am_crypto_sha1_c::d_substitution_0_15(
       
   203 	const u32_t t,
       
   204 	u32_t * const A,
       
   205 	u32_t * const B,
       
   206 	u32_t * const C,
       
   207 	u32_t * const D,
       
   208 	u32_t * const E,
       
   209 	const u32_t Wt
       
   210 	)
       
   211 {
       
   212 	EAP_UNREFERENCED_PARAMETER(t);
       
   213 
       
   214 	const u32_t TEMP = eap_sha1_rotate(*A, 5ul)
       
   215 		+ eap_sha1_ft_0_19(*B, *C, *D)
       
   216 		+ *E + Wt + eap_am_crypto_sha1_c::EAP_SHA1_K__0_19;
       
   217 
       
   218 	d_substitution(A, B, C, D, E, TEMP);
       
   219 
       
   220 	EAP_SHA1_TRACE_DEBUG(m_am_tools, EAP_TRACE_MASK_SHA1,
       
   221 					(EAPL("SHA1: t=%d\t%08x\t%08x\t%08x\t%08x\t%08x\n"),
       
   222 					 t, *A, *B, *C, *D, *E));
       
   223 }
       
   224 
       
   225 //--------------------------------------------------
       
   226 
       
   227 inline void eap_am_crypto_sha1_c::d_substitution_16_19(
       
   228 	const u32_t t,
       
   229 	u32_t * const A,
       
   230 	u32_t * const B,
       
   231 	u32_t * const C,
       
   232 	u32_t * const D,
       
   233 	u32_t * const E,
       
   234 	u32_t * const Wt,
       
   235 	const u32_t Wt_3,
       
   236 	const u32_t Wt_8,
       
   237 	const u32_t Wt_14,
       
   238 	const u32_t Wt_16
       
   239 	)
       
   240 {
       
   241 	EAP_UNREFERENCED_PARAMETER(t);
       
   242 
       
   243 	*Wt = eap_sha1_b_substitution(Wt_3, Wt_8, Wt_14, Wt_16);
       
   244 
       
   245 	const u32_t TEMP = eap_sha1_rotate(*A, 5ul)
       
   246 		+ eap_sha1_ft_0_19(*B, *C, *D)
       
   247 		+ *E + *Wt + eap_am_crypto_sha1_c::EAP_SHA1_K__0_19;
       
   248 
       
   249 	d_substitution(A, B, C, D, E, TEMP);
       
   250 
       
   251 	EAP_SHA1_TRACE_DEBUG(m_am_tools, EAP_TRACE_MASK_SHA1,
       
   252 					(EAPL("SHA1: t=%d\t%08x\t%08x\t%08x\t%08x\t%08x\n"),
       
   253 					 t, *A, *B, *C, *D, *E));
       
   254 }
       
   255 
       
   256 //--------------------------------------------------
       
   257 
       
   258 inline void eap_am_crypto_sha1_c::d_substitution_20_39(
       
   259 	const u32_t t,
       
   260 	u32_t * const A,
       
   261 	u32_t * const B,
       
   262 	u32_t * const C,
       
   263 	u32_t * const D,
       
   264 	u32_t * const E,
       
   265 	u32_t * const Wt,
       
   266 	const u32_t Wt_3,
       
   267 	const u32_t Wt_8,
       
   268 	const u32_t Wt_14,
       
   269 	const u32_t Wt_16
       
   270 	)
       
   271 {
       
   272 	EAP_UNREFERENCED_PARAMETER(t);
       
   273 
       
   274 	*Wt = eap_sha1_b_substitution(Wt_3, Wt_8, Wt_14, Wt_16);
       
   275 
       
   276 	const u32_t TEMP = eap_sha1_rotate(*A, 5ul)
       
   277 		+ eap_sha1_ft_20_39(*B, *C, *D)
       
   278 		+ *E + *Wt + eap_am_crypto_sha1_c::EAP_SHA1_K_20_39;
       
   279 
       
   280 	d_substitution(A, B, C, D, E, TEMP);
       
   281 
       
   282 	EAP_SHA1_TRACE_DEBUG(m_am_tools, EAP_TRACE_MASK_SHA1,
       
   283 					(EAPL("SHA1: t=%d\t%08x\t%08x\t%08x\t%08x\t%08x\n"),
       
   284 					 t, *A, *B, *C, *D, *E));
       
   285 }
       
   286 
       
   287 //--------------------------------------------------
       
   288 
       
   289 inline void eap_am_crypto_sha1_c::d_substitution_40_59(
       
   290 	const u32_t t,
       
   291 	u32_t * const A,
       
   292 	u32_t * const B,
       
   293 	u32_t * const C,
       
   294 	u32_t * const D,
       
   295 	u32_t * const E,
       
   296 	u32_t * const Wt,
       
   297 	const u32_t Wt_3,
       
   298 	const u32_t Wt_8,
       
   299 	const u32_t Wt_14,
       
   300 	const u32_t Wt_16
       
   301 	)
       
   302 {
       
   303 	EAP_UNREFERENCED_PARAMETER(t);
       
   304 
       
   305 	*Wt = eap_sha1_b_substitution(Wt_3, Wt_8, Wt_14, Wt_16);
       
   306 
       
   307 	const u32_t TEMP = eap_sha1_rotate(*A, 5ul)
       
   308 		+ eap_sha1_ft_40_59(*B, *C, *D)
       
   309 		+ *E + *Wt + static_cast<u32_t>(eap_am_crypto_sha1_c::EAP_SHA1_K_40_59);
       
   310 
       
   311 	d_substitution(A, B, C, D, E, TEMP);
       
   312 
       
   313 	EAP_SHA1_TRACE_DEBUG(m_am_tools, EAP_TRACE_MASK_SHA1,
       
   314 					(EAPL("SHA1: t=%d\t%08x\t%08x\t%08x\t%08x\t%08x\n"),
       
   315 					 t, *A, *B, *C, *D, *E));
       
   316 }
       
   317 
       
   318 //--------------------------------------------------
       
   319 
       
   320 inline void eap_am_crypto_sha1_c::d_substitution_60_79(
       
   321 	const u32_t t,
       
   322 	u32_t * const A,
       
   323 	u32_t * const B,
       
   324 	u32_t * const C,
       
   325 	u32_t * const D,
       
   326 	u32_t * const E,
       
   327 	u32_t * const Wt,
       
   328 	const u32_t Wt_3,
       
   329 	const u32_t Wt_8,
       
   330 	const u32_t Wt_14,
       
   331 	const u32_t Wt_16
       
   332 	)
       
   333 {
       
   334 	EAP_UNREFERENCED_PARAMETER(t);
       
   335 
       
   336 	*Wt = eap_sha1_b_substitution(Wt_3, Wt_8, Wt_14, Wt_16);
       
   337 
       
   338 	const u32_t TEMP = eap_sha1_rotate(*A, 5ul)
       
   339 		+ eap_sha1_ft_60_79(*B, *C, *D)
       
   340 		+ *E + *Wt + static_cast<u32_t>(eap_am_crypto_sha1_c::EAP_SHA1_K_60_79);
       
   341 
       
   342 	d_substitution(A, B, C, D, E, TEMP);
       
   343 
       
   344 	EAP_SHA1_TRACE_DEBUG(m_am_tools, EAP_TRACE_MASK_SHA1,
       
   345 					(EAPL("SHA1: t=%d\t%08x\t%08x\t%08x\t%08x\t%08x\n"),
       
   346 					 t, *A, *B, *C, *D, *E));
       
   347 }
       
   348 
       
   349 //--------------------------------------------------
       
   350 
       
   351 EAP_FUNC_EXPORT eap_status_e
       
   352 eap_am_crypto_sha1_c::eap_sha1_process_data_host_order(
       
   353 	const u32_t * W,
       
   354 	u32_t W_count
       
   355 	)
       
   356 {
       
   357 	u32_t A;
       
   358 	u32_t B;
       
   359 	u32_t C;
       
   360 	u32_t D;
       
   361 	u32_t E;
       
   362 
       
   363 	if (W == 0
       
   364 		//|| (reinterpret_cast<u32_t>(W) % sizeof(u32_t)) != 0
       
   365 		|| W_count == 0
       
   366 		|| (W_count % EAP_AM_CRYPTO_SHA1_BLOCK_u32_COUNT) != 0)
       
   367 	{
       
   368 		EAP_ASSERT_ANYWAY;
       
   369 		EAP_SYSTEM_DEBUG_BREAK();
       
   370 		return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_parameter);
       
   371 	}
       
   372 
       
   373 
       
   374 	#if defined(_DEBUG)
       
   375 		for (u32_t ind = 0ul; ind < W_count; ind++)
       
   376 		{
       
   377 			EAP_SHA1_TRACE_DEBUG(m_am_tools, EAP_TRACE_MASK_SHA1,
       
   378 						(EAPL("SHA1: W[%d]=%08x\n"),
       
   379 						 ind,
       
   380 						 W[ind]));
       
   381 		} // for()
       
   382 	#endif //#if defined(_DEBUG)
       
   383 
       
   384 
       
   385 	do
       
   386 	{
       
   387 
       
   388 		#if defined(_DEBUG)
       
   389 			EAP_SHA1_TRACE_DEBUG(m_am_tools, EAP_TRACE_MASK_SHA1,
       
   390 					(EAPL("SHA1: H[0]=0x%08x, H[1]=0x%08x, H[2]=0x%08x, H[3]=0x%08x, H[4]=0x%08x\n"),
       
   391 					 m_H[0],
       
   392 					 m_H[1],
       
   393 					 m_H[2],
       
   394 					 m_H[3],
       
   395 					 m_H[4]));
       
   396 			EAP_SHA1_TRACE_DEBUG(m_am_tools, EAP_TRACE_MASK_SHA1,
       
   397 					(EAPL("SHA1: % 4s\t% 8s\t% 8s\t% 8s\t% 8s\t% 8s\n"),
       
   398 					"t", "A", "B", "C", "D", "E"));
       
   399 		#endif //#if defined(_DEBUG)
       
   400 
       
   401 		A = m_H[0];
       
   402 		B = m_H[1];
       
   403 		C = m_H[2];
       
   404 		D = m_H[3];
       
   405 		E = m_H[4];
       
   406 
       
   407 		d_substitution_0_15( 0, &A, &B, &C, &D, &E, W[ 0]);
       
   408 		d_substitution_0_15( 1, &A, &B, &C, &D, &E, W[ 1]);
       
   409 		d_substitution_0_15( 2, &A, &B, &C, &D, &E, W[ 2]);
       
   410 		d_substitution_0_15( 3, &A, &B, &C, &D, &E, W[ 3]);
       
   411 		d_substitution_0_15( 4, &A, &B, &C, &D, &E, W[ 4]);
       
   412 		d_substitution_0_15( 5, &A, &B, &C, &D, &E, W[ 5]);
       
   413 		d_substitution_0_15( 6, &A, &B, &C, &D, &E, W[ 6]);
       
   414 		d_substitution_0_15( 7, &A, &B, &C, &D, &E, W[ 7]);
       
   415 		d_substitution_0_15( 8, &A, &B, &C, &D, &E, W[ 8]);
       
   416 		d_substitution_0_15( 9, &A, &B, &C, &D, &E, W[ 9]);
       
   417 		d_substitution_0_15(10, &A, &B, &C, &D, &E, W[10]);
       
   418 		d_substitution_0_15(11, &A, &B, &C, &D, &E, W[11]);
       
   419 		d_substitution_0_15(12, &A, &B, &C, &D, &E, W[12]);
       
   420 		d_substitution_0_15(13, &A, &B, &C, &D, &E, W[13]);
       
   421 		d_substitution_0_15(14, &A, &B, &C, &D, &E, W[14]);
       
   422 		d_substitution_0_15(15, &A, &B, &C, &D, &E, W[15]);
       
   423 
       
   424 		d_substitution_16_19(16, &A, &B, &C, &D, &E, &(m_T[ 0]),
       
   425 							 W[13], W[ 8], W[ 2], W[ 0]);
       
   426 		d_substitution_16_19(17, &A, &B, &C, &D, &E, &(m_T[ 1]),
       
   427 							 W[14], W[ 9], W[ 3], W[ 1]);
       
   428 		d_substitution_16_19(18, &A, &B, &C, &D, &E, &(m_T[ 2]),
       
   429 							 W[15], W[10], W[ 4], W[ 2]);
       
   430 		d_substitution_16_19(19, &A, &B, &C, &D, &E, &(m_T[ 3]),
       
   431 							 m_T[ 0], W[11], W[ 5], W[ 3]);
       
   432 
       
   433 		d_substitution_20_39(20, &A, &B, &C, &D, &E, &(m_T[ 4]),
       
   434 							 m_T[ 1], W[12], W[ 6], W[ 4]);
       
   435 		d_substitution_20_39(21, &A, &B, &C, &D, &E, &(m_T[ 5]),
       
   436 							 m_T[ 2], W[13], W[ 7], W[ 5]);
       
   437 		d_substitution_20_39(22, &A, &B, &C, &D, &E, &(m_T[ 6]),
       
   438 							 m_T[ 3], W[14], W[ 8], W[ 6]);
       
   439 		d_substitution_20_39(23, &A, &B, &C, &D, &E, &(m_T[ 7]),
       
   440 							 m_T[ 4], W[15], W[ 9], W[ 7]);
       
   441 		d_substitution_20_39(24, &A, &B, &C, &D, &E, &(m_T[ 8]),
       
   442 							 m_T[ 5], m_T[ 0], W[10], W[ 8]);
       
   443 		d_substitution_20_39(25, &A, &B, &C, &D, &E, &(m_T[ 9]),
       
   444 							 m_T[ 6], m_T[ 1], W[11], W[ 9]);
       
   445 		d_substitution_20_39(26, &A, &B, &C, &D, &E, &(m_T[10]),
       
   446 							 m_T[ 7], m_T[ 2], W[12], W[10]);
       
   447 		d_substitution_20_39(27, &A, &B, &C, &D, &E, &(m_T[11]),
       
   448 							 m_T[ 8], m_T[ 3], W[13], W[11]);
       
   449 		d_substitution_20_39(28, &A, &B, &C, &D, &E, &(m_T[12]),
       
   450 							 m_T[ 9], m_T[ 4], W[14], W[12]);
       
   451 		d_substitution_20_39(29, &A, &B, &C, &D, &E, &(m_T[13]),
       
   452 							 m_T[10], m_T[ 5], W[15], W[13]);
       
   453 		d_substitution_20_39(30, &A, &B, &C, &D, &E, &(m_T[14]),
       
   454 							 m_T[11], m_T[ 6], m_T[ 0], W[14]);
       
   455 		d_substitution_20_39(31, &A, &B, &C, &D, &E, &(m_T[15]),
       
   456 							 m_T[12], m_T[ 7], m_T[ 1], W[15]);
       
   457 		d_substitution_20_39(32, &A, &B, &C, &D, &E, &(m_T[ 0]),
       
   458 							 m_T[13], m_T[ 8], m_T[ 2], m_T[ 0]);
       
   459 		d_substitution_20_39(33, &A, &B, &C, &D, &E, &(m_T[ 1]),
       
   460 							 m_T[14], m_T[ 9], m_T[ 3], m_T[ 1]);
       
   461 		d_substitution_20_39(34, &A, &B, &C, &D, &E, &(m_T[ 2]),
       
   462 							 m_T[15], m_T[10], m_T[ 4], m_T[ 2]);
       
   463 		d_substitution_20_39(35, &A, &B, &C, &D, &E, &(m_T[ 3]),
       
   464 							 m_T[ 0], m_T[11], m_T[ 5], m_T[ 3]);
       
   465 		d_substitution_20_39(36, &A, &B, &C, &D, &E, &(m_T[ 4]),
       
   466 							 m_T[ 1], m_T[12], m_T[ 6], m_T[ 4]);
       
   467 		d_substitution_20_39(37, &A, &B, &C, &D, &E, &(m_T[ 5]),
       
   468 							 m_T[ 2], m_T[13], m_T[ 7], m_T[ 5]);
       
   469 		d_substitution_20_39(38, &A, &B, &C, &D, &E, &(m_T[ 6]),
       
   470 							 m_T[ 3], m_T[14], m_T[ 8], m_T[ 6]);
       
   471 		d_substitution_20_39(39, &A, &B, &C, &D, &E, &(m_T[ 7]),
       
   472 							 m_T[ 4], m_T[15], m_T[ 9], m_T[ 7]);
       
   473 
       
   474 		d_substitution_40_59(40, &A, &B, &C, &D, &E, &(m_T[ 8]),
       
   475 							 m_T[ 5], m_T[ 0], m_T[10], m_T[ 8]);
       
   476 		d_substitution_40_59(41, &A, &B, &C, &D, &E, &(m_T[ 9]),
       
   477 							 m_T[ 6], m_T[ 1], m_T[11], m_T[ 9]);
       
   478 		d_substitution_40_59(42, &A, &B, &C, &D, &E, &(m_T[10]),
       
   479 							 m_T[ 7], m_T[ 2], m_T[12], m_T[10]);
       
   480 		d_substitution_40_59(43, &A, &B, &C, &D, &E, &(m_T[11]),
       
   481 							 m_T[ 8], m_T[ 3], m_T[13], m_T[11]);
       
   482 		d_substitution_40_59(44, &A, &B, &C, &D, &E, &(m_T[12]),
       
   483 							 m_T[ 9], m_T[ 4], m_T[14], m_T[12]);
       
   484 		d_substitution_40_59(45, &A, &B, &C, &D, &E, &(m_T[13]),
       
   485 							 m_T[10], m_T[ 5], m_T[15], m_T[13]);
       
   486 		d_substitution_40_59(46, &A, &B, &C, &D, &E, &(m_T[14]),
       
   487 							 m_T[11], m_T[ 6], m_T[ 0], m_T[14]);
       
   488 		d_substitution_40_59(47, &A, &B, &C, &D, &E, &(m_T[15]),
       
   489 							 m_T[12], m_T[ 7], m_T[ 1], m_T[15]);
       
   490 		d_substitution_40_59(48, &A, &B, &C, &D, &E, &(m_T[ 0]),
       
   491 							 m_T[13], m_T[ 8], m_T[ 2], m_T[ 0]);
       
   492 		d_substitution_40_59(49, &A, &B, &C, &D, &E, &(m_T[ 1]),
       
   493 							 m_T[14], m_T[ 9], m_T[ 3], m_T[ 1]);
       
   494 		d_substitution_40_59(50, &A, &B, &C, &D, &E, &(m_T[ 2]),
       
   495 							 m_T[15], m_T[10], m_T[ 4], m_T[ 2]);
       
   496 		d_substitution_40_59(51, &A, &B, &C, &D, &E, &(m_T[ 3]),
       
   497 							 m_T[ 0], m_T[11], m_T[ 5], m_T[ 3]);
       
   498 		d_substitution_40_59(52, &A, &B, &C, &D, &E, &(m_T[ 4]),
       
   499 							 m_T[ 1], m_T[12], m_T[ 6], m_T[ 4]);
       
   500 		d_substitution_40_59(53, &A, &B, &C, &D, &E, &(m_T[ 5]),
       
   501 							 m_T[ 2], m_T[13], m_T[ 7], m_T[ 5]);
       
   502 		d_substitution_40_59(54, &A, &B, &C, &D, &E, &(m_T[ 6]),
       
   503 							 m_T[ 3], m_T[14], m_T[ 8], m_T[ 6]);
       
   504 		d_substitution_40_59(55, &A, &B, &C, &D, &E, &(m_T[ 7]),
       
   505 							 m_T[ 4], m_T[15], m_T[ 9], m_T[ 7]);
       
   506 		d_substitution_40_59(56, &A, &B, &C, &D, &E, &(m_T[ 8]),
       
   507 							 m_T[ 5], m_T[ 0], m_T[10], m_T[ 8]);
       
   508 		d_substitution_40_59(57, &A, &B, &C, &D, &E, &(m_T[ 9]),
       
   509 							 m_T[ 6], m_T[ 1], m_T[11], m_T[ 9]);
       
   510 		d_substitution_40_59(58, &A, &B, &C, &D, &E, &(m_T[10]),
       
   511 							 m_T[ 7], m_T[ 2], m_T[12], m_T[10]);
       
   512 		d_substitution_40_59(59, &A, &B, &C, &D, &E, &(m_T[11]),
       
   513 							 m_T[ 8], m_T[ 3], m_T[13], m_T[11]);
       
   514 
       
   515 		d_substitution_60_79(60, &A, &B, &C, &D, &E, &(m_T[12]),
       
   516 							 m_T[ 9], m_T[ 4], m_T[14], m_T[12]);
       
   517 		d_substitution_60_79(61, &A, &B, &C, &D, &E, &(m_T[13]),
       
   518 							 m_T[10], m_T[ 5], m_T[15], m_T[13]);
       
   519 		d_substitution_60_79(62, &A, &B, &C, &D, &E, &(m_T[14]),
       
   520 							 m_T[11], m_T[ 6], m_T[ 0], m_T[14]);
       
   521 		d_substitution_60_79(63, &A, &B, &C, &D, &E, &(m_T[15]),
       
   522 							 m_T[12], m_T[ 7], m_T[ 1], m_T[15]);
       
   523 		d_substitution_60_79(64, &A, &B, &C, &D, &E, &(m_T[ 0]),
       
   524 							 m_T[13], m_T[ 8], m_T[ 2], m_T[ 0]);
       
   525 		d_substitution_60_79(65, &A, &B, &C, &D, &E, &(m_T[ 1]),
       
   526 							 m_T[14], m_T[ 9], m_T[ 3], m_T[ 1]);
       
   527 		d_substitution_60_79(66, &A, &B, &C, &D, &E, &(m_T[ 2]),
       
   528 							 m_T[15], m_T[10], m_T[ 4], m_T[ 2]);
       
   529 		d_substitution_60_79(67, &A, &B, &C, &D, &E, &(m_T[ 3]),
       
   530 							 m_T[ 0], m_T[11], m_T[ 5], m_T[ 3]);
       
   531 		d_substitution_60_79(68, &A, &B, &C, &D, &E, &(m_T[ 4]),
       
   532 							 m_T[ 1], m_T[12], m_T[ 6], m_T[ 4]);
       
   533 		d_substitution_60_79(69, &A, &B, &C, &D, &E, &(m_T[ 5]),
       
   534 							 m_T[ 2], m_T[13], m_T[ 7], m_T[ 5]);
       
   535 		d_substitution_60_79(70, &A, &B, &C, &D, &E, &(m_T[ 6]),
       
   536 							 m_T[ 3], m_T[14], m_T[ 8], m_T[ 6]);
       
   537 		d_substitution_60_79(71, &A, &B, &C, &D, &E, &(m_T[ 7]),
       
   538 							 m_T[ 4], m_T[15], m_T[ 9], m_T[ 7]);
       
   539 		d_substitution_60_79(72, &A, &B, &C, &D, &E, &(m_T[ 8]),
       
   540 							 m_T[ 5], m_T[ 0], m_T[10], m_T[ 8]);
       
   541 		d_substitution_60_79(73, &A, &B, &C, &D, &E, &(m_T[ 9]),
       
   542 							 m_T[ 6], m_T[ 1], m_T[11], m_T[ 9]);
       
   543 		d_substitution_60_79(74, &A, &B, &C, &D, &E, &(m_T[10]),
       
   544 							 m_T[ 7], m_T[ 2], m_T[12], m_T[10]);
       
   545 		d_substitution_60_79(75, &A, &B, &C, &D, &E, &(m_T[11]),
       
   546 							 m_T[ 8], m_T[ 3], m_T[13], m_T[11]);
       
   547 		d_substitution_60_79(76, &A, &B, &C, &D, &E, &(m_T[12]),
       
   548 							 m_T[ 9], m_T[ 4], m_T[14], m_T[12]);
       
   549 		d_substitution_60_79(77, &A, &B, &C, &D, &E, &(m_T[13]),
       
   550 							 m_T[10], m_T[ 5], m_T[15], m_T[13]);
       
   551 		d_substitution_60_79(78, &A, &B, &C, &D, &E, &(m_T[14]),
       
   552 							 m_T[11], m_T[ 6], m_T[ 0], m_T[14]);
       
   553 		d_substitution_60_79(79, &A, &B, &C, &D, &E, &(m_T[15]),
       
   554 							 m_T[12], m_T[ 7], m_T[ 1], m_T[15]);
       
   555 
       
   556 		m_H[0] = m_H[0] + A;
       
   557 		m_H[1] = m_H[1] + B;
       
   558 		m_H[2] = m_H[2] + C;
       
   559 		m_H[3] = m_H[3] + D;
       
   560 		m_H[4] = m_H[4] + E;
       
   561 
       
   562 		W_count -= EAP_AM_CRYPTO_SHA1_BLOCK_u32_COUNT;
       
   563 		W += EAP_AM_CRYPTO_SHA1_BLOCK_u32_COUNT;
       
   564 
       
   565 	} while(W_count > 0ul);
       
   566 
       
   567 	EAP_SHA1_TRACE_DEBUG(m_am_tools, EAP_TRACE_MASK_SHA1,
       
   568 					(EAPL("SHA1: digest=\t%08x\t%08x\t%08x\t%08x\t%08x\n"),
       
   569 					 m_H[0], m_H[1], m_H[2], m_H[3], m_H[4]));
       
   570 
       
   571 	return EAP_STATUS_RETURN(m_am_tools, eap_status_ok);
       
   572 }
       
   573 
       
   574 //--------------------------------------------------
       
   575 
       
   576 EAP_FUNC_EXPORT eap_status_e
       
   577 eap_am_crypto_sha1_c::eap_sha1_process_data_network_order(
       
   578 	const u32_t * W,
       
   579 	u32_t W_count
       
   580 	)
       
   581 {
       
   582 	if (W == 0
       
   583 		//|| (reinterpret_cast<u32_t>(W) % sizeof(u32_t)) != 0
       
   584 		|| W_count == 0
       
   585 		|| (W_count % EAP_AM_CRYPTO_SHA1_BLOCK_u32_COUNT) != 0)
       
   586 	{
       
   587 		EAP_ASSERT_ANYWAY;
       
   588 		EAP_SYSTEM_DEBUG_BREAK();
       
   589 		return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_parameter);
       
   590 	}
       
   591 
       
   592 	eap_status_e status = eap_status_ok;
       
   593 
       
   594 	// Array of 16 temporary 32-bit unsigned integers.
       
   595 	u32_t count = W_count / EAP_AM_CRYPTO_SHA1_BLOCK_u32_COUNT;	
       
   596 
       
   597 	for (u32_t ind = 0ul; ind < count; ind++)
       
   598 	{	
       
   599 		for (u32_t ind_W = 0ul; ind_W < EAP_AM_CRYPTO_SHA1_BLOCK_u32_COUNT
       
   600 				 ; ind_W++)
       
   601 		{
       
   602 			// Here we must read data in 8-bit blocks bacause W can be aligned at any position.
       
   603 			const u8_t * const data
       
   604 				= reinterpret_cast<const u8_t *>(
       
   605 					&W[ind*EAP_AM_CRYPTO_SHA1_BLOCK_u32_COUNT+ind_W]);
       
   606 			m_W_in_host_order[ind_W]
       
   607 				= (data[0] << 24)
       
   608 				| (data[1] << 16)
       
   609 				| (data[2] <<  8)
       
   610 				| (data[3] <<  0);
       
   611 		} // for()
       
   612 	
       
   613 		status = eap_sha1_process_data_host_order(
       
   614 			m_W_in_host_order,
       
   615 			EAP_AM_CRYPTO_SHA1_BLOCK_u32_COUNT);
       
   616 		if (status != eap_status_ok)
       
   617 		{
       
   618 			return EAP_STATUS_RETURN(m_am_tools, status);
       
   619 		}
       
   620 	
       
   621 	} // for()
       
   622 	
       
   623 	return EAP_STATUS_RETURN(m_am_tools, status);
       
   624 }
       
   625 
       
   626 //--------------------------------------------------
       
   627 
       
   628 EAP_FUNC_EXPORT eap_status_e eap_am_crypto_sha1_c::copy_message_digest(
       
   629 	void * const output,
       
   630 	u32_t * const max_output_size)
       
   631 {
       
   632 	if (output == 0
       
   633 		|| max_output_size == 0
       
   634 		|| *max_output_size < EAP_AM_CRYPTO_SHA1_DIGEST_BUFFER_BYTE_SIZE)
       
   635 	{
       
   636 		return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_parameter);
       
   637 	}
       
   638 
       
   639 #if defined(EAP_LITTLE_ENDIAN)
       
   640 	// We must change the data from host order to network order.
       
   641 	u32_t * const tmp_H = static_cast<u32_t *>(output);
       
   642 	for (u32_t ind = 0ul; ind < EAP_AM_CRYPTO_SHA1_DIGEST_BUFFER_u32_COUNT
       
   643 			 ; ind++)
       
   644 	{
       
   645 		tmp_H[ind] = eap_htonl(m_H[ind]);
       
   646 	} // for()
       
   647 
       
   648 #elif defined(EAP_BIG_ENDIAN)
       
   649 
       
   650 	m_am_tools->memmove(
       
   651 		output,
       
   652 		m_H,
       
   653 		EAP_AM_CRYPTO_SHA1_DIGEST_BUFFER_BYTE_SIZE);
       
   654 
       
   655 #else
       
   656 #error ERROR: define EAP_LITTLE_ENDIAN (byte 0 is least significant (i386)) \
       
   657 or EAP_BIG_ENDIAN (byte 0 is most significant (mc68k)).
       
   658 #endif
       
   659 
       
   660 	*max_output_size = EAP_AM_CRYPTO_SHA1_DIGEST_BUFFER_BYTE_SIZE;
       
   661 
       
   662 	return EAP_STATUS_RETURN(m_am_tools, eap_status_ok);
       
   663 }
       
   664 
       
   665 //--------------------------------------------------
       
   666 
       
   667 EAP_FUNC_EXPORT eap_status_e eap_am_crypto_sha1_c::eap_sha1_dss_G_function(
       
   668 	const void * const data,
       
   669 	const u32_t data_length,
       
   670 	void * const output,
       
   671 	u32_t * const output_length
       
   672 	)
       
   673 {
       
   674 	if (data == 0
       
   675 		|| data_length == 0
       
   676 		|| data_length > EAP_AM_CRYPTO_SHA1_DIGEST_BUFFER_BYTE_SIZE
       
   677 		|| output == 0
       
   678 		|| output_length == 0
       
   679 		|| *output_length < EAP_AM_CRYPTO_SHA1_DIGEST_BUFFER_BYTE_SIZE)
       
   680 	{
       
   681 		return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_parameter);
       
   682 	}
       
   683 
       
   684 	eap_status_e status = hash_init();
       
   685 	if (status != eap_status_ok)
       
   686 	{
       
   687 		return EAP_STATUS_RETURN(m_am_tools, status);
       
   688 	}
       
   689 
       
   690 	m_am_tools->memset(m_W_in_host_order, 0, sizeof(m_W_in_host_order));
       
   691 	m_am_tools->memmove(m_W_in_host_order, data, data_length);
       
   692 
       
   693 
       
   694 #if defined(EAP_LITTLE_ENDIAN)
       
   695 
       
   696 	{
       
   697 		for (u32_t ind_W = 0ul; ind_W < EAP_AM_CRYPTO_SHA1_BLOCK_u32_COUNT
       
   698 				 ; ind_W++)
       
   699 		{
       
   700 			m_W_in_host_order[ind_W] = eap_ntohl(m_W_in_host_order[ind_W]);
       
   701 		} // for()
       
   702 
       
   703 		status = eap_sha1_process_data_host_order(
       
   704 			m_W_in_host_order,
       
   705 			EAP_AM_CRYPTO_SHA1_BLOCK_u32_COUNT);
       
   706 		if (status != eap_status_ok)
       
   707 		{
       
   708 			return EAP_STATUS_RETURN(m_am_tools, status);
       
   709 		}
       
   710 	}
       
   711 
       
   712 #elif defined(EAP_BIG_ENDIAN)
       
   713 
       
   714 	{
       
   715 		u32_t count_W = data_length
       
   716 			/ EAP_AM_CRYPTO_SHA1_DIGEST_BUFFER_BYTE_SIZE;
       
   717 
       
   718 		status = eap_sha1_process_data_host_order(m_W_in_host_order, count_W);
       
   719 		if (status != eap_status_ok)
       
   720 		{
       
   721 			return EAP_STATUS_RETURN(m_am_tools, status);
       
   722 		}
       
   723 	}
       
   724 
       
   725 #else
       
   726 #error ERROR: define EAP_LITTLE_ENDIAN (byte 0 is least significant (i386)) \
       
   727 or EAP_BIG_ENDIAN (byte 0 is most significant (mc68k)).
       
   728 #endif
       
   729 
       
   730 	status = copy_message_digest(
       
   731 		output,
       
   732 		output_length);
       
   733 	if (status != eap_status_ok)
       
   734 	{
       
   735 		return EAP_STATUS_RETURN(m_am_tools, status);
       
   736 	}
       
   737 
       
   738 	return EAP_STATUS_RETURN(m_am_tools, status);
       
   739 }
       
   740 
       
   741 //--------------------------------------------------
       
   742 
       
   743 /**
       
   744  * This function returns the size of message digest of HASH-algorithm.
       
   745  */
       
   746 EAP_FUNC_EXPORT u32_t eap_am_crypto_sha1_c::get_digest_length()
       
   747 {
       
   748 	return EAP_AM_CRYPTO_SHA1_DIGEST_BUFFER_BYTE_SIZE;
       
   749 }
       
   750 
       
   751 //--------------------------------------------------
       
   752 
       
   753 /**
       
   754  * This function returns the size of block of HASH-algorithm.
       
   755  */
       
   756 EAP_FUNC_EXPORT u32_t eap_am_crypto_sha1_c::get_block_size()
       
   757 {
       
   758 	return EAP_AM_CRYPTO_SHA1_BLOCK_BYTE_SIZE;
       
   759 }
       
   760 
       
   761 //--------------------------------------------------
       
   762 
       
   763 /**
       
   764  * This function initializes the context of SHA1-algorithm.
       
   765  */
       
   766 EAP_FUNC_EXPORT eap_status_e eap_am_crypto_sha1_c::hash_init()
       
   767 {
       
   768 	m_full_hashed_data_length = 0ul;
       
   769 
       
   770 	m_H[0] = static_cast<u32_t>(EAP_SHA1_INIT_H0);
       
   771 	m_H[1] = static_cast<u32_t>(EAP_SHA1_INIT_H1);
       
   772 	m_H[2] = static_cast<u32_t>(EAP_SHA1_INIT_H2);
       
   773 	m_H[3] = static_cast<u32_t>(EAP_SHA1_INIT_H3);
       
   774 	m_H[4] = static_cast<u32_t>(EAP_SHA1_INIT_H4);
       
   775 
       
   776 	if (m_saved_data.get_is_valid() == false)
       
   777 	{
       
   778 		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
   779 	}
       
   780 
       
   781 	eap_status_e status = m_saved_data.set_data_length(0ul);
       
   782 
       
   783 	return EAP_STATUS_RETURN(m_am_tools, status);
       
   784 }
       
   785 
       
   786 //--------------------------------------------------
       
   787 /**
       
   788  * This function updates the context of SHA1-algorithm with data.
       
   789  */
       
   790 EAP_FUNC_EXPORT eap_status_e eap_am_crypto_sha1_c::hash_update(
       
   791 	const void * const data,
       
   792 	const u32_t data_length)
       
   793 {
       
   794 	eap_status_e status = eap_status_ok;
       
   795 	u32_t prosessed_data_length = 0ul;
       
   796 	
       
   797 		
       
   798 	m_full_hashed_data_length += data_length;
       
   799 
       
   800 	EAP_SHA1_TRACE_DEBUG(m_am_tools, EAP_TRACE_MASK_SHA1,
       
   801 					(EAPL("SHA1: Processed data length %u\n"),
       
   802 					 m_full_hashed_data_length));
       
   803 
       
   804 	if (m_saved_data.get_is_valid_data() == true
       
   805 		&& m_saved_data.get_data_length() > 0ul)
       
   806 	{
       
   807 		EAP_SHA1_TRACE_DATA_DEBUG(
       
   808 			m_am_tools,
       
   809 			EAP_TRACE_MASK_SHA1,
       
   810 			(EAPL("SHA1 saved data"),
       
   811 			 m_saved_data.get_data(m_saved_data.get_data_length()),
       
   812 			 m_saved_data.get_data_length()));
       
   813 		
       
   814 		// Here we have remaining data to process from previous call
       
   815 		// of hash_update().
       
   816 		u32_t needed_data_length = EAP_AM_CRYPTO_SHA1_BLOCK_BYTE_SIZE
       
   817 			- m_saved_data.get_data_length();
       
   818 		if (needed_data_length > data_length)
       
   819 		{
       
   820 			// Not enough input data.
       
   821 			needed_data_length = data_length;
       
   822 		}
       
   823 
       
   824 		prosessed_data_length = needed_data_length;
       
   825 		status = m_saved_data.add_data(data, needed_data_length);
       
   826 		if (status != eap_status_ok)
       
   827 		{
       
   828 			return EAP_STATUS_RETURN(m_am_tools, status);
       
   829 		}
       
   830 
       
   831 		if (m_saved_data.get_data_length()
       
   832 			== EAP_AM_CRYPTO_SHA1_BLOCK_BYTE_SIZE)
       
   833 		{
       
   834 			// Enough data to process.
       
   835 			// Just one block of integers in W array.
       
   836 
       
   837 			status = eap_sha1_process_data_network_order(
       
   838 				reinterpret_cast<const u32_t *>(
       
   839 					m_saved_data.get_data(
       
   840 						m_saved_data.get_data_length())),
       
   841 				EAP_AM_CRYPTO_SHA1_BLOCK_u32_COUNT
       
   842 				);
       
   843 		
       
   844 			if (status != eap_status_ok)
       
   845 			{
       
   846 				return EAP_STATUS_RETURN(m_am_tools, status);
       
   847 			}
       
   848 
       
   849 			// This is optimization of buffer allocations.
       
   850 			status = m_saved_data.set_data_length(0ul);
       
   851 			if (status != eap_status_ok)
       
   852 			{
       
   853 				return EAP_STATUS_RETURN(m_am_tools, status);
       
   854 			}
       
   855 		}
       
   856 		
       
   857 		EAP_ASSERT(m_saved_data.get_is_valid_data() == false
       
   858 		|| m_saved_data.get_data_length()
       
   859 			   <= EAP_AM_CRYPTO_SHA1_BLOCK_BYTE_SIZE);
       
   860 	
       
   861 	}
       
   862 
       
   863 	u32_t remaining_data_length = data_length - prosessed_data_length;
       
   864 	u32_t full_block_count = remaining_data_length
       
   865 		/ EAP_AM_CRYPTO_SHA1_BLOCK_BYTE_SIZE;
       
   866 
       
   867 	if (full_block_count > 0ul)
       
   868 	{
       
   869 		// Here we have full blocks to process.
       
   870 		status = eap_sha1_process_data_network_order(
       
   871 			reinterpret_cast<const u32_t *>(
       
   872 				static_cast<const u8_t *>(data)+prosessed_data_length),
       
   873 			full_block_count * EAP_AM_CRYPTO_SHA1_BLOCK_u32_COUNT
       
   874 			);
       
   875 		
       
   876 		if (status != eap_status_ok)
       
   877 		{
       
   878 			return EAP_STATUS_RETURN(m_am_tools, status);
       
   879 		}
       
   880 
       
   881 		prosessed_data_length += sizeof(u32_t) * full_block_count
       
   882 			* EAP_AM_CRYPTO_SHA1_BLOCK_u32_COUNT;
       
   883 	}
       
   884 	if (data_length > prosessed_data_length)
       
   885 	{
       
   886 		// Save the remaining data.
       
   887 		status = m_saved_data.add_data(
       
   888 			static_cast<const u8_t *>(data)+prosessed_data_length,
       
   889 			data_length-prosessed_data_length);
       
   890 		if (status != eap_status_ok)
       
   891 		{
       
   892 			return EAP_STATUS_RETURN(m_am_tools, status);
       
   893 		}
       
   894 	}
       
   895 
       
   896 	return EAP_STATUS_RETURN(m_am_tools, status);
       
   897 }
       
   898 
       
   899 //--------------------------------------------------
       
   900 
       
   901 /**
       
   902  * This function writes the message digest to buffer.
       
   903  * @param Length is set if md_length_or_null is non-NULL.
       
   904  */
       
   905 EAP_FUNC_EXPORT eap_status_e eap_am_crypto_sha1_c::hash_final(
       
   906 	void * const message_digest,
       
   907 	u32_t *md_length_or_null)
       
   908 {
       
   909 	eap_status_e status = eap_status_ok;
       
   910 
       
   911 	if (message_digest == 0)
       
   912 	{
       
   913 		return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_parameter);
       
   914 	}
       
   915 
       
   916 	if (m_saved_data.get_is_valid_data() == true)
       
   917 	{
       
   918 		EAP_SHA1_TRACE_DATA_DEBUG(
       
   919 			m_am_tools,
       
   920 			EAP_TRACE_MASK_SHA1,
       
   921 			(EAPL("SHA1 saved data"),
       
   922 			 m_saved_data.get_data(m_saved_data.get_data_length()),
       
   923 			 m_saved_data.get_data_length()));
       
   924 	}
       
   925 
       
   926 	// First add the one bit. We use one byte 0x80.
       
   927 	u8_t bit_pad = 0x80;
       
   928 	status = m_saved_data.add_data(&bit_pad, sizeof(bit_pad));
       
   929 	if (status != eap_status_ok)
       
   930 	{
       
   931 		return EAP_STATUS_RETURN(m_am_tools, status);
       
   932 	}
       
   933 
       
   934 	// Here we may have remaining data to process from previous call
       
   935 	// of hash_update().
       
   936 	u32_t min_data_length = m_saved_data.get_data_length() + sizeof(u64_t);
       
   937 	u32_t padding_zero_count = 0ul;
       
   938 	u32_t block_count = min_data_length / EAP_AM_CRYPTO_SHA1_BLOCK_BYTE_SIZE;
       
   939 	if ((min_data_length % EAP_AM_CRYPTO_SHA1_BLOCK_BYTE_SIZE) != 0)
       
   940 	{
       
   941 		// Last block is not full.
       
   942 		++block_count;
       
   943 	}
       
   944 	padding_zero_count = (block_count*EAP_AM_CRYPTO_SHA1_BLOCK_BYTE_SIZE)
       
   945 		- min_data_length;
       
   946 
       
   947 	// Now we need to pad the remaining data.
       
   948 	u32_t data_length = m_saved_data.get_data_length();
       
   949 	status = m_saved_data.set_buffer_length(data_length+padding_zero_count);
       
   950 	if (status != eap_status_ok)
       
   951 	{
       
   952 		return EAP_STATUS_RETURN(m_am_tools, status);
       
   953 	}
       
   954 	m_saved_data.set_data_length(data_length+padding_zero_count);
       
   955 
       
   956 	u8_t * const padding = m_saved_data.get_data_offset(data_length, padding_zero_count);
       
   957 	if (padding == 0)
       
   958 	{
       
   959 		return EAP_STATUS_RETURN(m_am_tools, eap_status_buffer_too_short);
       
   960 	}
       
   961 
       
   962 	m_am_tools->memset(
       
   963 		padding,
       
   964 		0,
       
   965 		padding_zero_count);
       
   966 
       
   967 	// And finally the length of the hashed data is added to block.
       
   968 	// Note the length is in bits.
       
   969 	u64_t full_hashed_data_length_in_network_order
       
   970 		= eap_htonll(eap_shift_left_64_bit(m_full_hashed_data_length, 3ul));
       
   971 	status = m_saved_data.add_data(
       
   972 		&full_hashed_data_length_in_network_order,
       
   973 		sizeof(full_hashed_data_length_in_network_order));
       
   974 	if (status != eap_status_ok)
       
   975 	{
       
   976 		return EAP_STATUS_RETURN(m_am_tools, status);
       
   977 	}
       
   978 
       
   979 	EAP_ASSERT(m_saved_data.get_data_length()
       
   980 			   >= EAP_AM_CRYPTO_SHA1_BLOCK_BYTE_SIZE
       
   981 			   && (m_saved_data.get_data_length()
       
   982 				   % EAP_AM_CRYPTO_SHA1_BLOCK_BYTE_SIZE) == 0);
       
   983 
       
   984 	u32_t full_block_count = m_saved_data.get_data_length()
       
   985 		/ EAP_AM_CRYPTO_SHA1_BLOCK_BYTE_SIZE;
       
   986 
       
   987 	status = eap_sha1_process_data_network_order(
       
   988 		reinterpret_cast<const u32_t *>(
       
   989 			m_saved_data.get_data(
       
   990 				m_saved_data.get_data_length())),
       
   991 		full_block_count * EAP_AM_CRYPTO_SHA1_BLOCK_u32_COUNT
       
   992 		);
       
   993 	if (status != eap_status_ok)
       
   994 	{
       
   995 		return EAP_STATUS_RETURN(m_am_tools, status);
       
   996 	}
       
   997 
       
   998 	// This is optimization of buffer allocations.
       
   999 	status = m_saved_data.set_data_length(0ul);
       
  1000 	if (status != eap_status_ok)
       
  1001 	{
       
  1002 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  1003 	}
       
  1004 
       
  1005 
       
  1006 	u32_t output_length = 0ul;
       
  1007 	if (md_length_or_null == 0)
       
  1008 	{
       
  1009 		// Let's use temporary length variable.
       
  1010 		output_length = EAP_AM_CRYPTO_SHA1_DIGEST_BUFFER_BYTE_SIZE;
       
  1011 		md_length_or_null = &output_length;
       
  1012 	}
       
  1013 
       
  1014 	status = copy_message_digest(
       
  1015 		message_digest,
       
  1016 		md_length_or_null);
       
  1017 	if (status != eap_status_ok)
       
  1018 	{
       
  1019 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  1020 	}
       
  1021 
       
  1022 	return EAP_STATUS_RETURN(m_am_tools, eap_status_ok);
       
  1023 }
       
  1024 
       
  1025 //--------------------------------------------------
       
  1026 
       
  1027 /**
       
  1028  * This function cleans up the SHA1 context.
       
  1029  */
       
  1030 EAP_FUNC_EXPORT eap_status_e eap_am_crypto_sha1_c::hash_cleanup()
       
  1031 {
       
  1032 	m_saved_data.reset();
       
  1033 
       
  1034 	m_full_hashed_data_length = 0ul;
       
  1035 
       
  1036 	m_am_tools->memset(m_H, 0, EAP_AM_CRYPTO_SHA1_DIGEST_BUFFER_BYTE_SIZE);
       
  1037 
       
  1038 	return EAP_STATUS_RETURN(m_am_tools, eap_status_ok);
       
  1039 }
       
  1040 
       
  1041 //--------------------------------------------------
       
  1042 
       
  1043 /**
       
  1044  * This function copies the context of SHA1.
       
  1045  */
       
  1046 EAP_FUNC_EXPORT eap_status_e eap_am_crypto_sha1_c::copy_context(
       
  1047 	const eap_variable_data_c * const saved_data,
       
  1048 	const u64_t full_hashed_data_length,
       
  1049 	const u32_t * const H,
       
  1050 	const u32_t * const T,
       
  1051 	const u32_t * const W_in_host_order)
       
  1052 {
       
  1053 	if (saved_data->get_is_valid_data() == true)
       
  1054 	{
       
  1055 		eap_status_e status = m_saved_data.set_copy_of_buffer(saved_data);
       
  1056 		if (status != eap_status_ok)
       
  1057 		{
       
  1058 			return EAP_STATUS_RETURN(m_am_tools, status);
       
  1059 		}
       
  1060 	}
       
  1061 	else
       
  1062 	{
       
  1063 		// No saved data. Just reset.
       
  1064 		m_saved_data.reset();
       
  1065 	}
       
  1066 	
       
  1067 	m_full_hashed_data_length = full_hashed_data_length;
       
  1068 
       
  1069 	m_am_tools->memmove(m_H, H, sizeof(m_H));
       
  1070 
       
  1071 	m_am_tools->memmove(m_T, T, sizeof(m_T));
       
  1072 
       
  1073 	m_am_tools->memmove(m_W_in_host_order, W_in_host_order, sizeof(m_W_in_host_order));
       
  1074 
       
  1075 	return EAP_STATUS_RETURN(m_am_tools, eap_status_ok);
       
  1076 }
       
  1077 
       
  1078 //--------------------------------------------------
       
  1079 
       
  1080 /**
       
  1081  * This function copies the context of SHA1.
       
  1082  */
       
  1083 EAP_FUNC_EXPORT eap_am_crypto_sha1_c * eap_am_crypto_sha1_c::copy()
       
  1084 {
       
  1085 	eap_am_crypto_sha1_c * const sha1 = new eap_am_crypto_sha1_c(m_am_tools);
       
  1086 	if (sha1 == 0
       
  1087 		|| sha1->get_is_valid() == false)
       
  1088 	{
       
  1089 		delete sha1;
       
  1090 		return 0;
       
  1091 	}
       
  1092 
       
  1093 	eap_status_e status = sha1->copy_context(
       
  1094 		&m_saved_data,
       
  1095 		m_full_hashed_data_length,
       
  1096 		m_H,
       
  1097 		m_T,
       
  1098 		m_W_in_host_order);
       
  1099 	if (status != eap_status_ok)
       
  1100 	{
       
  1101 		delete sha1;
       
  1102 		return 0;
       
  1103 	}
       
  1104 
       
  1105 	return sha1;
       
  1106 }
       
  1107 
       
  1108 //--------------------------------------------------
       
  1109 
       
  1110 
       
  1111 
       
  1112 // End.