1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/security/cryptoservices/certificateandkeymgmt/pkixcertbase/pkixcerts.cpp Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,416 @@
1.4 +/*
1.5 +* Copyright (c) 1997-2009 Nokia Corporation and/or its subsidiary(-ies).
1.6 +* All rights reserved.
1.7 +* This component and the accompanying materials are made available
1.8 +* under the terms of the License "Eclipse Public License v1.0"
1.9 +* which accompanies this distribution, and is available
1.10 +* at the URL "http://www.eclipse.org/legal/epl-v10.html".
1.11 +*
1.12 +* Initial Contributors:
1.13 +* Nokia Corporation - initial contribution.
1.14 +*
1.15 +* Contributors:
1.16 +*
1.17 +* Description:
1.18 +*
1.19 +*/
1.20 +
1.21 +
1.22 +#include "pkixcerts.h"
1.23 +#include <ccertattributefilter.h>
1.24 +#include <cctcertinfo.h>
1.25 +
1.26 +// CPKIXCertSource
1.27 +////////////////////
1.28 +
1.29 +MPKIXCertSource::~MPKIXCertSource()
1.30 + {
1.31 + }
1.32 +
1.33 +// This function returns ETrue iff the issuer altname in aSubjectCert matches the
1.34 +// subject altname in aIssuerCert
1.35 +TBool MPKIXCertSource::AltNameMatchL(const CX509Certificate& aSubjectCert,
1.36 + const CX509Certificate& aIssuerCert) const
1.37 + {
1.38 + TBool res = EFalse;
1.39 + const CX509CertExtension* subjectExt = aSubjectCert.Extension(KIssuerAltName);
1.40 + const CX509CertExtension* issuerExt = aIssuerCert.Extension(KSubjectAltName);
1.41 + if ((subjectExt) && (issuerExt))
1.42 + {
1.43 + const CX509AltNameExt* issuerAltName = CX509AltNameExt::NewLC(subjectExt->Data());
1.44 + const CX509AltNameExt* subjectAltName = CX509AltNameExt::NewLC(issuerExt->Data());
1.45 + if (subjectAltName->Match(*issuerAltName))
1.46 + {
1.47 + res = ETrue;
1.48 + }
1.49 + CleanupStack::PopAndDestroy(2);//subjectAltName, issuerAltName
1.50 + }
1.51 + return res;
1.52 + }
1.53 +
1.54 +// CPKIXCertsFromStore
1.55 +////////////////////////
1.56 +
1.57 +CPKIXCertsFromStore* CPKIXCertsFromStore::NewL(MCertStore& aCertStore)
1.58 + {
1.59 + CPKIXCertsFromStore* self = CPKIXCertsFromStore::NewLC(aCertStore);
1.60 + CleanupStack::Pop(self);
1.61 + return self;
1.62 + }
1.63 +
1.64 +CPKIXCertsFromStore* CPKIXCertsFromStore::NewLC(MCertStore& aCertStore)
1.65 + {
1.66 + CPKIXCertsFromStore* self = new(ELeave) CPKIXCertsFromStore(aCertStore);
1.67 + CleanupStack::PushL(self);
1.68 + self->ConstructL();
1.69 + return self;
1.70 + }
1.71 +
1.72 +CPKIXCertsFromStore* CPKIXCertsFromStore::NewL(MCertStore& aCertStore, TUid aClient)
1.73 + {
1.74 + CPKIXCertsFromStore* self = CPKIXCertsFromStore::NewLC(aCertStore, aClient);
1.75 + CleanupStack::Pop(self);
1.76 + return self;
1.77 + }
1.78 +
1.79 +CPKIXCertsFromStore* CPKIXCertsFromStore::NewLC(MCertStore& aCertStore, TUid aClient)
1.80 + {
1.81 + CPKIXCertsFromStore* self = new(ELeave) CPKIXCertsFromStore(aCertStore, aClient);
1.82 + CleanupStack::PushL(self);
1.83 + self->ConstructL(aClient);
1.84 + return self;
1.85 + }
1.86 +
1.87 +void CPKIXCertsFromStore::Initialize(TRequestStatus& aStatus)
1.88 + {
1.89 + // In the case of a WIM, we don't have trust settings,
1.90 + // the WIM store will ignore the filter and return all certificates
1.91 + aStatus = KRequestPending;
1.92 + iOriginalRequestStatus = &aStatus;
1.93 + iState = EInitialize;
1.94 + iCertStore.List(iCertInfos, *iFilter, iStatus);
1.95 + SetActive();
1.96 + }
1.97 +
1.98 +void CPKIXCertsFromStore::CandidatesL(const CX509Certificate& aSubject,
1.99 + RPointerArray<CX509Certificate>& aCandidates,
1.100 + TRequestStatus& aStatus)
1.101 + {
1.102 + aStatus = KRequestPending;
1.103 + iOriginalRequestStatus = &aStatus;
1.104 +
1.105 + iRootName = &aSubject.IssuerName();
1.106 + iSubject = &aSubject;
1.107 + iCandidates = &aCandidates;
1.108 + iEntriesIndex = -1;
1.109 +
1.110 + iState = ECheckTrusted;
1.111 + TRequestStatus* status = &iStatus;
1.112 + User::RequestComplete(status, KErrNone);
1.113 + SetActive();
1.114 + }
1.115 +
1.116 +void CPKIXCertsFromStore::CancelCandidates()
1.117 + {
1.118 + Cancel();
1.119 + }
1.120 +
1.121 +void CPKIXCertsFromStore::Release()
1.122 + {
1.123 + delete this;
1.124 + }
1.125 +
1.126 +CPKIXCertsFromStore::~CPKIXCertsFromStore()
1.127 + {
1.128 + Cancel();
1.129 +
1.130 + iCertInfos.Close();
1.131 +
1.132 + delete iFilter;
1.133 +
1.134 + delete iCertData;
1.135 + delete iCertPtr;
1.136 + }
1.137 +
1.138 +//private functions
1.139 +CPKIXCertsFromStore::CPKIXCertsFromStore(MCertStore& aCertStore)
1.140 + : CActive(EPriorityNormal), iCertStore(aCertStore)
1.141 + {
1.142 + CActiveScheduler::Add(this);
1.143 + }
1.144 +
1.145 +CPKIXCertsFromStore::CPKIXCertsFromStore(MCertStore& aCertStore, TUid aClient)
1.146 +: CActive(EPriorityNormal), iClient(aClient), iCertStore(aCertStore)
1.147 + {
1.148 + CActiveScheduler::Add(this);
1.149 + }
1.150 +
1.151 +void CPKIXCertsFromStore::ConstructL()
1.152 + {
1.153 + iFilter = CCertAttributeFilter::NewL();
1.154 + iFilter->SetFormat(EX509Certificate);
1.155 + iFilter->SetOwnerType(ECACertificate);
1.156 + }
1.157 +
1.158 +void CPKIXCertsFromStore::ConstructL(TUid aClient)
1.159 + {
1.160 + iFilter = CCertAttributeFilter::NewL();
1.161 + iFilter->SetUid(aClient);
1.162 + iFilter->SetFormat(EX509Certificate);
1.163 + iFilter->SetOwnerType(ECACertificate);
1.164 + }
1.165 +
1.166 +void CPKIXCertsFromStore::RunL()
1.167 + {
1.168 + User::LeaveIfError(iStatus.Int());
1.169 +
1.170 + switch (iState)
1.171 + {
1.172 + case EInitialize:
1.173 + iState = EIdle;
1.174 + User::RequestComplete(iOriginalRequestStatus, iStatus.Int());
1.175 + break;
1.176 +
1.177 + case ECheckTrusted:
1.178 + HandleECheckTrusted();
1.179 + break;
1.180 +
1.181 + case EGetCertificate:
1.182 + HandleEGetCertificateL();
1.183 + break;
1.184 +
1.185 + case EAddCandidate:
1.186 + HandleEAddCandidateL();
1.187 + break;
1.188 +
1.189 + case EEnd:
1.190 + iState = EIdle;
1.191 + User::RequestComplete(iOriginalRequestStatus, KErrNone);
1.192 + break;
1.193 +
1.194 + default:
1.195 + __ASSERT_ALWAYS(0, User::Panic(_L("CPKIXCertsFromStore"), 1));
1.196 + break;
1.197 + }
1.198 + }
1.199 +
1.200 +TInt CPKIXCertsFromStore::RunError(TInt aError)
1.201 + {
1.202 + User::RequestComplete(iOriginalRequestStatus, aError);
1.203 + return KErrNone;
1.204 + }
1.205 +
1.206 +void CPKIXCertsFromStore::DoCancel()
1.207 + {
1.208 + switch(iState)
1.209 + {
1.210 + case EInitialize:
1.211 + iCertStore.CancelList();
1.212 + break;
1.213 +
1.214 + case EGetCertificate:
1.215 + iCertStore.CancelTrusted();
1.216 + break;
1.217 +
1.218 + case EAddCandidate:
1.219 + iCertStore.CancelRetrieve();
1.220 + break;
1.221 +
1.222 + case ECheckTrusted:
1.223 + case EEnd:
1.224 + // nothing to do
1.225 + break;
1.226 +
1.227 + default:
1.228 + __ASSERT_ALWAYS(0, User::Panic(_L("CPKIXCertsFromStore"), 1));
1.229 + break;
1.230 + }
1.231 +
1.232 + User::RequestComplete(iOriginalRequestStatus, KErrCancel);
1.233 + iState = EIdle;
1.234 + }
1.235 +
1.236 +void CPKIXCertsFromStore::HandleECheckTrusted()
1.237 + {// iEntriesIndex has been initialized to -1 by Candidates
1.238 + iEntriesIndex++;
1.239 + if (iEntriesIndex < iCertInfos.Count())
1.240 + {
1.241 + const CCTCertInfo* entry = iCertInfos[iEntriesIndex];
1.242 +
1.243 + // Fix for DEF017139 "PKIXCert ignores trust"
1.244 + // Check the certificate is trusted and discard it if not
1.245 + iCertStore.Trusted(*entry, iIsTrusted, iStatus);
1.246 + iState = EGetCertificate;
1.247 + }
1.248 + else
1.249 + {
1.250 + iState = EEnd;
1.251 + TRequestStatus* status = &iStatus;
1.252 + User::RequestComplete(status, KErrNone);
1.253 + }
1.254 + SetActive();
1.255 + }
1.256 +
1.257 +void CPKIXCertsFromStore::HandleEGetCertificateL()
1.258 +{
1.259 + if (iIsTrusted)
1.260 + {// Fine to trust, go ahead
1.261 + const CCTCertInfo* entry = iCertInfos[iEntriesIndex];
1.262 + __ASSERT_DEBUG(!iCertData, User::Panic(_L("CPKIXCertsFromStore"), 1));
1.263 + iCertData = HBufC8::NewL(entry->Size());
1.264 + __ASSERT_DEBUG(!iCertPtr, User::Panic(_L("CPKIXCertsFromStore"), 1));
1.265 + iCertPtr = new(ELeave) TPtr8(iCertData->Des());
1.266 + iCertStore.Retrieve(*entry, *iCertPtr, iStatus);
1.267 + iState = EAddCandidate;
1.268 + }
1.269 + else
1.270 + {// Not trusted, check next for trust
1.271 + iState = ECheckTrusted;
1.272 + TRequestStatus* status = &iStatus;
1.273 + User::RequestComplete(status, KErrNone);
1.274 + }
1.275 +
1.276 + SetActive();
1.277 +}
1.278 +
1.279 +
1.280 +TBool CPKIXCertsFromStore::IsDuplicateL(const CX509Certificate& aCandidate)
1.281 + {
1.282 +
1.283 + TInt candidatesCount = iCandidates->Count();
1.284 + for (TInt i = 0; i < candidatesCount; i++)
1.285 + {
1.286 +
1.287 + // Certificate is a duplicate iff
1.288 + // a) The public keys have the same hash, and
1.289 + // b) The serial numbers are identical
1.290 +
1.291 + CX509Certificate* cert = (*iCandidates)[i];
1.292 + if (cert->KeyIdentifierL() == aCandidate.KeyIdentifierL()
1.293 + && cert->SerialNumber() == aCandidate.SerialNumber())
1.294 + {
1.295 + return ETrue;
1.296 + }
1.297 +
1.298 + }
1.299 +
1.300 + return EFalse;
1.301 +
1.302 + }
1.303 +
1.304 +void CPKIXCertsFromStore::HandleEAddCandidateL()
1.305 + {
1.306 + CX509Certificate *candidate = CX509Certificate::NewLC(*iCertData);
1.307 + delete iCertData;
1.308 + iCertData = 0;
1.309 + delete iCertPtr;
1.310 + iCertPtr = 0;
1.311 +
1.312 + if (iRootName->Count() > 0)
1.313 + {
1.314 + if (candidate->SubjectName().ExactMatchL(*iRootName) && !IsDuplicateL(*candidate))
1.315 + {
1.316 + User::LeaveIfError(iCandidates->Append(candidate));
1.317 + CleanupStack::Pop(); // candidate
1.318 + }
1.319 + else
1.320 + {
1.321 + CleanupStack::PopAndDestroy(); // candidate
1.322 + }
1.323 + }
1.324 + else
1.325 + {
1.326 + const CX500DistinguishedName& candidateName = candidate->SubjectName();
1.327 + if ((candidateName.Count() == 0) && (AltNameMatchL(*iSubject, *candidate)))
1.328 + {
1.329 + User::LeaveIfError(iCandidates->Append(candidate));
1.330 + CleanupStack::Pop(); // candidate
1.331 + }
1.332 + else
1.333 + {
1.334 + CleanupStack::PopAndDestroy(); // candidate
1.335 + }
1.336 + }
1.337 +
1.338 + iState = ECheckTrusted;
1.339 + TRequestStatus* status = &iStatus;
1.340 + User::RequestComplete(status, KErrNone);
1.341 + SetActive();
1.342 + }
1.343 +
1.344 +//CPKIXCertsFromClient
1.345 +//public functions
1.346 +CPKIXCertsFromClient* CPKIXCertsFromClient::NewL(const RPointerArray<CX509Certificate>& aCerts)
1.347 + {
1.348 + CPKIXCertsFromClient* self = new(ELeave) CPKIXCertsFromClient(aCerts);
1.349 + return self;
1.350 + }
1.351 +
1.352 +CPKIXCertsFromClient* CPKIXCertsFromClient::NewLC(const RPointerArray<CX509Certificate>& aCerts)
1.353 + {
1.354 + CPKIXCertsFromClient* self = new(ELeave) CPKIXCertsFromClient(aCerts);
1.355 + CleanupStack::PushL(self);
1.356 + return self;
1.357 + }
1.358 +
1.359 +void CPKIXCertsFromClient::Release()
1.360 + {
1.361 + delete this;
1.362 + }
1.363 +
1.364 +CPKIXCertsFromClient::~CPKIXCertsFromClient()
1.365 + {
1.366 + }
1.367 +
1.368 +void CPKIXCertsFromClient::CandidatesL(const CX509Certificate& aSubject,
1.369 + RPointerArray<CX509Certificate>& aCandidates,
1.370 + TRequestStatus& aStatus)
1.371 + {
1.372 + // There is no need for this to be asynchronous but it is because the base class
1.373 + // wants this to be
1.374 +
1.375 + const CX500DistinguishedName& rootName = aSubject.IssuerName();
1.376 + TInt count = iCerts.Count();
1.377 + const CX509Certificate* candidate = NULL;
1.378 + if (rootName.Count() > 0)
1.379 + {
1.380 + for (TInt i = 0; i < count; i++)
1.381 + {
1.382 + candidate = iCerts[i];
1.383 + if (candidate->SubjectName().ExactMatchL(rootName))
1.384 + {
1.385 + CX509Certificate* cert = CX509Certificate::NewLC(*candidate);
1.386 + User::LeaveIfError(aCandidates.Append(cert));
1.387 + CleanupStack::Pop();
1.388 + }
1.389 + }
1.390 + }
1.391 + else
1.392 + {
1.393 + for (TInt i = 0; i < count; i++)
1.394 + {
1.395 + candidate = iCerts[i];
1.396 + const CX500DistinguishedName& candidateName = candidate->SubjectName();
1.397 + if ((candidateName.Count() ==0) && (AltNameMatchL(aSubject, *candidate)))
1.398 + {
1.399 + CX509Certificate* cert = CX509Certificate::NewLC(*candidate);
1.400 + User::LeaveIfError(aCandidates.Append(cert));
1.401 + CleanupStack::Pop();
1.402 + }
1.403 + }
1.404 + }
1.405 +
1.406 + TRequestStatus* status = &aStatus;
1.407 + User::RequestComplete(status, KErrNone);
1.408 + }
1.409 +
1.410 +void CPKIXCertsFromClient::CancelCandidates()
1.411 + {
1.412 + // Nothing to do because the function completes immediately
1.413 + }
1.414 +
1.415 +//private functions
1.416 +CPKIXCertsFromClient::CPKIXCertsFromClient(const RPointerArray<CX509Certificate>& aCerts)
1.417 + :iCerts(aCerts)
1.418 + {
1.419 + }