First public contribution.
2 * Copyright (c) 1997-2009 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 "pkixcerts.h"
20 #include <ccertattributefilter.h>
21 #include <cctcertinfo.h>
26 MPKIXCertSource::~MPKIXCertSource()
30 // This function returns ETrue iff the issuer altname in aSubjectCert matches the
31 // subject altname in aIssuerCert
32 TBool MPKIXCertSource::AltNameMatchL(const CX509Certificate& aSubjectCert,
33 const CX509Certificate& aIssuerCert) const
36 const CX509CertExtension* subjectExt = aSubjectCert.Extension(KIssuerAltName);
37 const CX509CertExtension* issuerExt = aIssuerCert.Extension(KSubjectAltName);
38 if ((subjectExt) && (issuerExt))
40 const CX509AltNameExt* issuerAltName = CX509AltNameExt::NewLC(subjectExt->Data());
41 const CX509AltNameExt* subjectAltName = CX509AltNameExt::NewLC(issuerExt->Data());
42 if (subjectAltName->Match(*issuerAltName))
46 CleanupStack::PopAndDestroy(2);//subjectAltName, issuerAltName
51 // CPKIXCertsFromStore
52 ////////////////////////
54 CPKIXCertsFromStore* CPKIXCertsFromStore::NewL(MCertStore& aCertStore)
56 CPKIXCertsFromStore* self = CPKIXCertsFromStore::NewLC(aCertStore);
57 CleanupStack::Pop(self);
61 CPKIXCertsFromStore* CPKIXCertsFromStore::NewLC(MCertStore& aCertStore)
63 CPKIXCertsFromStore* self = new(ELeave) CPKIXCertsFromStore(aCertStore);
64 CleanupStack::PushL(self);
69 CPKIXCertsFromStore* CPKIXCertsFromStore::NewL(MCertStore& aCertStore, TUid aClient)
71 CPKIXCertsFromStore* self = CPKIXCertsFromStore::NewLC(aCertStore, aClient);
72 CleanupStack::Pop(self);
76 CPKIXCertsFromStore* CPKIXCertsFromStore::NewLC(MCertStore& aCertStore, TUid aClient)
78 CPKIXCertsFromStore* self = new(ELeave) CPKIXCertsFromStore(aCertStore, aClient);
79 CleanupStack::PushL(self);
80 self->ConstructL(aClient);
84 void CPKIXCertsFromStore::Initialize(TRequestStatus& aStatus)
86 // In the case of a WIM, we don't have trust settings,
87 // the WIM store will ignore the filter and return all certificates
88 aStatus = KRequestPending;
89 iOriginalRequestStatus = &aStatus;
91 iCertStore.List(iCertInfos, *iFilter, iStatus);
95 void CPKIXCertsFromStore::CandidatesL(const CX509Certificate& aSubject,
96 RPointerArray<CX509Certificate>& aCandidates,
97 TRequestStatus& aStatus)
99 aStatus = KRequestPending;
100 iOriginalRequestStatus = &aStatus;
102 iRootName = &aSubject.IssuerName();
103 iSubject = &aSubject;
104 iCandidates = &aCandidates;
107 iState = ECheckTrusted;
108 TRequestStatus* status = &iStatus;
109 User::RequestComplete(status, KErrNone);
113 void CPKIXCertsFromStore::CancelCandidates()
118 void CPKIXCertsFromStore::Release()
123 CPKIXCertsFromStore::~CPKIXCertsFromStore()
136 CPKIXCertsFromStore::CPKIXCertsFromStore(MCertStore& aCertStore)
137 : CActive(EPriorityNormal), iCertStore(aCertStore)
139 CActiveScheduler::Add(this);
142 CPKIXCertsFromStore::CPKIXCertsFromStore(MCertStore& aCertStore, TUid aClient)
143 : CActive(EPriorityNormal), iClient(aClient), iCertStore(aCertStore)
145 CActiveScheduler::Add(this);
148 void CPKIXCertsFromStore::ConstructL()
150 iFilter = CCertAttributeFilter::NewL();
151 iFilter->SetFormat(EX509Certificate);
152 iFilter->SetOwnerType(ECACertificate);
155 void CPKIXCertsFromStore::ConstructL(TUid aClient)
157 iFilter = CCertAttributeFilter::NewL();
158 iFilter->SetUid(aClient);
159 iFilter->SetFormat(EX509Certificate);
160 iFilter->SetOwnerType(ECACertificate);
163 void CPKIXCertsFromStore::RunL()
165 User::LeaveIfError(iStatus.Int());
171 User::RequestComplete(iOriginalRequestStatus, iStatus.Int());
175 HandleECheckTrusted();
178 case EGetCertificate:
179 HandleEGetCertificateL();
183 HandleEAddCandidateL();
188 User::RequestComplete(iOriginalRequestStatus, KErrNone);
192 __ASSERT_ALWAYS(0, User::Panic(_L("CPKIXCertsFromStore"), 1));
197 TInt CPKIXCertsFromStore::RunError(TInt aError)
199 User::RequestComplete(iOriginalRequestStatus, aError);
203 void CPKIXCertsFromStore::DoCancel()
208 iCertStore.CancelList();
211 case EGetCertificate:
212 iCertStore.CancelTrusted();
216 iCertStore.CancelRetrieve();
225 __ASSERT_ALWAYS(0, User::Panic(_L("CPKIXCertsFromStore"), 1));
229 User::RequestComplete(iOriginalRequestStatus, KErrCancel);
233 void CPKIXCertsFromStore::HandleECheckTrusted()
234 {// iEntriesIndex has been initialized to -1 by Candidates
236 if (iEntriesIndex < iCertInfos.Count())
238 const CCTCertInfo* entry = iCertInfos[iEntriesIndex];
240 // Fix for DEF017139 "PKIXCert ignores trust"
241 // Check the certificate is trusted and discard it if not
242 iCertStore.Trusted(*entry, iIsTrusted, iStatus);
243 iState = EGetCertificate;
248 TRequestStatus* status = &iStatus;
249 User::RequestComplete(status, KErrNone);
254 void CPKIXCertsFromStore::HandleEGetCertificateL()
257 {// Fine to trust, go ahead
258 const CCTCertInfo* entry = iCertInfos[iEntriesIndex];
259 __ASSERT_DEBUG(!iCertData, User::Panic(_L("CPKIXCertsFromStore"), 1));
260 iCertData = HBufC8::NewL(entry->Size());
261 __ASSERT_DEBUG(!iCertPtr, User::Panic(_L("CPKIXCertsFromStore"), 1));
262 iCertPtr = new(ELeave) TPtr8(iCertData->Des());
263 iCertStore.Retrieve(*entry, *iCertPtr, iStatus);
264 iState = EAddCandidate;
267 {// Not trusted, check next for trust
268 iState = ECheckTrusted;
269 TRequestStatus* status = &iStatus;
270 User::RequestComplete(status, KErrNone);
277 TBool CPKIXCertsFromStore::IsDuplicateL(const CX509Certificate& aCandidate)
280 TInt candidatesCount = iCandidates->Count();
281 for (TInt i = 0; i < candidatesCount; i++)
284 // Certificate is a duplicate iff
285 // a) The public keys have the same hash, and
286 // b) The serial numbers are identical
288 CX509Certificate* cert = (*iCandidates)[i];
289 if (cert->KeyIdentifierL() == aCandidate.KeyIdentifierL()
290 && cert->SerialNumber() == aCandidate.SerialNumber())
301 void CPKIXCertsFromStore::HandleEAddCandidateL()
303 CX509Certificate *candidate = CX509Certificate::NewLC(*iCertData);
309 if (iRootName->Count() > 0)
311 if (candidate->SubjectName().ExactMatchL(*iRootName) && !IsDuplicateL(*candidate))
313 User::LeaveIfError(iCandidates->Append(candidate));
314 CleanupStack::Pop(); // candidate
318 CleanupStack::PopAndDestroy(); // candidate
323 const CX500DistinguishedName& candidateName = candidate->SubjectName();
324 if ((candidateName.Count() == 0) && (AltNameMatchL(*iSubject, *candidate)))
326 User::LeaveIfError(iCandidates->Append(candidate));
327 CleanupStack::Pop(); // candidate
331 CleanupStack::PopAndDestroy(); // candidate
335 iState = ECheckTrusted;
336 TRequestStatus* status = &iStatus;
337 User::RequestComplete(status, KErrNone);
341 //CPKIXCertsFromClient
343 CPKIXCertsFromClient* CPKIXCertsFromClient::NewL(const RPointerArray<CX509Certificate>& aCerts)
345 CPKIXCertsFromClient* self = new(ELeave) CPKIXCertsFromClient(aCerts);
349 CPKIXCertsFromClient* CPKIXCertsFromClient::NewLC(const RPointerArray<CX509Certificate>& aCerts)
351 CPKIXCertsFromClient* self = new(ELeave) CPKIXCertsFromClient(aCerts);
352 CleanupStack::PushL(self);
356 void CPKIXCertsFromClient::Release()
361 CPKIXCertsFromClient::~CPKIXCertsFromClient()
365 void CPKIXCertsFromClient::CandidatesL(const CX509Certificate& aSubject,
366 RPointerArray<CX509Certificate>& aCandidates,
367 TRequestStatus& aStatus)
369 // There is no need for this to be asynchronous but it is because the base class
372 const CX500DistinguishedName& rootName = aSubject.IssuerName();
373 TInt count = iCerts.Count();
374 const CX509Certificate* candidate = NULL;
375 if (rootName.Count() > 0)
377 for (TInt i = 0; i < count; i++)
379 candidate = iCerts[i];
380 if (candidate->SubjectName().ExactMatchL(rootName))
382 CX509Certificate* cert = CX509Certificate::NewLC(*candidate);
383 User::LeaveIfError(aCandidates.Append(cert));
390 for (TInt i = 0; i < count; i++)
392 candidate = iCerts[i];
393 const CX500DistinguishedName& candidateName = candidate->SubjectName();
394 if ((candidateName.Count() ==0) && (AltNameMatchL(aSubject, *candidate)))
396 CX509Certificate* cert = CX509Certificate::NewLC(*candidate);
397 User::LeaveIfError(aCandidates.Append(cert));
403 TRequestStatus* status = &aStatus;
404 User::RequestComplete(status, KErrNone);
407 void CPKIXCertsFromClient::CancelCandidates()
409 // Nothing to do because the function completes immediately
413 CPKIXCertsFromClient::CPKIXCertsFromClient(const RPointerArray<CX509Certificate>& aCerts)