vpnengine/ikecert/src/ikev2pkiservice.cpp
changeset 0 33413c0669b9
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vpnengine/ikecert/src/ikev2pkiservice.cpp	Thu Dec 17 09:14:51 2009 +0200
@@ -0,0 +1,812 @@
+/*
+* Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "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:   IKEv2 specifig certificate reading related stuff
+*
+*/
+
+#include <x500dn.h>
+#include <x509cert.h>
+#include <asn1dec.h>
+
+#include "ikev2pkiservice.h"
+#include "utlcrypto.h"
+#include "ikecert.h"
+#include "ikecaelem.h"
+#include "ikecalist.h"
+#include "ikedebug.h"
+#include "ikepolparser.h"
+#include "ikev2const.h"
+#include "ikecertconst.h"
+//
+// CIkePkiService Class
+//
+_LIT8(KEmptyString, "");
+
+
+const TInt KDefaultCertificateBufferSize = 2048;
+
+//
+//  Certificate field indicators for GetCertificateFieldDERL()
+//
+
+#ifdef _DEBUG
+
+#define SET_ACTIVE DEBUG_LOG2(_L("CIkeV2PkiService::SetActive (0x%x) %d\n"), this, __LINE__);\
+                   SetActive()
+
+#else
+
+#define SET_ACTIVE SetActive()
+
+#endif 
+
+
+EXPORT_C CIkeV2PkiService* CIkeV2PkiService::NewL(MIkeV2PkiServiceObserver& aObserver, MIkeDebug& aDebug)
+    {     
+    CIkeV2PkiService* self = new (ELeave) CIkeV2PkiService(aObserver, aDebug);
+    CleanupStack::PushL(self);
+    self->ConstructL();
+    CleanupStack::Pop(self);
+    return self;
+    }
+
+
+CIkeV2PkiService::CIkeV2PkiService(MIkeV2PkiServiceObserver& aObserver, MIkeDebug& aDebug)
+    :CActive(EPriorityStandard),  
+    iObserver(aObserver),
+    iDebug(aDebug),
+    iState(EPkiServiceIdle),     
+    iCertPtr(NULL, 0)
+    {
+    CActiveScheduler::Add(this);
+    }
+
+
+void CIkeV2PkiService::ConstructL()
+    {    
+    User::LeaveIfError(iPkiService.Connect());
+
+    iTrustedCAList   = new (ELeave) CIkeCaList(2);
+    iReadCertificate = HBufC8::NewL(KDefaultCertificateBufferSize);
+    iCertPtr.Set(iReadCertificate->Des());
+
+    //The code assumes that these are not NULL.
+    //Reallocated, when needed
+    iSubjName = HBufC8::NewL(2);      
+    iRfc822Name = HBufC8::NewL(2);              
+    }
+
+
+EXPORT_C CIkeV2PkiService::~CIkeV2PkiService()
+    {
+	Cancel();
+
+    delete iUserCertificate;
+    delete i1Certificate;
+    delete i2Certificate;
+    delete i2CertificateName;
+	delete iTrustedCAList;
+
+    iCasTrustedByPeer.Reset();
+    iCasTrustedByPeer.Close();
+
+	delete iCaName;
+	delete iReadCertificate;
+	delete iSubjName;
+	delete iRfc822Name;
+	
+	iPkiService.Close();	
+    }
+
+
+void CIkeV2PkiService::DoCancel()
+    {
+    
+    iPkiService.CancelPendingOperation();    
+    iState = EPkiServiceIdle;
+    
+    delete iCaName;
+    iCaName = NULL;
+
+    __ASSERT_DEBUG(iReadCertificate != NULL, User::Invariant());
+    iReadCertificate->Des().Zero();
+    
+        
+    __ASSERT_DEBUG(iSubjName != NULL, User::Invariant());
+    iSubjName->Des().Zero();
+    
+    __ASSERT_DEBUG(iRfc822Name != NULL, User::Invariant());
+    iRfc822Name->Des().Zero();
+
+			
+    iCasTrustedByPeer.Reset();    
+    
+    delete iIkeDataCAList;		
+    iIkeDataCAList = NULL;
+    
+    iTrustedCAList->ResetAndDestroy();
+    }
+
+
+TInt CIkeV2PkiService::RunError(TInt /*aError*/)
+    {    
+    //Currently RunL may leave.
+    //But we seem to ignore the possible leave.
+    
+	return KErrNone; 
+    }
+
+
+EXPORT_C void CIkeV2PkiService::ReadTrustedUserCertificateL()
+    {    
+    __ASSERT_ALWAYS(!IsActive(), User::Invariant());
+    __ASSERT_ALWAYS(iTrustedCAList != NULL, User::Invariant());    
+    __ASSERT_ALWAYS(iIkeData->iOwnCert.iOwnCertExists, User::Invariant());
+
+    iCasTrustedByPeer.Reset();
+		
+	for (TInt i = 0; i < iTrustedCAList->Count(); ++i)
+	    {		    
+        CIkeCaElem* caElem = (*iTrustedCAList)[i];
+        User::LeaveIfError(iCasTrustedByPeer.Append(caElem));
+	    }
+
+
+    iState = EReadingCertificate;
+
+    if (iTrustedCAList->Count() > 0)
+        {
+        CIkeCaElem* CaElem = iCasTrustedByPeer[0];	                   
+        HBufC8* caName = IkeCert::GetCertificateFieldDERL(CaElem->Certificate(), KSubjectName);
+        if (caName == NULL)
+            {
+            User::Leave(KErrArgument);
+            }
+        delete iCaName;
+        iCaName = caName;
+        
+        ReadUserCertificateL(*iCaName, EFalse);
+        }
+    else
+        {
+        //No CA's found.
+        //We can't read anything
+        User::Leave(KErrNotFound);
+        }
+    }
+
+
+EXPORT_C TInt CIkeV2PkiService::Ikev2SignatureL(const TDesC8& aTrustedAuthority, 
+                                                const TOwnCertInfo& aOwnCertInfo, 
+                                                const TDesC8& aMsgOctets, 
+                                                TDes8& aSignature, TUint8 aAuthMeth)
+    {
+    __ASSERT_ALWAYS(!IsActive(), User::Invariant());	
+
+	TPKIKeyAlgorithm keyAlgorithm = EPKIRSA;	
+    TInt length = aOwnCertInfo.iSubjectDnSuffix.Length();
+    if ( length )
+        {
+        delete iSubjName;
+        iSubjName = NULL;
+        iSubjName = HBufC8::NewL(length);  	   			 
+        iSubjName->Des().Copy(aOwnCertInfo.iSubjectDnSuffix);		
+        }
+    else 
+        {
+        iSubjName->Des().Zero();
+        } 
+
+    length = aOwnCertInfo.iRfc822NameFqdn.Length();
+    if ( length )
+        {
+        delete iRfc822Name;
+        iRfc822Name = NULL;
+        iRfc822Name = HBufC8::NewL(length);  	   			 
+        iRfc822Name->Des().Copy(aOwnCertInfo.iRfc822NameFqdn);        	 
+        }
+    else
+        {
+        iRfc822Name->Des().Zero();
+        }
+
+	//
+	// Build PKCS1v15 format signature (ASN1 encoded) for RSA and SHA1 for DSA
+	//
+	CUtlMessageDigest* digest = TUtlCrypto::MakeMessageDigesterL(TUtlCrypto::EUtlMessageDigestSha1);
+	CleanupStack::PushL(digest);
+	HBufC8* asn1EncodedHash =NULL;
+	HBufC8* DSSHash = NULL;
+			
+	switch( aAuthMeth )
+		{
+			case RSA_DIGITAL_SIGN:
+				asn1EncodedHash = IkeCert::BuildPkcs1v15HashL(digest->Final(aMsgOctets));
+				User::LeaveIfNull(asn1EncodedHash);
+	    		CleanupStack::PopAndDestroy(digest);
+    			CleanupStack::PushL(asn1EncodedHash);
+    			User::LeaveIfError(iPkiService.Sign(aTrustedAuthority, *iSubjName, *iRfc822Name, 
+		                                    		EX509DigitalSignature, aOwnCertInfo.iPrivateKeyLength, 
+	                                    			keyAlgorithm, *asn1EncodedHash, aSignature));
+   				CleanupStack::PopAndDestroy(asn1EncodedHash);
+   				DEBUG_LOG(_L("Signing Auth data using RSA key."));
+   				break;
+			case DSS_DIGITAL_SIGN:
+				DSSHash = HBufC8::New(20);
+				DSSHash->Des().Append(digest->Final(aMsgOctets));
+				CleanupStack::PopAndDestroy(digest);
+    			CleanupStack::PushL(DSSHash);
+				User::LeaveIfError(iPkiService.Sign(aTrustedAuthority, *iSubjName, *iRfc822Name, 
+		                                    EX509DigitalSignature, aOwnCertInfo.iPrivateKeyLength, 
+	                                    	keyAlgorithm, *DSSHash, aSignature));
+   				CleanupStack::PopAndDestroy(DSSHash);
+   				DEBUG_LOG(_L("Signing Auth data using DSA key."));
+   				break;
+   			default:
+   				DEBUG_LOG1(_L("Authentication method %d not supported when using digital signatures."), aAuthMeth);
+   				User::Leave(KErrNotSupported);
+   				break;			
+		}
+
+	return aSignature.Length();
+    }	 
+
+
+EXPORT_C const CIkeCaList& CIkeV2PkiService::CaList() const
+    {
+    return *iTrustedCAList;
+    }
+            
+    
+EXPORT_C const TDesC8& CIkeV2PkiService::UserCertificateData() const 
+    {    
+    if (iUserCertificate != NULL)
+        {
+        return *iUserCertificate;
+        }
+    else
+        {
+        return KEmptyString;
+        }
+    }
+
+EXPORT_C const TDesC8& CIkeV2PkiService::I2CertificateData() const 
+    {    
+    if (i2Certificate != NULL)
+        {
+        return *i2Certificate;
+        }
+    else
+        {
+        return KEmptyString;
+        }
+    }
+
+EXPORT_C const TDesC8& CIkeV2PkiService::I1CertificateData() const 
+    {    
+    if (i1Certificate != NULL)
+        {
+        return *i1Certificate;
+        }
+    else
+        {
+        return KEmptyString;
+        }
+    }
+    
+    
+EXPORT_C const TDesC8& CIkeV2PkiService::TrustedCaName() const
+    {
+    if ( i2CertificateName != NULL )
+        {
+        return *i2CertificateName;
+        }
+    if (iCaName != NULL)
+        {
+        return *iCaName;
+        }
+    else
+        {
+        return KEmptyString;
+        }
+    }               				
+
+
+void CIkeV2PkiService::ReadUserCertificateL(const TDesC8& aTrustedAuthority, TBool aGetCACert)
+    {
+    __ASSERT_DEBUG(iReadCertificate != NULL, User::Invariant());
+   //
+   // Read certificate from PKI store using pkiserviceapi
+   //  
+	TPKIKeyAlgorithm keyAlgorithm = EPKIRSA; 
+	TPKICertificateOwnerType ownerType; 	
+	TUint keySize = 0;
+	
+	 if ( aGetCACert )
+	    {
+	        ownerType = EPKICACertificate;
+
+	        //Init CA cert ident data.
+	        //aTrustedAuthority (issuer) checking for CA certs is not supported.
+	        //__ASSERT_ALWAYS(aTrustedAuthority.Length() == 0, User::Invariant());
+	        if ( aTrustedAuthority.Length() == 0 )
+	            {
+	            delete iSubjName;
+	            iSubjName = NULL;
+	            iSubjName = iCaName->AllocL();
+	            iRfc822Name->Des().Zero();
+	            } 
+	     }
+	 else
+	     {
+	     ownerType = EPKIUserCertificate;	    
+	     TInt length = iIkeData->iOwnCert.iSubjectDnSuffix.Length();
+	     if ( length )
+	         {
+	         delete iSubjName;
+	         iSubjName = NULL;
+	         iSubjName = HBufC8::NewL(length);  	   			 
+	         iSubjName->Des().Copy(iIkeData->iOwnCert.iSubjectDnSuffix);		
+	         }
+	     else 
+	         {
+	         iSubjName->Des().Zero();
+	         } 
+
+	     length = iIkeData->iOwnCert.iRfc822NameFqdn.Length();
+	     if ( length )
+	         {
+	         delete iRfc822Name;
+	         iRfc822Name = NULL;
+	         iRfc822Name = HBufC8::NewL(length);  	   			 
+	         iRfc822Name->Des().Copy(iIkeData->iOwnCert.iRfc822NameFqdn);        	 
+	         }
+	     else
+	         {
+	         iRfc822Name->Des().Zero();
+	         }
+	     keySize = iIkeData->iOwnCert.iPrivateKeyLength;
+	     }
+	iPkiService.ReadCertificateL(aTrustedAuthority,
+	                              *iSubjName, *iRfc822Name,
+			                      ownerType, keySize,
+			                      keyAlgorithm, iCertPtr,
+			                      &iResArray, iStatus);
+    SET_ACTIVE;
+    }	 
+
+
+void CIkeV2PkiService::CIkeV2PkiServiceApplUidArrayCleanup(TAny* any)
+    {
+    RArray<TUid>* applUidList = reinterpret_cast<RArray<TUid>*>(any);
+    applUidList->Reset();
+    applUidList->Close();
+    delete applUidList;    
+    }
+
+
+void CIkeV2PkiService::RunL()
+    {   
+    DEBUG_LOG1(_L("CIkeV2PkiService::RunL: Status %d"), iStatus.Int());
+    
+	//
+	// A PKI service operation completed. Take actions according to
+	// iOperation code
+	//
+
+    TInt err = KErrNone;
+			
+	TInt status = iStatus.Int();				
+
+    iPkiService.Finalize(iResArray);
+    iResArray = NULL;
+
+	
+	switch ( iState )
+	    {
+		case EBuildingCaList:
+            TRAP(err, BuildingCaListRunL());
+            break;				
+		case EReadingCertificate:
+		    TRAP(err, ReadUserCertificateRunL());
+			break;
+		case EReadingCertificateChain:
+		    TRAP(err, ReadCertificateChainRunL());
+		    break;
+		default:
+		    DEBUG_LOG(_L("RunL called in unknown state"));
+		    User::Invariant();
+			break;
+	    }	
+
+	if ( err != KErrNone )
+	    {	
+	    DEBUG_LOG(_L("Operation completed. Signalling observer."));
+
+        SignalObserverL(err);
+	    }   
+    }
+
+
+void CIkeV2PkiService::ReadUserCertificateRunL()
+    {        
+	//
+	// A Certificate has been read PKI store.
+	// Build X509 certificate object from certificate data
+	//
+	switch(iStatus.Int())
+	    {
+	    case KErrNone:	        
+	        iUserCertificate = iReadCertificate->AllocL();
+	        iReadCertificate->Des().Zero();
+	        SignalObserverL(KErrNone);            
+	        break;
+	    case KPKIErrBufferTooShort:
+		    {	
+            //
+            // Allocate a new buffer for ASN1 coded certificate read from PKI store
+            // Buffer size is now asked from pkiserviceapi 
+            //            
+            TInt realCertSize;        
+            User::LeaveIfError(iPkiService.GetRequiredBufferSize(realCertSize));
+
+            delete iReadCertificate;
+            iReadCertificate = NULL;
+
+            iReadCertificate = HBufC8::NewL(realCertSize);
+            iCertPtr.Set(iReadCertificate->Des());
+            		   		   
+            ReadUserCertificateL(*iCaName, EFalse);
+		    }
+	        break;
+	    case KPKIErrNotFound:
+	        {	            
+            //
+            // Get next user certificate from PKI store using either Key
+            // identifier or CA name as read argument
+            //                                    
+            iCasTrustedByPeer.Remove(0);
+            if ( iCasTrustedByPeer.Count() > 0 )
+                {
+                
+                CIkeCaElem* CaElem = iCasTrustedByPeer[0];	                                   
+                HBufC8* caName = IkeCert::GetCertificateFieldDERL(CaElem->Certificate(), KSubjectName);
+                if (caName == NULL)
+                    {
+                    User::Leave(KErrArgument);
+                    }
+                delete iCaName;
+                iCaName = caName;
+                caName=NULL;
+                delete caName;
+                ReadUserCertificateL(*iCaName, EFalse);
+                }	   
+            else
+                {
+                User::Leave(KErrNotFound);
+                }
+	        }
+            break;
+	    case KErrNotFound:
+	        ReadCertificateChainL();
+	        break;
+        default:
+            User::Leave(iStatus.Int());
+            break;            
+	    }
+    }    
+
+
+void CIkeV2PkiService::BuildingCaListRunL()
+    {       
+    
+    switch(iStatus.Int())
+        {
+        case KErrNone:
+            {                        
+            iIkeDataCAList->Delete(0);     
+            
+    	    ASSERT(iReadCertificate);
+    		HBufC8* caCert = iReadCertificate; // Link CA buffer to CIkeCaElem
+    		CleanupStack::PushL(caCert);		
+    		
+    		iReadCertificate = NULL;    		
+    		iReadCertificate = HBufC8::NewL(KDefaultCertificateBufferSize);
+    		iCertPtr.Set(iReadCertificate->Des());
+    		
+    		
+     		CIkeCaElem* caElem = CIkeCaElem::NewL(caCert);
+    		CleanupStack::Pop(caCert);		
+    		CleanupStack::PushL(caElem);
+    		
+    		//Append ca cert to list, if not already present.
+    		if (iTrustedCAList->FindCaElem(caElem->KeyHash()) == NULL)
+    		    {    		    
+    		    iTrustedCAList->AppendL(caElem);
+    		    CleanupStack::Pop(caElem);
+    		    }
+            else
+                {
+                CleanupStack::PopAndDestroy(caElem);
+                }
+            
+            if (iIkeDataCAList->Count() > 0)
+                {
+                ImportNextCaElemFromIkeDataListL();
+                }
+            else
+                {
+                
+                if (iIkeData->iOwnCert.iOwnCertExists)
+                    {
+                    ReadTrustedUserCertificateL();
+                    }
+                else
+                    {
+                    SignalObserverL(KErrNone);
+                    }
+                }
+            }
+            break;
+        case KPKIErrBufferTooShort:
+            {
+                
+            DEBUG_LOG(_L("Buffer too short"));
+            
+            TInt certSize = 0;            
+		    User::LeaveIfError(iPkiService.GetRequiredBufferSize(certSize));
+            
+            __ASSERT_DEBUG(iCertPtr.MaxLength() < certSize, User::Invariant());
+            
+            delete iReadCertificate;
+            iReadCertificate = NULL;            
+            iReadCertificate = HBufC8::NewL(certSize);
+            iCertPtr.Set(iReadCertificate->Des());
+            
+            //Tries to reimport the certificate.
+            ImportNextCaElemFromIkeDataListL();            
+            }
+            break;
+        default:        
+            DEBUG_LOG1(_L("Error code %d"), iStatus.Int());
+            User::Leave(iStatus.Int());
+            break;
+        }
+    }
+
+
+EXPORT_C void CIkeV2PkiService::InitIkeV2PkiService(const CIkeData* aIkeData)
+    {          
+    __ASSERT_DEBUG(iState == EPkiServiceIdle, User::Invariant());
+    __ASSERT_DEBUG(iIkeDataCAList == NULL, User::Invariant());
+    __ASSERT_DEBUG(aIkeData->iCAList != NULL, User::Invariant());
+    __ASSERT_DEBUG(aIkeData->iCAList->Count() > 0, User::Invariant());
+    __ASSERT_DEBUG(iIkeData == NULL, User::Invariant());
+    
+    iIkeData = aIkeData;
+    
+    iState = EBuildingCaList;
+    TRAPD(err, InitIkeV2PkiServiceL());
+    if (err != KErrNone)
+        {
+        iStatus = KRequestPending;
+        SET_ACTIVE;
+        
+        TRequestStatus* status = &iStatus;
+        User::RequestComplete(status, err);
+        }     
+    }
+    
+
+void CIkeV2PkiService::InitIkeV2PkiServiceL()
+    {               
+    if (iIkeData->iClientCertType != NULL)
+        {
+        if (iIkeData->iClientCertType->GetData().Compare(_L("DEVICE")) == 0)
+            {
+            User::LeaveIfError(iPkiService.SetStoreType(EPkiStoreTypeDevice));
+            }
+        else
+            {
+            User::LeaveIfError(iPkiService.SetStoreType(EPkiStoreTypeUser));
+            }
+        }
+    
+    iIkeDataCAList = new (ELeave) CArrayFixFlat<TCertInfo>(2);
+    for (TInt i = 0; i < iIkeData->iCAList->Count(); ++i)
+        {
+        const TCertInfo* info = (*iIkeData->iCAList)[i];
+        iIkeDataCAList->AppendL(*info);
+        }       
+         
+    ImportNextCaElemFromIkeDataListL();         
+    }
+    
+    
+void CIkeV2PkiService::ImportNextCaElemFromIkeDataListL()
+    {        
+    __ASSERT_DEBUG(iIkeDataCAList != NULL, User::Invariant());
+    __ASSERT_DEBUG(iIkeDataCAList->Count() > 0, User::Invariant());
+    
+    const TCertInfo certInfo = (*iIkeDataCAList)[0];        
+    switch(certInfo.iFormat)
+        {            
+        case CA_NAME:    
+            delete iSubjName;
+            iSubjName = NULL;
+            iSubjName = HBufC8::NewL(certInfo.iData.Length());
+            iSubjName->Des().Copy(certInfo.iData);                    
+        	iPkiService.ReadCertificateL(KEmptyString,
+                                         *iSubjName, KEmptyString,
+		                                 EPKICACertificate, 0,
+		                                 EPKIRSA, iCertPtr,
+		                                 &iResArray, iStatus);
+            SET_ACTIVE;  
+            break;                  
+        case KEY_ID:
+            if (!IkeParser::TextToHexOctets(certInfo.iData, iCertKeyId))
+                {
+                User::Leave(KErrArgument);
+                }
+            iPkiService.ReadCertificateL(iCertKeyId, iCertPtr,
+            			                 &iResArray, iStatus);
+            SET_ACTIVE;                     
+            break;
+       case APPL_UID:           
+            {            
+            //Get the list of applicable CA certs and appends it
+            //to the original list, which was defined in the policy.
+            //After this removes the currently handled node and
+            //calls the method recursively.
+            RArray<TUid>*  applUidList = IkeParser::GetApplUidListL(certInfo.iData);	
+            CleanupStack::PushL(TCleanupItem(CIkeV2PkiServiceApplUidArrayCleanup,
+                                 applUidList));
+
+            CArrayFix<TCertificateListEntry>* applicableCaCertList;
+            iPkiService.ListApplicableCertificatesL(*applUidList, applicableCaCertList);                                
+            
+            CleanupStack::PopAndDestroy(); //applUidList
+                        
+            if (applicableCaCertList->Count() > 0)
+                {                                            
+                CleanupStack::PushL(applicableCaCertList);
+                TCertInfo* info = new (ELeave) TCertInfo;
+                CleanupDeletePushL(info);
+                for (TInt i = 0; i < applicableCaCertList->Count(); i++)
+                    {
+                    const TCertificateListEntry& entry = (*applicableCaCertList)[i];
+                    info->iFormat = CA_NAME;
+                    info->iData.Zero();
+                    info->iData.Copy(entry.iIdentitySubjectName);
+
+                    iIkeDataCAList->AppendL(*info);
+                    DEBUG_LOG1(_L("Appending Applicable cert to the list (%S)"), &(info->iData));
+                                                
+                    }
+                
+                CleanupStack::PopAndDestroy(info);
+                CleanupStack::PopAndDestroy(applicableCaCertList);
+                
+                iIkeDataCAList->Delete(0);                
+                ImportNextCaElemFromIkeDataListL();
+                }
+            else
+                {
+                delete applicableCaCertList;
+                applicableCaCertList = NULL;
+                
+                iStatus = KRequestPending;
+                SET_ACTIVE;
+                
+                TRequestStatus* status = &iStatus;
+                User::RequestComplete(status, KErrNotFound);                
+                }                                                                
+            }
+            break;
+        default:
+            User::Leave(KErrArgument);                
+            break;
+        }
+    }
+
+void CIkeV2PkiService::ReadCertificateChainL()
+    {
+    delete iCaName;
+    iCaName = NULL;
+    iCaName = IkeCert::GetCertificateFieldDERL(iCasTrustedByPeer[0]->Certificate(), KSubjectName);;
+    iState = EReadingCertificateChain;
+    ReadUserCertificateL(KEmptyString, EFalse);
+    }
+
+void CIkeV2PkiService::ReadCertificateChainRunL()
+    {
+    TInt err;
+    HBufC8* issuerName=NULL;
+    TRAP(err, issuerName =  IkeCert::GetCertificateFieldDERL(iReadCertificate, KIssuerName));
+    if (err!=KErrNone)
+        {
+        err=KKmdIkeNoCertFoundErr;
+        User::Leave(err);
+        }
+    if ( issuerName->Compare(iCaName->Des())==0)
+        {
+        iReadCertificate->Des().Zero();
+        delete issuerName;
+        issuerName = NULL;
+        SignalObserverL(KErrNone);    
+        }
+    else
+        {
+         delete issuerName;
+         issuerName = NULL;
+         delete iCaName;
+         iCaName = NULL;
+         iCaName =  IkeCert::GetCertificateFieldDERL(iReadCertificate, KIssuerName);
+         delete iSubjName;
+         iSubjName = NULL;
+         iSubjName = iCaName->AllocL();
+         if ( !iUserCertificate)
+             iUserCertificate = iReadCertificate->AllocL();
+         else if ( !i2Certificate )
+             {
+             i2Certificate = iReadCertificate->AllocL();
+             i2CertificateName= IkeCert::GetCertificateFieldDERL(i2Certificate, KSubjectName);
+             }
+         else if ( !i1Certificate)
+             i1Certificate = iReadCertificate->AllocL();
+                            
+         iPkiService.ReadCertificateL(KEmptyString,
+                                      *iSubjName, KEmptyString,
+                                      EPKICACertificate, 0,
+                                      EPKIRSA, iCertPtr,
+                                      &iResArray, iStatus);
+         SET_ACTIVE;
+        }
+        
+    }
+    
+void CIkeV2PkiService::SignalObserverL(TInt aStatus)
+{    
+    DEBUG_LOG1(_L("CIkeV2PkiService::SignalObserverL: Signalling with %d"), aStatus);
+    
+    if (aStatus != KErrNone)
+        {
+        delete iUserCertificate;
+        iUserCertificate = NULL;
+        
+		delete iCaName;
+		iCaName = NULL;
+				
+		iCertPtr.Zero();
+        
+        iTrustedCAList->ResetAndDestroy(); // Trusted CA certificate list 
+               
+        }
+
+    iIkeData = NULL;
+
+    iSubjName->Des().Zero();
+    iRfc822Name->Des().Zero();
+
+    iCertKeyId.Zero();
+    iResArray = NULL;
+    
+    iCasTrustedByPeer.Reset();
+    	    	    	    
+    delete iIkeDataCAList;
+    iIkeDataCAList = NULL;
+    	    	       
+    iState = EPkiServiceIdle;
+    iObserver.IkeV2PkiInitCompleteL(aStatus);		
+}