diff -r 000000000000 -r 33413c0669b9 vpnengine/ikecert/src/ikev1pkiservice.cpp --- /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 +#include +#include +#include + +#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 *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&)(*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/ = %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