eapol/eapol_framework/wapi_common/src/ec_cs_tlv.cpp
changeset 17 8840d3e38314
equal deleted inserted replaced
2:1c7bc153c08e 17:8840d3e38314
       
     1 /*
       
     2 * ============================================================================
       
     3 *  Name        : ./accesssec/eapol/eapol_framework/wapi_common/src/ec_cs_tlv.cpp
       
     4 *  Part of     : WAPI / WAPI       *** Info from the SWAD
       
     5 *  Description : WAPI authentication
       
     6 *  Version     : %version: 19 % << Don't touch! Updated by Synergy at check-out.
       
     7 *
       
     8 *  Copyright © 2001-2009 Nokia.  All rights reserved.
       
     9 *  This material, including documentation and any related computer
       
    10 *  programs, is protected by copyright controlled by Nokia.  All
       
    11 *  rights are reserved.  Copying, including reproducing, storing,
       
    12 *  adapting or translating, any or all of this material requires the
       
    13 *  prior written consent of Nokia.  This material also contains
       
    14 *  confidential information which may not be disclosed to others
       
    15 *  without the prior written consent of Nokia.
       
    16 * ============================================================================
       
    17 * Template version: 4.1.1
       
    18 */
       
    19 
       
    20 // This is enumeration of WAPI source code.
       
    21 #if defined(USE_EAP_MINIMUM_RELEASE_TRACES)
       
    22 	#undef EAP_FILE_NUMBER_ENUM
       
    23 	#define EAP_FILE_NUMBER_ENUM 706 
       
    24 	#undef EAP_FILE_NUMBER_DATE 
       
    25 	#define EAP_FILE_NUMBER_DATE 1127594498 
       
    26 #endif //#if defined(USE_EAP_MINIMUM_RELEASE_TRACES)
       
    27 
       
    28 #if defined(USE_WAPI_CORE)
       
    29 
       
    30 #include "eap_am_memory.h"
       
    31 #include "eap_crypto_api.h"
       
    32 #include "ec_cs_tlv.h"
       
    33 #include "eap_automatic_variable.h"
       
    34 #include "ec_cs_tlv_payloads.h"
       
    35 #include "ec_cs_strings.h"
       
    36 #include "ec_cs_data.h"
       
    37 
       
    38 
       
    39 /** @file */
       
    40 
       
    41 //------------------------------------------------------------------------------
       
    42 
       
    43 /**
       
    44  * The destructor of the ec_cs_tlv_c class does nothing.
       
    45  */
       
    46 ec_cs_tlv_c::~ec_cs_tlv_c()
       
    47 {
       
    48 	delete m_payloads;
       
    49 	m_payloads = 0;
       
    50 }
       
    51 
       
    52 //--------------------------------------------------
       
    53 
       
    54 /**
       
    55  * The constructor of the ec_cs_tlv_c class simply initializes the attributes.
       
    56  */
       
    57 ec_cs_tlv_c::ec_cs_tlv_c(
       
    58 	abs_eap_am_tools_c * const tools,
       
    59 	const bool true_when_is_client)
       
    60 	: m_am_tools(tools)
       
    61 	, m_payloads(0)
       
    62 	, m_is_client(true_when_is_client)
       
    63 	, m_is_valid(true)
       
    64 {
       
    65 }
       
    66 
       
    67 //--------------------------------------------------
       
    68 
       
    69 EAP_FUNC_EXPORT const ec_cs_tlv_payloads_c * ec_cs_tlv_c::get_payloads() const
       
    70 {
       
    71 	return m_payloads;
       
    72 }
       
    73 
       
    74 //--------------------------------------------------
       
    75 
       
    76 EAP_FUNC_EXPORT bool ec_cs_tlv_c::get_is_valid()
       
    77 {
       
    78 	return m_is_valid;
       
    79 }
       
    80 
       
    81 //--------------------------------------------------
       
    82 
       
    83 EAP_FUNC_EXPORT eap_status_e ec_cs_tlv_c::reset()
       
    84 {
       
    85 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
    86 
       
    87 	EAP_TRACE_DEBUG(
       
    88 		m_am_tools,
       
    89 		TRACE_FLAGS_DEFAULT,
       
    90 		(EAPL("ec_cs_tlv_c::reset()\n")));
       
    91 
       
    92 	EAP_TRACE_RETURN_STRING(m_am_tools, "returns: ec_cs_tlv_c::reset()");
       
    93 
       
    94 	if (m_payloads == 0)
       
    95 	{
       
    96 		m_payloads = new ec_cs_tlv_payloads_c(m_am_tools, m_is_client);
       
    97 
       
    98 		if (m_payloads == 0
       
    99 			|| m_payloads->get_is_valid() == false)
       
   100 		{
       
   101 			delete m_payloads;
       
   102 			m_payloads = 0;
       
   103 
       
   104 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   105 			return EAP_STATUS_RETURN(m_am_tools, eap_status_ok);
       
   106 		}
       
   107 	}
       
   108 
       
   109 	eap_status_e status = m_payloads->reset();
       
   110 
       
   111 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   112 	return EAP_STATUS_RETURN(m_am_tools, status);
       
   113 }
       
   114 
       
   115 //--------------------------------------------------
       
   116 
       
   117 EAP_FUNC_EXPORT eap_status_e ec_cs_tlv_c::generate_data_key(
       
   118 	const bool in_true_when_encryption_key,
       
   119 	const ec_cs_data_type_e in_data_type,
       
   120 	eap_variable_data_c * const out_key,
       
   121 	const eap_variable_data_c * const in_base_key,
       
   122 	const eap_variable_data_c * const in_data_reference,
       
   123 	const eap_variable_data_c * const in_CS_store_device_seed)
       
   124 {
       
   125 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   126 
       
   127 	EAP_TRACE_DEBUG(
       
   128 		m_am_tools,
       
   129 		TRACE_FLAGS_DEFAULT,
       
   130 		(EAPL("EC-CS: ec_cs_tlv_c::generate_data_key()\n")));
       
   131 
       
   132 	EAP_TRACE_RETURN_STRING(m_am_tools, "returns: ec_cs_tlv_c::generate_data_key()");
       
   133 
       
   134 	eap_status_e status(eap_status_process_general_error);
       
   135 
       
   136 	if (in_base_key == 0
       
   137 		|| in_base_key->get_is_valid_data() == false)
       
   138 	{
       
   139 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   140 		return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_parameter);
       
   141 	}
       
   142 
       
   143 	if (in_CS_store_device_seed->get_is_valid_data() == false)
       
   144 	{
       
   145 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   146 		return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_parameter);
       
   147 	}
       
   148 
       
   149 	if (out_key == 0
       
   150 		|| out_key->get_is_valid() == false)
       
   151 	{
       
   152 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   153 		return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_parameter);
       
   154 	}
       
   155 
       
   156 	// - - - - - - - - - - - - - - - - - - - - - - - -
       
   157 
       
   158 	eap_variable_data_c label(m_am_tools);
       
   159 	if (label.get_is_valid() == false)
       
   160 	{
       
   161 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   162 		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
   163 	}
       
   164 
       
   165 	if (in_true_when_encryption_key == true)
       
   166 	{
       
   167 		EAP_TRACE_DEBUG(
       
   168 			m_am_tools,
       
   169 			TRACE_FLAGS_DEFAULT,
       
   170 			(EAPL("EC-CS: ec_cs_store_c::generate_data_key(): creates encyption key\n")));
       
   171 
       
   172 		status = label.set_copy_of_buffer(EC_CS_ENCRYPTION_KEY_LABEL, EC_CS_ENCRYPTION_KEY_LABEL_SIZE);
       
   173 		if (status != eap_status_ok)
       
   174 		{
       
   175 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   176 			return EAP_STATUS_RETURN(m_am_tools, status);
       
   177 		}
       
   178 	}
       
   179 	else
       
   180 	{
       
   181 		EAP_TRACE_DEBUG(
       
   182 			m_am_tools,
       
   183 			TRACE_FLAGS_DEFAULT,
       
   184 			(EAPL("EC-CS: ec_cs_store_c::generate_data_key(): creates MAC key\n")));
       
   185 
       
   186 		status = label.set_copy_of_buffer(EC_CS_MAC_KEY_LABEL, EC_CS_MAC_KEY_LABEL_SIZE);
       
   187 		if (status != eap_status_ok)
       
   188 		{
       
   189 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   190 			return EAP_STATUS_RETURN(m_am_tools, status);
       
   191 		}
       
   192 	}
       
   193 
       
   194 	// - - - - - - - - - - - - - - - - - - - - - - - -
       
   195 
       
   196 	eap_variable_data_c seed(m_am_tools);
       
   197 	if (seed.get_is_valid() == false)
       
   198 	{
       
   199 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   200 		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
   201 	}
       
   202 
       
   203 	status = seed.set_copy_of_buffer(in_CS_store_device_seed);
       
   204 	if (status != eap_status_ok)
       
   205 	{
       
   206 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   207 		return EAP_STATUS_RETURN(m_am_tools, status);
       
   208 	}
       
   209 
       
   210 	status = seed.add_data(EC_CS_SEED_SEPARATOR, EC_CS_SEED_SEPARATOR_SIZE);
       
   211 	if (status != eap_status_ok)
       
   212 	{
       
   213 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   214 		return EAP_STATUS_RETURN(m_am_tools, status);
       
   215 	}
       
   216 
       
   217 	if (in_data_type == ec_cs_data_type_master_key)
       
   218 	{
       
   219 		EAP_TRACE_DEBUG(
       
   220 			m_am_tools,
       
   221 			TRACE_FLAGS_DEFAULT,
       
   222 			(EAPL("EC-CS: ec_cs_store_c::generate_data_key(): creates a key for master key :-)\n")));
       
   223 
       
   224 		status = seed.add_data(EC_CS_MASTER_KEY_SEED, EC_CS_MASTER_KEY_SEED_SIZE);
       
   225 		if (status != eap_status_ok)
       
   226 		{
       
   227 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   228 			return EAP_STATUS_RETURN(m_am_tools, status);
       
   229 		}
       
   230 	}
       
   231 	else if (in_data_type == ec_cs_data_type_reference_counter)
       
   232 	{
       
   233 		EAP_TRACE_DEBUG(
       
   234 			m_am_tools,
       
   235 			TRACE_FLAGS_DEFAULT,
       
   236 			(EAPL("EC-CS: ec_cs_store_c::generate_data_key(): creates reference counter key\n")));
       
   237 
       
   238 		status = seed.add_data(EC_CS_REFERENCE_COUNTER_SEED, EC_CS_REFERENCE_COUNTER_SEED_SIZE);
       
   239 		if (status != eap_status_ok)
       
   240 		{
       
   241 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   242 			return EAP_STATUS_RETURN(m_am_tools, status);
       
   243 		}
       
   244 	}
       
   245 	else if (in_data_type == ec_cs_data_type_ca_certificate_data)
       
   246 	{
       
   247 		EAP_TRACE_DEBUG(
       
   248 			m_am_tools,
       
   249 			TRACE_FLAGS_DEFAULT,
       
   250 			(EAPL("EC-CS: ec_cs_store_c::generate_data_key(): creates CA certificate data key\n")));
       
   251 
       
   252 		status = seed.add_data(EC_CS_CA_CERTIFICATE_DATA_DATA_SEED, EC_CS_CA_CERTIFICATE_DATA_DATA_SEED_SIZE);
       
   253 		if (status != eap_status_ok)
       
   254 		{
       
   255 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   256 			return EAP_STATUS_RETURN(m_am_tools, status);
       
   257 		}
       
   258 	}
       
   259 	else if (in_data_type == ec_cs_data_type_client_certificate_data)
       
   260 	{
       
   261 		EAP_TRACE_DEBUG(
       
   262 			m_am_tools,
       
   263 			TRACE_FLAGS_DEFAULT,
       
   264 			(EAPL("EC-CS: ec_cs_store_c::generate_data_key(): creates client certificate data key\n")));
       
   265 
       
   266 		status = seed.add_data(EC_CS_USER_CERTIFICATE_DATA_DATA_SEED, EC_CS_USER_CERTIFICATE_DATA_DATA_SEED_SIZE);
       
   267 		if (status != eap_status_ok)
       
   268 		{
       
   269 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   270 			return EAP_STATUS_RETURN(m_am_tools, status);
       
   271 		}
       
   272 	}
       
   273 	else if (in_data_type == ec_cs_data_type_private_key_data)
       
   274 	{
       
   275 		EAP_TRACE_DEBUG(
       
   276 			m_am_tools,
       
   277 			TRACE_FLAGS_DEFAULT,
       
   278 			(EAPL("EC-CS: ec_cs_store_c::generate_data_key(): creates private key data key\n")));
       
   279 
       
   280 		status = seed.add_data(EC_CS_PRIVATE_KEY_DATA_SEED, EC_CS_PRIVATE_KEY_DATA_SEED_SIZE);
       
   281 		if (status != eap_status_ok)
       
   282 		{
       
   283 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   284 			return EAP_STATUS_RETURN(m_am_tools, status);
       
   285 		}
       
   286 	}
       
   287 	else if (in_data_type == ec_cs_data_type_ca_asu_id)
       
   288 	{
       
   289 		EAP_TRACE_DEBUG(
       
   290 			m_am_tools,
       
   291 			TRACE_FLAGS_DEFAULT,
       
   292 			(EAPL("EC-CS: ec_cs_store_c::generate_data_key(): creates CA ASU-ID data key\n")));
       
   293 
       
   294 		status = seed.add_data(EC_CS_CA_ASU_ID_DATA_SEED, EC_CS_CA_ASU_ID_DATA_SEED_SIZE);
       
   295 		if (status != eap_status_ok)
       
   296 		{
       
   297 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   298 			return EAP_STATUS_RETURN(m_am_tools, status);
       
   299 		}
       
   300 	}
       
   301 	else if (in_data_type == ec_cs_data_type_client_asu_id)
       
   302 	{
       
   303 		EAP_TRACE_DEBUG(
       
   304 			m_am_tools,
       
   305 			TRACE_FLAGS_DEFAULT,
       
   306 			(EAPL("EC-CS: ec_cs_store_c::generate_data_key(): creates client ASU-ID data key\n")));
       
   307 
       
   308 		status = seed.add_data(EC_CS_CLIENT_ASU_ID_DATA_SEED, EC_CS_CLIENT_ASU_ID_DATA_SEED_SIZE);
       
   309 		if (status != eap_status_ok)
       
   310 		{
       
   311 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   312 			return EAP_STATUS_RETURN(m_am_tools, status);
       
   313 		}
       
   314 	}
       
   315 	else
       
   316 	{
       
   317 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   318 		return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_parameter);
       
   319 	}
       
   320 
       
   321 	status = seed.add_data(in_data_reference);
       
   322 	if (status != eap_status_ok)
       
   323 	{
       
   324 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   325 		return EAP_STATUS_RETURN(m_am_tools, status);
       
   326 	}
       
   327 
       
   328 	// - - - - - - - - - - - - - - - - - - - - - - - -
       
   329 
       
   330 	status = out_key->set_buffer_length(EC_CS_MAC_KEY_SIZE);
       
   331 	if (status != eap_status_ok)
       
   332 	{
       
   333 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   334 		return EAP_STATUS_RETURN(m_am_tools, status);
       
   335 	}
       
   336 
       
   337 	status = out_key->set_data_length(EC_CS_MAC_KEY_SIZE);
       
   338 	if (status != eap_status_ok)
       
   339 	{
       
   340 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   341 		return EAP_STATUS_RETURN(m_am_tools, status);
       
   342 	}
       
   343 
       
   344 	crypto_tls_prf_c t_prf(m_am_tools);
       
   345 
       
   346 	if (t_prf.get_is_valid() == false)
       
   347 	{
       
   348 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   349 		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
   350 	}
       
   351 
       
   352 	EAP_TRACE_DATA_DEBUG(
       
   353 		m_am_tools,
       
   354 		TRACE_FLAGS_DEFAULT,
       
   355 		(EAPL("EC CS store base key"),
       
   356 		 in_base_key->get_data(),
       
   357 		 in_base_key->get_data_length()));
       
   358 
       
   359 	EAP_TRACE_DATA_DEBUG(
       
   360 		m_am_tools,
       
   361 		TRACE_FLAGS_DEFAULT,
       
   362 		(EAPL("EC CS store device seed"),
       
   363 		 in_CS_store_device_seed->get_data(),
       
   364 		 in_CS_store_device_seed->get_data_length()));
       
   365 
       
   366 	EAP_TRACE_DATA_DEBUG(
       
   367 		m_am_tools,
       
   368 		TRACE_FLAGS_DEFAULT,
       
   369 		(EAPL("EC CS store reference"),
       
   370 		 in_data_reference->get_data(),
       
   371 		 in_data_reference->get_data_length()));
       
   372 
       
   373 	status = t_prf.tls_prf_init(
       
   374 		in_base_key,
       
   375 		&label,
       
   376 		&seed);
       
   377 
       
   378 	if (status != eap_status_ok)
       
   379 	{
       
   380 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   381 		return EAP_STATUS_RETURN(m_am_tools, status);
       
   382 	}
       
   383 
       
   384 	status = t_prf.tls_prf_output(
       
   385 		out_key->get_data(),
       
   386 		static_cast<u16_t>(out_key->get_data_length()));
       
   387 
       
   388 	if (status != eap_status_ok)
       
   389 	{
       
   390 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   391 		return EAP_STATUS_RETURN(m_am_tools, status);
       
   392 	}
       
   393 
       
   394 
       
   395 	EAP_ASSERT((EC_CS_MAC_KEY_SIZE >= EC_CS_ENCRYPTION_KEY_SIZE));
       
   396 
       
   397 	if (in_true_when_encryption_key == true)
       
   398 	{
       
   399 		status = out_key->set_data_length(EC_CS_ENCRYPTION_KEY_SIZE);
       
   400 		if (status != eap_status_ok)
       
   401 		{
       
   402 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   403 			return EAP_STATUS_RETURN(m_am_tools, status);
       
   404 		}
       
   405 	}
       
   406 
       
   407 	EAP_TRACE_DATA_DEBUG(
       
   408 		m_am_tools,
       
   409 		TRACE_FLAGS_DEFAULT,
       
   410 		(EAPL("EC CS store key"),
       
   411 		 out_key->get_data(),
       
   412 		 out_key->get_data_length()));
       
   413 
       
   414 	// - - - - - - - - - - - - - - - - - - - - - - - -
       
   415 
       
   416 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   417 	return EAP_STATUS_RETURN(m_am_tools, status);
       
   418 }
       
   419 
       
   420 //--------------------------------------------------
       
   421 
       
   422 EAP_FUNC_EXPORT eap_status_e ec_cs_tlv_c::create_tlv(
       
   423 	ec_cs_variable_data_c * const new_tlv,
       
   424 	const ec_cs_tlv_type_e type,
       
   425 	const eap_variable_data_c * const pac_attributes)
       
   426 {
       
   427 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   428 
       
   429 	EAP_TRACE_DEBUG(
       
   430 		m_am_tools,
       
   431 		TRACE_FLAGS_DEFAULT,
       
   432 		(EAPL("ec_cs_tlv_c::create_tlv()\n")));
       
   433 
       
   434 	EAP_TRACE_RETURN_STRING(m_am_tools, "returns: ec_cs_tlv_c::create_tlv()");
       
   435 
       
   436 	if (new_tlv == 0
       
   437 		|| new_tlv->get_is_valid() == false)
       
   438 	{
       
   439 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   440 		return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_parameter);
       
   441 	}
       
   442 
       
   443 	if (pac_attributes == 0
       
   444 		|| pac_attributes->get_is_valid_data() == false)
       
   445 	{
       
   446 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   447 		return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_parameter);
       
   448 	}
       
   449 
       
   450 	/*  EC CS TLV
       
   451 	 *  0                   1                   2                   3   
       
   452 	 *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 
       
   453 	 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       
   454 	 * |      TLV Type (AVP Type)      |            Length             |
       
   455 	 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       
   456 	 * |            EC CS Attributes ...                  
       
   457 	 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       
   458 	 */
       
   459 
       
   460 	eap_status_e status = new_tlv->set_copy_of_buffer(
       
   461 		type,
       
   462 		pac_attributes->get_data(),
       
   463 		pac_attributes->get_data_length());
       
   464 
       
   465 	EC_CS_TLV_TRACE_PAYLOAD("Creates EC CS TLV", (new_tlv->get_header()), m_is_client);
       
   466 
       
   467 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   468 	return EAP_STATUS_RETURN(m_am_tools, status);
       
   469 }
       
   470 
       
   471 //--------------------------------------------------
       
   472 
       
   473 EAP_FUNC_EXPORT eap_status_e ec_cs_tlv_c::create_generic_tlv(
       
   474 	ec_cs_variable_data_c * const new_tlv,
       
   475 	const ec_cs_tlv_type_e type,
       
   476 	const eap_variable_data_c * const payload)
       
   477 {
       
   478 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   479 
       
   480 	EAP_TRACE_DEBUG(
       
   481 		m_am_tools,
       
   482 		TRACE_FLAGS_DEFAULT,
       
   483 		(EAPL("ec_cs_tlv_c::create_generic_tlv()\n")));
       
   484 
       
   485 	EAP_TRACE_RETURN_STRING(m_am_tools, "returns: ec_cs_tlv_c::create_generic_tlv()");
       
   486 
       
   487 	if (new_tlv == 0
       
   488 		|| new_tlv->get_is_valid() == false)
       
   489 	{
       
   490 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   491 		return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_parameter);
       
   492 	}
       
   493 
       
   494 	/*  CS-generic TLV
       
   495 	 *  0                   1                   2                   3   
       
   496 	 *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 
       
   497 	 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       
   498 	 * |      TLV Type (AVP Type)      |            Length             |
       
   499 	 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       
   500 	 * |                                                               |
       
   501 	 * |                            Payload                            |
       
   502 	 * |                                                               |
       
   503 	 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       
   504 	 */
       
   505 
       
   506 	eap_status_e status(eap_status_ok);
       
   507 
       
   508 	if (payload != 0
       
   509 		&& payload->get_is_valid_data() == true)
       
   510 	{
       
   511 		status = new_tlv->set_copy_of_buffer(
       
   512 			type,
       
   513 			payload->get_data(),
       
   514 			payload->get_data_length());
       
   515 	}
       
   516 	else
       
   517 	{
       
   518 		status = new_tlv->set_copy_of_buffer(
       
   519 			type,
       
   520 			0,
       
   521 			0ul);
       
   522 	}
       
   523 
       
   524 	EC_CS_TLV_TRACE_PAYLOAD("Creates CS-generic TLV", (new_tlv->get_header()), m_is_client);
       
   525 
       
   526 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   527 	return EAP_STATUS_RETURN(m_am_tools, status);
       
   528 }
       
   529 
       
   530 //--------------------------------------------------
       
   531 
       
   532 EAP_FUNC_EXPORT eap_status_e ec_cs_tlv_c::create_u32_t_tlv(
       
   533 	ec_cs_variable_data_c * const new_tlv,
       
   534 	const ec_cs_tlv_type_e type,
       
   535 	const u32_t value)
       
   536 {
       
   537 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   538 
       
   539 	EAP_TRACE_DEBUG(
       
   540 		m_am_tools,
       
   541 		TRACE_FLAGS_DEFAULT,
       
   542 		(EAPL("ec_cs_tlv_c::create_u32_t_tlv(%s)\n"),
       
   543 		ec_cs_tlv_header_c::get_tlv_string(type)));
       
   544 
       
   545 	EAP_TRACE_RETURN_STRING(m_am_tools, "returns: ec_cs_tlv_c::create_u32_t_tlv()");
       
   546 
       
   547 	if (new_tlv == 0
       
   548 		|| new_tlv->get_is_valid() == false)
       
   549 	{
       
   550 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   551 		return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_parameter);
       
   552 	}
       
   553 
       
   554 	/*  CS-u32_t TLV
       
   555 	 *  0                   1                   2                   3   
       
   556 	 *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 
       
   557 	 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       
   558 	 * |      TLV Type (AVP Type)      |            Length             |
       
   559 	 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       
   560 	 * |       any 32-bit value                                        |
       
   561 	 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       
   562 	 */
       
   563 
       
   564 	u32_t network_order_value(eap_htonl(value));
       
   565 
       
   566 	eap_status_e status = new_tlv->set_copy_of_buffer(
       
   567 		type,
       
   568 		&network_order_value,
       
   569 		sizeof(network_order_value));
       
   570 
       
   571 	EC_CS_TLV_TRACE_PAYLOAD("Creates CS-32-bit TLV", (new_tlv->get_header()), m_is_client);
       
   572 
       
   573 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   574 	return EAP_STATUS_RETURN(m_am_tools, status);
       
   575 }
       
   576 
       
   577 //--------------------------------------------------
       
   578 
       
   579 EAP_FUNC_EXPORT eap_status_e ec_cs_tlv_c::create_u16_t_tlv(
       
   580 	ec_cs_variable_data_c * const new_tlv,
       
   581 	const ec_cs_tlv_type_e type,
       
   582 	const u16_t value)
       
   583 {
       
   584 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   585 
       
   586 	EAP_TRACE_DEBUG(
       
   587 		m_am_tools,
       
   588 		TRACE_FLAGS_DEFAULT,
       
   589 		(EAPL("ec_cs_tlv_c::create_u16_t_tlv(%s)\n"),
       
   590 		ec_cs_tlv_header_c::get_tlv_string(type)));
       
   591 
       
   592 	EAP_TRACE_RETURN_STRING(m_am_tools, "returns: ec_cs_tlv_c::create_u16_t_tlv()");
       
   593 
       
   594 	if (new_tlv == 0
       
   595 		|| new_tlv->get_is_valid() == false)
       
   596 	{
       
   597 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   598 		return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_parameter);
       
   599 	}
       
   600 
       
   601 	/*  CS-u16_t TLV
       
   602 	 *  0                   1                   2                   3   
       
   603 	 *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 
       
   604 	 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       
   605 	 * |      TLV Type (AVP Type)      |            Length             |
       
   606 	 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       
   607 	 * |       any 16-bit value        |
       
   608 	 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       
   609 	 */
       
   610 
       
   611 	u16_t network_order_value(eap_htons(value));
       
   612 
       
   613 	eap_status_e status = new_tlv->set_copy_of_buffer(
       
   614 		type,
       
   615 		&network_order_value,
       
   616 		sizeof(network_order_value));
       
   617 
       
   618 	EC_CS_TLV_TRACE_PAYLOAD("Creates CS-16-bit lifetime TLV", (new_tlv->get_header()), m_is_client);
       
   619 
       
   620 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   621 	return EAP_STATUS_RETURN(m_am_tools, status);
       
   622 }
       
   623 
       
   624 //--------------------------------------------------
       
   625 
       
   626 EAP_FUNC_EXPORT eap_status_e ec_cs_tlv_c::read_generic_tlv(
       
   627 	const ec_cs_variable_data_c * const tlv,
       
   628 	const ec_cs_tlv_type_e type,
       
   629 	eap_variable_data_c * const payload)
       
   630 {
       
   631 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   632 
       
   633 	EAP_TRACE_DEBUG(
       
   634 		m_am_tools,
       
   635 		TRACE_FLAGS_DEFAULT,
       
   636 		(EAPL("ec_cs_tlv_c::read_generic_tlv()\n")));
       
   637 
       
   638 	EAP_TRACE_RETURN_STRING(m_am_tools, "returns: ec_cs_tlv_c::read_generic_tlv()");
       
   639 
       
   640 	if (tlv != 0
       
   641 		&& tlv->get_type() == type
       
   642 		&& payload != 0
       
   643 		&& payload->get_is_valid() == true)
       
   644 	{
       
   645 		u8_t * type_data = tlv->get_data(sizeof(u16_t));
       
   646 		if (type_data == 0)
       
   647 		{
       
   648 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   649 			return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_payload);
       
   650 		}
       
   651 
       
   652 		eap_status_e status = payload->set_copy_of_buffer(type_data, tlv->get_data_length());
       
   653 
       
   654 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   655 		return EAP_STATUS_RETURN(m_am_tools, status);
       
   656 	}
       
   657 	else
       
   658 	{
       
   659 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   660 		return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_parameter);
       
   661 	}
       
   662 }
       
   663 
       
   664 //--------------------------------------------------
       
   665 
       
   666 EAP_FUNC_EXPORT eap_status_e ec_cs_tlv_c::read_u32_t_tlv(
       
   667 	const ec_cs_variable_data_c * const tlv,
       
   668 	const ec_cs_tlv_type_e type,
       
   669 	u32_t * const value)
       
   670 {
       
   671 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   672 
       
   673 	EAP_TRACE_DEBUG(
       
   674 		m_am_tools,
       
   675 		TRACE_FLAGS_DEFAULT,
       
   676 		(EAPL("ec_cs_tlv_c::read_u32_t_tlv()\n")));
       
   677 
       
   678 	EAP_TRACE_RETURN_STRING(m_am_tools, "returns: ec_cs_tlv_c::read_u32_t_tlv()");
       
   679 
       
   680 	if (tlv != 0
       
   681 		&& tlv->get_type() == type
       
   682 		&& value != 0)
       
   683 	{
       
   684 		u8_t * type_data = tlv->get_data(sizeof(u16_t));
       
   685 		if (type_data == 0)
       
   686 		{
       
   687 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   688 			return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_payload);
       
   689 		}
       
   690 
       
   691 		*value = eap_read_u16_t_network_order(
       
   692 			type_data,
       
   693 			sizeof(u32_t));
       
   694 
       
   695 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   696 		return EAP_STATUS_RETURN(m_am_tools, eap_status_ok);
       
   697 	}
       
   698 	else
       
   699 	{
       
   700 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   701 		return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_parameter);
       
   702 	}
       
   703 }
       
   704 
       
   705 //--------------------------------------------------
       
   706 
       
   707 EAP_FUNC_EXPORT eap_status_e ec_cs_tlv_c::read_u16_t_tlv(
       
   708 	const ec_cs_variable_data_c * const tlv,
       
   709 	const ec_cs_tlv_type_e type,
       
   710 	u16_t * const value)
       
   711 {
       
   712 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   713 
       
   714 	EAP_TRACE_DEBUG(
       
   715 		m_am_tools,
       
   716 		TRACE_FLAGS_DEFAULT,
       
   717 		(EAPL("ec_cs_tlv_c::read_u16_t_tlv()\n")));
       
   718 
       
   719 	EAP_TRACE_RETURN_STRING(m_am_tools, "returns: ec_cs_tlv_c::read_u16_t_tlv()");
       
   720 
       
   721 	if (tlv != 0
       
   722 		&& tlv->get_type() == type
       
   723 		&& value != 0)
       
   724 	{
       
   725 		u8_t * type_data = tlv->get_data(sizeof(u16_t));
       
   726 		if (type_data == 0)
       
   727 		{
       
   728 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   729 			return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_payload);
       
   730 		}
       
   731 
       
   732 		*value = eap_read_u16_t_network_order(
       
   733 			type_data,
       
   734 			sizeof(u16_t));
       
   735 
       
   736 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   737 		return EAP_STATUS_RETURN(m_am_tools, eap_status_ok);
       
   738 	}
       
   739 	else
       
   740 	{
       
   741 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   742 		return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_parameter);
       
   743 	}
       
   744 }
       
   745 
       
   746 //--------------------------------------------------
       
   747 
       
   748 EAP_FUNC_EXPORT eap_status_e ec_cs_tlv_c::create_MAC(
       
   749 	eap_variable_data_c * const MAC,
       
   750 	const eap_variable_data_c * const server_opaque_mac_key,
       
   751 	const eap_variable_data_c * const protected_data)
       
   752 {
       
   753 	crypto_sha_256_c sha256(m_am_tools);
       
   754 	crypto_hmac_c hmac(m_am_tools, &sha256, false);
       
   755 
       
   756 	eap_status_e status = hmac.hmac_set_key(
       
   757 		server_opaque_mac_key);
       
   758 	if (status != eap_status_ok)
       
   759 	{
       
   760 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   761 		return EAP_STATUS_RETURN(m_am_tools, status);
       
   762 	}
       
   763 
       
   764 	EAP_TRACE_DATA_DEBUG(
       
   765 		m_am_tools,
       
   766 		TRACE_FLAGS_DEFAULT,
       
   767 		(EAPL("EC-CS Compound MAC over data"),
       
   768 		protected_data->get_data(),
       
   769 		protected_data->get_data_length()));
       
   770 
       
   771 	status = hmac.hmac_update(
       
   772 		protected_data->get_data(),
       
   773 		protected_data->get_data_length());
       
   774 	if (status != eap_status_ok)
       
   775 	{
       
   776 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   777 		return EAP_STATUS_RETURN(m_am_tools, status);
       
   778 	}
       
   779 
       
   780 	if (MAC == 0
       
   781 		|| MAC->get_is_valid() == false)
       
   782 	{
       
   783 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   784 		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
   785 	}
       
   786 
       
   787 	status = MAC->set_buffer_length(hmac.get_digest_length());
       
   788 	if (status != eap_status_ok)
       
   789 	{
       
   790 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   791 		return EAP_STATUS_RETURN(m_am_tools, status);
       
   792 	}
       
   793 
       
   794 	status = MAC->set_data_length(hmac.get_digest_length());
       
   795 	if (status != eap_status_ok)
       
   796 	{
       
   797 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   798 		return EAP_STATUS_RETURN(m_am_tools, status);
       
   799 	}
       
   800 
       
   801 	u32_t mac_length = hmac.get_digest_length();
       
   802 
       
   803 	status = hmac.hmac_final(
       
   804 		MAC->get_data(),
       
   805 		&mac_length);
       
   806 	if (status != eap_status_ok)
       
   807 	{
       
   808 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   809 		return EAP_STATUS_RETURN(m_am_tools, status);
       
   810 	}
       
   811 	else if (mac_length != hmac.get_digest_length())
       
   812 	{
       
   813 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   814 		return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_parameter);
       
   815 	}
       
   816 
       
   817 	EAP_TRACE_DATA_DEBUG(
       
   818 		m_am_tools,
       
   819 		TRACE_FLAGS_DEFAULT,
       
   820 		(EAPL("EC-CS Compound MAC"),
       
   821 		 MAC->get_data(),
       
   822 		 hmac.get_digest_length()));
       
   823 
       
   824 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   825 	return EAP_STATUS_RETURN(m_am_tools, status);
       
   826 }
       
   827 
       
   828 //--------------------------------------------------
       
   829 
       
   830 EAP_FUNC_EXPORT eap_status_e ec_cs_tlv_c::create_encrypted_tlv(
       
   831 	const ec_cs_tlv_type_e new_tlv_type,
       
   832 	const eap_variable_data_c * const encryption_key,
       
   833 	const ec_cs_variable_data_c * const plaintext_data_tlvs,
       
   834 	ec_cs_variable_data_c * const new_tlv)
       
   835 {
       
   836 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   837 
       
   838 	EAP_TRACE_DEBUG(
       
   839 		m_am_tools,
       
   840 		TRACE_FLAGS_DEFAULT,
       
   841 		(EAPL("ec_cs_tlv_c::create_encrypted_tlv()\n")));
       
   842 
       
   843 	EAP_TRACE_RETURN_STRING(m_am_tools, "returns: ec_cs_tlv_c::create_encrypted_tlv()");
       
   844 
       
   845 	if (new_tlv == 0
       
   846 		|| new_tlv->get_is_valid() == false)
       
   847 	{
       
   848 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   849 		return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_parameter);
       
   850 	}
       
   851 
       
   852 	EC_CS_TLV_TRACE_PAYLOAD("Plain text TLV", (plaintext_data_tlvs->get_header()), m_is_client);
       
   853 
       
   854 	eap_status_e status(eap_status_process_general_error);
       
   855 
       
   856 	//----------------------------------------------------------------------
       
   857 
       
   858 	/*
       
   859 	 * EC CS Encrypted block TLV
       
   860 	 *
       
   861  	 * 0                   1                   2                   3   
       
   862 	 *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 
       
   863 	 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+    -+ -+
       
   864 	 * | Type=CS-Encrypted block TLV   |    Length=4+16+4+n+4+m        |     |  |
       
   865 	 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -+  |  |
       
   866 	 * | Type=CS-Encryption IV TLV     |          Length=16            |  |  |  | plain text
       
   867 	 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+  |  |  |
       
   868 	 * |                              IV (16 octets)                   |  |  |  |
       
   869 	 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -+  |  |
       
   870 	 * | Type=CS-Encrypted data TLV    |          Length=n+4+m         |  |  |  |
       
   871 	 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+  |  | -+
       
   872 	 * |                           data TLVs (n octets)                |  |  |  |
       
   873 	 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+  |  |  | encrypted
       
   874 	 * | Type=CS-padding TLV           |          Length=m             |  |  |  | multiple of
       
   875 	 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+  |  |  | 16 octets
       
   876 	 * |                           padding (m octets)                  |  |  |  |
       
   877 	 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -+ -+ -+
       
   878 	 */
       
   879 
       
   880 	//----------------------------------------------------------------------
       
   881 
       
   882 	crypto_aes_c aes(m_am_tools);
       
   883 	crypto_cbc_c aes_cbc(m_am_tools, &aes, false);
       
   884 
       
   885 	if (aes.get_is_valid() == false
       
   886 		|| aes_cbc.get_is_valid() == false)
       
   887 	{
       
   888 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   889 		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
   890 	}
       
   891 
       
   892 	ec_cs_variable_data_c temporary_encrypt_tlv(m_am_tools);
       
   893 	if (temporary_encrypt_tlv.get_is_valid() == false)
       
   894 	{
       
   895 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   896 		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
   897 	}
       
   898 
       
   899 	status = temporary_encrypt_tlv.set_copy_of_buffer(plaintext_data_tlvs);
       
   900 	if (status != eap_status_ok)
       
   901 	{
       
   902 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   903 		return EAP_STATUS_RETURN(m_am_tools, status);
       
   904 	}
       
   905 
       
   906 	//----------------------------------------------------------------------
       
   907 	// Create IV.
       
   908 	// IV will be added to the begin of the encypted data.
       
   909 
       
   910 	ec_cs_variable_data_c  * const IV_tlv = new ec_cs_variable_data_c(m_am_tools);
       
   911 	eap_automatic_variable_c<ec_cs_variable_data_c> automatic_IV_tlv(m_am_tools, IV_tlv);
       
   912 	if (IV_tlv == 0
       
   913 		|| IV_tlv->get_is_valid() == false)
       
   914 	{
       
   915 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   916 		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
   917 	}
       
   918 
       
   919 	{
       
   920 		eap_variable_data_c IV(m_am_tools);
       
   921 		if (IV.get_is_valid() == false)
       
   922 		{
       
   923 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   924 			return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
   925 		}
       
   926 
       
   927 		status = IV.set_buffer_length(aes_cbc.get_block_size());
       
   928 		if (status != eap_status_ok)
       
   929 		{
       
   930 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   931 			return EAP_STATUS_RETURN(m_am_tools, status);
       
   932 		}
       
   933 
       
   934 		status = IV.set_data_length(aes_cbc.get_block_size());
       
   935 		if (status != eap_status_ok)
       
   936 		{
       
   937 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   938 			return EAP_STATUS_RETURN(m_am_tools, status);
       
   939 		}
       
   940 
       
   941 		crypto_random_c rand(m_am_tools);
       
   942 		if (rand.get_is_valid() == false)
       
   943 		{
       
   944 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   945 			return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
   946 		}
       
   947 
       
   948 		status = rand.get_rand_bytes(
       
   949 			IV.get_data(),
       
   950 			IV.get_data_length());
       
   951 		if (status != eap_status_ok)
       
   952 		{
       
   953 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   954 			return EAP_STATUS_RETURN(m_am_tools, status);
       
   955 		}
       
   956 
       
   957 		status = create_generic_tlv(
       
   958 			IV_tlv,
       
   959 			ec_cs_tlv_type_CS_encryption_IV,
       
   960 			&IV);
       
   961 		if (status != eap_status_ok)
       
   962 		{
       
   963 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   964 			return EAP_STATUS_RETURN(m_am_tools, status);
       
   965 		}
       
   966 	}
       
   967 
       
   968 	//----------------------------------------------------------------------
       
   969 	// Create padding.
       
   970 
       
   971 	{
       
   972 		u32_t padding_length(
       
   973 			aes_cbc.get_block_size()
       
   974 				- ((temporary_encrypt_tlv.get_data_length() + ec_cs_tlv_header_c::get_header_length())
       
   975 					% aes_cbc.get_block_size()));
       
   976 
       
   977 		u8_t max_padding[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, };
       
   978 
       
   979 		eap_variable_data_c padding(m_am_tools);
       
   980 		if (padding.get_is_valid() == false)
       
   981 		{
       
   982 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   983 			return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
   984 		}
       
   985 
       
   986 		status = padding.set_buffer(
       
   987 			max_padding,
       
   988 			padding_length,
       
   989 			false,
       
   990 			false);
       
   991 		if (status != eap_status_ok)
       
   992 		{
       
   993 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   994 			return EAP_STATUS_RETURN(m_am_tools, status);
       
   995 		}
       
   996 
       
   997 		ec_cs_variable_data_c  * const padding_tlv = new ec_cs_variable_data_c(m_am_tools);
       
   998 		eap_automatic_variable_c<ec_cs_variable_data_c> automatic_padding_tlv(m_am_tools, padding_tlv);
       
   999 		if (padding_tlv == 0
       
  1000 			|| padding_tlv->get_is_valid() == false)
       
  1001 		{
       
  1002 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1003 			return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
  1004 		}
       
  1005 
       
  1006 		status = create_generic_tlv(
       
  1007 			padding_tlv,
       
  1008 			ec_cs_tlv_type_CS_padding,
       
  1009 			&padding);
       
  1010 
       
  1011 		// Add padding TLV to plaintext data.
       
  1012 		status = temporary_encrypt_tlv.add_data(
       
  1013 			padding_tlv->get_full_tlv_buffer()->get_data(),
       
  1014 			padding_tlv->get_full_tlv_buffer()->get_data_length());
       
  1015 		if (status != eap_status_ok)
       
  1016 		{
       
  1017 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1018 			return EAP_STATUS_RETURN(m_am_tools, status);
       
  1019 		}
       
  1020 	}
       
  1021 
       
  1022 	//----------------------------------------------------------------------
       
  1023 	// Encrypt data.
       
  1024 
       
  1025 	{
       
  1026 		status = aes_cbc.set_encryption_key(
       
  1027 			IV_tlv->get_data(IV_tlv->get_data_length()),
       
  1028 			IV_tlv->get_data_length(),
       
  1029 			encryption_key->get_data(),
       
  1030 			encryption_key->get_data_length());
       
  1031 		if (status != eap_status_ok)
       
  1032 		{
       
  1033 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1034 			return EAP_STATUS_RETURN(m_am_tools, status);
       
  1035 		}
       
  1036 
       
  1037 		// NOTE, only the data field including padding TLV is encrypted.
       
  1038 		status = aes_cbc.encrypt_data(
       
  1039 			temporary_encrypt_tlv.get_data(temporary_encrypt_tlv.get_data_length()),
       
  1040 			temporary_encrypt_tlv.get_data_length());
       
  1041 		if (status != eap_status_ok)
       
  1042 		{
       
  1043 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1044 			return EAP_STATUS_RETURN(m_am_tools, status);
       
  1045 		}
       
  1046 	}
       
  1047 
       
  1048 	//----------------------------------------------------------------------
       
  1049 	// Combine TLVs.
       
  1050 
       
  1051 	{
       
  1052 		status = create_generic_tlv(
       
  1053 			new_tlv,
       
  1054 			new_tlv_type,
       
  1055 			IV_tlv->get_full_tlv_buffer());
       
  1056 		if (status != eap_status_ok)
       
  1057 		{
       
  1058 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1059 			return EAP_STATUS_RETURN(m_am_tools, status);
       
  1060 		}
       
  1061 
       
  1062 		status = new_tlv->add_data(
       
  1063 			temporary_encrypt_tlv.get_full_tlv_buffer()->get_data(),
       
  1064 			temporary_encrypt_tlv.get_full_tlv_buffer()->get_data_length());
       
  1065 		if (status != eap_status_ok)
       
  1066 		{
       
  1067 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1068 			return EAP_STATUS_RETURN(m_am_tools, status);
       
  1069 		}
       
  1070 	}
       
  1071 
       
  1072 	//----------------------------------------------------------------------
       
  1073 
       
  1074 	EC_CS_TLV_TRACE_PAYLOAD("EC CS Encrypted block TLV", (new_tlv->get_header()), m_is_client);
       
  1075 
       
  1076 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1077 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  1078 }
       
  1079 
       
  1080 //--------------------------------------------------
       
  1081 
       
  1082 EAP_FUNC_EXPORT eap_status_e ec_cs_tlv_c::parse_encrypted_tlv(
       
  1083 	const eap_variable_data_c * const in_decryption_key,
       
  1084 	const ec_cs_variable_data_c * const in_encrypted_block_tlv,
       
  1085 	ec_cs_variable_data_c * const plain_text_tlv)
       
  1086 {
       
  1087 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1088 
       
  1089 	EAP_TRACE_DEBUG(
       
  1090 		m_am_tools,
       
  1091 		TRACE_FLAGS_DEFAULT,
       
  1092 		(EAPL("ec_cs_tlv_c::parse_encrypted_tlv()\n")));
       
  1093 
       
  1094 	EAP_TRACE_RETURN_STRING(m_am_tools, "returns: ec_cs_tlv_c::parse_encrypted_tlv()");
       
  1095 
       
  1096 	if (plain_text_tlv == 0
       
  1097 		|| plain_text_tlv->get_is_valid() == false)
       
  1098 	{
       
  1099 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1100 		return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_parameter);
       
  1101 	}
       
  1102 
       
  1103 	//----------------------------------------------------------------------
       
  1104 
       
  1105 	EC_CS_TLV_TRACE_PAYLOAD("EC CS Encrypted block TLV", (in_encrypted_block_tlv->get_header()), m_is_client);
       
  1106 
       
  1107 	/*
       
  1108 	 * EC CS Encrypted block TLV
       
  1109 	 *
       
  1110  	 * 0                   1                   2                   3   
       
  1111 	 *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 
       
  1112 	 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+    -+ -+
       
  1113 	 * | Type=CS-Encrypted block TLV   |     Length=4+16+4+n+4+m       |     |  |
       
  1114 	 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -+  |  |
       
  1115 	 * | Type=CS-Encryption IV TLV     |           Length=16           |  |  |  | plain text
       
  1116 	 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+  |  |  |
       
  1117 	 * |                              IV (16 octets)                   |  |  |  |
       
  1118 	 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -+  |  |
       
  1119 	 * | Type=CS-Encrypted data TLV    |           Length=n+4+m        |  |  |  |
       
  1120 	 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+  |  | -+
       
  1121 	 * |                           data TLVs (n octets)                |  |  |  |
       
  1122 	 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+  |  |  | encrypted
       
  1123 	 * | Type=CS-padding TLV           |           Length=m            |  |  |  | multiple of
       
  1124 	 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+  |  |  | 16 octets
       
  1125 	 * |                           padding (m octets)                  |  |  |  |
       
  1126 	 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -+ -+ -+
       
  1127 	 */
       
  1128 
       
  1129 	//----------------------------------------------------------------------
       
  1130 
       
  1131 	eap_status_e status(eap_status_process_general_error);
       
  1132 
       
  1133 	ec_cs_tlv_payloads_c * const CS_encrypted_block_payloads = new ec_cs_tlv_payloads_c(m_am_tools, m_is_client);
       
  1134 	eap_automatic_variable_c<ec_cs_tlv_payloads_c> automatic_CS_encrypted_block_payloads(m_am_tools, CS_encrypted_block_payloads);
       
  1135 	if (CS_encrypted_block_payloads == 0
       
  1136 		|| CS_encrypted_block_payloads->get_is_valid() == false)
       
  1137 	{
       
  1138 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1139 		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
  1140 	}
       
  1141 
       
  1142 	u32_t encrypted_block_payloads_length(in_encrypted_block_tlv->get_data_length());
       
  1143 	u32_t encrypted_block_payloads_padding_length(0ul);
       
  1144 
       
  1145 	status = CS_encrypted_block_payloads->parse_ec_cs_payloads(
       
  1146 		in_encrypted_block_tlv->get_data(in_encrypted_block_tlv->get_data_length()), ///< This is the start of the IV TLV and Encrypted data TLV.
       
  1147 		&encrypted_block_payloads_length, ///< This is the length of the buffer. This must match with the length of all payloads.
       
  1148 		&encrypted_block_payloads_padding_length ///< Length of possible padding is set to this variable.
       
  1149 		);
       
  1150 	if (status != eap_status_ok)
       
  1151 	{
       
  1152 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1153 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  1154 	}
       
  1155 
       
  1156 	ec_cs_variable_data_c * const IV_tlv = CS_encrypted_block_payloads->get_tlv_pointer(ec_cs_tlv_type_CS_encryption_IV);
       
  1157 
       
  1158 	if (IV_tlv == 0
       
  1159 		|| IV_tlv->get_is_valid() == false)
       
  1160 	{
       
  1161 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1162 		return EAP_STATUS_RETURN(m_am_tools, eap_status_missing_payload);
       
  1163 	}
       
  1164 
       
  1165 	ec_cs_variable_data_c * const encrypted_data_tlv = CS_encrypted_block_payloads->get_tlv_pointer(ec_cs_tlv_type_CS_encrypted_data);
       
  1166 
       
  1167 	if (encrypted_data_tlv == 0
       
  1168 		|| encrypted_data_tlv->get_is_valid() == false)
       
  1169 	{
       
  1170 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1171 		return EAP_STATUS_RETURN(m_am_tools, eap_status_missing_payload);
       
  1172 	}
       
  1173 
       
  1174 	// Decrypt EC CS Encrypted data TLV
       
  1175 
       
  1176 	crypto_aes_c aes(m_am_tools);
       
  1177 	crypto_cbc_c aes_cbc(m_am_tools, &aes, false);
       
  1178 
       
  1179 	if (aes.get_is_valid() == false
       
  1180 		|| aes_cbc.get_is_valid() == false)
       
  1181 	{
       
  1182 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1183 		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
  1184 	}
       
  1185 
       
  1186 	status = aes_cbc.set_decryption_key(
       
  1187 		IV_tlv->get_data(IV_tlv->get_data_length()),
       
  1188 		IV_tlv->get_data_length(),
       
  1189 		in_decryption_key->get_data(),
       
  1190 		in_decryption_key->get_data_length());
       
  1191 	if (status != eap_status_ok)
       
  1192 	{
       
  1193 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1194 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  1195 	}
       
  1196 
       
  1197 	status = aes_cbc.decrypt_data(
       
  1198 		encrypted_data_tlv->get_data(encrypted_data_tlv->get_data_length()),
       
  1199 		encrypted_data_tlv->get_data_length());
       
  1200 	if (status != eap_status_ok)
       
  1201 	{
       
  1202 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1203 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  1204 	}
       
  1205 
       
  1206 	status = plain_text_tlv->set_copy_of_buffer(
       
  1207 		encrypted_data_tlv->get_full_tlv_buffer()->get_data(),
       
  1208 		encrypted_data_tlv->get_full_tlv_buffer()->get_data_length());
       
  1209 
       
  1210 	EC_CS_TLV_TRACE_PAYLOAD("EC CS plain text TLV", (plain_text_tlv->get_header()), m_is_client);
       
  1211 
       
  1212 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1213 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  1214 }
       
  1215 
       
  1216 //--------------------------------------------------
       
  1217 
       
  1218 EAP_FUNC_EXPORT eap_status_e ec_cs_tlv_c::create_data_with_MAC(
       
  1219 	const eap_variable_data_c * const MAC_key,
       
  1220 	const eap_variable_data_c * const in_data,
       
  1221 	eap_variable_data_c * const out_data_tlv)
       
  1222 {
       
  1223 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1224 
       
  1225 	EAP_TRACE_DEBUG(
       
  1226 		m_am_tools,
       
  1227 		TRACE_FLAGS_DEFAULT,
       
  1228 		(EAPL("ec_cs_tlv_c::create_data_with_MAC()\n")));
       
  1229 
       
  1230 	EAP_TRACE_RETURN_STRING(m_am_tools, "returns: ec_cs_tlv_c::create_data_with_MAC()");
       
  1231 
       
  1232 	if (out_data_tlv == 0
       
  1233 		|| out_data_tlv->get_is_valid() == false)
       
  1234 	{
       
  1235 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1236 		return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_parameter);
       
  1237 	}
       
  1238 
       
  1239 	if (in_data == 0
       
  1240 		|| in_data->get_is_valid() == false)
       
  1241 	{
       
  1242 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1243 		return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_parameter);
       
  1244 	}
       
  1245 
       
  1246 
       
  1247 	eap_status_e status(eap_status_process_general_error);
       
  1248 
       
  1249 	//----------------------------------------------------------------------
       
  1250 
       
  1251 	/*
       
  1252 	 * data in EC CS store
       
  1253 	 *
       
  1254 	 *  0                   1                   2                   3   
       
  1255 	 *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 
       
  1256 	 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -+
       
  1257 	 * | Type=data TLV                 |           Length              |  |
       
  1258 	 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+  | protected
       
  1259 	 * |                             data (n octets)                   |  | by MAC
       
  1260 	 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -+
       
  1261 	 * | Type=CS-MAC TLV               |           Length=32           |  |
       
  1262 	 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+  |
       
  1263 	 * |                              MAC (32 octets)                  |  |
       
  1264 	 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -+
       
  1265 	 */
       
  1266 
       
  1267 	status = out_data_tlv->set_copy_of_buffer(in_data);
       
  1268 	if (status != eap_status_ok)
       
  1269 	{
       
  1270 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1271 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  1272 	}
       
  1273 
       
  1274 	//----------------------------------------------------------------------
       
  1275 	// Add MAC TLV.
       
  1276 
       
  1277 	ec_cs_variable_data_c  * const MAC_tlv = new ec_cs_variable_data_c(m_am_tools);
       
  1278 	eap_automatic_variable_c<ec_cs_variable_data_c> automatic_MAC_tlv(m_am_tools, MAC_tlv);
       
  1279 	if (MAC_tlv == 0
       
  1280 		|| MAC_tlv->get_is_valid() == false)
       
  1281 	{
       
  1282 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1283 		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
  1284 	}
       
  1285 
       
  1286 	{
       
  1287 		eap_variable_data_c MAC(m_am_tools);
       
  1288 
       
  1289 		status = create_MAC(
       
  1290 			&MAC,
       
  1291 			MAC_key,
       
  1292 			out_data_tlv);
       
  1293 		if (status != eap_status_ok)
       
  1294 		{
       
  1295 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1296 			return EAP_STATUS_RETURN(m_am_tools, status);
       
  1297 		}
       
  1298 
       
  1299 		status = create_generic_tlv(
       
  1300 			MAC_tlv,
       
  1301 			ec_cs_tlv_type_CS_MAC,
       
  1302 			&MAC);
       
  1303 		if (status != eap_status_ok)
       
  1304 		{
       
  1305 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1306 			return EAP_STATUS_RETURN(m_am_tools, status);
       
  1307 		}
       
  1308 
       
  1309 		EC_CS_TLV_TRACE_PAYLOAD("CS-MAC TLV", (MAC_tlv->get_header()), m_is_client);
       
  1310 
       
  1311 		status = out_data_tlv->add_data(MAC_tlv->get_full_tlv_buffer());
       
  1312 		if (status != eap_status_ok)
       
  1313 		{
       
  1314 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1315 			return EAP_STATUS_RETURN(m_am_tools, status);
       
  1316 		}
       
  1317 	}
       
  1318 
       
  1319 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1320 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  1321 }
       
  1322 
       
  1323 //--------------------------------------------------
       
  1324 
       
  1325 EAP_FUNC_EXPORT eap_status_e ec_cs_tlv_c::verify_data_with_MAC(
       
  1326 	const eap_variable_data_c * const in_base_key,
       
  1327 	const eap_variable_data_c * const in_CS_store_device_seed,
       
  1328 	const ec_cs_data_c * const in_CS_data_with_MAC)
       
  1329 {
       
  1330 	EAP_TRACE_DEBUG(
       
  1331 		m_am_tools,
       
  1332 		TRACE_FLAGS_DEFAULT,
       
  1333 		(EAPL("ec_cs_tlv_c::verify_data_with_MAC()\n")));
       
  1334 
       
  1335 	EAP_TRACE_RETURN_STRING(m_am_tools, "returns: ec_cs_tlv_c::verify_data_with_MAC()");
       
  1336 
       
  1337 	eap_status_e status(eap_status_process_general_error);
       
  1338 
       
  1339 	eap_variable_data_c MAC_key(m_am_tools);
       
  1340 	if (MAC_key.get_is_valid() == false)
       
  1341 	{
       
  1342 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1343 		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
  1344 	}
       
  1345 
       
  1346 	status = generate_data_key(
       
  1347 		false,
       
  1348 		in_CS_data_with_MAC->get_type(),
       
  1349 		&MAC_key,
       
  1350 		in_base_key,
       
  1351 		in_CS_data_with_MAC->get_reference(),
       
  1352 		in_CS_store_device_seed);
       
  1353 	if (status != eap_status_ok)
       
  1354 	{
       
  1355 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1356 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  1357 	}
       
  1358 
       
  1359 	status = parse_data_with_MAC(
       
  1360 		&MAC_key,
       
  1361 		in_CS_data_with_MAC->get_data());
       
  1362 	if (status != eap_status_ok)
       
  1363 	{
       
  1364 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1365 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  1366 	}
       
  1367 
       
  1368 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1369 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  1370 }
       
  1371 
       
  1372 //--------------------------------------------------
       
  1373 
       
  1374 EAP_FUNC_EXPORT eap_status_e ec_cs_tlv_c::parse_data_with_MAC(
       
  1375 	const eap_variable_data_c * const MAC_key,
       
  1376 	const eap_variable_data_c * const CS_data)
       
  1377 {
       
  1378 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1379 
       
  1380 	EAP_TRACE_DEBUG(
       
  1381 		m_am_tools,
       
  1382 		TRACE_FLAGS_DEFAULT,
       
  1383 		(EAPL("ec_cs_tlv_c::parse_data_with_MAC()\n")));
       
  1384 
       
  1385 	EAP_TRACE_RETURN_STRING(m_am_tools, "returns: ec_cs_tlv_c::parse_data_with_MAC()");
       
  1386 
       
  1387 	if (CS_data == 0
       
  1388 		|| CS_data->get_is_valid() == false)
       
  1389 	{
       
  1390 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1391 		return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_parameter);
       
  1392 	}
       
  1393 
       
  1394 	eap_status_e status(eap_status_process_general_error);
       
  1395 
       
  1396 	//----------------------------------------------------------------------
       
  1397 
       
  1398 	delete m_payloads;
       
  1399 	m_payloads = new ec_cs_tlv_payloads_c(m_am_tools, m_is_client);
       
  1400 
       
  1401 	if (m_payloads == 0
       
  1402 		|| m_payloads->get_is_valid() == false)
       
  1403 	{
       
  1404 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1405 		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
  1406 	}
       
  1407 
       
  1408 	u32_t encrypted_block_payloads_length(CS_data->get_data_length());
       
  1409 	u32_t encrypted_block_payloads_padding_length(0ul);
       
  1410 
       
  1411 	status = m_payloads->parse_ec_cs_payloads(
       
  1412 		CS_data->get_data(CS_data->get_data_length()), ///< This is the start of TLVs, the last one must be MAC TLV.
       
  1413 		&encrypted_block_payloads_length, ///< This is the length of the buffer. This must match with the length of all payloads.
       
  1414 		&encrypted_block_payloads_padding_length ///< Length of possible padding is set to this variable.
       
  1415 		);
       
  1416 	if (status != eap_status_ok)
       
  1417 	{
       
  1418 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1419 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  1420 	}
       
  1421 
       
  1422 	ec_cs_variable_data_c * const CS_MAC_tlv = m_payloads->get_tlv_pointer(ec_cs_tlv_type_CS_MAC);
       
  1423 
       
  1424 	if (CS_MAC_tlv == 0
       
  1425 		|| CS_MAC_tlv->get_is_valid() == false)
       
  1426 	{
       
  1427 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1428 		return EAP_STATUS_RETURN(m_am_tools, eap_status_missing_payload);
       
  1429 	}
       
  1430 
       
  1431 	{
       
  1432 		eap_variable_data_c MAC_data(m_am_tools);
       
  1433 		if (MAC_data.get_is_valid() == false)
       
  1434 		{
       
  1435 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1436 			return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
  1437 		}
       
  1438 
       
  1439 		// MAC data includes all data except MAC TLV.
       
  1440 		u32_t MAC_data_length
       
  1441 			= CS_data->get_data_length() - CS_MAC_tlv->get_full_tlv_buffer()->get_data_length();
       
  1442 
       
  1443 		status = MAC_data.set_buffer(
       
  1444 			CS_data->get_data(),
       
  1445 			MAC_data_length,
       
  1446 			false,
       
  1447 			false);
       
  1448 		if (status != eap_status_ok)
       
  1449 		{
       
  1450 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1451 			return EAP_STATUS_RETURN(m_am_tools, status);
       
  1452 		}
       
  1453 
       
  1454 		eap_variable_data_c MAC(m_am_tools);
       
  1455 		if (MAC.get_is_valid() == false)
       
  1456 		{
       
  1457 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1458 			return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
  1459 		}
       
  1460 
       
  1461 		status = create_MAC(
       
  1462 			&MAC,
       
  1463 			MAC_key,
       
  1464 			&MAC_data);
       
  1465 		if (status != eap_status_ok)
       
  1466 		{
       
  1467 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1468 			return EAP_STATUS_RETURN(m_am_tools, status);
       
  1469 		}
       
  1470 
       
  1471 		if (MAC.compare(CS_MAC_tlv->get_data(CS_MAC_tlv->get_data_length()), CS_MAC_tlv->get_data_length()) != 0)
       
  1472 		{
       
  1473 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1474 			return EAP_STATUS_RETURN(m_am_tools, eap_status_authentication_failure);
       
  1475 		}
       
  1476 	}
       
  1477 
       
  1478 	//----------------------------------------------------------------------
       
  1479 
       
  1480 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1481 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  1482 }
       
  1483 
       
  1484 //--------------------------------------------------
       
  1485 
       
  1486 EAP_FUNC_EXPORT eap_status_e ec_cs_tlv_c::create_master_key_data(
       
  1487 	const eap_variable_data_c * const in_CS_password,
       
  1488 	const eap_variable_data_c * const in_CS_store_device_seed,
       
  1489 	const eap_variable_data_c * const in_CS_master_key_or_null,
       
  1490 	const eap_variable_data_c * const in_data_reference,
       
  1491 	eap_variable_data_c * const master_key_data)
       
  1492 {
       
  1493 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1494 
       
  1495 	EAP_TRACE_DEBUG(
       
  1496 		m_am_tools,
       
  1497 		TRACE_FLAGS_DEFAULT,
       
  1498 		(EAPL("ec_cs_tlv_c::create_master_key_data()\n")));
       
  1499 
       
  1500 	EAP_TRACE_RETURN_STRING(m_am_tools, "returns: ec_cs_tlv_c::create_master_key_data()");
       
  1501 
       
  1502 	if (in_CS_password == 0
       
  1503 		|| in_CS_password->get_is_valid_data() == false)
       
  1504 	{
       
  1505 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1506 		return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_parameter);
       
  1507 	}
       
  1508 
       
  1509 	if (in_CS_store_device_seed == 0
       
  1510 		|| in_CS_store_device_seed->get_is_valid_data() == false)
       
  1511 	{
       
  1512 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1513 		return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_parameter);
       
  1514 	}
       
  1515 
       
  1516 	if (in_CS_master_key_or_null != 0
       
  1517 		&& in_CS_master_key_or_null->get_is_valid_data() == false)
       
  1518 	{
       
  1519 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1520 		return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_parameter);
       
  1521 	}
       
  1522 
       
  1523 	if (master_key_data == 0
       
  1524 		|| master_key_data->get_is_valid() == false)
       
  1525 	{
       
  1526 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1527 		return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_parameter);
       
  1528 	}
       
  1529 
       
  1530 	//----------------------------------------------------------------------
       
  1531 
       
  1532 	eap_variable_data_c master_key_encryption_key(m_am_tools);
       
  1533 	if (master_key_encryption_key.get_is_valid() == false)
       
  1534 	{
       
  1535 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1536 		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
  1537 	}
       
  1538 
       
  1539 	eap_status_e status = generate_data_key(
       
  1540 		true,
       
  1541 		ec_cs_data_type_master_key,
       
  1542 		&master_key_encryption_key,
       
  1543 		in_CS_password,
       
  1544 		in_data_reference,
       
  1545 		in_CS_store_device_seed);
       
  1546 	if (status != eap_status_ok)
       
  1547 	{
       
  1548 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1549 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  1550 	}
       
  1551 
       
  1552 	eap_variable_data_c master_key_MAC_key(m_am_tools);
       
  1553 	if (master_key_MAC_key.get_is_valid() == false)
       
  1554 	{
       
  1555 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1556 		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
  1557 	}
       
  1558 
       
  1559 	status = generate_data_key(
       
  1560 		false,
       
  1561 		ec_cs_data_type_master_key,
       
  1562 		&master_key_MAC_key,
       
  1563 		in_CS_password,
       
  1564 		in_data_reference,
       
  1565 		in_CS_store_device_seed);
       
  1566 	if (status != eap_status_ok)
       
  1567 	{
       
  1568 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1569 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  1570 	}
       
  1571 
       
  1572 
       
  1573 	ec_cs_variable_data_c encrypted_data_tlv(m_am_tools);
       
  1574 	if (encrypted_data_tlv.get_is_valid() == false)
       
  1575 	{
       
  1576 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1577 		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
  1578 	}
       
  1579 
       
  1580 	ec_cs_variable_data_c master_key_tlv(m_am_tools);
       
  1581 	if (master_key_tlv.get_is_valid() == false)
       
  1582 	{
       
  1583 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1584 		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
  1585 	}
       
  1586 
       
  1587 	eap_variable_data_c CS_master_key(m_am_tools);
       
  1588 	if (CS_master_key.get_is_valid() == false)
       
  1589 	{
       
  1590 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1591 		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
  1592 	}
       
  1593 
       
  1594 	if (in_CS_master_key_or_null == 0)
       
  1595 	{
       
  1596 		// Create a new EC CS Store Master Key.
       
  1597 		EAP_TRACE_DEBUG(
       
  1598 			m_am_tools,
       
  1599 			TRACE_FLAGS_DEFAULT,
       
  1600 			(EAPL("ec_cs_tlv_c::create_master_key_data(): Creates new master key.\n")));
       
  1601 
       
  1602 		crypto_random_c rand(m_am_tools);
       
  1603 
       
  1604 		if (rand.get_is_valid() == false)
       
  1605 		{
       
  1606 			return EAP_STATUS_RETURN(m_am_tools, status);
       
  1607 		}
       
  1608 
       
  1609 		status = CS_master_key.set_buffer_length(EC_CS_MASTER_KEY_SIZE);
       
  1610 		if (status != eap_status_ok)
       
  1611 		{
       
  1612 			return EAP_STATUS_RETURN(m_am_tools, status);
       
  1613 		}
       
  1614 
       
  1615 		status = CS_master_key.set_data_length(EC_CS_MASTER_KEY_SIZE);
       
  1616 		if (status != eap_status_ok)
       
  1617 		{
       
  1618 			return EAP_STATUS_RETURN(m_am_tools, status);
       
  1619 		}
       
  1620 
       
  1621 		status = rand.get_rand_bytes(
       
  1622 			CS_master_key.get_data(
       
  1623 				CS_master_key.get_data_length()),
       
  1624 			CS_master_key.get_data_length());
       
  1625 		if (status != eap_status_ok)
       
  1626 		{
       
  1627 			return EAP_STATUS_RETURN(m_am_tools, status);
       
  1628 		}
       
  1629 	}
       
  1630 	else
       
  1631 	{
       
  1632 		EAP_TRACE_DEBUG(
       
  1633 			m_am_tools,
       
  1634 			TRACE_FLAGS_DEFAULT,
       
  1635 			(EAPL("ec_cs_tlv_c::create_master_key_data(): Uses existing master key.\n")));
       
  1636 
       
  1637 		status = CS_master_key.set_buffer(in_CS_master_key_or_null);
       
  1638 		if (status != eap_status_ok)
       
  1639 		{
       
  1640 			return EAP_STATUS_RETURN(m_am_tools, status);
       
  1641 		}
       
  1642 	}
       
  1643 
       
  1644 	status = create_generic_tlv(
       
  1645 		&master_key_tlv,
       
  1646 		ec_cs_tlv_type_CS_master_key,
       
  1647 		&CS_master_key);
       
  1648 	if (status != eap_status_ok)
       
  1649 	{
       
  1650 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1651 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  1652 	}
       
  1653 
       
  1654 	status = create_generic_tlv(
       
  1655 		&encrypted_data_tlv,
       
  1656 		ec_cs_tlv_type_CS_encrypted_data,
       
  1657 		master_key_tlv.get_full_tlv_buffer());
       
  1658 	if (status != eap_status_ok)
       
  1659 	{
       
  1660 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1661 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  1662 	}
       
  1663 
       
  1664 	ec_cs_variable_data_c CS_encrypted_block_tlv(m_am_tools);
       
  1665 	if (CS_encrypted_block_tlv.get_is_valid() == false)
       
  1666 	{
       
  1667 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1668 		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
  1669 	}
       
  1670 
       
  1671 	status = create_encrypted_tlv(
       
  1672 		ec_cs_tlv_type_CS_encrypted_block,
       
  1673 		&master_key_encryption_key,
       
  1674 		&encrypted_data_tlv,
       
  1675 		&CS_encrypted_block_tlv);
       
  1676 	if (status != eap_status_ok)
       
  1677 	{
       
  1678 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1679 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  1680 	}
       
  1681 
       
  1682 	status = create_data_with_MAC(
       
  1683 		&master_key_MAC_key,
       
  1684 		CS_encrypted_block_tlv.get_full_tlv_buffer(),
       
  1685 		master_key_data);
       
  1686 	if (status != eap_status_ok)
       
  1687 	{
       
  1688 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1689 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  1690 	}
       
  1691 
       
  1692 	EAP_TRACE_DATA_DEBUG(
       
  1693 		m_am_tools,
       
  1694 		TRACE_FLAGS_DEFAULT,
       
  1695 		(EAPL("New Master key data"),
       
  1696 		 master_key_data->get_data(),
       
  1697 		 master_key_data->get_data_length()));
       
  1698 
       
  1699 	//----------------------------------------------------------------------
       
  1700 
       
  1701 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1702 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  1703 }
       
  1704 
       
  1705 //------------------------------------------------------------------------------
       
  1706 
       
  1707 EAP_FUNC_EXPORT eap_status_e ec_cs_tlv_c::parse_cs_tlv(
       
  1708 	const ec_cs_variable_data_c * const PAC_tlv)
       
  1709 {
       
  1710 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1711 
       
  1712 	EAP_TRACE_DEBUG(
       
  1713 		m_am_tools,
       
  1714 		TRACE_FLAGS_DEFAULT,
       
  1715 		(EAPL("ec_cs_tlv_c::parse_cs_tlv()\n")));
       
  1716 
       
  1717 	EAP_TRACE_RETURN_STRING(m_am_tools, "returns: ec_cs_tlv_c::parse_cs_tlv()");
       
  1718 
       
  1719 	if (PAC_tlv == 0
       
  1720 		|| PAC_tlv->get_is_valid_data() == false)
       
  1721 	{
       
  1722 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1723 		return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_parameter);
       
  1724 	}
       
  1725 
       
  1726 	eap_status_e status(eap_status_process_general_error);
       
  1727 
       
  1728 	status = PAC_tlv->get_header()->check_header();
       
  1729 	if (status != eap_status_ok)
       
  1730 	{
       
  1731 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1732 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  1733 	}
       
  1734 
       
  1735 	if ((PAC_tlv->get_header()->get_header_length() + PAC_tlv->get_header()->get_data_length()) > PAC_tlv->get_header()->get_header_buffer_length())
       
  1736 	{
       
  1737 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1738 		return EAP_STATUS_RETURN(m_am_tools, eap_status_header_corrupted);
       
  1739 	}
       
  1740 
       
  1741 	EC_CS_TLV_TRACE_PAYLOAD("Parse CS TLV", (PAC_tlv->get_header()), m_is_client);
       
  1742 
       
  1743 
       
  1744 	{
       
  1745 		delete m_payloads;
       
  1746 		m_payloads = 0;
       
  1747 		m_payloads = new ec_cs_tlv_payloads_c(m_am_tools, m_is_client);
       
  1748 
       
  1749 		if (m_payloads == 0
       
  1750 			|| m_payloads->get_is_valid() == false)
       
  1751 		{
       
  1752 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1753 			return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
  1754 		}
       
  1755 
       
  1756 		u32_t buffer_length(PAC_tlv->get_data_length());
       
  1757 		u32_t padding_length(0ul);
       
  1758 
       
  1759 		status = m_payloads->parse_ec_cs_payloads(
       
  1760 			PAC_tlv->get_data(PAC_tlv->get_data_length()), ///< This is the start of the message buffer.
       
  1761 			&buffer_length, ///< This is the length of the buffer. This must match with the length of all payloads.
       
  1762 			&padding_length ///< Length of possible padding is set to this variable.
       
  1763 			);
       
  1764 		if (status != eap_status_ok)
       
  1765 		{
       
  1766 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1767 			return EAP_STATUS_RETURN(m_am_tools, status);
       
  1768 		}
       
  1769 	}
       
  1770 
       
  1771 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1772 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  1773 }
       
  1774 
       
  1775 //------------------------------------------------------------------------------
       
  1776 
       
  1777 EAP_FUNC_EXPORT eap_status_e ec_cs_tlv_c::parse_encrypted_tlv_with_MAC(
       
  1778 	const ec_cs_data_type_e in_data_type,
       
  1779 	const eap_variable_data_c * const in_base_key,
       
  1780 	const eap_variable_data_c * const in_data_reference,
       
  1781 	const eap_variable_data_c * const in_CS_store_device_seed,
       
  1782 	const eap_variable_data_c * const in_data_tlv,
       
  1783 	ec_cs_variable_data_c * const out_plain_text_tlv)
       
  1784 {
       
  1785 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1786 
       
  1787 	EAP_TRACE_DEBUG(
       
  1788 		m_am_tools,
       
  1789 		TRACE_FLAGS_DEFAULT,
       
  1790 		(EAPL("ec_cs_tlv_c::parse_encrypted_tlv_with_MAC()\n")));
       
  1791 
       
  1792 	EAP_TRACE_RETURN_STRING(m_am_tools, "returns: ec_cs_tlv_c::parse_encrypted_tlv_with_MAC()");
       
  1793 
       
  1794 	EAP_TRACE_DATA_DEBUG(
       
  1795 		m_am_tools,
       
  1796 		TRACE_FLAGS_DEFAULT,
       
  1797 		(EAPL("parse_encrypted_tlv_with_MAC(): in_data_tlv"),
       
  1798 		 in_data_tlv->get_data(),
       
  1799 		 in_data_tlv->get_data_length()));
       
  1800 
       
  1801 	/*
       
  1802 	 * Encrypted data with MAC.
       
  1803 	 *
       
  1804  	 * 0                   1                   2                   3   
       
  1805 	 *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 
       
  1806 	 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -+ -+ -+
       
  1807 	 * | Type=Any pre-selected TLVs    | Length=4+l+4+16+4+n+4+m       |  |  |  |
       
  1808 	 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+  |  |M |
       
  1809 	 * |                     Any pre-selected data (l octets)          |  |  |A |
       
  1810 	 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -+  |C |
       
  1811 	 * | Type=CS-Encrypted-Block TLV   |  Length=4+16+4+n+4+m          |  |  |  | plain text
       
  1812 	 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+  |  |d |
       
  1813 	 * | Type=CS-Encryption IV TLV     |           Length=16           |  |  |a |
       
  1814 	 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+  |  |t |
       
  1815 	 * |                              IV (16 octets)                   |  |  |a |
       
  1816 	 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+  |  |  |
       
  1817 	 * | Type=CS-Encrypted data TLV    |           Length=n+4+m        |  |  |  |
       
  1818 	 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+  |  | -+
       
  1819 	 * |                          Master key TLV (n octets)            |  |  |  |
       
  1820 	 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+  |  |  | encrypted
       
  1821 	 * | Type=CS-padding TLV           |           Length=m            |  |  |  | multiple of
       
  1822 	 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+  |  |  | 16 octets
       
  1823 	 * |                           padding (m octets)                  |  |  |  |
       
  1824 	 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -+ -+ -+
       
  1825 	 * | Type=CS-MAC TLV               |           Length=32           |  |
       
  1826 	 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+  |
       
  1827 	 * |                              MAC (32 octets)                  |  |
       
  1828 	 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -+
       
  1829 	 */
       
  1830 
       
  1831 	eap_status_e status(eap_status_process_general_error);
       
  1832 
       
  1833 	// First check the MAC is correct.
       
  1834 
       
  1835 	{
       
  1836 		eap_variable_data_c MAC_key(m_am_tools);
       
  1837 		if (MAC_key.get_is_valid() == false)
       
  1838 		{
       
  1839 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1840 			return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
  1841 		}
       
  1842 
       
  1843 		status = generate_data_key(
       
  1844 			false,
       
  1845 			in_data_type,
       
  1846 			&MAC_key,
       
  1847 			in_base_key,
       
  1848 			in_data_reference,
       
  1849 			in_CS_store_device_seed);
       
  1850 		if (status != eap_status_ok)
       
  1851 		{
       
  1852 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1853 			return EAP_STATUS_RETURN(m_am_tools, status);
       
  1854 		}
       
  1855 
       
  1856 		status = parse_data_with_MAC(
       
  1857 			&MAC_key,
       
  1858 			in_data_tlv);
       
  1859 		if (status != eap_status_ok)
       
  1860 		{
       
  1861 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1862 			return EAP_STATUS_RETURN(m_am_tools, status);
       
  1863 		}
       
  1864 	}
       
  1865 
       
  1866 	const ec_cs_variable_data_c * const encrypted_block_tlv = get_payloads()->get_tlv_pointer(ec_cs_tlv_type_CS_encrypted_block);
       
  1867 	if (encrypted_block_tlv == 0)
       
  1868 	{
       
  1869 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1870 		return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_parameter);
       
  1871 	}
       
  1872 
       
  1873 	// Second, decrypt encrypted block.
       
  1874 
       
  1875 	{
       
  1876 		eap_variable_data_c decryption_key(m_am_tools);
       
  1877 		if (decryption_key.get_is_valid() == false)
       
  1878 		{
       
  1879 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1880 			return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
  1881 		}
       
  1882 
       
  1883 		status = generate_data_key(
       
  1884 			true,
       
  1885 			in_data_type,
       
  1886 			&decryption_key,
       
  1887 			in_base_key,
       
  1888 			in_data_reference,
       
  1889 			in_CS_store_device_seed);
       
  1890 		if (status != eap_status_ok)
       
  1891 		{
       
  1892 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1893 			return EAP_STATUS_RETURN(m_am_tools, status);
       
  1894 		}
       
  1895 
       
  1896 		status = parse_encrypted_tlv(
       
  1897 			&decryption_key,
       
  1898 			encrypted_block_tlv,
       
  1899 			out_plain_text_tlv);
       
  1900 	}
       
  1901 
       
  1902 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1903 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  1904 }
       
  1905 
       
  1906 //------------------------------------------------------------------------------
       
  1907 
       
  1908 EAP_FUNC_EXPORT eap_status_e ec_cs_tlv_c::create_encrypted_certificate(
       
  1909 	const ec_cs_data_type_e in_data_type,
       
  1910 	const eap_variable_data_c * const in_base_key,
       
  1911 	const eap_variable_data_c * const in_data_reference,
       
  1912 	const eap_variable_data_c * const in_CS_store_device_seed,
       
  1913 	const eap_variable_data_c * const in_certificate_reference,
       
  1914 	const ec_cs_tlv_type_e in_certificate_tlv_type,
       
  1915 	const eap_variable_data_c * const in_certificate_data,
       
  1916 	eap_variable_data_c * const out_certificate_data_block)
       
  1917 {
       
  1918 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1919 
       
  1920 	EAP_TRACE_DEBUG(
       
  1921 		m_am_tools,
       
  1922 		TRACE_FLAGS_DEFAULT,
       
  1923 		(EAPL("ec_cs_tlv_c::create_encrypted_certificate()\n")));
       
  1924 
       
  1925 	EAP_TRACE_RETURN_STRING(m_am_tools, "returns: ec_cs_tlv_c::create_encrypted_certificate()");
       
  1926 
       
  1927 	eap_status_e status(eap_status_process_general_error);
       
  1928 
       
  1929 	/**
       
  1930 	 *  0                   1                   2                   3   
       
  1931 	 *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 
       
  1932 	 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -+
       
  1933 	 * | Type=Certificate-ref. TLV     |           Length              |  |
       
  1934 	 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+  | protected
       
  1935 	 * |                    Certificate-reference                      |  | by MAC
       
  1936 	 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+  |
       
  1937 	 * | Type=CS-Encrypted-Block TLV   |           Length              |  |
       
  1938 	 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+  |
       
  1939 	 * |      CS-Encrypted block TLVs (Certificate-Data TLV) ...          |
       
  1940 	 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -+
       
  1941 	 * | Type=CS-MAC TLV               |           Length=32           |  |
       
  1942 	 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+  |
       
  1943 	 * |                           CS MAC (32 octets)                  |  |
       
  1944 	 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -+
       
  1945 	 */
       
  1946 
       
  1947 	ec_cs_variable_data_c encrypted_block_tlv(m_am_tools);
       
  1948 
       
  1949 	if (encrypted_block_tlv.get_is_valid() == false)
       
  1950 	{
       
  1951 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1952 		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
  1953 	}
       
  1954 
       
  1955 	{
       
  1956 		eap_variable_data_c encryption_key(m_am_tools);
       
  1957 		if (encryption_key.get_is_valid() == false)
       
  1958 		{
       
  1959 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1960 			return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
  1961 		}
       
  1962 
       
  1963 		status = generate_data_key(
       
  1964 			true,
       
  1965 			in_data_type,
       
  1966 			&encryption_key,
       
  1967 			in_base_key,
       
  1968 			in_data_reference,
       
  1969 			in_CS_store_device_seed);
       
  1970 		if (status != eap_status_ok)
       
  1971 		{
       
  1972 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1973 			return EAP_STATUS_RETURN(m_am_tools, status);
       
  1974 		}
       
  1975 
       
  1976 		ec_cs_variable_data_c certificate_data_tlv(m_am_tools);
       
  1977 
       
  1978 		if (certificate_data_tlv.get_is_valid() == false)
       
  1979 		{
       
  1980 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1981 			return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
  1982 		}
       
  1983 
       
  1984 		status = certificate_data_tlv.set_copy_of_buffer(
       
  1985 			in_certificate_tlv_type,
       
  1986 			in_certificate_data->get_data(),
       
  1987 			in_certificate_data->get_data_length());
       
  1988 		if (status != eap_status_ok)
       
  1989 		{
       
  1990 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1991 			return EAP_STATUS_RETURN(m_am_tools, status);
       
  1992 		}
       
  1993 
       
  1994 		ec_cs_variable_data_c plain_text_block_tlv(m_am_tools);
       
  1995 
       
  1996 		if (plain_text_block_tlv.get_is_valid() == false)
       
  1997 		{
       
  1998 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1999 			return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
  2000 		}
       
  2001 
       
  2002 		status = plain_text_block_tlv.set_copy_of_buffer(
       
  2003 			ec_cs_tlv_type_CS_encrypted_data,
       
  2004 			certificate_data_tlv.get_full_tlv_buffer()->get_data(),
       
  2005 			certificate_data_tlv.get_full_tlv_buffer()->get_data_length());
       
  2006 		if (status != eap_status_ok)
       
  2007 		{
       
  2008 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2009 			return EAP_STATUS_RETURN(m_am_tools, status);
       
  2010 		}
       
  2011 
       
  2012 		status = create_encrypted_tlv(
       
  2013 			ec_cs_tlv_type_CS_encrypted_block,
       
  2014 			&encryption_key,
       
  2015 			&plain_text_block_tlv,
       
  2016 			&encrypted_block_tlv);
       
  2017 		if (status != eap_status_ok)
       
  2018 		{
       
  2019 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2020 			return EAP_STATUS_RETURN(m_am_tools, status);
       
  2021 		}
       
  2022 	}
       
  2023 
       
  2024 	eap_variable_data_c MAC_data_buffer(m_am_tools);
       
  2025 	if (MAC_data_buffer.get_is_valid() == false)
       
  2026 	{
       
  2027 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2028 		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
  2029 	}
       
  2030 
       
  2031 	{
       
  2032 		ec_cs_variable_data_c certificate_reference_tlv(m_am_tools);
       
  2033 
       
  2034 		if (certificate_reference_tlv.get_is_valid() == false)
       
  2035 		{
       
  2036 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2037 			return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
  2038 		}
       
  2039 
       
  2040 		status = certificate_reference_tlv.set_copy_of_buffer(
       
  2041 			ec_cs_tlv_type_CS_certificate_reference,
       
  2042 			in_certificate_reference->get_data(),
       
  2043 			in_certificate_reference->get_data_length());
       
  2044 		if (status != eap_status_ok)
       
  2045 		{
       
  2046 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2047 			return EAP_STATUS_RETURN(m_am_tools, status);
       
  2048 		}
       
  2049 
       
  2050 		status = MAC_data_buffer.set_copy_of_buffer(certificate_reference_tlv.get_full_tlv_buffer());
       
  2051 		if (status != eap_status_ok)
       
  2052 		{
       
  2053 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2054 			return EAP_STATUS_RETURN(m_am_tools, status);
       
  2055 		}
       
  2056 	}
       
  2057 
       
  2058 	status = MAC_data_buffer.add_data(encrypted_block_tlv.get_full_tlv_buffer());
       
  2059 	if (status != eap_status_ok)
       
  2060 	{
       
  2061 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2062 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  2063 	}
       
  2064 
       
  2065 	{
       
  2066 		eap_variable_data_c MAC_key(m_am_tools);
       
  2067 		if (MAC_key.get_is_valid() == false)
       
  2068 		{
       
  2069 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2070 			return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
  2071 		}
       
  2072 
       
  2073 		status = generate_data_key(
       
  2074 			false,
       
  2075 			in_data_type,
       
  2076 			&MAC_key,
       
  2077 			in_base_key,
       
  2078 			in_data_reference,
       
  2079 			in_CS_store_device_seed);
       
  2080 		if (status != eap_status_ok)
       
  2081 		{
       
  2082 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2083 			return EAP_STATUS_RETURN(m_am_tools, status);
       
  2084 		}
       
  2085 
       
  2086 		status = create_data_with_MAC(
       
  2087 			&MAC_key,
       
  2088 			&MAC_data_buffer,
       
  2089 			out_certificate_data_block);
       
  2090 
       
  2091 		EAP_TRACE_DATA_DEBUG(
       
  2092 			m_am_tools,
       
  2093 			TRACE_FLAGS_DEFAULT,
       
  2094 			(EAPL("New encrypted certificate data"),
       
  2095 			 out_certificate_data_block->get_data(),
       
  2096 			 out_certificate_data_block->get_data_length()));
       
  2097 	}
       
  2098 
       
  2099 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2100 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  2101 }
       
  2102 
       
  2103 //------------------------------------------------------------------------------
       
  2104 
       
  2105 EAP_FUNC_EXPORT eap_status_e ec_cs_tlv_c::parse_encrypted_certificate(
       
  2106 	const ec_cs_data_type_e in_data_type,
       
  2107 	const eap_variable_data_c * const in_base_key,
       
  2108 	const eap_variable_data_c * const in_data_reference,
       
  2109 	const eap_variable_data_c * const in_CS_store_device_seed,
       
  2110 	const eap_variable_data_c * const in_certificate_data_block,
       
  2111 	eap_variable_data_c * const out_certificate_reference)
       
  2112 {
       
  2113 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2114 
       
  2115 	EAP_TRACE_DEBUG(
       
  2116 		m_am_tools,
       
  2117 		TRACE_FLAGS_DEFAULT,
       
  2118 		(EAPL("ec_cs_tlv_c::parse_encrypted_certificate()\n")));
       
  2119 
       
  2120 	EAP_TRACE_RETURN_STRING(m_am_tools, "returns: ec_cs_tlv_c::parse_encrypted_certificate()");
       
  2121 
       
  2122 	eap_status_e status(eap_status_process_general_error);
       
  2123 
       
  2124 	ec_cs_variable_data_c decrypted_block_tlv(m_am_tools);
       
  2125 	if (decrypted_block_tlv.get_is_valid() == false)
       
  2126 	{
       
  2127 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2128 		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
  2129 	}
       
  2130 
       
  2131 	status = parse_encrypted_tlv_with_MAC(
       
  2132 		in_data_type,
       
  2133 		in_base_key,
       
  2134 		in_data_reference,
       
  2135 		in_CS_store_device_seed,
       
  2136 		in_certificate_data_block,
       
  2137 		&decrypted_block_tlv);
       
  2138 	if (status != eap_status_ok)
       
  2139 	{
       
  2140 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2141 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  2142 	}
       
  2143 
       
  2144 	const ec_cs_variable_data_c * const certificate_reference_tlv = get_payloads()->get_tlv_pointer(ec_cs_tlv_type_CS_certificate_reference);
       
  2145 	if (certificate_reference_tlv == 0)
       
  2146 	{
       
  2147 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2148 		return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_parameter);
       
  2149 	}
       
  2150 
       
  2151 	status = out_certificate_reference->set_copy_of_buffer(certificate_reference_tlv->get_full_tlv_buffer());
       
  2152 	if (status != eap_status_ok)
       
  2153 	{
       
  2154 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2155 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  2156 	}
       
  2157 
       
  2158 	status = parse_cs_tlv(&decrypted_block_tlv);
       
  2159 	if (status != eap_status_ok)
       
  2160 	{
       
  2161 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2162 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  2163 	}
       
  2164 
       
  2165 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2166 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  2167 }
       
  2168 
       
  2169 //------------------------------------------------------------------------------
       
  2170 
       
  2171 #endif //#if defined(USE_WAPI_CORE)
       
  2172 
       
  2173 // End.