eapol/eapol_framework/eapol_common/common/asn1_der_type.cpp
changeset 0 c8830336c852
child 2 1c7bc153c08e
equal deleted inserted replaced
-1:000000000000 0:c8830336c852
       
     1 /*
       
     2 * Copyright (c) 2008 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of the License "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:  EAP and WLAN authentication protocols.
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 
       
    20 #include "asn1_der_type.h"
       
    21 #include "eap_automatic_variable.h"
       
    22 
       
    23 //--------------------------------------------------
       
    24 
       
    25 EAP_FUNC_EXPORT asn1_der_type_c::~asn1_der_type_c()
       
    26 {
       
    27 	delete m_sub_types;
       
    28 	m_sub_types = 0;
       
    29 }
       
    30 
       
    31 //--------------------------------------------------
       
    32 
       
    33 EAP_FUNC_EXPORT asn1_der_type_c::asn1_der_type_c(
       
    34 	abs_eap_am_tools_c * const tools)
       
    35 	: m_am_tools(tools)
       
    36 	, m_is_valid(false)
       
    37 	, m_index(0u)
       
    38 	, m_count_of_sub_types(0u)
       
    39 	, m_recursion(0ul)
       
    40 	, m_input_data_length(0ul)
       
    41 	, m_input_data(0)
       
    42 	, m_used_octets(0ul)
       
    43 	, m_offset_of_length_field(0ul)
       
    44 	, m_offset_of_contents_field(0ul)
       
    45 	, m_parent_type(0)
       
    46 	, m_sub_types(0)
       
    47 {
       
    48 	m_is_valid = true;
       
    49 }
       
    50 
       
    51 //--------------------------------------------------
       
    52 
       
    53 EAP_FUNC_EXPORT bool asn1_der_type_c::get_is_valid() const
       
    54 {
       
    55 	return m_is_valid;
       
    56 }
       
    57 
       
    58 //--------------------------------------------------
       
    59 
       
    60 EAP_FUNC_EXPORT u32_t asn1_der_type_c::get_index() const
       
    61 {
       
    62 	return m_index;
       
    63 }
       
    64 
       
    65 //--------------------------------------------------
       
    66 
       
    67 u32_t asn1_der_type_c::get_input_data_length() const
       
    68 {
       
    69 	return m_input_data_length;
       
    70 }
       
    71 
       
    72 //--------------------------------------------------
       
    73 
       
    74 const u8_t * asn1_der_type_c::get_input_data() const
       
    75 {
       
    76 	return m_input_data;
       
    77 }
       
    78 
       
    79 //--------------------------------------------------
       
    80 
       
    81 u16_t asn1_der_type_c::get_recursion() const
       
    82 {
       
    83 	return m_recursion;
       
    84 }
       
    85 
       
    86 //--------------------------------------------------
       
    87 
       
    88 EAP_FUNC_EXPORT eap_const_string asn1_der_type_c::get_class_string() const
       
    89 {
       
    90 
       
    91 #if defined(USE_EAP_DEBUG_TRACE)
       
    92 
       
    93 	asn1_class_e asn1_class = get_class();
       
    94 
       
    95 	if (asn1_class == asn1_class_universal)
       
    96 	{
       
    97 		return("U");
       
    98 	}
       
    99 	else if (asn1_class == asn1_class_application)
       
   100 	{
       
   101 		return("A");
       
   102 	}
       
   103 	else if (asn1_class == asn1_class_context_specific)
       
   104 	{
       
   105 		return("C");
       
   106 	}
       
   107 	else if (asn1_class == asn1_class_private)
       
   108 	{
       
   109 		return("P");
       
   110 	}
       
   111 	else
       
   112 #endif //#if defined(USE_EAP_DEBUG_TRACE)
       
   113 	{
       
   114 		return("<Unknown Class>");
       
   115 	}
       
   116 }
       
   117 
       
   118 //--------------------------------------------------
       
   119 
       
   120 EAP_FUNC_EXPORT eap_const_string asn1_der_type_c::get_pc_string() const
       
   121 {
       
   122 
       
   123 #if defined(USE_EAP_DEBUG_TRACE)
       
   124 
       
   125 	asn1_pc_e pc = get_pc();
       
   126 
       
   127 	if (pc == asn1_pc_primitive)
       
   128 	{
       
   129 		return("P");
       
   130 	}
       
   131 	else if (pc == asn1_pc_constructed)
       
   132 	{
       
   133 		return("C");
       
   134 	}
       
   135 	else
       
   136 #endif //#if defined(USE_EAP_DEBUG_TRACE)
       
   137 	{
       
   138 		return("<Unknown PC>");
       
   139 	}
       
   140 }
       
   141 
       
   142 //--------------------------------------------------
       
   143 
       
   144 EAP_FUNC_EXPORT eap_const_string asn1_der_type_c::get_tag_string() const
       
   145 {
       
   146 
       
   147 #if defined(USE_EAP_DEBUG_TRACE)
       
   148 
       
   149 	asn1_class_e asn1_class = get_class();
       
   150 	asn1_tag_e tag = get_tag();
       
   151 
       
   152 	if (asn1_class == asn1_class_context_specific)
       
   153 	{
       
   154 		static const eap_char context[][4] = { "[0]", "[1]", "[2]", "[3]", "[4]", "[5]", "[6]", "[7]", "[8]", "[9]", };
       
   155 		if (tag < (sizeof(context)/sizeof(context[0])))
       
   156 		{
       
   157 			return context[tag];
       
   158 		}
       
   159 		else
       
   160 		{
       
   161 			return("<Too big context>");
       
   162 		}
       
   163 	}
       
   164 	else
       
   165 	{
       
   166 		EAP_IF_RETURN_STRING(tag, asn1_tag_end_of_content)
       
   167 		else EAP_IF_RETURN_STRING(tag, asn1_tag_boolean)
       
   168 		else EAP_IF_RETURN_STRING(tag, asn1_tag_integer)
       
   169 		else EAP_IF_RETURN_STRING(tag, asn1_tag_bit_string)
       
   170 		else EAP_IF_RETURN_STRING(tag, asn1_tag_octet_string)
       
   171 		else EAP_IF_RETURN_STRING(tag, asn1_tag_null)
       
   172 		else EAP_IF_RETURN_STRING(tag, asn1_tag_object_identifier)
       
   173 		else EAP_IF_RETURN_STRING(tag, asn1_tag_object_descriptor)
       
   174 		else EAP_IF_RETURN_STRING(tag, asn1_tag_external)
       
   175 		else EAP_IF_RETURN_STRING(tag, asn1_tag_real)
       
   176 		else EAP_IF_RETURN_STRING(tag, asn1_tag_enumerated)
       
   177 		else EAP_IF_RETURN_STRING(tag, asn1_tag_empedded_pdv)
       
   178 		else EAP_IF_RETURN_STRING(tag, asn1_tag_utf8_string)
       
   179 		else EAP_IF_RETURN_STRING(tag, asn1_tag_relative_oid)
       
   180 		else EAP_IF_RETURN_STRING(tag, asn1_tag_unknown_14)
       
   181 		else EAP_IF_RETURN_STRING(tag, asn1_tag_unknown_15)
       
   182 		else EAP_IF_RETURN_STRING(tag, asn1_tag_sequence)
       
   183 		else EAP_IF_RETURN_STRING(tag, asn1_tag_set)
       
   184 		else EAP_IF_RETURN_STRING(tag, asn1_tag_numeric_string)
       
   185 		else EAP_IF_RETURN_STRING(tag, asn1_tag_printable_string)
       
   186 		else EAP_IF_RETURN_STRING(tag, asn1_tag_t61_string)
       
   187 		else EAP_IF_RETURN_STRING(tag, asn1_tag_videotex_string)
       
   188 		else EAP_IF_RETURN_STRING(tag, asn1_tag_ia5_string)
       
   189 		else EAP_IF_RETURN_STRING(tag, asn1_tag_utc_time)
       
   190 		else EAP_IF_RETURN_STRING(tag, asn1_tag_unknown_24)
       
   191 		else EAP_IF_RETURN_STRING(tag, asn1_tag_graphic_string)
       
   192 		else EAP_IF_RETURN_STRING(tag, asn1_tag_visible_string)
       
   193 		else EAP_IF_RETURN_STRING(tag, asn1_tag_general_string)
       
   194 		else EAP_IF_RETURN_STRING(tag, asn1_tag_universal_string)
       
   195 		else EAP_IF_RETURN_STRING(tag, asn1_tag_character_string)
       
   196 		else EAP_IF_RETURN_STRING(tag, asn1_tag_bmp_string)
       
   197 		else EAP_IF_RETURN_STRING(tag, asn1_tag_extented)
       
   198 		else EAP_IF_RETURN_STRING(tag, asn1_tag_none)
       
   199 		else
       
   200 		{
       
   201 			return("<Unknown Tag>");
       
   202 		}
       
   203 	}
       
   204 
       
   205 #else
       
   206 
       
   207 	return("<Unknown Tag>");
       
   208 
       
   209 #endif //#if defined(USE_EAP_DEBUG_TRACE)
       
   210 
       
   211 }
       
   212 
       
   213 //--------------------------------------------------
       
   214 
       
   215 #if defined(USE_EAP_DEBUG_TRACE)
       
   216 
       
   217 eap_status_e asn1_der_type_c::debug_create_prefix(const u32_t recursion, u8_t * const prefix, const u32_t max_prefix, u32_t * const prefix_length)
       
   218 {
       
   219 	if (prefix == 0)
       
   220 	{
       
   221 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   222 		return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_parameter);
       
   223 	}
       
   224 
       
   225 	u32_t offset(0ul);
       
   226 
       
   227 	for (u32_t ind = 0ul; ind < recursion; ++ind)
       
   228 	{
       
   229 		offset += m_am_tools->snprintf(
       
   230 			&prefix[offset],
       
   231 			max_prefix - offset,
       
   232 			"  |\0");
       
   233 
       
   234 		if (max_prefix <= offset)
       
   235 		{
       
   236 			break;
       
   237 		}
       
   238 	}
       
   239 
       
   240 	if (max_prefix > offset)
       
   241 	{
       
   242 		prefix[offset] = 0;
       
   243 	}
       
   244 
       
   245 	*prefix_length = offset;
       
   246 
       
   247 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   248 	return EAP_STATUS_RETURN(m_am_tools, eap_status_ok);
       
   249 }
       
   250 
       
   251 #endif //#if defined(USE_EAP_DEBUG_TRACE)
       
   252 
       
   253 //--------------------------------------------------
       
   254 
       
   255 #if defined(USE_EAP_DEBUG_TRACE)
       
   256 
       
   257 eap_status_e asn1_der_type_c::debug_header(eap_variable_data_c * const debug_buffer)
       
   258 {
       
   259 	if (debug_buffer == 0)
       
   260 	{
       
   261 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   262 		return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_parameter);
       
   263 	}
       
   264 
       
   265 	const u32_t max_data_length(m_recursion * SIZE_OF_ONE_OCTET_STRING + m_offset_of_contents_field * SIZE_OF_ONE_OCTET_STRING);
       
   266 
       
   267 	if (max_data_length > debug_buffer->get_buffer_length())
       
   268 	{
       
   269 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   270 		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
   271 	}
       
   272 
       
   273 	eap_status_e status = debug_buffer->set_data_length(max_data_length);
       
   274 	if (status != eap_status_ok)
       
   275 	{
       
   276 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   277 		return EAP_STATUS_RETURN(m_am_tools, status);
       
   278 	}
       
   279 
       
   280 	u32_t ind(0ul);
       
   281 	u32_t offset(0ul);
       
   282 
       
   283 	u8_t * const prefix = reinterpret_cast<u8_t *>(debug_buffer->get_data(max_data_length));
       
   284 
       
   285 	if (prefix == 0)
       
   286 	{
       
   287 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   288 		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
   289 	}
       
   290 
       
   291 	status = debug_create_prefix(m_recursion, prefix, max_data_length, &offset);
       
   292 	if (status != eap_status_ok)
       
   293 	{
       
   294 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   295 		return EAP_STATUS_RETURN(m_am_tools, status);
       
   296 	}
       
   297 
       
   298 	for (ind = 0ul; ind < m_offset_of_length_field && ind < m_input_data_length; ++ind)
       
   299 	{
       
   300 		offset += m_am_tools->snprintf(
       
   301 			debug_buffer->get_data_offset(offset, debug_buffer->get_data_length() - offset),
       
   302 			debug_buffer->get_data_length() - offset,
       
   303 			"%02x \0",
       
   304 			m_input_data[ind]);
       
   305 	}
       
   306 
       
   307 	for (ind = m_offset_of_length_field; ind < m_offset_of_contents_field && ind < m_input_data_length; ++ind)
       
   308 	{
       
   309 		offset += m_am_tools->snprintf(
       
   310 			debug_buffer->get_data_offset(offset, debug_buffer->get_data_length() - offset),
       
   311 			debug_buffer->get_data_length() - offset,
       
   312 			"%02x \0",
       
   313 			m_input_data[ind]);
       
   314 	}
       
   315 
       
   316 	status = debug_buffer->add_end_null();
       
   317 	if (status != eap_status_ok)
       
   318 	{
       
   319 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   320 		return EAP_STATUS_RETURN(m_am_tools, status);
       
   321 	}
       
   322 
       
   323 	eap_const_string tag_string = 0;
       
   324 	eap_char buffer[MAX_STACK_BUFFER];
       
   325 
       
   326 	if (get_class() == asn1_class_application)
       
   327 	{
       
   328 		m_am_tools->snprintf(
       
   329 			reinterpret_cast<u8_t *>(buffer),
       
   330 			MAX_STACK_BUFFER,
       
   331 			"Application[%d]\0",
       
   332 			get_tag());
       
   333 
       
   334 		tag_string = buffer;
       
   335 	}
       
   336 	else if (get_class() == asn1_class_context_specific)
       
   337 	{
       
   338 		m_am_tools->snprintf(
       
   339 			reinterpret_cast<u8_t *>(buffer),
       
   340 			MAX_STACK_BUFFER,
       
   341 			"[%d]\0",
       
   342 			get_tag());
       
   343 
       
   344 		tag_string = buffer;
       
   345 	}
       
   346 	else
       
   347 	{
       
   348 		tag_string = get_tag_string();
       
   349 	}
       
   350 
       
   351 	EAP_TRACE_DEBUG(
       
   352 		m_am_tools,
       
   353 		TRACE_FLAGS_DEFAULT,
       
   354 		(EAPL("%s # %s, %s, %s, length=0x%x=%d, this=0x%08x, index=%d\n"),
       
   355 			debug_buffer->get_data(max_data_length),
       
   356 			get_class_string(),
       
   357 			get_pc_string(),
       
   358 			tag_string,
       
   359 			get_content_length(),
       
   360 			get_content_length(),
       
   361 			this,
       
   362 			m_index));
       
   363 
       
   364 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   365 	return EAP_STATUS_RETURN(m_am_tools, status);
       
   366 }
       
   367 
       
   368 #endif //#if defined(USE_EAP_DEBUG_TRACE)
       
   369 
       
   370 //--------------------------------------------------
       
   371 
       
   372 #if defined(USE_EAP_DEBUG_TRACE)
       
   373 
       
   374 eap_status_e asn1_der_type_c::debug_content(eap_variable_data_c * const debug_buffer)
       
   375 {
       
   376 	if (debug_buffer == 0)
       
   377 	{
       
   378 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   379 		return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_parameter);
       
   380 	}
       
   381 
       
   382 	eap_status_e status(eap_status_process_general_error);
       
   383 
       
   384 	if (get_tag() == asn1_tag_object_identifier)
       
   385 	{
       
   386 		status = debug_object_identifier(debug_buffer);
       
   387 	}
       
   388 	else
       
   389 	{
       
   390 		status = debug_data(debug_buffer);
       
   391 	}
       
   392 
       
   393 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   394 	return EAP_STATUS_RETURN(m_am_tools, status);
       
   395 }
       
   396 
       
   397 #endif //#if defined(USE_EAP_DEBUG_TRACE)
       
   398 
       
   399 //--------------------------------------------------
       
   400 
       
   401 #if defined(USE_EAP_DEBUG_TRACE)
       
   402 
       
   403 eap_status_e asn1_der_type_c::debug_data(eap_variable_data_c * const debug_buffer)
       
   404 {
       
   405 	if (debug_buffer == 0)
       
   406 	{
       
   407 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   408 		return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_parameter);
       
   409 	}
       
   410 
       
   411 	const u32_t max_prefix_length((m_recursion + 1ul) * SIZE_OF_ONE_OCTET_STRING + COUNT_OF_OCTETS * SIZE_OF_ONE_OCTET_STRING + 1ul);
       
   412 	const u32_t ascii_length(COUNT_OF_OCTETS + 5ul);
       
   413 
       
   414 	if ((max_prefix_length + ascii_length) > debug_buffer->get_buffer_length())
       
   415 	{
       
   416 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   417 		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
   418 	}
       
   419 
       
   420 	eap_status_e status = debug_buffer->set_data_length(max_prefix_length + ascii_length);
       
   421 	if (status != eap_status_ok)
       
   422 	{
       
   423 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   424 		return EAP_STATUS_RETURN(m_am_tools, status);
       
   425 	}
       
   426 
       
   427 	u8_t * const prefix = reinterpret_cast<u8_t *>(debug_buffer->get_data(max_prefix_length));
       
   428 	u8_t * const ascii = reinterpret_cast<u8_t *>(debug_buffer->get_data_offset(max_prefix_length, ascii_length));
       
   429 
       
   430 	if (prefix == 0 || ascii == 0)
       
   431 	{
       
   432 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   433 		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
   434 	}
       
   435 
       
   436 	u32_t ind(0ul);
       
   437 	u32_t offset(0ul);
       
   438 
       
   439 	status = debug_create_prefix(m_recursion + 1u, prefix, max_prefix_length, &offset);
       
   440 	if (status != eap_status_ok)
       
   441 	{
       
   442 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   443 		return EAP_STATUS_RETURN(m_am_tools, status);
       
   444 	}
       
   445 
       
   446 	u32_t init_indentation_offset = offset;
       
   447 	u32_t type_data_size = get_header_length() + get_content_length();
       
   448 	u32_t data_ind(0ul);
       
   449 	u32_t ascii_ind(0ul);
       
   450 	u8_t octet(0);
       
   451 
       
   452 	for (ind = m_offset_of_contents_field; ind < type_data_size && ind < m_input_data_length; ++ind)
       
   453 	{
       
   454 		offset += m_am_tools->snprintf(
       
   455 			&prefix[offset],
       
   456 			max_prefix_length - offset,
       
   457 			"%02x \0",
       
   458 			m_input_data[ind]);
       
   459 
       
   460 		octet = m_input_data[ind];
       
   461 
       
   462 		if (octet < 0x20 || 0x7e < octet)
       
   463 		{
       
   464 			octet = '.';
       
   465 		}
       
   466 
       
   467 		m_am_tools->snprintf(
       
   468 			&ascii[ascii_ind],
       
   469 			ascii_length - ascii_ind,
       
   470 			"%c\0",
       
   471 			octet);
       
   472 
       
   473 		++data_ind;
       
   474 		++ascii_ind;
       
   475 
       
   476 		if ((ascii_ind % COUNT_OF_OCTETS) == 0)
       
   477 		{
       
   478 			prefix[offset] = 0;
       
   479 			ascii[ascii_ind] = 0;
       
   480 
       
   481 			offset = init_indentation_offset;
       
   482 			ascii_ind = 0ul;
       
   483 
       
   484 			EAP_TRACE_DEBUG(
       
   485 				m_am_tools,
       
   486 				TRACE_FLAGS_DEFAULT,
       
   487 				(EAPL("%s |%s|\n"),
       
   488 					prefix,
       
   489 					ascii));
       
   490 		}
       
   491 	} // for()
       
   492 
       
   493 	u32_t remainder(ascii_ind % COUNT_OF_OCTETS);
       
   494 
       
   495 	if (remainder > 0ul)
       
   496 	{
       
   497 		for (; ascii_ind < COUNT_OF_OCTETS; ++ascii_ind)
       
   498 		{
       
   499 			offset += m_am_tools->snprintf(
       
   500 				&prefix[offset],
       
   501 				max_prefix_length - offset,
       
   502 				"   \0");
       
   503 
       
   504 			m_am_tools->snprintf(
       
   505 				&ascii[ascii_ind],
       
   506 				ascii_length - ascii_ind,
       
   507 				" \0");
       
   508 		} // for()
       
   509 
       
   510 		prefix[offset] = 0;
       
   511 		ascii[ascii_ind] = 0;
       
   512 
       
   513 		EAP_TRACE_DEBUG(
       
   514 			m_am_tools,
       
   515 			TRACE_FLAGS_DEFAULT,
       
   516 			(EAPL("%s |%s|\n"),
       
   517 				prefix,
       
   518 				ascii));
       
   519 	}
       
   520 
       
   521 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   522 	return EAP_STATUS_RETURN(m_am_tools, status);
       
   523 }
       
   524 
       
   525 #endif //#if defined(USE_EAP_DEBUG_TRACE)
       
   526 
       
   527 //--------------------------------------------------
       
   528 
       
   529 #if defined(USE_EAP_DEBUG_TRACE)
       
   530 
       
   531 eap_status_e asn1_der_type_c::debug_object_identifier(eap_variable_data_c * const debug_buffer)
       
   532 {
       
   533 	if (debug_buffer == 0)
       
   534 	{
       
   535 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   536 		return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_parameter);
       
   537 	}
       
   538 
       
   539 	eap_status_e status(eap_status_process_general_error);
       
   540 
       
   541 	// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
       
   542 
       
   543 	status = debug_buffer->set_data_length(debug_buffer->get_buffer_length());
       
   544 	if (status != eap_status_ok)
       
   545 	{
       
   546 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   547 		return EAP_STATUS_RETURN(m_am_tools, status);
       
   548 	}
       
   549 
       
   550 	const u32_t recursion(m_recursion + 1u);
       
   551 	const u32_t max_prefix_length(recursion * SIZE_OF_ONE_OCTET_STRING + 1ul);
       
   552 
       
   553 	if (debug_buffer->get_buffer_length() < (max_prefix_length + 2ul))
       
   554 	{
       
   555 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   556 		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
   557 	}
       
   558 
       
   559 	const u32_t max_data_output_length((debug_buffer->get_buffer_length() - (max_prefix_length + 2ul))/2ul);
       
   560 	const u32_t max_plain_output_length(max_data_output_length);
       
   561 
       
   562 	u32_t prefix_length(0ul);
       
   563 
       
   564 	u8_t * const prefix = debug_buffer->get_data();
       
   565 	if (prefix == 0)
       
   566 	{
       
   567 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   568 		return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_parameter);
       
   569 	}
       
   570 
       
   571 	status = debug_create_prefix(recursion, prefix, max_prefix_length, &prefix_length);
       
   572 	if (status != eap_status_ok)
       
   573 	{
       
   574 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   575 		return EAP_STATUS_RETURN(m_am_tools, status);
       
   576 	}
       
   577 
       
   578 	u8_t * const data_output = debug_buffer->get_data_offset(max_prefix_length, max_data_output_length);
       
   579 	if (data_output == 0)
       
   580 	{
       
   581 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   582 		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
   583 	}
       
   584 	data_output[max_data_output_length-1ul] = 0;
       
   585 
       
   586 	u8_t * const plain_output = debug_buffer->get_data_offset(max_prefix_length + max_data_output_length, max_plain_output_length);
       
   587 	if (plain_output == 0)
       
   588 	{
       
   589 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   590 		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
   591 	}
       
   592 	plain_output[max_plain_output_length - 1ul] = 0;
       
   593 
       
   594 	// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
       
   595 
       
   596 	const u32_t length = get_content_length();
       
   597 	
       
   598 	if (length == 0)
       
   599 	{
       
   600 		EAP_TRACE_DEBUG(
       
   601 			m_am_tools,
       
   602 			TRACE_FLAGS_DEFAULT,
       
   603 			(EAPL("# ERROR: invalid %s, length=%d\n"),
       
   604 				get_tag_string(),
       
   605 				length));
       
   606 
       
   607 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   608 		return EAP_STATUS_RETURN(m_am_tools, eap_status_buffer_too_short);
       
   609 	}
       
   610 
       
   611 	const u8_t * const oid_data = get_content();
       
   612 
       
   613 	if (oid_data == 0)
       
   614 	{
       
   615 		EAP_TRACE_DEBUG(
       
   616 			m_am_tools,
       
   617 			TRACE_FLAGS_DEFAULT,
       
   618 			(EAPL("# ERROR: invalid %s, length=%d\n"),
       
   619 				get_tag_string(),
       
   620 				length));
       
   621 
       
   622 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   623 		return EAP_STATUS_RETURN(m_am_tools, eap_status_buffer_too_short);
       
   624 	}
       
   625 
       
   626 	u32_t offset(0ul);
       
   627 	u8_t oid_octet = oid_data[offset];
       
   628 	u32_t oid1 = oid_octet / 40;
       
   629 	u32_t oid2 = (oid_octet - oid1*40);
       
   630 
       
   631 	EAP_TRACE_DEBUG(
       
   632 		m_am_tools,
       
   633 		TRACE_FLAGS_DEFAULT,
       
   634 		(EAPL("%s%02x # = %d = 40 * %d + %d => %d.%d\n"),
       
   635 		prefix,
       
   636 		oid_octet,
       
   637 		oid_octet,
       
   638 		oid1,
       
   639 		oid2,
       
   640 		oid1,
       
   641 		oid2));
       
   642 
       
   643 	++offset;
       
   644 
       
   645 	while(offset < length)
       
   646 	{
       
   647 		u32_t oid_length(0ul);
       
   648 		u32_t data_output_offset(0ul);
       
   649 		u32_t plain_output_offset(0ul);
       
   650 		u32_t ind(0ul);
       
   651 
       
   652 		for (ind = offset; ind < length; ++ind)
       
   653 		{
       
   654 			u8_t oid_octet = oid_data[ind];
       
   655 			++oid_length;
       
   656 			if ((oid_octet & OID_HIGH_BIT) == 0)
       
   657 			{
       
   658 				break;
       
   659 			}
       
   660 		} // for()
       
   661 
       
   662 		u32_t power = oid_length - 1ul;
       
   663 		u32_t oid_value(0ul);
       
   664 
       
   665 		for (ind = offset; ind < (offset+oid_length); ++ind)
       
   666 		{
       
   667 			u8_t oid_octet = oid_data[ind];
       
   668 
       
   669 			data_output_offset += m_am_tools->snprintf(
       
   670 				&data_output[data_output_offset],
       
   671 				max_data_output_length - data_output_offset,
       
   672 				"%02x \0",
       
   673 				oid_octet);
       
   674 
       
   675 			u8_t oid = oid_octet & (~OID_HIGH_BIT);
       
   676 
       
   677 			if (ind > offset)
       
   678 			{
       
   679 				plain_output_offset += m_am_tools->snprintf(
       
   680 					&plain_output[plain_output_offset],
       
   681 					max_data_output_length - plain_output_offset,
       
   682 					" + \0");
       
   683 			}
       
   684 
       
   685 			if (power > 1ul)
       
   686 			{
       
   687 				plain_output_offset += m_am_tools->snprintf(
       
   688 					&plain_output[plain_output_offset],
       
   689 					max_data_output_length - plain_output_offset,
       
   690 					"0x%02x * 128 ^ %d\0",
       
   691 					oid,
       
   692 					power);
       
   693 			}
       
   694 			else if (power > 0ul)
       
   695 			{
       
   696 				plain_output_offset += m_am_tools->snprintf(
       
   697 					&plain_output[plain_output_offset],
       
   698 					max_data_output_length - plain_output_offset,
       
   699 					"0x%02x * 128\0",
       
   700 					oid);
       
   701 			}
       
   702 			else
       
   703 			{
       
   704 				plain_output_offset += m_am_tools->snprintf(
       
   705 					&plain_output[plain_output_offset],
       
   706 					max_data_output_length - plain_output_offset,
       
   707 					"0x%02x\0",
       
   708 					oid);
       
   709 			}
       
   710 
       
   711 			oid_value = (oid_value << 7) + oid;
       
   712 
       
   713 			--power;
       
   714 		} // for()
       
   715 
       
   716 		EAP_TRACE_DEBUG(
       
   717 			m_am_tools,
       
   718 			TRACE_FLAGS_DEFAULT,
       
   719 			(EAPL("%s%s # %s = %d\n"),
       
   720 			prefix,
       
   721 			data_output,
       
   722 			plain_output,
       
   723 			oid_value));
       
   724 
       
   725 		offset += oid_length;
       
   726 	}
       
   727 
       
   728 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   729 	return EAP_STATUS_RETURN(m_am_tools, status);
       
   730 }
       
   731 
       
   732 #endif //#if defined(USE_EAP_DEBUG_TRACE)
       
   733 
       
   734 //--------------------------------------------------
       
   735 
       
   736 eap_status_e asn1_der_type_c::initialize(
       
   737 	const u32_t length,
       
   738 	const u8_t * const data,
       
   739 	const u16_t recursion,
       
   740 	const u32_t index,
       
   741 	eap_variable_data_c * const debug_buffer)
       
   742 {
       
   743 	if (index > 0xffff)
       
   744 	{
       
   745 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   746 		return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_parameter);
       
   747 	}
       
   748 
       
   749 	m_index = static_cast<u16_t>(index);
       
   750 
       
   751 	m_recursion = recursion;
       
   752 
       
   753 	m_input_data_length = length;
       
   754 
       
   755 	if (m_input_data_length == 0)
       
   756 	{
       
   757 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   758 		return EAP_STATUS_RETURN(m_am_tools, eap_status_buffer_too_short);
       
   759 	}
       
   760 
       
   761 	m_input_data = data;
       
   762 
       
   763 	if (m_input_data == 0)
       
   764 	{
       
   765 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   766 		return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_parameter);
       
   767 	}
       
   768 	m_offset_of_length_field = get_offset_of_length_field();
       
   769 
       
   770 	if (m_offset_of_length_field > m_input_data_length
       
   771 		|| m_offset_of_length_field == 0)
       
   772 	{
       
   773 		ASN1_DEBUG_HEADER(this, debug_buffer);
       
   774 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   775 		return EAP_STATUS_RETURN(m_am_tools, eap_status_buffer_too_short);
       
   776 	}
       
   777 
       
   778 	m_offset_of_contents_field = get_offset_of_contents_field();
       
   779 
       
   780 	if (m_offset_of_contents_field > m_input_data_length
       
   781 		|| m_offset_of_contents_field == 0)
       
   782 	{
       
   783 		ASN1_DEBUG_HEADER(this, debug_buffer);
       
   784 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   785 		return EAP_STATUS_RETURN(m_am_tools, eap_status_buffer_too_short);
       
   786 	}
       
   787 
       
   788 	if ((m_offset_of_contents_field + get_content_length()) > m_input_data_length)
       
   789 	{
       
   790 		ASN1_DEBUG_HEADER(this, debug_buffer);
       
   791 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   792 		return EAP_STATUS_RETURN(m_am_tools, eap_status_buffer_too_short);
       
   793 	}
       
   794 
       
   795 	u32_t data_length = get_header_length() + get_content_length();
       
   796 
       
   797 	if (m_input_data_length >= data_length)
       
   798 	{
       
   799 		m_input_data_length = data_length;
       
   800 	}
       
   801 	else
       
   802 	{
       
   803 		ASN1_DEBUG_HEADER(this, debug_buffer);
       
   804 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   805 		return EAP_STATUS_RETURN(m_am_tools, eap_status_buffer_too_short);
       
   806 	}
       
   807 
       
   808 	add_used_octets(get_header_length());
       
   809 
       
   810 	ASN1_DEBUG_HEADER(this, debug_buffer);
       
   811 
       
   812 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   813 	return EAP_STATUS_RETURN(m_am_tools, eap_status_ok);
       
   814 }
       
   815 
       
   816 //--------------------------------------------------
       
   817 
       
   818 EAP_FUNC_EXPORT asn1_der_type_c::asn1_class_e asn1_der_type_c::get_class() const
       
   819 {
       
   820 	if (m_input_data == 0)
       
   821 	{
       
   822 		return asn1_der_type_c::asn1_class_none;
       
   823 	}
       
   824 
       
   825 	return static_cast<asn1_der_type_c::asn1_class_e>(m_input_data[0] & asn1_identifier_mask_class);
       
   826 }
       
   827 
       
   828 //--------------------------------------------------
       
   829 
       
   830 EAP_FUNC_EXPORT asn1_der_type_c::asn1_pc_e asn1_der_type_c::get_pc() const
       
   831 {
       
   832 	if (m_input_data == 0)
       
   833 	{
       
   834 		return asn1_der_type_c::asn1_pc_none;
       
   835 	}
       
   836 
       
   837 	return static_cast<asn1_der_type_c::asn1_pc_e>(m_input_data[0] & asn1_identifier_mask_pc);
       
   838 }
       
   839 
       
   840 //--------------------------------------------------
       
   841 
       
   842 EAP_FUNC_EXPORT asn1_der_type_c::asn1_tag_e asn1_der_type_c::get_tag() const
       
   843 {
       
   844 	if (m_input_data == 0)
       
   845 	{
       
   846 		return asn1_der_type_c::asn1_tag_none;
       
   847 	}
       
   848 
       
   849 	asn1_der_type_c::asn1_tag_e tag = static_cast<asn1_der_type_c::asn1_tag_e>(m_input_data[0] & asn1_identifier_mask_tag);
       
   850 
       
   851 	if (m_offset_of_length_field == asn1_identifier_const_simple_tag_size
       
   852 		&& static_cast<asn1_identifier_mask_e>(tag) != asn1_identifier_mask_tag)
       
   853 	{
       
   854 		// Simple Tag.
       
   855 		return tag;
       
   856 	}
       
   857 	else if (m_offset_of_length_field > asn1_identifier_const_simple_tag_size)
       
   858 	{
       
   859 		return asn1_der_type_c::asn1_tag_extented;
       
   860 	}
       
   861 	else
       
   862 	{
       
   863 		return asn1_der_type_c::asn1_tag_none;
       
   864 	}
       
   865 }
       
   866 
       
   867 //--------------------------------------------------
       
   868 
       
   869 EAP_FUNC_EXPORT eap_status_e asn1_der_type_c::get_extented_tag(const u8_t ** const extented_tag, u32_t * const extented_tag_size) const
       
   870 {
       
   871 	if (extented_tag == 0
       
   872 		|| extented_tag_size == 0)
       
   873 	{
       
   874 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   875 		return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_parameter);
       
   876 	}
       
   877 
       
   878 	if (get_tag() == asn1_der_type_c::asn1_tag_extented)
       
   879 	{
       
   880 		*extented_tag = m_input_data + asn1_identifier_const_simple_tag_size;
       
   881 		*extented_tag_size = m_offset_of_length_field - asn1_identifier_const_simple_tag_size;
       
   882 	}
       
   883 	else
       
   884 	{
       
   885 		*extented_tag = m_input_data;
       
   886 		*extented_tag_size = m_offset_of_length_field;
       
   887 	}
       
   888 
       
   889 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   890 	return EAP_STATUS_RETURN(m_am_tools, eap_status_ok);
       
   891 }
       
   892 
       
   893 //--------------------------------------------------
       
   894 
       
   895 u16_t asn1_der_type_c::get_offset_of_length_field()
       
   896 {
       
   897 	if (m_input_data == 0)
       
   898 	{
       
   899 		return 0ul;
       
   900 	}
       
   901 
       
   902 	asn1_der_type_c::asn1_tag_e tag = static_cast<asn1_der_type_c::asn1_tag_e>(m_input_data[0] & asn1_identifier_mask_tag);
       
   903 
       
   904 	if (static_cast<asn1_identifier_mask_e>(tag) != asn1_identifier_mask_tag)
       
   905 	{
       
   906 		// Simple Tag.
       
   907 		return asn1_identifier_const_simple_tag_size;
       
   908 	}
       
   909 	else if (m_input_data_length > asn1_identifier_const_simple_tag_size)
       
   910 	{
       
   911 		const u8_t * extented_tag = &(m_input_data[1]);
       
   912 		if (extented_tag == 0)
       
   913 		{
       
   914 			return 0ul;
       
   915 		}
       
   916 
       
   917 		const u8_t * const end_byte = &(m_input_data[m_input_data_length]);
       
   918 		if (end_byte == 0)
       
   919 		{
       
   920 			return 0ul;
       
   921 		}
       
   922 
       
   923 		while (extented_tag < end_byte)
       
   924 		{
       
   925 			if ((extented_tag[0] & static_cast<u8_t>(asn1_high_bit_mask_tag)) == 0)
       
   926 			{
       
   927 				return (extented_tag - m_input_data);
       
   928 			}
       
   929 
       
   930 			++extented_tag;
       
   931 		}
       
   932 	}
       
   933 
       
   934 	// Illegal data.
       
   935 	return 0ul;
       
   936 }
       
   937 
       
   938 //--------------------------------------------------
       
   939 
       
   940 u16_t asn1_der_type_c::get_offset_of_contents_field()
       
   941 {
       
   942 	if (m_input_data == 0)
       
   943 	{
       
   944 		return 0ul;
       
   945 	}
       
   946 
       
   947 	if (m_offset_of_length_field < asn1_identifier_const_simple_tag_size
       
   948 		|| m_offset_of_length_field > m_input_data_length)
       
   949 	{
       
   950 		return 0ul;
       
   951 	}
       
   952 
       
   953 	const u8_t length_octet1 = m_input_data[m_offset_of_length_field];
       
   954 
       
   955 	if ((length_octet1 & static_cast<u8_t>(asn1_high_bit_mask_tag)) == 0)
       
   956 	{
       
   957 		// Short Length field.
       
   958 		return m_offset_of_length_field + asn1_identifier_const_short_length_size;
       
   959 	}
       
   960 	else if (m_input_data_length > static_cast<u32_t>(m_offset_of_length_field + asn1_identifier_const_short_length_size))
       
   961 	{
       
   962 		const u8_t * extented_length = &(m_input_data[m_offset_of_length_field]);
       
   963 		if (extented_length == 0)
       
   964 		{
       
   965 			return 0ul;
       
   966 		}
       
   967 
       
   968 		u16_t count_of_length_octets = static_cast<u16_t>((*extented_length) & static_cast<u8_t>(~asn1_high_bit_mask_tag));
       
   969 
       
   970 		u16_t offset(static_cast<u16_t>(m_offset_of_length_field + asn1_identifier_const_short_length_size + count_of_length_octets));
       
   971 
       
   972 		if (offset > m_input_data_length)
       
   973 		{
       
   974 			// Illegal data.
       
   975 			return 0ul;
       
   976 		}
       
   977 
       
   978 		return offset;
       
   979 	}
       
   980 
       
   981 	// Illegal data.
       
   982 	return 0ul;
       
   983 }
       
   984 
       
   985 //--------------------------------------------------
       
   986 
       
   987 EAP_FUNC_EXPORT u32_t asn1_der_type_c::get_header_length() const
       
   988 {
       
   989 	return m_offset_of_contents_field;
       
   990 }
       
   991 
       
   992 //--------------------------------------------------
       
   993 
       
   994 EAP_FUNC_EXPORT u32_t asn1_der_type_c::get_content_length() const
       
   995 {
       
   996 	if (m_input_data == 0
       
   997 		|| m_offset_of_length_field == 0ul
       
   998 		|| m_offset_of_contents_field == 0ul)
       
   999 	{
       
  1000 		return 0ul;
       
  1001 	}
       
  1002 
       
  1003 	const u8_t * extented_length = &(m_input_data[m_offset_of_length_field]);
       
  1004 	if (extented_length == 0)
       
  1005 	{
       
  1006 		return 0ul;
       
  1007 	}
       
  1008 
       
  1009 	if (((*extented_length) & static_cast<u8_t>(asn1_high_bit_mask_tag)) == 0)
       
  1010 	{
       
  1011 		// Short Length field.
       
  1012 		return static_cast<u32_t>(*extented_length);
       
  1013 	}
       
  1014 
       
  1015 	u32_t count_of_length_octets = static_cast<u32_t>((*extented_length) & static_cast<u8_t>(~asn1_high_bit_mask_tag));
       
  1016 
       
  1017 	if ((m_offset_of_length_field + asn1_identifier_const_short_length_size + count_of_length_octets) > m_input_data_length)
       
  1018 	{
       
  1019 		// Illegal data.
       
  1020 		return 0ul;
       
  1021 	}
       
  1022 
       
  1023 	const u8_t * end_byte = &(m_input_data[m_offset_of_contents_field]);
       
  1024 	if (end_byte == 0)
       
  1025 	{
       
  1026 		return 0ul;
       
  1027 	}
       
  1028 
       
  1029 	++extented_length;
       
  1030 
       
  1031 	if (static_cast<u32_t>(end_byte - extented_length) > sizeof(u32_t))
       
  1032 	{
       
  1033 		// Overflow of length.
       
  1034 		return 0ul;
       
  1035 	}
       
  1036 
       
  1037 	u32_t length(0ul);
       
  1038 
       
  1039 
       
  1040 	while (extented_length < end_byte)
       
  1041 	{
       
  1042 		length = (length << 8) + static_cast<u32_t>(*extented_length);
       
  1043 		++extented_length;
       
  1044 	}
       
  1045 
       
  1046 	return length;
       
  1047 }
       
  1048 
       
  1049 //--------------------------------------------------
       
  1050 
       
  1051 EAP_FUNC_EXPORT const u8_t * asn1_der_type_c::get_content() const
       
  1052 {
       
  1053 	if (m_input_data == 0)
       
  1054 	{
       
  1055 		return 0;
       
  1056 	}
       
  1057 
       
  1058 	if (m_offset_of_contents_field > m_input_data_length
       
  1059 		|| m_offset_of_contents_field == 0)
       
  1060 	{
       
  1061 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1062 		return 0;
       
  1063 	}
       
  1064 
       
  1065 	return (&m_input_data[m_offset_of_contents_field]);
       
  1066 }
       
  1067 
       
  1068 //--------------------------------------------------
       
  1069 
       
  1070 EAP_FUNC_EXPORT u32_t asn1_der_type_c::get_full_data_length() const
       
  1071 {
       
  1072 	return m_input_data_length;
       
  1073 }
       
  1074 
       
  1075 //--------------------------------------------------
       
  1076 
       
  1077 EAP_FUNC_EXPORT const u8_t * asn1_der_type_c::get_full_data() const
       
  1078 {
       
  1079 	return m_input_data;
       
  1080 }
       
  1081 
       
  1082 //--------------------------------------------------
       
  1083 
       
  1084 void asn1_der_type_c::set_parent_type(asn1_der_type_c * const parent_type)
       
  1085 {
       
  1086 	m_parent_type = parent_type;
       
  1087 }
       
  1088 
       
  1089 //--------------------------------------------------
       
  1090 
       
  1091 asn1_der_type_c * asn1_der_type_c::get_parent_type() const
       
  1092 {
       
  1093 	return m_parent_type;
       
  1094 }
       
  1095 
       
  1096 //--------------------------------------------------
       
  1097 
       
  1098 eap_status_e asn1_der_type_c::add_sub_type(asn1_der_type_c * const sub_type)
       
  1099 {
       
  1100 	if (m_sub_types == 0)
       
  1101 	{
       
  1102 		m_sub_types = new eap_array_c<asn1_der_type_c>(m_am_tools);
       
  1103 		if (m_sub_types == 0)
       
  1104 		{
       
  1105 			delete sub_type;
       
  1106 
       
  1107 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1108 			return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
  1109 		}
       
  1110 	}
       
  1111 
       
  1112 	sub_type->set_parent_type(this);
       
  1113 
       
  1114 	eap_status_e status = m_sub_types->add_object(sub_type, true);
       
  1115 
       
  1116 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1117 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  1118 }
       
  1119 
       
  1120 //--------------------------------------------------
       
  1121 
       
  1122 EAP_FUNC_EXPORT const eap_array_c<asn1_der_type_c> * asn1_der_type_c::get_sub_types() const
       
  1123 {
       
  1124 	return m_sub_types;
       
  1125 }
       
  1126 
       
  1127 //--------------------------------------------------
       
  1128 
       
  1129 EAP_FUNC_EXPORT const asn1_der_type_c * asn1_der_type_c::get_sub_type(
       
  1130 	const asn1_type_const_c * const asn1_type) const
       
  1131 {
       
  1132 	const asn1_type_object_c * type = asn1_type[0].get_type();
       
  1133 
       
  1134 	if (type == 0
       
  1135 		|| type->get_is_valid() == false)
       
  1136 	{
       
  1137 		return 0;
       
  1138 	}
       
  1139 
       
  1140 	ASN1_TYPE_TRACE_DEBUG(
       
  1141 		m_am_tools,
       
  1142 		TRACE_FLAGS_DEFAULT,
       
  1143 		(EAPL("# asn1_type = 0x%08x, class=%d, tag=%d, index=%d\n"),
       
  1144 		type,
       
  1145 		type->get_asn1_class(),
       
  1146 		type->get_asn1_tag(),
       
  1147 		type->get_index()));
       
  1148 
       
  1149 	const asn1_der_type_c * current_type = this;
       
  1150 
       
  1151 	ASN1_TYPE_TRACE_DEBUG(
       
  1152 		m_am_tools,
       
  1153 		TRACE_FLAGS_DEFAULT,
       
  1154 		(EAPL("### current_type = 0x%08x, class=%d, tag=%d, index=%d\n"),
       
  1155 		current_type,
       
  1156 		current_type->get_class(),
       
  1157 		current_type->get_tag(),
       
  1158 		0));
       
  1159 
       
  1160 	if (current_type->get_class() != type->get_asn1_class()
       
  1161 		|| current_type->get_tag() != type->get_asn1_tag())
       
  1162 	{
       
  1163 		ASN1_TYPE_TRACE_DEBUG(
       
  1164 			m_am_tools,
       
  1165 			TRACE_FLAGS_DEFAULT,
       
  1166 			(EAPL("ERROR: ### current_type does not match.\n")));
       
  1167 		return 0;
       
  1168 	}
       
  1169 
       
  1170 	++type;
       
  1171 
       
  1172 	while (current_type != 0 && type->get_is_valid() == true)
       
  1173 	{
       
  1174 		ASN1_TYPE_TRACE_DEBUG(
       
  1175 			m_am_tools,
       
  1176 			TRACE_FLAGS_DEFAULT,
       
  1177 			(EAPL("# asn1_type = 0x%08x, class=%d, tag=%d, index=%d\n"),
       
  1178 			type,
       
  1179 			type->get_asn1_class(),
       
  1180 			type->get_asn1_tag(),
       
  1181 			type->get_index()));
       
  1182 
       
  1183 		const eap_array_c<asn1_der_type_c> * sub_type_array = current_type->get_sub_types();
       
  1184 		if (sub_type_array == 0)
       
  1185 		{
       
  1186 			ASN1_TYPE_TRACE_DEBUG(
       
  1187 				m_am_tools,
       
  1188 				TRACE_FLAGS_DEFAULT,
       
  1189 				(EAPL("ERROR: ### No sub-type array.\n")));
       
  1190 			return 0;
       
  1191 		}
       
  1192 
       
  1193 		current_type = 0;
       
  1194 
       
  1195 		for (u32_t sub_ind = type->get_index(); sub_ind < sub_type_array->get_object_count(); ++sub_ind)
       
  1196 		{
       
  1197 			const asn1_der_type_c * const sub_type = sub_type_array->get_object(sub_ind);
       
  1198 			if (sub_type == 0
       
  1199 				|| sub_type->get_is_valid() == false)
       
  1200 			{
       
  1201 				ASN1_TYPE_TRACE_DEBUG(
       
  1202 					m_am_tools,
       
  1203 					TRACE_FLAGS_DEFAULT,
       
  1204 					(EAPL("ERROR: ### No sub-type.\n")));
       
  1205 				return 0;
       
  1206 			}
       
  1207 
       
  1208 			ASN1_TYPE_TRACE_DEBUG(
       
  1209 				m_am_tools,
       
  1210 				TRACE_FLAGS_DEFAULT,
       
  1211 				(EAPL("### sub_type = 0x%08x, class=%d, tag=%d, index=%d\n"),
       
  1212 				sub_type,
       
  1213 				sub_type->get_class(),
       
  1214 				sub_type->get_tag(),
       
  1215 				sub_ind));
       
  1216 
       
  1217 			if (sub_type->get_class() == type->get_asn1_class()
       
  1218 				&& sub_type->get_tag() == type->get_asn1_tag())
       
  1219 			{
       
  1220 				current_type = sub_type;
       
  1221 				break;
       
  1222 			}
       
  1223 		}
       
  1224 
       
  1225 		++type;
       
  1226 	}
       
  1227 
       
  1228 	if (current_type == 0)
       
  1229 	{
       
  1230 		ASN1_TYPE_TRACE_DEBUG(
       
  1231 			m_am_tools,
       
  1232 			TRACE_FLAGS_DEFAULT,
       
  1233 			(EAPL("ERROR: ### No match found.\n")));
       
  1234 	}
       
  1235 	else
       
  1236 	{
       
  1237 		ASN1_TYPE_TRACE_DEBUG(
       
  1238 			m_am_tools,
       
  1239 			TRACE_FLAGS_DEFAULT,
       
  1240 			(EAPL("### Match found.\n")));
       
  1241 
       
  1242 		ASN1_TYPE_TRACE_DATA_DEBUG(
       
  1243 			m_am_tools,
       
  1244 			TRACE_FLAGS_DEFAULT,
       
  1245 			(EAPL("ASN.1 type data"),
       
  1246 			current_type->get_full_data(),
       
  1247 			current_type->get_full_data_length()));
       
  1248 	}
       
  1249 
       
  1250 	return current_type;
       
  1251 }
       
  1252 
       
  1253 //--------------------------------------------------
       
  1254 
       
  1255 EAP_FUNC_EXPORT const asn1_der_type_c * asn1_der_type_c::get_previous_type() const
       
  1256 {
       
  1257 	const asn1_der_type_c * parent = get_parent_type();
       
  1258 
       
  1259 	if (parent == 0)
       
  1260 	{
       
  1261 		return 0;
       
  1262 	}
       
  1263 
       
  1264 	if (parent->get_sub_types() == 0)
       
  1265 	{
       
  1266 		return 0;
       
  1267 	}
       
  1268 
       
  1269 	const u32_t object_count = parent->get_sub_types()->get_object_count();
       
  1270 
       
  1271 	if (object_count <= 1ul)
       
  1272 	{
       
  1273 		return 0;
       
  1274 	}
       
  1275 
       
  1276 	const u32_t previous_index = get_index() - 1ul;
       
  1277 
       
  1278 	if (object_count <= previous_index)
       
  1279 	{
       
  1280 		return 0;
       
  1281 	}
       
  1282 
       
  1283 	return parent->get_sub_types()->get_object(previous_index);
       
  1284 }
       
  1285 
       
  1286 //--------------------------------------------------
       
  1287 
       
  1288 EAP_FUNC_EXPORT const asn1_der_type_c * asn1_der_type_c::get_next_type() const
       
  1289 {
       
  1290 	const asn1_der_type_c * parent = get_parent_type();
       
  1291 
       
  1292 	if (parent == 0)
       
  1293 	{
       
  1294 		return 0;
       
  1295 	}
       
  1296 
       
  1297 	const u32_t next_index = get_index() + 1ul;
       
  1298 
       
  1299 	if (parent->get_sub_types() == 0
       
  1300 		|| parent->get_sub_types()->get_object_count() <= next_index)
       
  1301 	{
       
  1302 		return 0;
       
  1303 	}
       
  1304 
       
  1305 	return parent->get_sub_types()->get_object(next_index);
       
  1306 }
       
  1307 
       
  1308 //--------------------------------------------------
       
  1309 
       
  1310 EAP_FUNC_EXPORT u16_t asn1_der_type_c::get_count_of_sub_types() const
       
  1311 {
       
  1312 	return m_count_of_sub_types;
       
  1313 }
       
  1314 
       
  1315 //--------------------------------------------------
       
  1316 
       
  1317 EAP_FUNC_EXPORT void asn1_der_type_c::increase_count_of_sub_types()
       
  1318 {
       
  1319 	++m_count_of_sub_types;
       
  1320 }
       
  1321 
       
  1322 //--------------------------------------------------
       
  1323 
       
  1324 void asn1_der_type_c::add_used_octets(const u32_t used_octets)
       
  1325 {
       
  1326 	m_used_octets += used_octets;
       
  1327 }
       
  1328 
       
  1329 //--------------------------------------------------
       
  1330 
       
  1331 u32_t asn1_der_type_c::get_used_octets() const
       
  1332 {
       
  1333 	return m_used_octets;
       
  1334 }
       
  1335 
       
  1336 //--------------------------------------------------
       
  1337 
       
  1338 u32_t asn1_der_type_c::get_unused_data_length() const
       
  1339 {
       
  1340 	return get_input_data_length() - get_used_octets();
       
  1341 }
       
  1342 
       
  1343 //--------------------------------------------------
       
  1344 
       
  1345 const u8_t * asn1_der_type_c::get_unused_data() const
       
  1346 {
       
  1347 	return get_input_data() + get_used_octets();
       
  1348 }
       
  1349 
       
  1350 //--------------------------------------------------
       
  1351 
       
  1352 eap_status_e asn1_der_type_c::encode_oid_from_string(eap_const_string oid, const u32_t oid_length, eap_variable_data_c * const buffer) const
       
  1353 {
       
  1354 	if (oid == 0
       
  1355 		|| buffer == 0
       
  1356 		|| buffer->get_is_valid() == false)
       
  1357 	{
       
  1358 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1359 		return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_parameter);
       
  1360 	}
       
  1361 
       
  1362 	eap_status_e status(eap_status_process_general_error);
       
  1363 
       
  1364 	const eap_char * oid_char = oid;
       
  1365 	const eap_char * end_char = &oid[oid_length];
       
  1366 	u32_t remaining_length(oid_length);
       
  1367 	u32_t first_component(0ul);
       
  1368 	u32_t component_index(0ul);
       
  1369 
       
  1370 	status = buffer->set_data_length(0ul);
       
  1371 	if (status != eap_status_ok)
       
  1372 	{
       
  1373 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1374 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  1375 	}
       
  1376 
       
  1377 	while(oid_char < end_char)
       
  1378 	{
       
  1379 		// Search next dot (.).
       
  1380 		const eap_char * dot  = reinterpret_cast<const eap_char *>(m_am_tools->memchr(oid_char, '.', remaining_length));
       
  1381 		if (dot == 0)
       
  1382 		{
       
  1383 			// The last component.
       
  1384 			dot  = reinterpret_cast<const eap_char *>(oid_char + remaining_length);
       
  1385 			if (dot == 0
       
  1386 				|| dot != end_char)
       
  1387 			{
       
  1388 				EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1389 				return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_parameter);
       
  1390 			}
       
  1391 		}
       
  1392 
       
  1393 		u32_t integer(0ul);
       
  1394 
       
  1395 		status = m_am_tools->number_string_to_u32(
       
  1396 			reinterpret_cast<const u8_t *>(oid_char),
       
  1397 			dot - oid_char,
       
  1398 			&integer);
       
  1399 		if (status != eap_status_ok)
       
  1400 		{
       
  1401 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1402 			return EAP_STATUS_RETURN(m_am_tools, status);
       
  1403 		}
       
  1404 
       
  1405 		if (component_index == 0ul)
       
  1406 		{
       
  1407 			// The first component is encoded with the second component.
       
  1408 			first_component = integer;
       
  1409 		}
       
  1410 		else if (component_index == 1ul)
       
  1411 		{
       
  1412 			if (first_component < 2ul
       
  1413 				&& integer > 39ul)
       
  1414 			{
       
  1415 				EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1416 				return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_parameter);
       
  1417 			}
       
  1418 			else if (first_component > 2ul)
       
  1419 			{
       
  1420 				EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1421 				return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_parameter);
       
  1422 			}
       
  1423 
       
  1424 			const u32_t oid_value = first_component * 40ul + integer;
       
  1425 			if (oid_value > 0xff)
       
  1426 			{
       
  1427 				EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1428 				return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_parameter);
       
  1429 			}
       
  1430 
       
  1431 			const u8_t oid_octet(static_cast<u8_t>(oid_value));
       
  1432 
       
  1433 			status = buffer->add_data(&oid_octet, sizeof(oid_octet));
       
  1434 			if (status != eap_status_ok)
       
  1435 			{
       
  1436 				EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1437 				return EAP_STATUS_RETURN(m_am_tools, status);
       
  1438 			}
       
  1439 		}
       
  1440 		else
       
  1441 		{
       
  1442 			eap_variable_data_c encoded_data(m_am_tools);
       
  1443 			if (encoded_data.get_is_valid() == false)
       
  1444 			{
       
  1445 				EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1446 				return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
  1447 			}
       
  1448 
       
  1449 			const u32_t ENCODE_BASE = 128ul;
       
  1450 
       
  1451 			while(integer > 0ul)
       
  1452 			{
       
  1453 				const u8_t oid_octet = static_cast<u8_t>(integer % ENCODE_BASE);
       
  1454 
       
  1455 				// Encodes the octets to reverse order.
       
  1456 				status = encoded_data.add_data(&oid_octet, sizeof(oid_octet));
       
  1457 				if (status != eap_status_ok)
       
  1458 				{
       
  1459 					EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1460 					return EAP_STATUS_RETURN(m_am_tools, status);
       
  1461 				}
       
  1462 
       
  1463 				integer = integer / ENCODE_BASE;
       
  1464 			} // while()
       
  1465 
       
  1466 			for (u32_t ind = encoded_data.get_data_length(); ind > 0ul; --ind)
       
  1467 			{
       
  1468 				// reads the octets on reverse order.
       
  1469 				u8_t * oid_octet = encoded_data.get_data_offset(ind-1ul, sizeof(u8_t));
       
  1470 				if (oid_octet == 0)
       
  1471 				{
       
  1472 					EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1473 					return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_parameter);
       
  1474 				}
       
  1475 
       
  1476 				if (ind > 1ul)
       
  1477 				{
       
  1478 					// All but the last octet have high bit set.
       
  1479 					*oid_octet |= static_cast<u8_t>(asn1_high_bit_mask_tag);
       
  1480 				}
       
  1481 
       
  1482 				status = buffer->add_data(oid_octet, sizeof(*oid_octet));
       
  1483 				if (status != eap_status_ok)
       
  1484 				{
       
  1485 					EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1486 					return EAP_STATUS_RETURN(m_am_tools, status);
       
  1487 				}
       
  1488 			} // for()
       
  1489 		}
       
  1490 
       
  1491 		remaining_length -= (dot - oid_char) + 1ul;
       
  1492 
       
  1493 		oid_char = dot+1ul;
       
  1494 
       
  1495 		++component_index;
       
  1496 
       
  1497 	} // while()
       
  1498 
       
  1499 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1500 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  1501 }
       
  1502 
       
  1503 //--------------------------------------------------
       
  1504 
       
  1505 EAP_FUNC_EXPORT eap_status_e asn1_der_type_c::compare_object_identifier(const u8_t * const der_encoded_oid, const u32_t oid_length) const
       
  1506 {
       
  1507 	if (get_tag() != asn1_tag_object_identifier
       
  1508 		|| der_encoded_oid == 0)
       
  1509 	{
       
  1510 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1511 		return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_parameter);
       
  1512 	}
       
  1513 
       
  1514 	const u32_t content_length(get_content_length());
       
  1515 
       
  1516 	if (content_length != oid_length
       
  1517 		|| m_am_tools->memcmp(
       
  1518 			der_encoded_oid, 
       
  1519 			get_content(), 
       
  1520 			content_length) != 0)
       
  1521 	{
       
  1522 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1523 		return eap_status_no_match;
       
  1524 	}
       
  1525 
       
  1526 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1527 	return EAP_STATUS_RETURN(m_am_tools, eap_status_ok);
       
  1528 }
       
  1529 
       
  1530 //--------------------------------------------------
       
  1531 
       
  1532 EAP_FUNC_EXPORT eap_status_e asn1_der_type_c::compare_object_identifier(eap_const_string oid, const u32_t oid_length) const
       
  1533 {
       
  1534 	if (get_tag() != asn1_tag_object_identifier
       
  1535 		|| oid == 0)
       
  1536 	{
       
  1537 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1538 		return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_parameter);
       
  1539 	}
       
  1540 
       
  1541 	eap_variable_data_c oid_buffer(m_am_tools);
       
  1542 
       
  1543 	if (oid_buffer.get_is_valid() == false)
       
  1544 	{
       
  1545 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1546 		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
  1547 	}
       
  1548 
       
  1549 	eap_status_e status = encode_oid_from_string(oid, oid_length, &oid_buffer);
       
  1550 	if (status != eap_status_ok)
       
  1551 	{
       
  1552 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1553 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  1554 	}
       
  1555 
       
  1556 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1557 	return compare_object_identifier(oid_buffer.get_data(), oid_buffer.get_data_length());
       
  1558 }
       
  1559 
       
  1560 //--------------------------------------------------
       
  1561 
       
  1562 EAP_FUNC_EXPORT eap_status_e asn1_der_type_c::decode(const eap_variable_data_c * const asn1_der_data)
       
  1563 {
       
  1564 	if (asn1_der_data == 0)
       
  1565 	{
       
  1566 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1567 		return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_parameter);
       
  1568 	}
       
  1569 
       
  1570 	eap_variable_data_c * debug_buffer = 0;
       
  1571 
       
  1572 #if defined(USE_EAP_DEBUG_TRACE)
       
  1573 	// Buffer is used for debug traces.
       
  1574 	eap_variable_data_c tmp_debug_buffer(m_am_tools);
       
  1575 
       
  1576 	{
       
  1577 		eap_status_e status = tmp_debug_buffer.set_buffer_length(MAX_DEBUG_BUFFER);
       
  1578 		if (status != eap_status_ok)
       
  1579 		{
       
  1580 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1581 			return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
  1582 		}
       
  1583 
       
  1584 		debug_buffer = &tmp_debug_buffer;
       
  1585 	}
       
  1586 #endif //	#if defined(USE_EAP_DEBUG_TRACE)
       
  1587 
       
  1588 
       
  1589 	eap_status_e status = initialize(
       
  1590 		asn1_der_data->get_data_length(),
       
  1591 		asn1_der_data->get_data(),
       
  1592 		0ul,
       
  1593 		0ul,
       
  1594 		debug_buffer);
       
  1595 	if (status != eap_status_ok)
       
  1596 	{
       
  1597 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1598 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  1599 	}
       
  1600 
       
  1601 	asn1_der_type_c * current_type = this;
       
  1602 
       
  1603 	if (current_type->get_pc() == asn1_pc_constructed)
       
  1604 	{
       
  1605 		ASN1_TYPE_TRACE_DEBUG(
       
  1606 			m_am_tools,
       
  1607 			TRACE_FLAGS_DEFAULT,
       
  1608 			(EAPL("# this = 0x%08x, input_data_length=%d, used_octets=%d\n"),
       
  1609 			 current_type,
       
  1610 			 current_type->get_input_data_length(),
       
  1611 			 current_type->get_used_octets()));
       
  1612 
       
  1613 		while (current_type->get_used_octets() != current_type->get_input_data_length())
       
  1614 		{
       
  1615 			asn1_der_type_c * sub_type = new asn1_der_type_c(m_am_tools);
       
  1616 
       
  1617 			eap_automatic_variable_c<asn1_der_type_c> automatic_sub_type(m_am_tools, sub_type);
       
  1618 
       
  1619 			if (sub_type == 0
       
  1620 				|| sub_type->get_is_valid() == false)
       
  1621 			{
       
  1622 				EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1623 				return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
  1624 			}
       
  1625 
       
  1626 			ASN1_TYPE_TRACE_DEBUG(
       
  1627 				m_am_tools,
       
  1628 				TRACE_FLAGS_DEFAULT,
       
  1629 				(EAPL("# this = 0x%08x, unused_data_length=%d, recursion=%d\n"),
       
  1630 				 current_type,
       
  1631 				 current_type->get_unused_data_length(),
       
  1632 				 current_type->get_recursion()));
       
  1633 
       
  1634 			status = sub_type->initialize(
       
  1635 				current_type->get_unused_data_length(),
       
  1636 				current_type->get_unused_data(),
       
  1637 				current_type->get_recursion() + 1u,
       
  1638 				current_type->get_count_of_sub_types(),
       
  1639 				debug_buffer);
       
  1640 			if (status != eap_status_ok)
       
  1641 			{
       
  1642 				EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1643 				return EAP_STATUS_RETURN(m_am_tools, status);
       
  1644 			}
       
  1645 
       
  1646 			current_type->increase_count_of_sub_types();
       
  1647 
       
  1648 			ASN1_TYPE_TRACE_DEBUG(
       
  1649 				m_am_tools,
       
  1650 				TRACE_FLAGS_DEFAULT,
       
  1651 				(EAPL("# this = 0x%08x, used_octets=%d\n"),
       
  1652 				 sub_type,
       
  1653 				 sub_type->get_used_octets()));
       
  1654 
       
  1655 			automatic_sub_type.do_not_free_variable();
       
  1656 
       
  1657 			status = current_type->add_sub_type(sub_type);
       
  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 			if (sub_type->get_pc() == asn1_pc_primitive)
       
  1665 			{
       
  1666 				ASN1_DEBUG_DATA(sub_type, debug_buffer);
       
  1667 
       
  1668 				sub_type->add_used_octets(sub_type->get_content_length());
       
  1669 
       
  1670 				current_type = sub_type;
       
  1671 
       
  1672 				do
       
  1673 				{
       
  1674 					sub_type = current_type;
       
  1675 					current_type = current_type->get_parent_type();
       
  1676 					current_type->add_used_octets(sub_type->get_used_octets());
       
  1677 
       
  1678 					ASN1_TYPE_TRACE_DEBUG(
       
  1679 						m_am_tools,
       
  1680 						TRACE_FLAGS_DEFAULT,
       
  1681 						(EAPL("# this = 0x%08x, input_data_length=%d, used_octets=%d\n"),
       
  1682 						 current_type,
       
  1683 						 current_type->get_input_data_length(),
       
  1684 						 current_type->get_used_octets()));
       
  1685 				}
       
  1686 				while (current_type->get_used_octets() == current_type->get_input_data_length() && current_type->get_parent_type() != 0);
       
  1687 			}
       
  1688 			else
       
  1689 			{
       
  1690 				current_type = sub_type;
       
  1691 			}
       
  1692 
       
  1693 		} // while()
       
  1694 	}
       
  1695 	else
       
  1696 	{
       
  1697 		ASN1_DEBUG_DATA(this, debug_buffer);
       
  1698 	}
       
  1699 
       
  1700 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1701 	return EAP_STATUS_RETURN(m_am_tools, eap_status_ok);
       
  1702 }
       
  1703 
       
  1704 //--------------------------------------------------
       
  1705 
       
  1706 // End.