eapol/eapol_framework/wapi_common/src/wapi_asn1_der_parser.cpp
changeset 17 8840d3e38314
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/eapol/eapol_framework/wapi_common/src/wapi_asn1_der_parser.cpp	Fri Mar 19 09:29:58 2010 +0200
@@ -0,0 +1,554 @@
+/*
+* ============================================================================
+*  Name        : ./accesssec/eapol/eapol_framework/wapi_common/src/wapi_asn1_der_parser.cpp
+*  Part of     : WAPI / WAPI       *** Info from the SWAD
+*  Description : WAPI authentication
+*  Version     : %version: 12 % << Don't touch! Updated by Synergy at check-out.
+*
+*  Copyright © 2001-2009 Nokia.  All rights reserved.
+*  This material, including documentation and any related computer
+*  programs, is protected by copyright controlled by Nokia.  All
+*  rights are reserved.  Copying, including reproducing, storing,
+*  adapting or translating, any or all of this material requires the
+*  prior written consent of Nokia.  This material also contains
+*  confidential information which may not be disclosed to others
+*  without the prior written consent of Nokia.
+* ============================================================================
+* Template version: 4.1.1
+*/
+
+#include "wapi_asn1_der_parser.h"
+#include "eap_automatic_variable.h"
+#include "wapi_types.h"
+
+//--------------------------------------------------------------------------------------------------
+
+EAP_FUNC_EXPORT wapi_asn1_der_parser_c::~wapi_asn1_der_parser_c()
+{
+}
+
+//--------------------------------------------------------------------------------------------------
+
+EAP_FUNC_EXPORT wapi_asn1_der_parser_c::wapi_asn1_der_parser_c(
+	abs_eap_am_tools_c * const tools)
+	: m_am_tools(tools)
+	, m_is_valid(false)
+	, m_objects(tools)
+{
+	m_is_valid = true;
+}
+
+//--------------------------------------------------------------------------------------------------
+
+EAP_FUNC_EXPORT bool wapi_asn1_der_parser_c::get_is_valid() const
+{
+	return m_is_valid;
+}
+
+//--------------------------------------------------------------------------------------------------
+
+EAP_FUNC_EXPORT eap_status_e wapi_asn1_der_parser_c::decode(const eap_variable_data_c * const asn1_der_data)
+{
+	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
+
+	ASN1_TYPE_TRACE_DEBUG(
+		m_am_tools,
+		TRACE_FLAGS_DEFAULT,
+		(EAPL("WAPI_Core: this = 0x%08x: wapi_asn1_der_parser_c::decode()\n"),
+		 this));
+
+	EAP_TRACE_RETURN_STRING(m_am_tools, "returns: wapi_asn1_der_parser_c::decode()");
+
+	eap_status_e status(eap_status_process_general_error);
+
+	// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+	bool data_continues(true);
+
+	status = m_objects.reset();
+	if (status != eap_status_ok)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+
+	eap_variable_data_c input(m_am_tools);
+	if (input.get_is_valid() == false)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
+	}
+
+	u32_t input_offset(0ul);
+	const u32_t input_length(asn1_der_data->get_data_length());
+	u32_t input_remain_length(input_length);
+
+	while(data_continues == true)
+	{
+		asn1_der_type_c * const asn1_der_object = new asn1_der_type_c(m_am_tools);
+
+		eap_automatic_variable_c<asn1_der_type_c> automatic_asn1_der_object(m_am_tools, asn1_der_object);
+
+		if (asn1_der_object == 0
+			|| asn1_der_object->get_is_valid() == false)
+		{
+			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+			return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
+		}
+
+		status = input.set_buffer(
+			asn1_der_data->get_data_offset(input_offset, input_remain_length),
+			input_remain_length,
+			false,
+			false);
+
+		status = asn1_der_object->decode(&input);
+		if (status != eap_status_ok)
+		{
+			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+			return EAP_STATUS_RETURN(m_am_tools, status);
+		}
+
+		automatic_asn1_der_object.do_not_free_variable();
+
+		status = m_objects.add_object(asn1_der_object, true);
+		if (status != eap_status_ok)
+		{
+			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+			return EAP_STATUS_RETURN(m_am_tools, status);
+		}
+
+		input_offset += asn1_der_object->get_full_data_length();
+
+		if (input_remain_length < asn1_der_object->get_full_data_length())
+		{
+			data_continues = false;
+		}
+		else
+		{
+			input_remain_length -= asn1_der_object->get_full_data_length();
+
+			if (input_remain_length >= input_length
+				|| input_offset >= input_length)
+			{
+				data_continues = false;
+			}
+		}
+	}
+
+	// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+	return EAP_STATUS_RETURN(m_am_tools, status);
+}
+
+//--------------------------------------------------------------------------------------------------
+
+EAP_FUNC_EXPORT const asn1_der_type_c * wapi_asn1_der_parser_c::get_object(const u32_t index) const
+{
+	if (m_objects.get_object_count() <= index)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		(void) EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_index);
+		return 0;
+	}
+
+	return m_objects.get_object(index);
+}
+
+//--------------------------------------------------------------------------------------------------
+
+EAP_FUNC_EXPORT u32_t wapi_asn1_der_parser_c::get_object_count() const
+{
+	return m_objects.get_object_count();
+}
+
+//--------------------------------------------------------------------------------------------------
+
+EAP_FUNC_EXPORT eap_status_e wapi_asn1_der_parser_c::get_wapi_identity(
+	eap_variable_data_c * const subject_name,
+	eap_variable_data_c * const issuer_name,
+	eap_variable_data_c * const sequence_number)
+{
+	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
+
+	ASN1_TYPE_TRACE_DEBUG(
+		m_am_tools,
+		TRACE_FLAGS_DEFAULT,
+		(EAPL("WAPI_Core: this = 0x%08x: wapi_asn1_der_parser_c::get_wapi_identity()\n"),
+		 this));
+
+	EAP_TRACE_RETURN_STRING(m_am_tools, "returns: wapi_asn1_der_parser_c::get_wapi_identity()");
+
+	eap_status_e status(eap_status_process_general_error);
+
+	if (subject_name == 0
+		|| issuer_name == 0
+		|| sequence_number == 0
+		|| subject_name->get_is_valid() == false
+		|| issuer_name->get_is_valid() == false
+		|| sequence_number->get_is_valid() == false)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_parameter);
+	}
+
+	// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+	const asn1_type_const_c type_object_identifier[] =
+		{
+			ASN1_TYPE_OBJECT(
+				asn1_der_type_c::asn1_class_universal,
+				asn1_der_type_c::asn1_tag_sequence,
+				0),										// Name ::= CHOICE { RDNSequence } 
+														// ::= RDNSequence 
+														// ::= SEQUENCE OF RelativeDistinguishedName
+														// ::= {organizationalUnitName[0], commonName[1]}
+			ASN1_TYPE_OBJECT(
+				asn1_der_type_c::asn1_class_universal,
+				asn1_der_type_c::asn1_tag_set,
+				1),										// commonName ::= SET OF AttributeTypeAndValue
+			ASN1_TYPE_OBJECT(
+				asn1_der_type_c::asn1_class_universal,
+				asn1_der_type_c::asn1_tag_sequence,
+				0),										// AttributeTypeAndValue ::= SEQUENCE {
+														//		type     AttributeType,
+														//		value    AttributeValue }
+			ASN1_TYPE_OBJECT(
+				asn1_der_type_c::asn1_class_universal,
+				asn1_der_type_c::asn1_tag_object_identifier,
+				0),										// AttributeType ::= OBJECT IDENTIFIER
+			ASN1_TYPE_OBJECT_TERMINATOR
+		};
+
+	u32_t index(0ul);
+
+	{
+		const asn1_der_type_c * const der_subject_name = get_object(index);
+
+		if (der_subject_name == 0
+			|| der_subject_name->get_is_valid() == false)
+		{
+			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+			return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_index);
+		}
+
+		const asn1_der_type_c * const der_object_identifier = der_subject_name->get_sub_type(type_object_identifier);
+
+		if (der_object_identifier == 0
+			|| der_object_identifier->get_is_valid() == false)
+		{
+			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+			return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_index);
+		}
+
+		if (der_object_identifier->get_full_data_length() != sizeof(WAPI_COMMON_NAME_OID_PARAMETER)
+			|| m_am_tools->memcmp(WAPI_COMMON_NAME_OID_PARAMETER,
+			der_object_identifier->get_full_data(),
+			sizeof(WAPI_COMMON_NAME_OID_PARAMETER)) != 0)
+		{
+			// ERROR: wrong payload.
+			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+			return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_data_payload);
+		}
+
+		status = subject_name->set_copy_of_buffer(
+			der_subject_name->get_full_data(),
+			der_subject_name->get_full_data_length());
+		if (status != eap_status_ok)
+		{
+			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+			return EAP_STATUS_RETURN(m_am_tools, status);
+		}
+
+		EAP_TRACE_DATA_DEBUG(
+			m_am_tools,
+			TRACE_FLAGS_DEFAULT,
+			(EAPL("subject_name"),
+			subject_name->get_data(),
+			subject_name->get_data_length()));
+	}
+
+	// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+	++index;
+
+	{
+		const asn1_der_type_c * const der_issuer_name = get_object(index);
+
+		if (der_issuer_name == 0
+			|| der_issuer_name->get_is_valid() == false)
+		{
+			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+			return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_index);
+		}
+
+		const asn1_der_type_c * const der_object_identifier = der_issuer_name->get_sub_type(type_object_identifier);
+
+		if (der_object_identifier == 0
+			|| der_object_identifier->get_is_valid() == false)
+		{
+			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+			return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_index);
+		}
+
+		if (der_object_identifier->get_full_data_length() != sizeof(WAPI_COMMON_NAME_OID_PARAMETER)
+			|| m_am_tools->memcmp(WAPI_COMMON_NAME_OID_PARAMETER,
+			der_object_identifier->get_full_data(),
+			sizeof(WAPI_COMMON_NAME_OID_PARAMETER)) != 0)
+		{
+			// ERROR: wrong payload.
+			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+			return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_data_payload);
+		}
+
+		status = issuer_name->set_copy_of_buffer(
+			der_issuer_name->get_full_data(),
+			der_issuer_name->get_full_data_length());
+		if (status != eap_status_ok)
+		{
+			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+			return EAP_STATUS_RETURN(m_am_tools, status);
+		}
+
+		EAP_TRACE_DATA_DEBUG(
+			m_am_tools,
+			TRACE_FLAGS_DEFAULT,
+			(EAPL("issuer_name"),
+			issuer_name->get_data(),
+			issuer_name->get_data_length()));
+	}
+
+	// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+	++index;
+
+	{
+		const asn1_der_type_c * const der_sequence_number = get_object(index);
+
+		if (der_sequence_number == 0
+			|| der_sequence_number->get_is_valid() == false)
+		{
+			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+			return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_index);
+		}
+
+		switch(der_sequence_number->get_tag())
+		{
+		case asn1_der_type_c::asn1_tag_integer:
+			// OK
+			break;
+		default:
+			// ERROR: wrong payload.
+			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+			return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_data_payload);
+		};
+
+		status = sequence_number->set_copy_of_buffer(
+			der_sequence_number->get_full_data(),
+			der_sequence_number->get_full_data_length());
+		if (status != eap_status_ok)
+		{
+			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+			return EAP_STATUS_RETURN(m_am_tools, status);
+		}
+
+		EAP_TRACE_DATA_DEBUG(
+			m_am_tools,
+			TRACE_FLAGS_DEFAULT,
+			(EAPL("sequence_number"),
+			sequence_number->get_data(),
+			sequence_number->get_data_length()));
+	}
+
+	// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+	return EAP_STATUS_RETURN(m_am_tools, status);
+}
+
+//--------------------------------------------------------------------------------------------------
+
+EAP_FUNC_EXPORT eap_status_e wapi_asn1_der_parser_c::get_wapi_identity(
+	eap_variable_data_c * const wapi_identity)
+{
+	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
+
+	ASN1_TYPE_TRACE_DEBUG(
+		m_am_tools,
+		TRACE_FLAGS_DEFAULT,
+		(EAPL("WAPI_Core: this = 0x%08x: wapi_asn1_der_parser_c::get_wapi_identity()\n"),
+		 this));
+
+	EAP_TRACE_RETURN_STRING(m_am_tools, "returns: wapi_asn1_der_parser_c::get_wapi_identity()");
+
+	eap_status_e status(eap_status_process_general_error);
+
+	if (wapi_identity == 0
+		|| wapi_identity->get_is_valid() == false)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_parameter);
+	}
+
+	// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+	eap_variable_data_c subject_name(m_am_tools);
+	eap_variable_data_c issuer_name(m_am_tools);
+	eap_variable_data_c sequence_number(m_am_tools);
+
+	if (subject_name.get_is_valid() == false
+		|| issuer_name.get_is_valid() == false
+		|| sequence_number.get_is_valid() == false)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
+	}
+
+	status = get_wapi_identity(
+		&subject_name,
+		&issuer_name,
+		&sequence_number);
+	if (status != eap_status_ok)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+
+	status = wapi_identity->set_copy_of_buffer(&subject_name);
+	if (status != eap_status_ok)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+
+	status = wapi_identity->add_data(&issuer_name);
+	if (status != eap_status_ok)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+
+	status = wapi_identity->add_data(&sequence_number);
+	if (status != eap_status_ok)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+
+	// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+	return EAP_STATUS_RETURN(m_am_tools, status);
+}
+
+
+//--------------------------------------------------------------------------------------------------
+
+EAP_FUNC_EXPORT eap_status_e wapi_asn1_der_parser_c::get_decoded_subject_name(
+    eap_variable_data_c * const identity_data,
+    eap_variable_data_c * const decoded_data)
+{
+    
+    eap_status_e status = eap_status_ok;
+    eap_variable_data_c subject_name(m_am_tools);
+   
+	if ( subject_name.get_is_valid() == false )
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
+	}
+    
+    // The data is stored to this objects internal variables with decode
+    status = decode(identity_data);
+	if (status != eap_status_ok)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+    
+	const asn1_type_const_c type_name_sequence[] =
+		{
+			ASN1_TYPE_OBJECT(
+				asn1_der_type_c::asn1_class_universal,
+				asn1_der_type_c::asn1_tag_sequence,
+				0),										// Name ::= CHOICE { RDNSequence } 
+														// ::= RDNSequence 
+														// ::= SEQUENCE OF RelativeDistinguishedName
+														// ::= {organizationalUnitName[0], commonName[1]}
+			ASN1_TYPE_OBJECT(
+				asn1_der_type_c::asn1_class_universal,
+				asn1_der_type_c::asn1_tag_set,
+				1),										// commonName ::= SET OF AttributeTypeAndValue
+			ASN1_TYPE_OBJECT(
+				asn1_der_type_c::asn1_class_universal,
+				asn1_der_type_c::asn1_tag_sequence,
+				0),										// AttributeTypeAndValue ::= SEQUENCE {
+														//		type     AttributeType,
+														//		value    AttributeValue }
+#if 0
+			// This last object is variable type and it is handled later.
+			ASN1_TYPE_OBJECT(
+				asn1_der_type_c::asn1_class_universal,
+				asn1_der_type_c::asn1_tag_printable_string,
+				0),										// AttributeValue ::= ANY DEFINED BY AttributeType
+														// ::= DirectoryString ::= CHOICE {
+														// teletexString           TeletexString (SIZE (1..MAX)),
+														// printableString         PrintableString (SIZE (1..MAX)),
+														// universalString         UniversalString (SIZE (1..MAX)),
+														// utf8String              UTF8String (SIZE (1..MAX)),
+														// bmpString               BMPString (SIZE (1..MAX)) }
+#endif
+			ASN1_TYPE_OBJECT_TERMINATOR
+		};
+
+	if (get_object_count() == 0ul)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_index);
+	}
+
+	const asn1_der_type_c * const der_name_sequence = get_object(0ul)->get_sub_type(type_name_sequence);
+
+	if (der_name_sequence == 0
+		|| der_name_sequence->get_is_valid() == false)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_index);
+	}
+
+	// Second object (index 1) in SEQUENCE is AttributeValue.
+	const asn1_der_type_c * const der_name = der_name_sequence->get_sub_types()->get_object(1ul);
+
+	if (der_name == 0
+		|| der_name->get_is_valid() == false
+		|| (/* der_name->get_tag() != asn1_der_type_c::asn1_tag_teletex_string // This is not defined yet.
+			&& */
+			der_name->get_tag() != asn1_der_type_c::asn1_tag_printable_string
+			&& der_name->get_tag() != asn1_der_type_c::asn1_tag_universal_string
+			&& der_name->get_tag() != asn1_der_type_c::asn1_tag_utf8_string
+			&& der_name->get_tag() != asn1_der_type_c::asn1_tag_bmp_string
+			&& der_name->get_tag() != asn1_der_type_c::asn1_tag_t61_string))
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_index);
+	}
+
+    // Copy the decoded data into the returned parameter
+    status = decoded_data->set_copy_of_buffer(
+		der_name->get_content(), 
+		der_name->get_content_length());
+	if (status != eap_status_ok)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+    
+    EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+    return EAP_STATUS_RETURN(m_am_tools, status);
+}
+
+
+//--------------------------------------------------------------------------------------------------
+
+// End.