omadrm/drmengine/roapstorage/src/RoapStorageSession.cpp
changeset 0 95b198f216e5
child 18 8a03a285ab14
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/omadrm/drmengine/roapstorage/src/RoapStorageSession.cpp	Thu Dec 17 08:52:27 2009 +0200
@@ -0,0 +1,2506 @@
+/*
+* Copyright (c) 2004-2008 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:  Session class for handling roap storage client requests
+*
+*/
+
+
+// INCLUDE FILES
+#include <s32file.h>
+#include <f32file.h>
+#include <x509cert.h>
+#include <x509keys.h>
+#include <asn1dec.h>
+#include <hash.h>
+#include <s32mem.h>
+#include <centralrepository.h>
+#include <uri8.h>
+#ifdef RD_DRM_METERING
+#include <DRMRightsClient.h>
+#include <random.h>
+#endif //RD_DRM_METERING
+#ifdef RD_MULTIPLE_DRIVE
+#include <DriveInfo.h>
+#endif
+#include <e32base.h>  // CleanupResetAndDestroyPushL dependencies
+#include "drmaescrypto.h"
+#include "RoapStorageSession.h"
+#include "DRMContextDB.h"
+#include "DRMRIContext.h"
+#include "DRMDomainContext.h"
+#include "RoapStorageServer.h"
+#include "CmlaCrypto.h"
+#include "DrmAesCrypto.h"
+#include "DrmKeyStorage.h"
+#include "RoapDef.h"
+#include "RoapLog.h"
+#include "drmroapclientserver.h"
+#include "drmclockclient.h"
+#include "DrmTypes.h"
+#include "drmpointerarray.h"
+//OCSP classes
+#include "roapocsp.h"
+#include "responsedecoder.h"
+#include "certid.h"
+//drm clock
+#include "drmclockclient.h"
+
+#include "base64.h"
+
+#include "cleanupresetanddestroy.h" // CleanupResetAndDestroyPushL
+// NAMESPACES
+using namespace Roap;
+
+// EXTERNAL DATA STRUCTURES
+// EXTERNAL FUNCTION PROTOTYPES
+
+// CONSTANTS
+const TInt KMaxElementLength = 327680;
+const TInt KMinDomainIdLength = 4;
+// DEBUG PRINT MACROS
+#ifdef _DEBUG
+#include <flogger.h>
+_LIT(KMacLogDir, "DRM");
+_LIT(KMacLogFile, "MAC.log");
+#define MACLOG( a ) RFileLogger::Write( KMacLogDir(), KMacLogFile(), EFileLoggingModeAppend, a );
+#define MACLOGHEX( ptr, len ) RFileLogger::HexDump( KMacLogDir(), KMacLogFile(), EFileLoggingModeAppend, _S(""), _S(""), ptr, len );
+#define MACLOGLIT( a ) MACLOG( _L ( a ) )
+#define _DRM_DETAILED_DEBUG // uncomment if want detailed debugs to log file
+#else
+#undef _DRM_DETAILED_DEBUG
+#define MACLOG( a )
+#define MACLOGHEX( ptr, len )
+#define MACLOGLIT( a )
+#endif
+#ifdef _DRM_DETAILED_DEBUG
+#define MACLOGDETAIL( a ) MACLOG( a )
+#define MACLOGHEXDETAIL( ptr, len ) MACLOGHEX( ptr, len )
+#define MACLOGLITDETAIL( a ) MACLOGLIT( a )
+#define MACLOGLDETAIL( a ) MACLOGLIT( a )
+#define CERTDETAIL( c ) \
+{ \
+const TPtrC8* n( c->DataElementEncoding( CX509Certificate::ESerialNumber ) ); \
+const TPtrC8* a( c->DataElementEncoding( CX509Certificate::EAlgorithmId ) ); \
+const TPtrC8* s( c->DataElementEncoding( CX509Certificate::ESubjectName ) ); \
+const TPtrC8* i( c->DataElementEncoding( CX509Certificate::EIssuerName ) ); \
+const TPtrC8* p( c->DataElementEncoding( CX509Certificate::ESubjectPublicKeyInfo ) ); \
+MACLOGLDETAIL( "certificate (subject issuer serial algorithm key)" ) \
+MACLOGHEXDETAIL( s->Ptr(), s->Length() ) \
+MACLOGHEXDETAIL( i->Ptr(), i->Length() ) \
+MACLOGHEXDETAIL( n->Ptr(), n->Length() ) \
+MACLOGHEXDETAIL( a->Ptr(), a->Length() ) \
+MACLOGHEXDETAIL( p->Ptr(), p->Length() ) \
+}
+#else
+#define MACLOGDETAIL( a )
+#define MACLOGHEXDETAIL( ptr, len )
+#define MACLOGLITDETAIL( a )
+#define MACLOGLDETAIL( a )
+#define CERTDETAIL( a )
+#endif
+// END OF DEBUG PRINT MACROS
+// LOCAL CONSTANTS AND MACROS
+_LIT8( KRoapDomainKey, "roap:domainKey");
+_LIT8( KRoapX509SPKIHash, "roap:X509SPKIHash");
+_LIT8( KRoapXmlNs, " xmlns:roap=\"urn:oma:bac:dldrm:roap-1.0\"");
+#ifdef RD_DRM_METERING
+_LIT8( KCmlaIp1, "http://www.cm-la.com/tech/cmlaip/cmlaip#cmlaip-1");
+#endif
+
+static const TUid KCRUidRoapHandler =
+    {
+    0x10205CBF
+    };
+static const TInt KRoapHandlerRegistrationWhitelist = 1;
+static const TInt KMaxWhiteListLen = 1024;
+
+static const TInt KTzZulu( 0 ); //UTC time zone
+#ifdef RD_MULTIPLE_DRIVE
+_LIT( KRIContextFileName, "_:\\private\\101F51F2\\ricontexts.dat" );
+_LIT( KDomainContextFileName, "_:\\private\\101F51F2\\domaincontexts.dat" );
+#endif
+
+#define ROAPDB ( ( CRoapStorageServer* )( Server() ) )->ContextDB()
+
+static const TInt KP3( 3 );
+#define IPCREAD0L( a ) aMessage.ReadL( 0, a )
+#define IPCREAD1L( a ) aMessage.ReadL( 1, a )
+#define IPCREAD2L( a ) aMessage.ReadL( 2, a )
+#define IPCREAD3L( a ) aMessage.ReadL( KP3, a )
+#define IPCWRITE0L( a ) aMessage.WriteL( 0, a )
+#define IPCWRITE1L( a ) aMessage.WriteL( 1, a )
+#define IPCWRITE2L( a ) aMessage.WriteL( 2, a )
+#define IPCWRITE3L( a ) aMessage.WriteL( KP3, a )
+#define IPCGETDESLEN0 aMessage.GetDesLength( 0 )
+#define IPCGETDESLEN1 aMessage.GetDesLength( 1 )
+#define IPCGETDESLEN2 aMessage.GetDesLength( 2 )
+#define IPCGETDESLEN3 aMessage.GetDesLength( KP3 )
+#define IPCGETDESMAXLEN0 aMessage.GetDesMaxLength( 0 )
+#define IPCGETDESMAXLEN1 aMessage.GetDesMaxLength( 1 )
+#define IPCGETDESMAXLEN2 aMessage.GetDesMaxLength( 2 )
+#define IPCGETDESMAXLEN3 aMessage.GetDesMaxLength( KP3 )
+
+const TInt KSanityDataLengthLow = 0;
+const TInt KSanityDataLengthHigh = 32768;
+// DATA TYPES
+// LOCAL FUNCTION PROTOTYPES
+LOCAL_C RPointerArray<HBufC8> BufferToArrayL( TDesC8& aBuffer );
+LOCAL_C HBufC8* ArrayToBufferLC( const RPointerArray<HBufC8>& aArray );
+
+LOCAL_C void UnwrapDomainKeyL( MDrmKeyStorage* aKeyStorage,
+    const TDesC8& aProtectedDomainKey, HBufC8*& aDomainKey, HBufC8*& aMacKey,
+    TKeyTransportScheme& aTransportScheme );
+LOCAL_C TBool VerifyMacL( TDesC8& aDomainElements, TDesC8& aMacs,
+    RPointerArray<HBufC8>& aMacKeys );
+
+// ---------------------------------------------------------------------------
+// DeleteAndSetNull
+// ---------------------------------------------------------------------------
+//
+template<typename Taa> Taa*& DeleteAndSetNull( Taa*& aArg )
+    {
+    if ( aArg )
+        {
+        delete aArg;
+        aArg = NULL;
+        }
+    return aArg;
+    }
+
+// ---------------------------------------------------------------------------
+// SanitizeL
+// Performs a sanity check on length parameters
+// ---------------------------------------------------------------------------
+//
+LOCAL_C void SanitizeL( TInt aParam )
+    {
+    User::LeaveIfError( aParam );
+    if ( aParam <= KSanityDataLengthLow || aParam > KSanityDataLengthHigh )
+        {
+        User::Leave( KErrArgument );
+        }
+    }
+
+// ---------------------------------------------------------------------------
+// Swap elements
+// ---------------------------------------------------------------------------
+//
+template<typename T>
+LOCAL_C void SwapElement( RPointerArray<T>& aArray, TInt aFirst, TInt aSecond )
+    {
+    if ( aFirst != aSecond )
+        {
+        T* temp( NULL);
+        temp = aArray[aFirst];
+        aArray[aFirst] = aArray[aSecond];
+        aArray[aSecond] = temp;
+        }
+    }
+// ---------------------------------------------------------------------------
+// Sort Ocsp responses for certChain validation
+// ---------------------------------------------------------------------------
+//
+LOCAL_C TBool SortOcspCertsL( RPointerArray<CX509Certificate>& aOcspCerts,
+    const CX509Certificate* aRootCert )
+    {
+    MACLOGLITDETAIL( "::SortOcspCertsL -->" )
+    const TInt last( aOcspCerts.Count() - 1 );
+    TBool sortable( EFalse );
+
+    // Find first find cert issued by root cert
+    // There can be only one cert issued by Root on valid cert chain
+    for ( TInt i( 0 ); !sortable && i <= last; i++ )
+        {
+        if ( aRootCert->SubjectName().ExactMatchL(
+            aOcspCerts[i]->IssuerName() ) )
+            {
+            SwapElement<CX509Certificate> ( aOcspCerts, i, last );
+            sortable = ETrue;
+            }
+        }
+
+    for ( TInt s(last); sortable && s > 0; s-- )
+        {
+        sortable = EFalse;
+        for ( TInt i( s - 1 ); !sortable && i >= 0; i-- )
+            {
+            // compare cert s subject to issuer i
+            if ( aOcspCerts[s]->SubjectName().ExactMatchL(
+                aOcspCerts[i]->IssuerName() ) )
+                {
+                SwapElement<CX509Certificate> ( aOcspCerts, i, s-1 );
+                sortable = ETrue;
+                }
+            }
+        }
+    MACLOGLITDETAIL( "--> ::SortOcspCertsL" )
+    return sortable;
+    }
+
+// ---------------------------------------------------------------------------
+// VerifyOcspCertChainL()
+// ---------------------------------------------------------------------------
+//
+LOCAL_C TBool VerifyOcspCertChainL( const COCSPResponse& aResponse,
+    const CX509Certificate* aRootCert, CX509Certificate*& aOcspCert )
+    {
+    MACLOGLITDETAIL( "::VerifyOcspCertChainL -->" )
+
+
+
+    CX509Certificate* cert = NULL;
+    const CX509Certificate* signingCert = NULL;
+    TInt pos = 0;
+    TBool result = ETrue;
+
+    RPointerArray<CX509Certificate> certArray;
+    CleanupResetAndDestroyPushL( certArray );
+
+    const TPtrC8* ocspCerts( aResponse.SigningCerts() );
+
+    if ( !ocspCerts )
+        {
+        MACLOGLIT( "No OCSP certs present" )
+#ifdef _DISABLE_OCSP_CHECK
+        CleanupStack::PopAndDestroy( &certArray );
+        return ETrue;
+#endif
+        User::Leave( KErrRoapServerFatal );
+        }
+
+    MACLOGLITDETAIL( "getting certs in OCSP response" )
+    while ( pos < ocspCerts->Length() )
+        {
+        cert = CX509Certificate::NewLC( *ocspCerts, pos );
+        certArray.AppendL( cert );
+        CleanupStack::Pop( cert );
+        CERTDETAIL( cert )
+        }
+
+    result = SortOcspCertsL( certArray, aRootCert );
+
+    // validate the OCSP cert chain up till root cert (root cert is already validated)
+    for ( TInt i = 0; i < certArray.Count() && result; i++ )
+        {
+        cert = certArray[i];
+        if ( certArray.Count() - 1 == i )
+            {
+            signingCert = aRootCert;
+            }
+        else
+            {
+            signingCert = certArray[i + 1];
+            }
+        MACLOGLDETAIL( "OCSP verify, using certificate" )
+        CERTDETAIL( cert )
+        result = cert->VerifySignatureL( signingCert->PublicKey().KeyData() );
+#ifdef _DEBUG
+        if ( result )
+            {
+            MACLOGLIT( "Verify succeeded." )
+            }
+        else
+            {
+            MACLOGLIT( "Verify failed." )
+            }
+#endif
+        }
+
+    // Copy OCSP cert and return it
+    aOcspCert = CX509Certificate::NewL( *certArray[0] );
+
+    CleanupStack::PopAndDestroy( &certArray );
+    MACLOGLITDETAIL( "--> ::VerifyOcspCertChainL" )
+    return result;
+    }
+
+
+#ifdef _DISABLE_DRM_TIME_UPDATE_CHECK
+LOCAL_C TBool IsCmlaRootL(
+    const RPointerArray<HBufC8>& /*aTrustedRoots*/,
+    const CX509Certificate* /* aRootCert */)
+    {
+    MACLOGLITDETAIL( "IsCmlaRootL -->\n--> IsCmlaRootL" )
+    return ETrue;
+    }
+#else
+LOCAL_C TBool IsCmlaRootL( const RPointerArray<HBufC8>& aTrustedRoots,
+    const CX509Certificate* aRootCert )
+    {
+    MACLOGLITDETAIL( "IsCmlaRootL -->" )
+    TBool isCmlaRoot( EFalse );
+    // Check are we running on a CMLA device
+    for ( TInt i = 0; i < aTrustedRoots.Count() && !isCmlaRoot; i++ )
+        {
+        HBufC8* encodedRoot( Base64EncodeL( *aTrustedRoots[i] ) );
+        CleanupStack::PushL( encodedRoot );
+        if ( encodedRoot->CompareF( KRoapCmlaRootHash() ) == 0
+            || encodedRoot->CompareF( KRoapCmlaRnDRootHash() ) == 0
+            || encodedRoot->CompareF( KRoapCmlaRnDRootHashOld() ) == 0 )
+            {
+            isCmlaRoot = ETrue;
+            }
+        CleanupStack::PopAndDestroy( encodedRoot );
+        encodedRoot = NULL;
+        }
+    if ( isCmlaRoot )
+        {
+        __UHEAP_MARK;
+        // The root cert found, check that it's the CMLA (production or R&D) root
+        CSHA1* hash( CSHA1::NewL() );
+        CleanupStack::PushL( hash );
+        hash->Hash( *aRootCert->DataElementEncoding(
+            CX509Certificate::ESubjectPublicKeyInfo ) );
+        MACLOGLDETAIL( "Inputs for SHA1" )
+        MACLOGHEXDETAIL(
+            aRootCert->DataElementEncoding(
+                CX509Certificate::ESubjectPublicKeyInfo )->Ptr(),
+            aRootCert->DataElementEncoding(
+                CX509Certificate::ESubjectPublicKeyInfo )->Length() )
+
+        HBufC8* encodedRoot( Base64EncodeL( hash->Final() ) );
+        CleanupStack::PushL( encodedRoot );
+
+        MACLOGLDETAIL( "Encoded root (base64 encoded SHA1 of public key)" )
+        MACLOGDETAIL( *encodedRoot )
+        MACLOGLDETAIL( "CMLA root" )
+        MACLOGDETAIL( KRoapCmlaRootHash() )
+        MACLOGLDETAIL( "CMLA RD root" )
+        MACLOGDETAIL( KRoapCmlaRnDRootHash() )
+        MACLOGLDETAIL( "old CMLA RD root" )
+        MACLOGDETAIL( KRoapCmlaRnDRootHashOld() )
+
+        if ( encodedRoot->CompareF( KRoapCmlaRootHash() ) != 0
+            && encodedRoot->CompareF( KRoapCmlaRnDRootHash() ) != 0
+            && encodedRoot->CompareF( KRoapCmlaRnDRootHashOld() ) != 0 )
+            {
+            // The RI CA cert is not signed by CMLA root
+            MACLOGLIT( "The RI CA cert is not signed by CMLA (production or R&D) root" )
+            isCmlaRoot = EFalse;
+            }
+        else
+            {
+            // We are running on a CMLA device and
+            // RI certificate is signed by the CMLA (production or R&D) root
+            // -> Verify still that the OCSP chain is signed by CMLA
+            MACLOGLIT( "RI certificate is signed by the CMLA root" )
+            }
+        CleanupStack::PopAndDestroy( encodedRoot );
+        CleanupStack::PopAndDestroy( hash );
+        __UHEAP_MARKEND;
+        }
+    MACLOGLITDETAIL( "--> IsCmlaRootL" )
+    return isCmlaRoot;
+    }
+#endif
+
+
+// ---------------------------------------------------------------------------
+// ValidateNonceL
+// ---------------------------------------------------------------------------
+//
+LOCAL_C TBool ValidateNonceL( const COCSPResponse& aResponse,
+    const TDesC8& aRegReqNonce )
+    {
+    // check that nonce in OCSP response equals to the nonce sent in Reg Request
+    TBool ret( EFalse );
+    const TPtrC8 * nonce( aResponse.DataElementEncoding(
+        COCSPResponse::ENonce ) );
+
+    if ( !nonce )
+        {
+        // no nonce found -> don't update DRM Time
+        MACLOGLIT( "No nonce in the OCSP response!" )
+        ret = EFalse;
+        }
+    else if ( nonce->CompareF( aRegReqNonce ) != 0 )
+        {
+        // Maybe the nonce is in ASN.1 format?
+        // -> Remove the first two bytes (type and size), and try again
+        TASN1DecGeneric asn1Dec( *nonce );
+        asn1Dec.InitL();
+        TPtrC8 ptr( asn1Dec.GetContentDER() );
+        if ( ptr.CompareF( aRegReqNonce ) != 0 )
+            {
+            MACLOGLIT( "Fatal server error: OCSP nonce != RegRequest nonce!" )
+            User::Leave( KErrRoapServerFatal );
+            }
+        else
+            {
+            MACLOGLIT( "OCSP nonce == RegRequest nonce." )
+            ret = ETrue;
+            }
+        MACLOGLDETAIL( "values ( OCSP nonce, request nonce  )" )
+        MACLOGHEXDETAIL( nonce->Ptr(), nonce->Length() )
+        MACLOGHEXDETAIL( aRegReqNonce.Ptr(), aRegReqNonce.Length() )
+        }
+    else
+        {
+        ret = ETrue;
+        MACLOGLDETAIL( "values ( OCSP nonce, request nonce  )" )
+        MACLOGHEXDETAIL( nonce->Ptr(), nonce->Length() )
+        MACLOGHEXDETAIL( aRegReqNonce.Ptr(), aRegReqNonce.Length() )
+        }
+    return ret;
+    }
+// ---------------------------------------------------------------------------
+// IsTimeUpdateAllowedL()
+// ---------------------------------------------------------------------------
+//
+LOCAL_C TBool IsTimeUpdateAllowedL(
+    const RPointerArray<HBufC8>& aTrustedRoots,
+    const RPointerArray<HBufC8>& aRootCertificates,
+    const RPointerArray<HBufC8>& aCertChain,
+    const COCSPResponse& aOcspResponse,
+    const TDesC8& aRegReqNonce )
+    {
+    MACLOGLITDETAIL( "::IsTimeUpdateAllowedL -->" )
+
+
+    // check that nonce in OCSP response equals to the nonce sent in Reg Request
+    TBool bIsAllowed( ValidateNonceL( aOcspResponse, aRegReqNonce ) );
+
+    if ( !bIsAllowed )
+        {
+        MACLOGLIT( "No nonce. Not possible to update DRM time" )
+        return bIsAllowed;
+        }
+
+
+    if ( !aCertChain.Count() )
+        {
+        MACLOGLIT( "Wrong input data - No certificates or OCSP responses" )
+        bIsAllowed = EFalse;
+        return bIsAllowed;
+        }
+
+    CX509Certificate* riCa = NULL;
+    CX509Certificate* rootCert = NULL;
+    // Get the last cert from the chain.
+    // It should be signed by some of our trusted anchor
+    riCa = CX509Certificate::NewLC( *( aCertChain[aCertChain.Count() - 1] ) );
+    MACLOGLITDETAIL( "Selected as RI CA" ) // (last of given cert chain)
+    CERTDETAIL( riCa )
+
+    // iterate over root certificates and check, whether given
+    // RI CA issuer matches name of the selected root
+    for ( TInt i = 0; i < aRootCertificates.Count() && !rootCert; i++ )
+        {
+        rootCert = CX509Certificate::NewL( *aRootCertificates[i] );
+        if ( !rootCert->SubjectName().ExactMatchL( riCa->IssuerName() ) )
+            {
+            delete rootCert;
+            rootCert = NULL;
+            }
+        }
+
+    if ( rootCert )
+        {
+        MACLOGLDETAIL( "Selected root CERT" )
+        CERTDETAIL( rootCert )
+        CleanupStack::PushL( rootCert );
+
+        if ( IsCmlaRootL( aTrustedRoots, rootCert ) )
+            {
+            CX509Certificate* ocspCert = NULL;
+            __UHEAP_MARK;
+            // Try to verify OCSP cert chain with the root cert
+            if ( VerifyOcspCertChainL( aOcspResponse, rootCert,
+                DeleteAndSetNull<CX509Certificate> ( ocspCert ) ) )
+                {
+                MACLOGLITDETAIL( "OCSP cert chain verified with root cert" )
+                MACLOGLIT( "DRM Time update allowed!" )
+                bIsAllowed = ETrue;
+                }
+            // Try to verify OCSP cert chain with the RI CA cert
+
+            else if ( VerifyOcspCertChainL( aOcspResponse, riCa,
+                DeleteAndSetNull<CX509Certificate> ( ocspCert ) ) )
+                {
+                MACLOGLITDETAIL( "OCSP cert chain verified with RI CA cert" )
+                // Check signing of RiCa
+                bIsAllowed = riCa->VerifySignatureL(
+                    rootCert->PublicKey().KeyData() );
+                if ( !bIsAllowed )
+                    {
+                    MACLOGLITDETAIL( "RI CA cert verify failed" )
+                    MACLOGLIT( "DRM time update not allowed!" )
+                    }
+                else
+                    {
+                    MACLOGLITDETAIL( "RI CA verified with root cert" )
+                    MACLOGLIT( "DRM time update allowed" )
+                    }
+                }
+            else
+                {
+                MACLOGLITDETAIL( "OCSP cert chain verify failed" )
+                MACLOGLIT( "DRM Time update is not allowed!" )
+                bIsAllowed = EFalse;
+                }
+
+            if ( ocspCert )
+                {
+                if ( !aOcspResponse.VerifySignatureL(
+                    ocspCert->PublicKey().KeyData() ) )
+                    {
+                    MACLOGLIT( "OCSP response signature verification failed" )
+                    bIsAllowed = EFalse;
+                    }
+                if ( bIsAllowed )
+                    {
+                    const TTime timeCandidate( aOcspResponse.ProducedAt() );
+                    if ( !ocspCert->ValidityPeriod().Valid( timeCandidate ) )
+                        {
+                        MACLOGLIT( "OCSP responder cert expired in respect to proposed new time" )
+                        bIsAllowed = EFalse;
+                        }
+                    }
+                }
+            DeleteAndSetNull<CX509Certificate> ( ocspCert );
+            __UHEAP_MARKEND;
+            }
+        CleanupStack::PopAndDestroy( rootCert );
+        rootCert = NULL;
+        }
+    CleanupStack::PopAndDestroy( riCa );
+    riCa = NULL;
+    MACLOGLITDETAIL( "--> ::IsTimeUpdateAllowedL" )
+    return bIsAllowed;
+    }
+
+//LOCAL CLASS DECLARATION
+// Used for lazy connecting to clock server (only connected if needed)
+class LazyClockClient
+    {
+public:
+    inline LazyClockClient();
+    inline virtual ~LazyClockClient();
+    inline void GetSecureTimeL( TTime& aTime, TInt& aZone,
+        DRMClock::ESecurityLevel& aLevel );
+    inline void UpdateSecureTimeL( const TTime& aTime, const TInt aZone );
+    inline void Close();
+private:
+    inline void ConnectL();
+    TBool iConnected;
+    RDRMClockClient iClock;
+    };
+
+// ============================ MEMBER FUNCTIONS ===============================
+
+// ---------------------------------------------------------------------------
+inline LazyClockClient::LazyClockClient() :
+    iConnected( EFalse )
+    {
+    }
+
+// ---------------------------------------------------------------------------
+inline LazyClockClient::~LazyClockClient()
+    {
+    Close();
+    }
+
+// ---------------------------------------------------------------------------
+inline void LazyClockClient::Close()
+    {
+    iClock.Close();
+    iConnected = EFalse;
+    }
+
+// ---------------------------------------------------------------------------
+inline void LazyClockClient::ConnectL()
+    {
+    if ( !iConnected )
+        {
+        User::LeaveIfError( iClock.Connect() );
+        iConnected = ETrue;
+        }
+    }
+
+// ---------------------------------------------------------------------------
+inline void LazyClockClient::GetSecureTimeL( TTime& aTime, TInt& aZone,
+    DRMClock::ESecurityLevel& aLevel )
+    {
+    ConnectL();
+    User::LeaveIfError( iClock.GetSecureTime( aTime, aZone, aLevel ) );
+    }
+
+// ---------------------------------------------------------------------------
+inline void LazyClockClient::UpdateSecureTimeL( const TTime& aTime,
+    const TInt aZone )
+    {
+    ConnectL();
+    User::LeaveIfError( iClock.UpdateSecureTime( aTime, aZone ) );
+    }
+
+
+// CRoapStorageSession methods
+
+// ---------------------------------------------------------------------------
+// CRoapStorageSession::NewLC
+// Two-phased constructor.
+// ---------------------------------------------------------------------------
+//
+CRoapStorageSession* CRoapStorageSession::NewL()
+    {
+    CRoapStorageSession* self = new ( ELeave ) CRoapStorageSession();
+    CleanupStack::PushL( self );
+    self->ConstructL();
+    CleanupStack::Pop( self );
+    return self;
+    }
+
+// ---------------------------------------------------------------------------
+// CRoapStorageSession::~CRoapStorageSession
+// Destructor.
+// ---------------------------------------------------------------------------
+//
+CRoapStorageSession::~CRoapStorageSession()
+    {
+    delete iPreparedData;
+    delete iKeyStorage;
+    delete iLazyClock;
+    }
+
+// ---------------------------------------------------------------------------
+// CRoapStorageSession::ServiceL
+// ---------------------------------------------------------------------------
+//
+void CRoapStorageSession::ServiceL( const RMessage2& aMessage )
+    {
+    DispatchL( aMessage );
+    }
+
+// ---------------------------------------------------------------------------
+// CRoapStorageSession::DispatchL
+// ---------------------------------------------------------------------------
+//
+void CRoapStorageSession::DispatchL( const RMessage2& aMessage )
+    {
+    switch ( aMessage.Function() )
+        {
+        case EAddRiContext:
+            {
+            AddRiContextL( aMessage );
+            break;
+            }
+        case EAddDomainContext:
+            {
+            AddDomainContextL( aMessage );
+            break;
+            }
+        case EGetRiContext:
+            {
+            GetRiContextL( aMessage );
+            break;
+            }
+        case EGetDomainContext:
+            {
+            GetDomainContextL( aMessage );
+            break;
+            }
+        case EGetData:
+            {
+            GetDataL( aMessage );
+            break;
+            }
+        case EDeleteRiContext:
+            {
+            DeleteRiContextL( aMessage );
+            break;
+            }
+        case EDeleteDomainContext:
+            {
+            DeleteDomainContextL( aMessage );
+            break;
+            }
+        case EDeleteExpiredRIs:
+            {
+            DeleteExpiredRIsL( aMessage );
+            break;
+            }
+        case EDeleteExpiredDomains:
+            {
+            DeleteExpiredDomainsL( aMessage );
+            break;
+            }
+        case EWhiteListCheck:
+            {
+            WhiteListUrlExistsL( aMessage );
+            break;
+            }
+        case EGetPublicKey:
+            {
+            GetDevicePublicKeyDerL( aMessage );
+            break;
+            }
+        case EGetCertificates:
+            {
+            GetDeviceCertificateChainL( aMessage );
+            break;
+            }
+        case ESignMessage:
+            {
+            SignL( aMessage );
+            break;
+            }
+        case ESelectRoot:
+            {
+            SelectTrustedRootL( aMessage );
+            break;
+            }
+        case EActivateRoot:
+            {
+            ActivateTrustedRootL( aMessage );
+            break;
+            }
+        case EGetTrustedRoots:
+            {
+            GetTrustedRootsL( aMessage );
+            break;
+            }
+        case EGetRootCert:
+            {
+            GetRootCertificateL( aMessage );
+            break;
+            }
+        case EDeleteExpired:
+            {
+            DeleteExpiredContextsL( aMessage );
+            break;
+            }
+        case EDeleteAll:
+            {
+            DeleteAllL( aMessage );
+            break;
+            }
+        case ERsaSign:
+            {
+            RsaSignL( aMessage );
+            break;
+            }
+#ifdef RD_DRM_METERING
+        case EGetMeteringData:
+            {
+            GetMeteringDataL( aMessage );
+            break;
+            }
+        case EDeleteMeteringData:
+            {
+            DeleteMeteringDataL( aMessage );
+            break;
+            }
+        case ERetrieveAllRIContexts:
+            {
+            GetAllRIContextsL( aMessage );
+            break;
+            }
+        case EUpdateRIContext:
+            {
+            UpdateRIContextL( aMessage );
+            break;
+            }
+#endif // RD_DRM_METERING
+        case EUpdateDrmTime:
+            {
+            UpdateDrmTimeL( aMessage );
+            break;
+            }
+        case EVerifyOcspResponses:
+            {
+            VerifyOcspResponsesL( aMessage );
+            break;
+            }
+        case EGetOcspResponderId:
+            {
+            GetOcspResponderIdL( aMessage );
+            break;
+            }
+        default:
+            MACLOGLIT( "CRoapStorageSession::ServiceL: Invalid command" )
+            PanicClient( aMessage, EPanicBadFunction );
+        }
+    }
+
+// ---------------------------------------------------------------------------
+// CRoapStorageSession::PanicClient
+// ---------------------------------------------------------------------------
+//
+void CRoapStorageSession::PanicClient(
+    const RMessage2& aMessage,
+    TPanic aReason )
+    {
+    _LIT( KPanicCategory, "RoapStorageSession" );
+    if ( !aMessage.IsNull() )
+        {
+        aMessage.Panic( KPanicCategory, aReason );
+        }
+    }
+
+// ---------------------------------------------------------------------------
+// CRoapStorageSession::ServiceError
+// ---------------------------------------------------------------------------
+//
+void CRoapStorageSession::ServiceError(
+    const RMessage2& aMessage,
+    TInt aError )
+    {
+    MACLOGLITDETAIL( "CRoapStorageSession::ServiceError -->" )
+
+    if ( aError == KErrBadDescriptor )
+        {
+        PanicClient( aMessage, EPanicBadDescriptor );
+        }
+    else
+        {
+        CSession2::ServiceError( aMessage, aError );
+        }
+    MACLOGLITDETAIL( "--> CRoapStorageSession::ServiceError" )
+    }
+
+// ---------------------------------------------------------------------------
+// CRoapStorageSession::CRoapStorageSession
+// Default constructor.
+// ---------------------------------------------------------------------------
+//
+CRoapStorageSession::CRoapStorageSession()
+    {
+    }
+
+// ---------------------------------------------------------------------------
+// CRoapStorageSession::ConstructL
+// Second phase constructor. Initializes the log tool in DRM internal testing.
+// ---------------------------------------------------------------------------
+//
+void CRoapStorageSession::ConstructL()
+    {
+    iKeyStorage = DrmKeyStorageNewL();
+    iKeyStorage->SelectDefaultRootL();
+    iDeleteExpired = ETrue;
+    iLazyClock = new ( ELeave ) LazyClockClient();
+    }
+
+// ---------------------------------------------------------------------------
+// CRoapStorageSession::AddRiContextL
+// ---------------------------------------------------------------------------
+//
+void CRoapStorageSession::AddRiContextL( const RMessage2& aMessage )
+    {
+    MACLOGLITDETAIL( "CRoapStorageSession::AddRiContextL -->" )
+    CDRMRIContext* context = NULL;
+    HBufC8* contextData = NULL;
+    TPtr8 data( NULL, 0 );
+    TInt size = 0;
+
+    if ( iDeleteExpired )
+        {
+        TTime drmTime;
+        DRMClock::ESecurityLevel level;
+        TInt zone = KTzZulu;
+        iLazyClock->GetSecureTimeL( drmTime, zone, level );
+
+        if ( level == DRMClock::KSecure )
+            {
+            ROAPDB->DeleteExpiredRightsIssuerContextsL( drmTime );
+            ROAPDB->DeleteExpiredDomainContextsL( drmTime );
+            iDeleteExpired = EFalse;
+            }
+        }
+
+    size = User::LeaveIfError( IPCGETDESLEN0 );
+    contextData = HBufC8::NewMaxLC( size );
+    data.Set( const_cast<TUint8*> ( contextData->Ptr() ), 0, size );
+    IPCREAD0L( data );
+    MACLOGLITDETAIL( "Serialized RI context" )
+    MACLOGHEXDETAIL( contextData->Ptr(), contextData->Length() )
+
+    context = CDRMRIContext::NewLC();
+    context->ImportL( data );
+    ROAPDB->StoreRightsIssuerContextL( *context );
+
+    CleanupStack::PopAndDestroy( context );
+    CleanupStack::PopAndDestroy( contextData );
+    aMessage.Complete( KErrNone );
+    MACLOGLITDETAIL( "--> CRoapStorageSession::AddRiContextL" )
+    }
+
+// ---------------------------------------------------------------------------
+// CRoapStorageSession::AddDomainContextL
+// ---------------------------------------------------------------------------
+//
+void CRoapStorageSession::AddDomainContextL( const RMessage2& aMessage )
+    {
+    MACLOGLITDETAIL( "CRoapStorageSession::AddDomainContextL -->" )
+    CDRMDomainContext* context = NULL;
+    HBufC8* contextData = NULL;
+    HBufC8* domainElements = NULL;
+    HBufC8* macs = NULL;
+    TPtr8 data( NULL, 0 );
+    TInt size = 0;
+    TKeyTransportScheme transScheme;
+    TPckg<TKeyTransportScheme> package( transScheme );
+
+    HBufC8* plainDomainKey = NULL;
+    HBufC8* plainMacKey = NULL;
+
+    if ( iDeleteExpired )
+        {
+        TTime drmTime;
+        DRMClock::ESecurityLevel level;
+        TInt zone = KTzZulu;
+        iLazyClock->GetSecureTimeL( drmTime, zone, level );
+
+        if ( level == DRMClock::KSecure )
+            {
+            ROAPDB->DeleteExpiredRightsIssuerContextsL( drmTime );
+            ROAPDB->DeleteExpiredDomainContextsL( drmTime );
+            iDeleteExpired = EFalse;
+            }
+        }
+
+    RPointerArray<HBufC8> plainDomainKeys;
+    CleanupResetAndDestroyPushL( plainDomainKeys );
+
+    RPointerArray<HBufC8> plainMacKeys;
+    CleanupResetAndDestroyPushL( plainMacKeys );
+
+    size = IPCGETDESLEN0;
+
+    if ( size <= 0 )
+        {
+        User::Leave( KErrArgument );
+        }
+
+    contextData = HBufC8::NewMaxLC( size );
+    data.Set( const_cast<TUint8*> ( contextData->Ptr() ), 0, size );
+    IPCREAD0L( data );
+    MACLOGLITDETAIL( "Serialized domain context" )
+    MACLOGHEXDETAIL( contextData->Ptr(), contextData->Length() )
+
+    context = CDRMDomainContext::NewLC();
+    context->ImportL( data );
+
+    TPtrC8 domainId = context->DomainID();
+
+    if ( domainId.Length() <= 0 )
+        {
+        User::Leave( KErrArgument );
+        }
+
+    IPCREAD1L( package );
+
+    size = IPCGETDESLEN2;
+
+    if ( size <= 0 )
+        {
+        User::Leave( KErrArgument );
+        }
+
+    macs = HBufC8::NewLC( size );
+    data.Set( macs->Des() );
+    IPCREAD2L( data );
+
+    size = IPCGETDESLEN3;
+
+    if ( size <= 0 )
+        {
+        User::Leave( KErrArgument );
+        }
+
+    domainElements = HBufC8::NewLC( size );
+    data.Set( domainElements->Des() );
+    IPCREAD3L( data );
+
+    const RPointerArray<HBufC8>& domainKeys( context->DomainKeys() );
+
+    for ( TInt i = 0; i < domainKeys.Count(); i++ )
+        {
+        UnwrapDomainKeyL( iKeyStorage, *domainKeys[i], plainDomainKey,
+            plainMacKey, transScheme );
+        TInt ret( plainDomainKeys.Append( plainDomainKey ) );
+        if ( ret )
+            {
+            // Append did not succeed,
+            // delete buffers not in CleanupStack and leave.
+            delete plainDomainKey;
+            plainDomainKey = NULL;
+            delete plainMacKey;
+            plainMacKey = NULL;
+            User::LeaveIfError( ret );
+            }
+        CleanupStack::PushL( plainMacKey );
+        plainMacKeys.AppendL( plainMacKey );
+        CleanupStack::Pop( plainMacKey );
+        }
+
+    if ( !VerifyMacL( *domainElements, *macs, plainMacKeys ) )
+        {
+        User::Leave( KErrRoapServerFatal );
+        }
+
+    context->SetDomainKeysL( plainDomainKeys );
+
+    ROAPDB->StoreDomainContextL( *context );
+
+    CleanupStack::PopAndDestroy( domainElements );
+    CleanupStack::PopAndDestroy( macs );
+    CleanupStack::PopAndDestroy( context );
+    CleanupStack::PopAndDestroy( contextData );
+    CleanupStack::PopAndDestroy( &plainMacKeys );
+    CleanupStack::PopAndDestroy( &plainDomainKeys );
+    aMessage.Complete( KErrNone );
+    MACLOGLITDETAIL( "--> CRoapStorageSession::AddDomainContextL" )
+    }
+
+// ---------------------------------------------------------------------------
+// CRoapStorageSession::GetRiContextL
+// ---------------------------------------------------------------------------
+//
+void CRoapStorageSession::GetRiContextL( const RMessage2& aMessage )
+    {
+    MACLOGLITDETAIL( "CRoapStorageSession::GetRiContextL -->" )
+    CDRMRIContext* context = CDRMRIContext::NewLC();
+    HBufC8* riId = NULL;
+    TInt size = 0;
+    TPtr8 data( NULL, 0 );
+
+    TPckg<TInt> package( size );
+    riId = HBufC8::NewLC( User::LeaveIfError( IPCGETDESLEN1 ) );
+    data.Set( riId->Des() );
+    IPCREAD1L( data );
+    if ( riId->Length() != SHA1_HASH )
+        {
+        User::Leave( KErrArgument );
+        }
+    context->SetRIIDL( *riId );
+    ROAPDB->FetchRightsIssuerContextL( *context );
+    size = context->Size();
+    IPCWRITE0L( package );
+    delete iPreparedData;
+    iPreparedData = NULL;
+    iPreparedData = context->ExportL();
+
+    CleanupStack::PopAndDestroy( riId ); // riId, context
+    CleanupStack::PopAndDestroy( context ); // riId, context
+    aMessage.Complete( KErrNone );
+    MACLOGLITDETAIL( " --> CRoapStorageSession::GetRiContextL" )
+    }
+
+// ---------------------------------------------------------------------------
+// CRoapStorageSession::GetDomainContextL
+// ---------------------------------------------------------------------------
+//
+void CRoapStorageSession::GetDomainContextL( const RMessage2& aMessage )
+    {
+    MACLOGLITDETAIL( "CRoapStorageSession::GetDomainContextL -->" )
+    RThread thread;
+    aMessage.ClientL( thread );
+    CleanupClosePushL( thread );
+
+    CDRMDomainContext* context = CDRMDomainContext::NewLC();
+    HBufC8* domainId = NULL;
+    TInt size = 0;
+    TPtr8 data( NULL, 0 );
+    _LIT_SECURITY_POLICY_V0(vidCheck, VID_DEFAULT);
+    // Check Default VID
+
+    TPckg<TInt> package( size );
+    domainId = HBufC8::NewLC( User::LeaveIfError( IPCGETDESLEN1 ) );
+    data.Set( domainId->Des() );
+    IPCREAD1L( data );
+    if ( domainId->Length() < KMinDomainIdLength || domainId->Length()
+        > SHA1_HASH )
+        {
+        User::Leave( KErrArgument );
+        }
+
+    context->SetDomainIDL( *domainId );
+    ROAPDB->FetchDomainContextL( *context );
+    if ( !vidCheck.CheckPolicy( thread ) )
+        {
+        // Remove sensitive data since trusted vendor id not present
+        RPointerArray<HBufC8> emptyDomainKeys;
+        CleanupResetAndDestroyPushL( emptyDomainKeys );
+        emptyDomainKeys.Reset();
+        context->SetDomainKeysL( emptyDomainKeys );
+        CleanupStack::PopAndDestroy( &emptyDomainKeys );
+        }
+    size = context->Size();
+    IPCWRITE0L( package );
+    delete iPreparedData;
+    iPreparedData = NULL;
+    iPreparedData = context->ExportL();
+
+    CleanupStack::PopAndDestroy( domainId );
+    CleanupStack::PopAndDestroy( context );
+    CleanupStack::PopAndDestroy( &thread );
+    aMessage.Complete( KErrNone );
+    MACLOGLITDETAIL( " --> CRoapStorageSession::GetDomainContextL" )
+    }
+
+// ---------------------------------------------------------------------------
+// CRoapStorageSession::GetDataL
+// ---------------------------------------------------------------------------
+//
+void CRoapStorageSession::GetDataL( const RMessage2& aMessage )
+    {
+    if ( !iPreparedData )
+        {
+        User::Leave( KErrNotReady );
+        }
+
+    IPCWRITE0L( iPreparedData->Des() );
+
+    delete iPreparedData;
+    iPreparedData = NULL;
+
+    aMessage.Complete( KErrNone );
+    }
+
+// ---------------------------------------------------------------------------
+// CRoapStorageSession::DeleteRiContextL
+// ---------------------------------------------------------------------------
+//
+void CRoapStorageSession::DeleteRiContextL( const RMessage2& aMessage )
+    {
+    MACLOGLITDETAIL( "CRoapStorageSession::DeleteRiContextL -->" )
+    HBufC8* riId = NULL;
+    TPtr8 data( NULL, 0 );
+
+    SanitizeL( aMessage.GetDesLength( 0 ) );
+
+    riId = HBufC8::NewLC( IPCGETDESLEN0 );
+    data.Set( riId->Des() );
+    IPCREAD0L( data );
+
+    if ( riId->Length() != SHA1_HASH )
+        {
+        User::Leave( KErrArgument );
+        }
+
+    ROAPDB->DeleteRightsIssuerContextL( *riId );
+
+    CleanupStack::PopAndDestroy( riId );
+    aMessage.Complete( KErrNone );
+    MACLOGLITDETAIL( "--> CRoapStorageSession::DeleteRiContextL" )
+    }
+
+// ---------------------------------------------------------------------------
+// CRoapStorageSession::DeleteDomainContextL
+// ---------------------------------------------------------------------------
+//
+void CRoapStorageSession::DeleteDomainContextL( const RMessage2& aMessage )
+    {
+    MACLOGLITDETAIL( "CRoapStorageSession::DeleteDomainContextL -->" )
+    HBufC8* domainId = NULL;
+    TPtr8 data( NULL, 0 );
+
+    SanitizeL( aMessage.GetDesLength( 0 ) );
+
+    domainId = HBufC8::NewLC( IPCGETDESLEN0 );
+    data.Set( domainId->Des() );
+    IPCREAD0L( data );
+
+    if ( domainId->Length() < KMinDomainIdLength || domainId->Length()
+        > SHA1_HASH )
+        {
+        User::Leave( KErrArgument );
+        }
+
+    ROAPDB->DeleteDomainContextL( *domainId );
+
+    CleanupStack::PopAndDestroy( domainId );
+    aMessage.Complete( KErrNone );
+    MACLOGLITDETAIL( "--> CRoapStorageSession::DeleteDomainContextL" )
+    }
+
+// ---------------------------------------------------------------------------
+// CRoapStorageSession::DeleteExpiredRIsL
+// ---------------------------------------------------------------------------
+//
+void CRoapStorageSession::DeleteExpiredRIsL( const RMessage2& aMessage )
+    {
+    MACLOGLITDETAIL( "CRoapStorageSession::DeleteExpiredRIsL -->" )
+    TTime time;
+    TPckg<TTime> package( time );
+
+    IPCREAD0L( package );
+    ROAPDB->DeleteExpiredRightsIssuerContextsL( time );
+
+    aMessage.Complete( KErrNone );
+    MACLOGLITDETAIL( "--> CRoapStorageSession::DeleteExpiredRIsL" )
+    }
+
+// ---------------------------------------------------------------------------
+// CRoapStorageSession::DeleteExpiredDomainsL
+// ---------------------------------------------------------------------------
+//
+void CRoapStorageSession::DeleteExpiredDomainsL( const RMessage2& aMessage )
+    {
+    MACLOGLITDETAIL( "CRoapStorageSession::DeleteExpiredDomainsL -->" )
+    TTime time;
+    TPckg<TTime> package( time );
+
+    IPCREAD0L( package );
+    ROAPDB->DeleteExpiredDomainContextsL( time );
+
+    aMessage.Complete( KErrNone );
+    MACLOGLITDETAIL( "--> CRoapStorageSession::DeleteExpiredDomainsL" )
+    }
+
+// ---------------------------------------------------------------------------
+// CRoapStorageSession::WhiteListUrlExistsL
+// ---------------------------------------------------------------------------
+//
+void CRoapStorageSession::WhiteListUrlExistsL( const RMessage2& aMessage )
+    {
+    MACLOGLITDETAIL( "CRoapStorageSession::WhiteListURLExistsL -->" )
+    HBufC8* url = NULL;
+    TPtr8 data( NULL, 0 );
+    TBool exists = EFalse;
+
+    __UHEAP_MARK;
+    SanitizeL( aMessage.GetDesLength( 0 ) );
+    User::LeaveIfError( IPCGETDESLEN1 );
+    TBool fromPreConfiguredWhiteList( EFalse );
+    TPckg<TBool> preConfiguredInOutParam( fromPreConfiguredWhiteList );
+
+    url = HBufC8::NewLC( IPCGETDESLEN0 );
+    data.Set( url->Des() );
+    IPCREAD0L( data );
+    IPCREAD1L( preConfiguredInOutParam );
+    exists = ROAPDB->WhiteListURLExistsL( *url );
+
+    if ( exists )
+        {
+        fromPreConfiguredWhiteList = EFalse;
+        }
+    else if ( fromPreConfiguredWhiteList )
+        {
+        TPtrC8 whitelistElement( NULL, 0 );
+        HBufC* buffer = HBufC::NewLC( KMaxWhiteListLen );
+        HBufC8* whitelist = HBufC8::NewLC( KMaxWhiteListLen );
+
+        TPtr ptr( NULL, 0 );
+        ptr.Set( buffer->Des() );
+        CRepository* repository = CRepository::NewLC( KCRUidRoapHandler );
+        repository->Get( KRoapHandlerRegistrationWhitelist, ptr );
+        data.Set( whitelist->Des() );
+        data.Copy( ptr );
+        TLex8 lex( *whitelist );
+
+        TUriParser8 uri;
+        uri.Parse( *url );
+
+        const TDesC8& host = uri.Extract( EUriHost );
+        while ( !exists && !lex.Eos() )
+            {
+            whitelistElement.Set( lex.NextToken() );
+            if ( host.Right( whitelistElement.Length() ).CompareF(
+                whitelistElement ) == 0 )
+                {
+                exists = ETrue;
+                }
+            }
+        fromPreConfiguredWhiteList = exists;
+        CleanupStack::PopAndDestroy( repository );
+        CleanupStack::PopAndDestroy( whitelist );
+        CleanupStack::PopAndDestroy( buffer );
+        }
+
+    CleanupStack::PopAndDestroy( url );
+    IPCWRITE1L( preConfiguredInOutParam );
+    exists ? aMessage.Complete( KErrNone ) : aMessage.Complete( KErrNotFound );
+    __UHEAP_MARKEND;
+    MACLOGLITDETAIL( "--> CRoapStorageSession::WhiteListURLExistsL" )
+    }
+
+// ---------------------------------------------------------------------------
+// CRoapStorageSession::GetDevicePublicKeyDerL
+// ---------------------------------------------------------------------------
+//
+void CRoapStorageSession::GetDevicePublicKeyDerL( const RMessage2& aMessage )
+    {
+    MACLOGLITDETAIL( "CRoapStorageSession::GetDevicePublicKeyDerL -->" )
+    HBufC8* publicKey = NULL;
+    TInt size = 0;
+    TPtr8 data( NULL, 0 );
+    TPckg<TInt> package( size );
+    CX509Certificate* cert = NULL;
+    RPointerArray<HBufC8> certChain;
+
+    CleanupResetAndDestroyPushL( certChain );
+
+    iKeyStorage->GetCertificateChainL( certChain );
+    if ( certChain.Count() > 0 )
+        cert = CX509Certificate::NewL( *certChain[0] );
+    else
+        User::Leave( KErrNotFound );
+    CleanupStack::PopAndDestroy( &certChain );
+    CleanupStack::PushL( cert );
+    publicKey = cert->DataElementEncoding(
+        CX509Certificate::ESubjectPublicKeyInfo )->AllocLC();
+    size = publicKey->Size();
+    IPCWRITE0L( package );
+    delete iPreparedData;
+    iPreparedData = NULL;
+    iPreparedData = publicKey;
+    CleanupStack::Pop( publicKey );
+    CleanupStack::PopAndDestroy( cert );
+    aMessage.Complete( KErrNone );
+    MACLOGLITDETAIL( "--> CRoapStorageSession::GetDevicePublicKeyDerL" )
+    }
+
+// ---------------------------------------------------------------------------
+// CRoapStorageSession::GetDeviceCertificateChainL
+// ---------------------------------------------------------------------------
+//
+void CRoapStorageSession::GetDeviceCertificateChainL(
+    const RMessage2& aMessage )
+    {
+    MACLOGLITDETAIL( "CRoapStorageSession::GetCertificateChainL -->" )
+    RPointerArray<HBufC8> certChain;
+    HBufC8* certChainBuf = NULL;
+    TInt bufferSize = 0;
+    TPckg<TInt> package( bufferSize );
+
+    CleanupResetAndDestroyPushL( certChain );
+
+    iKeyStorage->GetCertificateChainL( certChain );
+    certChainBuf = ArrayToBufferLC( certChain );
+    CleanupStack::Pop( certChainBuf );
+    CleanupStack::PopAndDestroy( &certChain );
+    CleanupStack::PushL( certChainBuf );
+    bufferSize = certChainBuf->Size();
+    IPCWRITE0L( package );
+    delete iPreparedData;
+    iPreparedData = certChainBuf;
+    CleanupStack::Pop( certChainBuf );
+    aMessage.Complete( KErrNone );
+    MACLOGLITDETAIL( "--> CRoapStorageSession::GetCertificateChainL" )
+    }
+
+// ---------------------------------------------------------------------------
+// CRoapStorageSession::SignL
+// ---------------------------------------------------------------------------
+//
+void CRoapStorageSession::SignL( const RMessage2& aMessage )
+    {
+    MACLOGLITDETAIL( "CRoapStorageSession::SignL -->" )
+    HBufC8* hash = NULL;
+    HBufC8* signature = NULL;
+    TInt size = 0;
+    TPtr8 data( NULL, 0 );
+    TPckg<TInt> package( size );
+
+    if ( IPCGETDESLEN1 <= 0 || IPCGETDESLEN1 >= KMaxTInt / 2 )
+        {
+        User::Leave( KErrArgument );
+        }
+
+    hash = HBufC8::NewLC( IPCGETDESLEN1 );
+
+    data.Set( hash->Des() );
+    IPCREAD1L( data );
+    signature = OmaCrypto::RsaPssSignHashL( iKeyStorage, *hash );
+    CleanupStack::PushL( signature );
+    size = signature->Size();
+    IPCWRITE0L( package );
+    delete iPreparedData;
+    iPreparedData = signature;
+    CleanupStack::Pop( signature );
+    CleanupStack::PopAndDestroy( hash );
+    aMessage.Complete( KErrNone );
+    MACLOGLITDETAIL( "--> CRoapStorageSession::SignL" )
+    }
+
+// ---------------------------------------------------------------------------
+// CRoapStorageSession::RsaSignL
+// ---------------------------------------------------------------------------
+//
+void CRoapStorageSession::RsaSignL( const RMessage2& aMessage )
+    {
+    MACLOGLITDETAIL( "CRoapStorageSession::RsaSignL -->" )
+    HBufC8* hash = NULL;
+    HBufC8* signature = NULL;
+    TInt size = 0;
+    TPtr8 data( NULL, 0 );
+    TPckg<TInt> package( size );
+
+    if ( IPCGETDESLEN1 <= 0 || IPCGETDESLEN1 >= KMaxTInt / 2 )
+        {
+        User::Leave( KErrArgument );
+        }
+
+    hash = HBufC8::NewLC( IPCGETDESLEN1 );
+
+    data.Set( hash->Des() );
+    IPCREAD1L( data );
+    signature = iKeyStorage->RsaSignL( data );
+    CleanupStack::PushL( signature );
+    size = signature->Size();
+    IPCWRITE0L( package );
+    delete iPreparedData;
+    iPreparedData = signature;
+    CleanupStack::Pop( signature );
+    CleanupStack::PopAndDestroy( hash );
+    aMessage.Complete( KErrNone );
+    MACLOGLITDETAIL( "--> CRoapStorageSession::RsaSignL" )
+    }
+
+// ---------------------------------------------------------------------------
+// CRoapStorageSession::SelectTrustedRootL
+// ---------------------------------------------------------------------------
+//
+void CRoapStorageSession::SelectTrustedRootL( const RMessage2& aMessage )
+    {
+    MACLOGLITDETAIL( "CRoapStorageSession::SelectTrustedRootL -->" )
+    RPointerArray<HBufC8> riRoots;
+    RPointerArray<HBufC8> deviceRoots;
+    HBufC8* rootsBuf = NULL;
+    TPtr8 data( NULL, 0 );
+    TBool commonRootFound = EFalse;
+    TInt i = 0;
+    TInt j = 0;
+
+    CleanupResetAndDestroyPushL( riRoots );
+    CleanupResetAndDestroyPushL( deviceRoots );
+
+    SanitizeL( aMessage.GetDesLength( 0 ) );
+    rootsBuf = HBufC8::NewLC( IPCGETDESLEN0 );
+
+    data.Set( rootsBuf->Des() );
+    IPCREAD0L( data );
+    riRoots = BufferToArrayL( *rootsBuf );
+    iKeyStorage->GetTrustedRootsL( deviceRoots );
+
+    while ( i < deviceRoots.Count() && !commonRootFound )
+        {
+        j = 0;
+        while ( j < riRoots.Count() && !commonRootFound )
+            {
+            if ( deviceRoots[i]->CompareF( *riRoots[j] ) == KErrNone )
+                {
+                commonRootFound = ETrue;
+                }
+            ++j;
+            }
+        ++i;
+        }
+    if ( !commonRootFound )
+        {
+        User::Leave( KErrNotFound );
+        }
+
+    const TPtrC8 selectedRoot( *( deviceRoots[i - 1] ) );
+    iKeyStorage->SelectTrustedRootL( selectedRoot );
+    IPCWRITE1L( selectedRoot );
+    MACLOGLITDETAIL( "Selected trusted root" )
+    MACLOGHEXDETAIL( selectedRoot.Ptr(), selectedRoot.Length() )
+
+    CleanupStack::PopAndDestroy( rootsBuf );
+    CleanupStack::PopAndDestroy( &deviceRoots );
+    CleanupStack::PopAndDestroy( &riRoots );
+    aMessage.Complete( KErrNone );
+    MACLOGLITDETAIL( "--> CRoapStorageSession::SelectTrustedRootL" )
+    }
+
+// ---------------------------------------------------------------------------
+// CRoapStorageSession::ActivateTrustedRootL
+// ---------------------------------------------------------------------------
+//
+void CRoapStorageSession::ActivateTrustedRootL( const RMessage2& aMessage )
+    {
+    MACLOGLITDETAIL( "CRoapStorageSession::ActivateTrustedRootL -->" )
+    TBuf8<SHA1_HASH> trustedRoot;
+
+    if ( IPCGETDESLEN0 <= 0 )
+        {
+        // select default root
+        iKeyStorage->SelectTrustedRootL( KNullDesC8 );
+        }
+    else
+        {
+        // select the root indicated by the client
+        IPCREAD0L( trustedRoot );
+        if ( trustedRoot.Length() != SHA1_HASH )
+            {
+            User::Leave( KErrArgument );
+            }
+        iKeyStorage->SelectTrustedRootL( trustedRoot );
+        }
+    aMessage.Complete( KErrNone );
+    MACLOGLITDETAIL( "--> CRoapStorageSession::ActivateTrustedRootL" )
+    }
+
+// ---------------------------------------------------------------------------
+// CRoapStorageSession::GetTrustedRootsL
+// ---------------------------------------------------------------------------
+//
+void CRoapStorageSession::GetTrustedRootsL( const RMessage2& aMessage )
+    {
+    MACLOGLITDETAIL( "CRoapStorageSession::GetTrustedRootsL -->" )
+    RPointerArray<HBufC8> deviceRoots;
+    TInt size = 0;
+    HBufC8* rootsData = NULL;
+
+    CleanupResetAndDestroyPushL( deviceRoots );
+
+    TPckg<TInt> package( size );
+    iKeyStorage->GetTrustedRootsL( deviceRoots );
+    rootsData = ArrayToBufferLC( deviceRoots );
+    size = rootsData->Size();
+    IPCWRITE0L( package );
+    delete iPreparedData;
+    iPreparedData = NULL;
+    iPreparedData = rootsData;
+
+    CleanupStack::Pop( rootsData );
+    CleanupStack::PopAndDestroy( &deviceRoots );
+    aMessage.Complete( KErrNone );
+    MACLOGLITDETAIL( "--> CRoapStorageSession::GetTrustedRootsL" )
+    }
+
+// ---------------------------------------------------------------------------
+// CRoapStorageSession::GetRootCertificateL
+// ---------------------------------------------------------------------------
+//
+void CRoapStorageSession::GetRootCertificateL( const RMessage2& aMessage )
+    {
+    MACLOGLITDETAIL( "CRoapStorageSession::GetRootCertificateL -->" )
+    HBufC8* rootCertBuf( NULL );
+    HBufC* subject( NULL );
+    TInt size( 0 );
+    TPtr data( NULL, 0 );
+    RPointerArray<HBufC8> rootCerts;
+    TPckg<TInt> package( size );
+    CX509Certificate* rootCert( NULL );
+    HBufC* rootName( NULL );
+    TInt i = 0;
+
+    SanitizeL( IPCGETDESLEN1 );
+    subject = HBufC::NewLC( User::LeaveIfError( IPCGETDESLEN1 ) );
+    data.Set( subject->Des() );
+    IPCREAD1L( data );
+
+    iKeyStorage->GetRootCertificatesL( rootCerts );
+
+    CleanupResetAndDestroyPushL( rootCerts );
+
+    for ( i = 0; i < rootCerts.Count() && !rootCertBuf; i++ )
+        {
+        rootCert = CX509Certificate::NewLC( *( rootCerts[i] ) );
+        rootName = rootCert->IssuerName().DisplayNameL();
+        CleanupStack::PushL( rootName );
+        const TInt compareResult( rootName->CompareF( *subject ) );
+        CleanupStack::PopAndDestroy( rootName );
+        CleanupStack::PopAndDestroy( rootCert );
+        if ( compareResult == KErrNone )
+            {
+            rootCertBuf = rootCerts[i]->AllocLC();
+            }
+        }
+
+    if ( !rootCertBuf )
+        {
+        User::Leave( KErrNotFound );
+        }
+
+    size = rootCertBuf->Size();
+    IPCWRITE0L( package );
+    delete iPreparedData;
+    iPreparedData = NULL;
+    iPreparedData = rootCertBuf;
+
+    CleanupStack::Pop( rootCertBuf );
+    CleanupStack::PopAndDestroy( &rootCerts );
+    CleanupStack::PopAndDestroy( subject );
+    aMessage.Complete( KErrNone );
+    MACLOGLITDETAIL( "--> CRoapStorageSession::GetRootCertificateL" )
+    }
+
+// ---------------------------------------------------------------------------
+// CRoapStorageSession::DeleteExpiredContextsL
+// ---------------------------------------------------------------------------
+//
+void CRoapStorageSession::DeleteExpiredContextsL( const RMessage2& aMessage )
+    {
+    MACLOGLITDETAIL( "CRoapStorageSession::DeleteExpiredContextsL -->" )
+    TTime time;
+    TPckg<TTime> package( time );
+
+    IPCREAD0L( package );
+    ROAPDB->DeleteExpiredRightsIssuerContextsL( time );
+    ROAPDB->DeleteExpiredDomainContextsL( time );
+
+    aMessage.Complete( KErrNone );
+    MACLOGLITDETAIL( "--> CRoapStorageSession::DeleteExpiredContextsL" )
+    }
+
+// ---------------------------------------------------------------------------
+// CRoapStorageSession::DeleteAllL
+// ---------------------------------------------------------------------------
+//
+void CRoapStorageSession::DeleteAllL( const RMessage2& aMessage )
+    {
+
+    MACLOGLITDETAIL( "CRoapStorageSession::DeleteAllL -->" )
+#ifndef RD_MULTIPLE_DRIVE
+
+    ROAPDB->DeleteAllL( KRIContextFile(), KDomainContextFile() );
+
+#else //RD_MULTIPLE_DRIVE
+    RFs fs;
+    TInt driveNumber( -1 );
+    TChar driveLetter;
+    DriveInfo::GetDefaultDrive( DriveInfo::EDefaultSystem, driveNumber );
+
+    User::LeaveIfError( fs.Connect() );
+    CleanupClosePushL( fs );
+    fs.DriveToChar( driveNumber, driveLetter );
+    CleanupStack::PopAndDestroy( &fs );
+
+    TFileName riContextFile;
+    riContextFile.Copy( KRIContextFileName );
+    __ASSERT_ALWAYS( riContextFile.Length()>0, User::Invariant() );
+    riContextFile[0] = ( TUint )driveLetter;
+
+    TFileName domainContextFile;
+    domainContextFile.Copy( KDomainContextFileName );
+    __ASSERT_ALWAYS( domainContextFile.Length()>0, User::Invariant() );
+    domainContextFile[0] = ( TUint )driveLetter;
+
+    ROAPDB->DeleteAllL( riContextFile, domainContextFile );
+
+#endif
+
+    aMessage.Complete( KErrNone );
+    MACLOGLITDETAIL( "--> CRoapStorageSession::DeleteAllL" )
+    }
+
+// ---------------------------------------------------------------------------
+// CRoapStorageSession::GetMeteringDataL
+// ---------------------------------------------------------------------------
+//
+void CRoapStorageSession::GetMeteringDataL( const RMessage2& aMessage )
+    {
+    MACLOGLITDETAIL( "CRoapStorageSession::GetMeteringDataL -->" )
+#ifndef RD_DRM_METERING
+    aMessage.Complete( KErrNotSupported );
+#else
+    HBufC8* riId = NULL;
+    HBufC8* meteringData = NULL;
+    HBufC8* encryptedMeteringData = NULL;
+    RDRMRightsClient client;
+    TInt mekAndMakSize = 0;
+    TInt meteringDataSize = 0;
+    TPtr8 data( NULL, 0 );
+    TPtr8 ptr( NULL, 0 );
+    TPckg<TInt> MakMek( mekAndMakSize );
+    TPckg<TInt> dataSize( meteringDataSize );
+    TBuf8<KDCFKeySize> mac;
+    TBuf8<KDCFKeySize> mek;
+    TBuf8<KDCFKeySize> initializingVector;
+    CRSAPublicKey* riPublicKey = NULL;
+    CX509Certificate* cert = NULL;
+    CSHA1* hasher = NULL;
+    TBuf8<SHA1_HASH> encKeyHash;
+    TX509KeyFactory factory;
+    TKeyTransportScheme selectedAlgorithm = EOma;
+    HBufC8* encryptedMekAndMak = NULL;
+    CDRMRIContext* context = NULL;
+
+    User::LeaveIfError( client.Connect() );
+    CleanupClosePushL( client );
+
+    SanitizeL( aMessage.GetDesLength( 0 ) );
+
+    riId = HBufC8::NewLC( IPCGETDESLEN0 );
+    data.Set( riId->Des() );
+    IPCREAD0L( data );
+
+    // generate mek
+    mek.SetLength( OmaCrypto::KKeySize );
+    TRandom::Random( mek );
+
+    // generate mac
+    mac.SetLength( OmaCrypto::KMacSize );
+    TRandom::Random( mac );
+
+    initializingVector.SetLength( KDCFKeySize );
+    TRandom::Random( initializingVector );
+
+    context = CDRMRIContext::NewLC();
+    context->SetRIIDL( *riId );
+    ROAPDB->FetchRightsIssuerContextL( *context );
+
+    cert = CX509Certificate::NewLC( *( context->CertificateChain() )[0] );
+
+    hasher = CSHA1::NewL();
+    CleanupStack::PushL( hasher );
+    // Calculate SHA1_HASH for RI public key
+    hasher->Hash( *cert->DataElementEncoding(
+        CX509Certificate::ESubjectPublicKeyInfo ) );
+    encKeyHash.Append( hasher->Final() );
+    CleanupStack::PopAndDestroy( hasher );
+
+    riPublicKey = factory.RSAPublicKeyL( cert->PublicKey().KeyData() );
+    CleanupStack::PopAndDestroy( cert );
+    cert = NULL;
+    CleanupStack::PushL( riPublicKey );
+
+    // check if we are not using OMA algorithms
+    for ( TInt i = 0; i < context->Algorithms().Count(); i++ )
+        {
+        if ( context->Algorithms()[i]->CompareF( KCmlaIp1() ) == KErrNone )
+            {
+            selectedAlgorithm = ECmlaIp1;
+            break;
+            }
+        }
+
+    // Wrap Mek and Mac with RI's public key
+    if ( selectedAlgorithm == EOma )
+        {
+        encryptedMekAndMak = OmaCrypto::RsaKemKwsEncryptL( riPublicKey, mek,
+            mac );
+        }
+    else
+        { // CMLA
+        encryptedMekAndMak = CmlaCrypto::CmlaIpEncryptL( selectedAlgorithm,
+            riPublicKey, mek, mac );
+        }
+    CleanupStack::PopAndDestroy( riPublicKey );
+    riPublicKey = NULL;
+    CleanupStack::PopAndDestroy( context );
+    context = NULL;
+
+    CleanupStack::PushL( encryptedMekAndMak );
+
+    mekAndMakSize = encryptedMekAndMak->Size();
+    // Get the actual metering data!!!
+    meteringData = client.GetMeteringDataL( *riId );
+
+    if ( !meteringData )
+        {
+        MACLOGLIT( "No metering Data found from DB!:" )
+        }
+    else
+        {
+        MACLOGLIT( "Raw meteringData:" )
+        MACLOGHEX( meteringData->Ptr(), meteringData->Length() )
+        CleanupStack::PushL( meteringData );
+
+        encryptedMeteringData = DrmAesCrypto::DrmAesEncryptL( mek,
+            initializingVector, ETrue, meteringData->Des() );
+
+        CleanupStack::PopAndDestroy( meteringData );
+        meteringData = NULL;
+
+        CleanupStack::PushL( encryptedMeteringData );
+
+        MACLOGLIT( "Ciphered meteringData with 128-bit AESCBC:" )
+        MACLOGHEX( encryptedMeteringData->Ptr(), encryptedMeteringData->Length())
+        meteringDataSize = encryptedMeteringData->Size();
+        }
+
+    IPCWRITE1L( MakMek );
+    IPCWRITE2L( dataSize );
+    if ( iPreparedData )
+        {
+        delete iPreparedData;
+        iPreparedData = NULL;
+        }
+    iPreparedData = HBufC8::NewL( OmaCrypto::KMacSize + SHA1_HASH
+        + mekAndMakSize + meteringDataSize );
+    ptr.Set( iPreparedData->Des() );
+    ptr.Copy( mac );
+    ptr.Append( encKeyHash );
+    ptr.Append( *encryptedMekAndMak );
+    if ( encryptedMeteringData )
+        {
+        ptr.Append( *encryptedMeteringData );
+        CleanupStack::PopAndDestroy( encryptedMeteringData );
+        }
+
+    MACLOGLIT( "Final iPreparedData:" )
+    MACLOGHEX( iPreparedData->Ptr(), iPreparedData->Length() )
+
+    CleanupStack::PopAndDestroy( encryptedMekAndMak );
+    CleanupStack::PopAndDestroy( riId );
+    CleanupStack::PopAndDestroy( &client );
+    // riId, client
+    aMessage.Complete( KErrNone );
+#endif //RD_DRM_METERING
+    MACLOGLITDETAIL( "--> CRoapStorageSession::GetMeteringDataL" )
+    }
+
+// ---------------------------------------------------------------------------
+// CRoapStorageSession::DeleteMeteringDataL
+// ---------------------------------------------------------------------------
+//
+void CRoapStorageSession::DeleteMeteringDataL( const RMessage2& aMessage )
+    {
+    MACLOGLITDETAIL( "CRoapStorageSession::DeleteMeteringDataL -->" )
+#ifndef RD_DRM_METERING
+    aMessage.Complete( KErrNotSupported );
+#else
+    HBufC8* riId = NULL;
+    TPtr8 data( NULL, 0 );
+    RDRMRightsClient client;
+
+    User::LeaveIfError( client.Connect() );
+    CleanupClosePushL( client );
+    riId = HBufC8::NewLC( User::LeaveIfError( IPCGETDESLEN0 ) );
+    data.Set( riId->Des() );
+    IPCREAD0L( data );
+    client.DeleteMeteringDataL( *riId );
+
+    CleanupStack::PopAndDestroy( riId );
+    CleanupStack::PopAndDestroy( &client );
+
+    aMessage.Complete( KErrNone );
+#endif // RD_DRM_METERING
+    MACLOGLITDETAIL( "--> CRoapStorageSession::DeleteMeteringDataL" )
+    }
+
+// ---------------------------------------------------------------------------
+// CRoapStorageSession::GetAllRIContextsL
+// ---------------------------------------------------------------------------
+//
+void CRoapStorageSession::GetAllRIContextsL( const RMessage2& aMessage )
+    {
+    MACLOGLITDETAIL( "CRoapStorageSession::GetAllRIContextsL -->" )
+#ifndef RD_DRM_METERING
+    aMessage.Complete( KErrNotSupported );
+#else
+    TInt size = 0;
+    TPtr8 data( NULL, 0 );
+    CDRMPointerArray<CDRMRIContext>* contexts = CDRMPointerArray<
+        CDRMRIContext>::NewLC();
+    contexts->SetAutoCleanup( ETrue );
+
+    TPckg<TInt> package( size );
+
+    ROAPDB->FetchAllRightsIssuerContextsL( *contexts );
+
+    // Calculate the size of the output buffer:
+    if ( contexts->Count() )
+        {
+        size = contexts->Count() * sizeof(TInt) + sizeof(TInt);
+        for ( TInt i = 0; i < contexts->Count(); i++ )
+            {
+            size += ( *contexts )[i]->Size();
+            }
+        }
+    else
+        {
+        User::Leave( KErrNotFound );
+        }
+
+    IPCWRITE0L( package );
+
+    // Create a buffer of the proper size and export the data to the buffer:
+    if ( iPreparedData )
+        {
+        delete iPreparedData;
+        iPreparedData = NULL;
+        }
+    iPreparedData = HBufC8::NewMaxL( size );
+
+    if ( !iPreparedData )
+        {
+        User::Leave( KErrNoMemory );
+        }
+
+    RMemWriteStream stream( ( TAny* )( iPreparedData->Ptr() ), size );
+    CleanupClosePushL( stream );
+    TInt value = 0;
+
+    for ( TInt i = 0; i < contexts->Count(); i++ )
+        {
+        // Size:
+        value = ( *contexts )[i]->Size();
+        stream.WriteInt32L( value );
+
+        // Data:
+        ( *contexts )[i]->ExternalizeL( stream );
+        }
+    // Finishing size:
+    value = 0;
+    stream.WriteInt32L( value );
+
+    CleanupStack::PopAndDestroy( 2, contexts ); // stream, contexts
+
+    aMessage.Complete( KErrNone );
+#endif // RD_DRM_METERING
+    MACLOGLITDETAIL( "--> CRoapStorageSession::GetAllRIContextsL" )
+    }
+
+// ---------------------------------------------------------------------------
+// CRoapStorageSession::UpdateRIContextL
+// ---------------------------------------------------------------------------
+//
+void CRoapStorageSession::UpdateRIContextL( const RMessage2& aMessage )
+    {
+    MACLOGLITDETAIL( "CRoapStorageSession::UpdateRIContextL -->" )
+#ifndef RD_DRM_METERING
+    aMessage.Complete( KErrNotSupported );
+#else
+    CDRMRIContext* context = NULL;
+    HBufC8* contextData = NULL;
+    TPtr8 data( NULL, 0 );
+    TInt size = 0;
+
+    size = User::LeaveIfError( IPCGETDESLEN0 );
+    contextData = HBufC8::NewMaxLC( size );
+    data.Set( const_cast<TUint8*> ( contextData->Ptr() ), 0, size );
+    IPCREAD0L( data );
+    context = CDRMRIContext::NewLC();
+    context->ImportL( data );
+
+    // Update RI context:
+    ROAPDB->UpdateRightsIssuerContextL( *context );
+
+    CleanupStack::PopAndDestroy( context );
+    CleanupStack::PopAndDestroy( contextData );
+    aMessage.Complete( KErrNone );
+#endif // RD_DRM_METERING
+    MACLOGLITDETAIL( "--> CRoapStorageSession::UpdateRIContextL" )
+    }
+
+// ---------------------------------------------------------------------------
+// CRoapStorageSession::UpdateDrmTimeL
+// ---------------------------------------------------------------------------
+//
+void CRoapStorageSession::UpdateDrmTimeL( const RMessage2& aMessage )
+    {
+    MACLOGLITDETAIL( "CRoapStorageSession::UpdateDrmTimeL -->" )
+    COCSPResponseDecoder* responseDecoder = NULL;
+    COCSPResponse* response = NULL;
+    RPointerArray<HBufC8> ocspResponses;
+
+    RPointerArray<HBufC8> riCertChain;
+
+    TBool clockUpdated( EFalse );
+    TPckg<TBool> retBuf( clockUpdated );
+
+    // Some sanity checks
+    const TInt argLen0( IPCGETDESLEN0 );
+    const TInt argLen1( IPCGETDESLEN1 );
+    const TInt argLen2( IPCGETDESLEN2 );
+    SanitizeL( argLen0 );
+    SanitizeL( argLen1 );
+    SanitizeL( argLen2 );
+    User::LeaveIfError( IPCGETDESLEN3 );
+
+    RBuf8 readBuf;
+    CleanupClosePushL( readBuf );
+    readBuf.CreateL( Max( argLen0, Max( argLen1, argLen2 ) ) );
+
+    readBuf.Zero();
+    IPCREAD0L( readBuf );
+    MACLOGLDETAIL( "---- read Ri Cert Chain ----" )
+    MACLOGHEXDETAIL( readBuf.Ptr(), readBuf.Length() )
+    riCertChain = BufferToArrayL( readBuf );
+    CleanupResetAndDestroyPushL( riCertChain );
+
+    readBuf.Zero();
+    IPCREAD1L( readBuf );
+    MACLOGLDETAIL( "---- read serialized OCSP responses ----" )
+    MACLOGHEXDETAIL( readBuf.Ptr(), readBuf.Length() )
+    ocspResponses = BufferToArrayL( readBuf );
+    CleanupResetAndDestroyPushL( ocspResponses );
+
+    readBuf.Zero();
+    IPCREAD2L( readBuf );
+    MACLOGLDETAIL( "---- read request nonce ----" )
+    MACLOGHEXDETAIL( readBuf.Ptr(), readBuf.Length() )
+    const TPtrC8 regReqNonce( readBuf ); // Do not modify readBuf after this.
+
+    // Get trusted roots and root certificates.
+    RPointerArray<HBufC8> trustedRoots;
+    CleanupResetAndDestroyPushL( trustedRoots );
+    iKeyStorage->GetTrustedRootsL( trustedRoots );
+    RPointerArray<HBufC8> rootCertificates;
+    CleanupResetAndDestroyPushL( rootCertificates );
+    iKeyStorage->GetRootCertificatesL( rootCertificates );
+
+    //First, check, if update is allowed
+    if ( ocspResponses.Count() )
+        {
+        responseDecoder = COCSPResponseDecoder::NewL( *ocspResponses[0] );
+        CleanupStack::PushL( responseDecoder );
+        response = responseDecoder->TakeResponse(); // CRoapEng owns the response now
+        User::LeaveIfNull( response );
+        CleanupStack::PopAndDestroy( responseDecoder );
+        responseDecoder = NULL;
+        CleanupStack::PushL( response );
+        if ( ::IsTimeUpdateAllowedL( trustedRoots, rootCertificates,
+            riCertChain, *response, regReqNonce ) )
+            {
+            iLazyClock->UpdateSecureTimeL( response->ProducedAt(), KTzZulu );
+            clockUpdated = ETrue;
+            MACLOGLIT( "DRM time updated" )
+            }
+
+        CleanupStack::PopAndDestroy( response );
+        }
+    else
+        {
+        MACLOGLIT( "No OCSP responses present!" )
+        // So wrong argument got
+        }
+    CleanupStack::PopAndDestroy( &rootCertificates );
+    CleanupStack::PopAndDestroy( &trustedRoots );
+    CleanupStack::PopAndDestroy( &ocspResponses );
+    CleanupStack::PopAndDestroy( &riCertChain );
+    CleanupStack::PopAndDestroy( &readBuf );
+    IPCWRITE3L( retBuf );
+
+    aMessage.Complete( KErrNone );
+    MACLOGLITDETAIL( "--> CRoapStorageSession::UpdateDrmTimeL" )
+    }
+
+// ---------------------------------------------------------------------------
+// BufferToArrayL
+// Created buffer will contain
+// <amount of elements:int32, element data1, element data2...>
+// ---------------------------------------------------------------------------
+//
+LOCAL_C RPointerArray<HBufC8> BufferToArrayL( TDesC8& aBuffer )
+    {
+    TInt32 count = 0;
+    HBufC8* element = NULL;
+    RPointerArray<HBufC8> array;
+    CleanupResetAndDestroyPushL( array );
+    TInt size = aBuffer.Size();
+    RMemReadStream stream( ( TAny* )( aBuffer.Ptr() ), size );
+    CleanupClosePushL( stream );
+
+    // amount of elements
+    count = stream.ReadInt32L();
+
+    // for each element in RPointerArray
+    for ( TInt i = 0; i < count; i++ )
+        {
+        // Read the element and append it to array
+        element = HBufC8::NewLC( stream, KMaxElementLength );
+        array.AppendL( element );
+        CleanupStack::Pop( element );
+        }
+
+    CleanupStack::PopAndDestroy( &stream );
+    CleanupStack::Pop( &array );
+    return array;
+    }
+
+// ---------------------------------------------------------------------------
+// ArrayToBuffer
+// Created buffer will contain <amount of elements:int32, data1, data2 ...>
+// ---------------------------------------------------------------------------
+//
+LOCAL_C HBufC8* ArrayToBufferLC( const RPointerArray<HBufC8>& aArray )
+    {
+    HBufC8* buffer = NULL;
+    TInt32 sizeOfElements = 0;
+
+    for ( TInt i = 0; i < aArray.Count(); i++ )
+        {
+        sizeOfElements += aArray[i]->Length() + sizeof(TInt); // sizeof(TInt) is for
+        // element length info
+        }
+    // length of elements + amount of elements
+    sizeOfElements += sizeof(TInt32);
+
+    buffer = HBufC8::NewMaxLC( sizeOfElements );
+
+    RMemWriteStream stream( ( TAny* )( buffer->Ptr() ), sizeOfElements );
+    CleanupClosePushL( stream );
+
+    stream.WriteInt32L( aArray.Count() );
+
+    for ( TInt i = 0; i < aArray.Count(); i++ )
+        {
+        stream << *( aArray[i] );
+        }
+
+    CleanupStack::PopAndDestroy( &stream );
+
+    return buffer;
+    }
+
+// ---------------------------------------------------------------------------
+// UnwrapDomainKeyL
+// ---------------------------------------------------------------------------
+//
+LOCAL_C void UnwrapDomainKeyL(
+    MDrmKeyStorage* aKeyStorage,
+    const TDesC8& aProtectedDomainKey,
+    HBufC8*& aDomainKey,
+    HBufC8*& aMacKey,
+    TKeyTransportScheme& aTransportScheme )
+    {
+    MACLOGLITDETAIL( "::UnwrapDomainKeyL -->" )
+    TBuf8<OmaCrypto::KMacSize> mac;
+    TBuf8<OmaCrypto::KKeySize> dk;
+    TPtrC8 macAndRek( 0, 0 );
+    TPtrC8 wrappedCek( 0, 0 );
+
+    if ( aTransportScheme == EOma )
+        {
+        OmaCrypto::RsaKemKwsDecryptL( aKeyStorage, aProtectedDomainKey, dk,
+            mac );
+        }
+    else
+        {
+        CmlaCrypto::CmlaIpDecryptL( aTransportScheme, aKeyStorage,
+            aProtectedDomainKey, dk, mac );
+        }
+
+    HBufC8* domainKey( dk.AllocLC() );
+    aMacKey = mac.AllocL();
+    CleanupStack::Pop( domainKey );
+    aDomainKey = domainKey;
+    MACLOGLITDETAIL( "--> ::UnwrapDomainKeyL" )
+    }
+
+// ---------------------------------------------------------------------------
+// VerifyMac
+// ---------------------------------------------------------------------------
+//
+LOCAL_C TBool VerifyMacL(
+    TDesC8& aDomainElements,
+    TDesC8& aMacs,
+    RPointerArray<HBufC8>& aMacKeys )
+    {
+    MACLOGLITDETAIL( "::VerifyMacL -->" )
+    __UHEAP_MARK;
+    RPointerArray<HBufC8> domainArray;
+    RPointerArray<HBufC8> macArray;
+    CMessageDigest* hMac = NULL;
+    HBufC8* domainKeyWithNs = NULL;
+    TPtr8 domainKeyWithNsPtr( NULL, NULL );
+    TPtrC8 hmac_value( KNullDesC8 );
+    TInt index = 0;
+
+    CleanupResetAndDestroyPushL( domainArray );
+    CleanupResetAndDestroyPushL( macArray );
+
+    domainArray = BufferToArrayL( aDomainElements );
+    macArray = BufferToArrayL( aMacs );
+
+    if ( domainArray.Count() != macArray.Count() || macArray.Count()
+        != aMacKeys.Count() )
+        {
+        User::Leave( KErrRoapServerFatal );
+        }
+
+    //Verify macs
+    for ( TInt i = 0; i < aMacKeys.Count(); i++ )
+        {
+        // Add ROAP namespaces
+        domainKeyWithNs = HBufC8::NewLC( domainArray[i]->Length() + 2
+            * KRoapXmlNs().Length() );
+        domainKeyWithNsPtr.Set( domainKeyWithNs->Des() );
+        index = domainArray[i]->Find( KRoapDomainKey() );
+        if ( index == KErrNotFound )
+            {
+            index = domainArray[i]->Find( KRoapX509SPKIHash() );
+            if ( index == KErrNotFound )
+                {
+                User::Leave( KErrCorrupt );
+                }
+            index += KRoapX509SPKIHash().Length();
+            }
+        else
+            {
+            index += KRoapDomainKey().Length();
+            }
+        domainKeyWithNsPtr.Copy( domainArray[i]->Left( index ) );
+        domainKeyWithNsPtr.Append( KRoapXmlNs() );
+        domainKeyWithNsPtr.Append( domainArray[i]->Right(
+            domainArray[i]->Length() - index ) );
+
+        hMac = CMessageDigestFactory::NewHMACLC( CMessageDigest::ESHA1,
+            *aMacKeys[i] );
+        hMac->Update( domainKeyWithNsPtr );
+
+        hmac_value.Set( hMac->Final() );
+
+        MACLOGLIT( "DomainKeyElement:" )
+        MACLOGHEX( domainKeyWithNsPtr.Ptr(), domainKeyWithNsPtr.Length() )
+        MACLOGLIT( "Calculated HMAC_value:" )
+        MACLOGHEX( hmac_value.Ptr(), hmac_value.Length() )
+        MACLOGLIT( "HMAC_value:" )
+        MACLOGHEX( macArray[i]->Ptr(), macArray[i]->Length() )
+
+        if ( hmac_value.CompareF( *macArray[i] ) != 0 )
+            {
+            // MAC validation failed
+            User::Leave( KErrRightsServerMacFailed );
+            }
+        CleanupStack::PopAndDestroy( 2, domainKeyWithNs ); // hMac, domainKeyWithNs
+        }
+
+    CleanupStack::PopAndDestroy( &macArray );
+    CleanupStack::PopAndDestroy( &domainArray );
+    __UHEAP_MARKEND;
+    MACLOGLITDETAIL( "--> ::VerifyMacL" )
+    return ETrue;
+    }
+
+// ---------------------------------------------------------------------------
+// CRoapStorageSession::VerifyOcspResponsesL()
+// ---------------------------------------------------------------------------
+//
+void CRoapStorageSession::VerifyOcspResponsesL( const RMessage2& aMessage )
+    {
+    MACLOGLITDETAIL( "CRoapStorageSession::VerifyOcspResponsesL -->" )
+
+    const TInt argLen0( IPCGETDESLEN0 );
+    const TInt argLen1( IPCGETDESLEN1 );
+    const TInt argLen2( IPCGETDESLEN2 );
+    SanitizeL( argLen0 );
+    SanitizeL( argLen1 );
+    SanitizeL( argLen2 );
+    User::LeaveIfError( IPCGETDESLEN3 );
+
+    COCSPResponseDecoder* responseDecoder = NULL;
+    COCSPResponse* response = NULL;
+    COCSPResponseCertInfo* certInfo = NULL;
+    COCSPCertID* certID = NULL;
+    CX509Certificate* ocspCert = NULL;
+    TBool result = EFalse;
+    TInt certInfoCount = 0;
+    TInt found = KErrNone;
+    CX509Certificate* riCaCert( NULL );
+
+    TPckg<TBool> package( result );
+
+    RBuf8 readBuf;
+    CleanupClosePushL( readBuf );
+    readBuf.CreateL( Max( argLen0, Max( argLen1, argLen2 ) ) );
+
+    // read arguments
+    IPCREAD0L( readBuf );
+    RPointerArray<HBufC8> ocspResponses( BufferToArrayL( readBuf ) );
+    CleanupResetAndDestroyPushL( ocspResponses );
+    readBuf.Zero();
+
+    IPCREAD1L( readBuf );
+    riCaCert = CX509Certificate::NewLC( readBuf );
+    readBuf.Zero();
+
+    IPCREAD2L( readBuf );
+    RPointerArray<HBufC8> certSerialNums( BufferToArrayL( readBuf ) );
+    CleanupResetAndDestroyPushL( certSerialNums );
+    readBuf.Zero();
+
+    // Check OcspResponses. Only the very first response is checked.
+    if ( ocspResponses.Count() )
+        {
+        responseDecoder = COCSPResponseDecoder::NewL( *ocspResponses[0] );
+        CleanupStack::PushL( responseDecoder );
+        response = responseDecoder->TakeResponse();
+        CleanupStack::PopAndDestroy( responseDecoder );
+        User::LeaveIfNull( response );
+        CleanupStack::PushL( response );
+
+        if ( !response )
+            {
+            MACLOGLIT( "No OCSP certificate!" )
+            User::Leave( KErrArgument );
+            }
+
+        result = VerifyOcspCertChainL( *response, riCaCert, ocspCert );
+
+        CleanupStack::PushL( ocspCert );
+
+        // validate OCSP response signature and
+        // that all the RI cert in the chain is valid (status == good)
+        if ( result )
+            {
+            result = response->VerifySignatureL(
+                ocspCert->PublicKey().KeyData() );
+            }
+
+        if ( result )
+            {
+            certInfoCount = response->CertCount();
+            if ( certSerialNums.Count() && result )
+                {
+                TBool isCertStatusFound = EFalse;
+                for ( TInt i = 0; i < certInfoCount && result; i++ )
+                    {
+                    certInfo = response->CertInfo( i ); // certInfo is owned by response
+                    certID = certInfo->CertID(); // certID is owned by certInfo
+                    found = certSerialNums[0]->Compare(
+                        certID->SerialNumber() );
+                    if ( found == KErrNone )
+                        {
+                        isCertStatusFound = ETrue;
+                        if ( certInfo->Status() != OCSP::EGood )
+                            {
+                            result = EFalse;
+                            }
+                        }
+                    }
+                if ( !isCertStatusFound )
+                    {
+                    result = EFalse;
+                    }
+                }
+            }
+
+        CleanupStack::PopAndDestroy( ocspCert );
+        CleanupStack::PopAndDestroy( response );
+        }
+    CleanupStack::PopAndDestroy( &certSerialNums );
+    CleanupStack::PopAndDestroy( riCaCert );
+    CleanupStack::PopAndDestroy( &ocspResponses );
+    CleanupStack::PopAndDestroy( &readBuf );
+
+#ifdef _ROAP_TESTING
+    if ( result )
+        {
+        MACLOGLIT( "OCSP response verification ok." )
+        }
+    else
+        {
+        MACLOGLIT( "OCSP response verification failed." )
+        }
+#endif
+
+#ifdef _DISABLE_OCSP_CHECK
+    result = ETrue;
+#endif
+    IPCWRITE3L( package );
+    aMessage.Complete( KErrNone );
+    MACLOGLITDETAIL( "--> CRoapStorageSession::VerifyOcspResponsesL" )
+    }
+// ---------------------------------------------------------------------------
+// CRoapStorageSession::GetOcspResponderIdL
+// ---------------------------------------------------------------------------
+//
+void CRoapStorageSession::GetOcspResponderIdL( const RMessage2& aMessage )
+    {
+    MACLOGLITDETAIL( "CRoapStorageSession::GetOCSPResponderIdL -->" )
+    COCSPResponseDecoder* rd( NULL );
+    COCSPResponse* response( NULL );
+
+    RPointerArray<CX509Certificate> certArray;
+    CX509Certificate* cert( NULL );
+    CSHA1* hash( NULL );
+    TInt pos( 0 );
+    TInt size( 0 );
+    TPckg<TInt> sizeArg( size );
+
+    SanitizeL( IPCGETDESLEN0 );
+    User::LeaveIfError( IPCGETDESLEN1 );
+    CleanupResetAndDestroyPushL( certArray );
+
+    HBufC8* riId( HBufC8::NewLC( IPCGETDESLEN0 ) );
+    TPtr8 data( riId->Des() );
+    IPCREAD0L( data );
+    if ( riId->Length() != SHA1_HASH )
+        {
+        User::Leave( KErrArgument );
+        }
+    CDRMRIContext* context( CDRMRIContext::NewLC() );
+    context->SetRIIDL( *riId );
+    CleanupStack::Pop( context );
+    CleanupStack::PopAndDestroy( riId );
+    riId = NULL;
+    CleanupStack::PushL( context );
+    ROAPDB->FetchRightsIssuerContextL( *context );
+
+    const RPointerArray<HBufC8>& ocspResponses( context->OCSPResponse() );
+    // Fetch OCSP response from given RiId
+
+    if ( !ocspResponses.Count() )
+        {
+        User::Leave( KErrRoapDevice );
+        }
+
+    rd = COCSPResponseDecoder::NewL( *ocspResponses[0] );
+    CleanupStack::PushL( rd );
+    response = rd->TakeResponse(); // CRoapEng owns the response now
+    CleanupStack::PopAndDestroy( rd );
+    rd = NULL;
+    CleanupStack::PopAndDestroy( context );
+    context = NULL;
+    User::LeaveIfNull( response );
+
+    CleanupStack::PushL( response );
+    const TPtrC8* ocspCerts( response->SigningCerts() );
+
+    TBool ocspResponseUsable( EFalse );
+    // Get SecureTime from ClockServer
+    TTime secureTime;
+    TInt zone( KTzZulu );
+    DRMClock::ESecurityLevel securityLevel( DRMClock::KInsecure );
+    iLazyClock->GetSecureTimeL( secureTime, zone, securityLevel );
+
+    if ( securityLevel == DRMClock::KSecure )
+        {
+        ocspResponseUsable = ETrue;
+        }
+    // Verify that OCSP responses are not expired
+    for ( TInt i( 0 ); ocspResponseUsable && i < response->CertCount(); ++i )
+        {
+        const TTime* nextUpdate( response->CertInfo( i )->NextUpdate() );
+        if ( !nextUpdate || *nextUpdate <= secureTime || response->CertInfo(
+            i )->RevocationTime() )
+            {
+            ocspResponseUsable = EFalse;
+            }
+        }
+
+    if ( ocspResponseUsable )
+        {
+        while ( ocspCerts && pos < ocspCerts->Length() )
+            {
+            cert = CX509Certificate::NewLC( *ocspCerts, pos );
+            certArray.AppendL( cert );
+            CleanupStack::Pop( cert );
+            }
+        ocspCerts = NULL;
+        }
+    CleanupStack::PopAndDestroy( response );
+    response = NULL;
+
+    if ( cert )
+        {
+        // hash the SubjectPublicKeyInfo element
+        hash = CSHA1::NewL();
+        CleanupStack::PushL( hash );
+        hash->Hash( *cert->DataElementEncoding(
+            CX509Certificate::ESubjectPublicKeyInfo ) );
+
+        delete iPreparedData;
+        iPreparedData = NULL;
+        iPreparedData = hash->Final().AllocL();
+        CleanupStack::PopAndDestroy( hash );
+        size = iPreparedData->Length();
+        MACLOGLIT( "Got OCSP responder" )
+        MACLOGHEX( iPreparedData->Ptr(), iPreparedData->Length() )
+        }
+    CleanupStack::PopAndDestroy( &certArray );
+    IPCWRITE1L( sizeArg );
+    aMessage.Complete( KErrNone );
+    MACLOGLITDETAIL( "--> CRoapStorageSession::GetOCSPResponderIdL" )
+    }
+
+//  End of File