diff -r 000000000000 -r 33413c0669b9 vpnengine/pkiservice/src/pkisupport.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vpnengine/pkiservice/src/pkisupport.cpp Thu Dec 17 09:14:51 2009 +0200 @@ -0,0 +1,1324 @@ +/* +* Copyright (c) 2003-2008 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: +* CPKISupport class implements the PKI interface for Symbian Certificate +* storage. +* +*/ + + + +#include +#include +#include +#include +#include +#include +#include + +#include "pkiwrapper.h" +#include "PKIMapper.h" +#include "pkisupport.h" +#include "pkisession.h" +#include "log_r6.h" +#include "pkiserviceassert.h" +#include "pkiserviceconstants.h" +#include + + +CPKISupport* CPKISupport::NewLC(CPKIMapper& aMapper, CPKIWrapper& aWrapper) + { + CPKISupport* self = new (ELeave)CPKISupport(aMapper, aWrapper); + CleanupStack::PushL(self); + self->ConstructL(); + return self; + } + +CPKISupport* CPKISupport::NewL(CPKIMapper& aMapper, CPKIWrapper& aWrapper) + { + CPKISupport* self = CPKISupport::NewLC(aMapper, aWrapper); + CleanupStack::Pop(self); + return self; + } + +void CPKISupport::ConstructL() + { + User::LeaveIfError(iEventMediator.Connect()); + } + +CPKISupport::~CPKISupport() + { + LOG_("CPKISupport::~CPKISupport"); + Cancel(); + + if(iCerts != NULL) + { + iCerts->Close(); + delete iCerts; + } + delete iCertFilter; + delete iCertStore; + iFSession.Close(); + iApplUids.Close(); + delete iImportCertMapping; + delete iImportCertData; + iEventMediator.Close(); + delete iCertInfoForLogging; + iCertInfoForLogging = NULL; + } + +CPKISupport::CPKISupport(CPKIMapper& aMapper, CPKIWrapper& aWrapper) + :CActive(CActive::EPriorityStandard), + iMapper(aMapper), + iWrapper(aWrapper), + iPending(ENoPendingOperation), + iImportCertDataPtr(NULL, 0) + { + LOG_("-> CPKISupport::CPKISupport()\n"); + CActiveScheduler::Add(this); + + SetCertStoreType(EPkiStoreTypeAny); + LOG_("<- CPKISupport::CPKISupport()\n"); + } + +// --------------------------------------------------------------------------- +// StartInitializeL +// --------------------------------------------------------------------------- +// +void CPKISupport::StartInitializeL(const RMessage2& aMessage) + { + LOG_("-> CPKISupport::StartInitialize()"); + User::LeaveIfError(iFSession.Connect()); + iCertStore = CUnifiedCertStore::NewL(iFSession, ETrue); + PKISERVICE_ASSERT(!iCerts); + iCerts = new (ELeave) RMPointerArray; + + iMessage = aMessage; + iCallerStatus = NULL; + iSupportStatus = KErrNone; + + iInitState = EInitInitializeCertStore; + iCertStore->Initialize(iStatus); + iPending = EInitializeCertStore; + SetActive(); + + LOG_("<- CPKISupport::StartInitialize()"); + } + + +// --------------------------------------------------------------------------- +// FindInterfacesL +// --------------------------------------------------------------------------- +// +void CPKISupport::FindInterfacesL() + { + TInt i(0); + + // Find writable cert interface + LOG(Log::Printf(_L("Find interfaces"))); + + TBool allStoresFound(EFalse); + + MCTWritableCertStore* certStore; + + TInt storeCount = iCertStore->WritableCertStoreCount(); + LOG_1("Found %d cert stores\n", storeCount); + + + // Find both user and device cert stores + for(i = 0; i < storeCount; i++) + { + certStore= &(iCertStore->WritableCertStore(i)); + + if(certStore->Token().Label().Compare(KUserCertStore) == 0) + { + // found the user cert store... See if device cert store + // was already found as well + iWritableCertStore = certStore; + + LOG(Log::Printf(_L("Found writable user certificate store\n"))); + + if (!allStoresFound) + { + allStoresFound = ETrue; + } + else + { + break; + } + } + else if (certStore->Token().Label().Compare(KDeviceCertStore) == 0) + { + + // found the device cert store + iWritableDeviceCertStore = certStore; + + LOG(Log::Printf(_L("Found writable device certificate store\n"))); + + // See if user cert store was already found as well + if (!allStoresFound) + { + allStoresFound = ETrue; + } + else + { + break; + } + } + } + + if (iWritableDeviceCertStore == NULL) + { + LOG(Log::Printf(_L("Note: Device cert store not found\n"))); + } + } + + +// --------------------------------------------------------------------------- +// ContinueImportCTFObjectsL +// --------------------------------------------------------------------------- +// +void CPKISupport::ListAllCertificatesL() +{ + LOG_("-> CPKISupport::ListAllCertificatesL"); + + PKISERVICE_ASSERT( !iCertFilter ); + iCertFilter = CCertAttributeFilter::NewL(); + + iSupportStatus = KErrNone; + iInitState = EInitRetrieveCertList; + iImportCounter = 0; + iToggleSwitch = EFalse; + + // Get list of all known certificates + GetCertificateStoreListAsync(); + LOG_("<- CPKISupport::ListAllCertificatesL"); +} + + + +// --------------------------------------------------------------------------- +// ImportCTFCertsL +// --------------------------------------------------------------------------- +// +void CPKISupport::ReadNextCertForImportL() +{ + LOG_("-> CPKISupport::ImportNextCertL()"); + PKISERVICE_ASSERT(iImportCounter < iCerts->Count()); + + if(iImportCounter == 0) + { + LOG_1("Import %d certificates\n", iCerts->Count()); + } + + LOG_1("Import certificate:%d", iImportCounter); + LOG_1("Label: %S", &((*iCerts)[iImportCounter]->Label())); + + PKISERVICE_ASSERT((*iCerts)[iImportCounter]->CertificateFormat() == EX509Certificate); + + TSecurityObjectDescriptor descriptor; + descriptor.SetSubjectKeyId( + (*iCerts)[iImportCounter]->SubjectKeyId()); + descriptor.SetOwnerType( + (TPKICertificateOwnerType)(*iCerts)[iImportCounter]-> + CertificateOwnerType()); + descriptor.SetIsDeletable( + (*iCerts)[iImportCounter]->IsDeletable()); + + delete iImportCertMapping; + iImportCertMapping = NULL; + iImportCertMapping = new (ELeave) CMapDescriptor(descriptor); + + iImportCertMapping->SetMapObjectName((*iCerts)[iImportCounter]->Label()); + + delete iImportCertData; + iImportCertData = NULL; + iImportCertData = HBufC8::NewL((*iCerts)[iImportCounter]->Size()); + iImportCertDataPtr.Set(iImportCertData->Des()); + + LOG_(" Values set OK, retrieving"); + iCertStore->Retrieve( + *(*iCerts)[iImportCounter], iImportCertDataPtr, iStatus); + iPending = ECertRetrieve; + SetActive(); + LOG_("<- CPKISupport::ImportCTFCertsL() SetActive() and ret: EFalse"); +} + +// --------------------------------------------------------------------------- +// ImportOneCTFCertL +// --------------------------------------------------------------------------- +// +void CPKISupport::SaveCertInfoToCacheL() + { + if((iImportCertMapping != NULL) && (iImportCertData != NULL)) + { + LOG_("Saving cert info to cache"); + + CX509Certificate* certificate = CX509Certificate::NewLC(iImportCertDataPtr); + const CSubjectPublicKeyInfo& publicKeyInfo = certificate->PublicKey(); + const TPtrC8 keyData = publicKeyInfo.KeyData(); + + TX509KeyFactory keyFactory; + switch(publicKeyInfo.AlgorithmId()) + { + case ERSA: + { + iImportCertMapping->iKeyAlgorithm = EPKIRSA; + const CRSAPublicKey* keyRSA = keyFactory.RSAPublicKeyL( keyData ); + const TInteger& n = keyRSA->N(); + iImportCertMapping->iKeySize = n.BitCount(); + delete keyRSA; + } + break; + case EDSA: + { + iImportCertMapping->iKeyAlgorithm = EPKIDSA; + TPtrC8 params = publicKeyInfo.EncodedParams(); + const CDSAPublicKey* keyDSA = keyFactory.DSAPublicKeyL( params, keyData ); + const TInteger& y = keyDSA->Y(); + iImportCertMapping->iKeySize = y.BitCount(); + delete keyDSA; + } + break; + default: + iImportCertMapping->iKeyAlgorithm = EPKIInvalidAlgorithm; + break; + } + CleanupStack::PopAndDestroy(certificate); + + iWrapper.SaveIdentityL(*iImportCertMapping, + iImportCertDataPtr, + ((*iCerts)[iImportCounter])->CertificateOwnerType()); + + TInt storeType = (*iCerts)[iImportCounter]->Token().TokenType().Type().iUid; + if ( storeType == STORETYPE_DEVICE_CERT_ID ) + { + iImportCertMapping->SetCertStoreType(EPkiStoreTypeDevice); + } + else if ( storeType == STORETYPE_USER_CERT_ID ) + { + iImportCertMapping->SetCertStoreType(EPkiStoreTypeUser); + } + else + { + iImportCertMapping->SetCertStoreType(EPkiStoreTypeAny); + } + + for(TInt i=0;iiApplUids.Append(iApplUids[i]); + } + User::LeaveIfError( + iMapper.AddMapping(*iImportCertMapping) ); + + iApplUids.Close(); + + iImportCertMapping = NULL; + iImportCounter++; + } + } + +// --------------------------------------------------------------------------- +// GetApplicationsOfCTFCertL +// --------------------------------------------------------------------------- +// +TBool CPKISupport::GetApplicationsOfCTFCertL() +{ + LOG_("-> CPKISupport::GetApplicationsOfCTFCertL()"); + if((iImportCertMapping != NULL) && (iImportCertData != NULL)) + { + if(iToggleSwitch == EFalse) + { + if((*iCerts)[iImportCounter]->CertificateOwnerType() == ECACertificate) + { + PKISERVICE_ASSERT(iApplUids.Count() == 0); + + iToggleSwitch = ETrue; + // Get applications + iCertStore->Applications(*(*iCerts)[iImportCounter], iApplUids, iStatus); + iPending = EApplications; + LOG_("<- CPKISupport::GetApplicationsOfCTFCertL() SetActive(), ret: ETrue"); + SetActive(); + return ETrue; + } + else + { + LOG_("<- CPKISupport::GetApplicationsOfCTFCertL() Not a CA cert, ret: EFalse"); + return EFalse; + } + } + else + { + LOG_("<- CPKISupport::GetApplicationsOfCTFCertL() iToggleSwitch == ETrue, ret: EFalse"); + iToggleSwitch = EFalse; + return EFalse; + } + } + else + { + return EFalse; + } +} + + +// --------------------------------------------------------------------------- +// CancelCurrentOperation +// --------------------------------------------------------------------------- +// +void CPKISupport::CancelCurrentOperation() + { + LOG_1("CPKISupport::CancelCurrentOperation iPending: %d", iPending); + MCTWritableCertStore* certStore(NULL); + switch(iPending) + { + case ENoPendingOperation: + // No pending operation + PKISERVICE_ASSERT( iStatus.Int() != KRequestPending); + break; + case EInitializeCertStore: + // FALLTROUGH + case EListCerts: + // FALLTROUGH + case EListDevCerts: + // FALLTROUGH + case ECertRetrieve: + // FALLTROUGH + case ECertRemove: + // FALLTROUGH + case ESetTrust: + // FALLTROUGH + case ETrusted: + // FALLTROUGH + case ESetApplicability: + // FALLTROUGH + case EApplications: + // FALLTROUGH + case EIsApplicable: + PKISERVICE_ASSERT( iCertStore ); + iCertStore->Cancel(); + break; + case ECertAdd: + if (iCertStoreType == EPkiStoreTypeDevice) + { + LOG_("CPKISupport::CancelCurrentOperation cancelling device cert store op"); + certStore = iWritableDeviceCertStore; + } + else if (iCertStoreType == EPkiStoreTypeUser) + { + LOG_("CPKISupport::CancelCurrentOperation cancelling user cert store op"); + certStore = iWritableCertStore; + } + else + { + LOG_("CPKISupport::CancelCurrentOperation cancelling user cert store op (unknown store type was defined)"); + certStore = iWritableCertStore; + } + PKISERVICE_ASSERT( certStore ); + certStore->CancelAdd(); + break; + default: + LOG_("CPKISupport::CancelCurrentOperation - default"); + break; + } + } + +// --------------------------------------------------------------------------- +// ConvertPKIAlgorithm +// --------------------------------------------------------------------------- +// +CCTKeyInfo::EKeyAlgorithm CPKISupport::ConvertPKIAlgorithm(TPKIKeyAlgorithm aAlg) +{ + CCTKeyInfo::EKeyAlgorithm algorithm = CCTKeyInfo::EInvalidAlgorithm; + + switch(aAlg) + { + case EPKIRSA: + algorithm = CCTKeyInfo::ERSA; + break; + case EPKIDSA: + algorithm = CCTKeyInfo::EDSA; + break; + case EPKIDH: + algorithm = CCTKeyInfo::EDH; + break; + default: + break; + } + return algorithm; +} + +// --------------------------------------------------------------------------- +// ConvertSymbianAlgorithm +// --------------------------------------------------------------------------- +// +TPKIKeyAlgorithm CPKISupport::ConvertSymbianAlgorithm(CCTKeyInfo::EKeyAlgorithm aAlg) +{ + TPKIKeyAlgorithm algorithm = EPKIInvalidAlgorithm; + + switch(aAlg) + { + case ERSA: + algorithm = EPKIRSA; + break; + case EDSA: + algorithm = EPKIDSA; + break; + case EDH: + algorithm = EPKIDH; + break; + default: + break; + } + return algorithm; +} + +// --------------------------------------------------------------------------- +// CActive methods +// --------------------------------------------------------------------------- +// +void CPKISupport::RunL() + { + LOG_1("CPKISupport::RunL err:%d", iStatus.Int()); + + iSupportStatus = iStatus.Int(); + if((iSupportStatus == KErrNotSupported) && + iToggleSwitch && (iInitState == EInitCompleteImportCerts)) + { + // Some implementations of MIDP2 certstore return KErrNotSupported + // when calling iCertStore->Applications() + LOG_1("CPKISupport::RunL ignore error :%d", iSupportStatus); + iSupportStatus = KErrNone; + } + + iPending = ENoPendingOperation; + if(iSupportStatus == KErrNone) + { + DoRunOperationL(); + } + else + { + iSubState = ESSCompleteRequest; + } + + if(iSubState == ESSCompleteRequest) + { + if(iInitState != EInitDone) + { + iMessage.Complete(iSupportStatus); + } + else + { + CompleteCallerStatus( iSupportStatus ); + } + } + } + +// --------------------------------------------------------------------------- +// GetRequiredBufferSize +// --------------------------------------------------------------------------- +// +TInt CPKISupport::GetRequiredBufferSize() + { + LOG_1("CPKISupport::GetRequiredBufferSize:%d", iRequiredBufferLength); + return iRequiredBufferLength; + } + +// --------------------------------------------------------------------------- +// SetCallerStatusPending +// --------------------------------------------------------------------------- +// +void CPKISupport::SetCallerStatusPending(TRequestStatus& aStatus) + { + iCallerStatus = &aStatus; + aStatus = KRequestPending; + } + +// --------------------------------------------------------------------------- +// CompleteCallerStatus +// --------------------------------------------------------------------------- +// +void CPKISupport::CompleteCallerStatus(TInt aError) + { + LOG_("-> CPKISupport::CompleteCallerStatus"); + if(iCallerStatus) + { + if(iCurrentFunction == PkiService::EStoreCertificate || + iCurrentFunction == PkiService::EAttachCertificate) + LogCertStoring(aError); + + LOG_("Completing caller status"); + User::RequestComplete(iCallerStatus, aError); + } + else + { + LOG_("Completing rmessage"); + iMessage.Complete(aError); + } + LOG_("<- CPKISupport::CompleteCallerStatus"); + } + +// --------------------------------------------------------------------------- +// LogCertStoring +// --------------------------------------------------------------------------- +// +void CPKISupport::LogCertStoring(TInt aError) + { + TUid uId(KPkiServiceUid3); + if(aError == KErrNone) + iEventMediator.ReportLogEvent(uId, EInfo, R_VPN_MSG_CERT_INSTALLED, 1, iCertInfoForLogging); + else + { + TPckgBuf int1Des(aError); + iEventMediator.ReportLogEvent(uId, EError, R_VPN_MSG_CERT_INSTALL_FAILED, 2, &int1Des, iCertInfoForLogging); + } + } + +// --------------------------------------------------------------------------- +// DoCancel +// --------------------------------------------------------------------------- +// +void CPKISupport::DoCancel() + { + LOG_1("CPKISupport::DoCancel:%d", iStatus.Int()); + CancelCurrentOperation(); + CompleteCallerStatus( iStatus.Int() ); + } + +// --------------------------------------------------------------------------- +// RunError +// --------------------------------------------------------------------------- +// +TInt CPKISupport::RunError(TInt aError) + { + LOG_1("RunError status = %d", aError); + CompleteCallerStatus( aError ); + return KErrNone; + } + +// --------------------------------------------------------------------------- +// SetCurrentFunction +// --------------------------------------------------------------------------- +// +void CPKISupport::SetCurrentFunction(TInt aFunc) + { + iCurrentFunction = aFunc; + iSubState = ESSComplete; + } + + +// --------------------------------------------------------------------------- +// StoreCertificateL +// --------------------------------------------------------------------------- +// +void CPKISupport::StoreCertificateL(const TDesC &aLabel, + TCertificateOwnerType aOwnerType, + const TDesC8 &aBufferPtr, + const TBool& aIsDeletable, + TRequestStatus& aStatus) +{ + LOG_("Store certificate"); + iSupportStatus = KErrNone; + SetCallerStatusPending( aStatus ); + iKeyId.Zero(); + + MCTWritableCertStore* certStore(NULL); + + CX509Certificate* tempCert = CX509Certificate::NewLC(aBufferPtr); + iKeyId = tempCert->KeyIdentifierL(); + CleanupStack::PopAndDestroy(); + + if(aOwnerType == EUserCertificate) + { + if (iCertStoreType == EPkiStoreTypeDevice) + { + LOG(Log::Printf(_L(" Using device cert store\n"))); + certStore = iWritableDeviceCertStore; + } + else if (iCertStoreType == EPkiStoreTypeUser) + { + LOG(Log::Printf(_L(" Using user cert store\n"))); + certStore = iWritableCertStore; + } + else if (iCertStoreType == EPkiStoreTypeAny) + { + LOG(Log::Printf(_L(" Any cert store type, using user cert store\n"))); + certStore = iWritableCertStore; + } + else + { + LOG(Log::Printf(_L(" Error: Unknown cert store type, defaulting to user cert store\n"))); + certStore = iWritableCertStore; + } + } + else + { + certStore = iWritableCertStore; + } + + certStore->Add(aLabel, EX509Certificate, + aOwnerType, NULL, NULL, + aBufferPtr, aIsDeletable, iStatus); + + ExtractCertInfoL(aLabel, aOwnerType, aBufferPtr); + + iPending = ECertAdd; + SetActive(); +} + +// --------------------------------------------------------------------------- +// ExtractCertInfoL +// --------------------------------------------------------------------------- +// +void CPKISupport::ExtractCertInfoL(const TDesC& aLabel, + const TCertificateOwnerType& aOwnerType, + const TDesC8& aBufferPtr) +{ + _LIT8(KFormat,"Type: %S, Label: %S, Subject: %S, Issuer: %S"); + + TBuf8<4> type; + if(aOwnerType == EPKICACertificate) + type.Copy(_L8("CA")); + else + type.Copy(_L8("USER")); + + CX509Certificate* tempCert = CX509Certificate::NewLC(aBufferPtr); + + HBufC* subject = tempCert->SubjectL(); + CleanupStack::PushL(subject); + + HBufC* issuer = tempCert->IssuerL(); + CleanupStack::PushL(issuer); + + // Calculates size of + // "Type: Label: