--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/vpnengine/ikecert/src/ikev1pkiservice.cpp Thu Dec 17 09:14:51 2009 +0200
@@ -0,0 +1,1067 @@
+/*
+* Copyright (c) 2005-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: PKI store and Certificate verification interface class
+* implementation for IKEv1 plug-in
+*
+*/
+
+#include <x500dn.h>
+#include <x509cert.h>
+#include <asn1dec.h>
+#include <utf.h>
+
+#include "ikedebug.h"
+#include "ikev1pkiservice.h"
+#include "utlcrypto.h"
+#include "ikecert.h"
+#include "ikecaelem.h"
+#include "ikepublickey.h"
+#include "ikecalist.h"
+#include "ikepkiutils.h"
+#include "pkcs10.h"
+#include "vpnapidefs.h"
+#include "pkiutil.h"
+#include "ikecertconst.h"
+
+//
+// CIkeV1PkiService Class
+//
+_LIT8(KEmptyString, "");
+
+
+EXPORT_C CIkeV1PkiService* CIkeV1PkiService::NewL(
+ CIkeData* aIkeData,
+ MIkeDebug& aDebug
+)
+{
+ CIkeV1PkiService* self =
+ new (ELeave) CIkeV1PkiService(aIkeData, aDebug);
+
+ CleanupStack::PushL(self);
+ self->ConstructL();
+ CleanupStack::Pop(self);
+ return self;
+}
+
+
+CIkeV1PkiService::CIkeV1PkiService(
+ CIkeData* aIkeData,
+ MIkeDebug& aDebug
+) :
+ iOperation(KNoOperation),
+ iIkeData(aIkeData),
+ iCertPtr(NULL, 0),
+ iCertBfrSize(2048),
+ iDebug(aDebug)
+{
+}
+
+
+void CIkeV1PkiService::ConstructL()
+{
+ User::LeaveIfError(iPkiService.Connect());
+
+ // Set certificate store type to device certificate store,
+ // if Own_cert_type is defined as "DEVICE"
+ if ( iIkeData->iClientCertType != NULL )
+ {
+ TPtrC16 certStoreType = iIkeData->iClientCertType->GetData();
+ if ( certStoreType.CompareF(_L("DEVICE")) == 0 )
+ {
+ User::LeaveIfError(iPkiService.SetStoreType(EPkiStoreTypeDevice));
+ }
+ else
+ {
+ User::LeaveIfError(iPkiService.SetStoreType(EPkiStoreTypeUser));
+ }
+ }
+
+ iTrustedCAList = new (ELeave) CIkeCaList(2);
+ iReadCertificate = HBufC8::NewL(iCertBfrSize);
+
+
+ //The code assumes that these are not NULL.
+ //Reallocated, when needed
+ iSubjName = HBufC8::NewL(2);
+ iRfc822Name = HBufC8::NewL(2);
+}
+
+
+EXPORT_C CIkeV1PkiService::~CIkeV1PkiService()
+{
+ if ( iApplUidList )
+ {
+ iApplUidList->Reset();
+ delete iApplUidList;
+ }
+
+ if ( iCaCertList )
+ {
+ iCaCertList->Reset();
+ delete iCaCertList;
+ }
+
+ delete iTrustedCAList;
+
+ iCasTrustedByPeer.Reset();
+ iCasTrustedByPeer.Close();
+
+ delete iCaName;
+ delete iCa1Name;
+ delete iCa2Name;
+
+ delete iReadCertificate;
+ delete iSubjName;
+ delete iRfc822Name;
+
+
+ iPkiService.Close();
+}
+
+
+EXPORT_C TBool CIkeV1PkiService::ImportCACertsL(
+ CArrayFixFlat<TCertInfo*> *aCAList
+)
+{
+ DEBUG_LOG(_L("-> CIkeV1PkiService::ImportCACertsL"));
+
+ //
+ // Build trusted CA certificate list into CIkeV1PkiService object
+ // aCAList call parameter array contains the list of trusted CA:s
+ // (names in ASCII format).
+ // Read corresponding certificate from PKI store and if found,
+ // add a new element (=CIkeCaElem) into CIkeCaList
+ //
+ TBool Status = EFalse;
+
+ if ( aCAList && aCAList->Count() )
+ {
+ delete iCaName;
+
+ iCaName = NULL;
+ iCaName = HBufC8::NewL(256);
+ iCaNameList = aCAList;
+ iCurrIndex = 0;
+ iOperation = KBuildingCaList;
+
+ Status = GetNextCaElemL();
+ }
+
+ return Status;
+}
+
+
+//
+// CIkeV1PkiService::ReadCertWithNameL
+// This method is used to read a certificate from the PKI store.
+// Input parameters:
+// -- const TDesC8& Trusted CA name
+// -- TBool aGetCACert
+// ETrue = Read a CA certificate; EFalse read an user certificate
+// Output parameters:
+// -- X509 certificate into iReadCertificate buffer
+//
+EXPORT_C TInt CIkeV1PkiService::ReadUserCertWithNameL(
+ const TDesC8& aTrustedCaName, CIkeData* aIkeData, TBool aDnType)
+
+{
+ iIkeData = aIkeData;
+
+ delete iCaName;
+ iCaName = NULL;
+ iCaName = HBufC8::NewL(aTrustedCaName.Length());
+ iCaName->Des().Copy(aTrustedCaName);
+
+ delete iReadCertificate;
+ iReadCertificate=NULL;
+
+ TInt Status = ReadCertificateL(*iCaName, EFalse);
+
+ iUserCertDerType=aDnType;
+ return Status;
+}
+EXPORT_C TInt CIkeV1PkiService::ReadChainL(CIkeData* aIkeData, const HBufC8* aCAName)
+{
+ iIkeData = aIkeData;
+ delete iReadCertificate;
+ iReadCertificate=NULL;
+ //read own certificate
+ TInt Status = ReadCertificateL(KEmptyString, EFalse);
+ TInt StatusICA1 = KErrNotFound;
+ TInt StatusICA2 = KErrNotFound;
+ TInt StatusICA = KErrNotFound;
+
+ if ( Status == KErrNone )
+ {
+ iReadCertificateOrig = HBufC8::NewL(iReadCertificate->Length());
+ TPtr8 iReadCertCopy(iReadCertificateOrig->Des());
+ iReadCertCopy.Copy(iReadCertificate->Des());
+ delete iCaName;
+ iCaName = NULL;
+ iCaName = IkeCert::GetCertificateFieldDERL(iReadCertificate, KIssuerName);
+
+ //Read ICA2
+ StatusICA2 = ReadCertificateL(KEmptyString, ETrue);
+
+ if ( StatusICA2 != KErrNone)
+ {
+ delete iReadCertificateOrig;
+ iReadCertificateOrig=NULL;
+ return KErrNotFound;
+ }
+ }
+ if ( Status == KErrNone && StatusICA2 == KErrNone)
+ {
+
+ delete iCaName;
+ iCaName = NULL;
+ iCaName = IkeCert::GetCertificateFieldDERL(iReadCertificate, KIssuerName);
+ delete iCa2Name;
+ iCa2Name=NULL;
+ iCa2Name = GetCertificate();
+
+ CX500DistinguishedName* dn=NULL;
+ CX500DistinguishedName* asn1DnNameofICaName = NULL;
+ dn = CX500DistinguishedName::NewLC(*aCAName);
+ asn1DnNameofICaName = CX500DistinguishedName::NewLC(*iCaName);
+
+ if ( asn1DnNameofICaName->ExactMatchL(*dn) )
+
+ {
+ StatusICA=KErrNone;
+ //read ICA1
+ StatusICA1 = ReadCertificateL(KEmptyString, ETrue);
+ if ( StatusICA1 != KErrNone)
+ {
+ delete iReadCertificateOrig;
+ iReadCertificateOrig=NULL;
+
+ CleanupStack::PopAndDestroy(asn1DnNameofICaName);
+ asn1DnNameofICaName=NULL;
+
+ CleanupStack::PopAndDestroy(dn);
+ dn=NULL;
+
+ return KErrNotFound;
+ }
+ }
+ else
+ {
+ StatusICA1 = ReadCertificateL(KEmptyString, ETrue);
+ if ( StatusICA1 == KErrNotFound)
+ {
+ delete iReadCertificateOrig;
+ iReadCertificateOrig=NULL;
+
+ CleanupStack::PopAndDestroy(asn1DnNameofICaName);
+ asn1DnNameofICaName=NULL;
+
+ CleanupStack::PopAndDestroy(dn);
+ dn=NULL;
+
+ return KVpnErrInvalidCaCertFile;
+ }
+ else
+ StatusICA1=KErrNone;
+ }
+ CleanupStack::PopAndDestroy(asn1DnNameofICaName);
+ asn1DnNameofICaName=NULL;
+
+ CleanupStack::PopAndDestroy(dn);
+ dn=NULL;
+
+ }
+
+ if ( Status == KErrNone && StatusICA1 == KErrNone && StatusICA2 == KErrNone)
+ {
+ if ( StatusICA == KErrNotFound )
+ {
+ delete iCaName;
+ iCaName = NULL;
+ iCaName = IkeCert::GetCertificateFieldDERL(iReadCertificate, KIssuerName);
+ }
+ delete iCa1Name;
+ iCa1Name=NULL;
+ iCa1Name = GetCertificate();
+
+ CX500DistinguishedName* dn=NULL;
+ CX500DistinguishedName* asn1DnNameofICaName = NULL;
+
+ dn = CX500DistinguishedName::NewLC(*aCAName);
+
+ asn1DnNameofICaName = CX500DistinguishedName::NewLC(*iCaName);
+
+ if ( asn1DnNameofICaName->ExactMatchL(*dn) )
+ {
+ delete iCaName;
+ iCaName=NULL;
+ iCaName=HBufC8::NewL(aCAName->Length());
+ iCaName->Des().Copy(*aCAName);
+
+ TInt Status = ReadCertificateL(KEmptyString, ETrue);
+
+ delete iCaName;
+ iCaName = NULL;
+ iCaName = IkeCert::GetCertificateFieldDERL(iCa2Name, KSubjectName);
+
+ delete iReadCertificate;
+ iReadCertificate=iReadCertificateOrig;
+ iReadCertificateOrig=NULL;
+
+ CleanupStack::PopAndDestroy(asn1DnNameofICaName);
+ asn1DnNameofICaName=NULL;
+
+ CleanupStack::PopAndDestroy(dn);
+ dn=NULL;
+
+ if ( Status!=KErrNone )
+ return KVpnErrInvalidCaCertFile;
+ else
+ return KErrNone;
+ }
+ else
+ {
+ delete iReadCertificate;
+
+ iReadCertificate=iReadCertificateOrig;
+ iReadCertificateOrig=NULL;
+ delete iReadCertificateOrig;
+
+ delete iReadCertificate;
+ iReadCertificate=NULL;
+
+ CleanupStack::PopAndDestroy(asn1DnNameofICaName);
+ asn1DnNameofICaName=NULL;
+
+ CleanupStack::PopAndDestroy(dn);
+ dn=NULL;
+
+ return KErrNotFound;
+ }
+ }
+ return KErrNotFound;
+}
+
+//
+// CIkeV1PkiService::Ikev1SignatureL
+// This method is used to compute IKEv1 signature with a specified private key.
+// Actually a signature computed happens by referring the related certificate
+// when the PKI store produces the signature with corresponding private key.
+// Parameters:
+// -- const TDesC8& aTrustedAuthority
+// Trusted CA name coded either in ASN1 (DN) format or ASCII format
+// -- CIkeData* aHostData
+// Related IKE configuration section. Used to get IdentitySubjectName or
+// Identity Rfc822 Name information for actual PKI service ReadCertificateL
+// method call
+// -- const TDesC8& aHashIn
+// Hash data signed (in matter of fact the hash data is simply
+// encrypted with private key)
+// Return:
+// -- TInt, sign length
+//
+EXPORT_C TInt CIkeV1PkiService::Ikev1SignatureL(
+ const TDesC8& aTrustedCaName,
+ CIkeData* aIkeData,
+ const TDesC8& aHashIn,
+ TDes8& aSignature
+)
+{
+ iIkeData = aIkeData;
+ return ComputeSignatureL(aTrustedCaName, aHashIn, aSignature, EFalse);
+}
+
+
+EXPORT_C CIkeCaList* CIkeV1PkiService::CaList()
+{
+ return iTrustedCAList;
+}
+
+
+EXPORT_C HBufC8* CIkeV1PkiService::GetCertificate()
+{
+ HBufC8* Cert = iReadCertificate;
+ iReadCertificate = NULL;
+ return Cert;
+}
+
+
+EXPORT_C HBufC8* CIkeV1PkiService::GetTrustedCA()
+{
+ HBufC8* Cert = iCaName;
+ iCaName = NULL;
+ return Cert;
+}
+
+
+EXPORT_C HBufC8* CIkeV1PkiService::GetTrustedICA1()
+{
+ HBufC8* Cert = iCa1Name;
+ iCa1Name = NULL;
+ return Cert;
+}
+
+EXPORT_C HBufC8* CIkeV1PkiService::GetTrustedICA2()
+{
+ HBufC8* Cert = iCa2Name;
+ iCa2Name = NULL;
+ return Cert;
+}
+
+TInt CIkeV1PkiService::ComputeSignatureL(
+ const TDesC8& aTrustedAuthority,
+ const TDesC8& aHashIn,
+ TDes8& aSignature,
+ TBool aRsaSignature
+)
+{
+ DEBUG_LOG(_L("-> CIkeV1PkiService::ComputeSignatureL"));
+
+ TPKIKeyAlgorithm keyAlgorithm = EPKIRSA;
+ TUint keySize = InitUserCertIdentDataL();
+ HBufC8* Asn1EncodedHash = NULL;
+ TPtrC8 hashIn(aHashIn);
+
+ if ( aRsaSignature )
+ {
+ //
+ // Build PKCS1v15 format signature (ASN1 encoded)
+ //
+ Asn1EncodedHash = IkeCert::BuildPkcs1v15HashL(aHashIn);
+
+ ASSERT( Asn1EncodedHash != NULL );
+ hashIn.Set(Asn1EncodedHash->Des());
+ }
+
+ TInt SignLth = 0;
+ TInt err = iPkiService.Sign(aTrustedAuthority, *iSubjName, *iRfc822Name,
+ EX509DigitalSignature, keySize,
+ keyAlgorithm, hashIn, aSignature);
+
+ if (err == KErrNone)
+ {
+ SignLth = aSignature.Length();
+ }
+
+ DEBUG_LOG2(_L("Sign returned %d, length=%d"), err, SignLth);
+ User::LeaveIfError(err);
+
+ delete Asn1EncodedHash;
+ return SignLth;
+}
+
+
+TInt CIkeV1PkiService::ReadCertificateL(
+ const TDesC8& aTrustedAuthority, TBool aGetCACert
+)
+{
+ //
+ // Read certificate from PKI store using pkiserviceapi
+ //
+ DEBUG_LOG(
+ _L("-> ReadCertificateL(aTrustedAuthority, aGetCACert)")
+ );
+
+ TInt Status = KErrNone;
+ TPKIKeyAlgorithm keyAlgorithm = EPKIRSA;
+ TPKICertificateOwnerType ownerType;
+ TUint keySize = 0;
+
+ if (aGetCACert)
+ {
+ DEBUG_LOG(_L("Reading CA certificate"));
+
+ ownerType = EPKICACertificate;
+
+ //Init CA cert ident data.
+ //aTrustedAuthority (issuer) checking for CA certs is not supported.
+ if ( aTrustedAuthority.Length() == 0 )
+ {
+ delete iSubjName;
+ iSubjName = NULL;
+ iSubjName = iCaName->AllocL();
+ iRfc822Name->Des().Zero();
+ }
+ }
+ else
+ {
+ DEBUG_LOG(_L("Reading User certificate"));
+ ownerType = EPKIUserCertificate;
+ keySize = InitUserCertIdentDataL();
+ }
+
+ for (;;) // Only for easy exits...
+ {
+ if ( iReallocated )
+ {
+ //
+ // Allocate a new buffer for ASN1 coded certificate read from
+ // PKI store. Buffer size is now asked from pkiserviceapi
+ //
+ delete iReadCertificate;
+ iReadCertificate = NULL;
+ TInt RealCertSize;
+
+ if ( iPkiService.GetRequiredBufferSize(RealCertSize) == KErrNone )
+ iCertBfrSize = (RealCertSize | 0x3) + 1;
+ // Try double size in error case
+ else iCertBfrSize = (iCertBfrSize << 1);
+ }
+
+ if ( !iReadCertificate )
+ {
+ iReadCertificate=NULL;
+ iReadCertificate = HBufC8::NewL(iCertBfrSize);
+ }
+
+ iCertPtr.Set(iReadCertificate->Des());
+ iCertPtr.Zero();
+
+ TRequestStatus status;
+ iPkiService.ReadCertificateL(aTrustedAuthority,
+ *iSubjName, *iRfc822Name,
+ ownerType, keySize,
+ keyAlgorithm, iCertPtr,
+ &iResArray, status);
+
+
+ User::WaitForRequest(status);
+ Status = status.Int();
+ iPkiService.Finalize(iResArray);
+ iResArray = NULL;
+
+ if ( (Status == KPKIErrBufferTooShort) && !iReallocated )
+ {
+ //
+ // Certificate buffer was too small try to read once more if
+ // not already tried
+ //
+ iReallocated = ETrue;
+ }
+ else
+ {
+ if ( Status == KErrNone )
+ {
+ //iReadCertificate->Des().SetLength(iCertPtr.Length());
+ iReallocated = EFalse;
+ }
+ break;
+ }
+
+ }
+
+ DEBUG_LOG(
+ _L("<- ReadCertificateL(aTrustedAuthority, aGetCACert)")
+ );
+
+ return Status;
+}
+
+
+TUint CIkeV1PkiService::InitUserCertIdentDataL()
+{
+ DEBUG_LOG(_L("-> CIkeV1PkiService::InitUserCertIdentDataL"));
+ __ASSERT_ALWAYS(iIkeData != NULL, User::Invariant());
+
+ TUint keySize = 0; // Default: Length is undefined
+
+ if ( !iReallocated )
+ {
+ //
+ // Get possible user identity information from current IKE policy
+ // section and convert it from 16-bit Unicode into UTF-8 format
+ //
+ TInt Lth = 3*( iIkeData->iOwnCert.iSubjectDnSuffix.Length() );
+
+ if ( Lth )
+ {
+ delete iSubjName;
+ iSubjName = NULL;
+ iSubjName = HBufC8::NewL(Lth);
+
+ TPtr8 dn8 = iSubjName->Des();
+ TPtrC16 dn16( iIkeData->iOwnCert.iSubjectDnSuffix );
+
+ if ( 0 != CnvUtfConverter::ConvertFromUnicodeToUtf8(
+ dn8, dn16 ) )
+ {
+ User::Leave(KErrCorrupt);
+ }
+ }
+ else
+ {
+ iSubjName->Des().Zero();
+ }
+
+ Lth = iIkeData->iOwnCert.iRfc822NameFqdn.Length();
+
+ if ( Lth )
+ {
+ delete iRfc822Name;
+ iRfc822Name = NULL;
+ iRfc822Name = HBufC8::NewL(Lth);
+ iRfc822Name->Des().Copy(iIkeData->iOwnCert.iRfc822NameFqdn);
+ }
+ else
+ {
+ iRfc822Name->Des().Zero();
+ }
+
+ if ( iIkeData->iOwnCert.iPrivateKeyLength )
+ {
+ keySize = iIkeData->iOwnCert.iPrivateKeyLength;
+ }
+ }
+
+ DEBUG_LOG(_L("<- CIkeV1PkiService::InitUserCertIdentDataL"));
+ return keySize;
+}
+
+
+TBool CIkeV1PkiService::GetNextCaElemL()
+{
+ //
+ // Get next CA certificate from PKI store using current CA name in
+ // iCaNameList.
+ //
+ DEBUG_LOG(_L("-> CIkeV1PkiService::GetNextCaElemL"));
+
+ TCertInfo* CertInfo;
+ TBool Ret;
+
+ Ret = EFalse;
+ TInt Status;
+
+ while ( iCurrIndex < iCaNameList->Count() )
+ {
+ CertInfo = iCaNameList->At(iCurrIndex);
+
+ if ( CertInfo->iFormat == CA_NAME )
+ {
+ TPtr8 dn8 = iCaName->Des();
+ TPtrC16 dn16( CertInfo->iData );
+
+ if ( 0 != CnvUtfConverter::ConvertFromUnicodeToUtf8(
+ dn8, dn16
+ ) )
+ {
+ User::Leave(KErrCorrupt);
+ }
+
+ Status = ReadCertificateL(KEmptyString, ETrue);
+ Ret |= AddNextCaElemL(Status);
+ }
+ else if ( CertInfo->iFormat == KEY_ID )
+ {
+ Status = GetCertificateWithKeyIdL(CertInfo->iData);
+ Ret |= AddNextCaElemL(Status);
+ }
+ else if ( CertInfo->iFormat == APPL_UID )
+ {
+ Ret |= GetApplUidListL(CertInfo->iData);
+ }
+ else
+ {
+ Ret |= EFalse;
+ iCurrIndex ++;
+ DEBUG_LOG1(
+ _L("Unsupported CA certificate element format = %d"),
+ CertInfo->iFormat
+ );
+ }
+
+ }
+
+ iCaNameList = NULL;
+
+ DEBUG_LOG(_L("<- CIkeV1PkiService::GetNextCaElemL"));
+ return Ret;
+}
+
+
+TBool CIkeV1PkiService::AddNextCaElemL(TInt& aStatus)
+{
+ DEBUG_LOG(_L("-> CIkeV1PkiService::AddNextCaElemL()"));
+
+ //
+ // CA has been read PKI store. Build and add a new CIkeCaElem to CIkeCaList
+ //
+#ifdef _DEBUG
+ CertReadCompleted(ETrue, aStatus, __LINE__);
+#endif // _DEBUG
+
+ if (aStatus == KErrNotFound)
+ {
+ DEBUG_LOG(_L(" Leave: status == KErrNotFound"));
+ User::Leave(KVpnErrInvalidCaCertFile);
+ }
+
+ TBool Ret;
+
+ if ( aStatus == KErrNone )
+ {
+ ASSERT(iReadCertificate);
+ HBufC8* CaCert = iReadCertificate; // Link CA buffer to CIkeCaElem
+ CaCert->Des().SetLength(iCertPtr.Length());
+ iReadCertificate = NULL;
+ CleanupStack::PushL(CaCert);
+ CIkeCaElem* CaElem = CIkeCaElem::NewL(CaCert);
+ CleanupStack::Pop(CaCert);
+ CleanupStack::PushL(CaElem);
+ iTrustedCAList->AppendL(CaElem);
+ CleanupStack::Pop(CaElem);
+
+ if ( iOperation == KProcessingApplUidList )
+ iListIndex ++;
+ else iCurrIndex ++;
+
+ Ret = ETrue;
+ }
+ else
+ {
+ if ( iOperation == KProcessingApplUidList )
+ iListIndex ++;
+ else iCurrIndex ++;
+
+ Ret = EFalse;
+ }
+
+ DEBUG_LOG(_L("<- CIkeV1PkiService::AddNextCaElemL()"));
+
+ return Ret;
+}
+
+TInt CIkeV1PkiService::GetNextCertificateL()
+{
+ DEBUG_LOG(_L("-> CIkeV1PkiService::GetNextCertificateL"));
+ //
+ // Get next user certificate from PKI store using either Key
+ // identifier or CA name as read argument
+ //
+ TInt Status = KErrNotFound;
+ if ( iCasTrustedByPeer.Count() > 0 )
+ {
+ CIkeCaElem* CaElem = iCasTrustedByPeer[0];
+ iCasTrustedByPeer.Remove(0);
+ iOperation = KReadingCertificate;
+
+ HBufC8* CaName = IkeCert::GetCertificateFieldDERL(
+ CaElem->Certificate(), KSubjectName
+ );
+
+ if ( CaName )
+ {
+ delete iCaName;
+ iCaName = CaName;
+ ReadCertificateL(*iCaName, EFalse);
+ Status = KErrNone;
+ }
+
+ }
+
+ DEBUG_LOG(_L("<- CIkeV1PkiService::GetNextCertificateL"));
+ return Status;
+}
+
+
+TBool CIkeV1PkiService::CertificateReadL(TInt& aStatus)
+{
+ //
+ // A Certificate has been read PKI store.
+ // Build X509 certificate object from certificate data
+ //
+#ifdef _DEBUG
+ CertReadCompleted(EFalse, aStatus, __LINE__);
+#endif // _DEBUG
+ TBool Status = ETrue;
+
+ if ( aStatus == KErrNone )
+ {
+ iReallocated = EFalse;
+ iReadCertificate->Des().SetLength(iCertPtr.Length());
+ }
+ else
+ {
+ if ( (aStatus == KPKIErrBufferTooShort) && !iReallocated )
+ {
+ //
+ // Certificate buffer was too small try to read once more if
+ // not already tried
+ //
+ Status = EFalse;
+ aStatus = KErrNone;
+ iReallocated = ETrue;
+ ReadCertificateL(*iCaName, EFalse);
+ }
+
+ if ( (aStatus != KErrNone) && ( aStatus != KPKIErrBufferTooShort) )
+ {
+ //
+ // User certificate not found from PKI store, try to read next
+ //
+ iReallocated = EFalse;
+ aStatus = GetNextCertificateL();
+
+ if ( aStatus == KErrNone )
+ {
+ Status = EFalse;
+ }
+ }
+ }
+
+ return Status;
+}
+
+
+TInt CIkeV1PkiService::ReadCertificateL(const TPKIKeyIdentifier& aKeyIdentifier)
+{
+ //
+ // Read certificate from PKI store using pkiserviceapi
+ //
+ TRequestStatus status;
+
+ for (;;) // Only for easy exits...
+ {
+ if ( iReallocated )
+ {
+ //
+ // Allocate a new buffer for ASN1 coded certificate read from
+ // PKI store. Buffer size is now asked from pkiserviceapi
+ //
+ delete iReadCertificate;
+ iReadCertificate = NULL;
+ TInt RealCertSize;
+
+ if ( iPkiService.GetRequiredBufferSize(RealCertSize) == KErrNone )
+ iCertBfrSize = (RealCertSize | 0x3) + 1;
+ // Try double size in error case
+ else iCertBfrSize = (iCertBfrSize << 1);
+ }
+
+ if ( !iReadCertificate )
+ iReadCertificate = HBufC8::NewL(iCertBfrSize);
+
+ iCertPtr.Set((TUint8*)iReadCertificate->Ptr(), 0, iCertBfrSize);
+
+ iPkiService.ReadCertificateL(aKeyIdentifier, iCertPtr,
+ &iResArray, status);
+
+ User::WaitForRequest(status);
+ iPkiService.Finalize(iResArray);
+ iResArray = NULL;
+
+ if ( (status.Int() == KPKIErrBufferTooShort) && !iReallocated )
+ {
+ //
+ // Certificate buffer was too small try to read once more if
+ // not already tried
+ //
+ iReallocated = ETrue;
+ }
+ else
+ {
+ if ( status.Int() == KErrNone )
+ {
+ iReadCertificate->Des().SetLength(iCertPtr.Length());
+ iReallocated = EFalse;
+ }
+ break;
+ }
+
+ }
+
+ return status.Int();
+}
+
+
+TInt CIkeV1PkiService::ReadCertificateListL()
+{
+ //
+ // Read certificate list with Application UID:s
+ //
+ if ( iCaCertList )
+ {
+ iCaCertList->Reset();
+ delete iCaCertList;
+ iCaCertList = NULL;
+ }
+
+ iOperation = KBuildingApplUidList;
+
+ iPkiService.ListApplicableCertificatesL(
+ (const RArray<TUid>&)(*iApplUidList), iCaCertList
+ );
+
+ return KErrNone;
+}
+
+
+TInt CIkeV1PkiService::GetCertificateWithKeyIdL(const TDesC16& aKeyIdString)
+{
+ TInt Status;
+
+ if ( IkeParser::TextToHexOctets(aKeyIdString, iCertKeyId) )
+ Status = ReadCertificateL(iCertKeyId);
+ else Status = KErrArgument;
+
+ return Status;
+}
+
+
+TBool CIkeV1PkiService::GetApplUidListL(const TDesC16& aApplUidString)
+{
+ //
+ // Build application UID array to get trusted CA certificate list
+ // from PKI service.
+ //
+ if ( iApplUidList )
+ {
+ iApplUidList->Reset();
+ delete iApplUidList;
+ iApplUidList = NULL;
+ }
+
+ iApplUidList = IkeParser::GetApplUidListL(aApplUidString);
+
+ TBool Status = (iApplUidList->Count() != 0);
+
+ if ( Status )
+ {
+ TInt Ret = ReadCertificateListL();
+ Status = ( Ret == KErrNone);
+ iListIndex = 0;
+
+ Status = ApplUidCertListCompletedL(Ret);
+ }
+
+ return Status;
+}
+
+
+TBool CIkeV1PkiService::ApplUidCertListCompletedL(TInt aStatus)
+{
+ DEBUG_LOG2(
+ _L("Certificate list read completed, status= %d, list elem count= %d"),
+ aStatus, iCaCertList->Count()
+ );
+ DEBUG_LOG1(
+ _L(" APPL UID(s) = %S\n"), &iCaNameList->At(iCurrIndex)->iData
+ );
+
+ TBool Ret;
+
+ if ( (aStatus == KErrNone) && iCaCertList->Count() )
+ {
+ //
+ // Start to read in trusted CA certificates provided in list
+ //
+ iOperation = KProcessingApplUidList;
+ Ret = ReadNextInListL();
+ }
+ else
+ {
+ //
+ // No trusted CA certificates found with current application
+ // UID:s. Continue processing CA elements
+ //
+ Ret = EFalse;
+ iOperation = KBuildingCaList;
+ iCurrIndex ++;
+
+ }
+
+ return Ret;
+}
+
+
+TBool CIkeV1PkiService::ReadNextInListL()
+{
+ TBool Status = EFalse;
+
+ TInt Ret;
+
+ while ( iListIndex < iCaCertList->Count() )
+ {
+ Ret = ReadCertificateL(iCaCertList->At(iListIndex).iSubjectKeyId);
+ if ( AddNextCaElemL(Ret) )
+ Status = ETrue;
+ }
+
+ iCurrIndex ++;
+
+ return Status;
+}
+
+
+#ifdef _DEBUG
+
+void CIkeV1PkiService::CertReadCompleted(TBool aCaCert, TInt aStatus, TInt aLine )
+{
+ TBuf<320>DebugMsg;
+ if ( aCaCert )
+ {
+ ASSERT( iCurrIndex < iCaNameList->Count() );
+ DebugMsg.Format(_L("Trusted CA certificate read completed with status = %d (line = %d)"),
+ aStatus, aLine);
+ DebugMsg.AppendFormat(_L(" ; Search criteria: "));
+ TCertInfo* CertInfo = iCaNameList->At(iCurrIndex);
+ switch ( CertInfo->iFormat )
+ {
+ case CA_NAME:
+ DebugMsg.AppendFormat(_L("CA_NAME = %S\n"), &CertInfo->iData);
+ break;
+ case KEY_ID:
+ DebugMsg.AppendFormat(_L("KEY_ID = %S\n"), &CertInfo->iData);
+ break;
+ default:
+ TBuf<48> KeyIdString;
+ ASSERT( iListIndex < iCaCertList->Count() );
+ HexToString(iCaCertList->At(iListIndex).iSubjectKeyId, KeyIdString);
+ DebugMsg.AppendFormat(_L("APPL_UID/<KEY_ID> = %S\n"), &KeyIdString);
+ break;
+ }
+ }
+ else
+ {
+ DEBUG_LOG2(_L("End user certificate read completed with status = %d (line = %d)\n"),
+ aStatus, aLine);
+ }
+ DEBUG_LOG(DebugMsg);
+}
+
+void CIkeV1PkiService::HexToString(const TDesC8& aKeyId, TDes16& aKeyIdString)
+{
+ TInt i = 0;
+ TUint x;
+ TUint y;
+
+ while (i < aKeyId.Length())
+ {
+ x = (TUint)aKeyId[i];
+ for ( TInt j = 4; j >= 0; j -= 4 )
+ {
+ y = (x >> j) & 0xf;
+ TChar ch(y);
+ if ( y < 0xa )
+ ch += 0x30;
+ else if ( (y > 9) && (y < 0x10) )
+ ch += (0x61 - 0xa);
+ else ch += (0x30 - ch);
+ aKeyIdString.Append(ch);
+ }
+ i ++;
+ }
+}
+
+#endif //_DEBUG