pkiutilities/ocsp/src/directauthorisation.cpp
changeset 0 164170e6151a
equal deleted inserted replaced
-1:000000000000 0:164170e6151a
       
     1 // Copyright (c) 2001-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 // Define methods for authorisation scheme based on locally configured
       
    15 // authoritive root certs
       
    16 // 
       
    17 //
       
    18 
       
    19 #include "ocsp.h"
       
    20 #include "panic.h"
       
    21 #include <pkixcertchain.h>
       
    22 #include <asn1dec.h>
       
    23 #include <x509keys.h>
       
    24 #include <x509cert.h>
       
    25 #include <mcertstore.h>
       
    26 #include <ccertattributefilter.h>
       
    27 #include "ocsprequestandresponse.h"
       
    28 
       
    29 EXPORT_C COCSPDirectAuthorisationScheme* COCSPDirectAuthorisationScheme::NewLC(const TUid& aCertStoreUid, MCertStore& aCertStore)
       
    30 	{
       
    31 	COCSPDirectAuthorisationScheme* self = new(ELeave) COCSPDirectAuthorisationScheme(aCertStoreUid, aCertStore);
       
    32 	CleanupStack::PushL(self);
       
    33 	self->ConstructL();
       
    34 	return self;
       
    35 	}
       
    36 
       
    37 COCSPDirectAuthorisationScheme::COCSPDirectAuthorisationScheme(const TUid& aCertStoreUid, MCertStore& aCertStore) :
       
    38 	CActive(CActive::EPriorityStandard),
       
    39 	iCertStoreUid(aCertStoreUid),
       
    40 	iCertStore(aCertStore)
       
    41 	{
       
    42 	CActiveScheduler::Add(this);
       
    43 	}
       
    44 
       
    45 
       
    46 COCSPDirectAuthorisationScheme::~COCSPDirectAuthorisationScheme()
       
    47 	{
       
    48 	Cancel();
       
    49 	delete iCertChain;
       
    50 	delete iPKIXResult; 
       
    51 	delete iCertFilter;
       
    52 	delete iEncodedCertBuf;
       
    53 	delete iEncodedCertPtr;
       
    54 	iFs.Close();
       
    55 	iCertStoreEntries.Close();
       
    56 	delete iResponseCert;
       
    57 	}
       
    58 
       
    59 
       
    60 void COCSPDirectAuthorisationScheme::ConstructL()
       
    61 	{
       
    62 	iPKIXResult = CPKIXValidationResultBase::NewL();
       
    63 	
       
    64 	User::LeaveIfError(iFs.Connect());
       
    65 	
       
    66 	iCertFilter = CCertAttributeFilter::NewL();
       
    67 	iCertFilter->SetOwnerType(ECACertificate);
       
    68 	iCertFilter->SetUid(iCertStoreUid);
       
    69 	iCertFilter->SetFormat(EX509Certificate);
       
    70 	}
       
    71 
       
    72 /**
       
    73  * Starts the process of validating the response.
       
    74  * The initial value of the OCSP Status is set to signature validation failure.
       
    75  */
       
    76 void COCSPDirectAuthorisationScheme::ValidateL(OCSP::TStatus& aOCSPStatus,
       
    77 	COCSPResponse& aResponse, const TTime aValidationTime, TRequestStatus& aStatus,
       
    78 	const COCSPRequest& aRequest)
       
    79 	{
       
    80 	iValidationTime = aValidationTime;
       
    81 
       
    82 	iClientStatus = &aStatus;
       
    83 	*iClientStatus = KRequestPending;
       
    84 
       
    85 	iResponse = &aResponse;
       
    86 	iRequest = &aRequest;
       
    87 	
       
    88 	iOCSPStatus = &aOCSPStatus;
       
    89 	*iOCSPStatus = OCSP::EResponseSignatureValidationFailure;
       
    90 	
       
    91 	// this object needs to be deleted if the same COCSPDirectAuthorisationScheme
       
    92 	// object is used for validating more than one certificate via COCSPValidator
       
    93 	delete iCertChain;
       
    94 	iCertChain = NULL;
       
    95 		
       
    96 	StartValidateL();
       
    97 	}
       
    98 
       
    99 
       
   100 void COCSPDirectAuthorisationScheme::ValidateFromRoots()
       
   101 //
       
   102 // Certs for the chain were not included in the response.
       
   103 // See if any of the root certs for the given Uid can do the job.
       
   104 //
       
   105 	{
       
   106 	iCertStore.List(iCertStoreEntries, *iCertFilter, iStatus);
       
   107 	iState = EListCertEntries;
       
   108 	}
       
   109 
       
   110 /**
       
   111  * If response contains responder's certificate, chain validation would be done till the CA 
       
   112  * certificate which should be located in the store.
       
   113  */
       
   114 void COCSPDirectAuthorisationScheme::ValidateCertChainL()
       
   115 	{
       
   116 	__ASSERT_DEBUG(iCertChain, Panic(KErrCorrupt));
       
   117 
       
   118 	iCertChain->ValidateL(*iPKIXResult, iValidationTime, iStatus);
       
   119 	iState = EValidateCertChain;
       
   120 	}
       
   121 
       
   122 TBool COCSPDirectAuthorisationScheme::ValidateSignatureL()
       
   123 	{
       
   124 	__ASSERT_DEBUG(iCertChain, Panic(KErrCorrupt));
       
   125 
       
   126 	// Validate against first cert in chain - must exist
       
   127 	const CX509Certificate& eeCert = iCertChain->Cert(0);
       
   128 
       
   129 	return	OCSPUtils::DoesResponderIdMatchCertL(*iResponse, eeCert)
       
   130 		&&	OCSPUtils::IsResponseSignedByCertL(iResponse, eeCert);
       
   131 	}
       
   132 
       
   133 void COCSPDirectAuthorisationScheme::OnValidateCertChainL()
       
   134 // Called when cert chain validation completes
       
   135 	{
       
   136 	if (iPKIXResult->Error().iReason == EValidatedOK)
       
   137 		{
       
   138 		if (ValidateSignatureL())
       
   139 			{
       
   140 			delete iResponseCert;
       
   141 			iResponseCert = NULL;
       
   142 			iResponseCert = CX509Certificate::NewL(iCertChain->Cert(0));
       
   143 			*iOCSPStatus = OCSP::EValid;
       
   144 			}
       
   145 		}
       
   146 	User::RequestComplete(iClientStatus, KErrNone);
       
   147 	}
       
   148 		
       
   149 
       
   150 void COCSPDirectAuthorisationScheme::OnListCertEntries()
       
   151 // Called when listing cert store entries completes
       
   152 	{
       
   153 	// trigger transitory state to start getting entries
       
   154 	iCurEntry = -1;
       
   155 	iState = ERetrieveNext;
       
   156 	TRequestStatus* status = &iStatus;
       
   157 	User::RequestComplete(status, KErrNone);
       
   158 	SetActive();
       
   159 	}
       
   160 
       
   161 
       
   162 void COCSPDirectAuthorisationScheme::OnRetrieveNextL()
       
   163 // Transitory state to retrieve next entry triggered
       
   164 	{
       
   165 	delete iEncodedCertBuf;
       
   166 	iEncodedCertBuf = 0;
       
   167 	delete iEncodedCertPtr;
       
   168 	iEncodedCertPtr = 0;
       
   169 	if (++iCurEntry < iCertStoreEntries.Count())
       
   170 	// still more entries, get next one
       
   171 		{
       
   172 		CCTCertInfo* certInfo = iCertStoreEntries[iCurEntry];
       
   173 		ASSERT(certInfo);
       
   174 
       
   175 		iEncodedCertBuf = HBufC8::NewL(certInfo->Size());
       
   176 		iEncodedCertPtr = new(ELeave) TPtr8(iEncodedCertBuf->Des());
       
   177 
       
   178 		iCertStore.Retrieve(*certInfo, *iEncodedCertPtr, iStatus);
       
   179 		
       
   180 		iState = ERetrievingEntry;
       
   181 		
       
   182 		SetActive();
       
   183 		}
       
   184 	else
       
   185 	// no more entries, bad news
       
   186 		{
       
   187 		User::RequestComplete(iClientStatus, KErrNone);
       
   188 		}
       
   189 	}
       
   190 
       
   191 void COCSPDirectAuthorisationScheme::OnRetrievingEntryL()
       
   192 // Called when retrieving an entry completes.
       
   193 	{
       
   194 	CX509Certificate* cert = CX509Certificate::NewLC(*iEncodedCertPtr);
       
   195 	
       
   196 	if (	OCSPUtils::DoesResponderIdMatchCertL(*iResponse, *cert)
       
   197 		&&	OCSPUtils::IsResponseSignedByCertL(iResponse, *cert)
       
   198 		&&	cert->ValidityPeriod().Valid(iValidationTime))
       
   199 	// found a good one, job finished
       
   200 		{
       
   201 		delete iResponseCert;
       
   202 		iResponseCert = NULL;
       
   203 		CleanupStack::Pop(cert);
       
   204 		iResponseCert = cert;
       
   205 		*iOCSPStatus = OCSP::EValid;
       
   206 		User::RequestComplete(iClientStatus, KErrNone);
       
   207 		}
       
   208 	else
       
   209 	// wasn't good, try next one
       
   210 		{
       
   211 		iState = ERetrieveNext;
       
   212 		TRequestStatus* status = &iStatus;
       
   213 		User::RequestComplete(status, KErrNone);
       
   214 		SetActive();
       
   215 		CleanupStack::PopAndDestroy(cert);
       
   216 		}
       
   217 	
       
   218 	}
       
   219 
       
   220 void COCSPDirectAuthorisationScheme::RunL()
       
   221 //
       
   222 // Handles transitions from one state to the next
       
   223 //
       
   224 	{
       
   225 	User::LeaveIfError(iStatus.Int());
       
   226 
       
   227 	switch (iState)
       
   228 		{
       
   229 	case EValidateCertChain:
       
   230 		OnValidateCertChainL();
       
   231 		break;
       
   232 	case EListCertEntries:
       
   233 		OnListCertEntries();
       
   234 		break;
       
   235 	case ERetrieveNext:
       
   236 		OnRetrieveNextL();
       
   237 		break;
       
   238 	case ERetrievingEntry:
       
   239 		OnRetrievingEntryL();
       
   240 		break;
       
   241 	
       
   242 	default:
       
   243 		ASSERT(FALSE);
       
   244 		}
       
   245 	}
       
   246 
       
   247 void COCSPDirectAuthorisationScheme::DoCancel()
       
   248 //
       
   249 // Cancel
       
   250 //
       
   251 	{
       
   252 	switch (iState)
       
   253 		{
       
   254 	case EValidateCertChain:
       
   255 		ASSERT(iCertChain);
       
   256 		iCertChain->CancelValidate();
       
   257 		break;
       
   258 	case EListCertEntries:
       
   259 		iCertStore.CancelList();
       
   260 		break;
       
   261 	case ERetrieveNext:
       
   262 		// nothing to do, this is a transitory state
       
   263 		break;
       
   264 	case ERetrievingEntry:
       
   265 		iCertStore.CancelRetrieve();
       
   266 		break;
       
   267 	default:
       
   268 		ASSERT(FALSE);
       
   269 		}
       
   270 	if (iClientStatus)
       
   271 		{
       
   272 		User::RequestComplete(iClientStatus, KErrCancel);
       
   273 		}
       
   274 	}
       
   275 
       
   276 
       
   277 TInt COCSPDirectAuthorisationScheme::RunError(TInt aError)
       
   278 	{
       
   279 	if(aError == KErrArgument)
       
   280 		{
       
   281 		User::RequestComplete(iClientStatus, KErrNone);
       
   282 		}
       
   283 	else
       
   284 		{
       
   285 		User::RequestComplete(iClientStatus, aError);
       
   286 		}
       
   287 	return KErrNone;
       
   288 	}
       
   289 
       
   290 /**
       
   291  * If the response contains the certificate which signed the response, create the certificate chain
       
   292  * till the responder certificate. Otherwise validate directly from root certificates contained 
       
   293  * in the store initialized by the client.
       
   294  */
       
   295 void COCSPDirectAuthorisationScheme::StartValidateL()
       
   296 	{
       
   297 	const TPtrC8* certChainData = iResponse->DataElementEncoding(COCSPResponse::ECertificateChain);
       
   298 	
       
   299 	// Cert chain data was included in response
       
   300 	if (certChainData)
       
   301 		{
       
   302 		iCertChain = CPKIXCertChainBase::NewL(iCertStore, *certChainData, iCertStoreUid);
       
   303 		ValidateCertChainL();
       
   304 		}
       
   305 	else
       
   306 		{
       
   307 		// No cert chain in response - validate directly from root certs
       
   308 		ValidateFromRoots();
       
   309 		}
       
   310 	SetActive();
       
   311 	}
       
   312 
       
   313 void COCSPDirectAuthorisationScheme::CancelValidate()
       
   314 	{
       
   315 	CActive::Cancel();
       
   316 	}
       
   317 
       
   318 const CX509Certificate* COCSPDirectAuthorisationScheme::ResponderCert() const	
       
   319 	{
       
   320 	return iResponseCert;
       
   321 	}