eapol/eapol_framework/eapol_common/common/eap_crypto_api.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 22 
       
    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_crypto_api.h"
       
    31 
       
    32 //--------------------------------------------------
       
    33 
       
    34 // This is simple optimization.
       
    35 const u32_t EAP_CRYPTO_API_SHA1_DIGEST_BUFFER_BYTE_SIZE = 20ul;
       
    36 const u32_t EAP_CRYPTO_API_SHA1_BLOCK_BYTE_SIZE = 64ul;
       
    37 
       
    38 const u32_t EAP_CRYPTO_API_SHA_256_DIGEST_BUFFER_BYTE_SIZE = 32ul;
       
    39 const u32_t EAP_CRYPTO_API_SHA_256_BLOCK_BYTE_SIZE = 64ul;
       
    40 
       
    41 //--------------------------------------------------
       
    42 //--------------------------------------------------
       
    43 //--------------------------------------------------
       
    44 
       
    45 EAP_FUNC_EXPORT abs_crypto_cbc_block_algorithm_c::~abs_crypto_cbc_block_algorithm_c()
       
    46 {
       
    47 }
       
    48 
       
    49 
       
    50 EAP_FUNC_EXPORT abs_crypto_block_algorithm_c::~abs_crypto_block_algorithm_c()
       
    51 {
       
    52 }
       
    53 
       
    54 EAP_FUNC_EXPORT abs_crypto_stream_algorithm_c::~abs_crypto_stream_algorithm_c()
       
    55 {
       
    56 }
       
    57 
       
    58 EAP_FUNC_EXPORT abs_crypto_hash_algorithm_c::~abs_crypto_hash_algorithm_c()
       
    59 {
       
    60 }
       
    61 
       
    62 EAP_FUNC_EXPORT abs_crypto_hmac_algorithm_c::~abs_crypto_hmac_algorithm_c()
       
    63 {
       
    64 }
       
    65 
       
    66 //--------------------------------------------------
       
    67 //--------------------------------------------------
       
    68 //--------------------------------------------------
       
    69 
       
    70 
       
    71 EAP_FUNC_EXPORT crypto_hmac_c::~crypto_hmac_c()
       
    72 {
       
    73 	hmac_cleanup();
       
    74 
       
    75 	delete m_key;
       
    76 	m_key = 0;
       
    77 
       
    78 	delete m_ipad;
       
    79 	m_ipad = 0;
       
    80 
       
    81 	delete m_opad;
       
    82 	m_opad = 0;
       
    83 }
       
    84 
       
    85 EAP_FUNC_EXPORT crypto_hmac_c::crypto_hmac_c(
       
    86 	abs_eap_am_tools_c * const tools,
       
    87 	abs_crypto_hash_algorithm_c * const crypto_hash_algorithm,
       
    88 	const bool free_crypto_hash_algorithm)
       
    89 	: m_am_tools(tools)
       
    90 	, m_crypto_hash_algorithm(crypto_hash_algorithm)
       
    91 	, m_key(0)
       
    92 	, m_ipad(0)
       
    93 	, m_opad(0)
       
    94 	, m_is_valid(false)
       
    95 	, m_free_crypto_hash_algorithm(free_crypto_hash_algorithm)
       
    96 {
       
    97 	m_key = new eap_variable_data_c(m_am_tools);
       
    98 	if (m_key == 0)
       
    99 	{
       
   100 		return;
       
   101 	}
       
   102 
       
   103 	m_ipad = new eap_variable_data_c(m_am_tools);
       
   104 	if (m_ipad == 0)
       
   105 	{
       
   106 		return;
       
   107 	}
       
   108 
       
   109 	m_opad = new eap_variable_data_c(m_am_tools);
       
   110 	if (m_opad == 0)
       
   111 	{
       
   112 		return;
       
   113 	}
       
   114 
       
   115 	set_is_valid();
       
   116 }
       
   117 
       
   118 EAP_FUNC_EXPORT void crypto_hmac_c::set_is_valid()
       
   119 {
       
   120 	m_is_valid = true;
       
   121 }
       
   122 
       
   123 EAP_FUNC_EXPORT bool crypto_hmac_c::get_is_valid()
       
   124 {
       
   125 	return m_is_valid;
       
   126 }
       
   127 
       
   128 EAP_FUNC_EXPORT u32_t crypto_hmac_c::get_digest_length()
       
   129 {
       
   130 	return m_crypto_hash_algorithm->get_digest_length();
       
   131 }
       
   132 
       
   133 EAP_FUNC_EXPORT eap_status_e crypto_hmac_c::initialize_pad(
       
   134 	eap_variable_data_c * const p_pad,
       
   135 	const u8_t pad_value)
       
   136 {
       
   137 	if (get_is_valid() == false)
       
   138 	{
       
   139 		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
   140 	}
       
   141 
       
   142 	eap_status_e status = p_pad->set_buffer_length(
       
   143 		m_crypto_hash_algorithm->get_block_size());
       
   144 	if (status != eap_status_ok)
       
   145 	{
       
   146 		return EAP_STATUS_RETURN(m_am_tools, status);
       
   147 	}
       
   148 	p_pad->set_data_length(m_crypto_hash_algorithm->get_block_size());
       
   149 
       
   150 	u32_t ind = 0ul;
       
   151 	u8_t * key = m_key->get_data(m_key->get_data_length());
       
   152 	u8_t * ipad = p_pad->get_data(p_pad->get_data_length());
       
   153 	
       
   154 	for (ind = 0ul; ind < m_key->get_data_length(); ind++)
       
   155 	{
       
   156 		ipad[ind] = static_cast<u8_t>(key[ind] ^ pad_value);
       
   157 	}
       
   158 	
       
   159 	for (ind = m_key->get_data_length()
       
   160 			 ; ind < m_crypto_hash_algorithm->get_block_size(); ind++)
       
   161 	{
       
   162 		ipad[ind] = pad_value;
       
   163 	}
       
   164 
       
   165 	return EAP_STATUS_RETURN(m_am_tools, status);
       
   166 }
       
   167 
       
   168 EAP_FUNC_EXPORT eap_status_e crypto_hmac_c::hmac_set_key(
       
   169 	const eap_variable_data_c * const hmac_key)
       
   170 {
       
   171 	if (hmac_key == 0
       
   172 		|| hmac_key->get_is_valid_data() == false
       
   173 		|| get_is_valid() == false)
       
   174 	{
       
   175 		return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_parameter);
       
   176 	}
       
   177 
       
   178 	eap_status_e status = eap_status_process_general_error;
       
   179 
       
   180 	status = m_crypto_hash_algorithm->hash_init();
       
   181 	if (status != eap_status_ok)
       
   182 	{
       
   183 		return EAP_STATUS_RETURN(m_am_tools, status);
       
   184 	}
       
   185 
       
   186 	if (hmac_key->get_data_length()
       
   187 		> m_crypto_hash_algorithm->get_block_size())
       
   188 	{
       
   189 		status = m_crypto_hash_algorithm->hash_update(
       
   190 			hmac_key->get_data(hmac_key->get_data_length()),
       
   191 			hmac_key->get_data_length());
       
   192 		if (status != eap_status_ok)
       
   193 		{
       
   194 			return EAP_STATUS_RETURN(m_am_tools, status);
       
   195 		}
       
   196 
       
   197 		status = m_key->set_buffer_length(
       
   198 			m_crypto_hash_algorithm->get_digest_length());
       
   199 		if (status != eap_status_ok)
       
   200 		{
       
   201 			return EAP_STATUS_RETURN(m_am_tools, status);
       
   202 		}
       
   203 		m_key->set_data_length(m_crypto_hash_algorithm->get_digest_length());
       
   204 
       
   205 		u32_t md_length = m_key->get_data_length();
       
   206 
       
   207 		status = m_crypto_hash_algorithm->hash_final(
       
   208 			m_key->get_data(m_key->get_data_length()),
       
   209 			&md_length);
       
   210 		if (status != eap_status_ok)
       
   211 		{
       
   212 			return EAP_STATUS_RETURN(m_am_tools, status);
       
   213 		}
       
   214 
       
   215 		EAP_ASSERT(md_length == m_key->get_data_length());
       
   216 	}
       
   217 	else
       
   218 	{
       
   219 		status = m_key->set_copy_of_buffer(hmac_key);
       
   220 		if (status != eap_status_ok)
       
   221 		{
       
   222 			return EAP_STATUS_RETURN(m_am_tools, status);
       
   223 		}
       
   224 	}
       
   225 
       
   226 	// - - - - - - - - - - - - - - - - - - - -
       
   227 	// Initialize inner pad.
       
   228 
       
   229 	{
       
   230 		static const u8_t EAP_HMAC_IPAD = 0x36;
       
   231 
       
   232 		status = initialize_pad(
       
   233 			m_ipad,
       
   234 			EAP_HMAC_IPAD);
       
   235 		if (status != eap_status_ok)
       
   236 		{
       
   237 			return EAP_STATUS_RETURN(m_am_tools, status);
       
   238 		}
       
   239 	}
       
   240 
       
   241 	// - - - - - - - - - - - - - - - - - - - -
       
   242 	// Initialize outer pad.
       
   243 
       
   244 	{
       
   245 		static const u8_t EAP_HMAC_OPAD = 0x5C;
       
   246 
       
   247 		status = initialize_pad(
       
   248 			m_opad,
       
   249 			EAP_HMAC_OPAD);
       
   250 		if (status != eap_status_ok)
       
   251 		{
       
   252 			return EAP_STATUS_RETURN(m_am_tools, status);
       
   253 		}
       
   254 	}
       
   255 
       
   256 	// - - - - - - - - - - - - - - - - - - - -
       
   257 
       
   258 	status = m_crypto_hash_algorithm->hash_init();
       
   259 	if (status != eap_status_ok)
       
   260 	{
       
   261 		return EAP_STATUS_RETURN(m_am_tools, status);
       
   262 	}
       
   263 
       
   264 	status = m_crypto_hash_algorithm->hash_update(
       
   265 		m_ipad->get_data(m_ipad->get_data_length()),
       
   266 		m_ipad->get_data_length());
       
   267 	if (status != eap_status_ok)
       
   268 	{
       
   269 		return EAP_STATUS_RETURN(m_am_tools, status);
       
   270 	}
       
   271 
       
   272 	return EAP_STATUS_RETURN(m_am_tools, status);
       
   273 }
       
   274 
       
   275 EAP_FUNC_EXPORT eap_status_e crypto_hmac_c::hmac_update(
       
   276 	const void * const data,
       
   277 	const u32_t data_length)
       
   278 {
       
   279 	if (get_is_valid() == false)
       
   280 	{
       
   281 		return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_parameter);
       
   282 	}
       
   283 
       
   284 	eap_status_e status = m_crypto_hash_algorithm->hash_update(
       
   285 		data,
       
   286 		data_length);
       
   287 	if (status != eap_status_ok)
       
   288 	{
       
   289 		return EAP_STATUS_RETURN(m_am_tools, status);
       
   290 	}
       
   291 
       
   292 	return EAP_STATUS_RETURN(m_am_tools, status);
       
   293 }
       
   294 
       
   295 EAP_FUNC_EXPORT eap_status_e crypto_hmac_c::hmac_final(
       
   296 	void * const message_digest,
       
   297 	u32_t *md_length_or_null)
       
   298 {
       
   299 	if (get_is_valid() == false)
       
   300 	{
       
   301 		return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_parameter);
       
   302 	}
       
   303 
       
   304 	eap_variable_data_c idigest(m_am_tools);
       
   305 
       
   306 	eap_status_e status = idigest.set_buffer_length(
       
   307 		m_crypto_hash_algorithm->get_digest_length());
       
   308 	if (status != eap_status_ok)
       
   309 	{
       
   310 		return EAP_STATUS_RETURN(m_am_tools, status);
       
   311 	}
       
   312 	idigest.set_data_length(m_crypto_hash_algorithm->get_digest_length());
       
   313 
       
   314 	u32_t md_length = idigest.get_data_length();
       
   315 
       
   316 	status = m_crypto_hash_algorithm->hash_final(
       
   317 		idigest.get_data(idigest.get_data_length()),
       
   318 		&md_length);
       
   319 	if (status != eap_status_ok)
       
   320 	{
       
   321 		return EAP_STATUS_RETURN(m_am_tools, status);
       
   322 	}
       
   323 
       
   324 	EAP_ASSERT(md_length == m_crypto_hash_algorithm->get_digest_length());
       
   325 
       
   326 	// - - - - - - - - - - - - - - - - - - - - - - - -
       
   327 
       
   328 	status = m_crypto_hash_algorithm->hash_init();
       
   329 	if (status != eap_status_ok)
       
   330 	{
       
   331 		return EAP_STATUS_RETURN(m_am_tools, status);
       
   332 	}
       
   333 
       
   334 	status = m_crypto_hash_algorithm->hash_update(
       
   335 		m_opad->get_data(m_opad->get_data_length()),
       
   336 		m_opad->get_data_length());
       
   337 	if (status != eap_status_ok)
       
   338 	{
       
   339 		return EAP_STATUS_RETURN(m_am_tools, status);
       
   340 	}
       
   341 
       
   342 	status = m_crypto_hash_algorithm->hash_update(
       
   343 		idigest.get_data(idigest.get_data_length()),
       
   344 		idigest.get_data_length());
       
   345 	if (status != eap_status_ok)
       
   346 	{
       
   347 		return EAP_STATUS_RETURN(m_am_tools, status);
       
   348 	}
       
   349 
       
   350 	status = m_crypto_hash_algorithm->hash_final(
       
   351 		message_digest,
       
   352 		md_length_or_null);
       
   353 	if (status != eap_status_ok)
       
   354 	{
       
   355 		return EAP_STATUS_RETURN(m_am_tools, status);
       
   356 	}
       
   357 
       
   358 	if (md_length_or_null != 0)
       
   359 	{
       
   360 		EAP_ASSERT(*md_length_or_null
       
   361 				   == m_crypto_hash_algorithm->get_digest_length());
       
   362 	}
       
   363 
       
   364 	return EAP_STATUS_RETURN(m_am_tools, status);
       
   365 }
       
   366 
       
   367 
       
   368 EAP_FUNC_EXPORT eap_status_e crypto_hmac_c::hmac_128_final(
       
   369 	void * const message_digest,
       
   370 	u32_t *md_length_or_null)
       
   371 {
       
   372 	if (message_digest == 0)
       
   373 	{
       
   374 		return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_parameter);
       
   375 	}
       
   376 
       
   377 	u32_t tmp_length = get_digest_length();
       
   378 	eap_variable_data_c tmp_digest(m_am_tools);
       
   379 	if (tmp_digest.get_is_valid() == false)
       
   380 	{
       
   381 		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
   382 	}
       
   383 	eap_status_e status = tmp_digest.set_buffer_length(tmp_length);
       
   384 	if (status != eap_status_ok)
       
   385 	{
       
   386 		return EAP_STATUS_RETURN(m_am_tools, status);
       
   387 	}
       
   388 
       
   389 	status = hmac_final(
       
   390 		tmp_digest.get_buffer(tmp_digest.get_buffer_length()),
       
   391 		&tmp_length);
       
   392 	if (status != eap_status_ok
       
   393 		|| tmp_length != tmp_digest.get_buffer_length())
       
   394 	{
       
   395 		if (md_length_or_null != 0)
       
   396 		{
       
   397 			*md_length_or_null = 0;
       
   398 		}
       
   399 		return EAP_STATUS_RETURN(m_am_tools, status);
       
   400 	}
       
   401 	else
       
   402 	{
       
   403 		status = tmp_digest.set_data_length(tmp_length);
       
   404 		if (status != eap_status_ok)
       
   405 	    {
       
   406 			return EAP_STATUS_RETURN(m_am_tools, status);
       
   407 	    }
       
   408 
       
   409 		if (md_length_or_null != 0)
       
   410 		{
       
   411 			*md_length_or_null = HMAC_SHA1_128_SIZE;
       
   412 		}
       
   413 
       
   414 		m_am_tools->memmove(
       
   415 			message_digest,
       
   416 			tmp_digest.get_data(HMAC_SHA1_128_SIZE),
       
   417 			HMAC_SHA1_128_SIZE);
       
   418 
       
   419 		return EAP_STATUS_RETURN(m_am_tools, status);
       
   420 	}
       
   421 }
       
   422 
       
   423 EAP_FUNC_EXPORT eap_status_e crypto_hmac_c::hmac_cleanup()
       
   424 {
       
   425 	if (m_key != 0)
       
   426 	{
       
   427 		m_key->reset();
       
   428 	}
       
   429 
       
   430 	if (m_ipad != 0)
       
   431 	{
       
   432 		m_ipad->reset();
       
   433 	}
       
   434 
       
   435 	if (m_opad != 0)
       
   436 	{
       
   437 		m_opad->reset();
       
   438 	}
       
   439 
       
   440 	if (m_free_crypto_hash_algorithm == true)
       
   441 	{
       
   442 		delete m_crypto_hash_algorithm;
       
   443 	}
       
   444 	m_crypto_hash_algorithm = 0;
       
   445 
       
   446 	m_is_valid = false;
       
   447 
       
   448 	return EAP_STATUS_RETURN(m_am_tools, eap_status_ok);
       
   449 }
       
   450 
       
   451 //--------------------------------------------------
       
   452 //--------------------------------------------------
       
   453 //--------------------------------------------------
       
   454 
       
   455 EAP_FUNC_EXPORT crypto_cbc_c::~crypto_cbc_c()
       
   456 {
       
   457 	reset();
       
   458 }
       
   459 
       
   460 //--------------------------------------------------
       
   461 
       
   462 EAP_FUNC_EXPORT crypto_cbc_c::crypto_cbc_c(
       
   463 	abs_eap_am_tools_c * const tools,
       
   464 	abs_crypto_block_algorithm_c * const crypto_block_algorithm,
       
   465 	const bool free_crypto_block_algorithm)
       
   466 	: m_am_tools(tools)
       
   467 	, m_crypto_block_algorithm(crypto_block_algorithm)
       
   468 	, m_is_valid(false)
       
   469 	, m_tmp_IV(0)
       
   470 	, m_encr_offset(0ul)
       
   471 	, m_encr_dispatch(0)
       
   472 	, m_encr_hold(0)
       
   473 	, m_saved_in_buffer(0)
       
   474 	, m_saved_out_buffer(0)
       
   475 	, m_iv_buffer_1(0)
       
   476 	, m_iv_buffer_2(0)
       
   477 	, m_free_crypto_block_algorithm(free_crypto_block_algorithm)
       
   478 {
       
   479 	m_tmp_IV = new eap_variable_data_c(m_am_tools);
       
   480 	m_encr_dispatch = new u8_t *[m_crypto_block_algorithm->get_block_size()];
       
   481 	m_encr_hold = new u8_t [m_crypto_block_algorithm->get_block_size()];
       
   482 	m_saved_in_buffer = new u8_t [m_crypto_block_algorithm->get_block_size()];
       
   483 	m_saved_out_buffer = new u8_t [m_crypto_block_algorithm->get_block_size()];
       
   484 	m_iv_buffer_1 = new u8_t [m_crypto_block_algorithm->get_block_size()];
       
   485 	m_iv_buffer_2 = new u8_t [m_crypto_block_algorithm->get_block_size()];
       
   486 
       
   487 	if (m_tmp_IV == 0
       
   488 		|| m_encr_dispatch == 0
       
   489 		|| m_encr_hold == 0
       
   490 		|| m_saved_in_buffer == 0
       
   491 		|| m_saved_out_buffer == 0
       
   492 		|| m_iv_buffer_1 == 0
       
   493 		|| m_iv_buffer_2 == 0)
       
   494 	{
       
   495 		reset();
       
   496 	}
       
   497 	else
       
   498 	{
       
   499 		set_is_valid();
       
   500 	}
       
   501 }
       
   502 
       
   503 //--------------------------------------------------
       
   504 
       
   505 EAP_FUNC_EXPORT void crypto_cbc_c::reset()
       
   506 {
       
   507 	m_is_valid = false;
       
   508 
       
   509 	if (m_tmp_IV != 0)
       
   510 	{
       
   511 		m_tmp_IV->reset();
       
   512 		delete m_tmp_IV;
       
   513 		m_tmp_IV = 0;
       
   514 	}
       
   515 
       
   516 	if (m_crypto_block_algorithm != 0)
       
   517 	{
       
   518 		if (m_encr_dispatch != 0)
       
   519 		{
       
   520 			m_am_tools->memset(
       
   521 				m_encr_dispatch,
       
   522 				0,
       
   523 				m_crypto_block_algorithm->get_block_size());
       
   524 		}
       
   525 
       
   526 		if (m_encr_hold != 0)
       
   527 		{
       
   528 			m_am_tools->memset(
       
   529 				m_encr_hold,
       
   530 				0,
       
   531 				m_crypto_block_algorithm->get_block_size());
       
   532 		}
       
   533 	}
       
   534 
       
   535 	delete [] m_encr_dispatch;
       
   536 	m_encr_dispatch = 0;
       
   537 
       
   538 	delete [] m_encr_hold;
       
   539 	m_encr_hold = 0;
       
   540 
       
   541 	delete [] m_saved_in_buffer;
       
   542 	m_saved_in_buffer = 0;
       
   543 
       
   544 	delete [] m_saved_out_buffer;
       
   545 	m_saved_out_buffer = 0;
       
   546 
       
   547 	delete [] m_iv_buffer_1;
       
   548 	m_iv_buffer_1 = 0;
       
   549 
       
   550 	delete [] m_iv_buffer_2;
       
   551 	m_iv_buffer_2 = 0;
       
   552 
       
   553 	if (m_free_crypto_block_algorithm == true)
       
   554 	{
       
   555 		delete m_crypto_block_algorithm;
       
   556 	}
       
   557 	m_crypto_block_algorithm = 0;
       
   558 }
       
   559 
       
   560 //--------------------------------------------------
       
   561 
       
   562 EAP_FUNC_EXPORT void crypto_cbc_c::cbc_xor_block(
       
   563 	const void * const cipher_IV,
       
   564 	void * const data_block,
       
   565 	const u32_t block_size,
       
   566 	const u32_t key_length)
       
   567 {
       
   568 	EAP_UNREFERENCED_PARAMETER(block_size);
       
   569 	EAP_UNREFERENCED_PARAMETER(key_length);
       
   570 	EAP_ASSERT((block_size % m_crypto_block_algorithm->get_block_size()) == 0);
       
   571 	EAP_ASSERT((key_length % m_crypto_block_algorithm->get_key_length()) == 0);
       
   572 
       
   573 #if defined(USE_EAP_64_BIT_MULTIPLICATION)
       
   574 	if ((reinterpret_cast<u32_t>(cipher_IV) % sizeof(u64_t)) == 0
       
   575 		&& (reinterpret_cast<u32_t>(data_block) % sizeof(u64_t)) == 0)
       
   576 	{
       
   577 		const u64_t * const pIV = static_cast<const u64_t *>(cipher_IV);
       
   578 		u64_t * const pdata = static_cast<u64_t *>(data_block);
       
   579 
       
   580 		for (u32_t ind = 0u; ind < block_size/sizeof(u64_t); ind++)
       
   581 		{
       
   582 			pdata[ind] ^= pIV[ind];
       
   583 		}
       
   584 	}
       
   585 	else
       
   586 #endif //#if defined(USE_EAP_64_BIT_MULTIPLICATION)
       
   587 	if ((reinterpret_cast<u32_t>(cipher_IV) % sizeof(u32_t)) == 0
       
   588 		&& (reinterpret_cast<u32_t>(data_block) % sizeof(u32_t)) == 0)
       
   589 	{
       
   590 		const u32_t * const pIV = static_cast<const u32_t *>(cipher_IV);
       
   591 		u32_t * const pdata = static_cast<u32_t *>(data_block);
       
   592 
       
   593 		for (u32_t ind = 0u; ind < block_size/sizeof(u32_t); ind++)
       
   594 		{
       
   595 			pdata[ind] ^= pIV[ind];
       
   596 		}
       
   597 	}
       
   598 	else if ((reinterpret_cast<u32_t>(cipher_IV) % sizeof(u16_t)) == 0
       
   599 		&& (reinterpret_cast<u32_t>(data_block) % sizeof(u16_t)) == 0)
       
   600 	{
       
   601 		const u16_t * const pIV = static_cast<const u16_t *>(cipher_IV);
       
   602 		u16_t * const pdata = static_cast<u16_t *>(data_block);
       
   603 
       
   604 		for (u32_t ind = 0u; ind < block_size/sizeof(u16_t); ind++)
       
   605 		{
       
   606 			pdata[ind] ^= pIV[ind];
       
   607 		}
       
   608 	}
       
   609 	else
       
   610 	{
       
   611 		const u8_t * const pIV = static_cast<const u8_t *>(cipher_IV);
       
   612 		u8_t * const pdata = static_cast<u8_t *>(data_block);
       
   613 
       
   614 		for (u32_t ind = 0u; ind < block_size/sizeof(u8_t); ind++)
       
   615 		{
       
   616 			pdata[ind] ^= pIV[ind];
       
   617 		}
       
   618 	}
       
   619 }
       
   620 
       
   621 //--------------------------------------------------
       
   622 
       
   623 EAP_FUNC_EXPORT void crypto_cbc_c::cbc_copy_block(
       
   624 	void * const target,
       
   625 	const void * const source,
       
   626 	const u32_t block_size,
       
   627 	const u32_t key_length)
       
   628 {
       
   629 	EAP_UNREFERENCED_PARAMETER(key_length);
       
   630 	EAP_ASSERT((block_size % m_crypto_block_algorithm->get_block_size()) == 0);
       
   631 	EAP_ASSERT((key_length % m_crypto_block_algorithm->get_key_length()) == 0);
       
   632 
       
   633 #if defined(USE_EAP_64_BIT_MULTIPLICATION)
       
   634 	if ((reinterpret_cast<u32_t>(source) % sizeof(u64_t)) == 0
       
   635 		&& (reinterpret_cast<u32_t>(target) % sizeof(u64_t)) == 0)
       
   636 	{
       
   637 		const u64_t * const p_source
       
   638 			= static_cast<const u64_t *>(source);
       
   639 		u64_t * const p_target = static_cast<u64_t *>(target);
       
   640 
       
   641 		for (u32_t ind = 0u; ind < block_size/sizeof(u64_t); ind++)
       
   642 		{
       
   643 			p_target[ind] = p_source[ind];
       
   644 		}
       
   645 	}
       
   646 	else
       
   647 #endif //#if defined(USE_EAP_64_BIT_MULTIPLICATION)
       
   648 	if ((reinterpret_cast<u32_t>(source) % sizeof(u32_t)) == 0
       
   649 		&& (reinterpret_cast<u32_t>(target) % sizeof(u32_t)) == 0)
       
   650 	{
       
   651 		const u32_t * const p_source
       
   652 			= static_cast<const u32_t *>(source);
       
   653 		u32_t * const p_target = static_cast<u32_t *>(target);
       
   654 
       
   655 		for (u32_t ind = 0u; ind < block_size/sizeof(u32_t); ind++)
       
   656 		{
       
   657 			p_target[ind] = p_source[ind];
       
   658 		}
       
   659 	}
       
   660 	else if ((reinterpret_cast<u32_t>(source) % sizeof(u16_t)) == 0
       
   661 		&& (reinterpret_cast<u32_t>(target) % sizeof(u16_t)) == 0)
       
   662 	{
       
   663 		const u16_t * const p_source
       
   664 			= static_cast<const u16_t *>(source);
       
   665 		u16_t * const p_target = static_cast<u16_t *>(target);
       
   666 
       
   667 		for (u32_t ind = 0u; ind < block_size/sizeof(u16_t); ind++)
       
   668 		{
       
   669 			p_target[ind] = p_source[ind];
       
   670 		}
       
   671 	}
       
   672 	else
       
   673 	{
       
   674 		const u8_t * const p_source = static_cast<const u8_t *>(source);
       
   675 		u8_t * const p_target = static_cast<u8_t *>(target);
       
   676 
       
   677 		for (u32_t ind = 0u; ind < block_size/sizeof(u8_t); ind++)
       
   678 		{
       
   679 			p_target[ind] = p_source[ind];
       
   680 		}
       
   681 	}
       
   682 }
       
   683 
       
   684 //--------------------------------------------------
       
   685 
       
   686 EAP_FUNC_EXPORT void crypto_cbc_c::set_is_valid()
       
   687 {
       
   688 	m_is_valid = true;
       
   689 }
       
   690 
       
   691 //--------------------------------------------------
       
   692 
       
   693 EAP_FUNC_EXPORT bool crypto_cbc_c::get_is_valid()
       
   694 {
       
   695 	return m_is_valid;
       
   696 }
       
   697 
       
   698 //--------------------------------------------------
       
   699 
       
   700 EAP_FUNC_EXPORT const eap_variable_data_c * crypto_cbc_c::get_tmp_IV()
       
   701 {
       
   702 	return m_tmp_IV;
       
   703 }
       
   704 
       
   705 //--------------------------------------------------
       
   706 
       
   707 EAP_FUNC_EXPORT bool crypto_cbc_c::get_encrypts()
       
   708 {
       
   709 	return m_crypto_block_algorithm->get_encrypts();
       
   710 }
       
   711 
       
   712 //--------------------------------------------------
       
   713 
       
   714 EAP_FUNC_EXPORT u32_t crypto_cbc_c::get_key_length()
       
   715 {
       
   716 	return m_crypto_block_algorithm->get_key_length();
       
   717 }
       
   718 
       
   719 //--------------------------------------------------
       
   720 
       
   721 EAP_FUNC_EXPORT u32_t crypto_cbc_c::get_block_size()
       
   722 {
       
   723 	return m_crypto_block_algorithm->get_block_size();
       
   724 }
       
   725 
       
   726 //--------------------------------------------------
       
   727 
       
   728 EAP_FUNC_EXPORT u32_t crypto_cbc_c::aligned_data_length(
       
   729 	u32_t data_length)
       
   730 {
       
   731 	const u32_t fill_bytes = data_length
       
   732 		% (m_crypto_block_algorithm->get_block_size());
       
   733 
       
   734 	// NOTE, this will always add padding bytes (1...BLOCK_SIZE).
       
   735 	data_length += ((m_crypto_block_algorithm->get_block_size())-fill_bytes);
       
   736 
       
   737 	return data_length;
       
   738 }
       
   739 
       
   740 //--------------------------------------------------
       
   741 
       
   742 EAP_FUNC_EXPORT eap_status_e crypto_cbc_c::add_padding_bytes(
       
   743 	void * const buffer,
       
   744 	const u32_t buffer_length,
       
   745 	const u8_t padding_byte)
       
   746 {
       
   747 	u8_t * const p_buffer = static_cast<u8_t *>(buffer);
       
   748 
       
   749 	EAP_TRACE_DEBUG(
       
   750 		m_am_tools,
       
   751 		TRACE_FLAGS_DEFAULT,
       
   752 		(EAPL("CBC: encrypt_function: crypto_cbc_c::add_padding_bytes(): buffer=0x%08x, buffer_length=%d, padding_byte=0x%02x\n"),
       
   753 		buffer,
       
   754 		buffer_length,
       
   755 		padding_byte));
       
   756 
       
   757 	for(u32_t ind = 0; ind < buffer_length; ind++)
       
   758 	{
       
   759 		p_buffer[ind] = padding_byte;
       
   760 	}
       
   761 
       
   762 	EAP_TRACE_DATA_DEBUG(
       
   763 		m_am_tools,
       
   764 		TRACE_FLAGS_DEFAULT,
       
   765 		(EAPL("crypto_cbc_c::add_padding_bytes()"),
       
   766 		 p_buffer,
       
   767 		 buffer_length));
       
   768 
       
   769 	return EAP_STATUS_RETURN(m_am_tools, eap_status_ok);
       
   770 }
       
   771 
       
   772 //--------------------------------------------------
       
   773 
       
   774 EAP_FUNC_EXPORT eap_status_e crypto_cbc_c::check_padding_bytes(
       
   775 	const void * const buffer,
       
   776 	const u32_t buffer_length,
       
   777 	const u8_t padding_byte)
       
   778 {
       
   779 	const u8_t * const p_buffer = static_cast<const u8_t *>(buffer);
       
   780 
       
   781 	EAP_TRACE_DEBUG(
       
   782 		m_am_tools,
       
   783 		TRACE_FLAGS_DEFAULT,
       
   784 		(EAPL("CBC: encrypt_function: crypto_cbc_c::check_padding_bytes(): buffer=0x%08x, buffer_length=%d, padding_byte=0x%02x\n"),
       
   785 		buffer,
       
   786 		buffer_length,
       
   787 		padding_byte));
       
   788 
       
   789 	EAP_TRACE_DATA_DEBUG(
       
   790 		m_am_tools,
       
   791 		TRACE_FLAGS_DEFAULT,
       
   792 		(EAPL("crypto_cbc_c::check_padding_bytes()"),
       
   793 		 p_buffer,
       
   794 		 buffer_length));
       
   795 
       
   796 	for(u32_t ind = 0; ind < buffer_length; ind++)
       
   797 	{
       
   798 		if (p_buffer[ind] != padding_byte)
       
   799 		{
       
   800 			return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_padding);
       
   801 		}
       
   802 	}
       
   803 
       
   804 	return EAP_STATUS_RETURN(m_am_tools, eap_status_ok);
       
   805 }
       
   806 
       
   807 //--------------------------------------------------
       
   808 
       
   809 EAP_FUNC_EXPORT eap_status_e crypto_cbc_c::set_encryption_key(
       
   810 	const void * const encryption_IV,
       
   811 	const u32_t encryption_IV_length,
       
   812 	const void * const key,
       
   813 	const u32_t key_length)
       
   814 {
       
   815 	eap_status_e status = m_tmp_IV->set_copy_of_buffer(
       
   816 		encryption_IV, encryption_IV_length);
       
   817 	if (status != eap_status_ok)
       
   818 	{
       
   819 		return EAP_STATUS_RETURN(m_am_tools, status);
       
   820 	}
       
   821 
       
   822 	return m_crypto_block_algorithm->set_encryption_key(
       
   823 		key,
       
   824 		key_length);
       
   825 }
       
   826 
       
   827 //--------------------------------------------------
       
   828 
       
   829 EAP_FUNC_EXPORT eap_status_e crypto_cbc_c::set_decryption_key(
       
   830 	const void * const encryption_IV,
       
   831 	const u32_t encryption_IV_length,
       
   832 	const void * const key,
       
   833 	const u32_t key_length)
       
   834 {
       
   835 	eap_status_e status = m_tmp_IV->set_copy_of_buffer(
       
   836 		encryption_IV, encryption_IV_length);
       
   837 	if (status != eap_status_ok)
       
   838 	{
       
   839 		return EAP_STATUS_RETURN(m_am_tools, status);
       
   840 	}
       
   841 
       
   842 	return m_crypto_block_algorithm->set_decryption_key(
       
   843 		key,
       
   844 		key_length);
       
   845 }
       
   846 
       
   847 //--------------------------------------------------
       
   848 
       
   849 EAP_FUNC_EXPORT eap_status_e crypto_cbc_c::internal_encrypt_data(
       
   850 	const void * const data_in,
       
   851 	void * const data_out,
       
   852 	const u32_t data_length)
       
   853 {
       
   854 	if ((data_length % m_crypto_block_algorithm->get_block_size()) != 0)
       
   855 	{
       
   856 		return EAP_STATUS_RETURN(
       
   857 			m_am_tools,
       
   858 			eap_status_data_length_not_aligned_to_block_size);
       
   859 	}
       
   860 
       
   861 	const u8_t * const p_data_in = static_cast<const u8_t *>(data_in);
       
   862 	u8_t * const p_data_out = static_cast<u8_t *>(data_out);
       
   863 
       
   864 	EAP_TRACE_DATA_DEBUG(
       
   865 		m_am_tools,
       
   866 		TRACE_FLAGS_EAP_AM_CRYPTO,
       
   867 		(EAPL("encrypt data_in"),
       
   868 		data_in, data_length));
       
   869 
       
   870 	cbc_copy_block(
       
   871 		m_saved_in_buffer,
       
   872 		data_in,
       
   873 		m_crypto_block_algorithm->get_block_size(),
       
   874 		m_crypto_block_algorithm->get_key_length());
       
   875 
       
   876 	cbc_xor_block(
       
   877 		m_tmp_IV->get_data(m_tmp_IV->get_data_length()),
       
   878 		m_saved_in_buffer,
       
   879 		m_crypto_block_algorithm->get_block_size(),
       
   880 		m_crypto_block_algorithm->get_key_length());
       
   881 
       
   882 	u32_t ind;
       
   883 	eap_status_e status = eap_status_ok;
       
   884 
       
   885 	for (ind = 0u; ind < data_length
       
   886 			 ; ind += m_crypto_block_algorithm->get_block_size())
       
   887 	{
       
   888 		if (ind > 0u)
       
   889 		{
       
   890 			cbc_copy_block(
       
   891 				m_saved_in_buffer,
       
   892 				p_data_in+ind,
       
   893 				m_crypto_block_algorithm->get_block_size(),
       
   894 				m_crypto_block_algorithm->get_key_length());
       
   895 
       
   896 			cbc_xor_block(
       
   897 				p_data_out+(ind-m_crypto_block_algorithm->get_block_size()),
       
   898 				m_saved_in_buffer,
       
   899 				m_crypto_block_algorithm->get_block_size(),
       
   900 				m_crypto_block_algorithm->get_key_length());
       
   901 		}
       
   902 
       
   903 		status = m_crypto_block_algorithm->encrypt_block(
       
   904 			m_saved_in_buffer,
       
   905 			m_saved_out_buffer,
       
   906 			m_crypto_block_algorithm->get_block_size());
       
   907 		if (status != eap_status_ok)
       
   908 		{
       
   909 			return EAP_STATUS_RETURN(m_am_tools, status);
       
   910 		}
       
   911 
       
   912 		cbc_copy_block(
       
   913 			p_data_out+ind,
       
   914 			m_saved_out_buffer,
       
   915 			m_crypto_block_algorithm->get_block_size(),
       
   916 			m_crypto_block_algorithm->get_key_length());
       
   917 
       
   918 	}
       
   919 
       
   920 	// Save the last block.
       
   921 	status = m_tmp_IV->set_copy_of_buffer(
       
   922 		p_data_out+(ind-m_crypto_block_algorithm->get_block_size()),
       
   923 		m_crypto_block_algorithm->get_block_size());
       
   924 
       
   925 	EAP_TRACE_DATA_DEBUG(
       
   926 		m_am_tools,
       
   927 		TRACE_FLAGS_EAP_AM_CRYPTO,
       
   928 		(EAPL("encrypt data_out"),
       
   929 		 data_out,
       
   930 		 data_length));
       
   931 
       
   932 	return EAP_STATUS_RETURN(m_am_tools, status);
       
   933 }
       
   934 
       
   935 //--------------------------------------------------
       
   936 
       
   937 EAP_FUNC_EXPORT eap_status_e crypto_cbc_c::encrypt_data(
       
   938 	const void * const data_in,
       
   939 	void * const data_out,
       
   940 	const u32_t data_length)
       
   941 {
       
   942 	EAP_ASSERT(data_in != data_out);
       
   943 
       
   944 	eap_status_e status = internal_encrypt_data(
       
   945 		data_in,
       
   946 		data_out,
       
   947 		data_length);
       
   948 
       
   949 	return EAP_STATUS_RETURN(m_am_tools, status);
       
   950 }
       
   951 
       
   952 //--------------------------------------------------
       
   953 
       
   954 EAP_FUNC_EXPORT eap_status_e crypto_cbc_c::encrypt_data(
       
   955 	void * const data_in_out,
       
   956 	const u32_t data_length)
       
   957 {
       
   958 
       
   959 	eap_status_e status = internal_encrypt_data(
       
   960 		data_in_out,
       
   961 		data_in_out,
       
   962 		data_length);
       
   963 
       
   964 	return EAP_STATUS_RETURN(m_am_tools, status);
       
   965 }
       
   966 
       
   967 //--------------------------------------------------
       
   968 
       
   969 EAP_FUNC_EXPORT eap_status_e crypto_cbc_c::internal_decrypt_data(
       
   970 	const void * const data_in,
       
   971 	void * const data_out,
       
   972 	const u32_t data_length)
       
   973 {
       
   974 	u8_t *saved_iv_buffer = m_iv_buffer_1;
       
   975 	u8_t *encrypted_buffer = m_iv_buffer_2;
       
   976 
       
   977 	if ((data_length % m_crypto_block_algorithm->get_block_size()) != 0u)
       
   978 	{
       
   979 		return EAP_STATUS_RETURN(
       
   980 			m_am_tools,
       
   981 			eap_status_data_length_not_aligned_to_block_size);
       
   982 	}
       
   983 
       
   984 	EAP_TRACE_DATA_DEBUG(
       
   985 		m_am_tools,
       
   986 		TRACE_FLAGS_EAP_AM_CRYPTO,
       
   987 		(EAPL("decrypt data_in"),
       
   988 		 data_in,
       
   989 		 data_length));
       
   990 
       
   991 	const u8_t * const p_data_in = static_cast<const u8_t *>(data_in);
       
   992 	u8_t * const p_data_out = static_cast<u8_t *>(data_out);
       
   993 
       
   994 	cbc_copy_block(
       
   995 		saved_iv_buffer,
       
   996 		m_tmp_IV->get_data(m_tmp_IV->get_data_length()),
       
   997 		m_crypto_block_algorithm->get_block_size(),
       
   998 		m_crypto_block_algorithm->get_key_length());
       
   999 
       
  1000 	u32_t ind;
       
  1001 	eap_status_e status = eap_status_ok;
       
  1002 
       
  1003 	for (ind = 0u; ind < data_length
       
  1004 			 ; ind += m_crypto_block_algorithm->get_block_size())
       
  1005 	{
       
  1006 		cbc_copy_block(
       
  1007 			encrypted_buffer,
       
  1008 			p_data_in+ind,
       
  1009 			m_crypto_block_algorithm->get_block_size(),
       
  1010 			m_crypto_block_algorithm->get_key_length());
       
  1011 
       
  1012 		cbc_copy_block(
       
  1013 			m_saved_in_buffer,
       
  1014 			p_data_in+ind,
       
  1015 			m_crypto_block_algorithm->get_block_size(),
       
  1016 			m_crypto_block_algorithm->get_key_length());
       
  1017 
       
  1018 		status = m_crypto_block_algorithm->decrypt_block(
       
  1019 			m_saved_in_buffer,
       
  1020 			m_saved_out_buffer,
       
  1021 			m_crypto_block_algorithm->get_block_size());
       
  1022 		if (status != eap_status_ok)
       
  1023 		{
       
  1024 			return EAP_STATUS_RETURN(m_am_tools, status);
       
  1025 		}
       
  1026 
       
  1027 		cbc_xor_block(
       
  1028 			saved_iv_buffer,
       
  1029 			m_saved_out_buffer,
       
  1030 			m_crypto_block_algorithm->get_block_size(),
       
  1031 			m_crypto_block_algorithm->get_key_length());
       
  1032 
       
  1033 		cbc_copy_block(
       
  1034 			p_data_out+ind,
       
  1035 			m_saved_out_buffer,
       
  1036 			m_crypto_block_algorithm->get_block_size(),
       
  1037 			m_crypto_block_algorithm->get_key_length());
       
  1038 
       
  1039 		u8_t *tmp = encrypted_buffer;
       
  1040 		encrypted_buffer = saved_iv_buffer;
       
  1041 		saved_iv_buffer = tmp;
       
  1042 	}
       
  1043 
       
  1044 	EAP_TRACE_DATA_DEBUG(
       
  1045 		m_am_tools,
       
  1046 		TRACE_FLAGS_EAP_AM_CRYPTO,
       
  1047 		(EAPL("decrypt data_out"),
       
  1048 		 data_out,
       
  1049 		 data_length));
       
  1050 
       
  1051 	// Save the last block.
       
  1052 	status = m_tmp_IV->set_copy_of_buffer(
       
  1053 		saved_iv_buffer,
       
  1054 		m_crypto_block_algorithm->get_block_size());
       
  1055 
       
  1056 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  1057 }
       
  1058 
       
  1059 //--------------------------------------------------
       
  1060 
       
  1061 EAP_FUNC_EXPORT eap_status_e crypto_cbc_c::decrypt_data(
       
  1062 	const void * const data_in,
       
  1063 	void * const data_out,
       
  1064 	const u32_t data_length)
       
  1065 {
       
  1066 	EAP_ASSERT(data_in != data_out);
       
  1067 
       
  1068 	eap_status_e status = internal_decrypt_data(
       
  1069 		data_in,
       
  1070 		data_out,
       
  1071 		data_length);
       
  1072 
       
  1073 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  1074 }
       
  1075 
       
  1076 //--------------------------------------------------
       
  1077 
       
  1078 EAP_FUNC_EXPORT eap_status_e crypto_cbc_c::decrypt_data(
       
  1079 	void * const data_in_out,
       
  1080 	const u32_t data_length)
       
  1081 {
       
  1082 
       
  1083 	eap_status_e status = internal_decrypt_data(
       
  1084 		data_in_out,
       
  1085 		data_in_out,
       
  1086 		data_length);
       
  1087 
       
  1088 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  1089 }
       
  1090 
       
  1091 //--------------------------------------------------
       
  1092 
       
  1093 EAP_FUNC_EXPORT eap_status_e crypto_cbc_c::update_non_aligned(
       
  1094 	const void * const msg_in,
       
  1095 	void * const msg_out,
       
  1096 	const u32_t msg_size)
       
  1097 {
       
  1098 	EAP_ASSERT_ALWAYS(msg_in != msg_out);
       
  1099 
       
  1100 	const u8_t *inp = reinterpret_cast<const u8_t *>(msg_in);
       
  1101 	u8_t *oup = static_cast<u8_t *>(msg_out);
       
  1102 	i32_t len = static_cast<i32_t>(msg_size);
       
  1103 	i32_t tail;
       
  1104 	eap_status_e status = eap_status_process_general_error;
       
  1105 
       
  1106 	if (m_encr_offset)
       
  1107 	{
       
  1108 		//
       
  1109 		// Non aligned handling
       
  1110 		//
       
  1111 		while (len > 0
       
  1112 			&& m_encr_offset
       
  1113 			   < static_cast<i32_t>(m_crypto_block_algorithm->get_block_size()))
       
  1114 		{
       
  1115 			m_encr_dispatch[m_encr_offset] = oup++;
       
  1116 			m_encr_hold[m_encr_offset++] = *inp++;
       
  1117 			len--;
       
  1118 		}
       
  1119 
       
  1120 		if (m_encr_offset == static_cast<i32_t>(m_crypto_block_algorithm->get_block_size()))
       
  1121 		{
       
  1122 			// Got full block, flush out
       
  1123 			if (m_crypto_block_algorithm->get_encrypts() == true)
       
  1124 			{
       
  1125 				status = encrypt_data(
       
  1126 					m_encr_hold,
       
  1127 					m_crypto_block_algorithm->get_block_size());
       
  1128 			}
       
  1129 			else
       
  1130 			{
       
  1131 				status = decrypt_data(
       
  1132 					m_encr_hold,
       
  1133 					m_crypto_block_algorithm->get_block_size());
       
  1134 			}
       
  1135 
       
  1136 			if (status != eap_status_ok)
       
  1137 			{
       
  1138 				EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1139 				return EAP_STATUS_RETURN(m_am_tools, status);
       
  1140 			}
       
  1141 
       
  1142 			for (m_encr_offset = 0
       
  1143 					 ; m_encr_offset
       
  1144 					 < static_cast<i32_t>(m_crypto_block_algorithm->get_block_size())
       
  1145 					 ; ++m_encr_offset)
       
  1146 			{
       
  1147 				*(m_encr_dispatch[m_encr_offset]) = m_encr_hold[m_encr_offset];
       
  1148 			}
       
  1149 			m_encr_offset = 0;
       
  1150 		}
       
  1151 		// Either len == 0 or (encrypt->encr_offset) == 0, or both!!!
       
  1152 	}
       
  1153 
       
  1154 	tail = len % m_crypto_block_algorithm->get_block_size();
       
  1155 	len -= tail;
       
  1156 	if (len > 0)
       
  1157 	{
       
  1158 		if (m_crypto_block_algorithm->get_encrypts() == true)
       
  1159 		{
       
  1160 			status = encrypt_data(
       
  1161 				inp,
       
  1162 				oup,
       
  1163 				len);
       
  1164 		}
       
  1165 		else
       
  1166 		{
       
  1167 			status = decrypt_data(
       
  1168 				inp,
       
  1169 				oup,
       
  1170 				len);
       
  1171 		}
       
  1172 
       
  1173 		if (status != eap_status_ok)
       
  1174 		{
       
  1175 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1176 			return EAP_STATUS_RETURN(m_am_tools, status);
       
  1177 		}
       
  1178 	}
       
  1179 
       
  1180 	if (tail > 0)
       
  1181 	{
       
  1182 		oup += len;
       
  1183 		inp += len;
       
  1184 		while (m_encr_offset < tail)
       
  1185 		{
       
  1186 			m_encr_dispatch[m_encr_offset] = oup++;
       
  1187 			m_encr_hold[m_encr_offset++] = *inp++;
       
  1188 		}
       
  1189 		status = eap_status_ok;
       
  1190 	}
       
  1191 
       
  1192 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  1193 }
       
  1194 
       
  1195 //--------------------------------------------------
       
  1196 
       
  1197 EAP_FUNC_EXPORT eap_status_e crypto_cbc_c::update_non_aligned(
       
  1198 	void * const msg_in_out,
       
  1199 	const u32_t msg_size)
       
  1200 {
       
  1201 	u8_t *msg = static_cast<u8_t *>(msg_in_out);
       
  1202 	i32_t len = static_cast<i32_t>(msg_size);
       
  1203 	i32_t tail;
       
  1204 	eap_status_e status = eap_status_process_general_error;
       
  1205 
       
  1206 	if (m_encr_offset)
       
  1207 	{
       
  1208 		//
       
  1209 		// Non aligned handling
       
  1210 		//
       
  1211 		while (len > 0
       
  1212 			&& m_encr_offset
       
  1213 			   < static_cast<i32_t>(m_crypto_block_algorithm->get_block_size()))
       
  1214 		{
       
  1215 			m_encr_dispatch[m_encr_offset] = msg;
       
  1216 			m_encr_hold[m_encr_offset++] = *msg++;
       
  1217 			len--;
       
  1218 		}
       
  1219 
       
  1220 		if (m_encr_offset == static_cast<i32_t>(m_crypto_block_algorithm->get_block_size()))
       
  1221 		{
       
  1222 			// Got full block, flush out
       
  1223 			if (m_crypto_block_algorithm->get_encrypts() == true)
       
  1224 			{
       
  1225 				status = encrypt_data(
       
  1226 					m_encr_hold,
       
  1227 					m_crypto_block_algorithm->get_block_size());
       
  1228 			}
       
  1229 			else
       
  1230 			{
       
  1231 				status = decrypt_data(
       
  1232 					m_encr_hold,
       
  1233 					m_crypto_block_algorithm->get_block_size());
       
  1234 			}
       
  1235 
       
  1236 			if (status != eap_status_ok)
       
  1237 			{
       
  1238 				EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1239 				return EAP_STATUS_RETURN(m_am_tools, status);
       
  1240 			}
       
  1241 
       
  1242 			for (m_encr_offset = 0
       
  1243 					 ; m_encr_offset
       
  1244 					 < static_cast<i32_t>(m_crypto_block_algorithm->get_block_size())
       
  1245 					 ; ++m_encr_offset)
       
  1246 			{
       
  1247 				*(m_encr_dispatch[m_encr_offset]) = m_encr_hold[m_encr_offset];
       
  1248 			}
       
  1249 			m_encr_offset = 0;
       
  1250 		}
       
  1251 		// Either len == 0 or (encrypt->encr_offset) == 0, or both!!!
       
  1252 	}
       
  1253 
       
  1254 	tail = len % m_crypto_block_algorithm->get_block_size();
       
  1255 	len -= tail;
       
  1256 	if (len > 0)
       
  1257 	{
       
  1258 		if (m_crypto_block_algorithm->get_encrypts() == true)
       
  1259 		{
       
  1260 			status = encrypt_data(
       
  1261 				msg,
       
  1262 				len);
       
  1263 		}
       
  1264 		else
       
  1265 		{
       
  1266 			status = decrypt_data(
       
  1267 				msg,
       
  1268 				len);
       
  1269 		}
       
  1270 
       
  1271 		if (status != eap_status_ok)
       
  1272 		{
       
  1273 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1274 			return EAP_STATUS_RETURN(m_am_tools, status);
       
  1275 		}
       
  1276 	}
       
  1277 
       
  1278 	if (tail > 0)
       
  1279 	{
       
  1280 		msg += len;
       
  1281 		while (m_encr_offset < tail)
       
  1282 		{
       
  1283 			m_encr_dispatch[m_encr_offset] = msg;
       
  1284 			m_encr_hold[m_encr_offset++] = *msg++;
       
  1285 		}
       
  1286 	}
       
  1287 
       
  1288 	return EAP_STATUS_RETURN(m_am_tools, eap_status_ok);
       
  1289 }
       
  1290 
       
  1291 //--------------------------------------------------
       
  1292 
       
  1293 EAP_FUNC_EXPORT eap_status_e crypto_cbc_c::finalize_non_aligned()
       
  1294 {
       
  1295 	eap_status_e status = eap_status_ok;
       
  1296 
       
  1297 	if (m_encr_offset > 0)
       
  1298 	{
       
  1299 		if ((m_encr_offset
       
  1300 			 % m_crypto_block_algorithm->get_block_size()) != 0u)
       
  1301 		{
       
  1302 			EAP_ASSERT_ALWAYS(
       
  1303 				(m_encr_offset
       
  1304 				 % m_crypto_block_algorithm->get_block_size()) == 0u);
       
  1305 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1306 			return EAP_STATUS_RETURN(m_am_tools, eap_status_data_length_not_aligned_to_block_size);
       
  1307 		}
       
  1308 
       
  1309 		i32_t ind;
       
  1310 
       
  1311 		/* Unfinished business... flush it out! */
       
  1312 		if (m_crypto_block_algorithm->get_encrypts() == true)
       
  1313 		{
       
  1314 			status = encrypt_data(
       
  1315 				m_encr_hold,
       
  1316 				m_crypto_block_algorithm->get_block_size());
       
  1317 		}
       
  1318 		else
       
  1319 		{
       
  1320 			status = decrypt_data(
       
  1321 				m_encr_hold,
       
  1322 				m_crypto_block_algorithm->get_block_size());
       
  1323 		}
       
  1324 
       
  1325 		if (status != eap_status_ok)
       
  1326 		{
       
  1327 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1328 			return EAP_STATUS_RETURN(m_am_tools, status);
       
  1329 		}
       
  1330 
       
  1331 		for (ind = 0u; ind < m_encr_offset; ++ind)
       
  1332 		{
       
  1333 			*(m_encr_dispatch[ind]) = m_encr_hold[ind];
       
  1334 		}
       
  1335 		m_encr_offset = 0;	/* (should not be needed, but... ) */
       
  1336 	}
       
  1337 
       
  1338 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  1339 }
       
  1340 
       
  1341 //--------------------------------------------------
       
  1342 //--------------------------------------------------
       
  1343 //--------------------------------------------------
       
  1344 
       
  1345 EAP_FUNC_EXPORT crypto_aes_c::~crypto_aes_c()
       
  1346 {
       
  1347 	if (m_aes_context.get_is_valid_data() == true)
       
  1348 	{
       
  1349 		m_am_tools->get_crypto()->aes_cleanup(&m_aes_context);
       
  1350 	}
       
  1351 	m_aes_context.reset();
       
  1352 }
       
  1353 
       
  1354 //--------------------------------------------------
       
  1355 
       
  1356 EAP_FUNC_EXPORT crypto_aes_c::crypto_aes_c(abs_eap_am_tools_c * const tools)
       
  1357 	: m_am_tools(tools)
       
  1358 	, m_is_valid(false)
       
  1359 	, m_aes_context(tools)
       
  1360 	, m_block_size(0u)
       
  1361 	, m_encrypt(false)
       
  1362 {
       
  1363 	m_block_size = m_am_tools->get_crypto()->aes_block_size();
       
  1364 
       
  1365 	m_aes_context.reset();
       
  1366 
       
  1367 	set_is_valid();
       
  1368 }
       
  1369 
       
  1370 //--------------------------------------------------
       
  1371 
       
  1372 EAP_FUNC_EXPORT bool crypto_aes_c::get_encrypts()
       
  1373 {
       
  1374 	return m_encrypt;
       
  1375 }
       
  1376 
       
  1377 //--------------------------------------------------
       
  1378 
       
  1379 EAP_FUNC_EXPORT void crypto_aes_c::set_is_valid()
       
  1380 {
       
  1381 	m_is_valid = true;
       
  1382 }
       
  1383 
       
  1384 //--------------------------------------------------
       
  1385 
       
  1386 EAP_FUNC_EXPORT bool crypto_aes_c::get_is_valid()
       
  1387 {
       
  1388 	return m_is_valid;
       
  1389 }
       
  1390 
       
  1391 //--------------------------------------------------
       
  1392 
       
  1393 EAP_FUNC_EXPORT u32_t crypto_aes_c::get_key_length()
       
  1394 {
       
  1395 	return m_am_tools->get_crypto()->aes_key_length();
       
  1396 }
       
  1397 
       
  1398 //--------------------------------------------------
       
  1399 
       
  1400 EAP_FUNC_EXPORT u32_t crypto_aes_c::get_block_size()
       
  1401 {
       
  1402 	return m_block_size;
       
  1403 }
       
  1404 
       
  1405 //--------------------------------------------------
       
  1406 
       
  1407 EAP_FUNC_EXPORT eap_status_e crypto_aes_c::set_encryption_key(
       
  1408 	const void * const key,
       
  1409 	const u32_t key_length)
       
  1410 {
       
  1411 	m_encrypt = true;
       
  1412 
       
  1413 	return m_am_tools->get_crypto()->aes_set_encryption_key(
       
  1414 		&m_aes_context, static_cast<const u8_t *>(key), key_length);
       
  1415 }
       
  1416 
       
  1417 //--------------------------------------------------
       
  1418 
       
  1419 EAP_FUNC_EXPORT eap_status_e crypto_aes_c::set_decryption_key(
       
  1420 	const void * const key,
       
  1421 	const u32_t key_length)
       
  1422 {
       
  1423 	m_encrypt = false;
       
  1424 
       
  1425 	return m_am_tools->get_crypto()->aes_set_decryption_key(
       
  1426 		&m_aes_context, static_cast<const u8_t *>(key), key_length);
       
  1427 }
       
  1428 
       
  1429 //--------------------------------------------------
       
  1430 
       
  1431 EAP_FUNC_EXPORT eap_status_e crypto_aes_c::encrypt_block(
       
  1432 	const void * const data_in,
       
  1433 	void * const data_out,
       
  1434 	const u32_t data_length)
       
  1435 {
       
  1436 	EAP_ASSERT_TOOLS(m_am_tools, ((reinterpret_cast<u32_t>(data_in) % 4) == 0));
       
  1437 	EAP_ASSERT_TOOLS(m_am_tools, ((reinterpret_cast<u32_t>(data_out) % 4) == 0));
       
  1438 
       
  1439 	return m_am_tools->get_crypto()->aes_encrypt_block(
       
  1440 		&m_aes_context,
       
  1441 		static_cast<const u8_t *>(data_in),
       
  1442 		static_cast<u8_t *>(data_out),
       
  1443 		data_length);
       
  1444 }
       
  1445 
       
  1446 //--------------------------------------------------
       
  1447 
       
  1448 EAP_FUNC_EXPORT eap_status_e crypto_aes_c::decrypt_block(
       
  1449 	const void * const data_in,
       
  1450 	void * const data_out,
       
  1451 	const u32_t data_length)
       
  1452 {
       
  1453 	EAP_ASSERT_TOOLS(m_am_tools, ((reinterpret_cast<u32_t>(data_in) % 4) == 0));
       
  1454 	EAP_ASSERT_TOOLS(m_am_tools, ((reinterpret_cast<u32_t>(data_out) % 4) == 0));
       
  1455 
       
  1456 	return m_am_tools->get_crypto()->aes_decrypt_block(
       
  1457 		&m_aes_context,
       
  1458 		static_cast<const u8_t *>(data_in),
       
  1459 		static_cast<u8_t *>(data_out), data_length);
       
  1460 }
       
  1461 
       
  1462 //--------------------------------------------------
       
  1463 //--------------------------------------------------
       
  1464 //--------------------------------------------------
       
  1465 
       
  1466 EAP_FUNC_EXPORT crypto_3des_ede_c::~crypto_3des_ede_c()
       
  1467 {
       
  1468 	if (m_context.get_is_valid_data() == true)
       
  1469 	{
       
  1470 		m_am_tools->get_crypto()->cleanup_3des_ede(&m_context);
       
  1471 	}
       
  1472 	m_context.reset();
       
  1473 }
       
  1474 
       
  1475 //--------------------------------------------------
       
  1476 
       
  1477 EAP_FUNC_EXPORT crypto_3des_ede_c::crypto_3des_ede_c(
       
  1478 	abs_eap_am_tools_c * const tools)
       
  1479 	: m_am_tools(tools)
       
  1480 	, m_is_valid(false)
       
  1481 	, m_context(tools)
       
  1482 	, m_block_size(0u)
       
  1483 	, m_encrypt(false)
       
  1484 {
       
  1485 	m_block_size = m_am_tools->get_crypto()->block_size_3des_ede();
       
  1486 
       
  1487 	m_context.reset();
       
  1488 
       
  1489 	set_is_valid();
       
  1490 }
       
  1491 
       
  1492 //--------------------------------------------------
       
  1493 
       
  1494 EAP_FUNC_EXPORT bool crypto_3des_ede_c::get_encrypts()
       
  1495 {
       
  1496 	return m_encrypt;
       
  1497 }
       
  1498 
       
  1499 //--------------------------------------------------
       
  1500 
       
  1501 EAP_FUNC_EXPORT void crypto_3des_ede_c::set_is_valid()
       
  1502 {
       
  1503 	m_is_valid = true;
       
  1504 }
       
  1505 
       
  1506 //--------------------------------------------------
       
  1507 
       
  1508 EAP_FUNC_EXPORT bool crypto_3des_ede_c::get_is_valid()
       
  1509 {
       
  1510 	return m_is_valid;
       
  1511 }
       
  1512 
       
  1513 //--------------------------------------------------
       
  1514 
       
  1515 EAP_FUNC_EXPORT u32_t crypto_3des_ede_c::get_key_length()
       
  1516 {
       
  1517 	return m_am_tools->get_crypto()->key_length_3des_ede();
       
  1518 }
       
  1519 
       
  1520 //--------------------------------------------------
       
  1521 
       
  1522 EAP_FUNC_EXPORT u32_t crypto_3des_ede_c::get_block_size()
       
  1523 {
       
  1524 	return m_block_size;
       
  1525 }
       
  1526 
       
  1527 //--------------------------------------------------
       
  1528 
       
  1529 EAP_FUNC_EXPORT eap_status_e crypto_3des_ede_c::set_encryption_key(
       
  1530 	const void * const key,
       
  1531 	const u32_t key_length)
       
  1532 {
       
  1533 	m_encrypt = true;
       
  1534 
       
  1535 	return m_am_tools->get_crypto()->set_encryption_key_3des_ede(
       
  1536 		&m_context, static_cast<const u8_t *>(key), key_length);
       
  1537 }
       
  1538 
       
  1539 //--------------------------------------------------
       
  1540 
       
  1541 EAP_FUNC_EXPORT eap_status_e crypto_3des_ede_c::set_decryption_key(
       
  1542 	const void * const key,
       
  1543 	const u32_t key_length)
       
  1544 {
       
  1545 	m_encrypt = false;
       
  1546 
       
  1547 	return m_am_tools->get_crypto()->set_decryption_key_3des_ede(
       
  1548 		&m_context, static_cast<const u8_t *>(key), key_length);
       
  1549 }
       
  1550 
       
  1551 //--------------------------------------------------
       
  1552 
       
  1553 EAP_FUNC_EXPORT eap_status_e crypto_3des_ede_c::encrypt_block(
       
  1554 	const void * const data_in,
       
  1555 	void * const data_out,
       
  1556 	const u32_t data_length)
       
  1557 {
       
  1558 	EAP_ASSERT_TOOLS(m_am_tools, ((reinterpret_cast<u32_t>(data_in) % 4) == 0));
       
  1559 	EAP_ASSERT_TOOLS(m_am_tools, ((reinterpret_cast<u32_t>(data_out) % 4) == 0));
       
  1560 
       
  1561 	return m_am_tools->get_crypto()->encrypt_block_3des_ede(
       
  1562 		&m_context,
       
  1563 		static_cast<const u8_t *>(data_in),
       
  1564 		static_cast<u8_t *>(data_out),
       
  1565 		data_length);
       
  1566 }
       
  1567 
       
  1568 //--------------------------------------------------
       
  1569 
       
  1570 EAP_FUNC_EXPORT eap_status_e crypto_3des_ede_c::decrypt_block(
       
  1571 	const void * const data_in,
       
  1572 	void * const data_out,
       
  1573 	const u32_t data_length)
       
  1574 {
       
  1575 	EAP_ASSERT_TOOLS(m_am_tools, ((reinterpret_cast<u32_t>(data_in) % 4) == 0));
       
  1576 	EAP_ASSERT_TOOLS(m_am_tools, ((reinterpret_cast<u32_t>(data_out) % 4) == 0));
       
  1577 
       
  1578 	return m_am_tools->get_crypto()->decrypt_block_3des_ede(
       
  1579 		&m_context,
       
  1580 		static_cast<const u8_t *>(data_in),
       
  1581 		static_cast<u8_t *>(data_out),
       
  1582 		data_length);
       
  1583 }
       
  1584 
       
  1585 //--------------------------------------------------
       
  1586 //--------------------------------------------------
       
  1587 //--------------------------------------------------
       
  1588 
       
  1589 EAP_FUNC_EXPORT crypto_aes_wrap_c::~crypto_aes_wrap_c()
       
  1590 {
       
  1591 }
       
  1592 
       
  1593 EAP_FUNC_EXPORT crypto_aes_wrap_c::crypto_aes_wrap_c(abs_eap_am_tools_c * const tools)
       
  1594 	: m_am_tools(tools)
       
  1595 	  , m_aes(tools)
       
  1596 	  , m_key(tools)
       
  1597 	  , m_encrypt(false)
       
  1598 	  , m_is_valid(false)
       
  1599 {
       
  1600 	if (m_aes.get_is_valid() == false)
       
  1601 	{
       
  1602 		return;
       
  1603 	}
       
  1604 
       
  1605 	if (m_key.get_is_valid() == false)
       
  1606 	{
       
  1607 		return;
       
  1608 	}
       
  1609 
       
  1610 	set_is_valid();
       
  1611 }
       
  1612 
       
  1613 EAP_FUNC_EXPORT void crypto_aes_wrap_c::set_is_valid()
       
  1614 {
       
  1615 	m_is_valid = true;
       
  1616 }
       
  1617 
       
  1618 EAP_FUNC_EXPORT bool crypto_aes_wrap_c::get_is_valid()
       
  1619 {
       
  1620 	return m_is_valid;
       
  1621 }
       
  1622 
       
  1623 EAP_FUNC_EXPORT bool crypto_aes_wrap_c::get_encrypts()
       
  1624 {
       
  1625 	return m_encrypt;
       
  1626 }
       
  1627 
       
  1628 EAP_FUNC_EXPORT u32_t crypto_aes_wrap_c::get_key_length()
       
  1629 {
       
  1630 	return m_aes.get_key_length();
       
  1631 }
       
  1632 
       
  1633 EAP_FUNC_EXPORT u32_t crypto_aes_wrap_c::get_block_size()
       
  1634 {
       
  1635 	return EAP_CRYPTO_AES_WRAP_BLOCK_SIZE;
       
  1636 }
       
  1637 
       
  1638 EAP_FUNC_EXPORT eap_status_e crypto_aes_wrap_c::set_encryption_key(
       
  1639 	const void * const key,
       
  1640 	const u32_t key_length)
       
  1641 {
       
  1642 	eap_status_e status = m_key.set_copy_of_buffer(key, key_length);
       
  1643 
       
  1644 	m_encrypt = true;
       
  1645 
       
  1646 	EAP_TRACE_DATA_DEBUG(
       
  1647 		m_am_tools,
       
  1648 		TRACE_FLAGS_EAP_AM_CRYPTO,
       
  1649 		(EAPL("AES-Wrap enc key"),
       
  1650 		 m_key.get_data(),
       
  1651 		 m_key.get_data_length()));
       
  1652 
       
  1653 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  1654 }
       
  1655 
       
  1656 EAP_FUNC_EXPORT eap_status_e crypto_aes_wrap_c::set_decryption_key(
       
  1657 	const void * const key,
       
  1658 	const u32_t key_length)
       
  1659 {
       
  1660 	eap_status_e status = m_key.set_copy_of_buffer(key, key_length);
       
  1661 
       
  1662 	m_encrypt = false;
       
  1663 
       
  1664 	EAP_TRACE_DATA_DEBUG(
       
  1665 		m_am_tools,
       
  1666 		TRACE_FLAGS_EAP_AM_CRYPTO,
       
  1667 		(EAPL("AES-Wrap dec key"),
       
  1668 		 m_key.get_data(),
       
  1669 		 m_key.get_data_length()));
       
  1670 
       
  1671 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  1672 }
       
  1673 
       
  1674 EAP_FUNC_EXPORT eap_status_e crypto_aes_wrap_c::add_padding_bytes(
       
  1675 	void * const buffer,
       
  1676 	const u32_t buffer_length)
       
  1677 {
       
  1678 	if (buffer == 0
       
  1679 		|| buffer_length == 0)
       
  1680 	{
       
  1681 		return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_parameter);
       
  1682 	}
       
  1683 
       
  1684 	u8_t * data = static_cast<u8_t *>(buffer);
       
  1685 	
       
  1686 	data[0] = 0xdd;
       
  1687 
       
  1688 	for (u32_t ind = 1ul; ind < buffer_length; ind++)
       
  1689 	{
       
  1690 		data[ind] = 0x00;
       
  1691 	}
       
  1692 
       
  1693 	return EAP_STATUS_RETURN(m_am_tools, eap_status_ok);
       
  1694 }
       
  1695 
       
  1696 EAP_FUNC_EXPORT eap_status_e crypto_aes_wrap_c::encrypt_block(
       
  1697 	const void * const data_in,
       
  1698 	const u32_t data_in_length,
       
  1699 	void * const data_out,
       
  1700 	const u32_t data_out_length)
       
  1701 {
       
  1702 #if !defined(DISABLE_CRYPTO_AES_WRAP)
       
  1703 	/*
       
  1704 	  Inputs:  Plaintext, n 64-bit values {P1, P2, ..., Pn}, and
       
  1705 	           Key, K (the KEK).
       
  1706 	  Outputs: Ciphertext, (n+1) 64-bit values {C0, C1, ..., Cn}.
       
  1707 	*/
       
  1708 	if (data_in == 0
       
  1709 		|| data_out == 0
       
  1710 		|| (data_in_length % get_block_size()) != 0
       
  1711 		|| data_out_length < data_in_length+get_block_size())
       
  1712 	{
       
  1713 		return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_parameter);
       
  1714 	}
       
  1715 
       
  1716 	EAP_TRACE_DATA_DEBUG(
       
  1717 		m_am_tools,
       
  1718 		TRACE_FLAGS_EAP_AM_CRYPTO,
       
  1719 		(EAPL("plain data"),
       
  1720 		 data_in,
       
  1721 		 data_in_length));
       
  1722 
       
  1723 	/*
       
  1724 	  1) Initialize variables.
       
  1725    
       
  1726 	  Set A = IV, an initial value (see 2.2.3)
       
  1727 	  For i = 1 to n
       
  1728 	      R[i] = P[i]
       
  1729 	*/
       
  1730 
       
  1731 	u64_t A_integrity_reg;
       
  1732 	EAP_ASSERT_TOOLS(m_am_tools, sizeof(A_integrity_reg) == sizeof(EAP_CRYPTO_AES_WRAP_DEFAULT_INITIAL_IV));
       
  1733 	m_am_tools->memmove(&A_integrity_reg, EAP_CRYPTO_AES_WRAP_DEFAULT_INITIAL_IV, sizeof(A_integrity_reg));
       
  1734 
       
  1735 	eap_variable_data_c Register(m_am_tools);
       
  1736 
       
  1737 	eap_status_e status = Register.set_copy_of_buffer(data_in, data_in_length);
       
  1738 	if (status != eap_status_ok)
       
  1739 	{
       
  1740 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  1741 	}
       
  1742 
       
  1743 	/*
       
  1744 	  2) Calculate intermediate values.
       
  1745 
       
  1746 	  For j = 0 to 5
       
  1747 	      For i=1 to n
       
  1748 		      B = AES(K, A | R[i])
       
  1749 			  A = MSB(64, B) ^ t where t = (n*j)+i
       
  1750 			  R[i] = LSB(64, B)
       
  1751 	*/
       
  1752 
       
  1753 	u64_t n_block_count = Register.get_data_length() / 8ul;
       
  1754 	u64_t B_tmp_buffer[2];
       
  1755 	eap_variable_data_c data(m_am_tools);
       
  1756 
       
  1757 	status = data.set_buffer_length(sizeof(A_integrity_reg) + EAP_CRYPTO_AES_WRAP_BLOCK_SIZE);
       
  1758 	if (status != eap_status_ok)
       
  1759 	{
       
  1760 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  1761 	}
       
  1762 
       
  1763 	for (u64_t j_ind = 0ul; j_ind <= 5ul; j_ind++)
       
  1764 	{
       
  1765 		for (u64_t i_ind = 1ul; i_ind <= n_block_count; i_ind++)
       
  1766 		{
       
  1767 			EAP_TRACE_DEBUG(
       
  1768 				m_am_tools,
       
  1769 				TRACE_FLAGS_EAP_AM_CRYPTO,
       
  1770 				(EAPL("\n")));
       
  1771 
       
  1772 			EAP_TRACE_DEBUG(
       
  1773 				m_am_tools,
       
  1774 				TRACE_FLAGS_EAP_AM_CRYPTO,
       
  1775 				(EAPL("crypto_aes_wrap_c::encrypt_block(): j_ind %d, i_ind %d\n"),
       
  1776 				 j_ind,
       
  1777 				 i_ind));
       
  1778 
       
  1779 			eap_status_e status = m_aes.set_encryption_key(
       
  1780 				m_key.get_data(),
       
  1781 				m_key.get_data_length());
       
  1782 			if (status != eap_status_ok)
       
  1783 			{
       
  1784 				return EAP_STATUS_RETURN(m_am_tools, status);
       
  1785 			}
       
  1786 
       
  1787 			EAP_TRACE_DATA_DEBUG(
       
  1788 				m_am_tools,
       
  1789 				TRACE_FLAGS_EAP_AM_CRYPTO,
       
  1790 				(EAPL("In A_integrity_reg"),
       
  1791 				 &A_integrity_reg,
       
  1792 				 sizeof(A_integrity_reg)));
       
  1793 
       
  1794 			status = data.set_copy_of_buffer(&A_integrity_reg, sizeof(A_integrity_reg));
       
  1795 			if (status != eap_status_ok)
       
  1796 			{
       
  1797 				return EAP_STATUS_RETURN(m_am_tools, status);
       
  1798 			}
       
  1799 
       
  1800 			u8_t * const Ri_reg = Register.get_data_offset(
       
  1801 				static_cast<u32_t>((i_ind-1ul))*static_cast<u32_t>(EAP_CRYPTO_AES_WRAP_BLOCK_SIZE),
       
  1802 				static_cast<u32_t>(EAP_CRYPTO_AES_WRAP_BLOCK_SIZE));
       
  1803 			if (Ri_reg == 0)
       
  1804 			{
       
  1805 				return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
  1806 			}
       
  1807 
       
  1808 			EAP_TRACE_DATA_DEBUG(
       
  1809 				m_am_tools,
       
  1810 				TRACE_FLAGS_EAP_AM_CRYPTO,
       
  1811 				(EAPL("         In Ri_reg"),
       
  1812 				 Ri_reg,
       
  1813 				 static_cast<u32_t>(EAP_CRYPTO_AES_WRAP_BLOCK_SIZE)));
       
  1814 
       
  1815 			status = data.add_data(Ri_reg, EAP_CRYPTO_AES_WRAP_BLOCK_SIZE);
       
  1816 			if (status != eap_status_ok)
       
  1817 			{
       
  1818 				return EAP_STATUS_RETURN(m_am_tools, status);
       
  1819 			}
       
  1820 
       
  1821 			EAP_ASSERT_TOOLS(m_am_tools, sizeof(B_tmp_buffer) == data.get_data_length());
       
  1822 
       
  1823 			status = m_aes.encrypt_block(
       
  1824 				data.get_data(),
       
  1825 				B_tmp_buffer,
       
  1826 				data.get_data_length());
       
  1827 			if (status != eap_status_ok)
       
  1828 			{
       
  1829 				return EAP_STATUS_RETURN(m_am_tools, status);
       
  1830 			}
       
  1831 
       
  1832 			EAP_TRACE_DATA_DEBUG(
       
  1833 				m_am_tools,
       
  1834 				TRACE_FLAGS_EAP_AM_CRYPTO,
       
  1835 				(EAPL("  Enc B_tmp_buffer"),
       
  1836 				 B_tmp_buffer,
       
  1837 				 sizeof(B_tmp_buffer)));
       
  1838 
       
  1839 			u64_t counter = m_am_tools->multiply_u64(n_block_count, j_ind) + i_ind;
       
  1840 
       
  1841 			A_integrity_reg = eap_htonll(
       
  1842 				m_am_tools->xor_u64(
       
  1843 					eap_ntohll(*B_tmp_buffer),
       
  1844 					counter));
       
  1845 
       
  1846 			m_am_tools->memmove(Ri_reg, B_tmp_buffer+1, sizeof(u64_t));
       
  1847 		}
       
  1848 	}
       
  1849 
       
  1850 	/*
       
  1851 	  3) Output the results.
       
  1852 
       
  1853 	  Set C[0] = A
       
  1854 	  For i = 1 to n
       
  1855 	      C[i] = R[i]
       
  1856 	*/
       
  1857 	
       
  1858 	u8_t * const C = static_cast<u8_t *>(data_out);
       
  1859 
       
  1860 	m_am_tools->memmove(C, &A_integrity_reg, EAP_CRYPTO_AES_WRAP_BLOCK_SIZE);
       
  1861 
       
  1862 	for (u32_t i_ind = 1ul; i_ind <= n_block_count; i_ind++)
       
  1863 	{
       
  1864 		u32_t offset = static_cast<u32_t>(i_ind)*static_cast<u32_t>(EAP_CRYPTO_AES_WRAP_BLOCK_SIZE);
       
  1865 
       
  1866 		u8_t * const Ri_reg = Register.get_data_offset(
       
  1867 			static_cast<u32_t>((i_ind-1ul))*static_cast<u32_t>(EAP_CRYPTO_AES_WRAP_BLOCK_SIZE),
       
  1868 			static_cast<u32_t>(EAP_CRYPTO_AES_WRAP_BLOCK_SIZE));
       
  1869 		if (Ri_reg == 0)
       
  1870 		{
       
  1871 			return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
  1872 		}
       
  1873 
       
  1874 		m_am_tools->memmove((C + offset), Ri_reg, EAP_CRYPTO_AES_WRAP_BLOCK_SIZE);
       
  1875 	}
       
  1876 
       
  1877 	EAP_TRACE_DATA_DEBUG(
       
  1878 		m_am_tools,
       
  1879 		TRACE_FLAGS_EAP_AM_CRYPTO,
       
  1880 		(EAPL("encrypted data"),
       
  1881 		 data_out,
       
  1882 		 data_out_length));
       
  1883 
       
  1884 	return EAP_STATUS_RETURN(m_am_tools, eap_status_ok);
       
  1885 
       
  1886 #else // !defined(DISABLE_CRYPTO_AES_WRAP)
       
  1887 	return EAP_STATUS_RETURN(m_am_tools, eap_status_not_supported);
       
  1888 #endif
       
  1889 
       
  1890 }
       
  1891 
       
  1892 EAP_FUNC_EXPORT eap_status_e crypto_aes_wrap_c::decrypt_block(
       
  1893 	const void * const data_in,
       
  1894 	const u32_t data_in_length,
       
  1895 	void * const data_out,
       
  1896 	const u32_t data_out_length)
       
  1897 {
       
  1898 #if !defined(DISABLE_CRYPTO_AES_WRAP)
       
  1899 	/*
       
  1900 	  Inputs:  Ciphertext, (n+1) 64-bit values {C0, C1, ..., Cn}, and
       
  1901 	           Key, K (the KEK).
       
  1902 	  Outputs: Plaintext, n 64-bit values {P0, P1, K, Pn}.
       
  1903 	*/
       
  1904 	if (data_in == 0
       
  1905 		|| data_out == 0
       
  1906 		|| (data_in_length % get_block_size()) != 0
       
  1907 		|| data_out_length < data_in_length-get_block_size())
       
  1908 	{
       
  1909 		return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_parameter);
       
  1910 	}
       
  1911 
       
  1912 	EAP_TRACE_DATA_DEBUG(
       
  1913 		m_am_tools,
       
  1914 		TRACE_FLAGS_EAP_AM_CRYPTO,
       
  1915 		(EAPL("encrypted data"),
       
  1916 		 data_in,
       
  1917 		 data_in_length));
       
  1918 
       
  1919 	/*
       
  1920 	  1) Initialize variables.
       
  1921 
       
  1922 	  Set A = C[0]
       
  1923 	  For i = 1 to n
       
  1924 	      R[i] = C[i]
       
  1925 	*/
       
  1926 	u64_t A_integrity_reg(0ul);
       
  1927 	const u8_t * const cipher_text = static_cast<const u8_t *>(data_in);
       
  1928 
       
  1929 	m_am_tools->memmove(&A_integrity_reg, cipher_text, EAP_CRYPTO_AES_WRAP_BLOCK_SIZE);
       
  1930 
       
  1931 	eap_variable_data_c Register(m_am_tools);
       
  1932 
       
  1933 	eap_status_e status = Register.set_copy_of_buffer(
       
  1934 		(cipher_text + static_cast<u32_t>(EAP_CRYPTO_AES_WRAP_BLOCK_SIZE)),
       
  1935 		data_in_length - static_cast<u32_t>(EAP_CRYPTO_AES_WRAP_BLOCK_SIZE));
       
  1936 	if (status != eap_status_ok)
       
  1937 	{
       
  1938 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  1939 	}
       
  1940 
       
  1941 	/*
       
  1942 	  2) Compute intermediate values.
       
  1943 
       
  1944 	  For j = 5 to 0
       
  1945 	      For i = n to 1
       
  1946 		      B = AES-1(K, (A ^ t) | R[i]) where t = n*j+i
       
  1947 			  A = MSB(64, B)
       
  1948 			  R[i] = LSB(64, B)
       
  1949 	*/
       
  1950 
       
  1951 	u64_t n_block_count = Register.get_data_length() / 8ul;
       
  1952 	u64_t B_tmp_buffer[2];
       
  1953 	eap_variable_data_c data(m_am_tools);
       
  1954 
       
  1955 	status = data.set_buffer_length(sizeof(A_integrity_reg) + EAP_CRYPTO_AES_WRAP_BLOCK_SIZE);
       
  1956 	if (status != eap_status_ok)
       
  1957 	{
       
  1958 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  1959 	}
       
  1960 
       
  1961 	u64_t j_ind(5ul);
       
  1962 
       
  1963 	for(;;)
       
  1964 	{
       
  1965 		for (u64_t i_ind = n_block_count; i_ind >= 1; i_ind--)
       
  1966 		{
       
  1967 			EAP_TRACE_DEBUG(
       
  1968 				m_am_tools,
       
  1969 				TRACE_FLAGS_EAP_AM_CRYPTO,
       
  1970 				(EAPL("\n")));
       
  1971 
       
  1972 			EAP_TRACE_DEBUG(
       
  1973 				m_am_tools,
       
  1974 				TRACE_FLAGS_EAP_AM_CRYPTO,
       
  1975 				(EAPL("crypto_aes_wrap_c::decrypt_block(): j_ind %d, i_ind %d\n"),
       
  1976 				 j_ind,
       
  1977 				 i_ind));
       
  1978 
       
  1979 			eap_status_e status = m_aes.set_decryption_key(
       
  1980 				m_key.get_data(),
       
  1981 				m_key.get_data_length());
       
  1982 			if (status != eap_status_ok)
       
  1983 			{
       
  1984 				return EAP_STATUS_RETURN(m_am_tools, status);
       
  1985 			}
       
  1986 
       
  1987 			u64_t counter = m_am_tools->multiply_u64(n_block_count, j_ind) + i_ind;
       
  1988 
       
  1989 			EAP_TRACE_DATA_DEBUG(
       
  1990 				m_am_tools,
       
  1991 				TRACE_FLAGS_EAP_AM_CRYPTO,
       
  1992 				(EAPL("In A_integrity_reg"),
       
  1993 				 &A_integrity_reg,
       
  1994 				 sizeof(A_integrity_reg)));
       
  1995 
       
  1996 			A_integrity_reg = eap_htonll(
       
  1997 				m_am_tools->xor_u64(
       
  1998 					eap_ntohll(A_integrity_reg),
       
  1999 					counter));
       
  2000 
       
  2001 			status = data.set_copy_of_buffer(&A_integrity_reg, sizeof(A_integrity_reg));
       
  2002 			if (status != eap_status_ok)
       
  2003 			{
       
  2004 				return EAP_STATUS_RETURN(m_am_tools, status);
       
  2005 			}
       
  2006 
       
  2007 			u8_t * const Ri_reg = Register.get_data_offset(
       
  2008 				static_cast<u32_t>((i_ind-1ul))*static_cast<u32_t>(EAP_CRYPTO_AES_WRAP_BLOCK_SIZE),
       
  2009 				static_cast<u32_t>(EAP_CRYPTO_AES_WRAP_BLOCK_SIZE));
       
  2010 			if (Ri_reg == 0)
       
  2011 			{
       
  2012 				return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
  2013 			}
       
  2014 
       
  2015 			EAP_TRACE_DATA_DEBUG(
       
  2016 				m_am_tools,
       
  2017 				TRACE_FLAGS_EAP_AM_CRYPTO,
       
  2018 				(EAPL("         In Ri_reg"),
       
  2019 				 Ri_reg,
       
  2020 				 EAP_CRYPTO_AES_WRAP_BLOCK_SIZE));
       
  2021 
       
  2022 			status = data.add_data(Ri_reg, EAP_CRYPTO_AES_WRAP_BLOCK_SIZE);
       
  2023 			if (status != eap_status_ok)
       
  2024 			{
       
  2025 				return EAP_STATUS_RETURN(m_am_tools, status);
       
  2026 			}
       
  2027 
       
  2028 			EAP_ASSERT_TOOLS(m_am_tools, sizeof(B_tmp_buffer) == data.get_data_length());
       
  2029 
       
  2030 			status = m_aes.decrypt_block(
       
  2031 				data.get_data(),
       
  2032 				B_tmp_buffer,
       
  2033 				data.get_data_length());
       
  2034 			if (status != eap_status_ok)
       
  2035 			{
       
  2036 				return EAP_STATUS_RETURN(m_am_tools, status);
       
  2037 			}
       
  2038 
       
  2039 			EAP_TRACE_DATA_DEBUG(
       
  2040 				m_am_tools,
       
  2041 				TRACE_FLAGS_EAP_AM_CRYPTO,
       
  2042 				(EAPL("  Dec B_tmp_buffer"),
       
  2043 				 B_tmp_buffer,
       
  2044 				 sizeof(B_tmp_buffer)));
       
  2045 
       
  2046 			A_integrity_reg = *B_tmp_buffer;
       
  2047 
       
  2048 			m_am_tools->memmove(Ri_reg, B_tmp_buffer+1, sizeof(u64_t));
       
  2049 		}
       
  2050 		
       
  2051 		if (j_ind == 0)
       
  2052 		{
       
  2053 			// Terminates the loop.
       
  2054 			break;
       
  2055 		}
       
  2056 
       
  2057 		// Decrementation must be after the termination test,
       
  2058 		// because we need to run the loop also with j_ind value 0.
       
  2059 		--j_ind;
       
  2060 	}
       
  2061 
       
  2062 	/*
       
  2063 	  3) Output results.
       
  2064 
       
  2065 	  If A is an appropriate initial value (see 2.2.3),
       
  2066 	  Then
       
  2067 	      For i = 1 to n
       
  2068 	          P[i] = R[i]
       
  2069 	  Else
       
  2070 	      Return an error
       
  2071 	*/
       
  2072 
       
  2073 	EAP_TRACE_DATA_DEBUG(
       
  2074 		m_am_tools,
       
  2075 		TRACE_FLAGS_EAP_AM_CRYPTO,
       
  2076 		(EAPL("plain data"),
       
  2077 		 Register.get_data(),
       
  2078 		 Register.get_data_length()));
       
  2079 
       
  2080 	if (m_am_tools->memcmp(&A_integrity_reg, EAP_CRYPTO_AES_WRAP_DEFAULT_INITIAL_IV, sizeof(A_integrity_reg)) == 0)
       
  2081 	{
       
  2082 		// OK
       
  2083 		m_am_tools->memmove(data_out, Register.get_data(), Register.get_data_length());
       
  2084 
       
  2085 		return EAP_STATUS_RETURN(m_am_tools, eap_status_ok);
       
  2086 	}
       
  2087 	else
       
  2088 	{
       
  2089 		return EAP_STATUS_RETURN(m_am_tools, eap_status_authentication_failure);
       
  2090 	}
       
  2091 
       
  2092 #else // !defined(DISABLE_CRYPTO_AES_WRAP)
       
  2093 
       
  2094 	return EAP_STATUS_RETURN(m_am_tools, eap_status_not_supported);
       
  2095 
       
  2096 #endif
       
  2097 
       
  2098 }
       
  2099 
       
  2100 //--------------------------------------------------
       
  2101 //--------------------------------------------------
       
  2102 //--------------------------------------------------
       
  2103 
       
  2104 EAP_FUNC_EXPORT crypto_random_c::~crypto_random_c()
       
  2105 {
       
  2106 }
       
  2107 
       
  2108 //--------------------------------------------------
       
  2109 
       
  2110 EAP_FUNC_EXPORT crypto_random_c::crypto_random_c(
       
  2111 	abs_eap_am_tools_c * const tools)
       
  2112 	: m_am_tools(tools)
       
  2113 	, m_is_valid(false)
       
  2114 {
       
  2115 	set_is_valid();
       
  2116 }
       
  2117 
       
  2118 //--------------------------------------------------
       
  2119 
       
  2120 EAP_FUNC_EXPORT void crypto_random_c::set_is_valid()
       
  2121 {
       
  2122 	m_is_valid = true;
       
  2123 }
       
  2124 
       
  2125 //--------------------------------------------------
       
  2126 
       
  2127 EAP_FUNC_EXPORT bool crypto_random_c::get_is_valid()
       
  2128 {
       
  2129 	return m_is_valid;
       
  2130 }
       
  2131 
       
  2132 //--------------------------------------------------
       
  2133 
       
  2134 EAP_FUNC_EXPORT eap_status_e crypto_random_c::get_rand_bytes(
       
  2135 	void * const buffer,
       
  2136 	const u32_t count)
       
  2137 {
       
  2138 	return m_am_tools->get_crypto()->get_rand_bytes(
       
  2139 		static_cast<u8_t *>(buffer), count);
       
  2140 }
       
  2141 
       
  2142 //--------------------------------------------------
       
  2143 
       
  2144 EAP_FUNC_EXPORT eap_status_e crypto_random_c::get_rand_bytes(
       
  2145 	eap_variable_data_c * const buffer,
       
  2146 	const u32_t count)
       
  2147 {
       
  2148 	if (buffer == 0
       
  2149 		|| buffer->get_is_valid() == false)
       
  2150 	{
       
  2151 		return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_parameter);
       
  2152 	}
       
  2153 
       
  2154 	eap_status_e status = buffer->init(count);
       
  2155 	if (status != eap_status_ok)
       
  2156 	{
       
  2157 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  2158 	}
       
  2159 
       
  2160 	status = buffer->set_data_length(count);
       
  2161 	if (status != eap_status_ok)
       
  2162 	{
       
  2163 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  2164 	}
       
  2165 
       
  2166 	status = get_rand_bytes(
       
  2167 		buffer->get_data(),
       
  2168 		buffer->get_data_length());
       
  2169 	if (status != eap_status_ok)
       
  2170 	{
       
  2171 		buffer->reset();
       
  2172 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  2173 	}
       
  2174 
       
  2175 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  2176 }
       
  2177 
       
  2178 //--------------------------------------------------
       
  2179 
       
  2180 EAP_FUNC_EXPORT u32_t crypto_random_c::get_rand_integer(
       
  2181 	const u32_t minimum,
       
  2182 	const u32_t maximum)
       
  2183 {
       
  2184 	const u32_t MAX_U32 = ~(static_cast<u32_t>(0ul));
       
  2185 
       
  2186 	u32_t random = 0ul;
       
  2187 
       
  2188 	if ((maximum - minimum) == MAX_U32 )
       
  2189 	{
       
  2190 		eap_status_e status = get_rand_bytes(&random, sizeof(random));
       
  2191 		if (status != eap_status_ok)
       
  2192 		{
       
  2193 			return 0;
       
  2194 		}
       
  2195 	}
       
  2196 	else
       
  2197 	{
       
  2198 		u32_t frame = ((maximum+1)-minimum);
       
  2199 		u32_t randomized = 0;
       
  2200 		u32_t max_value = MAX_U32 - (MAX_U32 % frame);
       
  2201 
       
  2202 		do
       
  2203 		{
       
  2204 			eap_status_e status = get_rand_bytes(&randomized, sizeof(randomized));
       
  2205 			if (status != eap_status_ok)
       
  2206 			{
       
  2207 				return 0;
       
  2208 			}
       
  2209 		}
       
  2210 		while(randomized >= max_value);
       
  2211 		
       
  2212 		random = ((randomized % frame) + minimum);
       
  2213 	}
       
  2214 
       
  2215 	EAP_TRACE_DEBUG(
       
  2216 		m_am_tools,
       
  2217 		TRACE_FLAGS_EAP_AM_CRYPTO,
       
  2218 		(EAPL("RANDOM u32_t %lu\n"),
       
  2219 		 random));
       
  2220 	
       
  2221 	return random;
       
  2222 }
       
  2223 
       
  2224 //--------------------------------------------------
       
  2225 
       
  2226 EAP_FUNC_EXPORT eap_status_e crypto_random_c::add_rand_seed(
       
  2227 	const void * const buffer,
       
  2228 	const u32_t count)
       
  2229 {
       
  2230 	return m_am_tools->get_crypto()->add_rand_seed(
       
  2231 		static_cast<const u8_t *>(buffer), count);
       
  2232 }
       
  2233 
       
  2234 //--------------------------------------------------
       
  2235 
       
  2236 EAP_FUNC_EXPORT eap_status_e crypto_random_c::add_rand_seed_hw_ticks()
       
  2237 {
       
  2238 	return m_am_tools->get_crypto()->add_rand_seed_hw_ticks();
       
  2239 }
       
  2240 
       
  2241 //--------------------------------------------------
       
  2242 //--------------------------------------------------
       
  2243 //--------------------------------------------------
       
  2244 
       
  2245 EAP_FUNC_EXPORT crypto_sha_256_c::~crypto_sha_256_c()
       
  2246 {
       
  2247 	hash_cleanup();
       
  2248 	m_sha_256_context.reset();
       
  2249 }
       
  2250 
       
  2251 //--------------------------------------------------
       
  2252 
       
  2253 EAP_FUNC_EXPORT crypto_sha_256_c::crypto_sha_256_c(abs_eap_am_tools_c * const tools)
       
  2254 	: m_am_tools(tools)
       
  2255 	, m_sha_256_context(tools)
       
  2256 	, m_is_valid(false)
       
  2257 {
       
  2258 	set_is_valid();
       
  2259 }
       
  2260 
       
  2261 //--------------------------------------------------
       
  2262 
       
  2263 EAP_FUNC_EXPORT eap_status_e crypto_sha_256_c::copy_context(
       
  2264 	const eap_variable_data_c * const sha_256_context)
       
  2265 {
       
  2266 	if (sha_256_context == 0
       
  2267 		|| sha_256_context->get_is_valid_data() == false)
       
  2268 	{
       
  2269 		set_is_invalid();
       
  2270 		return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_parameter);
       
  2271 	}
       
  2272 
       
  2273 	eap_status_e status = m_am_tools->get_crypto()->sha_256_copy_context(
       
  2274 		&m_sha_256_context,
       
  2275 		sha_256_context);
       
  2276 	if (status != eap_status_ok)
       
  2277 	{
       
  2278 		set_is_invalid();
       
  2279 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  2280 	}
       
  2281 
       
  2282 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  2283 }
       
  2284 
       
  2285 //--------------------------------------------------
       
  2286 
       
  2287 EAP_FUNC_EXPORT void crypto_sha_256_c::set_is_invalid()
       
  2288 {
       
  2289 	m_is_valid = false;
       
  2290 }
       
  2291 
       
  2292 //--------------------------------------------------
       
  2293 
       
  2294 EAP_FUNC_EXPORT void crypto_sha_256_c::set_is_valid()
       
  2295 {
       
  2296 	m_is_valid = true;
       
  2297 }
       
  2298 
       
  2299 //--------------------------------------------------
       
  2300 
       
  2301 EAP_FUNC_EXPORT bool crypto_sha_256_c::get_is_valid()
       
  2302 {
       
  2303 	return m_is_valid;
       
  2304 }
       
  2305 
       
  2306 //--------------------------------------------------
       
  2307 
       
  2308 EAP_FUNC_EXPORT u32_t crypto_sha_256_c::get_digest_length()
       
  2309 {
       
  2310 	// This is simple optimization.
       
  2311 	return EAP_CRYPTO_API_SHA_256_DIGEST_BUFFER_BYTE_SIZE;
       
  2312 }
       
  2313 
       
  2314 //--------------------------------------------------
       
  2315 
       
  2316 EAP_FUNC_EXPORT u32_t crypto_sha_256_c::get_block_size()
       
  2317 {
       
  2318 	// This is simple optimization.
       
  2319 	return EAP_CRYPTO_API_SHA_256_BLOCK_BYTE_SIZE;
       
  2320 }
       
  2321 
       
  2322 //--------------------------------------------------
       
  2323 
       
  2324 EAP_FUNC_EXPORT eap_status_e crypto_sha_256_c::hash_init()
       
  2325 {
       
  2326 	eap_status_e status = m_am_tools->get_crypto()->sha_256_init(&m_sha_256_context);
       
  2327 	if (m_sha_256_context.get_is_valid_data() == false)
       
  2328 	{
       
  2329 		set_is_invalid();
       
  2330 		if (status == eap_status_ok)
       
  2331 		{
       
  2332 			status = eap_status_allocation_error;
       
  2333 		}
       
  2334 	}
       
  2335 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  2336 }
       
  2337 
       
  2338 //--------------------------------------------------
       
  2339 
       
  2340 EAP_FUNC_EXPORT eap_status_e crypto_sha_256_c::hash_update(
       
  2341 	const void * const data,
       
  2342 	const u32_t data_length)
       
  2343 {
       
  2344 	eap_status_e status = m_am_tools->get_crypto()->sha_256_update(
       
  2345 		&m_sha_256_context,
       
  2346 		static_cast<const u8_t *>(data),
       
  2347 		data_length);
       
  2348 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  2349 }
       
  2350 
       
  2351 //--------------------------------------------------
       
  2352 
       
  2353 EAP_FUNC_EXPORT eap_status_e crypto_sha_256_c::hash_final(
       
  2354 	void * const message_digest,
       
  2355 	u32_t *md_length_or_null)
       
  2356 {
       
  2357 	eap_status_e status = m_am_tools->get_crypto()->sha_256_final(
       
  2358 		&m_sha_256_context,
       
  2359 		static_cast<u8_t *>(message_digest),
       
  2360 		md_length_or_null);
       
  2361 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  2362 }
       
  2363 
       
  2364 //--------------------------------------------------
       
  2365 
       
  2366 EAP_FUNC_EXPORT eap_status_e crypto_sha_256_c::hash_cleanup()
       
  2367 {
       
  2368 	if (m_sha_256_context.get_is_valid_data() == true)
       
  2369 	{
       
  2370 		m_am_tools->get_crypto()->sha_256_cleanup(&m_sha_256_context);
       
  2371 	}
       
  2372 	
       
  2373 	return EAP_STATUS_RETURN(m_am_tools, eap_status_ok);
       
  2374 }
       
  2375 
       
  2376 //--------------------------------------------------
       
  2377 
       
  2378 EAP_FUNC_EXPORT abs_crypto_hash_algorithm_c * crypto_sha_256_c::copy()
       
  2379 {
       
  2380 	crypto_sha_256_c * const new_context = new crypto_sha_256_c(m_am_tools);
       
  2381 	if (new_context == 0)
       
  2382 	{
       
  2383 		return 0;
       
  2384 	}
       
  2385 
       
  2386 	eap_status_e status = new_context->copy_context(&m_sha_256_context);
       
  2387 	if (status != eap_status_ok)
       
  2388 	{
       
  2389 		delete new_context;
       
  2390 		return 0;
       
  2391 	}
       
  2392 
       
  2393 	return new_context;
       
  2394 }
       
  2395 
       
  2396 //--------------------------------------------------
       
  2397 //--------------------------------------------------
       
  2398 //--------------------------------------------------
       
  2399 
       
  2400 EAP_FUNC_EXPORT crypto_sha1_c::~crypto_sha1_c()
       
  2401 {
       
  2402 	hash_cleanup();
       
  2403 	m_sha1_context.reset();
       
  2404 }
       
  2405 
       
  2406 //--------------------------------------------------
       
  2407 
       
  2408 EAP_FUNC_EXPORT crypto_sha1_c::crypto_sha1_c(abs_eap_am_tools_c * const tools)
       
  2409 	: m_am_tools(tools)
       
  2410 	, m_sha1_context(tools)
       
  2411 	, m_is_valid(false)
       
  2412 {
       
  2413 	set_is_valid();
       
  2414 }
       
  2415 
       
  2416 //--------------------------------------------------
       
  2417 
       
  2418 EAP_FUNC_EXPORT eap_status_e crypto_sha1_c::copy_context(
       
  2419 	const eap_variable_data_c * const sha1_context)
       
  2420 {
       
  2421 	if (sha1_context == 0
       
  2422 		|| sha1_context->get_is_valid_data() == false)
       
  2423 	{
       
  2424 		set_is_invalid();
       
  2425 		return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_parameter);
       
  2426 	}
       
  2427 
       
  2428 	eap_status_e status = m_am_tools->get_crypto()->sha1_copy_context(
       
  2429 		&m_sha1_context,
       
  2430 		sha1_context);
       
  2431 	if (status != eap_status_ok)
       
  2432 	{
       
  2433 		set_is_invalid();
       
  2434 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  2435 	}
       
  2436 
       
  2437 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  2438 }
       
  2439 
       
  2440 //--------------------------------------------------
       
  2441 
       
  2442 EAP_FUNC_EXPORT void crypto_sha1_c::set_is_invalid()
       
  2443 {
       
  2444 	m_is_valid = false;
       
  2445 }
       
  2446 
       
  2447 //--------------------------------------------------
       
  2448 
       
  2449 EAP_FUNC_EXPORT void crypto_sha1_c::set_is_valid()
       
  2450 {
       
  2451 	m_is_valid = true;
       
  2452 }
       
  2453 
       
  2454 //--------------------------------------------------
       
  2455 
       
  2456 EAP_FUNC_EXPORT bool crypto_sha1_c::get_is_valid()
       
  2457 {
       
  2458 	return m_is_valid;
       
  2459 }
       
  2460 
       
  2461 //--------------------------------------------------
       
  2462 
       
  2463 EAP_FUNC_EXPORT u32_t crypto_sha1_c::get_digest_length()
       
  2464 {
       
  2465 	// This is simple optimization.
       
  2466 	return EAP_CRYPTO_API_SHA1_DIGEST_BUFFER_BYTE_SIZE;
       
  2467 }
       
  2468 
       
  2469 //--------------------------------------------------
       
  2470 
       
  2471 EAP_FUNC_EXPORT u32_t crypto_sha1_c::get_block_size()
       
  2472 {
       
  2473 	// This is simple optimization.
       
  2474 	return EAP_CRYPTO_API_SHA1_BLOCK_BYTE_SIZE;
       
  2475 }
       
  2476 
       
  2477 //--------------------------------------------------
       
  2478 
       
  2479 EAP_FUNC_EXPORT eap_status_e crypto_sha1_c::hash_init()
       
  2480 {
       
  2481 	eap_status_e status = m_am_tools->get_crypto()->sha1_init(&m_sha1_context);
       
  2482 	if (m_sha1_context.get_is_valid_data() == false)
       
  2483 	{
       
  2484 		set_is_invalid();
       
  2485 		if (status == eap_status_ok)
       
  2486 		{
       
  2487 			status = eap_status_allocation_error;
       
  2488 		}
       
  2489 	}
       
  2490 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  2491 }
       
  2492 
       
  2493 //--------------------------------------------------
       
  2494 
       
  2495 EAP_FUNC_EXPORT eap_status_e crypto_sha1_c::hash_update(
       
  2496 	const void * const data,
       
  2497 	const u32_t data_length)
       
  2498 {
       
  2499 	eap_status_e status = m_am_tools->get_crypto()->sha1_update(
       
  2500 		&m_sha1_context,
       
  2501 		static_cast<const u8_t *>(data),
       
  2502 		data_length);
       
  2503 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  2504 }
       
  2505 
       
  2506 //--------------------------------------------------
       
  2507 
       
  2508 EAP_FUNC_EXPORT eap_status_e crypto_sha1_c::hash_final(
       
  2509 	void * const message_digest,
       
  2510 	u32_t *md_length_or_null)
       
  2511 {
       
  2512 	eap_status_e status = m_am_tools->get_crypto()->sha1_final(
       
  2513 		&m_sha1_context,
       
  2514 		static_cast<u8_t *>(message_digest),
       
  2515 		md_length_or_null);
       
  2516 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  2517 }
       
  2518 
       
  2519 //--------------------------------------------------
       
  2520 
       
  2521 EAP_FUNC_EXPORT eap_status_e crypto_sha1_c::hash_cleanup()
       
  2522 {
       
  2523 	if (m_sha1_context.get_is_valid_data() == true)
       
  2524 	{
       
  2525 		m_am_tools->get_crypto()->sha1_cleanup(&m_sha1_context);
       
  2526 	}
       
  2527 	
       
  2528 	return EAP_STATUS_RETURN(m_am_tools, eap_status_ok);
       
  2529 }
       
  2530 
       
  2531 //--------------------------------------------------
       
  2532 
       
  2533 EAP_FUNC_EXPORT abs_crypto_hash_algorithm_c * crypto_sha1_c::copy()
       
  2534 {
       
  2535 	crypto_sha1_c * const new_context = new crypto_sha1_c(m_am_tools);
       
  2536 	if (new_context == 0)
       
  2537 	{
       
  2538 		return 0;
       
  2539 	}
       
  2540 
       
  2541 	eap_status_e status = new_context->copy_context(&m_sha1_context);
       
  2542 	if (status != eap_status_ok)
       
  2543 	{
       
  2544 		delete new_context;
       
  2545 		return 0;
       
  2546 	}
       
  2547 
       
  2548 	return new_context;
       
  2549 }
       
  2550 
       
  2551 //--------------------------------------------------
       
  2552 //--------------------------------------------------
       
  2553 //--------------------------------------------------
       
  2554 
       
  2555 EAP_FUNC_EXPORT
       
  2556 crypto_ephemeral_diffie_hellman_c::~crypto_ephemeral_diffie_hellman_c()
       
  2557 {
       
  2558 }
       
  2559 
       
  2560 //--------------------------------------------------
       
  2561 
       
  2562 EAP_FUNC_EXPORT
       
  2563 crypto_ephemeral_diffie_hellman_c::crypto_ephemeral_diffie_hellman_c(
       
  2564 	abs_eap_am_tools_c * const tools)
       
  2565 	: m_am_tools(tools)
       
  2566 	, m_is_valid(false)
       
  2567 {
       
  2568 	set_is_valid();
       
  2569 }
       
  2570 
       
  2571 //--------------------------------------------------
       
  2572 
       
  2573 EAP_FUNC_EXPORT void crypto_ephemeral_diffie_hellman_c::set_is_valid()
       
  2574 {
       
  2575 	m_is_valid = true;
       
  2576 }
       
  2577 
       
  2578 //--------------------------------------------------
       
  2579 
       
  2580 EAP_FUNC_EXPORT bool crypto_ephemeral_diffie_hellman_c::get_is_valid()
       
  2581 {
       
  2582 	return m_is_valid;
       
  2583 }
       
  2584 
       
  2585 //--------------------------------------------------
       
  2586 
       
  2587 EAP_FUNC_EXPORT eap_status_e
       
  2588 crypto_ephemeral_diffie_hellman_c::generate_diffie_hellman_keys(
       
  2589 	eap_variable_data_c * const own_private_dh_key,
       
  2590 	eap_variable_data_c * const own_public_dh_key,
       
  2591 	const void * const prime,
       
  2592 	const u32_t prime_length,
       
  2593 	const void * const group_generator,
       
  2594 	const u32_t group_generator_length)
       
  2595 {
       
  2596 	return m_am_tools->get_crypto()->generate_diffie_hellman_keys(
       
  2597 		own_private_dh_key,
       
  2598 		own_public_dh_key,
       
  2599 		static_cast<const u8_t *>(prime),
       
  2600 		prime_length,
       
  2601 		static_cast<const u8_t *>(group_generator),
       
  2602 		group_generator_length);
       
  2603 }
       
  2604 
       
  2605 //--------------------------------------------------
       
  2606 
       
  2607 EAP_FUNC_EXPORT eap_status_e
       
  2608 crypto_ephemeral_diffie_hellman_c::generate_g_power_to_xy(
       
  2609 	const eap_variable_data_c * const own_private_dh_key,
       
  2610 	const eap_variable_data_c * const peer_public_dh_key,
       
  2611 	eap_variable_data_c * const shared_dh_key,
       
  2612 	const void * const prime,
       
  2613 	const u32_t prime_length,
       
  2614 	const void * const group_generator,
       
  2615 	const u32_t group_generator_length)
       
  2616 {
       
  2617 	return m_am_tools->get_crypto()->generate_g_power_to_xy(
       
  2618 		own_private_dh_key,
       
  2619 		peer_public_dh_key,
       
  2620 		shared_dh_key,
       
  2621 		static_cast<const u8_t *>(prime),
       
  2622 		prime_length,
       
  2623 		static_cast<const u8_t *>(group_generator),
       
  2624 		group_generator_length);
       
  2625 }
       
  2626 
       
  2627 //--------------------------------------------------
       
  2628 
       
  2629 EAP_FUNC_EXPORT eap_status_e
       
  2630 crypto_ephemeral_diffie_hellman_c::dh_cleanup(
       
  2631 	const eap_variable_data_c * const dh_context)
       
  2632 {
       
  2633 	return m_am_tools->get_crypto()->dh_cleanup(
       
  2634 		dh_context);
       
  2635 }
       
  2636 
       
  2637 //--------------------------------------------------
       
  2638 //--------------------------------------------------
       
  2639 //--------------------------------------------------
       
  2640 
       
  2641 EAP_FUNC_EXPORT crypto_md5_c::~crypto_md5_c()
       
  2642 {
       
  2643 	hash_cleanup();
       
  2644 	m_md5_context.reset();
       
  2645 }
       
  2646 
       
  2647 //--------------------------------------------------
       
  2648 
       
  2649 EAP_FUNC_EXPORT crypto_md5_c::crypto_md5_c(abs_eap_am_tools_c * const tools)
       
  2650 	: m_am_tools(tools)
       
  2651 	, m_md5_context(tools)
       
  2652 	, m_is_valid(false)
       
  2653 {
       
  2654 	set_is_valid();
       
  2655 }
       
  2656 
       
  2657 //--------------------------------------------------
       
  2658 
       
  2659 EAP_FUNC_EXPORT eap_status_e crypto_md5_c::copy_context(
       
  2660 	const eap_variable_data_c * const md5_context)
       
  2661 {
       
  2662 	if (md5_context == 0
       
  2663 		|| md5_context->get_is_valid_data() == false)
       
  2664 	{
       
  2665 		set_is_invalid();
       
  2666 		return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_parameter);
       
  2667 	}
       
  2668 
       
  2669 	eap_status_e status = m_am_tools->get_crypto()->md5_copy_context(
       
  2670 		&m_md5_context,
       
  2671 		md5_context);
       
  2672 	if (status != eap_status_ok)
       
  2673 	{
       
  2674 		set_is_invalid();
       
  2675 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  2676 	}
       
  2677 
       
  2678 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  2679 }
       
  2680 
       
  2681 //--------------------------------------------------
       
  2682 
       
  2683 EAP_FUNC_EXPORT void crypto_md5_c::set_is_invalid()
       
  2684 {
       
  2685 	m_is_valid = false;
       
  2686 }
       
  2687 
       
  2688 //--------------------------------------------------
       
  2689 
       
  2690 EAP_FUNC_EXPORT void crypto_md5_c::set_is_valid()
       
  2691 {
       
  2692 	m_is_valid = true;
       
  2693 }
       
  2694 
       
  2695 //--------------------------------------------------
       
  2696 
       
  2697 EAP_FUNC_EXPORT bool crypto_md5_c::get_is_valid()
       
  2698 {
       
  2699 	return m_is_valid;
       
  2700 }
       
  2701 
       
  2702 //--------------------------------------------------
       
  2703 
       
  2704 EAP_FUNC_EXPORT u32_t crypto_md5_c::get_digest_length()
       
  2705 {
       
  2706 	return m_am_tools->get_crypto()->get_md5_digest_length(&m_md5_context);
       
  2707 }
       
  2708 
       
  2709 //--------------------------------------------------
       
  2710 
       
  2711 EAP_FUNC_EXPORT u32_t crypto_md5_c::get_block_size()
       
  2712 {
       
  2713 	return m_am_tools->get_crypto()->get_md5_block_size(&m_md5_context);
       
  2714 }
       
  2715 
       
  2716 //--------------------------------------------------
       
  2717 
       
  2718 EAP_FUNC_EXPORT eap_status_e crypto_md5_c::hash_init()
       
  2719 {
       
  2720 	eap_status_e status = m_am_tools->get_crypto()->md5_init(&m_md5_context);
       
  2721 
       
  2722 	if (m_md5_context.get_is_valid_data() == false)
       
  2723 	{
       
  2724 		set_is_invalid();
       
  2725 		if (status == eap_status_ok)
       
  2726 		{
       
  2727 			status = eap_status_allocation_error;
       
  2728 		}
       
  2729 	}
       
  2730 
       
  2731 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  2732 }
       
  2733 
       
  2734 //--------------------------------------------------
       
  2735 
       
  2736 EAP_FUNC_EXPORT eap_status_e crypto_md5_c::hash_update(
       
  2737 	const void * const data,
       
  2738 	const u32_t data_length)
       
  2739 {
       
  2740 	eap_status_e status = m_am_tools->get_crypto()->md5_update(
       
  2741 		&m_md5_context,
       
  2742 		static_cast<const u8_t *>(data),
       
  2743 		data_length);
       
  2744 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  2745 }
       
  2746 
       
  2747 //--------------------------------------------------
       
  2748 
       
  2749 EAP_FUNC_EXPORT eap_status_e crypto_md5_c::hash_final(
       
  2750 	void * const message_digest,
       
  2751 	u32_t *md_length_or_null)
       
  2752 {
       
  2753 	eap_status_e status = m_am_tools->get_crypto()->md5_final(
       
  2754 		&m_md5_context,
       
  2755 		static_cast<u8_t *>(message_digest),
       
  2756 		md_length_or_null);
       
  2757 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  2758 }
       
  2759 
       
  2760 //--------------------------------------------------
       
  2761 
       
  2762 EAP_FUNC_EXPORT eap_status_e crypto_md5_c::hash_cleanup()
       
  2763 {
       
  2764 	if (m_md5_context.get_is_valid_data() == true)
       
  2765 	{
       
  2766 		m_am_tools->get_crypto()->md5_cleanup(&m_md5_context);
       
  2767 	}
       
  2768 	return EAP_STATUS_RETURN(m_am_tools, eap_status_ok);
       
  2769 }
       
  2770 
       
  2771 //--------------------------------------------------
       
  2772 
       
  2773 EAP_FUNC_EXPORT abs_crypto_hash_algorithm_c * crypto_md5_c::copy()
       
  2774 {
       
  2775 	crypto_md5_c * const new_context = new crypto_md5_c(m_am_tools);
       
  2776 	if (new_context == 0)
       
  2777 	{
       
  2778 		return 0;
       
  2779 	}
       
  2780 
       
  2781 	eap_status_e status = new_context->copy_context(&m_md5_context);
       
  2782 	if (status != eap_status_ok)
       
  2783 	{
       
  2784 		delete new_context;
       
  2785 		return 0;
       
  2786 	}
       
  2787 
       
  2788 	return new_context;
       
  2789 }
       
  2790 
       
  2791 //--------------------------------------------------
       
  2792 //--------------------------------------------------
       
  2793 //--------------------------------------------------
       
  2794 
       
  2795 EAP_FUNC_EXPORT crypto_md4_c::~crypto_md4_c()
       
  2796 {
       
  2797 	hash_cleanup();
       
  2798 	m_md4_context.reset();
       
  2799 }
       
  2800 
       
  2801 //--------------------------------------------------
       
  2802 
       
  2803 EAP_FUNC_EXPORT crypto_md4_c::crypto_md4_c(abs_eap_am_tools_c * const tools)
       
  2804 	: m_am_tools(tools)
       
  2805 	, m_md4_context(tools)
       
  2806 	, m_is_valid(false)
       
  2807 {
       
  2808 	set_is_valid();
       
  2809 }
       
  2810 
       
  2811 //--------------------------------------------------
       
  2812 
       
  2813 EAP_FUNC_EXPORT eap_status_e crypto_md4_c::copy_context(
       
  2814 	const eap_variable_data_c * const md4_context)
       
  2815 {
       
  2816 	if (md4_context == 0
       
  2817 		|| md4_context->get_is_valid_data() == false)
       
  2818 	{
       
  2819 		set_is_invalid();
       
  2820 		return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_parameter);
       
  2821 	}
       
  2822 
       
  2823 	eap_status_e status = m_am_tools->get_crypto()->md4_copy_context(
       
  2824 		&m_md4_context,
       
  2825 		md4_context);
       
  2826 	if (status != eap_status_ok)
       
  2827 	{
       
  2828 		set_is_invalid();
       
  2829 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  2830 	}
       
  2831 
       
  2832 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  2833 }
       
  2834 
       
  2835 //--------------------------------------------------
       
  2836 
       
  2837 EAP_FUNC_EXPORT void crypto_md4_c::set_is_invalid()
       
  2838 {
       
  2839 	m_is_valid = false;
       
  2840 }
       
  2841 
       
  2842 //--------------------------------------------------
       
  2843 
       
  2844 EAP_FUNC_EXPORT void crypto_md4_c::set_is_valid()
       
  2845 {
       
  2846 	m_is_valid = true;
       
  2847 }
       
  2848 
       
  2849 //--------------------------------------------------
       
  2850 
       
  2851 EAP_FUNC_EXPORT bool crypto_md4_c::get_is_valid()
       
  2852 {
       
  2853 	return m_is_valid;
       
  2854 }
       
  2855 
       
  2856 //--------------------------------------------------
       
  2857 
       
  2858 EAP_FUNC_EXPORT u32_t crypto_md4_c::get_digest_length()
       
  2859 {
       
  2860 	return m_am_tools->get_crypto()->get_md4_digest_length(&m_md4_context);
       
  2861 }
       
  2862 
       
  2863 //--------------------------------------------------
       
  2864 
       
  2865 EAP_FUNC_EXPORT u32_t crypto_md4_c::get_block_size()
       
  2866 {
       
  2867 	return m_am_tools->get_crypto()->get_md4_block_size(&m_md4_context);
       
  2868 }
       
  2869 
       
  2870 //--------------------------------------------------
       
  2871 
       
  2872 EAP_FUNC_EXPORT eap_status_e crypto_md4_c::hash_init()
       
  2873 {
       
  2874 	// Cleanup the previous context.
       
  2875 	hash_cleanup();
       
  2876 
       
  2877 	eap_status_e status = m_am_tools->get_crypto()->md4_init(&m_md4_context);
       
  2878 
       
  2879 	if (m_md4_context.get_is_valid_data() == false)
       
  2880 	{
       
  2881 		set_is_invalid();
       
  2882 		if (status == eap_status_ok)
       
  2883 		{
       
  2884 			status = eap_status_allocation_error;
       
  2885 		}
       
  2886 	}
       
  2887 
       
  2888 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  2889 }
       
  2890 
       
  2891 //--------------------------------------------------
       
  2892 
       
  2893 EAP_FUNC_EXPORT eap_status_e crypto_md4_c::hash_update(
       
  2894 	const void * const data,
       
  2895 	const u32_t data_length)
       
  2896 {
       
  2897 	eap_status_e status = m_am_tools->get_crypto()->md4_update(
       
  2898 		&m_md4_context,
       
  2899 		static_cast<const u8_t *>(data),
       
  2900 		data_length);
       
  2901 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  2902 }
       
  2903 
       
  2904 //--------------------------------------------------
       
  2905 
       
  2906 EAP_FUNC_EXPORT eap_status_e crypto_md4_c::hash_final(
       
  2907 	void * const message_digest,
       
  2908 	u32_t *md_length_or_null)
       
  2909 {
       
  2910 	eap_status_e status = m_am_tools->get_crypto()->md4_final(
       
  2911 		&m_md4_context,
       
  2912 		static_cast<u8_t *>(message_digest),
       
  2913 		md_length_or_null);
       
  2914 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  2915 }
       
  2916 
       
  2917 //--------------------------------------------------
       
  2918 
       
  2919 EAP_FUNC_EXPORT eap_status_e crypto_md4_c::hash_cleanup()
       
  2920 {
       
  2921 	if (m_md4_context.get_is_valid_data() == true)
       
  2922 	{
       
  2923 		m_am_tools->get_crypto()->md4_cleanup(&m_md4_context);
       
  2924 	}
       
  2925 	return EAP_STATUS_RETURN(m_am_tools, eap_status_ok);
       
  2926 }
       
  2927 
       
  2928 //--------------------------------------------------
       
  2929 
       
  2930 EAP_FUNC_EXPORT abs_crypto_hash_algorithm_c * crypto_md4_c::copy()
       
  2931 {
       
  2932 	crypto_md4_c * const new_context = new crypto_md4_c(m_am_tools);
       
  2933 	if (new_context == 0)
       
  2934 	{
       
  2935 		return 0;
       
  2936 	}
       
  2937 
       
  2938 	eap_status_e status = new_context->copy_context(&m_md4_context);
       
  2939 	if (status != eap_status_ok)
       
  2940 	{
       
  2941 		delete new_context;
       
  2942 		return 0;
       
  2943 	}
       
  2944 
       
  2945 	return new_context;
       
  2946 }
       
  2947 
       
  2948 //--------------------------------------------------
       
  2949 //--------------------------------------------------
       
  2950 //--------------------------------------------------
       
  2951 
       
  2952 EAP_FUNC_EXPORT crypto_rc4_c::~crypto_rc4_c()
       
  2953 {
       
  2954 	if (m_rc4_context.get_is_valid_data() == true)
       
  2955 	{
       
  2956 		m_am_tools->get_crypto()->rc4_cleanup(&m_rc4_context);
       
  2957 	}
       
  2958 }
       
  2959 
       
  2960 //--------------------------------------------------
       
  2961 
       
  2962 EAP_FUNC_EXPORT crypto_rc4_c::crypto_rc4_c(abs_eap_am_tools_c * const tools)
       
  2963 	: m_am_tools(tools)
       
  2964 	, m_rc4_context(tools)
       
  2965 	, m_is_valid(false)
       
  2966 {
       
  2967 	set_is_valid();
       
  2968 }
       
  2969 
       
  2970 //--------------------------------------------------
       
  2971 
       
  2972 EAP_FUNC_EXPORT void crypto_rc4_c::set_is_invalid()
       
  2973 {
       
  2974 	m_is_valid = false;
       
  2975 }
       
  2976 
       
  2977 //--------------------------------------------------
       
  2978 
       
  2979 EAP_FUNC_EXPORT void crypto_rc4_c::set_is_valid()
       
  2980 {
       
  2981 	m_is_valid = true;
       
  2982 }
       
  2983 
       
  2984 //--------------------------------------------------
       
  2985 
       
  2986 EAP_FUNC_EXPORT bool crypto_rc4_c::get_is_valid()
       
  2987 {
       
  2988 	return m_is_valid;
       
  2989 }
       
  2990 
       
  2991 //--------------------------------------------------
       
  2992 
       
  2993 EAP_FUNC_EXPORT eap_status_e crypto_rc4_c::set_key(
       
  2994 	const eap_variable_data_c * const key)
       
  2995 {
       
  2996 	return m_am_tools->get_crypto()->rc4_set_key(&m_rc4_context, key);
       
  2997 }
       
  2998 
       
  2999 //--------------------------------------------------
       
  3000 
       
  3001 EAP_FUNC_EXPORT eap_status_e crypto_rc4_c::discard_stream(
       
  3002 	const u32_t count_of_discarded_octets)
       
  3003 {
       
  3004 	eap_status_e status = eap_status_ok;
       
  3005 
       
  3006 	for (u32_t ind = 0ul; ind < count_of_discarded_octets; ind++)
       
  3007 	{
       
  3008 		u8_t octet = 0;
       
  3009 		status = encrypt_data(
       
  3010 			&octet,
       
  3011 			sizeof(octet));
       
  3012 		if (status != eap_status_ok)
       
  3013 		{
       
  3014 			return EAP_STATUS_RETURN(m_am_tools, status);
       
  3015 		}
       
  3016 	} // for()
       
  3017 
       
  3018 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  3019 }
       
  3020 
       
  3021 //--------------------------------------------------
       
  3022 
       
  3023 EAP_FUNC_EXPORT eap_status_e crypto_rc4_c::encrypt_data(
       
  3024 	void * const data_in_out,
       
  3025 	const u32_t data_length)
       
  3026 {
       
  3027 	return m_am_tools->get_crypto()->rc4_encrypt(
       
  3028 		&m_rc4_context,
       
  3029 		data_in_out,
       
  3030 		data_length);
       
  3031 }
       
  3032 
       
  3033 //--------------------------------------------------
       
  3034 
       
  3035 EAP_FUNC_EXPORT eap_status_e crypto_rc4_c::encrypt_data(
       
  3036 	const void * const data_in, 
       
  3037 	void * const data_out,
       
  3038 	const u32_t data_length)
       
  3039 {
       
  3040 	return m_am_tools->get_crypto()->rc4_encrypt(
       
  3041 		&m_rc4_context,
       
  3042 		data_in,
       
  3043 		data_out,
       
  3044 		data_length);
       
  3045 }
       
  3046 
       
  3047 //--------------------------------------------------
       
  3048 
       
  3049 EAP_FUNC_EXPORT eap_status_e crypto_rc4_c::decrypt_data(
       
  3050 	void * const data_in_out,
       
  3051 	const u32_t data_length)
       
  3052 {
       
  3053 	return m_am_tools->get_crypto()->rc4_decrypt(
       
  3054 		&m_rc4_context,
       
  3055 		data_in_out,
       
  3056 		data_length);
       
  3057 }
       
  3058 
       
  3059 //--------------------------------------------------
       
  3060 
       
  3061 EAP_FUNC_EXPORT eap_status_e crypto_rc4_c::decrypt_data(
       
  3062 	const void * const data_in, 
       
  3063 	void * const data_out,
       
  3064 	const u32_t data_length)
       
  3065 {
       
  3066 	return m_am_tools->get_crypto()->rc4_decrypt(
       
  3067 		&m_rc4_context,
       
  3068 		data_in,
       
  3069 		data_out,
       
  3070 		data_length);
       
  3071 }
       
  3072 
       
  3073 //--------------------------------------------------
       
  3074 //--------------------------------------------------
       
  3075 //--------------------------------------------------
       
  3076 
       
  3077 EAP_FUNC_EXPORT crypto_tls_base_prf_c::~crypto_tls_base_prf_c()
       
  3078 {
       
  3079 	tls_prf_cleanup();
       
  3080 }
       
  3081 
       
  3082 //--------------------------------------------------
       
  3083 
       
  3084 EAP_FUNC_EXPORT crypto_tls_base_prf_c::crypto_tls_base_prf_c(
       
  3085 	abs_eap_am_tools_c * const tools)
       
  3086 	: m_am_tools(tools)
       
  3087 	, m_is_valid(false)
       
  3088 {
       
  3089 	set_is_valid();
       
  3090 }
       
  3091 
       
  3092 //--------------------------------------------------
       
  3093 
       
  3094 EAP_FUNC_EXPORT void crypto_tls_base_prf_c::set_is_invalid()
       
  3095 {
       
  3096 	m_is_valid = false;
       
  3097 }
       
  3098 
       
  3099 //--------------------------------------------------
       
  3100 
       
  3101 EAP_FUNC_EXPORT void crypto_tls_base_prf_c::set_is_valid()
       
  3102 {
       
  3103 	m_is_valid = true;
       
  3104 }
       
  3105 
       
  3106 //--------------------------------------------------
       
  3107 
       
  3108 EAP_FUNC_EXPORT bool crypto_tls_base_prf_c::get_is_valid()
       
  3109 {
       
  3110 	return 	m_is_valid;
       
  3111 }
       
  3112 
       
  3113 //--------------------------------------------------
       
  3114 
       
  3115 EAP_FUNC_EXPORT eap_status_e crypto_tls_base_prf_c::tls_prf_A_value(
       
  3116 	abs_crypto_hmac_algorithm_c * const hash,
       
  3117 	eap_variable_data_c * const key,
       
  3118 	eap_variable_data_c * const seed,
       
  3119 	eap_variable_data_c * const A_output)
       
  3120 {
       
  3121 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3122 
       
  3123 	if (hash == 0
       
  3124 		|| key == 0
       
  3125 		|| seed == 0
       
  3126 		|| A_output == 0)
       
  3127 	{
       
  3128 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3129 		return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_parameter);
       
  3130 	}
       
  3131 
       
  3132 	// First we initialize A value.
       
  3133 
       
  3134 	eap_status_e status = hash->hmac_set_key(key);
       
  3135 	if (status != eap_status_ok)
       
  3136 	{
       
  3137 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3138 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  3139 	}
       
  3140 
       
  3141 	status = hash->hmac_update(
       
  3142 		seed->get_data(seed->get_data_length()),
       
  3143 		seed->get_data_length());
       
  3144 	if (status != eap_status_ok)
       
  3145 	{
       
  3146 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3147 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  3148 	}
       
  3149 
       
  3150 	u32_t hmac_md_length = hash->get_digest_length();
       
  3151 
       
  3152 	status = hash->hmac_final(
       
  3153 		A_output->get_data(hmac_md_length),
       
  3154 		&hmac_md_length);
       
  3155 	if (status != eap_status_ok)
       
  3156 	{
       
  3157 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3158 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  3159 	}
       
  3160 
       
  3161 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3162 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  3163 }
       
  3164 
       
  3165 //--------------------------------------------------
       
  3166 
       
  3167 EAP_FUNC_EXPORT eap_status_e crypto_tls_base_prf_c::tls_prf_one_round(
       
  3168 	abs_crypto_hmac_algorithm_c * const hash,
       
  3169 	const eap_variable_data_c * const key,
       
  3170 	eap_variable_data_c * const A_input,
       
  3171 	eap_variable_data_c * const seed,
       
  3172 	void * const out_buffer,
       
  3173 	const u32_t out_buffer_length)
       
  3174 {
       
  3175 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3176 
       
  3177 	if (hash == 0
       
  3178 		|| key == 0
       
  3179 		|| A_input == 0
       
  3180 		|| seed == 0
       
  3181 		|| out_buffer == 0)
       
  3182 	{
       
  3183 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3184 		return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_parameter);
       
  3185 	}
       
  3186 
       
  3187 	eap_status_e status = hash->hmac_set_key(key);
       
  3188 	if (status != eap_status_ok)
       
  3189 	{
       
  3190 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3191 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  3192 	}
       
  3193 	
       
  3194 	status = hash->hmac_update(
       
  3195 		A_input->get_data(A_input->get_data_length()),
       
  3196 		A_input->get_data_length());
       
  3197 	if (status != eap_status_ok)
       
  3198 	{
       
  3199 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3200 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  3201 	}
       
  3202 	
       
  3203 	status = hash->hmac_update(
       
  3204 		seed->get_data(seed->get_data_length()),
       
  3205 		seed->get_data_length());
       
  3206 	if (status != eap_status_ok)
       
  3207 	{
       
  3208 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3209 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  3210 	}
       
  3211 	
       
  3212 	u32_t hmac_md_length = hash->get_digest_length();
       
  3213 
       
  3214 	if (hmac_md_length > out_buffer_length)
       
  3215 	{
       
  3216 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3217 		return EAP_STATUS_RETURN(m_am_tools, eap_status_buffer_too_short);
       
  3218 	}
       
  3219 
       
  3220 	status = hash->hmac_final(
       
  3221 		out_buffer,
       
  3222 		&hmac_md_length);
       
  3223 	if (status != eap_status_ok)
       
  3224 	{
       
  3225 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3226 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  3227 	}
       
  3228 
       
  3229 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3230 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  3231 }
       
  3232 
       
  3233 //--------------------------------------------------
       
  3234 
       
  3235 EAP_FUNC_EXPORT eap_status_e crypto_tls_base_prf_c::tls_prf_cleanup()
       
  3236 {
       
  3237 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3238 
       
  3239 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3240 	return EAP_STATUS_RETURN(m_am_tools, eap_status_ok);
       
  3241 }
       
  3242 
       
  3243 //--------------------------------------------------
       
  3244 //--------------------------------------------------
       
  3245 //--------------------------------------------------
       
  3246 
       
  3247 EAP_FUNC_EXPORT crypto_tls_sha1_prf_c::~crypto_tls_sha1_prf_c()
       
  3248 {
       
  3249 	tls_prf_cleanup();
       
  3250 
       
  3251 	delete m_sha1_context;
       
  3252 	m_sha1_context = 0;
       
  3253 
       
  3254 	delete m_A_sha1_context;
       
  3255 	m_A_sha1_context = 0;
       
  3256 }
       
  3257 
       
  3258 //--------------------------------------------------
       
  3259 
       
  3260 EAP_FUNC_EXPORT crypto_tls_sha1_prf_c::crypto_tls_sha1_prf_c(
       
  3261 	abs_eap_am_tools_c * const tools)
       
  3262 	: crypto_tls_base_prf_c(tools)
       
  3263 	, m_am_tools(tools)
       
  3264 	, m_sha1_context(0)
       
  3265 	, m_A_sha1_context(0)
       
  3266 	, m_sha1_key(tools)
       
  3267 	, m_seed(tools)
       
  3268 	, m_is_valid(false)
       
  3269 {
       
  3270 	{
       
  3271 		crypto_sha1_c * sha1 = new crypto_sha1_c(m_am_tools);
       
  3272 		if (sha1 == 0
       
  3273 			|| sha1->get_is_valid() == false)
       
  3274 		{
       
  3275 			delete sha1;
       
  3276 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3277 			return;
       
  3278 		}
       
  3279 
       
  3280 		m_sha1_context = new crypto_hmac_c(m_am_tools, sha1, true);
       
  3281 		if (m_sha1_context == 0
       
  3282 			|| m_sha1_context->get_is_valid() == false)
       
  3283 		{
       
  3284 			delete m_sha1_context;
       
  3285 			m_sha1_context = 0;
       
  3286 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3287 			return;
       
  3288 		}
       
  3289 	}
       
  3290 
       
  3291 	{
       
  3292 		crypto_sha1_c * sha1 = new crypto_sha1_c(m_am_tools);
       
  3293 		if (sha1 == 0
       
  3294 			|| sha1->get_is_valid() == false)
       
  3295 		{
       
  3296 			delete sha1;
       
  3297 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3298 			return;
       
  3299 		}
       
  3300 
       
  3301 		m_A_sha1_context = new crypto_hmac_c(m_am_tools, sha1, true);
       
  3302 		if (m_A_sha1_context == 0
       
  3303 			|| m_A_sha1_context->get_is_valid() == false)
       
  3304 		{
       
  3305 			delete m_A_sha1_context;
       
  3306 			m_A_sha1_context = 0;
       
  3307 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3308 			return;
       
  3309 		}
       
  3310 	}
       
  3311 
       
  3312 	set_is_valid();
       
  3313 }
       
  3314 
       
  3315 //--------------------------------------------------
       
  3316 
       
  3317 EAP_FUNC_EXPORT void crypto_tls_sha1_prf_c::set_is_invalid()
       
  3318 {
       
  3319 	m_is_valid = false;
       
  3320 }
       
  3321 
       
  3322 //--------------------------------------------------
       
  3323 
       
  3324 EAP_FUNC_EXPORT void crypto_tls_sha1_prf_c::set_is_valid()
       
  3325 {
       
  3326 	m_is_valid = true;
       
  3327 }
       
  3328 
       
  3329 //--------------------------------------------------
       
  3330 
       
  3331 EAP_FUNC_EXPORT bool crypto_tls_sha1_prf_c::get_is_valid()
       
  3332 {
       
  3333 	return 	m_is_valid;
       
  3334 }
       
  3335 
       
  3336 //--------------------------------------------------
       
  3337 
       
  3338 EAP_FUNC_EXPORT eap_status_e crypto_tls_sha1_prf_c::tls_prf_init(
       
  3339 	const eap_variable_data_c * const secret,
       
  3340 	const eap_variable_data_c * const label,
       
  3341 	const eap_variable_data_c * const seed)
       
  3342 {
       
  3343 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3344 
       
  3345 	if (secret->get_is_valid_data() == false
       
  3346 		|| secret->get_data_length() == 0ul)
       
  3347 	{
       
  3348 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3349 		return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_parameter);
       
  3350 	}
       
  3351 
       
  3352 	if (label->get_is_valid_data() == false
       
  3353 		|| label->get_data_length() == 0ul)
       
  3354 	{
       
  3355 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3356 		return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_parameter);
       
  3357 	}
       
  3358 
       
  3359 	// NOTE seed could be empty buffer.
       
  3360 	if (seed->get_is_valid() == false)
       
  3361 	{
       
  3362 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3363 		return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_parameter);
       
  3364 	}
       
  3365 
       
  3366 	// - - - - - - - - - - - - - - - - - - - - - - - - - - - -
       
  3367 
       
  3368 	eap_variable_data_c input(m_am_tools);
       
  3369 
       
  3370 	eap_status_e status = input.add_data(label);
       
  3371 	if (status != eap_status_ok)
       
  3372 	{
       
  3373 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3374 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  3375 	}
       
  3376 
       
  3377 	status = input.add_data(seed);
       
  3378 	if (status != eap_status_ok)
       
  3379 	{
       
  3380 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3381 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  3382 	}
       
  3383 
       
  3384 	status = m_seed.set_copy_of_buffer(&input);
       
  3385 	if (status != eap_status_ok)
       
  3386 	{
       
  3387 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3388 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  3389 	}
       
  3390 
       
  3391 	EAP_TRACE_DATA_DEBUG(
       
  3392 		m_am_tools,
       
  3393 		TRACE_FLAGS_EAP_AM_CRYPTO,
       
  3394 		(EAPL("tls_prf_init(): m_seed"),
       
  3395 		m_seed.get_data(m_seed.get_data_length()),
       
  3396 		m_seed.get_data_length()));
       
  3397 
       
  3398 	// - - - - - - - - - - - - - - - - - - - - - - - - - - - -
       
  3399 
       
  3400 	status = m_sha1_key.set_copy_of_buffer(
       
  3401 		secret);
       
  3402 	if (status != eap_status_ok)
       
  3403 	{
       
  3404 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3405 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  3406 	}
       
  3407 
       
  3408 	EAP_TRACE_DATA_DEBUG(
       
  3409 		m_am_tools,
       
  3410 		TRACE_FLAGS_EAP_AM_CRYPTO,
       
  3411 		(EAPL("tls_prf_init(): m_sha1_key"),
       
  3412 		m_sha1_key.get_data(m_sha1_key.get_data_length()),
       
  3413 		m_sha1_key.get_data_length()));
       
  3414 
       
  3415 	// - - - - - - - - - - - - - - - - - - - - - - - - - - - -
       
  3416 
       
  3417 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3418 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  3419 }
       
  3420 
       
  3421 //--------------------------------------------------
       
  3422 
       
  3423 EAP_FUNC_EXPORT eap_status_e crypto_tls_sha1_prf_c::tls_prf_output(
       
  3424 	void * const pseudo_random_data,
       
  3425 	const u32_t pseudo_random_data_length)
       
  3426 {
       
  3427 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3428 
       
  3429 	if (pseudo_random_data == 0)
       
  3430 	{
       
  3431 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3432 		return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_parameter);
       
  3433 	}
       
  3434 
       
  3435 	eap_status_e status = eap_status_not_supported;
       
  3436 
       
  3437 	EAP_ASSERT_ALWAYS(get_is_valid() == true);
       
  3438 
       
  3439 	// - - - - - - - - - - - - - - - - - - - - - - - - - - - -
       
  3440 
       
  3441 	status = m_A_sha1_context->hmac_set_key(&m_sha1_key);
       
  3442 	if (status != eap_status_ok)
       
  3443 	{
       
  3444 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3445 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  3446 	}
       
  3447 	
       
  3448 	status = m_sha1_context->hmac_set_key(&m_sha1_key);
       
  3449 	if (status != eap_status_ok)
       
  3450 	{
       
  3451 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3452 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  3453 	}
       
  3454 	
       
  3455 	// - - - - - - - - - - - - - - - - - - - - - - - - - - - -
       
  3456 
       
  3457 	eap_variable_data_c A_sha1_output(m_am_tools);
       
  3458 
       
  3459 	status = A_sha1_output.init(m_A_sha1_context->get_digest_length());
       
  3460 	if (status != eap_status_ok)
       
  3461 	{
       
  3462 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3463 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  3464 	}
       
  3465 	A_sha1_output.set_is_valid();
       
  3466 	A_sha1_output.set_data_length(A_sha1_output.get_buffer_length());
       
  3467 
       
  3468 	// - - - - - - - - - - - - - - - - - - - - - - - - - - - -
       
  3469 
       
  3470 	eap_variable_data_c sha1_output(m_am_tools);
       
  3471 
       
  3472 	status = sha1_output.init(
       
  3473 		pseudo_random_data_length+m_sha1_context->get_digest_length());
       
  3474 	if (status != eap_status_ok)
       
  3475 	{
       
  3476 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3477 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  3478 	}
       
  3479 	sha1_output.set_is_valid();
       
  3480 	sha1_output.set_data_length(sha1_output.get_buffer_length());
       
  3481 
       
  3482 	// - - - - - - - - - - - - - - - - - - - - - - - - - - - -
       
  3483 	// - - - - - - - - - - - - - - - - - - - - - - - - - - - -
       
  3484 	// - - - - - - - - - - - - - - - - - - - - - - - - - - - -
       
  3485 
       
  3486 	{
       
  3487 		u32_t hmac_sha1_md_length = m_sha1_context->get_digest_length();
       
  3488 		u32_t sha1_count = sha1_output.get_data_length()
       
  3489 			/ m_sha1_context->get_digest_length();
       
  3490 
       
  3491 		// First we initialize A value:
       
  3492 		// A(0) = seed
       
  3493 		status = tls_prf_A_value(
       
  3494 			m_A_sha1_context,
       
  3495 			&m_sha1_key,
       
  3496 			&m_seed,
       
  3497 			&A_sha1_output);
       
  3498 		if (status != eap_status_ok)
       
  3499 		{
       
  3500 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3501 			return EAP_STATUS_RETURN(m_am_tools, status);
       
  3502 		}
       
  3503 
       
  3504 		// out(1) = HMAC_hash(secret, A(1) + seed)
       
  3505 		status = tls_prf_one_round(
       
  3506 			m_sha1_context,
       
  3507 			&m_sha1_key,
       
  3508 			&A_sha1_output,
       
  3509 			&m_seed,
       
  3510 			sha1_output.get_data_offset(0ul, hmac_sha1_md_length),
       
  3511 			hmac_sha1_md_length);
       
  3512 		if (status != eap_status_ok)
       
  3513 		{
       
  3514 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3515 			return EAP_STATUS_RETURN(m_am_tools, status);
       
  3516 		}
       
  3517 
       
  3518 		for (u32_t ind = 1ul; ind < sha1_count; ind++)
       
  3519 		{
       
  3520 			// Next A value is:
       
  3521 			// A(i) = HMAC_hash(secret, A(i-1)).
       
  3522 			status = tls_prf_A_value(
       
  3523 				m_A_sha1_context,
       
  3524 				&m_sha1_key,
       
  3525 				&A_sha1_output,
       
  3526 				&A_sha1_output);
       
  3527 			if (status != eap_status_ok)
       
  3528 			{
       
  3529 				EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3530 				return EAP_STATUS_RETURN(m_am_tools, status);
       
  3531 			}
       
  3532 
       
  3533 			// out(i) = HMAC_hash(secret, A(i) + seed)
       
  3534 			status = tls_prf_one_round(
       
  3535 				m_sha1_context,
       
  3536 				&m_sha1_key,
       
  3537 				&A_sha1_output,
       
  3538 				&m_seed,
       
  3539 				sha1_output.get_data_offset(
       
  3540 					ind*hmac_sha1_md_length,
       
  3541 					hmac_sha1_md_length),
       
  3542 				hmac_sha1_md_length);
       
  3543 			if (status != eap_status_ok)
       
  3544 			{
       
  3545 				EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3546 				return EAP_STATUS_RETURN(m_am_tools, status);
       
  3547 			}
       
  3548 		} // for()
       
  3549 	}
       
  3550 
       
  3551 	// - - - - - - - - - - - - - - - - - - - - - - - - - - - -
       
  3552 	// - - - - - - - - - - - - - - - - - - - - - - - - - - - -
       
  3553 	// - - - - - - - - - - - - - - - - - - - - - - - - - - - -
       
  3554 
       
  3555 	// Final operation is copy sha1_output to output buffer.
       
  3556 
       
  3557 	{
       
  3558 		EAP_TRACE_DATA_DEBUG(
       
  3559 			m_am_tools,
       
  3560 			TRACE_FLAGS_EAP_AM_CRYPTO,
       
  3561 			(EAPL("crypto_tls_sha1_prf_c::tls_prf_output(): sha1_output"),
       
  3562 			 sha1_output.get_data(pseudo_random_data_length),
       
  3563 			 pseudo_random_data_length));
       
  3564 
       
  3565 		EAP_ASSERT(pseudo_random_data_length <= sha1_output.get_data_length());
       
  3566 
       
  3567 		const u8_t * const sha1_buffer = sha1_output.get_data(
       
  3568 			pseudo_random_data_length);
       
  3569 		if (sha1_buffer == 0)
       
  3570 		{
       
  3571 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3572 			return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
  3573 		}
       
  3574 
       
  3575 		u8_t * const p_pseudo_random_data
       
  3576 			= static_cast<u8_t *>(pseudo_random_data);
       
  3577 
       
  3578 		m_am_tools->memmove(
       
  3579 			p_pseudo_random_data,
       
  3580 			sha1_buffer,
       
  3581 			pseudo_random_data_length);
       
  3582 
       
  3583 		EAP_TRACE_DATA_DEBUG(
       
  3584 			m_am_tools,
       
  3585 			TRACE_FLAGS_EAP_AM_CRYPTO,
       
  3586 			(EAPL("crypto_tls_sha1_prf_c::tls_prf_output(): ")
       
  3587 			 EAPL("p_pseudo_random_data"),
       
  3588 			 p_pseudo_random_data,
       
  3589 			 pseudo_random_data_length));
       
  3590 	}
       
  3591 
       
  3592 	// - - - - - - - - - - - - - - - - - - - - - - - - - - - -
       
  3593 
       
  3594 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3595 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  3596 }
       
  3597 
       
  3598 //--------------------------------------------------
       
  3599 
       
  3600 EAP_FUNC_EXPORT eap_status_e crypto_tls_sha1_prf_c::tls_prf_cleanup()
       
  3601 {
       
  3602 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3603 
       
  3604 	if (m_sha1_context != 0)
       
  3605 	{
       
  3606 		m_sha1_context->hmac_cleanup();
       
  3607 	}
       
  3608 
       
  3609 	if (m_A_sha1_context != 0)
       
  3610 	{
       
  3611 		m_A_sha1_context->hmac_cleanup();
       
  3612 	}
       
  3613 
       
  3614 	m_sha1_key.reset();
       
  3615 	m_seed.reset();
       
  3616 
       
  3617 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3618 	return EAP_STATUS_RETURN(m_am_tools, eap_status_ok);
       
  3619 }
       
  3620 
       
  3621 //--------------------------------------------------
       
  3622 //--------------------------------------------------
       
  3623 //--------------------------------------------------
       
  3624 
       
  3625 EAP_FUNC_EXPORT crypto_tls_md5_prf_c::~crypto_tls_md5_prf_c()
       
  3626 {
       
  3627 	tls_prf_cleanup();
       
  3628 
       
  3629 	delete m_md5_context;
       
  3630 	m_md5_context = 0;
       
  3631 
       
  3632 	delete m_A_md5_context;
       
  3633 	m_A_md5_context = 0;
       
  3634 }
       
  3635 
       
  3636 //--------------------------------------------------
       
  3637 
       
  3638 EAP_FUNC_EXPORT crypto_tls_md5_prf_c::crypto_tls_md5_prf_c(
       
  3639 	abs_eap_am_tools_c * const tools)
       
  3640 	: crypto_tls_base_prf_c(tools)
       
  3641 	, m_am_tools(tools)
       
  3642 	, m_md5_context(0)
       
  3643 	, m_A_md5_context(0)
       
  3644 	, m_md5_key(tools)
       
  3645 	, m_seed(tools)
       
  3646 	, m_is_valid(false)
       
  3647 {
       
  3648 	{
       
  3649 		crypto_md5_c * md5 = new crypto_md5_c(m_am_tools);
       
  3650 		if (md5 == 0
       
  3651 			|| md5->get_is_valid() == false)
       
  3652 		{
       
  3653 			delete md5;
       
  3654 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3655 			return;
       
  3656 		}
       
  3657 
       
  3658 		m_md5_context = new crypto_hmac_c(m_am_tools, md5, true);
       
  3659 		if (m_md5_context == 0
       
  3660 			|| m_md5_context->get_is_valid() == false)
       
  3661 		{
       
  3662 			delete m_md5_context;
       
  3663 			m_md5_context = 0;
       
  3664 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3665 			return;
       
  3666 		}
       
  3667 	}
       
  3668 
       
  3669 	{
       
  3670 		crypto_md5_c * md5 = new crypto_md5_c(m_am_tools);
       
  3671 		if (md5 == 0
       
  3672 			|| md5->get_is_valid() == false)
       
  3673 		{
       
  3674 			delete md5;
       
  3675 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3676 			return;
       
  3677 		}
       
  3678 
       
  3679 		m_A_md5_context = new crypto_hmac_c(m_am_tools, md5, true);
       
  3680 		if (m_A_md5_context == 0
       
  3681 			|| m_A_md5_context->get_is_valid() == false)
       
  3682 		{
       
  3683 			delete m_A_md5_context;
       
  3684 			m_A_md5_context = 0;
       
  3685 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3686 			return;
       
  3687 		}
       
  3688 	}
       
  3689 
       
  3690 	set_is_valid();
       
  3691 }
       
  3692 
       
  3693 //--------------------------------------------------
       
  3694 
       
  3695 EAP_FUNC_EXPORT void crypto_tls_md5_prf_c::set_is_invalid()
       
  3696 {
       
  3697 	m_is_valid = false;
       
  3698 }
       
  3699 
       
  3700 //--------------------------------------------------
       
  3701 
       
  3702 EAP_FUNC_EXPORT void crypto_tls_md5_prf_c::set_is_valid()
       
  3703 {
       
  3704 	m_is_valid = true;
       
  3705 }
       
  3706 
       
  3707 //--------------------------------------------------
       
  3708 
       
  3709 EAP_FUNC_EXPORT bool crypto_tls_md5_prf_c::get_is_valid()
       
  3710 {
       
  3711 	return 	m_is_valid;
       
  3712 }
       
  3713 
       
  3714 //--------------------------------------------------
       
  3715 
       
  3716 EAP_FUNC_EXPORT eap_status_e crypto_tls_md5_prf_c::tls_prf_init(
       
  3717 	const eap_variable_data_c * const secret,
       
  3718 	const eap_variable_data_c * const label,
       
  3719 	const eap_variable_data_c * const seed)
       
  3720 {
       
  3721 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3722 
       
  3723 	if (secret->get_is_valid_data() == false
       
  3724 		|| secret->get_data_length() == 0ul)
       
  3725 	{
       
  3726 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3727 		return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_parameter);
       
  3728 	}
       
  3729 
       
  3730 	if (label->get_is_valid_data() == false
       
  3731 		|| label->get_data_length() == 0ul)
       
  3732 	{
       
  3733 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3734 		return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_parameter);
       
  3735 	}
       
  3736 
       
  3737 	if (seed->get_is_valid_data() == false
       
  3738 		|| seed->get_data_length() == 0ul)
       
  3739 	{
       
  3740 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3741 		return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_parameter);
       
  3742 	}
       
  3743 
       
  3744 	// - - - - - - - - - - - - - - - - - - - - - - - - - - - -
       
  3745 
       
  3746 	eap_variable_data_c input(m_am_tools);
       
  3747 
       
  3748 	eap_status_e status = input.add_data(label);
       
  3749 	if (status != eap_status_ok)
       
  3750 	{
       
  3751 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3752 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  3753 	}
       
  3754 
       
  3755 	status = input.add_data(seed);
       
  3756 	if (status != eap_status_ok)
       
  3757 	{
       
  3758 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3759 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  3760 	}
       
  3761 
       
  3762 	status = m_seed.set_copy_of_buffer(&input);
       
  3763 	if (status != eap_status_ok)
       
  3764 	{
       
  3765 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3766 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  3767 	}
       
  3768 
       
  3769 	EAP_TRACE_DATA_DEBUG(
       
  3770 		m_am_tools,
       
  3771 		TRACE_FLAGS_EAP_AM_CRYPTO,
       
  3772 		(EAPL("tls_prf_init(): m_seed"),
       
  3773 		 m_seed.get_data(m_seed.get_data_length()),
       
  3774 		 m_seed.get_data_length()));
       
  3775 
       
  3776 	// - - - - - - - - - - - - - - - - - - - - - - - - - - - -
       
  3777 
       
  3778 	status = m_md5_key.set_copy_of_buffer(
       
  3779 		secret);
       
  3780 	if (status != eap_status_ok)
       
  3781 	{
       
  3782 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3783 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  3784 	}
       
  3785 
       
  3786 	EAP_TRACE_DATA_DEBUG(
       
  3787 		m_am_tools,
       
  3788 		TRACE_FLAGS_EAP_AM_CRYPTO,
       
  3789 		(EAPL("tls_prf_init(): m_md5_key"),
       
  3790 		 m_md5_key.get_data(m_md5_key.get_data_length()),
       
  3791 		 m_md5_key.get_data_length()));
       
  3792 
       
  3793 	// - - - - - - - - - - - - - - - - - - - - - - - - - - - -
       
  3794 
       
  3795 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3796 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  3797 }
       
  3798 
       
  3799 //--------------------------------------------------
       
  3800 
       
  3801 EAP_FUNC_EXPORT eap_status_e crypto_tls_md5_prf_c::tls_prf_output(
       
  3802 	void * const pseudo_random_data,
       
  3803 	const u32_t pseudo_random_data_length)
       
  3804 {
       
  3805 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3806 
       
  3807 	if (pseudo_random_data == 0)
       
  3808 	{
       
  3809 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3810 		return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_parameter);
       
  3811 	}
       
  3812 
       
  3813 	eap_status_e status = eap_status_not_supported;
       
  3814 
       
  3815 	EAP_ASSERT_ALWAYS(get_is_valid() == true);
       
  3816 
       
  3817 	// - - - - - - - - - - - - - - - - - - - - - - - - - - - -
       
  3818 
       
  3819 	status = m_A_md5_context->hmac_set_key(&m_md5_key);
       
  3820 	if (status != eap_status_ok)
       
  3821 	{
       
  3822 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3823 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  3824 	}
       
  3825 	
       
  3826 	status = m_md5_context->hmac_set_key(&m_md5_key);
       
  3827 	if (status != eap_status_ok)
       
  3828 	{
       
  3829 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3830 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  3831 	}
       
  3832 	
       
  3833 	// - - - - - - - - - - - - - - - - - - - - - - - - - - - -
       
  3834 
       
  3835 	eap_variable_data_c A_md5_output(m_am_tools);
       
  3836 
       
  3837 	status = A_md5_output.init(m_A_md5_context->get_digest_length());
       
  3838 	if (status != eap_status_ok)
       
  3839 	{
       
  3840 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3841 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  3842 	}
       
  3843 	A_md5_output.set_is_valid();
       
  3844 	A_md5_output.set_data_length(A_md5_output.get_buffer_length());
       
  3845 
       
  3846 	// - - - - - - - - - - - - - - - - - - - - - - - - - - - -
       
  3847 
       
  3848 	eap_variable_data_c md5_output(m_am_tools);
       
  3849 
       
  3850 	status = md5_output.init(
       
  3851 		pseudo_random_data_length+m_md5_context->get_digest_length());
       
  3852 	if (status != eap_status_ok)
       
  3853 	{
       
  3854 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3855 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  3856 	}
       
  3857 	md5_output.set_is_valid();
       
  3858 	md5_output.set_data_length(md5_output.get_buffer_length());
       
  3859 
       
  3860 	// - - - - - - - - - - - - - - - - - - - - - - - - - - - -
       
  3861 	// - - - - - - - - - - - - - - - - - - - - - - - - - - - -
       
  3862 	// - - - - - - - - - - - - - - - - - - - - - - - - - - - -
       
  3863 
       
  3864 	{
       
  3865 		u32_t hmac_md5_md_length = m_md5_context->get_digest_length();
       
  3866 		u32_t md5_count = md5_output.get_data_length()
       
  3867 			/ m_md5_context->get_digest_length();
       
  3868 
       
  3869 		// First we initialize A value:
       
  3870 		// A(0) = seed
       
  3871 		status = tls_prf_A_value(
       
  3872 			m_A_md5_context,
       
  3873 			&m_md5_key,
       
  3874 			&m_seed,
       
  3875 			&A_md5_output);
       
  3876 		if (status != eap_status_ok)
       
  3877 		{
       
  3878 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3879 			return EAP_STATUS_RETURN(m_am_tools, status);
       
  3880 		}
       
  3881 
       
  3882 		// out(1) = HMAC_hash(secret, A(1) + seed)
       
  3883 		status = tls_prf_one_round(
       
  3884 			m_md5_context,
       
  3885 			&m_md5_key,
       
  3886 			&A_md5_output,
       
  3887 			&m_seed,
       
  3888 			md5_output.get_data_offset(0ul, hmac_md5_md_length),
       
  3889 			hmac_md5_md_length);
       
  3890 		if (status != eap_status_ok)
       
  3891 		{
       
  3892 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3893 			return EAP_STATUS_RETURN(m_am_tools, status);
       
  3894 		}
       
  3895 
       
  3896 		for (u32_t ind = 1ul; ind < md5_count; ind++)
       
  3897 		{
       
  3898 			// Next A value is:
       
  3899 			// A(i) = HMAC_hash(secret, A(i-1)).
       
  3900 			status = tls_prf_A_value(
       
  3901 				m_A_md5_context,
       
  3902 				&m_md5_key,
       
  3903 				&A_md5_output,
       
  3904 				&A_md5_output);
       
  3905 			if (status != eap_status_ok)
       
  3906 			{
       
  3907 				EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3908 				return EAP_STATUS_RETURN(m_am_tools, status);
       
  3909 			}
       
  3910 
       
  3911 			// out(i) = HMAC_hash(secret, A(i) + seed)
       
  3912 			status = tls_prf_one_round(
       
  3913 				m_md5_context,
       
  3914 				&m_md5_key,
       
  3915 				&A_md5_output,
       
  3916 				&m_seed,
       
  3917 				md5_output.get_data_offset(
       
  3918 					ind*hmac_md5_md_length,
       
  3919 					hmac_md5_md_length),
       
  3920 				hmac_md5_md_length);
       
  3921 			if (status != eap_status_ok)
       
  3922 			{
       
  3923 				EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3924 				return EAP_STATUS_RETURN(m_am_tools, status);
       
  3925 			}
       
  3926 		} // for()
       
  3927 	}
       
  3928 
       
  3929 	// - - - - - - - - - - - - - - - - - - - - - - - - - - - -
       
  3930 	// - - - - - - - - - - - - - - - - - - - - - - - - - - - -
       
  3931 	// - - - - - - - - - - - - - - - - - - - - - - - - - - - -
       
  3932 
       
  3933 	// Final operation is copy md5_output to output buffer.
       
  3934 
       
  3935 	{
       
  3936 		EAP_TRACE_DATA_DEBUG(
       
  3937 			m_am_tools,
       
  3938 			TRACE_FLAGS_EAP_AM_CRYPTO,
       
  3939 			(EAPL("crypto_tls_md5_prf_c::tls_prf_output(): md5_output"),
       
  3940 			 md5_output.get_data(pseudo_random_data_length),
       
  3941 			 pseudo_random_data_length));
       
  3942 
       
  3943 		EAP_ASSERT(pseudo_random_data_length <= md5_output.get_data_length());
       
  3944 
       
  3945 		const u8_t * const md5_buffer
       
  3946 			= md5_output.get_data(pseudo_random_data_length);
       
  3947 		if (md5_buffer == 0)
       
  3948 		{
       
  3949 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3950 			return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
  3951 		}
       
  3952 
       
  3953 		u8_t * const p_pseudo_random_data
       
  3954 			= static_cast<u8_t *>(pseudo_random_data);
       
  3955 
       
  3956 		m_am_tools->memmove(
       
  3957 			p_pseudo_random_data,
       
  3958 			md5_buffer,
       
  3959 			pseudo_random_data_length);
       
  3960 
       
  3961 		EAP_TRACE_DATA_DEBUG(
       
  3962 			m_am_tools,
       
  3963 			TRACE_FLAGS_EAP_AM_CRYPTO,
       
  3964 			(EAPL("crypto_tls_md5_prf_c::tls_prf_output(): ")
       
  3965 			 EAPL("p_pseudo_random_data"),
       
  3966 			 p_pseudo_random_data,
       
  3967 			 pseudo_random_data_length));
       
  3968 	}
       
  3969 
       
  3970 	// - - - - - - - - - - - - - - - - - - - - - - - - - - - -
       
  3971 
       
  3972 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3973 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  3974 }
       
  3975 
       
  3976 //--------------------------------------------------
       
  3977 
       
  3978 EAP_FUNC_EXPORT eap_status_e crypto_tls_md5_prf_c::tls_prf_cleanup()
       
  3979 {
       
  3980 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3981 
       
  3982 	if (m_md5_context != 0)
       
  3983 	{
       
  3984 		m_md5_context->hmac_cleanup();
       
  3985 	}
       
  3986 
       
  3987 	if (m_A_md5_context != 0)
       
  3988 	{
       
  3989 		m_A_md5_context->hmac_cleanup();
       
  3990 	}
       
  3991 
       
  3992 	m_md5_key.reset();
       
  3993 	m_seed.reset();
       
  3994 
       
  3995 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3996 	return EAP_STATUS_RETURN(m_am_tools, eap_status_ok);
       
  3997 }
       
  3998 
       
  3999 //--------------------------------------------------
       
  4000 //--------------------------------------------------
       
  4001 //--------------------------------------------------
       
  4002 
       
  4003 EAP_FUNC_EXPORT crypto_tls_prf_c::~crypto_tls_prf_c()
       
  4004 {
       
  4005 	tls_prf_cleanup();
       
  4006 
       
  4007 	delete m_tls_md5_prf;
       
  4008 	m_tls_md5_prf = 0;
       
  4009 
       
  4010 	delete m_tls_sha1_prf;
       
  4011 	m_tls_sha1_prf = 0;
       
  4012 }
       
  4013 
       
  4014 //--------------------------------------------------
       
  4015 
       
  4016 EAP_FUNC_EXPORT crypto_tls_prf_c::crypto_tls_prf_c(
       
  4017 	abs_eap_am_tools_c * const tools)
       
  4018 	: m_am_tools(tools)
       
  4019 	, m_tls_md5_prf(0)
       
  4020 	, m_tls_sha1_prf(0)
       
  4021 	, m_is_valid(false)
       
  4022 {
       
  4023 	m_tls_md5_prf = new crypto_tls_md5_prf_c(tools);
       
  4024 	if (m_tls_md5_prf == 0)
       
  4025 	{
       
  4026 		return;
       
  4027 	}
       
  4028 
       
  4029 	m_tls_sha1_prf = new crypto_tls_sha1_prf_c(tools);
       
  4030 	if (m_tls_sha1_prf == 0)
       
  4031 	{
       
  4032 		return;
       
  4033 	}
       
  4034 
       
  4035 	set_is_valid();
       
  4036 }
       
  4037 
       
  4038 //--------------------------------------------------
       
  4039 
       
  4040 EAP_FUNC_EXPORT void crypto_tls_prf_c::set_is_invalid()
       
  4041 {
       
  4042 	m_is_valid = false;
       
  4043 }
       
  4044 
       
  4045 //--------------------------------------------------
       
  4046 
       
  4047 EAP_FUNC_EXPORT void crypto_tls_prf_c::set_is_valid()
       
  4048 {
       
  4049 	m_is_valid = true;
       
  4050 }
       
  4051 
       
  4052 //--------------------------------------------------
       
  4053 
       
  4054 EAP_FUNC_EXPORT bool crypto_tls_prf_c::get_is_valid()
       
  4055 {
       
  4056 	return 	m_is_valid;
       
  4057 }
       
  4058 
       
  4059 //--------------------------------------------------
       
  4060 
       
  4061 EAP_FUNC_EXPORT eap_status_e crypto_tls_prf_c::tls_prf_init(
       
  4062 	const eap_variable_data_c * const secret,
       
  4063 	const eap_variable_data_c * const label,
       
  4064 	const eap_variable_data_c * const seed)
       
  4065 {
       
  4066 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4067 
       
  4068 	if (m_tls_md5_prf == 0
       
  4069 		|| m_tls_sha1_prf == 0)
       
  4070 	{
       
  4071 		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
  4072 	}
       
  4073 
       
  4074 	if (secret->get_is_valid_data() == false
       
  4075 		|| secret->get_data_length() == 0ul)
       
  4076 	{
       
  4077 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4078 		return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_parameter);
       
  4079 	}
       
  4080 
       
  4081 	if (label->get_is_valid_data() == false
       
  4082 		|| label->get_data_length() == 0ul)
       
  4083 	{
       
  4084 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4085 		return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_parameter);
       
  4086 	}
       
  4087 
       
  4088 	if (seed->get_is_valid_data() == false
       
  4089 		|| seed->get_data_length() == 0ul)
       
  4090 	{
       
  4091 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4092 		return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_parameter);
       
  4093 	}
       
  4094 
       
  4095 	// - - - - - - - - - - - - - - - - - - - - - - - - - - - -
       
  4096 
       
  4097 	bool is_odd_key = false;
       
  4098 	if ((secret->get_data_length() % 2) != 0)
       
  4099 	{
       
  4100 		// Odd length, one byte will be shared with both keys.
       
  4101 		is_odd_key = true;
       
  4102 	}
       
  4103 
       
  4104 	u32_t key_length = secret->get_data_length() / 2ul;
       
  4105 	u32_t sha1_key_offset = key_length;
       
  4106 
       
  4107 	if (is_odd_key == true)
       
  4108 	{
       
  4109 		++key_length;
       
  4110 	}
       
  4111 
       
  4112 	eap_variable_data_c md5_secret(m_am_tools);
       
  4113 	eap_variable_data_c sha1_secret(m_am_tools);
       
  4114 
       
  4115 	eap_status_e status = md5_secret.set_buffer(
       
  4116 		secret->get_data_offset(0ul, key_length),
       
  4117 		key_length,
       
  4118 		false,
       
  4119 		false);
       
  4120 	if (status != eap_status_ok)
       
  4121 	{
       
  4122 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4123 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  4124 	}
       
  4125 
       
  4126 	status = sha1_secret.set_buffer(
       
  4127 		secret->get_data_offset(sha1_key_offset, key_length),
       
  4128 		key_length,
       
  4129 		false,
       
  4130 		false);
       
  4131 	if (status != eap_status_ok)
       
  4132 	{
       
  4133 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4134 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  4135 	}
       
  4136 
       
  4137 
       
  4138 	status = m_tls_md5_prf->tls_prf_init(&md5_secret, label, seed);
       
  4139 	if (status != eap_status_ok)
       
  4140 	{
       
  4141 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4142 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  4143 	}
       
  4144 
       
  4145 	status = m_tls_sha1_prf->tls_prf_init(&sha1_secret, label, seed);
       
  4146 	if (status != eap_status_ok)
       
  4147 	{
       
  4148 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4149 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  4150 	}
       
  4151 
       
  4152 	// - - - - - - - - - - - - - - - - - - - - - - - - - - - -
       
  4153 
       
  4154 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4155 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  4156 }
       
  4157 
       
  4158 //--------------------------------------------------
       
  4159 
       
  4160 EAP_FUNC_EXPORT eap_status_e crypto_tls_prf_c::tls_prf_output(
       
  4161 	void * const pseudo_random_data,
       
  4162 	const u32_t pseudo_random_data_length)
       
  4163 {
       
  4164 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4165 
       
  4166 	eap_status_e status = eap_status_not_supported;
       
  4167 
       
  4168 	EAP_ASSERT_ALWAYS(get_is_valid() == true);
       
  4169 
       
  4170 	// - - - - - - - - - - - - - - - - - - - - - - - - - - - -
       
  4171 
       
  4172 	eap_variable_data_c tls_md5_prf_output(m_am_tools);
       
  4173 	eap_variable_data_c tls_sha1_prf_output(m_am_tools);
       
  4174 
       
  4175 
       
  4176 	status = tls_md5_prf_output.init(pseudo_random_data_length);
       
  4177 	if (status != eap_status_ok)
       
  4178 	{
       
  4179 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4180 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  4181 	}
       
  4182 	tls_md5_prf_output.set_is_valid();
       
  4183 	tls_md5_prf_output.set_data_length(tls_md5_prf_output.get_buffer_length());
       
  4184 
       
  4185 	status = tls_sha1_prf_output.init(pseudo_random_data_length);
       
  4186 	if (status != eap_status_ok)
       
  4187 	{
       
  4188 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4189 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  4190 	}
       
  4191 	tls_sha1_prf_output.set_is_valid();
       
  4192 	tls_sha1_prf_output.set_data_length(
       
  4193 		tls_sha1_prf_output.get_buffer_length());
       
  4194 
       
  4195 
       
  4196 	status = m_tls_md5_prf->tls_prf_output(
       
  4197 		tls_md5_prf_output.get_data(tls_md5_prf_output.get_data_length()),
       
  4198 		tls_md5_prf_output.get_data_length());
       
  4199 	if (status != eap_status_ok)
       
  4200 	{
       
  4201 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4202 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  4203 	}
       
  4204 
       
  4205 	status = m_tls_sha1_prf->tls_prf_output(
       
  4206 		tls_sha1_prf_output.get_data(tls_sha1_prf_output.get_data_length()),
       
  4207 		tls_sha1_prf_output.get_data_length());
       
  4208 	if (status != eap_status_ok)
       
  4209 	{
       
  4210 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4211 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  4212 	}
       
  4213 
       
  4214 	// - - - - - - - - - - - - - - - - - - - - - - - - - - - -
       
  4215 	// - - - - - - - - - - - - - - - - - - - - - - - - - - - -
       
  4216 	// - - - - - - - - - - - - - - - - - - - - - - - - - - - -
       
  4217 
       
  4218 	// Final operation is XOR the md5_output and sha1_output.
       
  4219 
       
  4220 	{
       
  4221 		EAP_TRACE_DATA_DEBUG(
       
  4222 			m_am_tools,
       
  4223 			TRACE_FLAGS_EAP_AM_CRYPTO,
       
  4224 			(EAPL("tls_prf_init(): tls_md5_prf_output"),
       
  4225 			 tls_md5_prf_output.get_data(tls_md5_prf_output.get_data_length()),
       
  4226 			 tls_md5_prf_output.get_data_length()));
       
  4227 
       
  4228 		EAP_TRACE_DATA_DEBUG(
       
  4229 			m_am_tools,
       
  4230 			TRACE_FLAGS_EAP_AM_CRYPTO,
       
  4231 			(EAPL("tls_prf_init(): tls_sha1_prf_output"),
       
  4232 			 tls_sha1_prf_output.get_data(
       
  4233 				 tls_sha1_prf_output.get_data_length()),
       
  4234 			 tls_sha1_prf_output.get_data_length()));
       
  4235 
       
  4236 		EAP_ASSERT(
       
  4237 			pseudo_random_data_length
       
  4238 			<= tls_md5_prf_output.get_data_length());
       
  4239 		EAP_ASSERT(
       
  4240 			pseudo_random_data_length
       
  4241 			<= tls_sha1_prf_output.get_data_length());
       
  4242 
       
  4243 		const u8_t * const md5_buffer
       
  4244 			= tls_md5_prf_output.get_data(pseudo_random_data_length);
       
  4245 		const u8_t * const sha1_buffer
       
  4246 			= tls_sha1_prf_output.get_data(pseudo_random_data_length);
       
  4247 		u8_t * const p_pseudo_random_data
       
  4248 			= static_cast<u8_t *>(pseudo_random_data);
       
  4249 
       
  4250 		for (u32_t ind = 0u; ind < pseudo_random_data_length; ind++)
       
  4251 		{
       
  4252 			p_pseudo_random_data[ind]
       
  4253 				= static_cast<u8_t>((md5_buffer[ind] ^ sha1_buffer[ind]));
       
  4254 		}
       
  4255 
       
  4256 		EAP_TRACE_DATA_DEBUG(
       
  4257 			m_am_tools,
       
  4258 			TRACE_FLAGS_EAP_AM_CRYPTO,
       
  4259 			(EAPL("tls_prf_init(): p_pseudo_random_data"),
       
  4260 			 p_pseudo_random_data,
       
  4261 			 pseudo_random_data_length));
       
  4262 	}
       
  4263 
       
  4264 	// - - - - - - - - - - - - - - - - - - - - - - - - - - - -
       
  4265 
       
  4266 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4267 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  4268 }
       
  4269 
       
  4270 //--------------------------------------------------
       
  4271 
       
  4272 EAP_FUNC_EXPORT eap_status_e crypto_tls_prf_c::tls_prf_cleanup()
       
  4273 {
       
  4274 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4275 
       
  4276 	if (m_tls_md5_prf != 0)
       
  4277 	{
       
  4278 		m_tls_md5_prf->tls_prf_cleanup();
       
  4279 	}
       
  4280 
       
  4281 	if (m_tls_sha1_prf != 0)
       
  4282 	{
       
  4283 		m_tls_sha1_prf->tls_prf_cleanup();
       
  4284 	}
       
  4285 
       
  4286 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4287 	return EAP_STATUS_RETURN(m_am_tools, eap_status_ok);
       
  4288 }
       
  4289 
       
  4290 //--------------------------------------------------
       
  4291 //--------------------------------------------------
       
  4292 //--------------------------------------------------
       
  4293 
       
  4294 
       
  4295 EAP_FUNC_EXPORT crypto_eap_fast_hmac_sha1_prf_c::~crypto_eap_fast_hmac_sha1_prf_c()
       
  4296 {
       
  4297 	t_prf_cleanup();
       
  4298 
       
  4299 	delete m_context;
       
  4300 	m_context = 0;
       
  4301 }
       
  4302 
       
  4303 //--------------------------------------------------
       
  4304 
       
  4305 EAP_FUNC_EXPORT crypto_eap_fast_hmac_sha1_prf_c::crypto_eap_fast_hmac_sha1_prf_c(
       
  4306 	abs_eap_am_tools_c * const tools)
       
  4307 	: m_am_tools(tools)
       
  4308 	, m_context(0)
       
  4309 	, m_key(tools)
       
  4310 	, m_S_value(tools)
       
  4311 	, m_is_valid(false)
       
  4312 {
       
  4313 	{
       
  4314 		crypto_sha1_c * sha1 = new crypto_sha1_c(m_am_tools);
       
  4315 		if (sha1 == 0
       
  4316 			|| sha1->get_is_valid() == false)
       
  4317 		{
       
  4318 			delete sha1;
       
  4319 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4320 			return;
       
  4321 		}
       
  4322 
       
  4323 		m_context = new crypto_hmac_c(m_am_tools, sha1, true);
       
  4324 		if (m_context == 0
       
  4325 			|| m_context->get_is_valid() == false)
       
  4326 		{
       
  4327 			delete m_context;
       
  4328 			m_context = 0;
       
  4329 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4330 			return;
       
  4331 		}
       
  4332 	}
       
  4333 
       
  4334 	set_is_valid();
       
  4335 }
       
  4336 
       
  4337 //--------------------------------------------------
       
  4338 
       
  4339 EAP_FUNC_EXPORT void crypto_eap_fast_hmac_sha1_prf_c::set_is_invalid()
       
  4340 {
       
  4341 	m_is_valid = false;
       
  4342 }
       
  4343 
       
  4344 //--------------------------------------------------
       
  4345 
       
  4346 EAP_FUNC_EXPORT void crypto_eap_fast_hmac_sha1_prf_c::set_is_valid()
       
  4347 {
       
  4348 	m_is_valid = true;
       
  4349 }
       
  4350 
       
  4351 //--------------------------------------------------
       
  4352 
       
  4353 EAP_FUNC_EXPORT bool crypto_eap_fast_hmac_sha1_prf_c::get_is_valid()
       
  4354 {
       
  4355 	return 	m_is_valid;
       
  4356 }
       
  4357 
       
  4358 //--------------------------------------------------
       
  4359 
       
  4360 EAP_FUNC_EXPORT eap_status_e crypto_eap_fast_hmac_sha1_prf_c::t_prf_init(
       
  4361 	const eap_variable_data_c * const key,
       
  4362 	const eap_variable_data_c * const label,
       
  4363 	const eap_variable_data_c * const seed)
       
  4364 {
       
  4365 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4366 
       
  4367 	if (key->get_is_valid_data() == false
       
  4368 		|| key->get_data_length() == 0ul)
       
  4369 	{
       
  4370 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4371 		return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_parameter);
       
  4372 	}
       
  4373 
       
  4374 	if (label->get_is_valid_data() == false
       
  4375 		|| label->get_data_length() == 0ul)
       
  4376 	{
       
  4377 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4378 		return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_parameter);
       
  4379 	}
       
  4380 
       
  4381 	// NOTE seed could be empty buffer.
       
  4382 	if (seed != 0
       
  4383 		&& seed->get_is_valid() == false)
       
  4384 	{
       
  4385 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4386 		return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_parameter);
       
  4387 	}
       
  4388 
       
  4389 	// - - - - - - - - - - - - - - - - - - - - - - - - - - - -
       
  4390 
       
  4391 	m_S_value.reset();
       
  4392 
       
  4393 	eap_status_e status = m_S_value.set_copy_of_buffer(label);
       
  4394 	if (status != eap_status_ok)
       
  4395 	{
       
  4396 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4397 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  4398 	}
       
  4399 
       
  4400 	u8_t byte_counter(0ul);
       
  4401 
       
  4402 	status = m_S_value.add_data(&byte_counter, sizeof(byte_counter));
       
  4403 	if (status != eap_status_ok)
       
  4404 	{
       
  4405 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4406 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  4407 	}
       
  4408 
       
  4409 	if (seed != 0)
       
  4410 	{
       
  4411 		status = m_S_value.add_data(seed);
       
  4412 		if (status != eap_status_ok)
       
  4413 		{
       
  4414 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4415 			return EAP_STATUS_RETURN(m_am_tools, status);
       
  4416 		}
       
  4417 	}
       
  4418 
       
  4419 	EAP_TRACE_DATA_DEBUG(
       
  4420 		m_am_tools,
       
  4421 		TRACE_FLAGS_EAP_AM_CRYPTO,
       
  4422 		(EAPL("tls_prf_init(): m_S_value"),
       
  4423 		m_S_value.get_data(),
       
  4424 		m_S_value.get_data_length()));
       
  4425 
       
  4426 	// - - - - - - - - - - - - - - - - - - - - - - - - - - - -
       
  4427 
       
  4428 	status = m_key.set_copy_of_buffer(key);
       
  4429 	if (status != eap_status_ok)
       
  4430 	{
       
  4431 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4432 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  4433 	}
       
  4434 
       
  4435 	EAP_TRACE_DATA_DEBUG(
       
  4436 		m_am_tools,
       
  4437 		TRACE_FLAGS_EAP_AM_CRYPTO,
       
  4438 		(EAPL("tls_prf_init(): m_key"),
       
  4439 		m_key.get_data(),
       
  4440 		m_key.get_data_length()));
       
  4441 
       
  4442 	// - - - - - - - - - - - - - - - - - - - - - - - - - - - -
       
  4443 
       
  4444 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4445 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  4446 }
       
  4447 
       
  4448 //--------------------------------------------------
       
  4449 
       
  4450 EAP_FUNC_EXPORT eap_status_e crypto_eap_fast_hmac_sha1_prf_c::t_prf_output(
       
  4451 	void * const pseudo_random_data,
       
  4452 	const u16_t pseudo_random_data_length)
       
  4453 {
       
  4454 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4455 
       
  4456 	if (pseudo_random_data == 0)
       
  4457 	{
       
  4458 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4459 		return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_parameter);
       
  4460 	}
       
  4461 
       
  4462 	eap_status_e status = eap_status_not_supported;
       
  4463 
       
  4464 	EAP_ASSERT_ALWAYS(get_is_valid() == true);
       
  4465 
       
  4466 	// - - - - - - - - - - - - - - - - - - - - - - - - - - - -
       
  4467 
       
  4468 	status = m_context->hmac_set_key(&m_key);
       
  4469 	if (status != eap_status_ok)
       
  4470 	{
       
  4471 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4472 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  4473 	}
       
  4474 	
       
  4475 	// - - - - - - - - - - - - - - - - - - - - - - - - - - - -
       
  4476 
       
  4477 	eap_variable_data_c sha1_output(m_am_tools);
       
  4478 
       
  4479 	u32_t required_data = pseudo_random_data_length+m_context->get_digest_length();
       
  4480 
       
  4481 	status = sha1_output.init(
       
  4482 		required_data);
       
  4483 	if (status != eap_status_ok)
       
  4484 	{
       
  4485 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4486 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  4487 	}
       
  4488 	sha1_output.set_is_valid();
       
  4489 	sha1_output.set_data_length(0ul);
       
  4490 
       
  4491 	// - - - - - - - - - - - - - - - - - - - - - - - - - - - -
       
  4492 	// - - - - - - - - - - - - - - - - - - - - - - - - - - - -
       
  4493 	// - - - - - - - - - - - - - - - - - - - - - - - - - - - -
       
  4494 
       
  4495 	{
       
  4496 		u32_t hmac_sha1_md_length = m_context->get_digest_length();
       
  4497 		u32_t sha1_count = required_data
       
  4498 			/ m_context->get_digest_length();
       
  4499 
       
  4500 		// - - - - - - - - - - - - - - - - - - - - - - - -
       
  4501 
       
  4502 		// - - - - - - - - - - - - - - - - - - - - - - - -
       
  4503 
       
  4504 		eap_variable_data_c T_value(m_am_tools);
       
  4505 		if (T_value.get_is_valid() == false)
       
  4506 		{
       
  4507 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4508 			return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
  4509 		}
       
  4510 
       
  4511 		status = T_value.set_buffer_length(hmac_sha1_md_length);
       
  4512 		if (status != eap_status_ok)
       
  4513 		{
       
  4514 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4515 			return EAP_STATUS_RETURN(m_am_tools, status);
       
  4516 		}
       
  4517 
       
  4518 		status = T_value.set_data_length(0ul);
       
  4519 		if (status != eap_status_ok)
       
  4520 		{
       
  4521 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4522 			return EAP_STATUS_RETURN(m_am_tools, status);
       
  4523 		}
       
  4524 
       
  4525 		// - - - - - - - - - - - - - - - - - - - - - - - -
       
  4526 
       
  4527 		u16_t network_order_pseudo_random_data_length(eap_htons(pseudo_random_data_length));
       
  4528 		u8_t byte_counter(0ul);
       
  4529 
       
  4530 		for (u32_t ind = 0ul; ind < sha1_count; ind++)
       
  4531 		{
       
  4532 			++byte_counter;
       
  4533 
       
  4534 			// Next A value is:
       
  4535 			// T(i) = HMAC_hash(key, T(i-1) + S + outputlength + 0x(i)).
       
  4536 
       
  4537 			status = m_context->hmac_set_key(&m_key);
       
  4538 			if (status != eap_status_ok)
       
  4539 			{
       
  4540 				EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4541 				return EAP_STATUS_RETURN(m_am_tools, status);
       
  4542 			}
       
  4543 
       
  4544 			status = m_context->hmac_update(T_value.get_data(), T_value.get_data_length());
       
  4545 			if (status != eap_status_ok)
       
  4546 			{
       
  4547 				EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4548 				return EAP_STATUS_RETURN(m_am_tools, status);
       
  4549 			}
       
  4550 
       
  4551 			status = m_context->hmac_update(m_S_value.get_data(), m_S_value.get_data_length());
       
  4552 			if (status != eap_status_ok)
       
  4553 			{
       
  4554 				EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4555 				return EAP_STATUS_RETURN(m_am_tools, status);
       
  4556 			}
       
  4557 
       
  4558 			status = m_context->hmac_update(&network_order_pseudo_random_data_length, sizeof(network_order_pseudo_random_data_length));
       
  4559 			if (status != eap_status_ok)
       
  4560 			{
       
  4561 				EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4562 				return EAP_STATUS_RETURN(m_am_tools, status);
       
  4563 			}
       
  4564 
       
  4565 			status = m_context->hmac_update(&byte_counter, sizeof(byte_counter));
       
  4566 			if (status != eap_status_ok)
       
  4567 			{
       
  4568 				EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4569 				return EAP_STATUS_RETURN(m_am_tools, status);
       
  4570 			}
       
  4571 
       
  4572 			u32_t digest_length(m_context->get_digest_length());
       
  4573 
       
  4574 			status = T_value.set_data_length(digest_length);
       
  4575 			if (status != eap_status_ok)
       
  4576 			{
       
  4577 				EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4578 				return EAP_STATUS_RETURN(m_am_tools, status);
       
  4579 			}
       
  4580 
       
  4581 			status = m_context->hmac_final(
       
  4582 				T_value.get_data(),
       
  4583 				&digest_length);
       
  4584 
       
  4585 			if (m_context->get_digest_length() != digest_length)
       
  4586 			{
       
  4587 				EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4588 				return EAP_STATUS_RETURN(m_am_tools, status);
       
  4589 			}
       
  4590 
       
  4591 			status = sha1_output.add_data(&T_value);
       
  4592 			if (status != eap_status_ok)
       
  4593 			{
       
  4594 				EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4595 				return EAP_STATUS_RETURN(m_am_tools, status);
       
  4596 			}
       
  4597 
       
  4598 		} // for()
       
  4599 	}
       
  4600 
       
  4601 	// - - - - - - - - - - - - - - - - - - - - - - - - - - - -
       
  4602 	// - - - - - - - - - - - - - - - - - - - - - - - - - - - -
       
  4603 	// - - - - - - - - - - - - - - - - - - - - - - - - - - - -
       
  4604 
       
  4605 	// Final operation is copy sha1_output to output buffer.
       
  4606 
       
  4607 	{
       
  4608 		EAP_TRACE_DATA_DEBUG(
       
  4609 			m_am_tools,
       
  4610 			TRACE_FLAGS_EAP_AM_CRYPTO,
       
  4611 			(EAPL("crypto_eap_fast_hmac_sha1_prf_c::tls_prf_output(): sha1_output"),
       
  4612 			 sha1_output.get_data(pseudo_random_data_length),
       
  4613 			 pseudo_random_data_length));
       
  4614 
       
  4615 		EAP_ASSERT(pseudo_random_data_length <= sha1_output.get_data_length());
       
  4616 
       
  4617 		const u8_t * const sha1_buffer = sha1_output.get_data(
       
  4618 			pseudo_random_data_length);
       
  4619 		if (sha1_buffer == 0)
       
  4620 		{
       
  4621 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4622 			return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
  4623 		}
       
  4624 
       
  4625 		u8_t * const p_pseudo_random_data
       
  4626 			= static_cast<u8_t *>(pseudo_random_data);
       
  4627 
       
  4628 		m_am_tools->memmove(
       
  4629 			p_pseudo_random_data,
       
  4630 			sha1_buffer,
       
  4631 			pseudo_random_data_length);
       
  4632 
       
  4633 		EAP_TRACE_DATA_DEBUG(
       
  4634 			m_am_tools,
       
  4635 			TRACE_FLAGS_EAP_AM_CRYPTO,
       
  4636 			(EAPL("crypto_eap_fast_hmac_sha1_prf_c::tls_prf_output(): ")
       
  4637 			 EAPL("p_pseudo_random_data"),
       
  4638 			 p_pseudo_random_data,
       
  4639 			 pseudo_random_data_length));
       
  4640 	}
       
  4641 
       
  4642 	// - - - - - - - - - - - - - - - - - - - - - - - - - - - -
       
  4643 
       
  4644 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4645 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  4646 }
       
  4647 
       
  4648 //--------------------------------------------------
       
  4649 
       
  4650 EAP_FUNC_EXPORT eap_status_e crypto_eap_fast_hmac_sha1_prf_c::t_prf_cleanup()
       
  4651 {
       
  4652 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4653 
       
  4654 	if (m_context != 0)
       
  4655 	{
       
  4656 		m_context->hmac_cleanup();
       
  4657 	}
       
  4658 
       
  4659 	m_key.reset();
       
  4660 	m_S_value.reset();
       
  4661 
       
  4662 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4663 	return EAP_STATUS_RETURN(m_am_tools, eap_status_ok);
       
  4664 }
       
  4665 
       
  4666 
       
  4667 //--------------------------------------------------
       
  4668 //--------------------------------------------------
       
  4669 //--------------------------------------------------
       
  4670 
       
  4671 EAP_FUNC_EXPORT crypto_rsa_c::~crypto_rsa_c()
       
  4672 {
       
  4673 	cleanup();
       
  4674 }
       
  4675 
       
  4676 //--------------------------------------------------
       
  4677 
       
  4678 EAP_FUNC_EXPORT crypto_rsa_c::crypto_rsa_c(abs_eap_am_tools_c * const tools)
       
  4679 	: m_am_tools(tools)
       
  4680 	, m_context(tools)
       
  4681 	, m_is_valid(false)
       
  4682 {
       
  4683 }
       
  4684 
       
  4685 //--------------------------------------------------
       
  4686 
       
  4687 EAP_FUNC_EXPORT void crypto_rsa_c::set_is_invalid()
       
  4688 {
       
  4689 	m_is_valid = false;
       
  4690 }
       
  4691 
       
  4692 //--------------------------------------------------
       
  4693 
       
  4694 EAP_FUNC_EXPORT void crypto_rsa_c::set_is_valid()
       
  4695 {
       
  4696 	m_is_valid = true;
       
  4697 }
       
  4698 
       
  4699 //--------------------------------------------------
       
  4700 
       
  4701 EAP_FUNC_EXPORT bool crypto_rsa_c::get_is_valid()
       
  4702 {
       
  4703 	return 	m_is_valid;
       
  4704 }
       
  4705 
       
  4706 //--------------------------------------------------
       
  4707 
       
  4708 EAP_FUNC_EXPORT eap_status_e crypto_rsa_c::init()
       
  4709 {
       
  4710 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4711 
       
  4712 	eap_status_e status = m_am_tools->get_crypto()->rsa_init(&m_context);
       
  4713 
       
  4714 	if (m_context.get_is_valid_data() == false)
       
  4715 	{
       
  4716 		set_is_invalid();
       
  4717 		if (status == eap_status_ok)
       
  4718 		{
       
  4719 			status = eap_status_allocation_error;
       
  4720 		}
       
  4721 	}
       
  4722 
       
  4723 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4724 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  4725 }
       
  4726 
       
  4727 //--------------------------------------------------
       
  4728 
       
  4729 EAP_FUNC_EXPORT eap_status_e crypto_rsa_c::encrypt_with_public_key(
       
  4730 	const eap_variable_data_c * const public_rsa_key,
       
  4731 	const eap_variable_data_c * const input_data,
       
  4732 	eap_variable_data_c * const output_data)
       
  4733 {
       
  4734 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4735 
       
  4736 	eap_status_e status = m_am_tools->get_crypto()
       
  4737 		->rsa_encrypt_with_public_key(
       
  4738 			&m_context,
       
  4739 			public_rsa_key,
       
  4740 			input_data,
       
  4741 			output_data);
       
  4742 
       
  4743 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4744 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  4745 }
       
  4746 
       
  4747 //--------------------------------------------------
       
  4748 
       
  4749 EAP_FUNC_EXPORT eap_status_e crypto_rsa_c::decrypt_with_public_key(
       
  4750 	const eap_variable_data_c * const public_rsa_key,
       
  4751 	const eap_variable_data_c * const input_data,
       
  4752 	eap_variable_data_c * const output_data)
       
  4753 {
       
  4754 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4755 
       
  4756 	eap_status_e status = m_am_tools->get_crypto()
       
  4757 		->rsa_decrypt_with_public_key(
       
  4758 			&m_context,
       
  4759 			public_rsa_key,
       
  4760 			input_data,
       
  4761 			output_data);
       
  4762 
       
  4763 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4764 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  4765 }
       
  4766 
       
  4767 //--------------------------------------------------
       
  4768 
       
  4769 EAP_FUNC_EXPORT eap_status_e crypto_rsa_c::encrypt_with_private_key(
       
  4770 	const eap_variable_data_c * const private_rsa_key,
       
  4771 	const eap_variable_data_c * const input_data,
       
  4772 	eap_variable_data_c * const output_data)
       
  4773 {
       
  4774 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4775 
       
  4776 	eap_status_e status = m_am_tools->get_crypto()
       
  4777 		->rsa_encrypt_with_private_key(
       
  4778 			&m_context,
       
  4779 			private_rsa_key,
       
  4780 			input_data,
       
  4781 			output_data);
       
  4782 
       
  4783 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4784 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  4785 }
       
  4786 
       
  4787 //--------------------------------------------------
       
  4788 
       
  4789 EAP_FUNC_EXPORT eap_status_e crypto_rsa_c::decrypt_with_private_key(
       
  4790 	const eap_variable_data_c * const private_rsa_key,
       
  4791 	const eap_variable_data_c * const input_data,
       
  4792 	eap_variable_data_c * const output_data)
       
  4793 {
       
  4794 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4795 
       
  4796 	eap_status_e status = m_am_tools->get_crypto()
       
  4797 		->rsa_decrypt_with_private_key(
       
  4798 			&m_context,
       
  4799 			private_rsa_key,
       
  4800 			input_data,
       
  4801 			output_data);
       
  4802 
       
  4803 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4804 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  4805 }
       
  4806 
       
  4807 //--------------------------------------------------
       
  4808 
       
  4809 EAP_FUNC_EXPORT eap_status_e crypto_rsa_c::sign(
       
  4810 	const eap_variable_data_c * const private_rsa_key,
       
  4811 	const eap_variable_data_c * const hash,
       
  4812 	eap_variable_data_c * const signed_hash)
       
  4813 {
       
  4814 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4815 
       
  4816 	eap_status_e status = m_am_tools->get_crypto()->rsa_sign(
       
  4817 		&m_context,
       
  4818 		private_rsa_key,
       
  4819 		hash,
       
  4820 		signed_hash);
       
  4821 
       
  4822 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4823 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  4824 }
       
  4825 
       
  4826 //--------------------------------------------------
       
  4827 
       
  4828 EAP_FUNC_EXPORT eap_status_e crypto_rsa_c::verify(
       
  4829 	const eap_variable_data_c * const public_rsa_key,
       
  4830 	const eap_variable_data_c * const hash,
       
  4831 	const eap_variable_data_c * const signed_hash)
       
  4832 {
       
  4833 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4834 
       
  4835 	eap_status_e status = m_am_tools->get_crypto()->rsa_verify(
       
  4836 		&m_context,
       
  4837 		public_rsa_key,
       
  4838 		hash,
       
  4839 		signed_hash);
       
  4840 
       
  4841 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4842 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  4843 }
       
  4844 
       
  4845 //--------------------------------------------------
       
  4846 
       
  4847 EAP_FUNC_EXPORT eap_status_e crypto_rsa_c::cleanup()
       
  4848 {
       
  4849 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4850 
       
  4851 	eap_status_e status = m_am_tools->get_crypto()->rsa_cleanup(&m_context);
       
  4852 
       
  4853 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4854 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  4855 }
       
  4856 
       
  4857 //--------------------------------------------------
       
  4858 //--------------------------------------------------
       
  4859 //--------------------------------------------------
       
  4860 
       
  4861 EAP_FUNC_EXPORT crypto_dsa_c::~crypto_dsa_c()
       
  4862 {
       
  4863 	cleanup();
       
  4864 }
       
  4865 
       
  4866 //--------------------------------------------------
       
  4867 
       
  4868 EAP_FUNC_EXPORT crypto_dsa_c::crypto_dsa_c(abs_eap_am_tools_c * const tools)
       
  4869 	: m_am_tools(tools)
       
  4870 	, m_context(tools)
       
  4871 	, m_is_valid(false)
       
  4872 {
       
  4873 }
       
  4874 
       
  4875 //--------------------------------------------------
       
  4876 
       
  4877 EAP_FUNC_EXPORT void crypto_dsa_c::set_is_invalid()
       
  4878 {
       
  4879 	m_is_valid = false;
       
  4880 }
       
  4881 
       
  4882 //--------------------------------------------------
       
  4883 
       
  4884 EAP_FUNC_EXPORT void crypto_dsa_c::set_is_valid()
       
  4885 {
       
  4886 	m_is_valid = true;
       
  4887 }
       
  4888 
       
  4889 //--------------------------------------------------
       
  4890 
       
  4891 EAP_FUNC_EXPORT bool crypto_dsa_c::get_is_valid()
       
  4892 {
       
  4893 	return 	m_is_valid;
       
  4894 }
       
  4895 
       
  4896 //--------------------------------------------------
       
  4897 
       
  4898 EAP_FUNC_EXPORT eap_status_e crypto_dsa_c::init()
       
  4899 {
       
  4900 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4901 
       
  4902 	eap_status_e status = m_am_tools->get_crypto()->dsa_init(&m_context);
       
  4903 
       
  4904 	if (m_context.get_is_valid_data() == false)
       
  4905 	{
       
  4906 		set_is_invalid();
       
  4907 		if (status == eap_status_ok)
       
  4908 		{
       
  4909 			status = eap_status_allocation_error;
       
  4910 		}
       
  4911 	}
       
  4912 
       
  4913 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4914 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  4915 }
       
  4916 
       
  4917 //--------------------------------------------------
       
  4918 
       
  4919 EAP_FUNC_EXPORT eap_status_e crypto_dsa_c::sign(
       
  4920 	const eap_variable_data_c * const private_dsa_key,
       
  4921 	const eap_variable_data_c * const hash,
       
  4922 	eap_variable_data_c * const signed_hash)
       
  4923 {
       
  4924 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4925 
       
  4926 	eap_status_e status = m_am_tools->get_crypto()->dsa_sign(
       
  4927 		&m_context,
       
  4928 		private_dsa_key,
       
  4929 		hash,
       
  4930 		signed_hash);
       
  4931 
       
  4932 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4933 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  4934 }
       
  4935 
       
  4936 //--------------------------------------------------
       
  4937 
       
  4938 EAP_FUNC_EXPORT eap_status_e crypto_dsa_c::verify(
       
  4939 	const eap_variable_data_c * const public_dsa_key,
       
  4940 	const eap_variable_data_c * const dsa_param_p,
       
  4941 	const eap_variable_data_c * const dsa_param_q,
       
  4942 	const eap_variable_data_c * const dsa_param_g,
       
  4943 	const eap_variable_data_c * const hash,
       
  4944 	const eap_variable_data_c * const signed_hash)
       
  4945 {
       
  4946 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4947 
       
  4948 	eap_status_e status = m_am_tools->get_crypto()->dsa_verify(
       
  4949 		&m_context,
       
  4950 		public_dsa_key,
       
  4951 		dsa_param_p,
       
  4952 		dsa_param_q,
       
  4953 		dsa_param_g,
       
  4954 		hash,
       
  4955 		signed_hash);
       
  4956 
       
  4957 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4958 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  4959 }
       
  4960 
       
  4961 //--------------------------------------------------
       
  4962 
       
  4963 EAP_FUNC_EXPORT eap_status_e crypto_dsa_c::cleanup()
       
  4964 {
       
  4965 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4966 
       
  4967 	eap_status_e status = m_am_tools->get_crypto()->dsa_cleanup(&m_context);
       
  4968 
       
  4969 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4970 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  4971 }
       
  4972 
       
  4973 //--------------------------------------------------
       
  4974 //--------------------------------------------------
       
  4975 //--------------------------------------------------
       
  4976 
       
  4977 EAP_FUNC_EXPORT crypto_wpa_psk_password_hash_c::~crypto_wpa_psk_password_hash_c()
       
  4978 {	
       
  4979 }
       
  4980 
       
  4981 //--------------------------------------------------
       
  4982 
       
  4983 EAP_FUNC_EXPORT crypto_wpa_psk_password_hash_c::crypto_wpa_psk_password_hash_c(abs_eap_am_tools_c * const tools)
       
  4984 	: m_am_tools(tools)
       
  4985 	, m_is_valid(false)
       
  4986 {
       
  4987 	set_is_valid();
       
  4988 }
       
  4989 
       
  4990 //--------------------------------------------------
       
  4991 
       
  4992 void crypto_wpa_psk_password_hash_c::set_is_invalid()
       
  4993 {
       
  4994 	m_is_valid = false;
       
  4995 }
       
  4996 
       
  4997 //--------------------------------------------------
       
  4998 
       
  4999 void crypto_wpa_psk_password_hash_c::set_is_valid()
       
  5000 {
       
  5001 	m_is_valid = true;
       
  5002 }
       
  5003 
       
  5004 //--------------------------------------------------
       
  5005 
       
  5006 EAP_FUNC_EXPORT bool crypto_wpa_psk_password_hash_c::get_is_valid()
       
  5007 {
       
  5008 	return m_is_valid;
       
  5009 }
       
  5010 
       
  5011 //--------------------------------------------------
       
  5012 
       
  5013 // These are the functions for calculating PSK from ascii string 
       
  5014 // taken from 802.11i D3.0
       
  5015 
       
  5016 /*
       
  5017 * password - ascii string up to 63 characters in length
       
  5018 * ssid - octet string up to 32 octets
       
  5019 * ssidlength - length of ssid in octets
       
  5020 * output must be 40 octets in length and outputs 256 bits of key
       
  5021 */
       
  5022 EAP_FUNC_EXPORT eap_status_e crypto_wpa_psk_password_hash_c::password_hash(
       
  5023 	const eap_variable_data_c * const password,
       
  5024 	const eap_variable_data_c * const ssid,	
       
  5025 	eap_variable_data_c * const output,
       
  5026 	void * object,
       
  5027 	eap_status_e (*progress_callback)(void*, u32_t))
       
  5028 {
       
  5029 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  5030 	
       
  5031 	EAP_TRACE_DEBUG(
       
  5032 		m_am_tools,
       
  5033 		TRACE_FLAGS_DEFAULT,
       
  5034 		(EAPL("Hashing WPA PSK ASCII password.\n")));		
       
  5035 
       
  5036 	EAP_TRACE_DATA_DEBUG(
       
  5037 		m_am_tools,
       
  5038 		TRACE_FLAGS_DEFAULT, 
       
  5039 		(EAPL("password"),
       
  5040 		password->get_data(),
       
  5041 		password->get_data_length()));
       
  5042 
       
  5043 	EAP_TRACE_DATA_DEBUG(
       
  5044 		m_am_tools,
       
  5045 		TRACE_FLAGS_DEFAULT, 
       
  5046 		(EAPL("ssid"),
       
  5047 		ssid->get_data(),
       
  5048 		ssid->get_data_length()));
       
  5049 
       
  5050 	// Buffer must be reset before new HASH is added to it.
       
  5051 	// This causes the new HASH addition to the begin of the buffer.
       
  5052 	// This is small optimization that does not free the old buffer.
       
  5053 	eap_status_e status = output->reset_start_offset_and_data_length();
       
  5054 	if (status != eap_status_ok)
       
  5055 	{
       
  5056 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  5057 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  5058 	}
       
  5059 
       
  5060 	if ((password->get_data_length() > 63) || (ssid->get_data_length() > 32))
       
  5061 	{
       
  5062 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  5063 		return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_parameter);
       
  5064 	}
       
  5065 	
       
  5066 	status = password_hash_F(password, ssid, 4096, 1, output, object, progress_callback);
       
  5067 	if (status != eap_status_ok)
       
  5068 	{
       
  5069 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  5070 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  5071 	}
       
  5072 		
       
  5073 	status = password_hash_F(password, ssid, 4096, 2, output, object, progress_callback);
       
  5074 	if (status != eap_status_ok)
       
  5075 	{
       
  5076 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  5077 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  5078 	}
       
  5079 
       
  5080 	// truncate the buffer to 32 bytes
       
  5081 	output->set_data_length(WPA_PSK_LENGTH);
       
  5082 
       
  5083 	EAP_TRACE_DATA_DEBUG(
       
  5084 		m_am_tools,
       
  5085 		TRACE_FLAGS_DEFAULT, 
       
  5086 		(EAPL("WPA PSK"),
       
  5087 		output->get_data(),
       
  5088 		output->get_data_length()));
       
  5089 
       
  5090 
       
  5091 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  5092 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  5093 }
       
  5094 
       
  5095 eap_status_e crypto_wpa_psk_password_hash_c::password_hash_F(
       
  5096 	const eap_variable_data_c * const password,
       
  5097 	const eap_variable_data_c * const ssid,	
       
  5098 	u32_t iterations,
       
  5099 	u32_t count,
       
  5100 	eap_variable_data_c * const output,
       
  5101 	void * object,
       
  5102 	eap_status_e (*progress_callback)(void*, u32_t))
       
  5103 {
       
  5104 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  5105 	eap_status_e status(eap_status_process_general_error);
       
  5106 	
       
  5107 	crypto_sha1_c sha1(m_am_tools);
       
  5108 	
       
  5109 	status = sha1.hash_init();
       
  5110 	if (status != eap_status_ok)
       
  5111 	{
       
  5112 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  5113 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  5114 	}
       
  5115 	
       
  5116 	u32_t digest_length = sha1.get_digest_length();
       
  5117 
       
  5118 	crypto_hmac_c hmac(m_am_tools, &sha1, false);
       
  5119 
       
  5120 	u32_t i_ind, j_ind;
       
  5121 
       
  5122 	// Check for illegal characters
       
  5123 	for (i_ind = 0; i_ind < password->get_data_length(); i_ind++)
       
  5124 	{
       
  5125 		u8_t * const character = password->get_data_offset(i_ind, 1);
       
  5126 		if (character == 0)
       
  5127 		{
       
  5128 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  5129 			return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_parameter);
       
  5130 		}
       
  5131 
       
  5132 		if(!((*character >= 32) && (*character <= 126)))
       
  5133 		{
       
  5134 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  5135 			return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_parameter);
       
  5136 		}
       
  5137 	}
       
  5138 
       
  5139 	eap_variable_data_c digest(m_am_tools);	
       
  5140 	eap_variable_data_c digest1(m_am_tools);
       
  5141 
       
  5142 	status = digest.set_copy_of_buffer(ssid);
       
  5143 	if (status != eap_status_ok)
       
  5144 	{
       
  5145 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  5146 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  5147 	}
       
  5148 
       
  5149 	u8_t tmp[] = {
       
  5150 		static_cast<u8_t>((count>>24) & 0xff),
       
  5151 		static_cast<u8_t>((count>>16) & 0xff),
       
  5152 		static_cast<u8_t>((count>>8) & 0xff),
       
  5153 		static_cast<u8_t>(count & 0xff)
       
  5154 	};
       
  5155 
       
  5156 	status = digest.add_data(tmp, sizeof(tmp));
       
  5157 	if (status != eap_status_ok)
       
  5158 	{
       
  5159 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  5160 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  5161 	}
       
  5162 
       
  5163 	status = hmac.hmac_set_key(password);
       
  5164 	if (status != eap_status_ok)
       
  5165 	{
       
  5166 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  5167 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  5168 	}
       
  5169 
       
  5170 	status = hmac.hmac_update(
       
  5171 			digest.get_data(),
       
  5172 			digest.get_data_length());
       
  5173 	if (status != eap_status_ok)
       
  5174 	{
       
  5175 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  5176 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  5177 	}
       
  5178 
       
  5179 	status = digest1.set_buffer_length(digest_length);
       
  5180 	if (status != eap_status_ok)
       
  5181 	{
       
  5182 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  5183 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  5184 	}
       
  5185 
       
  5186 	status = hmac.hmac_final(
       
  5187 		digest1.get_buffer(digest_length),
       
  5188 			0);
       
  5189 	if (status != eap_status_ok)
       
  5190 	{
       
  5191 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  5192 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  5193 	}
       
  5194 	digest1.set_data_length(digest_length);
       
  5195 
       
  5196 	status = digest.set_buffer_length(digest_length);
       
  5197 	if (status != eap_status_ok)
       
  5198 	{
       
  5199 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  5200 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  5201 	}
       
  5202 	digest.set_data_length(digest_length);
       
  5203 
       
  5204 	/* output = U1 */
       
  5205 	status = output->add_data(&digest1);
       
  5206 	if (status != eap_status_ok)
       
  5207 	{
       
  5208 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  5209 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  5210 	}
       
  5211 
       
  5212 	u8_t * p_output = output->get_data_offset((count - 1) * digest_length, digest_length);
       
  5213 	if (p_output == 0)
       
  5214 	{
       
  5215 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  5216 		return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_parameter);
       
  5217 	}
       
  5218 	
       
  5219 	u32_t callback_trigger = 0ul;
       
  5220 
       
  5221 	for (i_ind = 1; i_ind < iterations; i_ind++) 
       
  5222 	{
       
  5223 		callback_trigger++;
       
  5224 
       
  5225 		if (callback_trigger > 400
       
  5226 			&& progress_callback != 0
       
  5227 			&& object != 0)
       
  5228 		{
       
  5229 			callback_trigger = 0;
       
  5230 			status = progress_callback(object, 400);		
       
  5231 			if (status != eap_status_ok)
       
  5232 			{
       
  5233 				// This means that the operation was cancelled.
       
  5234 				EAP_TRACE_DEBUG(
       
  5235 					m_am_tools,
       
  5236 					TRACE_FLAGS_DEFAULT,
       
  5237 					(EAPL("WPA PSK password hashing cancelled.\n")));
       
  5238 				return EAP_STATUS_RETURN(m_am_tools, status);
       
  5239 			}			
       
  5240 		}
       
  5241 
       
  5242 		status = hmac.hmac_set_key(password);
       
  5243 		if (status != eap_status_ok)
       
  5244 		{
       
  5245 			EAP_TRACE_DATA_ERROR(
       
  5246 				m_am_tools,
       
  5247 				TRACE_FLAGS_DEFAULT, 
       
  5248 				(EAPL("illegal password:"),
       
  5249 				password->get_data(),
       
  5250 				password->get_data_length()));
       
  5251 
       
  5252 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  5253 			return EAP_STATUS_RETURN(m_am_tools, status);
       
  5254 		}
       
  5255 
       
  5256 		status = hmac.hmac_update(
       
  5257 			digest1.get_data(),
       
  5258 			digest1.get_data_length());
       
  5259 		if (status != eap_status_ok)
       
  5260 		{
       
  5261 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  5262 			return EAP_STATUS_RETURN(m_am_tools, status);
       
  5263 		}
       
  5264 	
       
  5265 		status = hmac.hmac_final(
       
  5266 			digest.get_data(sha1.get_digest_length()),
       
  5267 				0);
       
  5268 		if (status != eap_status_ok)
       
  5269 		{
       
  5270 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  5271 			return EAP_STATUS_RETURN(m_am_tools, status);
       
  5272 		}
       
  5273 
       
  5274 		digest.set_data_length(digest_length);
       
  5275 
       
  5276 		status = digest1.set_copy_of_buffer(&digest);
       
  5277 		if (status != eap_status_ok)
       
  5278 		{
       
  5279 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  5280 			return EAP_STATUS_RETURN(m_am_tools, status);
       
  5281 		}
       
  5282 		
       
  5283 		/* output = output xor Un */		
       
  5284 		u8_t * p_digest = digest.get_data(digest_length);
       
  5285 		if (p_digest == 0)
       
  5286 		{
       
  5287 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  5288 			return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
  5289 		}
       
  5290 
       
  5291 		for (j_ind = 0; j_ind < digest_length; j_ind++)
       
  5292 		{
       
  5293 			p_output[j_ind] ^= p_digest[j_ind];
       
  5294 		}
       
  5295 	} // for()
       
  5296 
       
  5297 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  5298 	return EAP_STATUS_RETURN(m_am_tools, eap_status_ok);
       
  5299 }
       
  5300 
       
  5301 
       
  5302 //--------------------------------------------------
       
  5303 //--------------------------------------------------
       
  5304 //--------------------------------------------------
       
  5305 
       
  5306 
       
  5307 EAP_FUNC_EXPORT crypto_nt_hash_c::~crypto_nt_hash_c()
       
  5308 {	
       
  5309 }
       
  5310 
       
  5311 //--------------------------------------------------
       
  5312 
       
  5313 EAP_FUNC_EXPORT crypto_nt_hash_c::crypto_nt_hash_c(abs_eap_am_tools_c * const tools)
       
  5314 	: m_am_tools(tools)
       
  5315 	, m_is_valid(false)
       
  5316 {
       
  5317 	set_is_valid();
       
  5318 }
       
  5319 
       
  5320 //--------------------------------------------------
       
  5321 
       
  5322 void crypto_nt_hash_c::set_is_invalid()
       
  5323 {
       
  5324 	m_is_valid = false;
       
  5325 }
       
  5326 
       
  5327 //--------------------------------------------------
       
  5328 
       
  5329 void crypto_nt_hash_c::set_is_valid()
       
  5330 {
       
  5331 	m_is_valid = true;
       
  5332 }
       
  5333 
       
  5334 //--------------------------------------------------
       
  5335 
       
  5336 EAP_FUNC_EXPORT bool crypto_nt_hash_c::get_is_valid()
       
  5337 {
       
  5338 	return m_is_valid;
       
  5339 }
       
  5340 
       
  5341 //--------------------------------------------------
       
  5342 
       
  5343 EAP_FUNC_EXPORT eap_status_e crypto_nt_hash_c::nt_password_hash(
       
  5344 	const eap_variable_data_c * const password_utf8,
       
  5345 	eap_variable_data_c * const password_hash,
       
  5346 	const u32_t /* digest_size */)
       
  5347 {
       
  5348 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  5349 	if (password_utf8 == 0
       
  5350 		|| password_hash == 0)
       
  5351 	{
       
  5352 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  5353 		return EAP_STATUS_RETURN(m_am_tools, eap_status_process_general_error);
       
  5354 	}
       
  5355 
       
  5356 	eap_variable_data_c tmp_password_unicode(m_am_tools);
       
  5357 	eap_status_e status = m_am_tools->convert_utf8_to_unicode(tmp_password_unicode, *password_utf8);
       
  5358 	if (status != eap_status_ok)
       
  5359 	{
       
  5360 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  5361 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  5362 	}
       
  5363 
       
  5364 	// Ms-Chap-V2 wants the byte order of password is little endian
       
  5365 #if defined(EAP_BIG_ENDIAN)
       
  5366 	{
       
  5367 		u32_t password_size = tmp_password_unicode.get_data_length();
       
  5368 		u8_t * password = tmp_password_unicode.get_data(password_size);
       
  5369 		u8_t tmp;
       
  5370 
       
  5371 		for (i = 0; i < password_size; i += 2)
       
  5372 		{
       
  5373 			// Swap bytes
       
  5374 			tmp = password[i];
       
  5375 			password[i] = password[i + 1];
       
  5376 			password[i + 1] = tmp;
       
  5377 		}
       
  5378 	}
       
  5379 #endif // EAP_BIG_ENDIAN
       
  5380 
       
  5381 
       
  5382 	EAP_TRACE_DATA_DEBUG(
       
  5383 		m_am_tools,
       
  5384 		TRACE_FLAGS_DEFAULT,
       
  5385 		(EAPL("EAP_type_MSCHAPV2: nt_password_hash(), password_unicode"),
       
  5386 		tmp_password_unicode.get_data(),
       
  5387 		tmp_password_unicode.get_data_length()));
       
  5388 
       
  5389 	crypto_md4_c md4(m_am_tools);
       
  5390 
       
  5391 	status = md4.hash_init();
       
  5392 	if (status != eap_status_ok)
       
  5393 	{
       
  5394 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  5395 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  5396 	}
       
  5397 	
       
  5398 	status = md4.hash_update(
       
  5399 		tmp_password_unicode.get_data(),
       
  5400 		tmp_password_unicode.get_data_length()); // unicode-chars
       
  5401 	if (status != eap_status_ok)
       
  5402 	{
       
  5403 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  5404 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  5405 	}
       
  5406 
       
  5407 	password_hash->reset();
       
  5408 
       
  5409 	status = password_hash->set_buffer_length(md4.get_digest_length());
       
  5410 	if (status != eap_status_ok)
       
  5411 	{
       
  5412 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  5413 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  5414 	}
       
  5415 
       
  5416 	status = password_hash->set_data_length(md4.get_digest_length());
       
  5417 	if (status != eap_status_ok)
       
  5418 	{
       
  5419 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  5420 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  5421 	}
       
  5422 	
       
  5423 	status = md4.hash_final(password_hash->get_data(md4.get_digest_length()), 0);
       
  5424 
       
  5425 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  5426 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  5427 }
       
  5428 
       
  5429 //--------------------------------------------------
       
  5430 
       
  5431 EAP_FUNC_EXPORT eap_status_e crypto_nt_hash_c::hash_nt_password_hash(
       
  5432 	const eap_variable_data_c * const password_hash,
       
  5433 	eap_variable_data_c * const password_hash_hash,
       
  5434 	const u32_t digest_size)
       
  5435 {
       
  5436 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  5437 	if (!password_hash
       
  5438 	|| !password_hash_hash)
       
  5439 	{
       
  5440 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  5441 		return EAP_STATUS_RETURN(m_am_tools, eap_status_process_general_error);
       
  5442 	}
       
  5443 
       
  5444 	crypto_md4_c md4(m_am_tools);
       
  5445 
       
  5446 	eap_status_e status = md4.hash_init();
       
  5447 	if (status != eap_status_ok)
       
  5448 	{
       
  5449 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  5450 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  5451 	}
       
  5452 
       
  5453 	status = md4.hash_update(password_hash->get_data(digest_size), digest_size);
       
  5454 	if (status != eap_status_ok)
       
  5455 	{
       
  5456 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  5457 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  5458 	}
       
  5459 
       
  5460 	password_hash_hash->reset();
       
  5461 
       
  5462 	status = password_hash_hash->set_buffer_length(md4.get_digest_length());
       
  5463 	if (status != eap_status_ok)
       
  5464 	{
       
  5465 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  5466 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  5467 	}
       
  5468 
       
  5469 	status = password_hash_hash->set_data_length(md4.get_digest_length());
       
  5470 	if (status != eap_status_ok)
       
  5471 	{
       
  5472 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  5473 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  5474 	}
       
  5475 	
       
  5476 	status = md4.hash_final(password_hash_hash->get_data(md4.get_digest_length()), 0);
       
  5477 
       
  5478 	EAP_TRACE_DATA_DEBUG(
       
  5479 		m_am_tools,
       
  5480 		TRACE_FLAGS_DEFAULT,
       
  5481 		(EAPL("EAP_type_MSCHAPV2: hash_nt_password_hash(), password_hash_hash"),
       
  5482 		password_hash_hash->get_data(),
       
  5483 		password_hash_hash->get_data_length()));
       
  5484 
       
  5485 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  5486 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  5487 }
       
  5488 
       
  5489 //--------------------------------------------------
       
  5490 
       
  5491 /* RFC 3079 */
       
  5492 
       
  5493 static const u8_t eap_type_mschapv2_magic1[] = {
       
  5494 	0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74,
       
  5495 	0x68, 0x65, 0x20, 0x4d, 0x50, 0x50, 0x45, 0x20, 0x4d,
       
  5496 	0x61, 0x73, 0x74, 0x65, 0x72, 0x20, 0x4b, 0x65, 0x79 };
       
  5497 
       
  5498 EAP_FUNC_EXPORT eap_status_e crypto_nt_hash_c::get_master_key(
       
  5499 	const eap_variable_data_c * const in_password_hash_hash,
       
  5500 	const eap_variable_data_c * const in_nt_response,
       
  5501 	eap_variable_data_c * const out_master_key,
       
  5502 	const u32_t in_master_key_length)
       
  5503 {
       
  5504 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  5505 
       
  5506 	EAP_TRACE_DEBUG(
       
  5507 		m_am_tools, 
       
  5508 		TRACE_FLAGS_DEFAULT, 
       
  5509 		(EAPL("eap_type_mschapv2_c::get_master_key(): this = 0x%08x\n"),
       
  5510 		this));
       
  5511 
       
  5512 	if (in_password_hash_hash == 0
       
  5513 		|| in_password_hash_hash->get_is_valid_data() == false
       
  5514 		|| in_nt_response == 0
       
  5515 		|| in_nt_response->get_is_valid_data() == false
       
  5516 		|| out_master_key == 0
       
  5517 		|| out_master_key->get_is_valid() == false)
       
  5518 	{
       
  5519 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  5520 		return EAP_STATUS_RETURN(m_am_tools, eap_status_process_general_error);
       
  5521 	}
       
  5522 
       
  5523 	crypto_sha1_c sha1(m_am_tools);
       
  5524 
       
  5525 	eap_status_e status = sha1.hash_init();
       
  5526 	if (status != eap_status_ok)
       
  5527 	{
       
  5528 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  5529 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  5530 	}
       
  5531 
       
  5532 	status = sha1.hash_update(
       
  5533 		in_password_hash_hash->get_data(),
       
  5534 		in_password_hash_hash->get_data_length());
       
  5535 	if (status != eap_status_ok)
       
  5536 	{
       
  5537 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  5538 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  5539 	}
       
  5540 
       
  5541 	status = sha1.hash_update(
       
  5542 		in_nt_response->get_data(),
       
  5543 		in_nt_response->get_data_length());
       
  5544 	if (status != eap_status_ok)
       
  5545 	{
       
  5546 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  5547 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  5548 	}
       
  5549 
       
  5550 	status = sha1.hash_update(eap_type_mschapv2_magic1, sizeof(eap_type_mschapv2_magic1));
       
  5551 	if (status != eap_status_ok)
       
  5552 	{
       
  5553 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  5554 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  5555 	}
       
  5556 
       
  5557 	eap_variable_data_c digest(m_am_tools);
       
  5558 	if (digest.get_is_valid() == false)
       
  5559 	{
       
  5560 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  5561 		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
  5562 	}
       
  5563 	
       
  5564 	status = digest.set_buffer_length(sha1.get_digest_length());
       
  5565 	if (status != eap_status_ok)
       
  5566 	{
       
  5567 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  5568 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  5569 	}
       
  5570 
       
  5571 	status = digest.set_data_length(sha1.get_digest_length());
       
  5572 	if (status != eap_status_ok)
       
  5573 	{
       
  5574 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  5575 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  5576 	}
       
  5577 
       
  5578 	status = sha1.hash_final(
       
  5579 		digest.get_data(), 0);
       
  5580 	if (status != eap_status_ok)
       
  5581 	{
       
  5582 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  5583 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  5584 	}
       
  5585 
       
  5586 	status = out_master_key->set_copy_of_buffer(
       
  5587 		digest.get_data(in_master_key_length),
       
  5588 		in_master_key_length);
       
  5589 	if (status != eap_status_ok)
       
  5590 	{
       
  5591 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  5592 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  5593 	}
       
  5594 
       
  5595 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  5596 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  5597 }
       
  5598 
       
  5599 //--------------------------------------------------
       
  5600 
       
  5601 static const u8_t eap_type_mschapv2_magic2[] = {
       
  5602 	0x4f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x69,
       
  5603 	0x65, 0x6e, 0x74, 0x20, 0x73, 0x69, 0x64, 0x65, 0x2c, 0x20,
       
  5604 	0x74, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68,
       
  5605 	0x65, 0x20, 0x73, 0x65, 0x6e, 0x64, 0x20, 0x6b, 0x65, 0x79,
       
  5606 	0x3b, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73,
       
  5607 	0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x73, 0x69, 0x64, 0x65,
       
  5608 	0x2c, 0x20, 0x69, 0x74, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68,
       
  5609 	0x65, 0x20, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x20,
       
  5610 	0x6b, 0x65, 0x79, 0x2e };
       
  5611 
       
  5612 static const u8_t eap_type_mschapv2_magic3[] = {
       
  5613 	0x4f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x69,
       
  5614 	0x65, 0x6e, 0x74, 0x20, 0x73, 0x69, 0x64, 0x65, 0x2c, 0x20,
       
  5615 	0x74, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68,
       
  5616 	0x65, 0x20, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x20,
       
  5617 	0x6b, 0x65, 0x79, 0x3b, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68,
       
  5618 	0x65, 0x20, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x73,
       
  5619 	0x69, 0x64, 0x65, 0x2c, 0x20, 0x69, 0x74, 0x20, 0x69, 0x73,
       
  5620 	0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x65, 0x6e, 0x64, 0x20,
       
  5621 	0x6b, 0x65, 0x79, 0x2e };
       
  5622 		
       
  5623 
       
  5624 EAP_FUNC_EXPORT eap_status_e crypto_nt_hash_c::get_asymmetric_start_key(
       
  5625 	const eap_variable_data_c * const in_master_key,
       
  5626 	eap_variable_data_c * const out_session_key,
       
  5627 	const u32_t in_session_key_length,
       
  5628 	const bool in_is_send,
       
  5629 	const bool in_is_server)
       
  5630 {
       
  5631 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  5632 
       
  5633 	EAP_TRACE_DEBUG(
       
  5634 		m_am_tools, 
       
  5635 		TRACE_FLAGS_DEFAULT, 
       
  5636 		(EAPL("eap_type_mschapv2_c::get_asymmetric_start_key(): this = 0x%08x\n"),
       
  5637 		this));
       
  5638 
       
  5639 	if (in_master_key == 0
       
  5640 		|| in_master_key->get_is_valid_data() == false
       
  5641 		|| out_session_key == 0
       
  5642 		|| out_session_key->get_is_valid() == false)
       
  5643 	{
       
  5644 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  5645 		return EAP_STATUS_RETURN(m_am_tools, eap_status_process_general_error);
       
  5646 	}
       
  5647 
       
  5648 	crypto_sha1_c sha1(m_am_tools);
       
  5649 
       
  5650 	eap_status_e status = sha1.hash_init();
       
  5651 	if (status != eap_status_ok)
       
  5652 	{
       
  5653 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  5654 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  5655 	}
       
  5656 	status = sha1.hash_update(
       
  5657 		in_master_key->get_data(),
       
  5658 		in_master_key->get_data_length());
       
  5659 	if (status != eap_status_ok)
       
  5660 	{
       
  5661 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  5662 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  5663 	}
       
  5664 
       
  5665 	const u32_t padding_size = 40;
       
  5666 
       
  5667 	eap_variable_data_c padding(m_am_tools);
       
  5668 	if (padding.get_is_valid() == false)
       
  5669 	{
       
  5670 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  5671 		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
  5672 	}
       
  5673 
       
  5674 	status = padding.set_buffer_length(padding_size);
       
  5675 	if (status != eap_status_ok)
       
  5676 	{
       
  5677 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  5678 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  5679 	}
       
  5680 
       
  5681 	status = padding.set_data_length(padding_size);
       
  5682 	if (status != eap_status_ok)
       
  5683 	{
       
  5684 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  5685 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  5686 	}
       
  5687 
       
  5688 	const u32_t padding1_value = 0x00;
       
  5689 
       
  5690 	m_am_tools->memset(padding.get_data(), padding1_value, padding.get_data_length()); // padding1
       
  5691 
       
  5692 	status = sha1.hash_update(
       
  5693 		padding.get_data(),
       
  5694 		padding.get_data_length());
       
  5695 	if (status != eap_status_ok)
       
  5696 	{
       
  5697 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  5698 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  5699 	}
       
  5700 
       
  5701 	{
       
  5702 		const u8_t * magic = eap_type_mschapv2_magic2;
       
  5703 
       
  5704 		if (in_is_send == in_is_server)
       
  5705 		{
       
  5706 			magic = eap_type_mschapv2_magic3;
       
  5707 		}
       
  5708 
       
  5709 		status = sha1.hash_update(magic, sizeof(eap_type_mschapv2_magic2)); // magic2 and magic3 are both 84 bytes
       
  5710 		if (status != eap_status_ok)
       
  5711 		{
       
  5712 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  5713 			return EAP_STATUS_RETURN(m_am_tools, status);
       
  5714 		}
       
  5715 	}
       
  5716 
       
  5717 	const u32_t padding2_value = 0xf2;
       
  5718 
       
  5719 	m_am_tools->memset(padding.get_data(), padding2_value, padding.get_data_length()); // padding2
       
  5720 
       
  5721 	status = sha1.hash_update(
       
  5722 		padding.get_data(),
       
  5723 		padding.get_data_length());
       
  5724 	if (status != eap_status_ok)
       
  5725 	{
       
  5726 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  5727 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  5728 	}
       
  5729 
       
  5730 	eap_variable_data_c digest(m_am_tools);
       
  5731 	if (digest.get_is_valid() == false)
       
  5732 	{
       
  5733 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  5734 		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
  5735 	}
       
  5736 
       
  5737 	status = digest.set_buffer_length(sha1.get_digest_length());
       
  5738 	if (status != eap_status_ok)
       
  5739 	{
       
  5740 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  5741 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  5742 	}
       
  5743 
       
  5744 	status = digest.set_data_length(sha1.get_digest_length());
       
  5745 	if (status != eap_status_ok)
       
  5746 	{
       
  5747 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  5748 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  5749 	}
       
  5750 
       
  5751 	status = sha1.hash_final(digest.get_data(), 0);
       
  5752 	if (status != eap_status_ok)
       
  5753 	{
       
  5754 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  5755 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  5756 	}
       
  5757 
       
  5758 	status = out_session_key->set_copy_of_buffer(digest.get_data(in_session_key_length), in_session_key_length);
       
  5759 	if (status != eap_status_ok)
       
  5760 	{
       
  5761 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  5762 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  5763 	}
       
  5764 
       
  5765 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  5766 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  5767 }
       
  5768 
       
  5769 //--------------------------------------------------
       
  5770 
       
  5771 EAP_FUNC_EXPORT eap_status_e crypto_nt_hash_c::get_new_key_from_sha(
       
  5772 	const eap_variable_data_c * const in_start_key,
       
  5773 	const eap_variable_data_c * const in_session_key,
       
  5774 	eap_variable_data_c * const out_interim_key,
       
  5775 	const u32_t in_interim_key_length)
       
  5776 {
       
  5777 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  5778 
       
  5779 	EAP_TRACE_DEBUG(
       
  5780 		m_am_tools, 
       
  5781 		TRACE_FLAGS_DEFAULT, 
       
  5782 		(EAPL("eap_type_mschapv2_c::get_new_key_from_sha(): this = 0x%08x\n"),
       
  5783 		this));
       
  5784 
       
  5785 	if (in_start_key == 0
       
  5786 		|| in_start_key->get_is_valid_data() == false
       
  5787 		|| in_session_key == 0
       
  5788 		|| in_session_key->get_is_valid_data() == false
       
  5789 		|| out_interim_key == 0
       
  5790 		|| out_interim_key->get_is_valid() == false)
       
  5791 	{
       
  5792 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  5793 		return EAP_STATUS_RETURN(m_am_tools, eap_status_process_general_error);
       
  5794 	}
       
  5795 
       
  5796 	crypto_sha1_c sha1(m_am_tools);
       
  5797 
       
  5798 	eap_status_e status = sha1.hash_init();
       
  5799 	if (status != eap_status_ok)
       
  5800 	{
       
  5801 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  5802 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  5803 	}
       
  5804 	status = sha1.hash_update(
       
  5805 		in_start_key->get_data(),
       
  5806 		in_start_key->get_data_length());
       
  5807 	if (status != eap_status_ok)
       
  5808 	{
       
  5809 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  5810 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  5811 	}
       
  5812 
       
  5813 	const u32_t padding_size = 40;
       
  5814 
       
  5815 	eap_variable_data_c padding(m_am_tools);
       
  5816 	if (padding.get_is_valid() == false)
       
  5817 	{
       
  5818 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  5819 		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
  5820 	}
       
  5821 
       
  5822 	status = padding.set_buffer_length(padding_size);
       
  5823 	if (status != eap_status_ok)
       
  5824 	{
       
  5825 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  5826 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  5827 	}
       
  5828 
       
  5829 	status = padding.set_data_length(padding_size);
       
  5830 	if (status != eap_status_ok)
       
  5831 	{
       
  5832 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  5833 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  5834 	}
       
  5835 
       
  5836 
       
  5837 	const u32_t padding1_value = 0x00;
       
  5838 
       
  5839 	m_am_tools->memset(padding.get_data(), padding1_value, padding.get_data_length()); // padding1
       
  5840 
       
  5841 	status = sha1.hash_update(
       
  5842 		padding.get_data(),
       
  5843 		padding.get_data_length());
       
  5844 	if (status != eap_status_ok)
       
  5845 	{
       
  5846 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  5847 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  5848 	}
       
  5849 
       
  5850 	status = sha1.hash_update(
       
  5851 		in_session_key->get_data(),
       
  5852 		in_session_key->get_data_length());
       
  5853 	if (status != eap_status_ok)
       
  5854 	{
       
  5855 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  5856 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  5857 	}
       
  5858 
       
  5859 	const u32_t padding2_value = 0xf2;
       
  5860 
       
  5861 	m_am_tools->memset(padding.get_data(), padding2_value, padding.get_data_length()); // padding2
       
  5862 
       
  5863 	status = sha1.hash_update(
       
  5864 		padding.get_data(),
       
  5865 		padding.get_data_length());
       
  5866 	if (status != eap_status_ok)
       
  5867 	{
       
  5868 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  5869 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  5870 	}
       
  5871 
       
  5872 	eap_variable_data_c digest(m_am_tools);
       
  5873 	if (digest.get_is_valid() == false)
       
  5874 	{
       
  5875 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  5876 		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
  5877 	}
       
  5878 
       
  5879 	status = digest.set_buffer_length(sha1.get_digest_length());
       
  5880 	if (status != eap_status_ok)
       
  5881 	{
       
  5882 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  5883 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  5884 	}
       
  5885 
       
  5886 	status = digest.set_data_length(sha1.get_digest_length());
       
  5887 	if (status != eap_status_ok)
       
  5888 	{
       
  5889 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  5890 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  5891 	}
       
  5892 
       
  5893 	status = sha1.hash_final(digest.get_data(), 0);
       
  5894 	if (status != eap_status_ok)
       
  5895 	{
       
  5896 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  5897 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  5898 	}
       
  5899 
       
  5900 	status = out_interim_key->set_copy_of_buffer(digest.get_data(in_interim_key_length), in_interim_key_length);
       
  5901 	if (status != eap_status_ok)
       
  5902 	{
       
  5903 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  5904 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  5905 	}
       
  5906 
       
  5907 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  5908 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  5909 }
       
  5910 
       
  5911 //--------------------------------------------------
       
  5912 //--------------------------------------------------
       
  5913 //--------------------------------------------------
       
  5914 
       
  5915 void crypto_kd_hmac_sha256_c::set_is_invalid()
       
  5916 {
       
  5917 	m_is_valid = false;
       
  5918 }
       
  5919 
       
  5920 //--------------------------------------------------
       
  5921 
       
  5922 void crypto_kd_hmac_sha256_c::set_is_valid()
       
  5923 {
       
  5924 	m_is_valid = true;
       
  5925 }
       
  5926 
       
  5927 //--------------------------------------------------
       
  5928 
       
  5929 EAP_FUNC_EXPORT crypto_kd_hmac_sha256_c::~crypto_kd_hmac_sha256_c()
       
  5930 {
       
  5931 }
       
  5932 
       
  5933 //--------------------------------------------------
       
  5934 
       
  5935 EAP_FUNC_EXPORT crypto_kd_hmac_sha256_c::crypto_kd_hmac_sha256_c(abs_eap_am_tools_c * const tools)
       
  5936 	: m_am_tools(tools)
       
  5937 	, m_is_valid(false)
       
  5938 {
       
  5939 	set_is_valid();
       
  5940 }
       
  5941 
       
  5942 //--------------------------------------------------
       
  5943 
       
  5944 EAP_FUNC_EXPORT bool crypto_kd_hmac_sha256_c::get_is_valid()
       
  5945 {
       
  5946 	return m_is_valid;
       
  5947 }
       
  5948 
       
  5949 //--------------------------------------------------
       
  5950 
       
  5951 EAP_FUNC_EXPORT eap_status_e crypto_kd_hmac_sha256_c::expand_key(
       
  5952 	eap_variable_data_c * const output,
       
  5953 	const u32_t required_output_size,
       
  5954 	const eap_variable_data_c * const key,
       
  5955 	const eap_variable_data_c * const label
       
  5956 	)
       
  5957 {
       
  5958 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  5959 
       
  5960 	EAP_TRACE_DEBUG(m_am_tools, TRACE_FLAGS_DEFAULT, (EAPL("\n")));
       
  5961 	EAP_TRACE_DEBUG(
       
  5962 		m_am_tools,
       
  5963 		TRACE_FLAGS_DEFAULT,
       
  5964 		(EAPL("crypto_kd_hmac_sha256_c::expand_key()\n")));
       
  5965 
       
  5966 	output->reset();
       
  5967 
       
  5968 	crypto_sha_256_c sha_256(m_am_tools);
       
  5969 	if (sha_256.get_is_valid() == false)
       
  5970 	{
       
  5971 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  5972 		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
  5973 	}
       
  5974 
       
  5975 	crypto_hmac_c hmac_sha_256(
       
  5976 		m_am_tools,
       
  5977 		&sha_256,
       
  5978 		false);
       
  5979 	if (hmac_sha_256.get_is_valid() == false)
       
  5980 	{
       
  5981 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  5982 		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
  5983 	}
       
  5984 
       
  5985 	EAP_TRACE_DATA_DEBUG(
       
  5986 		m_am_tools,
       
  5987 		TRACE_FLAGS_DEFAULT,
       
  5988 		(EAPL("crypto_kd_hmac_sha256_c::expand_key(): key"),
       
  5989 		key->get_data(),
       
  5990 		key->get_data_length()));
       
  5991 
       
  5992 	EAP_TRACE_DATA_DEBUG(
       
  5993 		m_am_tools,
       
  5994 		TRACE_FLAGS_DEFAULT,
       
  5995 		(EAPL("crypto_kd_hmac_sha256_c::expand_key(): label"),
       
  5996 		label->get_data(),
       
  5997 		label->get_data_length()));
       
  5998 
       
  5999 	EAP_TRACE_DEBUG(
       
  6000 		m_am_tools,
       
  6001 		TRACE_FLAGS_DEFAULT,
       
  6002 		(EAPL("crypto_kd_hmac_sha256_c::expand_key(): required_output_size %d\n"),
       
  6003 		required_output_size));
       
  6004 
       
  6005 	const u32_t prf_digest_size(hmac_sha_256.get_digest_length());
       
  6006 	const u32_t iterations((required_output_size + prf_digest_size - 1) / prf_digest_size);
       
  6007 
       
  6008 	eap_status_e status = output->set_buffer_length(iterations * prf_digest_size);
       
  6009 	if (status != eap_status_ok)
       
  6010 	{
       
  6011 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  6012 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  6013 	}
       
  6014 
       
  6015 	status = output->set_data_length(iterations * prf_digest_size);
       
  6016 	if (status != eap_status_ok)
       
  6017 	{
       
  6018 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  6019 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  6020 	}
       
  6021 
       
  6022 	eap_variable_data_c input(m_am_tools);
       
  6023 	if (input.get_is_valid() == false)
       
  6024 	{
       
  6025 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  6026 		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
  6027 	}
       
  6028 
       
  6029 	status = input.set_buffer(label);
       
  6030 	if (status != eap_status_ok)
       
  6031 	{
       
  6032 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  6033 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  6034 	}
       
  6035 
       
  6036 
       
  6037 	for (u32_t ind = 0ul; ind != iterations; ++ind)
       
  6038 	{
       
  6039 		status = hmac_sha_256.hmac_set_key(key);
       
  6040 		if (status != eap_status_ok)
       
  6041 		{
       
  6042 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  6043 			return EAP_STATUS_RETURN(m_am_tools, status);
       
  6044 		}
       
  6045 
       
  6046 		status = hmac_sha_256.hmac_update(
       
  6047 			input.get_data(),
       
  6048 			input.get_data_length());
       
  6049 		if (status != eap_status_ok)
       
  6050 		{
       
  6051 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  6052 			return EAP_STATUS_RETURN(m_am_tools, status);
       
  6053 		}
       
  6054 
       
  6055 		u32_t md_length(prf_digest_size);
       
  6056 
       
  6057 		status = hmac_sha_256.hmac_final(
       
  6058 			output->get_data_offset(ind*prf_digest_size, prf_digest_size),
       
  6059 			&md_length);
       
  6060 		if (status != eap_status_ok)
       
  6061 		{
       
  6062 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  6063 			return EAP_STATUS_RETURN(m_am_tools, status);
       
  6064 		}
       
  6065 
       
  6066 		status = input.set_buffer(
       
  6067 			output->get_data_offset(ind*prf_digest_size, prf_digest_size),
       
  6068 			md_length,
       
  6069 			false,
       
  6070 			false);
       
  6071 		if (status != eap_status_ok)
       
  6072 		{
       
  6073 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  6074 			return EAP_STATUS_RETURN(m_am_tools, status);
       
  6075 		}
       
  6076 	} // for()
       
  6077 
       
  6078 	status = output->set_data_length(required_output_size);
       
  6079 	if (status != eap_status_ok)
       
  6080 	{
       
  6081 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  6082 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  6083 	}
       
  6084 
       
  6085 	EAP_TRACE_DATA_DEBUG(
       
  6086 		m_am_tools,
       
  6087 		TRACE_FLAGS_DEFAULT,
       
  6088 		(EAPL("crypto_kd_hmac_sha256_c::expand_key(): output"),
       
  6089 		output->get_data(),
       
  6090 		output->get_data_length()));
       
  6091 
       
  6092 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  6093 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  6094 }
       
  6095 
       
  6096 //--------------------------------------------------
       
  6097 // End.