--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/cryptoservices/certificateandkeymgmt/pkixcertbase/pkixcerts.cpp Wed Jul 08 11:25:26 2009 +0100
@@ -0,0 +1,416 @@
+/*
+* Copyright (c) 1997-2009 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of the License "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:
+*
+*/
+
+
+#include "pkixcerts.h"
+#include <ccertattributefilter.h>
+#include <cctcertinfo.h>
+
+// CPKIXCertSource
+////////////////////
+
+MPKIXCertSource::~MPKIXCertSource()
+ {
+ }
+
+// This function returns ETrue iff the issuer altname in aSubjectCert matches the
+// subject altname in aIssuerCert
+TBool MPKIXCertSource::AltNameMatchL(const CX509Certificate& aSubjectCert,
+ const CX509Certificate& aIssuerCert) const
+ {
+ TBool res = EFalse;
+ const CX509CertExtension* subjectExt = aSubjectCert.Extension(KIssuerAltName);
+ const CX509CertExtension* issuerExt = aIssuerCert.Extension(KSubjectAltName);
+ if ((subjectExt) && (issuerExt))
+ {
+ const CX509AltNameExt* issuerAltName = CX509AltNameExt::NewLC(subjectExt->Data());
+ const CX509AltNameExt* subjectAltName = CX509AltNameExt::NewLC(issuerExt->Data());
+ if (subjectAltName->Match(*issuerAltName))
+ {
+ res = ETrue;
+ }
+ CleanupStack::PopAndDestroy(2);//subjectAltName, issuerAltName
+ }
+ return res;
+ }
+
+// CPKIXCertsFromStore
+////////////////////////
+
+CPKIXCertsFromStore* CPKIXCertsFromStore::NewL(MCertStore& aCertStore)
+ {
+ CPKIXCertsFromStore* self = CPKIXCertsFromStore::NewLC(aCertStore);
+ CleanupStack::Pop(self);
+ return self;
+ }
+
+CPKIXCertsFromStore* CPKIXCertsFromStore::NewLC(MCertStore& aCertStore)
+ {
+ CPKIXCertsFromStore* self = new(ELeave) CPKIXCertsFromStore(aCertStore);
+ CleanupStack::PushL(self);
+ self->ConstructL();
+ return self;
+ }
+
+CPKIXCertsFromStore* CPKIXCertsFromStore::NewL(MCertStore& aCertStore, TUid aClient)
+ {
+ CPKIXCertsFromStore* self = CPKIXCertsFromStore::NewLC(aCertStore, aClient);
+ CleanupStack::Pop(self);
+ return self;
+ }
+
+CPKIXCertsFromStore* CPKIXCertsFromStore::NewLC(MCertStore& aCertStore, TUid aClient)
+ {
+ CPKIXCertsFromStore* self = new(ELeave) CPKIXCertsFromStore(aCertStore, aClient);
+ CleanupStack::PushL(self);
+ self->ConstructL(aClient);
+ return self;
+ }
+
+void CPKIXCertsFromStore::Initialize(TRequestStatus& aStatus)
+ {
+ // In the case of a WIM, we don't have trust settings,
+ // the WIM store will ignore the filter and return all certificates
+ aStatus = KRequestPending;
+ iOriginalRequestStatus = &aStatus;
+ iState = EInitialize;
+ iCertStore.List(iCertInfos, *iFilter, iStatus);
+ SetActive();
+ }
+
+void CPKIXCertsFromStore::CandidatesL(const CX509Certificate& aSubject,
+ RPointerArray<CX509Certificate>& aCandidates,
+ TRequestStatus& aStatus)
+ {
+ aStatus = KRequestPending;
+ iOriginalRequestStatus = &aStatus;
+
+ iRootName = &aSubject.IssuerName();
+ iSubject = &aSubject;
+ iCandidates = &aCandidates;
+ iEntriesIndex = -1;
+
+ iState = ECheckTrusted;
+ TRequestStatus* status = &iStatus;
+ User::RequestComplete(status, KErrNone);
+ SetActive();
+ }
+
+void CPKIXCertsFromStore::CancelCandidates()
+ {
+ Cancel();
+ }
+
+void CPKIXCertsFromStore::Release()
+ {
+ delete this;
+ }
+
+CPKIXCertsFromStore::~CPKIXCertsFromStore()
+ {
+ Cancel();
+
+ iCertInfos.Close();
+
+ delete iFilter;
+
+ delete iCertData;
+ delete iCertPtr;
+ }
+
+//private functions
+CPKIXCertsFromStore::CPKIXCertsFromStore(MCertStore& aCertStore)
+ : CActive(EPriorityNormal), iCertStore(aCertStore)
+ {
+ CActiveScheduler::Add(this);
+ }
+
+CPKIXCertsFromStore::CPKIXCertsFromStore(MCertStore& aCertStore, TUid aClient)
+: CActive(EPriorityNormal), iClient(aClient), iCertStore(aCertStore)
+ {
+ CActiveScheduler::Add(this);
+ }
+
+void CPKIXCertsFromStore::ConstructL()
+ {
+ iFilter = CCertAttributeFilter::NewL();
+ iFilter->SetFormat(EX509Certificate);
+ iFilter->SetOwnerType(ECACertificate);
+ }
+
+void CPKIXCertsFromStore::ConstructL(TUid aClient)
+ {
+ iFilter = CCertAttributeFilter::NewL();
+ iFilter->SetUid(aClient);
+ iFilter->SetFormat(EX509Certificate);
+ iFilter->SetOwnerType(ECACertificate);
+ }
+
+void CPKIXCertsFromStore::RunL()
+ {
+ User::LeaveIfError(iStatus.Int());
+
+ switch (iState)
+ {
+ case EInitialize:
+ iState = EIdle;
+ User::RequestComplete(iOriginalRequestStatus, iStatus.Int());
+ break;
+
+ case ECheckTrusted:
+ HandleECheckTrusted();
+ break;
+
+ case EGetCertificate:
+ HandleEGetCertificateL();
+ break;
+
+ case EAddCandidate:
+ HandleEAddCandidateL();
+ break;
+
+ case EEnd:
+ iState = EIdle;
+ User::RequestComplete(iOriginalRequestStatus, KErrNone);
+ break;
+
+ default:
+ __ASSERT_ALWAYS(0, User::Panic(_L("CPKIXCertsFromStore"), 1));
+ break;
+ }
+ }
+
+TInt CPKIXCertsFromStore::RunError(TInt aError)
+ {
+ User::RequestComplete(iOriginalRequestStatus, aError);
+ return KErrNone;
+ }
+
+void CPKIXCertsFromStore::DoCancel()
+ {
+ switch(iState)
+ {
+ case EInitialize:
+ iCertStore.CancelList();
+ break;
+
+ case EGetCertificate:
+ iCertStore.CancelTrusted();
+ break;
+
+ case EAddCandidate:
+ iCertStore.CancelRetrieve();
+ break;
+
+ case ECheckTrusted:
+ case EEnd:
+ // nothing to do
+ break;
+
+ default:
+ __ASSERT_ALWAYS(0, User::Panic(_L("CPKIXCertsFromStore"), 1));
+ break;
+ }
+
+ User::RequestComplete(iOriginalRequestStatus, KErrCancel);
+ iState = EIdle;
+ }
+
+void CPKIXCertsFromStore::HandleECheckTrusted()
+ {// iEntriesIndex has been initialized to -1 by Candidates
+ iEntriesIndex++;
+ if (iEntriesIndex < iCertInfos.Count())
+ {
+ const CCTCertInfo* entry = iCertInfos[iEntriesIndex];
+
+ // Fix for DEF017139 "PKIXCert ignores trust"
+ // Check the certificate is trusted and discard it if not
+ iCertStore.Trusted(*entry, iIsTrusted, iStatus);
+ iState = EGetCertificate;
+ }
+ else
+ {
+ iState = EEnd;
+ TRequestStatus* status = &iStatus;
+ User::RequestComplete(status, KErrNone);
+ }
+ SetActive();
+ }
+
+void CPKIXCertsFromStore::HandleEGetCertificateL()
+{
+ if (iIsTrusted)
+ {// Fine to trust, go ahead
+ const CCTCertInfo* entry = iCertInfos[iEntriesIndex];
+ __ASSERT_DEBUG(!iCertData, User::Panic(_L("CPKIXCertsFromStore"), 1));
+ iCertData = HBufC8::NewL(entry->Size());
+ __ASSERT_DEBUG(!iCertPtr, User::Panic(_L("CPKIXCertsFromStore"), 1));
+ iCertPtr = new(ELeave) TPtr8(iCertData->Des());
+ iCertStore.Retrieve(*entry, *iCertPtr, iStatus);
+ iState = EAddCandidate;
+ }
+ else
+ {// Not trusted, check next for trust
+ iState = ECheckTrusted;
+ TRequestStatus* status = &iStatus;
+ User::RequestComplete(status, KErrNone);
+ }
+
+ SetActive();
+}
+
+
+TBool CPKIXCertsFromStore::IsDuplicateL(const CX509Certificate& aCandidate)
+ {
+
+ TInt candidatesCount = iCandidates->Count();
+ for (TInt i = 0; i < candidatesCount; i++)
+ {
+
+ // Certificate is a duplicate iff
+ // a) The public keys have the same hash, and
+ // b) The serial numbers are identical
+
+ CX509Certificate* cert = (*iCandidates)[i];
+ if (cert->KeyIdentifierL() == aCandidate.KeyIdentifierL()
+ && cert->SerialNumber() == aCandidate.SerialNumber())
+ {
+ return ETrue;
+ }
+
+ }
+
+ return EFalse;
+
+ }
+
+void CPKIXCertsFromStore::HandleEAddCandidateL()
+ {
+ CX509Certificate *candidate = CX509Certificate::NewLC(*iCertData);
+ delete iCertData;
+ iCertData = 0;
+ delete iCertPtr;
+ iCertPtr = 0;
+
+ if (iRootName->Count() > 0)
+ {
+ if (candidate->SubjectName().ExactMatchL(*iRootName) && !IsDuplicateL(*candidate))
+ {
+ User::LeaveIfError(iCandidates->Append(candidate));
+ CleanupStack::Pop(); // candidate
+ }
+ else
+ {
+ CleanupStack::PopAndDestroy(); // candidate
+ }
+ }
+ else
+ {
+ const CX500DistinguishedName& candidateName = candidate->SubjectName();
+ if ((candidateName.Count() == 0) && (AltNameMatchL(*iSubject, *candidate)))
+ {
+ User::LeaveIfError(iCandidates->Append(candidate));
+ CleanupStack::Pop(); // candidate
+ }
+ else
+ {
+ CleanupStack::PopAndDestroy(); // candidate
+ }
+ }
+
+ iState = ECheckTrusted;
+ TRequestStatus* status = &iStatus;
+ User::RequestComplete(status, KErrNone);
+ SetActive();
+ }
+
+//CPKIXCertsFromClient
+//public functions
+CPKIXCertsFromClient* CPKIXCertsFromClient::NewL(const RPointerArray<CX509Certificate>& aCerts)
+ {
+ CPKIXCertsFromClient* self = new(ELeave) CPKIXCertsFromClient(aCerts);
+ return self;
+ }
+
+CPKIXCertsFromClient* CPKIXCertsFromClient::NewLC(const RPointerArray<CX509Certificate>& aCerts)
+ {
+ CPKIXCertsFromClient* self = new(ELeave) CPKIXCertsFromClient(aCerts);
+ CleanupStack::PushL(self);
+ return self;
+ }
+
+void CPKIXCertsFromClient::Release()
+ {
+ delete this;
+ }
+
+CPKIXCertsFromClient::~CPKIXCertsFromClient()
+ {
+ }
+
+void CPKIXCertsFromClient::CandidatesL(const CX509Certificate& aSubject,
+ RPointerArray<CX509Certificate>& aCandidates,
+ TRequestStatus& aStatus)
+ {
+ // There is no need for this to be asynchronous but it is because the base class
+ // wants this to be
+
+ const CX500DistinguishedName& rootName = aSubject.IssuerName();
+ TInt count = iCerts.Count();
+ const CX509Certificate* candidate = NULL;
+ if (rootName.Count() > 0)
+ {
+ for (TInt i = 0; i < count; i++)
+ {
+ candidate = iCerts[i];
+ if (candidate->SubjectName().ExactMatchL(rootName))
+ {
+ CX509Certificate* cert = CX509Certificate::NewLC(*candidate);
+ User::LeaveIfError(aCandidates.Append(cert));
+ CleanupStack::Pop();
+ }
+ }
+ }
+ else
+ {
+ for (TInt i = 0; i < count; i++)
+ {
+ candidate = iCerts[i];
+ const CX500DistinguishedName& candidateName = candidate->SubjectName();
+ if ((candidateName.Count() ==0) && (AltNameMatchL(aSubject, *candidate)))
+ {
+ CX509Certificate* cert = CX509Certificate::NewLC(*candidate);
+ User::LeaveIfError(aCandidates.Append(cert));
+ CleanupStack::Pop();
+ }
+ }
+ }
+
+ TRequestStatus* status = &aStatus;
+ User::RequestComplete(status, KErrNone);
+ }
+
+void CPKIXCertsFromClient::CancelCandidates()
+ {
+ // Nothing to do because the function completes immediately
+ }
+
+//private functions
+CPKIXCertsFromClient::CPKIXCertsFromClient(const RPointerArray<CX509Certificate>& aCerts)
+ :iCerts(aCerts)
+ {
+ }