How to use OSCP
===============
Note: The actual code snippets are indented.
Include ocsp.h in your header file.
#include <ocsp.h>
Link your project with ocsp.lib: add the following string to your project's .mmp
file:
LIBRARY ocsp.lib
Add the following to your class declaration, which should be derived from
CActive:
COcspClient* iOcspClient;
You will need to know revocation server URI. It is possible to get it from
installer preferences. Most Software Install components accept the URI as a
construction parameter. This is because they are started by the UI which stores
preferences in its resource file. If you want to retrieve it yourself, you can
use the following code (taken from InstallEngineImpl.cpp):
// Open instapp's ini file
static CDictionaryStore* OpenIniFileLC(RFs& aFs)
{
CApaAppFinder* appFinder=CApaScanningAppFinder::NewL(aFs);
CleanupStack::PushL(appFinder);
TUid instAppUid={KUidInstallAppValue};
TFileName libName=appFinder->FindAppL(KInstallAppName,instAppUid);
CleanupStack::PopAndDestroy(appFinder);
TParse parser;
User::LeaveIfError(parser.SetNoWild(KIniFileExtension,&KInstAppDriveC(),
&libName));
aFs.MkDirAll(parser.FullName()); // ignore the error
CDictionaryFileStore* dict = CDictionaryFileStore::OpenLC(aFs,
parser.FullName(),instAppUid);
return dict;
}
// get preferences from ini file
{
RFs fs;
User::LeaveIfError(fs.Connect());
CleanupClosePushL(fs);
CDictionaryStore* iniFile=OpenIniFileLC(fs); // see above
User::LeaveIfNull(iniFile);
RDictionaryReadStream readStream;
readStream.OpenLC(*iniFile,KUidInstallPrefs);
TInstallPrefs prefs; // this is what you need
TRAPD(ret,readStream >> prefs); // will return KErrEof first time
CleanupStack::PopAndDestroy(2); //readStream, iniFile
CleanupStack::Pop(); // fs
fs.Close();
}
If at any time you want to cancel OCSP check, call
iOcspClient->CancelCheck();
When ready to perform the check (the certificate chain is built), use the
following code as a template (from JavaInstallerSecurityManager.cpp):
COCSPParameters* params = COCSPParameters::NewLC();
params->SetURIL(*iOCSPServerURI, ETrue);
params->AddCertificatesL(*iCertChain);
// Set up authorisation scheme - we've a special UID registered with the
// certStore for the appropriate certificates
COCSPDirectAuthorisationScheme* scheme =
COCSPDirectAuthorisationScheme::NewLC(
TUid::Uid(KCertStoreUIDForSWInstallOCSPSigning));
params->AddAuthorisationSchemeL(scheme);
CleanupStack::Pop(scheme);
// Won't set validation time - this uses the response producedAt time
// instead. This avoids us relying on an accurate time in the device.
// Caching of old responses avoided by use of the nonce.
iOcspClient = COcspClient::NewL(params);
CleanupStack::Pop(params);
iOcspClient->Check(iStatus);
When the request completes and your class's RunL() is called, use the following
function template to process the result:
TBool accept = ETrue;
switch (iStatus.Int())
{
case OCSP::KErrNoCertificates:
// No certs in OCSP request - no proper cert chain formed.
// Covered by check digital sig logic already, so we let it pass.
break;
case KErrNone:
{
// Check the outcome of every transaction made
for (TInt index = 0;
accept && index < iOcspClient->TransactionCount();
++index)
{
const TOCSPOutcome& outcome = iOcspClient->Outcome(index);
// We have the OCSP response. Interpret it, asking the user
// what questions we need to. Return determines whether we
// continue the install
switch (outcome.iStatus)
{
case OCSP::ETransportError:
case OCSP::EClientInternalError:
case OCSP::EMalformedRequest:
case OCSP::EServerInternalError:
case OCSP::ETryLater:
case OCSP::ESignatureRequired:
case OCSP::EClientUnauthorised:
case OCSP::EUnknownResponseType:
// Error: unable to obtain certificate status
break;
case OCSP::ENoServerSpecified:
case OCSP::EInvalidURI:
// Error: invalid revocation server URI
break;
case OCSP::EResponseSignatureValidationFailure:
// Error: response signature validation failed
break;
case OCSP::EThisUpdateTooLate:
case OCSP::EThisUpdateTooEarly:
case OCSP::ENextUpdateTooEarly:
case OCSP::ENonceMismatch:
case OCSP::EMalformedResponse:
case OCSP::EUnknownCriticalExtension:
case OCSP::EMissingCertificates:
// Error: invalid server response
break;
case OCSP::EMissingNonce:
// Error: missing nonce
break;
case OCSP::ECertificateNotValidAtValidationTime:
// Error: invalid certificate status information
break;
case OCSP::EValid:
switch(outcome.iResult)
{
case OCSP::EGood:
accept = ETrue;
break;
case OCSP::EUnknown:
// ask user
break;
case OCSP::ERevoked:
// ask user
break;
default:
ASSERT(EFalse);
}
break;
default:
ASSERT(EFalse);
break;
}
}
break;
}
default:
// Error: cannot obtain certificate status, ask user
break;
}
delete iOcspClient;
iOcspClient = NULL;
OCSP check can take a long time. Therefore it is a good thing to display a
status dialog for the user telling her that OCSP check is in progress and
allowing her to cancel it. Both SIS and Java installers delegate this function
to their respective UI handlers.