diff -r 000000000000 -r 164170e6151a pkiutilities/ocsp/src/directauthorisation.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pkiutilities/ocsp/src/directauthorisation.cpp Tue Jan 26 15:20:08 2010 +0200 @@ -0,0 +1,321 @@ +// Copyright (c) 2001-2009 Nokia Corporation and/or its subsidiary(-ies). +// All rights reserved. +// This component and the accompanying materials are made available +// under the terms of "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: +// Define methods for authorisation scheme based on locally configured +// authoritive root certs +// +// + +#include "ocsp.h" +#include "panic.h" +#include +#include +#include +#include +#include +#include +#include "ocsprequestandresponse.h" + +EXPORT_C COCSPDirectAuthorisationScheme* COCSPDirectAuthorisationScheme::NewLC(const TUid& aCertStoreUid, MCertStore& aCertStore) + { + COCSPDirectAuthorisationScheme* self = new(ELeave) COCSPDirectAuthorisationScheme(aCertStoreUid, aCertStore); + CleanupStack::PushL(self); + self->ConstructL(); + return self; + } + +COCSPDirectAuthorisationScheme::COCSPDirectAuthorisationScheme(const TUid& aCertStoreUid, MCertStore& aCertStore) : + CActive(CActive::EPriorityStandard), + iCertStoreUid(aCertStoreUid), + iCertStore(aCertStore) + { + CActiveScheduler::Add(this); + } + + +COCSPDirectAuthorisationScheme::~COCSPDirectAuthorisationScheme() + { + Cancel(); + delete iCertChain; + delete iPKIXResult; + delete iCertFilter; + delete iEncodedCertBuf; + delete iEncodedCertPtr; + iFs.Close(); + iCertStoreEntries.Close(); + delete iResponseCert; + } + + +void COCSPDirectAuthorisationScheme::ConstructL() + { + iPKIXResult = CPKIXValidationResultBase::NewL(); + + User::LeaveIfError(iFs.Connect()); + + iCertFilter = CCertAttributeFilter::NewL(); + iCertFilter->SetOwnerType(ECACertificate); + iCertFilter->SetUid(iCertStoreUid); + iCertFilter->SetFormat(EX509Certificate); + } + +/** + * Starts the process of validating the response. + * The initial value of the OCSP Status is set to signature validation failure. + */ +void COCSPDirectAuthorisationScheme::ValidateL(OCSP::TStatus& aOCSPStatus, + COCSPResponse& aResponse, const TTime aValidationTime, TRequestStatus& aStatus, + const COCSPRequest& aRequest) + { + iValidationTime = aValidationTime; + + iClientStatus = &aStatus; + *iClientStatus = KRequestPending; + + iResponse = &aResponse; + iRequest = &aRequest; + + iOCSPStatus = &aOCSPStatus; + *iOCSPStatus = OCSP::EResponseSignatureValidationFailure; + + // this object needs to be deleted if the same COCSPDirectAuthorisationScheme + // object is used for validating more than one certificate via COCSPValidator + delete iCertChain; + iCertChain = NULL; + + StartValidateL(); + } + + +void COCSPDirectAuthorisationScheme::ValidateFromRoots() +// +// Certs for the chain were not included in the response. +// See if any of the root certs for the given Uid can do the job. +// + { + iCertStore.List(iCertStoreEntries, *iCertFilter, iStatus); + iState = EListCertEntries; + } + +/** + * If response contains responder's certificate, chain validation would be done till the CA + * certificate which should be located in the store. + */ +void COCSPDirectAuthorisationScheme::ValidateCertChainL() + { + __ASSERT_DEBUG(iCertChain, Panic(KErrCorrupt)); + + iCertChain->ValidateL(*iPKIXResult, iValidationTime, iStatus); + iState = EValidateCertChain; + } + +TBool COCSPDirectAuthorisationScheme::ValidateSignatureL() + { + __ASSERT_DEBUG(iCertChain, Panic(KErrCorrupt)); + + // Validate against first cert in chain - must exist + const CX509Certificate& eeCert = iCertChain->Cert(0); + + return OCSPUtils::DoesResponderIdMatchCertL(*iResponse, eeCert) + && OCSPUtils::IsResponseSignedByCertL(iResponse, eeCert); + } + +void COCSPDirectAuthorisationScheme::OnValidateCertChainL() +// Called when cert chain validation completes + { + if (iPKIXResult->Error().iReason == EValidatedOK) + { + if (ValidateSignatureL()) + { + delete iResponseCert; + iResponseCert = NULL; + iResponseCert = CX509Certificate::NewL(iCertChain->Cert(0)); + *iOCSPStatus = OCSP::EValid; + } + } + User::RequestComplete(iClientStatus, KErrNone); + } + + +void COCSPDirectAuthorisationScheme::OnListCertEntries() +// Called when listing cert store entries completes + { + // trigger transitory state to start getting entries + iCurEntry = -1; + iState = ERetrieveNext; + TRequestStatus* status = &iStatus; + User::RequestComplete(status, KErrNone); + SetActive(); + } + + +void COCSPDirectAuthorisationScheme::OnRetrieveNextL() +// Transitory state to retrieve next entry triggered + { + delete iEncodedCertBuf; + iEncodedCertBuf = 0; + delete iEncodedCertPtr; + iEncodedCertPtr = 0; + if (++iCurEntry < iCertStoreEntries.Count()) + // still more entries, get next one + { + CCTCertInfo* certInfo = iCertStoreEntries[iCurEntry]; + ASSERT(certInfo); + + iEncodedCertBuf = HBufC8::NewL(certInfo->Size()); + iEncodedCertPtr = new(ELeave) TPtr8(iEncodedCertBuf->Des()); + + iCertStore.Retrieve(*certInfo, *iEncodedCertPtr, iStatus); + + iState = ERetrievingEntry; + + SetActive(); + } + else + // no more entries, bad news + { + User::RequestComplete(iClientStatus, KErrNone); + } + } + +void COCSPDirectAuthorisationScheme::OnRetrievingEntryL() +// Called when retrieving an entry completes. + { + CX509Certificate* cert = CX509Certificate::NewLC(*iEncodedCertPtr); + + if ( OCSPUtils::DoesResponderIdMatchCertL(*iResponse, *cert) + && OCSPUtils::IsResponseSignedByCertL(iResponse, *cert) + && cert->ValidityPeriod().Valid(iValidationTime)) + // found a good one, job finished + { + delete iResponseCert; + iResponseCert = NULL; + CleanupStack::Pop(cert); + iResponseCert = cert; + *iOCSPStatus = OCSP::EValid; + User::RequestComplete(iClientStatus, KErrNone); + } + else + // wasn't good, try next one + { + iState = ERetrieveNext; + TRequestStatus* status = &iStatus; + User::RequestComplete(status, KErrNone); + SetActive(); + CleanupStack::PopAndDestroy(cert); + } + + } + +void COCSPDirectAuthorisationScheme::RunL() +// +// Handles transitions from one state to the next +// + { + User::LeaveIfError(iStatus.Int()); + + switch (iState) + { + case EValidateCertChain: + OnValidateCertChainL(); + break; + case EListCertEntries: + OnListCertEntries(); + break; + case ERetrieveNext: + OnRetrieveNextL(); + break; + case ERetrievingEntry: + OnRetrievingEntryL(); + break; + + default: + ASSERT(FALSE); + } + } + +void COCSPDirectAuthorisationScheme::DoCancel() +// +// Cancel +// + { + switch (iState) + { + case EValidateCertChain: + ASSERT(iCertChain); + iCertChain->CancelValidate(); + break; + case EListCertEntries: + iCertStore.CancelList(); + break; + case ERetrieveNext: + // nothing to do, this is a transitory state + break; + case ERetrievingEntry: + iCertStore.CancelRetrieve(); + break; + default: + ASSERT(FALSE); + } + if (iClientStatus) + { + User::RequestComplete(iClientStatus, KErrCancel); + } + } + + +TInt COCSPDirectAuthorisationScheme::RunError(TInt aError) + { + if(aError == KErrArgument) + { + User::RequestComplete(iClientStatus, KErrNone); + } + else + { + User::RequestComplete(iClientStatus, aError); + } + return KErrNone; + } + +/** + * If the response contains the certificate which signed the response, create the certificate chain + * till the responder certificate. Otherwise validate directly from root certificates contained + * in the store initialized by the client. + */ +void COCSPDirectAuthorisationScheme::StartValidateL() + { + const TPtrC8* certChainData = iResponse->DataElementEncoding(COCSPResponse::ECertificateChain); + + // Cert chain data was included in response + if (certChainData) + { + iCertChain = CPKIXCertChainBase::NewL(iCertStore, *certChainData, iCertStoreUid); + ValidateCertChainL(); + } + else + { + // No cert chain in response - validate directly from root certs + ValidateFromRoots(); + } + SetActive(); + } + +void COCSPDirectAuthorisationScheme::CancelValidate() + { + CActive::Cancel(); + } + +const CX509Certificate* COCSPDirectAuthorisationScheme::ResponderCert() const + { + return iResponseCert; + }