os/security/cryptoservices/certificateandkeymgmt/pkixcertbase/Pkixchainbuilder.cpp
First public contribution.
2 * Copyright (c) 1997-2010 Nokia Corporation and/or its subsidiary(-ies).
4 * This component and the accompanying materials are made available
5 * under the terms of the License "Eclipse Public License v1.0"
6 * which accompanies this distribution, and is available
7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
9 * Initial Contributors:
10 * Nokia Corporation - initial contribution.
19 #include "pkixchainbuilder.h"
21 CPKIXChainBuilder* CPKIXChainBuilder::NewL()
23 CPKIXChainBuilder* s = CPKIXChainBuilder::NewLC();
28 CPKIXChainBuilder* CPKIXChainBuilder::NewLC()
30 CPKIXChainBuilder* s = new (ELeave) CPKIXChainBuilder;
31 CleanupStack::PushL(s);
36 CPKIXChainBuilder::~CPKIXChainBuilder()
40 iCandidates.ResetAndDestroy();
44 void CPKIXChainBuilder::AddSourceL(MPKIXCertSource* aSource)
46 User::LeaveIfError(iSources.Append(aSource));
49 void CPKIXChainBuilder::AddIssuer(TInt& aNumberOfCertsAdded,
51 CArrayPtrFlat<CX509Certificate>& aChain,
52 TRequestStatus& aStatus)
54 iOriginalRequestStatus = &aStatus;
55 aStatus = KRequestPending;
58 iNumberOfCertsAdded = &aNumberOfCertsAdded;
60 iSubject = aChain[aChain.Count()-1];
61 __ASSERT_DEBUG(iSubject, User::Panic(_L("CPKICCertChainAO"), 1));
62 __ASSERT_DEBUG(!iCandidates.Count(), User::Panic(_L("CPKICCertChainAO"), 1));
65 iState = EAddCandidate;
66 TRequestStatus* status = &iStatus;
67 User::RequestComplete(status, KErrNone);
71 CPKIXChainBuilder::CPKIXChainBuilder()
72 : CActive(EPriorityNormal)
74 CActiveScheduler::Add(this);
77 void CPKIXChainBuilder::ConstructL()
81 TBool CPKIXChainBuilder::ResolveIssuersL(CArrayPtr<CX509Certificate>& aChain,
82 const RPointerArray<CX509Certificate>& aCandidates) const
84 //*this function attempts to figure out which certificate in aCandidates is the issuer of
85 //the last cert in the aChain, and adds a *copy* of the best guess to aChain
86 //*it assumes that the names match already
87 //*if it establishes that none are any good it returns EFalse
88 TInt count = aCandidates.Count();
95 CX509Certificate* cert = CX509Certificate::NewLC(*aCandidates[0]);
97 (*iNumberOfCertsAdded)++;
98 CleanupStack::Pop(cert);
102 const CX509Certificate* current = aChain[aChain.Count() - 1];
103 //1) look for SKI/AKI to distinguish
104 const CX509CertExtension* akiExt = current->Extension(KAuthorityKeyId);
107 const CX509AuthorityKeyIdExt* aki = CX509AuthorityKeyIdExt::NewLC(akiExt->Data());
108 TPtrC8 authorityKeyId = aki->KeyId();
109 if (authorityKeyId != KNullDesC8)
111 for (TInt i = 0; i < count; i++)
113 const CX509CertExtension* skiExt = (aCandidates[i])->Extension(KSubjectKeyId);
116 const CX509SubjectKeyIdExt* ski = CX509SubjectKeyIdExt::NewLC(skiExt->Data());
117 if (authorityKeyId == ski->KeyId())
119 CX509Certificate* issuer = CX509Certificate::NewLC(*aCandidates[i]);
120 aChain.AppendL(issuer);
121 (*iNumberOfCertsAdded)++;
122 CleanupStack::Pop();//issuer
123 CleanupStack::PopAndDestroy(2);//aki, ski
128 CleanupStack::PopAndDestroy();//ski
133 //ok, we haven't got a key ID for the issuer, so try for a serial number instead...
136 TPtrC8 authoritySerialNo = aki->AuthorityCertSerialNumber();
137 for (TInt i = 0; i < count; i++)
139 const CX509Certificate* candidate = aCandidates[i];
140 if (authoritySerialNo == candidate->SerialNumber())
142 CX509Certificate* issuer = CX509Certificate::NewLC(*candidate);
143 aChain.AppendL(issuer);
144 (*iNumberOfCertsAdded)++;
145 CleanupStack::Pop();//issuer
146 CleanupStack::PopAndDestroy();//aki
151 CleanupStack::PopAndDestroy();//aki
154 // If more then one subject matching candidates are found and they doesn't contain SKI/AKI,
155 // consider the most recently imported/added candidate as the issuer.
156 for(TInt index = count - 1; index >= 0; --index)
159 // if secure time is not available then fall back to the insecure version.
160 if(currentTime.UniversalTimeSecure() == KErrNoSecureTime)
162 currentTime.UniversalTime();
165 CX509Certificate* cert = CX509Certificate::NewLC(*aCandidates[index]);
166 // SKI/AKI are optional in versions lower than 3. So, relax the candidate selection rules only for version 1 & 2
167 // If the recent candidate is not valid enough(cert expired), consider it's previous valid candidate.
168 if((cert->Version() < 3) && (cert->ValidityPeriod().Valid(currentTime)))
170 aChain.AppendL(cert);
171 ++(*iNumberOfCertsAdded);
172 CleanupStack::Pop(cert);
177 CleanupStack::PopAndDestroy(cert);
186 void CPKIXChainBuilder::RunL()
188 User::LeaveIfError(iStatus.Int());
194 if (iIndex < iSources.Count())
196 iSources[iIndex]->CandidatesL(*iSubject, iCandidates, iStatus);
201 TRequestStatus* status = &iStatus;
202 User::RequestComplete(status, KErrNone);
209 *iResult = ResolveIssuersL(*iChain, iCandidates);
210 iCandidates.ResetAndDestroy();
211 User::RequestComplete(iOriginalRequestStatus, KErrNone);
215 User::Panic(_L("CPKIXChainBuilder"), 1);
220 void CPKIXChainBuilder::DoCancel()
223 int end = iSources.Count();
226 iSources[i]->CancelCandidates();
229 iCandidates.ResetAndDestroy();
231 User::RequestComplete(iOriginalRequestStatus, KErrCancel);
236 TInt CPKIXChainBuilder::RunError(TInt aError)
239 iCandidates.ResetAndDestroy();
240 User::RequestComplete(iOriginalRequestStatus, aError);