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