--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/cryptoservices/certificateandkeymgmt/pkixcertbase/Pkixchainbuilder.cpp Wed Jul 08 11:25:26 2009 +0100
@@ -0,0 +1,214 @@
+/*
+* 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 "pkixchainbuilder.h"
+
+CPKIXChainBuilder* CPKIXChainBuilder::NewL()
+ {
+ CPKIXChainBuilder* s = CPKIXChainBuilder::NewLC();
+ CleanupStack::Pop(s);
+ return s;
+ }
+
+CPKIXChainBuilder* CPKIXChainBuilder::NewLC()
+ {
+ CPKIXChainBuilder* s = new (ELeave) CPKIXChainBuilder;
+ CleanupStack::PushL(s);
+ s->ConstructL();
+ return s;
+ }
+
+CPKIXChainBuilder::~CPKIXChainBuilder()
+ {
+ Cancel();
+ iSources.Close();
+ iCandidates.ResetAndDestroy();
+ iCandidates.Close();
+ }
+
+void CPKIXChainBuilder::AddSourceL(MPKIXCertSource* aSource)
+ {
+ User::LeaveIfError(iSources.Append(aSource));
+ }
+
+void CPKIXChainBuilder::AddIssuer(TInt& aNumberOfCertsAdded,
+ TBool& aResult,
+ CArrayPtrFlat<CX509Certificate>& aChain,
+ TRequestStatus& aStatus)
+ {
+ iOriginalRequestStatus = &aStatus;
+ aStatus = KRequestPending;
+ iResult = &aResult;
+ iChain = &aChain;
+ iNumberOfCertsAdded = &aNumberOfCertsAdded;
+
+ iSubject = aChain[aChain.Count()-1];
+ __ASSERT_DEBUG(iSubject, User::Panic(_L("CPKICCertChainAO"), 1));
+ __ASSERT_DEBUG(!iCandidates.Count(), User::Panic(_L("CPKICCertChainAO"), 1));
+
+ iIndex = -1;
+ iState = EAddCandidate;
+ TRequestStatus* status = &iStatus;
+ User::RequestComplete(status, KErrNone);
+ SetActive();
+ }
+
+CPKIXChainBuilder::CPKIXChainBuilder()
+: CActive(EPriorityNormal)
+ {
+ CActiveScheduler::Add(this);
+ }
+
+void CPKIXChainBuilder::ConstructL()
+ {
+ }
+
+TBool CPKIXChainBuilder::ResolveIssuersL(CArrayPtr<CX509Certificate>& aChain,
+ const RPointerArray<CX509Certificate>& aCandidates) const
+ {
+ //*this function attempts to figure out which certificate in aCandidates is the issuer of
+ //the last cert in the aChain, and adds a *copy* of the best guess to aChain
+ //*it assumes that the names match already
+ //*if it establishes that none are any good it returns EFalse
+ TInt count = aCandidates.Count();
+ if (count == 0)
+ {
+ return EFalse;
+ }
+ if (count == 1)
+ {
+ CX509Certificate* cert = CX509Certificate::NewLC(*aCandidates[0]);
+ aChain.AppendL(cert);
+ (*iNumberOfCertsAdded)++;
+ CleanupStack::Pop(cert);
+ return ETrue;
+ }
+
+ const CX509Certificate* current = aChain[aChain.Count() - 1];
+ //1) look for SKI/AKI to distinguish
+ const CX509CertExtension* akiExt = current->Extension(KAuthorityKeyId);
+ if (akiExt)
+ {
+ const CX509AuthorityKeyIdExt* aki = CX509AuthorityKeyIdExt::NewLC(akiExt->Data());
+ TPtrC8 authorityKeyId = aki->KeyId();
+ if (authorityKeyId != KNullDesC8)
+ {
+ for (TInt i = 0; i < count; i++)
+ {
+ const CX509CertExtension* skiExt = (aCandidates[i])->Extension(KSubjectKeyId);
+ if (skiExt)
+ {
+ const CX509SubjectKeyIdExt* ski = CX509SubjectKeyIdExt::NewLC(skiExt->Data());
+ if (authorityKeyId == ski->KeyId())
+ {
+ CX509Certificate* issuer = CX509Certificate::NewLC(*aCandidates[i]);
+ aChain.AppendL(issuer);
+ (*iNumberOfCertsAdded)++;
+ CleanupStack::Pop();//issuer
+ CleanupStack::PopAndDestroy(2);//aki, ski
+ return ETrue;
+ }
+ else
+ {
+ CleanupStack::PopAndDestroy();//ski
+ }
+ }
+ }
+ }
+ //ok, we haven't got a key ID for the issuer, so try for a serial number instead...
+ else
+ {
+ TPtrC8 authoritySerialNo = aki->AuthorityCertSerialNumber();
+ for (TInt i = 0; i < count; i++)
+ {
+ const CX509Certificate* candidate = aCandidates[i];
+ if (authoritySerialNo == candidate->SerialNumber())
+ {
+ CX509Certificate* issuer = CX509Certificate::NewLC(*candidate);
+ aChain.AppendL(issuer);
+ (*iNumberOfCertsAdded)++;
+ CleanupStack::Pop();//issuer
+ CleanupStack::PopAndDestroy();//aki
+ return ETrue;
+ }
+ }
+ }
+ CleanupStack::PopAndDestroy();//aki
+ }
+
+ return EFalse;
+ }
+
+
+void CPKIXChainBuilder::RunL()
+ {
+ User::LeaveIfError(iStatus.Int());
+
+ switch (iState)
+ {
+ case EAddCandidate:
+ iIndex++;
+ if (iIndex < iSources.Count())
+ {
+ iSources[iIndex]->CandidatesL(*iSubject, iCandidates, iStatus);
+ }
+ else
+ {
+ iState = EFinished;
+ TRequestStatus* status = &iStatus;
+ User::RequestComplete(status, KErrNone);
+ }
+ SetActive();
+ break;
+
+ case EFinished:
+ iState = EIdle;
+ *iResult = ResolveIssuersL(*iChain, iCandidates);
+ iCandidates.ResetAndDestroy();
+ User::RequestComplete(iOriginalRequestStatus, KErrNone);
+ break;
+
+ default:
+ User::Panic(_L("CPKIXChainBuilder"), 1);
+ break;
+ }
+ }
+
+void CPKIXChainBuilder::DoCancel()
+ {
+ int i = 0;
+ int end = iSources.Count();
+ while (i < end)
+ {
+ iSources[i]->CancelCandidates();
+ i++;
+ }
+ iCandidates.ResetAndDestroy();
+
+ User::RequestComplete(iOriginalRequestStatus, KErrCancel);
+
+ iState = EIdle;
+ }
+
+TInt CPKIXChainBuilder::RunError(TInt aError)
+ {
+ iState = EIdle;
+ iCandidates.ResetAndDestroy();
+ User::RequestComplete(iOriginalRequestStatus, aError);
+ return KErrNone;
+ }