--- /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 <securitydefs.h>
+#include <cctcertinfo.h>
+#include <x509cert.h>
+#include <ccertattributefilter.h>
+#include <asymmetric.h>
+#include <unifiedcertstore.h>
+#include <mctwritablecertstore.h>
+
+#include "pkiwrapper.h"
+#include "PKIMapper.h"
+#include "pkisupport.h"
+#include "pkisession.h"
+#include "log_r6.h"
+#include "pkiserviceassert.h"
+#include "pkiserviceconstants.h"
+#include <vpnlogmessages.rsg>
+
+
+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<CCTCertInfo>;
+
+ 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;i<iApplUids.Count();i++)
+ {
+ iImportCertMapping->iApplUids.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<TInt> 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: <type> Label: <label> Subject: <subject> Issuer: <issuer>"
+ TInt bufSize(((TDesC8)KFormat).Length() + type.Length() + aLabel.Length() + subject->Length() + issuer->Length());
+ delete iCertInfoForLogging; iCertInfoForLogging = NULL;
+ iCertInfoForLogging = HBufC8::NewL(bufSize);
+
+ TPtr8 ptrLogMsg = iCertInfoForLogging->Des();
+ ptrLogMsg.Format(KFormat, &type, &aLabel, subject, issuer);
+
+ CleanupStack::PopAndDestroy(issuer);
+ CleanupStack::PopAndDestroy(subject);
+ CleanupStack::PopAndDestroy(tempCert);
+}
+
+
+// ---------------------------------------------------------------------------
+// ?description_if_needed
+// ---------------------------------------------------------------------------
+//
+void CPKISupport::AttachCertificateL(const TDesC& aLabel,
+ const TPKIKeyIdentifier &aKeyId, const TDesC8 &aBufferPtr,
+ TRequestStatus& aStatus)
+{
+ TKeyIdentifier tempKeyId;
+ CX509Certificate* certificate = CX509Certificate::NewLC(aBufferPtr);
+
+ LOG_("Attach certificate");
+
+ iSupportStatus = KErrNone;
+ iKeyId = aKeyId;
+
+ ExtractCertInfoL(aLabel, EUserCertificate, aBufferPtr);
+
+ // fetch the keyId from the certificate
+ tempKeyId = certificate->KeyIdentifierL();
+ // If given keyId is empty, use the keyId from the certificate
+ if(iKeyId.Length() == 0)
+ {
+ iKeyId = tempKeyId;
+ }
+
+ SetCallerStatusPending( aStatus );
+ CleanupStack::PopAndDestroy(certificate); // certificate
+
+ iSubState = ESSComplete;
+
+ MCTWritableCertStore* certStore(NULL);
+
+ LOG(Log::Printf(_L("-------------------"));
+
+ TBuf<256> buf;
+ buf.Format(_L("Attaching certificate '%S'"), &aLabel);
+ Log::Printf(buf);
+ Log::Printf(_L("Certificate's KEY ID:"));
+ Log::HexDump(NULL, NULL, iKeyId.Ptr(), iKeyId.Length());
+ );
+ if (iCertStoreType == EPkiStoreTypeDevice)
+ {
+ LOG(Log::Printf(_L("CPKISupport::ContinueAttachCertificate() Using device cert store\n")));
+ certStore = iWritableDeviceCertStore;
+ }
+ else if (iCertStoreType == EPkiStoreTypeUser)
+ {
+ LOG(Log::Printf(_L("CPKISupport::ContinueAttachCertificate() Using user cert store\n")));
+ certStore = iWritableCertStore;
+ }
+ else if (iCertStoreType == EPkiStoreTypeAny)
+ {
+ LOG(Log::Printf(_L("CPKISupport::ContinueAttachCertificate() Any cert store, 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;
+ }
+ LOG(Log::Printf(_L("-------------------")));
+
+ certStore->Add(aLabel,
+ EX509Certificate,
+ EUserCertificate,
+ &iKeyId,
+ NULL,
+ aBufferPtr,
+ iStatus);
+ iPending = ECertAdd;
+ SetActive();
+}
+
+
+// ---------------------------------------------------------------------------
+// ?description_if_needed
+// ---------------------------------------------------------------------------
+//
+void CPKISupport::RetrieveCertificateL(const TDesC &aLabel,
+ TPtr8 &aBufferPtr, const TPKICertificateOwnerType& aType,
+ TRequestStatus& aStatus)
+{
+ LOG(Log::Printf(_L("Retrieve certificate\n")));
+ iSupportStatus = KErrNone;
+ iCerts->Close();
+ iSubState = ESSContinue;
+ iOutBufferPtr = &aBufferPtr;
+ SetCallerStatusPending( aStatus );
+ SelectCertificateL(aLabel, aType);
+}
+
+// ---------------------------------------------------------------------------
+// ?description_if_needed
+// ---------------------------------------------------------------------------
+//
+void CPKISupport::ContinueRetrieveCertificate()
+{
+ iSubState = ESSComplete;
+ iPending = ECertRetrieve;
+
+ TUint certificateSize = (*iCerts)[0]->Size();
+ iRequiredBufferLength = certificateSize;
+ if (certificateSize <= iOutBufferPtr->MaxLength())
+ {
+ iCertStore->Retrieve(*(*iCerts)[0], *iOutBufferPtr, iStatus);
+ SetActive();
+ }
+ else
+ {
+ iStatus = KRequestPending;
+ SetActive();
+
+ TRequestStatus* ownStatus = &iStatus;
+ User::RequestComplete(ownStatus, KPKIErrBufferTooShort);
+ }
+}
+
+
+/**
+ Removes all unnecessary certificates from the certificate
+ list before generating the local mapping data.
+ More specifically, all MIDP2 and non X509 certificates are removed.
+ (MIDP2 certificates can never have a "VPN" trust setting.)
+
+ iListCleaned instance variable is used to limit the frequency
+ of this cleanup - it's only necessary once, during PKI startup.
+*/
+void CPKISupport::CleanupCertListL()
+ {
+ LOG_("Removing invalid certs (MIDP2 certs)");
+ if (iCerts)
+ {
+ TInt certcount = iCerts->Count();
+ _LIT(KMidp2Label, "MIDP2");
+ LOG_1("Total cert count, before cleanup: %d", iCerts->Count());
+ RMPointerArray<CCTCertInfo> removedInfos;
+ CleanupClosePushL(removedInfos);
+ for (TInt i = certcount - 1; i >= 0; i--)
+ {
+ CCTCertInfo* info = (*iCerts)[i];
+ if (info->Label().Compare(KMidp2Label) == 0 ||
+ info->CertificateFormat() != EX509Certificate)
+ {
+ // CCTCertInfo has private destructor
+ removedInfos.AppendL( info );
+ iCerts->Remove(i);
+ continue;
+ }
+ }
+ CleanupStack::PopAndDestroy(); // removedInfos
+ iCerts->Compress();
+ LOG_1("Total cert count, after cleanup: %d", iCerts->Count());
+ }
+ else
+ {
+ LOG_("Certs list empty!");
+ }
+ }
+
+// ---------------------------------------------------------------------------
+// DoRunOperationL
+// ---------------------------------------------------------------------------
+//
+void CPKISupport::DoRunOperationL()
+ {
+ LOG_1("CPKISupport::DoRunOperationL iInitState:%d", iInitState);
+ LOG_1("CPKISupport::DoRunOperationL iCurrentFunction:%d",
+ iCurrentFunction);
+ LOG_1("CPKISupport::DoRunOperationL iSubState:%d", iSubState);
+
+ switch(iInitState)
+ {
+ case EInitDone:
+ DoRunLoggedInOperationL();
+ break;
+
+ case EInitInitializeCertStore:
+ if(iMapper.CacheCreated())
+ {
+ FindInterfacesL();
+ iInitState = EInitDone;
+ iMessage.Complete(KErrNone);
+ return;
+ }
+ else
+ {
+ iMapper.SetCacheCreated();
+ FindInterfacesL();
+ ListAllCertificatesL();
+ }
+ break;
+ case EInitRetrieveCertList:
+ LOG_("CPKISupport::DoRunOperationL() EInitRetrieveCertList");
+ // Cert list might be new. Remove all MIDP2 certificates first,
+ // if it hasn't been already done
+ CleanupCertListL();
+ iInitState = EInitCompleteImportCerts;
+
+ //Falls through
+ case EInitCompleteImportCerts:
+ LOG_("CPKISupport::DoRunOperationL() EInitCompleteImportCerts");
+ if(GetApplicationsOfCTFCertL())
+ {
+ LOG_(" Getting cert's applications returned with FALSE, breaking");
+ break;
+ }
+ SaveCertInfoToCacheL(); // Handles one certificate, if found
+ if(iImportCounter < iCerts->Count())
+ {
+ ReadNextCertForImportL();
+ }
+ else
+ {
+ LOG_(" All certificates imported, doing clean ups");
+ // Cleanup
+
+ delete iImportCertMapping;
+ iImportCertMapping = NULL;
+
+ delete iImportCertData;
+ iImportCertData = NULL;
+
+ iCerts->Close();
+
+ delete iCertFilter;
+ iCertFilter = NULL;
+ iInitState = EInitDone;
+ iMessage.Complete(KErrNone);
+ }
+ break; // repeat
+ default:
+ PKISERVICE_INVARIANT();
+ iSupportStatus = KPKIErrUnexpectedState;
+ iSubState = ESSCompleteRequest;
+ break;
+ } // End switch(iInitState)
+
+ }
+
+// ---------------------------------------------------------------------------
+// DoRunLoggedInOperationL
+// ---------------------------------------------------------------------------
+//
+void CPKISupport::DoRunLoggedInOperationL()
+ {
+ LOG_1("CPKISupport::DoRunLoggedInOperationL iCurrentFunction:%d",
+ iCurrentFunction);
+ LOG_1("CPKISupport::DoRunLoggedInOperationL iSubState:%d", iSubState);
+
+ switch(iCurrentFunction)
+ {
+ case PkiService::EAttachCertificate:
+ switch(iSubState)
+ {
+ case ESSComplete:
+ iSubState = ESSCompleteRequest;
+ break;
+ default:
+ iSupportStatus = KPKIErrUnexpectedState;
+ iSubState = ESSCompleteRequest;
+ break;
+ }
+ break;
+
+ case PkiService::EReadCertificate:
+ switch(iSubState)
+ {
+ case ESSContinue:
+ {
+ if(iCerts->Count() > 1)
+ {
+ LOG(Log::Printf(_L("Duplicate Certificate\n")));
+ iSubState = ESSCompleteRequest;
+ iSupportStatus = KErrNotFound;
+ }
+ else if (iCerts->Count() < 1)
+ {
+ LOG(Log::Printf(_L("No matching certificates found\n")));
+ iSubState = ESSCompleteRequest;
+ iSupportStatus = KErrNotFound;
+ }
+ else if ((((*iCerts)[0])->CertificateOwnerType() == EUserCertificate) &&
+ (((iCertStoreType == EPkiStoreTypeDevice) && (((*iCerts)[0])->Token().Label().Compare(KDeviceCertStore)!=0)) ||
+ ((iCertStoreType == EPkiStoreTypeUser) && (((*iCerts)[0])->Token().Label().Compare(KUserCertStore)!=0))))
+ {
+ LOG_1("User certificate's certificate info does not match certificate store type. Store type is: %d", iCertStoreType);
+ iSubState = ESSCompleteRequest;
+ iSupportStatus = KErrNotFound;
+ }
+ else
+ {
+ ContinueRetrieveCertificate();
+ }
+ break;
+ }
+ case ESSComplete:
+ iSubState = ESSCompleteRequest;
+ break;
+ default:
+ iSupportStatus = KPKIErrUnexpectedState;
+ iSubState = ESSCompleteRequest;
+ break;
+ }
+ break;
+
+ case PkiService::ESetTrust:
+ case PkiService::ETrusted:
+ switch(iSubState)
+ {
+ case ESSContinue:
+ {
+ if(iCerts->Count() != 1)
+ {
+ iSubState = ESSCompleteRequest;
+ iSupportStatus = KErrNotFound;
+ }
+ else
+ {
+ if(iCurrentFunction == PkiService::ESetTrust)
+ {
+ ContinueSetTrust();
+ }
+ else
+ {
+ ContinueTrusted();
+ }
+ }
+ break;
+ }
+ case ESSComplete:
+ if(iCurrentFunction == PkiService::ETrusted)
+ {
+ iWrapper.SetTrusted(iTrusted);
+ }
+ iSubState = ESSCompleteRequest;
+ break;
+ default:
+ iSupportStatus = KPKIErrUnexpectedState;
+ iSubState = ESSCompleteRequest;
+ break;
+ }
+ break;
+
+ case PkiService::ESetApplicability:
+ case PkiService::EApplications:
+ switch(iSubState)
+ {
+ case ESSContinue:
+ {
+ if(iCerts->Count() != 1)
+ {
+ iSubState = ESSCompleteRequest;
+ iSupportStatus = KErrNotFound;
+ }
+ else
+ {
+ if(iCurrentFunction == PkiService::ESetApplicability)
+ {
+ ContinueSetApplicability();
+ }
+ else if(iCurrentFunction == PkiService::EApplications)
+ {
+ ContinueApplications();
+ }
+ else
+ {
+ PKISERVICE_INVARIANT();
+ }
+ }
+ break;
+ }
+ case ESSComplete:
+ if(iCurrentFunction == PkiService::EApplications)
+ {
+ iWrapper.SetApplications(iApplUids);
+ }
+
+ iSubState = ESSCompleteRequest;
+ break;
+ default:
+ iSupportStatus = KPKIErrUnexpectedState;
+ iSubState = ESSCompleteRequest;
+ break;
+ }
+ break;
+
+ case PkiService::ERemoveCertificate:
+ switch(iSubState)
+ {
+ case ESSContinue:
+ if(iCerts->Count() != 1)
+ {
+ iSupportStatus = KPKIErrNotFound;
+ iSubState = ESSCompleteRequest;
+ }
+ else
+ {
+ ContinueRemoveCertificate();
+ }
+ break;
+ case ESSComplete:
+ iSubState = ESSCompleteRequest;
+ break;
+ default:
+ iSupportStatus = KPKIErrUnexpectedState;
+ iSubState = ESSCompleteRequest;
+ break;
+ }
+ break;
+ default:
+ iSubState = ESSCompleteRequest;
+ break;
+ }
+ }
+
+
+
+
+
+
+// ---------------------------------------------------------------------------
+// ?description_if_needed
+// ---------------------------------------------------------------------------
+//
+void CPKISupport::RemoveCertificateL(const TDesC &aLabel,
+ TRequestStatus& aStatus)
+{
+ LOG(Log::Printf(_L("Remove certificate\n")));
+ iSupportStatus = KErrNone;
+ iCerts->Close();
+ iSubState = ESSContinue;
+ SetCallerStatusPending( aStatus );
+ SelectCertificateL(aLabel);
+}
+
+// ---------------------------------------------------------------------------
+// ?description_if_needed
+// ---------------------------------------------------------------------------
+//
+void CPKISupport::ContinueRemoveCertificate()
+{
+ iCertStore->Remove(*(*iCerts)[0], iStatus);
+ iPending = ECertRemove;
+ iSubState = ESSComplete;
+ SetActive();
+}
+
+
+// ---------------------------------------------------------------------------
+// ?description_if_needed
+// ---------------------------------------------------------------------------
+//
+void CPKISupport::SetTrustL(const TDesC &aLabel,
+ TBool aTrusted, TRequestStatus& aStatus)
+{
+ LOG(Log::Printf(_L("SetTrust\n")));
+ iSupportStatus = KErrNone;
+ iCerts->Close();
+ iSubState = ESSContinue;
+ iTrusted = aTrusted;
+ SetCallerStatusPending( aStatus );
+ SelectCertificateL(aLabel);
+}
+
+// ---------------------------------------------------------------------------
+// ?description_if_needed
+// ---------------------------------------------------------------------------
+//
+void CPKISupport::ContinueSetTrust()
+{
+ iSubState = ESSComplete;
+ iCertStore->SetTrust(*(*iCerts)[0], iTrusted, iStatus);
+ iPending = ESetTrust;
+ SetActive();
+}
+
+// ---------------------------------------------------------------------------
+// ?description_if_needed
+// ---------------------------------------------------------------------------
+//
+void CPKISupport::TrustedL(const TDesC &aLabel, TRequestStatus& aStatus)
+{
+ LOG(Log::Printf(_L("Trusted\n")));
+ iSupportStatus = KErrNone;
+ iCerts->Close();
+ iSubState = ESSContinue;
+ SetCallerStatusPending( aStatus );
+ SelectCertificateL(aLabel);
+}
+
+// ---------------------------------------------------------------------------
+// ?description_if_needed
+// ---------------------------------------------------------------------------
+//
+void CPKISupport::ContinueTrusted()
+{
+ iSubState = ESSComplete;
+ iCertStore->Trusted(*(*iCerts)[0], iTrusted, iStatus);
+ iPending = ETrusted;
+ SetActive();
+}
+
+// ---------------------------------------------------------------------------
+// ?description_if_needed
+// ---------------------------------------------------------------------------
+//
+void CPKISupport::SetApplicabilityL(const TDesC &aLabel, const RArray<TUid>& aApplUids, TRequestStatus& aStatus)
+{
+ LOG(Log::Printf(_L("SetApplicability\n")));
+ iSupportStatus = KErrNone;
+ iCerts->Close();
+ iSubState = ESSContinue;
+ iApplUids.Close();
+ for(TInt i = 0;i<aApplUids.Count();i++)
+ {
+ iApplUids.Append(aApplUids[i]);
+ }
+ SetCallerStatusPending( aStatus );
+ SelectCertificateL(aLabel);
+}
+
+// ---------------------------------------------------------------------------
+// ContinueSetApplicability
+// ---------------------------------------------------------------------------
+//
+void CPKISupport::ContinueSetApplicability()
+ {
+ PKISERVICE_ASSERT(iCerts && iCerts->Count());
+ iSubState = ESSComplete;
+ iCertStore->SetApplicability(*(*iCerts)[0], iApplUids, iStatus);
+ iPending = ESetApplicability;
+ SetActive();
+ }
+
+// ---------------------------------------------------------------------------
+// ?description_if_needed
+// ---------------------------------------------------------------------------
+//
+void CPKISupport::ApplicationsL(const TDesC &aLabel, TRequestStatus& aStatus)
+{
+ LOG(Log::Printf(_L("Applications\n")));
+ iSupportStatus = KErrNone;
+ iCerts->Close();
+ iSubState = ESSContinue;
+ SetCallerStatusPending( aStatus );
+ SelectCertificateL(aLabel);
+}
+
+// ---------------------------------------------------------------------------
+// ContinueApplications
+// ---------------------------------------------------------------------------
+//
+void CPKISupport::ContinueApplications()
+{
+ iSubState = ESSComplete;
+ iApplUids.Close();
+ iCertStore->Applications(*(*iCerts)[0], iApplUids, iStatus);
+ iPending = EApplications;
+ SetActive();
+}
+
+
+// ---------------------------------------------------------------------------
+// SelectCertificateL
+// ---------------------------------------------------------------------------
+//
+void CPKISupport::SelectCertificateL(const TDesC &aLabel,
+ const TPKICertificateOwnerType& aType )
+{
+ delete iCertFilter;
+ iCertFilter = NULL;
+ iCertFilter = CCertAttributeFilter::NewL();
+
+ LOG(Log::Printf(_L(" Select by label: %S\n"), &aLabel));
+ iCertFilter->SetLabel(aLabel);
+ if (aType != 0)
+ {
+ LOG_1(" Select by owner type: %d", aType);
+ iCertFilter->SetOwnerType(TCertificateOwnerType(aType));
+ }
+ GetCertificateStoreListAsync();
+}
+
+
+
+// ---------------------------------------------------------------------------
+// GetCertificateStoreListAsync()
+// ---------------------------------------------------------------------------
+//
+void CPKISupport::GetCertificateStoreListAsync()
+ {
+ LOG_1("-> CPKISupport::GetCertificateStoreListAsync() iSubState:%d",
+ iSubState );
+ // preconditions
+ PKISERVICE_ASSERT( iCerts && iCertFilter && iStatus != KRequestPending );
+ LOG_1("CPKISupport::GetSertificateStoreListAsync iSubState:%d",
+ iSubState );
+
+ // Get list of all known certificates
+ iCertStore->List(*iCerts, *iCertFilter, iStatus);
+ iPending = EListCerts;
+ SetActive();
+ LOG_("<- CPKISupport::GetCertificateStoreListAsync()");
+ }
+
+