eapol/eapol_framework/eapol_symbian/am/type/tls_peap/symbian/EapTlsPeapCertInterface.cpp
changeset 0 c8830336c852
child 2 1c7bc153c08e
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/eapol/eapol_framework/eapol_symbian/am/type/tls_peap/symbian/EapTlsPeapCertInterface.cpp	Thu Dec 17 08:47:43 2009 +0200
@@ -0,0 +1,2459 @@
+/*
+* Copyright (c) 2001-2006 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of the License "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description:  EAP and WLAN authentication protocols.
+*
+*/
+
+
+// This is enumeration of EAPOL source code.
+#if defined(USE_EAP_MINIMUM_RELEASE_TRACES)
+	#undef EAP_FILE_NUMBER_ENUM
+	#define EAP_FILE_NUMBER_ENUM 390 
+	#undef EAP_FILE_NUMBER_DATE 
+	#define EAP_FILE_NUMBER_DATE 1127594498 
+#endif //#if defined(USE_EAP_MINIMUM_RELEASE_TRACES)
+
+
+// INCLUDE FILES
+#include "EapTlsPeapCertInterface.h"
+#include "EapTlsPeapUtils.h"
+#include <x509keys.h>
+#include <x509cert.h>
+#include "eap_tlv_message_data.h"
+#include "eap_am_trace_symbian.h"
+
+const TText8 KKeyStoreHandlePrefix[] = "EapTlsPeapKeyStoreHandler";
+const TText8 KKeyStoreHandleKey[] = "CEapTlsPeapCertInterface KeyStore handle";
+
+enum TAlgorithmAndSignedType
+{
+	ERSASign = 1,
+	EDSASign,
+	ERSASignWithFixedDH,
+	EDSASignWithFixedDH,
+	ERSASignWithEphemeralDH,
+	EDSASignWithEphemeralDH
+};
+
+enum eap_type_tlspeap_stored_e
+{
+	eap_type_tlspeap_stored_keystore_handle = 1
+};
+
+// ================= MEMBER FUNCTIONS =======================
+
+// Completition functions should be moved to abstract IF
+
+CEapTlsPeapCertInterface* CEapTlsPeapCertInterface::NewL(abs_eap_am_tools_c* const aTools, 
+											   eap_am_type_tls_peap_symbian_c* const aParent)
+{
+	CEapTlsPeapCertInterface* self = new(ELeave) CEapTlsPeapCertInterface(aTools, aParent);
+	CleanupStack::PushL(self);
+	self->ConstructL();
+	CleanupStack::Pop();
+	return self;
+}
+
+//--------------------------------------------------
+
+CEapTlsPeapCertInterface::CEapTlsPeapCertInterface(abs_eap_am_tools_c* const aTools, eap_am_type_tls_peap_symbian_c* const aParent)
+: CActive(CActive::EPriorityStandard)
+,iParent(aParent)
+,m_am_tools(aTools)
+,iAllowedUserCerts(1)
+,iEncodedCertificate(0)
+,iCertPtr(0,0)
+,iMatchingUserCertInfos(1)
+,iCAIndex(0)
+{
+	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
+	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+}
+
+//--------------------------------------------------
+
+void CEapTlsPeapCertInterface::ConstructL()
+{
+	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
+	
+	User::LeaveIfError(iFs.Connect());
+	
+	CActiveScheduler::Add(this);		
+	
+	iValidationResult = CPKIXValidationResult::NewL();
+	
+	iEncodedCertificate = HBufC8::NewL(0);
+	iCertPtr.Set(iEncodedCertificate->Des());	
+
+	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+}
+
+//--------------------------------------------------
+
+CEapTlsPeapCertInterface::~CEapTlsPeapCertInterface()
+{
+	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
+	
+	iMatchingUserCerts.ResetAndDestroy();
+
+	iMatchingUserCertInfos.Reset();
+	
+	iAllowedUserCerts.Reset();
+
+	iRootCerts.ResetAndDestroy();
+	iUserCertChain.ResetAndDestroy();
+	
+	iCertAuthorities.ResetAndDestroy();
+	
+	TInt i(0);
+	for (i = 0; i < iCertInfos.Count(); i++)
+	{
+		iCertInfos[i]->Release();
+	}
+	iCertInfos.Reset();
+
+	for (i = 0; i < iKeyInfos.Count(); i++)
+	{
+		iKeyInfos[i]->Release();
+	}
+	iKeyInfos.Reset();
+
+	delete iCertFilter;
+	delete iCertStore;
+	delete iCertChain;
+	delete iValidationResult;
+	delete iInputCertChain;	
+	delete iEncodedCertificate;	
+	delete iDataIn;
+	delete iDataOut;
+	delete iSignature;
+	delete iPtrOut;
+	delete iSignaturePtr;
+	
+	iFs.Close();	
+	
+	EAP_TRACE_DEBUG(
+		m_am_tools,
+		TRACE_FLAGS_DEFAULT,
+		(EAPL("CEapTlsPeapCertInterface::~CEapTlsPeapCertInterface(): returns\n")));
+	
+	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+}
+
+//--------------------------------------------------
+
+void CEapTlsPeapCertInterface::GetMatchingCertificatesL(
+	const RArray<SCertEntry>& aAllowedUserCerts,
+	const TBool aUseCertAuthoritiesFilter,
+	EAP_TEMPLATE_CONST eap_array_c<eap_variable_data_c> * const aCertAuthorities,
+	const TBool aUseCertTypesFilter,
+	EAP_TEMPLATE_CONST eap_array_c<u8_t> * const aCertTypes,
+	const TBool aUseAllowedCipherSuitesFilter,
+	const RArray<TUint>& aAllowedCipherSuites)
+{
+	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
+	
+	iUseCertAuthoritiesFilter = aUseCertAuthoritiesFilter;
+	
+	iUseCertTypesFilter = aUseCertTypesFilter;
+	
+	iUseAllowedCipherSuitesFilter = aUseAllowedCipherSuitesFilter;
+
+	iAllowedUserCerts.Reset();
+	
+	EAP_TRACE_DEBUG(
+		m_am_tools,
+		TRACE_FLAGS_DEFAULT,
+		(EAPL("CEapTlsPeapCertInterface::GetMatchingCertificatesL: Total allowed user certs=%d\n"),
+		aAllowedUserCerts.Count()));		
+	
+	EAP_TRACE_DEBUG(
+		m_am_tools,
+		TRACE_FLAGS_DEFAULT,
+		(EAPL("CEapTlsPeapCertInterface::GetMatchingCertificatesL:UseCertAuthoritiesFilter=%d, UseCertTypesFilter=%d, UseAllowedCipherSuitesFilter=%d\n"),
+		iUseCertAuthoritiesFilter,iUseCertTypesFilter,iUseAllowedCipherSuitesFilter));		
+	
+	for (TInt j = 0; j < aAllowedUserCerts.Count(); j++)
+	{
+		iAllowedUserCerts.AppendL(aAllowedUserCerts[j]);
+		
+#if defined(_DEBUG) || defined(DEBUG)
+
+		// This is just for the debug prints.
+		TCertLabel tempLabel = iAllowedUserCerts[j].iLabel;
+		TKeyIdentifier tempSubjectKeyId = iAllowedUserCerts[j].iSubjectKeyId;
+		
+		EAP_TRACE_DEBUG(
+			m_am_tools,
+			TRACE_FLAGS_DEFAULT,
+			(EAPL("CEapTlsPeapCertInterface::GetMatchingCertificatesL: details of allowed user certs,Label=%S\n"),
+		&tempLabel));		
+		
+		EAP_TRACE_DATA_DEBUG_SYMBIAN( ( "GetMatchingCertificatesL : Subject Key Id:",
+		tempSubjectKeyId.Ptr(), tempSubjectKeyId.Size() ) );			
+#endif
+	}
+
+	if (iCertAuthorities.Count() > 0)
+	{
+		iCertAuthorities.ResetAndDestroy();
+	}
+	if (aUseCertAuthoritiesFilter)
+	{
+		for (TUint i = 0; i < aCertAuthorities->get_object_count(); i++)
+		{
+			HBufC8* buf = HBufC8::NewLC((aCertAuthorities->get_object(i))->get_data_length());
+			TPtr8 ptr = buf->Des();
+			ptr.Copy((aCertAuthorities->get_object(i))->get_data((aCertAuthorities->get_object(i))->get_data_length()),
+				(aCertAuthorities->get_object(i))->get_data_length());
+
+			// Try to form distiguished name
+			CX500DistinguishedName* tmp = 0;
+			TRAPD(err, tmp = CX500DistinguishedName::NewL(ptr));
+			if (err == KErrNone)
+			{
+				CleanupStack::PushL(tmp);
+				// Distinguished name was found -> add it to array.
+				User::LeaveIfError(iCertAuthorities.Append(tmp));
+				CleanupStack::Pop(tmp);
+			}
+			CleanupStack::PopAndDestroy(buf);
+		}
+	}
+	
+	if (aUseCertTypesFilter)
+	{
+		iCertTypes = aCertTypes;
+	}
+
+	if (aUseAllowedCipherSuitesFilter)
+	{	
+		iRSACertsAllowed = EFalse; 
+		iDSACertsAllowed = EFalse;
+		
+		for (TInt i = 0; i < aAllowedCipherSuites.Count(); i++)
+		{
+			if (EapTlsPeapUtils::CipherSuiteUseRSAKeys(static_cast<tls_cipher_suites_e>(aAllowedCipherSuites[i])))
+			{
+				iRSACertsAllowed = ETrue;
+			}
+			else if (EapTlsPeapUtils::CipherSuiteUseDSAKeys(static_cast<tls_cipher_suites_e>(aAllowedCipherSuites[i])))
+			{
+				iDSACertsAllowed = ETrue;
+			}
+		}
+	}
+
+	iState = EGetMatchingCertsInitStore;
+	
+	if (iCertStore == 0)
+	{
+		iCertStore = CUnifiedCertStore::NewL(iFs, false);
+		iCertStore->Initialize(iStatus);		
+	}
+	else
+	{
+		TRequestStatus* status = &iStatus;
+		User::RequestComplete(status, KErrNone);		
+	}		
+	SetActive();	
+	
+	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+}
+
+//--------------------------------------------------
+
+void CEapTlsPeapCertInterface::ReadCertificateL(SCertEntry& aCertInfo, const TBool aRetrieveChain)
+{	
+	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
+	iCertInfo = aCertInfo;
+	iRetrieveChain = aRetrieveChain;
+	iState = EReadCertInitStore;
+	
+	if (iCertStore == 0)
+	{
+		iCertStore = CUnifiedCertStore::NewL(iFs, false);
+		iCertStore->Initialize(iStatus);		
+	}
+	else
+	{
+		TRequestStatus* status = &iStatus;
+		User::RequestComplete(status, KErrNone);		
+	}		
+	SetActive();			
+	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+}
+
+//--------------------------------------------------
+
+void CEapTlsPeapCertInterface::ReadCACertificateL(SCertEntry& aCertInfo)
+{	
+	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
+	EAP_TRACE_DEBUG(m_am_tools, TRACE_FLAGS_DEFAULT, (EAPL("CEapTlsPeapCertInterface::ReadCACertificateL.\n")));
+	
+	iCertInfo = aCertInfo;
+	iState = EReadCACertInitStore;
+	
+	if (iCertStore == 0)
+	{
+		iCertStore = CUnifiedCertStore::NewL(iFs, false);
+		iCertStore->Initialize(iStatus);		
+	}
+	else
+	{
+		TRequestStatus* status = &iStatus;
+		User::RequestComplete(status, KErrNone);		
+	}		
+	SetActive();			
+	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+}
+
+
+//--------------------------------------------------
+
+void CEapTlsPeapCertInterface::ValidateChainL(TDesC8& aCertChain, RArray<SCertEntry>& aAllowedCACerts)
+{	
+	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);	
+	iCAIndex = 0;
+	iAllowedCACerts = aAllowedCACerts;
+	delete iInputCertChain;
+
+	iInputCertChain = 0;
+	iInputCertChain = aCertChain.AllocL();
+	iState = EValidateChainInitStore;
+	if (iCertStore == 0)
+	{
+		iCertStore = CUnifiedCertStore::NewL(iFs, false);
+		iCertStore->Initialize(iStatus);		
+	}
+	else
+	{
+		TRequestStatus* status = &iStatus;
+		User::RequestComplete(status, KErrNone);		
+	}
+	SetActive();
+	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+}
+
+//--------------------------------------------------
+
+void CEapTlsPeapCertInterface::DoCancel()
+{
+	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
+
+	EAP_TRACE_DEBUG(
+		m_am_tools,
+		TRACE_FLAGS_DEFAULT,
+		(EAPL("CEapTlsPeapCertInterface::DoCancel()\n")));
+
+	if (iCertStore != 0 && iCertStore->IsActive())
+	{
+		EAP_TRACE_DEBUG(
+			m_am_tools,
+			TRACE_FLAGS_DEFAULT,
+			(EAPL("CEapTlsPeapCertInterface::DoCancel(): calls iCertStore->CancelInitialize and other cancels()\n")));
+	
+		iCertStore->CancelInitialize();	
+		iCertStore->CancelList();
+		iCertStore->CancelGetCert();
+		iCertStore->CancelRetrieve();
+	}
+	
+	// We have to cancel singing if it is ongoing. Both for RSA and DSA.
+	if(iRSASigner != 0)
+	{
+		EAP_TRACE_DEBUG(
+			m_am_tools,
+			TRACE_FLAGS_DEFAULT,
+			(EAPL("CEapTlsPeapCertInterface::DoCancel(): calls iRSASigner->CancelSign()\n")));
+	
+		iRSASigner->CancelSign();
+		
+		EAP_TRACE_DEBUG(
+			m_am_tools,
+			TRACE_FLAGS_DEFAULT,
+			(EAPL("CEapTlsPeapCertInterface::DoCancel(): calls iRSASigner->Release()\n")));
+		
+		iRSASigner->Release(); // This seems to be needed.
+	}
+
+	if(iDSASigner != 0)
+	{
+		EAP_TRACE_DEBUG(
+			m_am_tools,
+			TRACE_FLAGS_DEFAULT,
+			(EAPL("CEapTlsPeapCertInterface::DoCancel(): calls iDSASigner->CancelSign()\n")));
+	
+		iDSASigner->CancelSign();
+		
+		EAP_TRACE_DEBUG(
+			m_am_tools,
+			TRACE_FLAGS_DEFAULT,
+			(EAPL("CEapTlsPeapCertInterface::DoCancel(): calls iDSASigner->Release()\n")));
+		
+		iDSASigner->Release(); // This seems to be needed.		
+	}
+
+	// We have to cancel decrypting if it is ongoing.
+	if(iDecryptor != 0)
+	{
+		EAP_TRACE_DEBUG(
+			m_am_tools,
+			TRACE_FLAGS_DEFAULT,
+			(EAPL("CEapTlsPeapCertInterface::DoCancel(): calls iDecryptor->CancelDecrypt()\n")));
+	
+		iDecryptor->CancelDecrypt();
+	}
+	
+	if (iKeyStore != 0 && iKeyStore->IsActive())
+	{
+		EAP_TRACE_DEBUG(
+			m_am_tools,
+			TRACE_FLAGS_DEFAULT,
+			(EAPL("CEapTlsPeapCertInterface::DoCancel(): calls iKeyStore->CancelOpen()\n")));
+
+		iKeyStore->CancelOpen();
+		
+		EAP_TRACE_DEBUG(
+			m_am_tools,
+			TRACE_FLAGS_DEFAULT,
+			(EAPL("CEapTlsPeapCertInterface::DoCancel(): calls iKeyStore->Cancel()\n")));
+		
+		iKeyStore->Cancel();
+	}
+
+	if (iCertChain != 0)
+	{
+		EAP_TRACE_DEBUG(
+			m_am_tools,
+			TRACE_FLAGS_DEFAULT,
+			(EAPL("CEapTlsPeapCertInterface::DoCancel(): calls iCertChain->CancelValidate()\n")));
+	
+		iCertChain->CancelValidate();
+	}
+	
+	EAP_TRACE_DEBUG(
+		m_am_tools,
+		TRACE_FLAGS_DEFAULT,
+		(EAPL("CEapTlsPeapCertInterface::DoCancel(): returns\n")));
+
+	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+}
+
+//--------------------------------------------------
+	
+void CEapTlsPeapCertInterface::SignL(
+	TKeyIdentifier& aKeyId,
+	const TDesC8& aHashIn,
+	const TUint aSignatureLength)
+{
+	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);	
+	iKeyIdentifier = aKeyId;
+	if (aHashIn.Size() > KMaxHashLength)
+	{
+		EAP_TRACE_DEBUG(m_am_tools, TRACE_FLAGS_DEFAULT, (EAPL("ERROR: Illegal hash size to SignL.\n")));
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		User::Leave(KErrGeneral);		
+	}
+	iHashIn.Copy(aHashIn);
+
+	delete iSignature;
+	iSignature = 0;
+
+	// Allocate space for the signature
+	iSignature = HBufC8::NewL(aSignatureLength);
+
+	delete iSignaturePtr;
+	iSignaturePtr = 0;
+
+	iSignaturePtr = new(ELeave) TPtr8(iSignature->Des());
+
+	EAP_TRACE_DATA_DEBUG(m_am_tools, TRACE_FLAGS_DEFAULT, (EAPL("SignL: aKeyId"),
+														   aKeyId.Ptr(),
+														   aKeyId.Length()));
+
+	EAP_TRACE_DATA_DEBUG(m_am_tools, TRACE_FLAGS_DEFAULT, (EAPL("SignL: aHashIn"),
+														   aHashIn.Ptr(),
+														   aHashIn.Length()));
+	
+	
+	if (iKeyStore == 0)
+	{
+		// Try to get the keystore class pointer from memory store
+		eap_variable_data_c key(m_am_tools);
+		eap_status_e status = key.set_copy_of_buffer(KKeyStoreHandlePrefix, sizeof(KKeyStoreHandlePrefix));
+		if (status != eap_status_ok)
+		{
+			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+			User::Leave(KErrNoMemory);
+		}
+		status = key.add_data(KKeyStoreHandleKey, sizeof(KKeyStoreHandleKey));
+		if (status != eap_status_ok)
+		{
+			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+			User::Leave(KErrNoMemory);
+		}
+		
+		eap_tlv_message_data_c tlv_data(m_am_tools);
+		
+		status = m_am_tools->memory_store_get_data(&key, &tlv_data);
+		if (status != eap_status_ok)
+		{
+			EAP_TRACE_DEBUG(
+				m_am_tools,
+				TRACE_FLAGS_DEFAULT,
+				(EAPL("EAP_type_TLSPEAP: cannot get previous keystore handle.\n")));
+
+
+			// At this point we can set the passphrase timeout because it the passphrase 
+			// cache in the FS token server is still empty. Passphrase timeout setting clears 
+			// the cache.
+			iState = ESignInitStore;
+			
+			iKeyStore = CUnifiedKeyStore::NewL(iFs);
+			iKeyStore->Initialize(iStatus);		
+			
+			status = tlv_data.add_message_data(
+				eap_type_tlspeap_stored_keystore_handle,
+				sizeof(iKeyStore),
+				&iKeyStore);
+			if (status != eap_status_ok)
+			{
+				EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+				User::Leave(KErrNoMemory);
+			}		
+			
+			status = m_am_tools->memory_store_add_data(
+				&key,
+				&tlv_data,
+				0);
+			if (status != eap_status_ok)
+			{			
+				EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+				User::Leave(KErrNoMemory);
+			}
+		}
+		else
+		{		
+			
+			status = m_am_tools->memory_store_get_data(&key, &tlv_data);
+			
+			EAP_TRACE_DEBUG(
+				m_am_tools,
+				TRACE_FLAGS_DEFAULT,
+				(EAPL("EAP_type_TLSPEAP: Found previous keystore handle.\n")));
+
+			// Parse read data.
+			eap_array_c<eap_tlv_header_c> tlv_blocks(m_am_tools);
+				
+			status = tlv_data.parse_message_data(&tlv_blocks);
+			if (status != eap_status_ok)
+			{
+				EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+				User::Leave(KErrGeneral);
+			}
+
+			if (tlv_blocks.get_object_count() > 0)
+			{
+				eap_tlv_header_c * const tlv = tlv_blocks.get_object(0);
+				if (tlv != 0)
+				{
+					if (tlv->get_type() == eap_type_tlspeap_stored_keystore_handle)
+					{
+						iKeyStore = *(reinterpret_cast<CUnifiedKeyStore **>(tlv->get_value(tlv->get_value_length())));
+						
+						// Skip passphrase setting because it clears the passphrase cache
+						iState = ESetPassphraseTimeout;
+							
+						TRequestStatus* status = &iStatus;
+						User::RequestComplete(status, KErrNone);
+						
+					}
+					else
+					{
+						EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+						User::Leave(KErrGeneral);
+					}
+				}
+				else
+				{
+					EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+					User::Leave(KErrGeneral);
+				}
+			}
+			else
+			{
+				EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+				User::Leave(KErrGeneral);
+			}			
+		}
+	}
+	else
+	{
+		// Skip passphrase setting because it clears the passphrase cache
+		iState = ESetPassphraseTimeout;
+
+		TRequestStatus* status = &iStatus;
+		User::RequestComplete(status, KErrNone);
+	}		
+	SetActive();
+
+
+		
+	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+}
+
+//--------------------------------------------------
+	
+void CEapTlsPeapCertInterface::DecryptL(
+	TKeyIdentifier& aKeyId,
+	const TDesC8& aDataIn)
+{
+	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);	
+	iKeyIdentifier = aKeyId;
+
+	delete iDataIn;
+	iDataIn = 0;
+	delete iDataOut;
+	iDataOut = 0;
+
+	iDataIn = HBufC8::NewL(aDataIn.Length());
+	iDataOut = HBufC8::NewL(aDataIn.Length());
+	
+	delete iPtrOut;
+	iPtrOut = 0;
+
+	iPtrOut = new(ELeave) TPtr8(iDataOut->Des());
+	TPtr8 ptrIn = iDataIn->Des();
+	
+	ptrIn.Copy(aDataIn);
+
+	iState = EDecryptInitStore;
+		
+	// Try to get the keystore handler class from memory store 
+	if (iKeyStore == 0)
+	{
+		// Try to get the keystore class pointer from memory store
+		eap_variable_data_c key(m_am_tools);
+		eap_status_e status = key.set_copy_of_buffer(KKeyStoreHandlePrefix, sizeof(KKeyStoreHandlePrefix));
+		if (status != eap_status_ok)
+		{
+			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+			User::Leave(KErrNoMemory);
+		}
+		status = key.add_data(KKeyStoreHandleKey, sizeof(KKeyStoreHandleKey));
+		if (status != eap_status_ok)
+		{
+			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+			User::Leave(KErrNoMemory);
+		}
+		
+		eap_tlv_message_data_c tlv_data(m_am_tools);
+		
+		status = m_am_tools->memory_store_get_data(&key, &tlv_data);
+		if (status != eap_status_ok)
+		{
+			EAP_TRACE_DEBUG(
+				m_am_tools,
+				TRACE_FLAGS_DEFAULT,
+				(EAPL("EAP_type_TLSPEAP: cannot get previous keystore handle.\n")));
+
+			iKeyStore = CUnifiedKeyStore::NewL(iFs);
+			iKeyStore->Initialize(iStatus);		
+			
+			status = tlv_data.add_message_data(
+				eap_type_tlspeap_stored_keystore_handle,
+				sizeof(iKeyStore),
+				&iKeyStore);
+			if (status != eap_status_ok)
+			{
+				EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+				User::Leave(KErrNoMemory);
+			}		
+			
+			status = m_am_tools->memory_store_add_data(
+				&key,
+				&tlv_data,
+				0);
+			if (status != eap_status_ok)
+			{			
+				EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+				User::Leave(KErrNoMemory);
+			}
+		}
+		else
+		{		
+			EAP_TRACE_DEBUG(
+				m_am_tools,
+				TRACE_FLAGS_DEFAULT,
+				(EAPL("EAP_type_TLSPEAP: Found previous keystore handle.\n")));
+
+			// Parse read data.
+			eap_array_c<eap_tlv_header_c> tlv_blocks(m_am_tools);
+				
+			status = tlv_data.parse_message_data(&tlv_blocks);
+			if (status != eap_status_ok)
+			{
+				EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+				User::Leave(KErrGeneral);
+			}
+
+			if (tlv_blocks.get_object_count() > 0)
+			{
+				eap_tlv_header_c * const tlv = tlv_blocks.get_object(0);
+				if (tlv != 0)
+				{
+					if (tlv->get_type() == eap_type_tlspeap_stored_keystore_handle)
+					{
+						iKeyStore = *(reinterpret_cast<CUnifiedKeyStore **>(tlv->get_value(tlv->get_value_length())));
+				
+						TRequestStatus* status = &iStatus;
+						User::RequestComplete(status, KErrNone);
+						
+					}
+					else
+					{
+						EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+						User::Leave(KErrGeneral);
+					}
+				}
+				else
+				{
+					EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+					User::Leave(KErrGeneral);
+				}
+			}
+			else
+			{
+				EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+				User::Leave(KErrGeneral);
+			}
+		}
+	}
+	else
+	{
+		TRequestStatus* status = &iStatus;
+		User::RequestComplete(status, KErrNone);
+	}		
+
+	SetActive();	
+	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+}
+
+//--------------------------------------------------
+
+void CEapTlsPeapCertInterface::RunL()
+{
+	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);		
+	
+	EAP_TRACE_DEBUG_SYMBIAN(
+	(_L("CEapTlsPeapCertInterface::RunL(): TEMP iStatus=%d, iState=%d"),
+	iStatus.Int(), iState));
+					
+	EAP_TRACE_DEBUG(
+		m_am_tools,
+		TRACE_FLAGS_DEFAULT,
+		(EAPL("CEapTlsPeapCertInterface::RunL(): iStatus %d\n"),
+		iStatus.Int()));
+
+	if (!(iStatus.Int() == KErrNone))
+	{		
+		EAP_TRACE_ERROR(
+			m_am_tools,
+			TRACE_FLAGS_DEFAULT,
+			(EAPL("ERROR: EAP-TLS certificate interface failed: %d.\n"),
+			iStatus.Int()));
+		iParent->SendErrorNotification(eap_status_user_cancel_authentication);
+		
+		if(iState == ESignOpenKeyStore)
+		{
+			// User probably cancelled the keystore password query.
+			
+			EAP_TRACE_DEBUG_SYMBIAN(
+			(_L("CEapTlsPeapCertInterface::RunL(): ESignOpenKeyStore Failed")));
+			
+			if(iRSASigner != NULL)
+			{
+				iRSASigner->Release();
+				
+				EAP_TRACE_DEBUG_SYMBIAN(
+				(_L("CEapTlsPeapCertInterface::RunL(): iRSASigner->Release() OK")));
+				
+			}
+			
+			if(iDSASigner != NULL)
+			{
+				iDSASigner->Release(); 
+				
+				EAP_TRACE_DEBUG_SYMBIAN(
+				(_L("CEapTlsPeapCertInterface::RunL(): iDSASigner->Release() OK")));							
+			}		
+		}
+		
+		return;
+	}
+
+	switch (iState)
+	{
+
+	case EGetMatchingCertsInitStore:
+		{
+			EAP_TRACE_DEBUG(
+				m_am_tools,
+				TRACE_FLAGS_DEFAULT,
+				(EAPL("CEapTlsPeapCertInterface::RunL(): EGetMatchingCertsInitStore\n")));
+
+			// Set up filter
+			delete iCertFilter;
+			iCertFilter = 0;
+
+			for (TInt i = 0; i < iCertInfos.Count(); i++)
+			{
+				iCertInfos[i]->Release();
+			}
+			iCertInfos.Reset();			
+			
+			TRAPD(err, iCertFilter = CCertAttributeFilter::NewL());
+			if (err != KErrNone)
+			{ 
+				EAP_TRACE_ERROR(m_am_tools, TRACE_FLAGS_DEFAULT, (EAPL("ERROR: Out of memory in EAP-TLS.\n")));
+				
+				CArrayFixFlat<SCertEntry> tmp(sizeof(SCertEntry));
+
+				m_am_tools->enter_global_mutex();
+				
+				iParent->complete_get_matching_certificates(tmp, eap_status_allocation_error); //Failure
+				
+				m_am_tools->leave_global_mutex();
+				break;
+			}
+			
+			iCertFilter->SetFormat(EX509Certificate);
+			iCertFilter->SetOwnerType(EUserCertificate);
+
+			iState = EGetMatchingCertsInitialize;
+			iCertStore->List(
+				iCertInfos,
+				*iCertFilter, 
+				iStatus);
+			SetActive();
+			
+		}
+		break;
+
+	case EGetMatchingCertsInitialize:
+		{
+			EAP_TRACE_DEBUG(
+				m_am_tools,
+				TRACE_FLAGS_DEFAULT,
+				(EAPL("CEapTlsPeapCertInterface::RunL(): EGetMatchingCertsInitialize, Total Certs: iCertInfos.Count()=%d\n"),
+				iCertInfos.Count()));
+
+			iMatchingUserCertInfos.Reset();
+
+			// Remove non-allowed
+			TInt i(0);
+			TInt j(0);
+			for (i = 0; i < iCertInfos.Count(); i++)
+			{
+				for (j = 0; j < iAllowedUserCerts.Count(); j++)
+				{				
+					if ( (iCertInfos[i]->Label().Compare(iAllowedUserCerts[j].iLabel) == 0
+						 || iCertInfos[i]->Label().Length() == 0
+						 || iAllowedUserCerts[j].iLabel.Length() == 0)
+						&& iCertInfos[i]->SubjectKeyId() == iAllowedUserCerts[j].iSubjectKeyId)
+					{
+
+						EAP_TRACE_DEBUG(
+							m_am_tools,
+							TRACE_FLAGS_DEFAULT,
+							(EAPL("RunL(): EGetMatchingCertsInitialize, Found a Matching USER cert\n")));
+
+						EAP_TRACE_DEBUG(
+							m_am_tools,
+							TRACE_FLAGS_DEFAULT,
+							(EAPL("RunL(): EGetMatchingCertsInitialize,Label of matching cert=%S\n"),
+							&(iCertInfos[i]->Label())));		
+						
+						EAP_TRACE_DATA_DEBUG_SYMBIAN(("RunL(): EGetMatchingCertsInitialize,SubjectkeyID of matching cert",
+						iCertInfos[i]->SubjectKeyId().Ptr(), iCertInfos[i]->SubjectKeyId().Size()));			
+
+						break;
+					}
+				}
+				if (j == iAllowedUserCerts.Count())
+				{
+					// Not allowed -> remove
+					iCertInfos.Remove(i);
+					i--;
+				}
+			}	
+			if (iCertInfos.Count() == 0)
+			{
+				EAP_TRACE_DEBUG(
+					m_am_tools,
+					TRACE_FLAGS_DEFAULT,
+					(EAPL("CEapTlsPeapCertInterface::RunL(): EGetMatchingCertsInitialize - No matching Certificates.\n")));
+			
+				// No matching certs
+				
+				CArrayFixFlat<SCertEntry>* tmp = NULL;
+				
+				TRAPD(err, tmp = new (ELeave) CArrayFixFlat<SCertEntry>(1) );
+				if (tmp == 0 || err != KErrNone)
+				{
+					// Timeout handles error situation
+					EAP_TRACE_ERROR(m_am_tools, TRACE_FLAGS_DEFAULT, (EAPL("ERROR: Out of memory in EAP-TLS.\n")));					
+				}
+				
+				m_am_tools->enter_global_mutex();
+				
+				iParent->complete_get_matching_certificates(*tmp, eap_status_illegal_certificate); //Failure
+				
+				m_am_tools->leave_global_mutex();
+
+				delete tmp;
+				break;
+			}
+
+			// Get the first certificate
+			iUserCertIndex = 0;
+
+			iMatchingUserCerts.ResetAndDestroy();
+							
+			iState = EGetMatchingCertsLoop;
+
+			iEncodedCertificate->Des().SetLength(0);
+			
+			TRAPD(err, iEncodedCertificate = iEncodedCertificate->ReAllocL(iCertInfos[iUserCertIndex]->Size()));
+			if (err != KErrNone)
+			{
+				EAP_TRACE_ERROR(m_am_tools, TRACE_FLAGS_DEFAULT, (EAPL("ERROR: Out of memory in EAP-TLS.\n")));
+				
+				CArrayFixFlat<SCertEntry> tmp(sizeof(SCertEntry));
+											
+				m_am_tools->enter_global_mutex();
+				
+				iParent->complete_get_matching_certificates(tmp, eap_status_allocation_error); //Failure
+				
+				m_am_tools->leave_global_mutex();
+
+				break;
+			}
+			
+			iCertPtr.Set(iEncodedCertificate->Des());
+
+			iCertStore->Retrieve(
+				*(iCertInfos[iUserCertIndex]), 
+				iCertPtr,
+				iStatus);
+			
+			SetActive();						
+		}		
+		break;
+
+	case EGetMatchingCertsLoop:
+		{
+			EAP_TRACE_DEBUG(
+				m_am_tools,
+				TRACE_FLAGS_DEFAULT,
+				(EAPL("CEapTlsPeapCertInterface::RunL(): EGetMatchingCertsLoop\n")));
+
+			CX509Certificate* cert = 0;
+			TRAPD(err, cert = CX509Certificate::NewL(iEncodedCertificate->Des()));
+			if (err != KErrNone || cert == 0)
+			{
+				EAP_TRACE_ERROR(m_am_tools, TRACE_FLAGS_DEFAULT, (EAPL("ERROR: Out of memory in EAP-TLS.\n")));
+				
+				CArrayFixFlat<SCertEntry> tmp(sizeof(SCertEntry));
+											
+				m_am_tools->enter_global_mutex();
+				
+				iParent->complete_get_matching_certificates(tmp, eap_status_allocation_error); //Failure
+				
+				m_am_tools->leave_global_mutex();
+
+				break;
+			}
+				
+			if (iMatchingUserCerts.Append(cert) != KErrNone)
+			{
+				delete cert;
+				EAP_TRACE_DEBUG(m_am_tools, TRACE_FLAGS_DEFAULT, (EAPL("ERROR: Out of memory in EAP-TLS.\n")));
+				
+				CArrayFixFlat<SCertEntry> tmp(sizeof(SCertEntry));
+
+				m_am_tools->enter_global_mutex();
+				
+				iParent->complete_get_matching_certificates(tmp, eap_status_allocation_error); //Failure
+				
+				m_am_tools->leave_global_mutex();
+							
+				break;
+			}
+			
+			// No need to validate iCertInfos here as the execution doesn't come to this case if iCertInfos
+			// is empty, check is done in the above case.
+						
+			SCertEntry entry;
+			entry.iLabel.Copy(iCertInfos[iUserCertIndex]->Label());
+			entry.iSubjectKeyId = iCertInfos[iUserCertIndex]->SubjectKeyId();
+			
+			TRAP(err, iMatchingUserCertInfos.AppendL(entry));
+			if (err != KErrNone)
+			{
+				EAP_TRACE_DEBUG(m_am_tools, TRACE_FLAGS_DEFAULT, (EAPL("ERROR: Out of memory in EAP-TLS.\n")));
+				
+				CArrayFixFlat<SCertEntry> tmp(sizeof(SCertEntry));
+				
+				m_am_tools->enter_global_mutex();
+				
+				iParent->complete_get_matching_certificates(tmp, eap_status_allocation_error); //Failure
+				
+				m_am_tools->leave_global_mutex();
+							
+				break;
+			}
+
+			iUserCertIndex++;
+
+			if (iUserCertIndex >= static_cast<TUint>(iCertInfos.Count()))
+			{				
+				// Check each item in iMatchingUserCerts against filters
+				TInt i(0);
+				
+				// CA filter
+				if (iUseCertAuthoritiesFilter)
+				{
+					for (i = 0; i < iMatchingUserCerts.Count(); i++)
+					{
+						const CX500DistinguishedName& dn = iMatchingUserCerts[i]->IssuerName();
+						
+						TInt j(0);
+
+						for (j = 0; j < iCertAuthorities.Count(); j++)
+						{
+							if (dn.ExactMatchL(*iCertAuthorities[j]))
+							{
+								// Matches
+								break;
+							}
+						}
+						if (j == iCertAuthorities.Count())
+						{						
+							// No match. Remove
+							delete iMatchingUserCerts[i];
+							iMatchingUserCerts.Remove(i);
+							iMatchingUserCertInfos.Delete(i);
+							i--;
+							
+							EAP_TRACE_DEBUG(
+								m_am_tools,
+								TRACE_FLAGS_DEFAULT,
+								(EAPL("RunL(): EGetMatchingCertsLoop Using CertAuthoritiesFilter - no distinguished name matching - Matching cert removed\n")));
+						}
+					}
+				}
+				// Check Certificate types
+				if (iUseCertTypesFilter)
+				{
+					for (i = 0; i < (TInt) iMatchingUserCerts.Count(); i++)
+					{
+						// Get the public key algorithm
+						const CSubjectPublicKeyInfo& public_key = iMatchingUserCerts[i]->PublicKey();
+						TAlgorithmId algorithm = public_key.AlgorithmId();
+						
+						TUint j(0);
+						for (j = 0; j < iCertTypes->get_object_count(); j++)
+						{
+							u8_t* val = iCertTypes->get_object(j);
+							if (algorithm == ERSA 
+								&& (*val == ERSASign
+								|| *val == ERSASignWithFixedDH 
+								|| *val == ERSASignWithEphemeralDH))
+							{
+								break;				
+							}
+							if (algorithm == EDSA 
+								&& (*val == EDSASign
+								|| *val == EDSASignWithFixedDH 
+								|| *val == EDSASignWithEphemeralDH))
+							{
+								break;				
+							}
+						}
+						if (j == iCertTypes->get_object_count())
+						{
+							// No match. Remove
+							delete iMatchingUserCerts[i];
+							iMatchingUserCerts.Remove(i);
+							iMatchingUserCertInfos.Delete(i);
+							i--;
+							
+							EAP_TRACE_DEBUG(
+								m_am_tools,
+								TRACE_FLAGS_DEFAULT,
+								(EAPL("RunL(): EGetMatchingCertsLoop Using CertTypesFilter - Public key algorithm(%d) or Signing methods NOT matching - Matching cert removed\n"),
+								algorithm));
+						}					
+
+					}
+				}
+				// Check cipher suites
+				if (iUseAllowedCipherSuitesFilter)
+				{
+					for (i = 0; i < static_cast<TUint> (iMatchingUserCerts.Count()); i++)
+					{
+						// Get the public key algorithm
+						const CSubjectPublicKeyInfo& public_key = iMatchingUserCerts[i]->PublicKey();
+						TAlgorithmId algorithm = public_key.AlgorithmId();		
+							
+						// IF it is RSA certificate that is not allowed
+						if (algorithm == ERSA && iRSACertsAllowed == EFalse
+							// OR it is DSA certificate that is not allowed
+							|| (algorithm == EDSA && iDSACertsAllowed == EFalse)
+							// OR it is some other type
+							|| (algorithm != ERSA && algorithm != EDSA))
+						{
+							// No match. Remove
+							delete iMatchingUserCerts[i];
+							iMatchingUserCerts.Remove(i);
+							iMatchingUserCertInfos.Delete(i);
+							i--;
+							
+							EAP_TRACE_DEBUG(
+								m_am_tools,
+								TRACE_FLAGS_DEFAULT,
+								(EAPL("RunL(): EGetMatchingCertsLoop Using AllowedCipherSuitesFilter -  Cert is NOT allowed (RSACertsAllowed=%d,DSACertsAllowed=%d) for this Public key algorithm(%d) - Matching cert removed\n"),
+								iRSACertsAllowed, iDSACertsAllowed, algorithm));							
+						}
+					}
+				}
+				// Return the certificates.
+				m_am_tools->enter_global_mutex();
+
+				iParent->complete_get_matching_certificates(iMatchingUserCertInfos, eap_status_ok);				
+
+				m_am_tools->leave_global_mutex();
+			}
+			else
+			{
+				
+				iState = EGetMatchingCertsLoop;
+
+				iEncodedCertificate->Des().SetLength(0);
+
+				TRAPD(err, iEncodedCertificate = iEncodedCertificate->ReAllocL(iCertInfos[iUserCertIndex]->Size()));
+				if (err != KErrNone)
+				{
+					EAP_TRACE_ERROR(m_am_tools, TRACE_FLAGS_DEFAULT, (EAPL("ERROR: Out of memory in EAP-TLS.\n")));
+				
+					CArrayFixFlat<SCertEntry> tmp(sizeof(SCertEntry));
+
+					m_am_tools->enter_global_mutex();
+					
+					iParent->complete_get_matching_certificates(tmp, eap_status_allocation_error); //Failure
+					
+					m_am_tools->leave_global_mutex();
+					
+					break;
+				}
+				
+				iCertPtr.Set(iEncodedCertificate->Des());
+
+				iCertStore->Retrieve(
+					*(iCertInfos[iUserCertIndex]), 
+					iCertPtr,
+					iStatus);
+							
+				SetActive();
+			}				
+		}
+		break;
+	
+	case EReadCertInitStore:
+		{
+			EAP_TRACE_DEBUG(
+				m_am_tools,
+				TRACE_FLAGS_DEFAULT,
+				(EAPL("CEapTlsPeapCertInterface::RunL(): EReadCertInitStore\n")));
+
+			// Set up filter
+			delete iCertFilter;
+			iCertFilter = 0;
+
+			for (TInt i = 0; i < iCertInfos.Count(); i++)
+			{
+				iCertInfos[i]->Release();
+			}
+			iCertInfos.Reset();			
+			
+			TRAPD(err, iCertFilter = CCertAttributeFilter::NewL());
+			if (err != KErrNone || iCertFilter == 0)
+			{ 
+				EAP_TRACE_ERROR(m_am_tools, TRACE_FLAGS_DEFAULT, (EAPL("ERROR: Out of memory in EAP-TLS.\n")));
+				
+				RPointerArray<CX509Certificate> tmp;
+				
+				m_am_tools->enter_global_mutex();
+				
+				iParent->complete_read_own_certificate(tmp, eap_status_allocation_error); //Failure
+				
+				m_am_tools->leave_global_mutex();
+				
+				break;
+			}
+			
+			iCertFilter->SetFormat(EX509Certificate);
+			iCertFilter->SetOwnerType(EUserCertificate);
+			iCertFilter->SetSubjectKeyId(iCertInfo.iSubjectKeyId);
+			if (iCertInfo.iLabel.Size()>0)
+				iCertFilter->SetLabel(iCertInfo.iLabel); // We can not use Label in the filter as certificates saved
+													   // by using SetConfigurationL (OMA DM etc uses it) will not have Label.
+
+			iState = EReadCertList;
+			iCertStore->List(
+				iCertInfos,
+				*iCertFilter, 
+				iStatus);
+			SetActive();
+			
+		}	
+		break;
+	
+	case EReadCertList:
+		{
+			EAP_TRACE_DEBUG(
+				m_am_tools,
+				TRACE_FLAGS_DEFAULT,
+				(EAPL("CEapTlsPeapCertInterface::RunL(): EReadCertList\n")));
+
+			// Now we should have all the cert infos in iCertInfos.			
+			if (iCertInfos.Count() == 0)
+			{
+				EAP_TRACE_ERROR(m_am_tools, TRACE_FLAGS_DEFAULT, (EAPL("ERROR: EReadCertList iCertInfos.Count = 0.\n")));			
+				
+				RPointerArray<CX509Certificate> tmp;
+				
+				m_am_tools->enter_global_mutex();
+				
+				iParent->complete_read_own_certificate(tmp, eap_status_illegal_certificate); //Failure
+				
+				m_am_tools->leave_global_mutex();
+
+				break;
+			}
+			
+			// Just take the first found certificate
+			CCTCertInfo* info;
+			info = iCertInfos[0];			
+
+			iState = EReadCert;
+			
+			iEncodedCertificate->Des().SetLength(0);
+
+			TRAPD(err, iEncodedCertificate = iEncodedCertificate->ReAllocL(info->Size()));
+			if (err != KErrNone)
+			{
+				EAP_TRACE_ERROR(m_am_tools, TRACE_FLAGS_DEFAULT, (EAPL("ERROR: Out of memory in EAP-TLS.\n")));			
+				
+				RPointerArray<CX509Certificate> tmp;
+								
+				m_am_tools->enter_global_mutex();
+				
+				iParent->complete_read_own_certificate(tmp, eap_status_allocation_error); //Failure
+				
+				m_am_tools->leave_global_mutex();
+				
+				break;
+			}
+				
+			iCertPtr.Set(iEncodedCertificate->Des());
+			
+			iCertStore->Retrieve(
+				*info, 
+				iCertPtr,
+				iStatus);
+			
+			SetActive();			
+		}
+		break;
+	case EReadCert:
+		{
+			EAP_TRACE_DEBUG(
+				m_am_tools,
+				TRACE_FLAGS_DEFAULT,
+				(EAPL("CEapTlsPeapCertInterface::RunL(): EReadCert\n")));
+
+			CX509Certificate* cert = 0;
+			TRAPD(err, cert = CX509Certificate::NewL(iEncodedCertificate->Des()));
+			if (err != KErrNone)
+			{
+				EAP_TRACE_ERROR(m_am_tools, TRACE_FLAGS_DEFAULT, (EAPL("ERROR: Out of memory in EAP-TLS.\n")));			
+				
+				RPointerArray<CX509Certificate> tmp;
+								
+				m_am_tools->enter_global_mutex();
+				
+				iParent->complete_read_own_certificate(tmp, eap_status_allocation_error); //Failure
+				
+				m_am_tools->leave_global_mutex();
+				
+				break;
+			}
+			
+			iUserCertChain.ResetAndDestroy();
+			if (iUserCertChain.Append(cert) != KErrNone)
+			{
+				delete cert;
+				EAP_TRACE_ERROR(m_am_tools, TRACE_FLAGS_DEFAULT, (EAPL("ERROR: Out of memory in EAP-TLS.\n")));			
+				
+				RPointerArray<CX509Certificate> tmp;
+								
+				m_am_tools->enter_global_mutex();
+				
+				iParent->complete_read_own_certificate(tmp, eap_status_allocation_error); //Failure
+				
+				m_am_tools->leave_global_mutex();
+				
+				break;
+			}
+			
+			EAP_TRACE_DEBUG(
+				m_am_tools,
+				TRACE_FLAGS_DEFAULT,
+				(EAPL("CEapTlsPeapCertInterface::RunL()-EReadCert: iRetrieveChain=%d\n"),
+				iRetrieveChain));
+			if (iRetrieveChain)
+			{
+				// Init Symbian store for cert fetching
+				iState = ERetrieveChainInitStore;
+				if (iCertStore == 0)
+				{
+					iCertStore = CUnifiedCertStore::NewL(iFs, false);
+					iCertStore->Initialize(iStatus);		
+				}
+				else
+				{
+					TRequestStatus* status = &iStatus;
+					User::RequestComplete(status, KErrNone);		
+				}
+				SetActive();
+				break;
+			}
+			
+			// Note that parent handles cert deletion from now on.
+			iParent->complete_read_own_certificate(iUserCertChain, eap_status_ok);
+		}
+		break;
+
+	case ERetrieveChainInitStore:
+		{		
+			EAP_TRACE_DEBUG(
+				m_am_tools,
+				TRACE_FLAGS_DEFAULT,
+				(EAPL("CEapTlsPeapCertInterface::RunL(): ERetrieveChainInitStore\n")));
+
+			// List all certificates
+			delete iCertFilter;
+			iCertFilter = 0;
+
+			for (TInt i = 0; i < iCertInfos.Count(); i++)
+			{
+				iCertInfos[i]->Release();
+			}
+			iCertInfos.Reset();			
+			
+			TRAPD(err, iCertFilter = CCertAttributeFilter::NewL());
+			if (err != KErrNone)
+			{ 
+				EAP_TRACE_ERROR(m_am_tools, TRACE_FLAGS_DEFAULT, (EAPL("ERROR: Out of memory in EAP-TLS.\n")));
+				
+				RPointerArray<CX509Certificate> tmp;
+								
+				m_am_tools->enter_global_mutex();
+				
+				iParent->complete_read_own_certificate(tmp, eap_status_allocation_error); //Failure
+				
+				m_am_tools->leave_global_mutex();
+				
+				break;
+			}
+			
+			iCertFilter->SetFormat(EX509Certificate);
+			iCertFilter->SetOwnerType(ECACertificate);
+
+			EAP_TRACE_DEBUG(
+				m_am_tools,
+				TRACE_FLAGS_DEFAULT,
+				(EAPL("CEapTlsPeapCertInterface::RunL(): For chain init store, we  need CA certificates only\n")));			
+
+			iState = EGetAllCerts;
+			iCertStore->List(
+				iCertInfos,
+				*iCertFilter, 
+				iStatus);
+			SetActive();
+		}
+		break;
+
+	case EGetAllCerts:
+		{
+			EAP_TRACE_DEBUG(
+				m_am_tools,
+				TRACE_FLAGS_DEFAULT,
+				(EAPL("CEapTlsPeapCertInterface::RunL(): EGetAllCerts\n")));
+
+			// Now we should have all the cert infos in iCertInfos.
+			
+			iRootCerts.ResetAndDestroy();
+			
+			// Validate iCertInfos before using it.
+			if (iCertInfos.Count() == 0)
+			{
+				EAP_TRACE_DEBUG(
+					m_am_tools,
+					TRACE_FLAGS_DEFAULT,
+					(EAPL("CEapTlsPeapCertInterface::RunL(): EGetAllCerts - No matching Certificates.\n")));
+			
+				// No matching certs. The authentication should fail now. So complete the request with an 
+				// empty chain.
+				
+				iUserCertChain.ResetAndDestroy();
+
+				m_am_tools->enter_global_mutex();
+				
+				// Note that parent handles cert deletion from now on.
+				iParent->complete_read_own_certificate(iUserCertChain, eap_status_illegal_certificate);
+
+				m_am_tools->leave_global_mutex();
+
+				break;
+			}
+			
+			CCTCertInfo* info;
+			info = iCertInfos[0];
+			iCAIndex = 0;
+
+			iState = ECreateCertChain;
+			
+			iEncodedCertificate->Des().SetLength(0);
+			TRAPD(err, iEncodedCertificate = iEncodedCertificate->ReAllocL(info->Size()));
+			if (err != KErrNone)
+			{
+				EAP_TRACE_ERROR(m_am_tools, TRACE_FLAGS_DEFAULT, (EAPL("ERROR: Out of memory in EAP-TLS.\n")));			
+				
+				RPointerArray<CX509Certificate> tmp;
+								
+				m_am_tools->enter_global_mutex();
+				
+				iParent->complete_read_own_certificate(tmp, eap_status_allocation_error); //Failure
+				
+				m_am_tools->leave_global_mutex();
+				
+				break;
+			}
+				
+			iCertPtr.Set(iEncodedCertificate->Des());
+			
+			iCertStore->Retrieve(
+				*info, 
+				iCertPtr,
+				iStatus);
+			
+			SetActive();			
+		}
+		break;
+
+	case ECreateCertChain:
+		{
+			EAP_TRACE_DEBUG(
+				m_am_tools,
+				TRACE_FLAGS_DEFAULT,
+				(EAPL("CEapTlsPeapCertInterface::RunL(): ECreateCertChain\n")));
+
+			CX509Certificate* cert = 0;
+			TRAPD(err, cert = CX509Certificate::NewL(iEncodedCertificate->Des()));
+			if (err != KErrNone || cert == 0)
+			{
+				EAP_TRACE_ERROR(m_am_tools, TRACE_FLAGS_DEFAULT, (EAPL("ERROR: Out of memory in EAP-TLS.\n")));			
+				
+				RPointerArray<CX509Certificate> tmp;
+								
+				m_am_tools->enter_global_mutex();
+				
+				iParent->complete_read_own_certificate(tmp, eap_status_allocation_error); //Failure
+				
+				m_am_tools->leave_global_mutex();
+				
+				break;
+			}
+			
+#if defined(_DEBUG) || defined(DEBUG)
+				
+				// No need to validate iCertInfos in here as it is done in case: EGetAllCerts
+				CCTCertInfo* tempInfo;
+				tempInfo = iCertInfos[iCAIndex];
+
+				// These are for the trace debug.
+				TCertLabel label = tempInfo->Label();				
+				TKeyIdentifier KeyIdentifier = tempInfo->SubjectKeyId();
+				TKeyIdentifier IssuerId = tempInfo->IssuerKeyId();
+				TCertificateFormat format = tempInfo->CertificateFormat();
+				TCertificateOwnerType ownerType = tempInfo->CertificateOwnerType();			
+				
+				EAP_TRACE_DEBUG_SYMBIAN((_L("\n CEapTlsPeapCertInterface::RunL() : About to retrieve Cert with details, Label = %S"), &label));
+				EAP_TRACE_DEBUG_SYMBIAN((_L("Other detials- Format=%d, Owner type=%d, IsDeletable=%d, Type UID=%d"),
+									format, ownerType, tempInfo->IsDeletable(), tempInfo->Type()));
+				
+				EAP_TRACE_DATA_DEBUG(m_am_tools, TRACE_FLAGS_DEFAULT, (EAPL("Subject key Id is"),
+					KeyIdentifier.Ptr(),
+					KeyIdentifier.Size()));
+
+				EAP_TRACE_DATA_DEBUG(m_am_tools, TRACE_FLAGS_DEFAULT, (EAPL("Issuer Id is"),
+					IssuerId.Ptr(),
+					IssuerId.Size()));
+					
+				EAP_TRACE_DEBUG(
+					m_am_tools,
+					TRACE_FLAGS_DEFAULT,
+					(EAPL("CEapTlsPeapCertInterface::RunL()- NEW subject key id stuff\n")));				
+			
+				if( cert != NULL )
+				{				
+					const CX509CertExtension* certExt = cert->Extension(KSubjectKeyId);
+					
+					if (certExt)
+					{
+						const CX509SubjectKeyIdExt* subKeyExt = CX509SubjectKeyIdExt::NewLC(certExt->Data());
+						EAP_UNREFERENCED_PARAMETER(subKeyExt);
+
+						EAP_TRACE_DATA_DEBUG(m_am_tools, TRACE_FLAGS_DEFAULT, (EAPL("NEW Subject key Id is:"),
+							subKeyExt->KeyId().Ptr(),
+							subKeyExt->KeyId().Size()));					
+
+						CleanupStack::PopAndDestroy(); // subKeyIdExt
+					}
+					else
+					{
+						EAP_TRACE_ERROR(m_am_tools, TRACE_FLAGS_DEFAULT, (EAPL("WARNING: No extension for this certificate\n")));			
+					}
+				}
+				else
+				{
+					EAP_TRACE_ERROR(m_am_tools, TRACE_FLAGS_DEFAULT, (EAPL("ERROR: No Certs here!\n")));			
+				}
+					
+#endif
+			
+		
+			// Signal completition
+			if (iRootCerts.Append(cert) != KErrNone)
+			{
+				delete cert;
+				EAP_TRACE_ERROR(m_am_tools, TRACE_FLAGS_DEFAULT, (EAPL("ERROR: Out of memory in EAP-TLS.\n")));			
+				
+				RPointerArray<CX509Certificate> tmp;
+								
+				m_am_tools->enter_global_mutex();
+				
+				iParent->complete_read_own_certificate(tmp, eap_status_allocation_error); //Failure
+				
+				m_am_tools->leave_global_mutex();
+				
+				break;
+			}
+
+			EAP_TRACE_DEBUG(
+				m_am_tools,
+				TRACE_FLAGS_DEFAULT,
+				(EAPL("CEapTlsPeapCertInterface::RunL()-ECreateCertChain: iCAIndex=%d, iRootCerts.Count()=%d, iUserCertChain.Count()= %d, iCertInfos-count=%d\n"),
+				iCAIndex, iRootCerts.Count(), iUserCertChain.Count(), iCertInfos.Count()));
+
+			iCAIndex++;
+			if (iCAIndex >= static_cast<TUint>(iCertInfos.Count()))
+			{
+				if(iUserCertChain.Count() == 0)
+				{
+					iParent->complete_read_own_certificate(iUserCertChain, eap_status_ca_certificate_unknown);
+					break;
+				}
+			
+				// We got all. Validate.
+				TInt i(0);
+				for (i = 0; i < iRootCerts.Count(); i++)
+				{
+					if (iUserCertChain[iUserCertChain.Count()-1]->IsSelfSignedL())
+					{
+						// The last cert in chain is self-signed. Our chain is ready.
+						
+						EAP_TRACE_DEBUG(
+							m_am_tools,
+							TRACE_FLAGS_DEFAULT,
+							(EAPL("CEapTlsPeapCertInterface::RunL()-ECreateCertChain: The last cert in chain is self-signed\n")));
+						
+						break;
+					}
+					if (iUserCertChain[iUserCertChain.Count()-1]->IssuerName().ExactMatchL(iRootCerts[i]->SubjectName()))
+					{
+						// DNs match. Check signature.
+						if (iUserCertChain[iUserCertChain.Count()-1]->PublicKey().AlgorithmId() != iRootCerts[i]->PublicKey().AlgorithmId())
+						{
+							// The algorithms differ.
+							continue;
+						}
+						CDSAParameters* dsaParams = 0;
+						CSigningKeyParameters* signParams = 0;
+
+						if (iUserCertChain[iUserCertChain.Count()-1]->PublicKey().AlgorithmId() == EDSA)
+						{
+							// DSA signing
+							const CSubjectPublicKeyInfo& key = iRootCerts[i]->PublicKey();
+							const TPtrC8 params = key.EncodedParams();	
+							
+							TRAPD(err, dsaParams = CX509DSAPublicKey::DSAParametersL(params));
+							if (err != KErrNone)
+							{				
+				
+								RPointerArray<CX509Certificate> tmp;
+								m_am_tools->enter_global_mutex();
+								
+								iParent->complete_read_own_certificate(tmp, eap_status_allocation_error); //Failure
+								
+								m_am_tools->leave_global_mutex();
+				
+								return;
+							}					
+									
+							TRAP(err, signParams = CSigningKeyParameters::NewL());
+							if (err != KErrNone)
+							{				
+								RPointerArray<CX509Certificate> tmp;
+				
+								m_am_tools->enter_global_mutex();
+								
+								iParent->complete_read_own_certificate(tmp, eap_status_allocation_error); //Failure
+								
+								m_am_tools->leave_global_mutex();				
+
+								delete dsaParams;
+								return;
+							}
+							TRAP(err, signParams->SetDSAParamsL(*dsaParams));
+							if (err != KErrNone)
+							{				
+								RPointerArray<CX509Certificate> tmp;
+								
+								m_am_tools->enter_global_mutex();
+								
+								iParent->complete_read_own_certificate(tmp, eap_status_allocation_error); //Failure
+								
+								m_am_tools->leave_global_mutex();
+				
+								delete dsaParams;
+								delete signParams;
+								return;
+							}
+
+							TRAP(err, iUserCertChain[iUserCertChain.Count()-1]->SetParametersL(*signParams));
+							if (err != KErrNone)
+							{
+								RPointerArray<CX509Certificate> tmp;
+								m_am_tools->enter_global_mutex();
+								
+								iParent->complete_read_own_certificate(tmp, eap_status_allocation_error); //Failure
+								
+								m_am_tools->leave_global_mutex();				
+							
+								delete dsaParams;
+								delete signParams;
+								return;
+							}
+						}						
+						
+						if (iUserCertChain[iUserCertChain.Count()-1]->VerifySignatureL(iRootCerts[i]->PublicKey().KeyData()))
+						{
+							// This is the next item in the chain.
+							if (iUserCertChain.Append(iRootCerts[i]) != KErrNone)
+							{
+								delete dsaParams;
+								delete signParams;
+								EAP_TRACE_ERROR(m_am_tools, TRACE_FLAGS_DEFAULT, (EAPL("ERROR: Out of memory in EAP-TLS.\n")));
+								RPointerArray<CX509Certificate> tmp;
+								
+								m_am_tools->enter_global_mutex();
+								
+								iParent->complete_read_own_certificate(tmp, eap_status_allocation_error); //Failure
+								
+								m_am_tools->leave_global_mutex();
+				
+								return;
+							}
+							// Remove the copied pointer from original list
+							iRootCerts.Remove(i);
+							i--;
+						}
+						// delete all
+						delete dsaParams;
+						delete signParams;
+					}
+				}
+				
+				iRootCerts.ResetAndDestroy();
+
+				// The chain is complete
+			m_am_tools->enter_global_mutex();
+			
+			// Note that parent handles cert deletion from now on.
+			iParent->complete_read_own_certificate(iUserCertChain, eap_status_ok);
+
+			m_am_tools->leave_global_mutex();
+
+			}
+			else // if (iCAIndex >= static_cast<TUint>(iCertInfos.Count()))
+			{
+				CCTCertInfo* info;
+				info = iCertInfos[iCAIndex]; // No need to vvalidate iCertInfos, as execution comes 
+											 // here only if iCertInfos has more items than iCAIndex
+
+				iState = ECreateCertChain;
+				
+				EAP_TRACE_DEBUG(
+					m_am_tools,
+					TRACE_FLAGS_DEFAULT,
+					(EAPL("CEapTlsPeapCertInterface::RunL()- ECreateCertChain - Before Retrieve(): iCAIndex=%d, size=%d\n"),
+					iCAIndex, info->Size()));			
+
+				
+				
+				iEncodedCertificate->Des().SetLength(0);
+				TRAPD(err, iEncodedCertificate = iEncodedCertificate->ReAllocL(info->Size()));
+				if (err != KErrNone)
+				{
+					EAP_TRACE_ERROR(m_am_tools, TRACE_FLAGS_DEFAULT, (EAPL("ERROR: Out of memory in EAP-TLS.\n")));			
+				
+					RPointerArray<CX509Certificate> tmp;
+					
+					m_am_tools->enter_global_mutex();
+					
+					iParent->complete_read_ca_certificate(tmp, eap_status_allocation_error); //Failure
+					
+					m_am_tools->leave_global_mutex();
+				
+					break;
+				}
+				
+				iCertPtr.Set(iEncodedCertificate->Des());
+			
+				iCertStore->Retrieve(
+					*info, 
+					iCertPtr,
+					iStatus);
+				
+				SetActive();						
+			}
+		}
+		break;
+
+	case EReadCACertInitStore:
+		{			 
+			EAP_TRACE_DEBUG(
+				m_am_tools,
+				TRACE_FLAGS_DEFAULT,
+				(EAPL("CEapTlsPeapCertInterface::RunL(): EReadCACertInitStore\n")));
+
+			// Set up filter
+			delete iCertFilter;
+			iCertFilter = 0;
+
+			for (TInt i = 0; i < iCertInfos.Count(); i++)
+			{
+				iCertInfos[i]->Release();
+			}
+			iCertInfos.Reset();			
+			
+			TRAPD(err, iCertFilter = CCertAttributeFilter::NewL());
+			if (err != KErrNone)
+			{ 
+				EAP_TRACE_ERROR(m_am_tools, TRACE_FLAGS_DEFAULT, (EAPL("ERROR: Out of memory in EAP-TLS.\n")));
+				RPointerArray<CX509Certificate> tmp;
+				
+				m_am_tools->enter_global_mutex();
+				
+				iParent->complete_read_ca_certificate(tmp, eap_status_allocation_error); //Failure
+				
+				m_am_tools->leave_global_mutex();
+				break;
+			}
+			
+			iCertFilter->SetFormat(EX509Certificate);
+			iCertFilter->SetOwnerType(ECACertificate);
+			iCertFilter->SetSubjectKeyId(iCertInfo.iSubjectKeyId);
+			if (iCertInfo.iLabel.Size()>0)
+				iCertFilter->SetLabel(iCertInfo.iLabel);// We can not use Label in the filter as certificates saved
+													// by using SetConfigurationL (OMA DM etc uses it) will not have Label.
+
+			iState = EReadCACertList;
+			iCertStore->List(
+				iCertInfos,
+				*iCertFilter, 
+				iStatus);
+			SetActive();
+			
+		}	
+		break;
+	
+	case EReadCACertList:
+		{
+			EAP_TRACE_DEBUG(
+				m_am_tools,
+				TRACE_FLAGS_DEFAULT,
+				(EAPL("CEapTlsPeapCertInterface::RunL(): EReadCACertList\n")));
+
+			// Now we should have all the cert infos in iCertInfos.			
+			if (iCertInfos.Count() == 0)
+			{
+				EAP_TRACE_ERROR(m_am_tools, TRACE_FLAGS_DEFAULT, (EAPL("ERROR: EReadCACertList iCertInfos.Count = 0.\n")));
+				RPointerArray<CX509Certificate> tmp;
+				
+				m_am_tools->enter_global_mutex();
+				
+				iParent->complete_read_ca_certificate(tmp, eap_status_allocation_error); //Failure
+				
+				m_am_tools->leave_global_mutex();
+				break;
+			}
+			
+			// Just take the first found certificate
+			CCTCertInfo* info;
+			info = iCertInfos[0];			
+
+			iState = EReadCACert;
+			
+			iEncodedCertificate->Des().SetLength(0);
+
+			TRAPD(err, iEncodedCertificate = iEncodedCertificate->ReAllocL(info->Size()));
+			if (err != KErrNone)
+			{
+				EAP_TRACE_ERROR(m_am_tools, TRACE_FLAGS_DEFAULT, (EAPL("ERROR: Out of memory in EAP-TLS.\n")));			
+				RPointerArray<CX509Certificate> tmp;
+				
+				m_am_tools->enter_global_mutex();
+				
+				iParent->complete_read_ca_certificate(tmp, eap_status_allocation_error); //Failure
+				
+				m_am_tools->leave_global_mutex();
+				break;
+			}
+				
+			iCertPtr.Set(iEncodedCertificate->Des());
+			
+			iCertStore->Retrieve(
+				*info, 
+				iCertPtr,
+				iStatus);
+			
+			SetActive();			
+		}
+		break;
+		
+	case EReadCACert:
+		{
+			EAP_TRACE_DEBUG(
+				m_am_tools,
+				TRACE_FLAGS_DEFAULT,
+				(EAPL("CEapTlsPeapCertInterface::RunL(): EReadCACert\n")));
+				
+			EAP_TRACE_DEBUG(
+				m_am_tools,
+				TRACE_FLAGS_DEFAULT,
+				(EAPL("CEapTlsPeapCertInterface::RunL():EncodedCertificate string size=%d\n"),
+				iEncodedCertificate->Size()));		
+
+			CX509Certificate* cert = 0;
+			TRAPD(err, cert = CX509Certificate::NewL(iEncodedCertificate->Des()));
+			if (err != KErrNone)
+			{
+				EAP_TRACE_ERROR(m_am_tools, TRACE_FLAGS_DEFAULT, (EAPL("ERROR: Out of memory in EAP-TLS.\n")));			
+				RPointerArray<CX509Certificate> tmp;
+				
+				m_am_tools->enter_global_mutex();
+				
+				iParent->complete_read_ca_certificate(tmp, eap_status_allocation_error); //Failure
+				
+				m_am_tools->leave_global_mutex();
+				break;
+			}
+			
+			// Use iUserCertChain on purpose for this anyway even though this is CA cert.
+			iUserCertChain.ResetAndDestroy();
+			if (iUserCertChain.Append(cert) != KErrNone)
+			{
+				delete cert;
+				EAP_TRACE_ERROR(m_am_tools, TRACE_FLAGS_DEFAULT, (EAPL("ERROR: Out of memory in EAP-TLS.\n")));			
+				RPointerArray<CX509Certificate> tmp;
+				
+				m_am_tools->enter_global_mutex();
+				
+				iParent->complete_read_ca_certificate(tmp, eap_status_allocation_error); //Failure
+				
+				m_am_tools->leave_global_mutex();
+				break;
+			}
+			
+			// Note that parent handles cert deletion from now on.
+			iParent->complete_read_ca_certificate(iUserCertChain, eap_status_ok);					
+		}
+		break;
+
+	case EValidateChainInitStore:
+		{
+			EAP_TRACE_DEBUG(
+				m_am_tools,
+				TRACE_FLAGS_DEFAULT,
+				(EAPL("CEapTlsPeapCertInterface::RunL(): EValidateChainInitStore\n")));
+
+			delete iCertFilter;
+			iCertFilter = 0;
+
+			for (TInt i = 0; i < iCertInfos.Count(); i++)
+			{
+				iCertInfos[i]->Release();
+			}
+			iCertInfos.Reset();			
+			
+			TRAPD(err, iCertFilter = CCertAttributeFilter::NewL());
+			if (err != KErrNone)
+			{ 
+				EAP_TRACE_ERROR(m_am_tools, TRACE_FLAGS_DEFAULT, (EAPL("ERROR: Out of memory in EAP-TLS.\n")));
+				CPKIXValidationResult* tmp = 0;
+				
+				m_am_tools->enter_global_mutex();
+
+				iParent->complete_validate_chain(*tmp, eap_status_ca_certificate_unknown); //Failure.
+
+				m_am_tools->leave_global_mutex();
+				break;
+			}
+			iCertFilter->SetOwnerType(ECACertificate);
+			iCertFilter->SetFormat(EX509Certificate);
+
+			iState = EValidateChainGetCACertList;
+			iCertStore->List(
+				iCertInfos,
+				*iCertFilter, 
+				iStatus);
+			SetActive();		
+		}
+		break;
+
+	case EValidateChainGetCACertList:
+		{			
+			EAP_TRACE_DEBUG(
+				m_am_tools,
+				TRACE_FLAGS_DEFAULT,
+				(EAPL("CEapTlsPeapCertInterface::RunL(): EValidateChainGetCACertList\n")));
+
+			int index;			
+			TIdentityRelation<SCertEntry> comparator(&EapTlsPeapUtils::CompareSCertEntries);
+			// Remove disallowed CA certs from the array
+			for (TInt i = 0; i < iCertInfos.Count(); i++)
+			{
+				SCertEntry certEntry;
+				certEntry.iLabel.Copy(iCertInfos[i]->Label());
+				certEntry.iSubjectKeyId.Copy(iCertInfos[i]->SubjectKeyId());
+				index = iAllowedCACerts.Find(certEntry, comparator);
+				
+				if (index == KErrNotFound)
+				{
+					// Remove					
+					iCertInfos[i]->Release();
+					iCertInfos.Remove(i);
+					i--;
+				}
+			}
+			if (iCertInfos.Count() == 0)
+			{	
+				// Create new validation result for this failure case. 
+				// CPKIXValidationResult does include a Reset-member function
+				// but it is not in x500.lib as the documentation says.
+				CPKIXValidationResult* validationResult = 0;
+				TRAPD(err, validationResult = CPKIXValidationResult::NewL());
+				if (err != KErrNone)
+				{
+					// Do nothing. Session timeout takes care of cleanup...
+					EAP_TRACE_ERROR(m_am_tools, TRACE_FLAGS_DEFAULT, (EAPL("ERROR: Out of memory in EAP-TLS.\n")));			
+				}
+				m_am_tools->enter_global_mutex();
+
+				iParent->complete_validate_chain(*validationResult, eap_status_ca_certificate_unknown); //Failure.
+
+				m_am_tools->leave_global_mutex();
+				delete validationResult;
+				break;
+			}
+			
+			CCTCertInfo* info;
+			info = iCertInfos[0];
+			iCAIndex = 0;
+
+			iState = EValidateChainGetCACert;
+			
+			iEncodedCertificate->Des().SetLength(0);
+			TRAPD(err, iEncodedCertificate = iEncodedCertificate->ReAllocL(info->Size()));
+			if (err != KErrNone)
+			{
+				EAP_TRACE_ERROR(m_am_tools, TRACE_FLAGS_DEFAULT, (EAPL("ERROR: Out of memory in EAP-TLS.\n")));			
+				
+				CPKIXValidationResult* tmp = 0;
+				
+				m_am_tools->enter_global_mutex();
+
+				iParent->complete_validate_chain(*tmp, eap_status_ca_certificate_unknown); //Failure.
+
+				m_am_tools->leave_global_mutex();
+				break;
+			}
+				
+			iCertPtr.Set(iEncodedCertificate->Des());			
+
+			iCertStore->Retrieve(
+				*info, 
+				iCertPtr,
+				iStatus);
+			
+			SetActive();			
+		}
+		break;
+
+	case EValidateChainGetCACert:
+		{
+			EAP_TRACE_DEBUG(
+				m_am_tools,
+				TRACE_FLAGS_DEFAULT,
+				(EAPL("CEapTlsPeapCertInterface::RunL(): EValidateChainGetCACert\n")));
+
+			CX509Certificate* cert = 0;
+			TRAPD(err, cert = CX509Certificate::NewL(iEncodedCertificate->Des()));
+			if (err != KErrNone)
+			{
+				EAP_TRACE_ERROR(m_am_tools, TRACE_FLAGS_DEFAULT, (EAPL("ERROR: Out of memory in EAP-TLS.\n")));			
+				CPKIXValidationResult* tmp = 0;
+				
+				m_am_tools->enter_global_mutex();
+
+				iParent->complete_validate_chain(*tmp, eap_status_ca_certificate_unknown); //Failure.
+
+				m_am_tools->leave_global_mutex();
+				break;
+			}
+		
+			// Signal completition
+			if (iRootCerts.Append(cert) != KErrNone)
+			{
+				delete cert;
+				EAP_TRACE_ERROR(m_am_tools, TRACE_FLAGS_DEFAULT, (EAPL("ERROR: Out of memory in EAP-TLS.\n")));			
+				CPKIXValidationResult* tmp = 0;
+				
+				m_am_tools->enter_global_mutex();
+
+				iParent->complete_validate_chain(*tmp, eap_status_ca_certificate_unknown); //Failure.
+
+				m_am_tools->leave_global_mutex();
+				break;
+			}
+
+			iCAIndex++;
+			if (iCAIndex >= static_cast<TUint>(iCertInfos.Count()))
+			{
+				delete iCertChain;
+				iCertChain = 0;
+
+				TRAPD(err, iCertChain = CPKIXCertChain::NewL(iFs, *iInputCertChain, iRootCerts));
+				if (err != KErrNone)
+				{
+					EAP_TRACE_ERROR(m_am_tools, TRACE_FLAGS_DEFAULT, (EAPL("ERROR: EAP-TLS error %d.\n"), err));
+					CPKIXValidationResult* tmp = 0;
+					
+					m_am_tools->enter_global_mutex();
+
+					iParent->complete_validate_chain(*tmp, eap_status_ca_certificate_unknown); //Failure.
+
+					m_am_tools->leave_global_mutex();
+					break;
+				}
+				// Set the current time
+				iTime.UniversalTime();
+				iState = EValidateChainEnd;
+				TRAP(err, iCertChain->ValidateL(*iValidationResult, iTime, iStatus));
+				if (err != KErrNone)
+				{
+					EAP_TRACE_ERROR(m_am_tools, TRACE_FLAGS_DEFAULT, (EAPL("ERROR: Error in certificate validation in EAP-TLS.\n")));			
+					CPKIXValidationResult* tmp = 0;
+					
+					m_am_tools->enter_global_mutex();
+
+					iParent->complete_validate_chain(*tmp, eap_status_ca_certificate_unknown); //Failure.
+
+					m_am_tools->leave_global_mutex();
+					break;
+				}				
+				SetActive();	// Validate.
+			}
+			else
+			{
+				CCTCertInfo* info;
+				info = iCertInfos[iCAIndex];
+
+				iState = EValidateChainGetCACert;
+				
+				iEncodedCertificate->Des().SetLength(0);
+				TRAPD(err, iEncodedCertificate = iEncodedCertificate->ReAllocL(info->Size()));
+				if (err != KErrNone)
+				{
+					EAP_TRACE_ERROR(m_am_tools, TRACE_FLAGS_DEFAULT, (EAPL("ERROR: Out of memory in EAP-TLS.\n")));			
+					CPKIXValidationResult* tmp = 0;
+					
+					m_am_tools->enter_global_mutex();
+
+					iParent->complete_validate_chain(*tmp, eap_status_ca_certificate_unknown); //Failure.
+
+					m_am_tools->leave_global_mutex();
+					break;
+				}
+				
+				iCertPtr.Set(iEncodedCertificate->Des());
+			
+				iCertStore->Retrieve(
+					*info, 
+					iCertPtr,
+					iStatus);
+				
+				SetActive();						
+			}
+		}
+		break;
+	
+	case EValidateChainEnd:
+
+		EAP_TRACE_DEBUG(
+			m_am_tools,
+			TRACE_FLAGS_DEFAULT,
+			(EAPL("CEapTlsPeapCertInterface::RunL(): EValidateChainEnd\n")));
+		
+		m_am_tools->enter_global_mutex();
+		
+		iParent->complete_validate_chain(*iValidationResult, eap_status_ok);
+
+		m_am_tools->leave_global_mutex();
+		// Ignore error because there is nothing that can be done.
+		break;
+
+	case ESignInitStore:
+		{
+			EAP_TRACE_DEBUG(
+				m_am_tools,
+				TRACE_FLAGS_DEFAULT,
+				(EAPL("CEapTlsPeapCertInterface::RunL(): ESignInitStore\n")));
+
+			iState = ESetPassphraseTimeout;
+			iKeyStore->SetPassphraseTimeout(-1 , iStatus);
+			SetActive();
+		}
+		break;
+	
+	case ESetPassphraseTimeout:
+		{
+			EAP_TRACE_DEBUG(
+				m_am_tools,
+				TRACE_FLAGS_DEFAULT,
+				(EAPL("CEapTlsPeapCertInterface::RunL(): ESetPassphraseTimeout\n")));
+
+			// Set up filter
+			delete iKeyFilter;
+			iKeyFilter = 0;
+			
+			TRAPD(err, iKeyFilter = new (ELeave) TCTKeyAttributeFilter);
+			if (err != KErrNone)
+			{ 
+				EAP_TRACE_ERROR(m_am_tools, TRACE_FLAGS_DEFAULT, (EAPL("ERROR: Out of memory in EAP-TLS.\n")));
+				RInteger tmp;
+				iParent->complete_sign(tmp, tmp, eap_status_key_error);
+				break;
+			}
+			
+			iKeyFilter->iKeyId = iKeyIdentifier;
+			iKeyFilter->iPolicyFilter = TCTKeyAttributeFilter::EUsableKeys;			
+
+			iState = ESignList;
+			iKeyStore->List(
+				iKeyInfos,
+				*iKeyFilter, 
+				iStatus);
+			SetActive();					
+		}
+		break;
+
+	case ESignList:
+		{
+			EAP_TRACE_DEBUG(
+				m_am_tools,
+				TRACE_FLAGS_DEFAULT,
+				(EAPL("CEapTlsPeapCertInterface::RunL(): ESignList, iKeyInfos.Count=%d\n"),
+				iKeyInfos.Count()));
+				
+			if(iKeyInfos.Count() <= 0)				
+			{
+				RInteger tmp;
+				iParent->complete_sign(tmp, tmp, eap_status_key_error);
+				break;
+			}
+
+			iState = ESignOpenKeyStore;
+
+			CKeyInfoBase::EKeyAlgorithm rsa(static_cast<CKeyInfoBase::EKeyAlgorithm> (1));
+			
+			if (iKeyInfos[0]->Algorithm() == rsa)
+			{	
+				// Note to the CodeScanner users. This function does not return any value.
+				(void)iKeyStore->Open(
+					iKeyInfos[0]->Handle(), 
+					iRSASigner, 
+					iStatus);				
+			}
+			else
+			{				
+				// Note to the CodeScanner users. This function does not return any value.
+				(void)iKeyStore->Open(
+					iKeyInfos[0]->Handle(), 
+					iDSASigner, 
+					iStatus);
+			}
+			SetActive();			
+		}
+		break;
+
+	case ESignOpenKeyStore:
+		{
+			EAP_TRACE_DEBUG(
+				m_am_tools,
+				TRACE_FLAGS_DEFAULT,
+				(EAPL("CEapTlsPeapCertInterface::RunL(): ESignOpenKeyStore, iKeyInfos.Count=%d\n"),
+				iKeyInfos.Count()));
+
+			if(iKeyInfos.Count() <= 0)				
+			{
+				RInteger tmp;
+				iParent->complete_sign(tmp, tmp, eap_status_key_error);
+				break;
+			}
+
+			iState = ESign;
+			
+			CKeyInfoBase::EKeyAlgorithm rsa(static_cast<CKeyInfoBase::EKeyAlgorithm> (1));
+		
+			if (iKeyInfos[0]->Algorithm() == rsa)
+			{	
+				iRSASigner->Sign(
+					iHashIn, 
+					iRSASignature, 
+					iStatus);		
+			}
+			else
+			{												
+				iDSASigner->Sign(
+					iHashIn, 
+					iDSASignature, 
+					iStatus);		
+			}
+
+			SetActive();
+		}
+		break;
+		
+	case ESign:
+		{
+			EAP_TRACE_DEBUG(
+				m_am_tools,
+				TRACE_FLAGS_DEFAULT,
+				(EAPL("CEapTlsPeapCertInterface::RunL(): ESign, iKeyInfos.Count=%d\n"),
+				iKeyInfos.Count()));
+
+			if(iKeyInfos.Count() <= 0)				
+			{
+				RInteger tmp;
+				iParent->complete_sign(tmp, tmp, eap_status_key_error);
+				break;
+			}
+
+			CKeyInfoBase::EKeyAlgorithm rsa(static_cast<CKeyInfoBase::EKeyAlgorithm> (1));
+			
+			if (iKeyInfos[0]->Algorithm() == rsa)
+			{
+				// This is just dummy integer. It is ignored in RSA case.
+				RInteger R = RInteger::NewL();
+				
+				CleanupStack::PushL(R);
+				
+				iParent->complete_sign(R, reinterpret_cast<const RInteger&>(iRSASignature->S()), eap_status_ok);
+				
+				CleanupStack::PopAndDestroy();
+				
+				iRSASigner->Release(); // This seems to be needed.
+			}
+			else
+			{
+				iParent->complete_sign(reinterpret_cast<const RInteger&>(iDSASignature->R()), 
+					reinterpret_cast<const RInteger&>(iDSASignature->S()), eap_status_ok);
+				
+				iDSASigner->Release(); // This seems to be needed.
+			}			
+		}
+		break;
+	
+	case EDecryptInitStore:
+		{
+			EAP_TRACE_DEBUG(
+				m_am_tools,
+				TRACE_FLAGS_DEFAULT,
+				(EAPL("CEapTlsPeapCertInterface::RunL(): EDecryptInitStore\n")));
+
+			// Set up filter
+			delete iKeyFilter;
+			iKeyFilter = 0;
+			
+			TRAPD(err, iKeyFilter = new (ELeave) TCTKeyAttributeFilter);
+			if (err != KErrNone)
+			{ 
+				EAP_TRACE_ERROR(m_am_tools, TRACE_FLAGS_DEFAULT, (EAPL("ERROR: Out of memory in EAP-TLS.\n")));
+				TBuf8<1> tmp;
+				iParent->complete_decrypt(tmp, eap_status_key_error);
+				break;
+			}
+			
+			iKeyFilter->iKeyId = iKeyIdentifier;
+			iKeyFilter->iPolicyFilter = TCTKeyAttributeFilter::EUsableKeys;			
+
+			iState = EDecryptList;
+			iKeyStore->List(
+				iKeyInfos,
+				*iKeyFilter, 
+				iStatus);
+			SetActive();			
+		}
+		break;
+		
+	case EDecryptList:
+		{
+			EAP_TRACE_DEBUG(
+				m_am_tools,
+				TRACE_FLAGS_DEFAULT,
+				(EAPL("CEapTlsPeapCertInterface::RunL(): EDecryptList, iKeyInfos.Count=%d\n"),
+				iKeyInfos.Count()));
+
+			if(iKeyInfos.Count() <= 0)				
+			{
+				TBuf8<1> tmp;
+				iParent->complete_decrypt(tmp, eap_status_key_error);
+				break;
+			}
+
+			iState = EDecryptOpenKeyStore;			
+			
+			// Note to the CodeScanner users. This function does not return any value.
+			(void)iKeyStore->Open(
+				iKeyInfos[0]->Handle(),
+				iDecryptor,
+				iStatus);
+							
+			SetActive();
+		}
+		break;
+		
+	case EDecryptOpenKeyStore:
+		{
+			EAP_TRACE_DEBUG(
+				m_am_tools,
+				TRACE_FLAGS_DEFAULT,
+				(EAPL("CEapTlsPeapCertInterface::RunL(): EDecryptOpenKeyStore\n")));
+
+			iState = EDecrypt;
+								
+			iDecryptor->Decrypt(
+				*iDataIn, 	
+				*iPtrOut, 
+				iStatus);	
+			
+			SetActive();
+		}
+		break;
+		
+	case EDecrypt:
+		{			
+			EAP_TRACE_DEBUG(
+				m_am_tools,
+				TRACE_FLAGS_DEFAULT,
+				(EAPL("CEapTlsPeapCertInterface::RunL(): EDecrypt\n")));
+
+			iParent->complete_decrypt(*iPtrOut, eap_status_ok);
+		}
+		break;
+	
+	default:
+			EAP_TRACE_DEBUG(
+				m_am_tools,
+				TRACE_FLAGS_DEFAULT,
+				(EAPL("CEapTlsPeapCertInterface::RunL(): unknown %d\n"),
+				iState));
+		break;
+	}
+	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+	return;
+}
+
+void CEapTlsPeapCertInterface::CancelSignWithPrivateKey()
+{
+	EAP_TRACE_DEBUG(
+		m_am_tools,
+		TRACE_FLAGS_DEFAULT,
+		(EAPL("CEapTlsPeapCertInterface::CancelSignWithPrivateKey():Cancelling Signing - iState=%d (13=ESign)\n"),
+		iState));		
+
+	if(IsActive())
+	{
+		
+		// We have to cancel singing if it is ongoing. Both for RSA and DSA.
+		if(iRSASigner != 0)
+		{
+			EAP_TRACE_DEBUG(
+				m_am_tools,
+				TRACE_FLAGS_DEFAULT,
+				(EAPL("CEapTlsPeapCertInterface::CancelSignWithPrivateKey(): calls iRSASigner->CancelSign()\n")));
+		
+			iRSASigner->CancelSign();
+		}
+
+		if(iDSASigner != 0)
+		{
+			EAP_TRACE_DEBUG(
+				m_am_tools,
+				TRACE_FLAGS_DEFAULT,
+				(EAPL("CEapTlsPeapCertInterface::CancelSignWithPrivateKey(): calls iDSASigner->CancelSign()\n")));
+		
+			iDSASigner->CancelSign();
+		}
+	}	
+}
+
+// End of file