pkiutilities/ocsp/src/cadirectauthorisation.cpp
changeset 0 164170e6151a
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/pkiutilities/ocsp/src/cadirectauthorisation.cpp	Tue Jan 26 15:20:08 2010 +0200
@@ -0,0 +1,134 @@
+// Copyright (c) 2005-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 the CA who issued the certificate
+// issues and signs the response.
+// 
+//
+
+#include "ocsp.h"
+#include "panic.h"
+#include <pkixcertchain.h>
+#include <asn1dec.h>
+#include <x509keys.h>
+#include <x509cert.h>
+#include "ocsprequestandresponse.h"
+
+
+EXPORT_C COCSPCaDirectAuthorisationScheme* COCSPCaDirectAuthorisationScheme::NewLC()
+	{
+	COCSPCaDirectAuthorisationScheme* self = new(ELeave) COCSPCaDirectAuthorisationScheme();
+	CleanupStack::PushL(self);
+	return self;
+	}
+
+/**
+	Validate the response if it is signed by the CA.  The response can
+	optionally contain a copy of the CA's certificate.
+*/
+void COCSPCaDirectAuthorisationScheme::ValidateL(OCSP::TStatus& aOCSPStatus,
+	COCSPResponse& aResponse, const TTime /* aValidationTime */, TRequestStatus& aStatus,
+	const COCSPRequest& aRequest)
+	{
+	TRequestStatus* validatorReqStatus = &aStatus;
+	aOCSPStatus = OCSP::EResponseSignatureValidationFailure;
+
+	// the OCSP requests are constructed in
+	// COCSPClient::ConstructL that exactly one certificate
+	// and its signer are sent in each request.
+	// (RFC 2560 S4.1.1 allows multiple pairs)
+	
+	// check the response is actually signed by the CA
+	// this effectively tests the same condition.
+	// By assuming there is only one request / response pair,
+	// there is no need to iterate through each response, which
+	// simplifies this scheme's implementation.
+
+	if (DoValidateL(aRequest, aResponse ))
+		{
+		aOCSPStatus = OCSP::EValid;
+		}
+	User::RequestComplete(validatorReqStatus, KErrNone);
+	};
+
+/**
+	Checks if the response is signed by the CA.
+	If the response has a certificate chain, it must contain
+	exactly the CA cert.  It is acceptable for the response
+	to have no certificate chain.
+
+	The responder ID in the certificate must match the CA cert,
+	and the whole response must be signed by the CA cert's signer.
+*/
+TBool COCSPCaDirectAuthorisationScheme::DoValidateL(
+	const COCSPRequest& aRequest, COCSPResponse& aResponse)
+{
+	// check the response contains either zero or one certificates.
+	// If the response contains a certificate, then it must be the
+	// same as the CA.
+
+	// get the intermediate which signed the EE
+	const CX509Certificate& caCert = aRequest.CertInfo(0).Issuer();
+	
+	// Retrieves the chain from the response of the responder certificate
+	// whic signed the response.
+	const TPtrC8* certChainData = aResponse.DataElementEncoding(COCSPResponse::ECertificateChain);
+	if (certChainData != 0)
+		{
+		if (! CertChainMatchesCertL(*certChainData, caCert))
+			return EFalse;
+		}
+
+	return
+			OCSPUtils::DoesResponderIdMatchCertL(aResponse, caCert)
+		&&	OCSPUtils::IsResponseSignedByCertL(&aResponse, caCert);
+}
+
+/**
+	Checks whether the encoded cert chain contains exactly
+	one cert which matches the supplied cert.
+
+	This is used to verify that, when a cert chain is sent with
+	the response, it contains exactly the CA cert.
+
+	@param	aCertChainData	DER-encoded certificate chain data
+							extracted from response.
+	@param	aCert			Certificate to look for.
+	@return					ETrue if the certificate chain contains
+							exactly one response which matches
+							aCert; EFalse otherwise.
+ */
+TBool COCSPCaDirectAuthorisationScheme::CertChainMatchesCertL(
+	const TDesC8& aCertChainData, const CX509Certificate& aCert)
+	{
+	// here we cannot assume that the response contains only the CA certificate,
+	// which signed the response as that can be a subordinate CA, so the chain
+	// can be like RCA(root CA) -> ICA(intermediate CA) -> SCA (sub-ordinate CA)
+	// we need to retrieve the SCA for this verification.
+	CX509Certificate* respCert = OCSPUtils::GetResponderCertLC(aCertChainData);
+	TBool match = aCert.IsEqualL(*respCert);
+	CleanupStack::PopAndDestroy(respCert);
+	return match;
+	}
+
+/**
+	This is a no-op because this implementation is not an
+	active object.
+ */
+void COCSPCaDirectAuthorisationScheme::CancelValidate()
+	{}
+
+const CX509Certificate* COCSPCaDirectAuthorisationScheme::ResponderCert() const	
+	{
+	return NULL;
+	}