--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/omadrm/drmengine/server/src/DRMDbSession.cpp Thu Dec 17 08:52:27 2009 +0200
@@ -0,0 +1,4928 @@
+/*
+* Copyright (c) 2003-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: This class handles all client requests.
+*
+*/
+
+
+// INCLUDE FILES
+#include <s32file.h>
+#include <f32file.h>
+#include <symmetric.h>
+#include <rijndael.h>
+#include <caf/caf.h>
+#include <x509keys.h>
+#include <asn1dec.h>
+#include <dcfrep.h>
+
+#include <e32math.h>
+#include <utf.h>
+
+#include <SysUtil.h> // Disk space checking
+
+#ifdef RD_MULTIPLE_DRIVE
+#include <DriveInfo.h>
+#endif
+
+#include "Oma2Agent.h"
+#include "DRMPermission.h"
+#include "DRMDbSession.h"
+#include "drmengineclientserver.h"
+#include "DRMRightsServer.h"
+#include "RoapStorageClient.h"
+#include "OmaCrypto.h"
+#include "CmlaCrypto.h"
+#include "DrmKeyStorage.h"
+#include "drmrightsdb.h"
+#include "drmparentstorage.h"
+#include "DrmDomainContext.h"
+#include "DrmRiContext.h"
+#include "drmenginetypedefs.h"
+#include "DRMXOma.h"
+
+#include "DRMNotifier.h"
+#include "DRMEventAddRemove.h"
+#include "DRMEventModify.h"
+#include "DRMRightsCleaner.h"
+#include "DRMActiveOperation.h"
+#include "drmconsume.h"
+#include "drmlog.h"
+#include "drmpointerarray.h"
+#include "base64.h"
+
+#ifdef RD_DRM_METERING
+#include "drmmeteringdbdata.h"
+#endif
+
+// NAMESPACES
+using namespace DRMEngine;
+
+// EXTERNAL DATA STRUCTURES
+// EXTERNAL FUNCTION PROTOTYPES
+// CONSTANTS
+
+// MACROS
+#define REPLAYCACHE reinterpret_cast< CDRMRightsServer* >\
+ (const_cast<CServer2*>(Server()))->ReplayCache()
+#define DRMDB ( ( CDRMRightsServer* )( Server() ) )->Database()
+#ifdef RD_DRM_METERING
+#define METERINGDB reinterpret_cast< CDRMRightsServer* >\
+ (const_cast<CServer2*>(Server()))->MeteringDatabase()
+#endif
+#define RFSSESSION ( ( CDRMRightsServer* )( Server() ) )->FileServerSession()
+#define DRMNOTIFIER ( ( CDRMRightsServer* )( Server() ) )->Notifier()
+#define XOMAHEADER ( ( CDRMRightsServer* )( Server() ) )->XOmaHeaders()
+#define IMEI ( ( CDRMRightsServer* )( Server() ) )->GetIMEIL()
+#define IMSI ( ( CDRMRightsServer* )( Server() ) )->GetIMSIL()
+#define SERVER reinterpret_cast< CDRMRightsServer* >\
+ (const_cast<CServer2*>(Server()))
+
+#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( 3, 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( 3, a )
+#define IPCGETDESLEN0 aMessage.GetDesLength( 0 )
+#define IPCGETDESLEN1 aMessage.GetDesLength( 1 )
+#define IPCGETDESLEN2 aMessage.GetDesLength( 2 )
+#define IPCGETDESLEN3 aMessage.GetDesLength( 3 )
+#define IPCGETDESMAXLEN0 aMessage.GetDesMaxLength( 0 )
+#define IPCGETDESMAXLEN1 aMessage.GetDesMaxLength( 1 )
+#define IPCGETDESMAXLEN2 aMessage.GetDesMaxLength( 2 )
+#define IPCGETDESMAXLEN3 aMessage.GetDesMaxLength( 3 )
+
+// LOCAL CONSTANTS AND MACROS
+
+#ifdef RD_MULTIPLE_DRIVE
+
+_LIT( KDbTempPath, "%c:\\system\\temp\\" );
+_LIT( KTimedReplayCacheFile, "%c:\\private\\101F51F2\\timererc.dat" );
+_LIT( KPlainReplayCacheFile, "%c:\\private\\101F51F2\\plainrc.dat" );
+#ifdef RD_DRM_METERING
+_LIT( KMeteringDataBaseFile, "%c:\\private\\101F51F2\\meterdb.dat" );
+#endif
+
+#else
+
+_LIT( KTimedReplayCacheFile, "c:\\private\\101F51F2\\timererc.dat" );
+_LIT( KPlainReplayCacheFile, "c:\\private\\101F51F2\\plainrc.dat" );
+#ifdef RD_DRM_METERING
+_LIT( KMeteringDataBaseFile, "c:\\private\\101F51F2\\meterdb.dat" );
+#endif
+
+#endif
+
+
+const TInt KMicrosecondsToSecond = 1000000;
+_LIT8( KFLPrefix, "flk" );
+_LIT8( KFLLongPrefix, "flk:flk" );
+
+_LIT8( KFLSuffix, "@localhost" );
+
+// These need to be updated if the DRM Filter / Oma1DcfCreator URI's change
+// IMPORTANT IMPORTANT IMPORTANT
+_LIT8( KDCMUri, "ldf:31415926535@localhost");
+_LIT8( KLDFUri, "flk:flkS60_3_0_Hutchinson_2005");
+
+_LIT8(KTimeStamp, "timeStamp");
+#ifdef RD_DRM_METERING
+_LIT8(KMeteringDelimiter, ":");
+_LIT8(KCRLF, "\r\n" );
+#endif
+
+LOCAL_C const TUint8 KFLPrefixLength = 3;
+const TUint32 KTrustedShutdownClient = 0x10205CB5;
+const TUint32 KAppInstSrv = 0x101F875A;
+
+
+const TInt KSanityDataLengthLow = 0;
+const TInt KSanityDataLengthHigh = 32768;
+
+// MODULE DATA STRUCTURES
+NONSHARABLE_STRUCT( TDeleteFile )
+ {
+ RFs* iFs;
+ TFileName* iFileName;
+ };
+
+// ============================ auto_handde helper class =======================
+//Auto handle for easening handle release on exceptional exit situations
+template<class T> class auto_handle
+ {
+public:
+
+ auto_handle() {}
+ auto_handle(T aHandle) : iHandle( aHandle ) {}
+ auto_handle( auto_handle<T>& aHandle) : iHandle( aHandle.release() ) {}
+ ~auto_handle() { iHandle.Close(); }
+ const T& operator()() const { return iHandle; }
+ T& operator()() { return iHandle; }
+ T get() const { return iHandle; }
+ T release() { T temp = iHandle; iHandle = 0; return temp; }
+
+private:
+ T iHandle;
+ };
+
+// DATA TYPES
+// LOCAL FUNCTION PROTOTYPES
+LOCAL_C void DeleteFile( TAny* aHandle );
+LOCAL_C void DeleteObject( TAny* aObject );
+LOCAL_C TTime EndTime( const TTime& aTime1, const TTime& aTime2 );
+
+// FORWARD DECLARATIONS
+LOCAL_C void ModifyRightsObjectByTimeL( CDRMPermission* aRights,
+ TTimeIntervalMicroSeconds& aChange,
+ TBool aModifyInsertionTime );
+LOCAL_C void ModifyTimesInListL( CDRMPermissionList* aList,
+ TTimeIntervalMicroSeconds& aChange,
+ TBool aModifyInsertionTime );
+
+LOCAL_C void ModifyConstraintByTime( CDRMConstraint* aConstraint,
+ TTimeIntervalMicroSeconds& aChange );
+
+LOCAL_C TPtrC8 ExtractElement( const TDesC8& aRights, const TDesC8& aElement,
+ TInt& aOffset );
+
+LOCAL_C TTime Iso8601ToTime( TDesC8& aTimeString );
+
+// ============================= LOCAL FUNCTIONS ==============================
+
+// -----------------------------------------------------------------------------
+// SanitizeL
+// Performs a sanity check on length parameters
+// -----------------------------------------------------------------------------
+//
+LOCAL_C void SanitizeL( TInt aParam )
+ {
+ if( aParam <= KSanityDataLengthLow || aParam > KSanityDataLengthHigh )
+ {
+ User::Leave(KErrArgument);
+ }
+ }
+
+
+LOCAL_C void ModifyTimesInListL( CDRMPermissionList* aList,
+ TTimeIntervalMicroSeconds& aChange,
+ TBool aModifyInsertionTime )
+ {
+ TInt i = 0;
+
+ // Go through the whole list and run the modification for all objects
+ for( i = 0; i < aList->Count(); i++ )
+ {
+ // Call modification for each rights object in the list
+ ModifyRightsObjectByTimeL( (*aList)[i], aChange, aModifyInsertionTime );
+ }
+ };
+
+LOCAL_C void ModifyRightsObjectByTimeL( CDRMPermission* aRights,
+ TTimeIntervalMicroSeconds& aChange,
+ TBool aModifyInsertionTime )
+ {
+
+ // If original insertion time exists and we want to change it, change it
+ if ( aModifyInsertionTime && aRights->iOriginalInsertTime != Time::NullTTime() )
+ {
+ aRights->iOriginalInsertTime += aChange;
+ }
+
+ if ( aRights->iAvailableRights & ERightsTopLevel )
+ {
+ ModifyConstraintByTime( aRights->iTopLevel, aChange );
+ }
+
+ // If play rights are available, check if they need to be changed
+ if ( aRights->iAvailableRights & ERightsPlay )
+ {
+ ModifyConstraintByTime( aRights->iPlay, aChange );
+ }
+
+ // If display rights are available, check if they need to be changed
+ if ( aRights->iAvailableRights & ERightsDisplay )
+ {
+ ModifyConstraintByTime( aRights->iDisplay, aChange );
+ }
+
+ // If execute rights are available, check if they need to be changed
+ if ( aRights->iAvailableRights & ERightsExecute )
+ {
+ ModifyConstraintByTime( aRights->iExecute, aChange );
+ }
+
+ // If print rights are available, check if they need to be changed
+ if ( aRights->iAvailableRights & ERightsPrint )
+ {
+ ModifyConstraintByTime( aRights->iPrint, aChange );
+ }
+
+ };
+
+LOCAL_C void ModifyConstraintByTime(
+ CDRMConstraint* aConstraint,
+ TTimeIntervalMicroSeconds& aChange )
+ {
+ // if start time exists, modify it
+ if ( aConstraint->iActiveConstraints & EConstraintStartTime )
+ {
+ aConstraint->iStartTime += aChange;
+ }
+
+ // if end time exists, modify it
+ if ( aConstraint->iActiveConstraints & EConstraintEndTime )
+ {
+ aConstraint->iEndTime += aChange;
+ }
+
+ // if activated interval exists, modify it
+ if ( aConstraint->iActiveConstraints & EConstraintInterval &&
+ aConstraint->iIntervalStart != Time::NullTTime() )
+ {
+ aConstraint->iIntervalStart += aChange;
+ }
+ };
+
+LOCAL_C TPtrC8 ExtractElement( const TDesC8& aRights,
+ const TDesC8& aElement,
+ TInt& aOffset )
+ {
+ DRMLOG( _L("CDRMDbSession::ExtractElement") );
+
+ TPtrC8 temp( KNullDesC8 );
+ TInt startPos = ( 0 );
+ TInt endPos = ( 0 );
+ TInt ret( 0 );
+ TInt startLength ( 0 );
+
+ auto_handle< RBuf8 > tagToBeFound;
+ // Must be nonleaving since this function is nonleaving
+ ret = tagToBeFound().Create( aElement.Length() + 3 ); // max "</" aElement ">"
+ if ( ret != KErrNone )
+ {
+ aOffset = -1;
+ return KNullDesC8();
+ }
+
+ // First we try to find the start tag (as localname)
+ tagToBeFound().SetLength( 0 );
+ tagToBeFound().AppendFormat( _L8( "<%S" ), &aElement );
+
+ temp.Set( aRights.Mid( aOffset ) );
+
+ startPos = temp.Find( tagToBeFound() );
+
+ startLength = tagToBeFound().Length();
+ startPos += aOffset;
+ temp.Set( aRights.Mid( startPos + startLength ) );
+
+ // Now find the end of the start tag
+ tagToBeFound().SetLength( 0 );
+ tagToBeFound().Append( _L8( ">" ) ); // '>' as last
+
+ // Define the starting point of the data after the start tag
+ // and skip the '>' mark.
+ startPos = startPos + startLength + temp.Find( tagToBeFound() ) + 1;
+
+ temp.Set( aRights.Mid( startPos ) );
+
+ // Finally find the start of the end tag
+ tagToBeFound().SetLength( 0 );
+ tagToBeFound().AppendFormat( _L8( "</%S" ), &aElement );
+
+ endPos = startPos + temp.Find(tagToBeFound() );
+
+ if ( endPos < startPos )
+ {
+ aOffset = -1;
+ return KNullDesC8();
+ }
+
+ temp.Set( aRights.Mid(startPos, endPos - startPos) );
+
+ aOffset = endPos;
+ DRMLOG2( _L( "Calculated length %d" ), endPos - startPos);
+ DRMLOG( _L( "Extracted element" ) );
+
+ //auto_handle closes and frees allocated resources
+ return temp;
+ };
+
+LOCAL_C TTime Iso8601ToTime( TDesC8& aTimeString )
+ {
+
+ DRMLOG( _L("CDRMDbSession::Iso8601ToTime") );
+
+ TLex8 lex;
+ TInt year = 0;
+ TInt month = 0;
+ TInt day = 0;
+ TInt hour = 0;
+ TInt minute = 0;
+ TInt second = 0;
+ TTime r = Time::NullTTime();
+ TLocale l;
+ TTimeIntervalSeconds offset(l.UniversalTimeOffset());
+
+ if (aTimeString.Length() > 0)
+ {
+ lex = aTimeString;
+ lex.Val(year);
+ lex.Inc();
+ lex.Val(month);
+ lex.Inc();
+ lex.Val(day);
+ lex.Inc();
+ lex.Val(hour);
+ lex.Inc();
+ lex.Val(minute);
+ lex.Inc();
+ lex.Val(second);
+ r = TTime(TDateTime(year, static_cast<TMonth>(month - 1), day - 1,
+ hour, minute, second, 0));
+ if (lex.Get() != 'Z')
+ {
+ r += offset;
+ }
+ }
+ return r;
+ }
+
+#ifdef RD_DRM_METERING
+LOCAL_C HBufC8* CreateMeteringDataL( CDRMPointerArray<CDrmMeteringDbData>* meteringArray )
+ {
+ // Calculate buffer size of cipher data
+ TInt size( sizeof( KCRLF ) );
+ HBufC8* cipherData = NULL;
+ TPtr8 ptr( NULL, 0 );
+
+ _LIT8( KElementStart, "<rawMeteringReportData>");
+ _LIT8( KElementEnd, "</rawMeteringReportData>");
+
+ size = KElementStart().Size() + KElementEnd().Size();
+
+ for( TUint i(0); i < meteringArray->Count(); i++ )
+ {
+ size += sizeof( ( *meteringArray)[i]->iContentId );
+ if ( (*meteringArray)[i]->iParentUid &&
+ (*meteringArray)[i]->iParentUid->Size() )
+ {
+ size += (*meteringArray)[i]->iParentUid->Size() + 1;
+ }
+ switch( (*meteringArray)[i]->iPermission )
+ {
+ case EPlay:
+ size += 4;
+ break;
+ case EView:
+ case EExecute:
+ size += 7;
+ break;
+ case EPrint:
+ size+= 5;
+ break;
+ default:
+ break; // Not a valid permission
+ }
+ size += (*meteringArray)[i]->iContentId->Size();
+ size += sizeof( (*meteringArray)[i]->iAccumulatedTime.Int() / 60 );
+ size += sizeof( (*meteringArray)[i]->iAccumulatedTime.Int() % 60 );
+ if( ( ( *meteringArray)[i]->iAccumulatedTime.Int() % 60 ) < 10 )
+ {
+ size++; //for precending zero for seconds..
+ }
+ size += sizeof( ( *meteringArray)[i]->iCount );
+ size += 4 * sizeof( KMeteringDelimiter ); // ":" -delimiter
+ size += sizeof( KCRLF );
+ }
+
+ cipherData = HBufC8::NewLC( size );
+ ptr.Set( cipherData->Des() );
+ ptr.Append( KElementStart );
+
+ for( TUint i(0); i < meteringArray->Count(); i++ )
+ {
+ ptr.Append( KCRLF );
+ if ( (*meteringArray)[i]->iParentUid &&
+ (*meteringArray)[i]->iParentUid->Size() )
+ {
+ ptr.Append( *(*meteringArray)[i]->iParentUid );
+ ptr.Append( _L(";") );
+ }
+ ptr.Append( *(*meteringArray)[i]->iContentId );
+ ptr.Append( KMeteringDelimiter );
+ switch( (*meteringArray)[i]->iPermission )
+ {
+ case EPlay:
+ ptr.Append( _L("play") );
+ break;
+ case EView:
+ ptr.Append( _L("display") );
+ break;
+ case EExecute:
+ ptr.Append( _L("execute") );
+ break;
+ case EPrint:
+ ptr.Append( _L("print") );
+ break;
+ default:
+ break; // Not a valid permission
+ } // export not supported
+ ptr.Append( KMeteringDelimiter );
+ ptr.AppendNum( (*meteringArray)[i]->iCount );
+ ptr.Append( KMeteringDelimiter );
+ ptr.AppendNum( (*meteringArray)[i]->iAccumulatedTime.Int() / 60 );
+ ptr.Append( KMeteringDelimiter );
+ if( ( ( *meteringArray)[i]->iAccumulatedTime.Int() % 60 ) < 10 )
+ {
+ ptr.AppendNum( 0 ); //precending zero for seconds..
+ }
+ ptr.AppendNum( (*meteringArray)[i]->iAccumulatedTime.Int() % 60 );
+ }
+ ptr.Append( KCRLF );
+ ptr.Append( KElementEnd );
+ CleanupStack::Pop( cipherData );
+ return cipherData;
+ }
+#endif
+
+// ----------------------------------------------------------------------------
+// DeleteFile
+// Deletes the file by TFileName presented by aHandle
+// ----------------------------------------------------------------------------
+//
+void DeleteFile( TAny* aHandle )
+ {
+ __ASSERT_DEBUG( aHandle, User::Panic( _L( "DeleteFile" ), KErrArgument ) );
+ TDeleteFile* handle = reinterpret_cast< TDeleteFile* >( aHandle );
+
+ handle->iFs->Delete( *( handle->iFileName ) );
+ }
+
+// ----------------------------------------------------------------------------
+// DeleteObject
+// Deletes the file by TFileName presented by aHandle
+// ----------------------------------------------------------------------------
+//
+void DeleteObject( TAny* aObject )
+ {
+ __ASSERT_DEBUG( aObject, User::Panic( _L( "DeleteObject" ), KErrArgument ) );
+ MDrmKeyStorage* object = reinterpret_cast< MDrmKeyStorage* >( aObject );
+ delete object;
+ object = NULL;
+ }
+
+
+// ----------------------------------------------------------------------------
+// EndTime
+// Calculate the true end time: pick the smaller one of aTime1 & aTime2,
+// but ignore Time::NullTTime anyhow.
+// ----------------------------------------------------------------------------
+//
+TTime EndTime( const TTime& aTime1, const TTime& aTime2 )
+ {
+ TTime nullTime = Time::NullTTime();
+
+ if ( aTime1 == nullTime )
+ {
+ return aTime2;
+ }
+
+ if ( aTime2 == nullTime )
+ {
+ return aTime1;
+ }
+
+ return Min( aTime1, aTime2 );
+ }
+
+// ============================ MEMBER FUNCTIONS ==============================
+// ----------------------------------------------------------------------------
+// CDRMRightsServer::NewLC
+// Two-phased constructor.
+// ----------------------------------------------------------------------------
+//
+CDRMDbSession* CDRMDbSession::NewL()
+ {
+ CDRMDbSession* self = new( ELeave ) CDRMDbSession();
+
+ CleanupStack::PushL( self );
+ self->ConstructL();
+ CleanupStack::Pop( self );
+ return self;
+ }
+
+// ----------------------------------------------------------------------------
+// CDRMRightsServer::~CDRMDbSession
+// Destructor.
+// ----------------------------------------------------------------------------
+//
+CDRMDbSession::~CDRMDbSession()
+ {
+ DRMLOG( _L( "CDRMDbSession::~" ) );
+ delete iPreparedData;
+ iPreparedData = NULL;
+
+ delete iWidePreparedData;
+ iWidePreparedData = NULL;
+
+ delete iFileName;
+ iFileName = NULL;
+
+ if ( iPendingRequest )
+ {
+ delete iPendingRequest;
+ }
+
+ delete iContentId;
+ iContentId = NULL;
+
+ iClient.Close();
+
+ iCek = KNullDesC8;
+ iCek.FillZ();
+
+ delete iConsume;
+ iRoapClient.Close();
+ }
+
+// ----------------------------------------------------------------------------
+// CDRMRightsServer::CDRMDbSession
+// Default constructor.
+// ----------------------------------------------------------------------------
+//
+CDRMDbSession::CDRMDbSession():
+ iCredentialsChecked(ENotChecked),
+ iContentId(NULL)
+ {
+ iRek.SetLength( 0 );
+ }
+
+
+// ----------------------------------------------------------------------------
+// CDRMDbSession::RoapClient
+// Returns a handle to the Roap client
+// ----------------------------------------------------------------------------
+Roap::RRoapStorageClient& CDRMDbSession::RoapClient()
+ {
+ return iRoapClient;
+ }
+
+// ----------------------------------------------------------------------------
+// CDRMRightsServer::ServiceL
+// Forwards requests from clients to helper methods.
+// ----------------------------------------------------------------------------
+//
+void CDRMDbSession::ServiceL( const RMessage2& aMessage )
+ {
+ DRMLOG( _L( "CDRMDbSession::ServiceL" ) );
+ DRMLOG2( _L( "Message Handle: %08x"), aMessage.Handle() );
+
+ // Close the client before opening a new connection over it to avoid
+ // leaking memory in the kernel side
+ iClient.Close();
+
+ aMessage.ClientL( iClient );
+
+ // This function call is TRAPped by framework, and message is completed
+ // with the error in case of leaving operation.
+ switch ( aMessage.Function() )
+ {
+ case EAddRecord:
+ AddRecordL( aMessage, ENoProtection );
+ break;
+
+ case EAddProtectedRecord:
+ AddRecordL( aMessage, EPublicKey );
+ break;
+
+ case EAddDomainRecord:
+ AddRecordL( aMessage, EDomainKey );
+ break;
+
+ case EGetDbEntry:
+ GetRecordL( aMessage );
+ break;
+
+ case EGetEntryList:
+ GetEntryListL( aMessage );
+ break;
+
+ case EDeleteWithCID:
+ DeleteL( aMessage );
+ break;
+
+ case EDeleteRO:
+ DeleteRecordL( aMessage );
+ break;
+
+ case EExportCIDs:
+ ExportCIDsL( aMessage );
+ break;
+
+ case EGetKey:
+ GetKeyL( aMessage );
+ break;
+
+ case ECheckRights:
+ CheckRightsL( aMessage );
+ break;
+
+ case ECount:
+ CountL( aMessage );
+ break;
+
+ case EDeleteAll:
+ DeleteAllL( aMessage );
+ break;
+
+ case EConsume:
+ ConsumeL( aMessage );
+ break;
+
+ case ECheckConsume:
+ CheckConsumeL( aMessage );
+ break;
+
+ case ECalculatePadding:
+ CalculatePaddingL( aMessage);
+ break;
+
+ case ESecureTime:
+ SecureTimeL( aMessage );
+ break;
+
+ case EGetPreparedData:
+ GetPreparedDataL( aMessage );
+ break;
+
+ case EAddDomainRO:
+ AddDomainROL( aMessage );
+ break;
+
+ case EGetDomainRO:
+ GetDomainROL( aMessage );
+ break;
+
+ case EDeleteDomainRO:
+ DeleteDomainROL( aMessage );
+ break;
+
+ case EIsInCache:
+ IsInCacheL( aMessage );
+ break;
+
+ case EAddToCache:
+ AddToCacheL( aMessage );
+ break;
+
+ case EDecrypt:
+ DecryptL( aMessage );
+ break;
+
+ case EEncrypt:
+ EncryptL( aMessage );
+ break;
+
+ case EInitializeKey:
+ InitializeKeyL( aMessage );
+ break;
+
+ case EInitializeGroupKey:
+ InitializeGroupKeyL( aMessage );
+ break;
+
+ case EGetDomainRoForCid:
+ GetDomainRosForCidL( aMessage );
+ break;
+
+ case EDeleteExpired:
+ DeleteExpiredPermissionsL( aMessage );
+ break;
+
+ case ESetEstimatedArrival:
+ SetEstimatedArrivalL( aMessage );
+ break;
+
+ case EGetEstimatedArrival:
+ GetEstimatedArrivalL( aMessage );
+ break;
+
+ case ESetName:
+ SetNameL( aMessage );
+ break;
+
+ case EGetName:
+ GetNameL( aMessage );
+ break;
+
+ case EGetWideData:
+ GetWideDataL( aMessage );
+ break;
+
+ case ECancel:
+ Cancel( aMessage );
+ break;
+
+ case EGetUdtData:
+ GetUdtDataL( aMessage );
+ break;
+
+ case EInitiateUdt:
+ InitiateUdtL( aMessage );
+ break;
+
+ case EInitOrphanedList:
+ InitExportOrphanedCIDsL( aMessage );
+ break;
+
+ case EGetOrphanedList:
+ ExportOrphanedCIDsL( aMessage );
+ break;
+
+ case EGetFLUri:
+ GetFLUriL( aMessage );
+ break;
+
+ case EEncodeRightsIssuerField:
+ EncodeRightsIssuerL( aMessage );
+ break;
+
+ case EDecodeRightsIssuerField:
+ DecodeRightsIssuerL( aMessage );
+ break;
+
+ case ESetAuthenticationSeed:
+ SetAuthenticationSeedL( aMessage );
+ break;
+
+ case EGetAuthenticationSeed:
+ GetAuthenticationSeedL( aMessage );
+ break;
+
+ case EVerifyMac:
+ VerifyMacL( aMessage );
+ break;
+
+ case EGetSupportedIndividuals:
+ GetSupportedIndividualsL( aMessage );
+ break;
+
+ case EStopWatching:
+ StopWatchingL( aMessage );
+ break;
+
+ case EUnwrapDeviceMacAndRek:
+ UnwrapMacAndRekL( aMessage, EFalse );
+ break;
+
+ case EUnwrapDomainMacAndRek:
+ UnwrapMacAndRekL( aMessage, ETrue );
+ break;
+
+ case EGetRandomData:
+ GetRandomDataL( aMessage );
+ break;
+
+ case EGetMeteringData:
+ GetMeteringDataL( aMessage );
+ break;
+
+ case EDeleteMeteringData:
+ DeleteMeteringDataL( aMessage );
+ break;
+
+ default:
+ DRMLOG( _L( "CDRMDbSession::DispatchL: Invalid command" ) );
+ User::Leave( KErrNotSupported );
+ }
+
+ // The message has already completed successfully.
+ DRMLOG2( _L( "CDRMDbSession::ServiceL ok (%08x)"), aMessage.Handle() );
+ }
+
+// ----------------------------------------------------------------------------
+// CDRMRightsServer::ServiceError
+// Completes the request with given error code if the request is still pending.
+// ----------------------------------------------------------------------------
+//
+void CDRMDbSession::ServiceError( const RMessage2& aMessage, TInt aError )
+ {
+ DRMLOG2( _L( "CDRMDbSession::ServiceError: error %d" ), aError );
+
+ if ( !aMessage.IsNull() )
+ {
+ aMessage.Complete( aError );
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CDRMRightsServer::ConstructL
+// Second phase constructor.
+// -----------------------------------------------------------------------------
+//
+void CDRMDbSession::ConstructL()
+ {
+ iRoapClientConnected = EFalse;
+ }
+
+// -----------------------------------------------------------------------------
+// CDRMRightsServer::AddRecord
+// Get the information from the client, construct a rights object, and add
+// it to the database.
+// -----------------------------------------------------------------------------
+//
+void CDRMDbSession::AddRecordL(
+ const RMessage2& aMessage,
+ TProtectionType aProtection )
+ {
+ DRMLOG( _L( "CDRMDbSession::AddRecordL" ) );
+ //__UHEAP_MARK;
+
+ CDRMPermission* permission = NULL;
+ HBufC8* wrappedcek = NULL;
+ HBufC8* cek = NULL;
+ HBufC8* CID = NULL;
+ HBufC8* rightsData = NULL;
+ TInt size = 0;
+ TPtr8 data( NULL, 0 );
+ TDRMUniqueID UID;
+
+
+ CDRMEventAddRemove* event = CDRMEventAddRemove::NewLC( ERightsObjectRecieved );
+ TRequestStatus status;
+
+ SanitizeL( aMessage.GetDesLength(0) );
+ SanitizeL( aMessage.GetDesLength(1) );
+
+ size = User::LeaveIfError( IPCGETDESLEN1 );
+ rightsData = HBufC8::NewMaxLC( size );
+ data.Set( const_cast< TUint8* >( rightsData->Ptr() ), 0, size );
+ IPCREAD1L( data );
+ permission = CDRMPermission::NewLC();
+ permission->ImportL( data );
+
+ UpdateSecureTime();
+
+ // Determine whether the RO is legal.
+ if ( ( ( permission->iAvailableRights & ERightsPlay ) &&
+ ( Invalid( *permission->iPlay ) ) ) ||
+ ( ( permission->iAvailableRights & ERightsDisplay ) &&
+ ( Invalid( *permission->iDisplay ) ) ) ||
+ ( ( permission->iAvailableRights & ERightsExecute ) &&
+ ( Invalid( *permission->iExecute ) ) ) ||
+ ( ( permission->iAvailableRights & ERightsPrint ) &&
+ ( Invalid( *permission->iPrint ) ) ) ||
+ ( ( permission->iAvailableRights & ERightsTopLevel ) &&
+ ( Invalid( *permission->iTopLevel ) ) ) )
+ {
+ User::Leave( ENoRights );
+ }
+
+ size = User::LeaveIfError( IPCGETDESLEN0 );
+ CID = HBufC8::NewLC( size );
+
+ size = User::LeaveIfError( IPCGETDESLEN2 );
+
+ // Always reserve enough space for a key, if it's 0 then it is, length will be as well.
+ size = size > KDCFKeySize ? size : KDCFKeySize;
+ if( size > KSanityDataLengthHigh )
+ {
+ User::Leave(KErrArgument);
+ }
+ wrappedcek = HBufC8::NewLC( size );
+
+ data.Set( CID->Des() );
+ IPCREAD0L( data );
+
+ data.Set( wrappedcek->Des() );
+ IPCREAD2L( data );
+
+
+ if ( aProtection != ENoProtection )
+ {
+ if(!iRek.Length())
+ {
+ User::Leave(KErrNotReady);
+ }
+
+ cek = OmaCrypto::AesUnwrapL(iRek, *wrappedcek);
+ CleanupStack::PopAndDestroy( wrappedcek );
+ CleanupStack::PushL( cek );
+ }
+ else
+ {
+ cek = wrappedcek;
+ }
+
+ DRMLOG(_L("CEK:"));
+ DRMLOGHEX(( *cek ));
+
+ if ( permission->iOriginalInsertTime == Time::NullTTime() )
+ {
+ permission->iOriginalInsertTime = iTrustedTime;
+ }
+
+ DRMDB.AddDBEntryL( *CID, *permission, *cek, UID );
+
+ // Remove a rights object from the xoma list if it is there
+ RPointerArray<CDRMXOma>& array = XOMAHEADER;
+ TInt i = 0;
+
+ for( ; i < array.Count(); i++ )
+ {
+ // if the content id is found, remove it from the list
+ if( !CID->Compare( array[i]->ContentID() ) )
+ {
+ delete array[i];
+ array.Remove( i );
+ break;
+ }
+ }
+
+ // Write the UID back to the client.
+ data.Set( reinterpret_cast< TUint8* >( &UID ), sizeof( UID ),
+ sizeof( UID ) );
+ IPCWRITE3L( data );
+
+ // Notify clients
+ event->SetContentIDL(CID->Des());
+
+ DRMNOTIFIER.SendEventL(*event,status);
+ User::WaitForRequest(status);
+
+ CleanupStack::PopAndDestroy( 5 ); // cek, CID, permission, data, event
+
+ aMessage.Complete( KErrNone );
+
+ //__UHEAP_MARKEND;
+ DRMLOG( _L( "CDRMDbSession::AddRecordL done" ) );
+ }
+
+// -----------------------------------------------------------------------------
+// CDRMRightsServer::GetRecordL
+// Get record.
+// -----------------------------------------------------------------------------
+//
+void CDRMDbSession::GetRecordL( const RMessage2& aMessage )
+ {
+ DRMLOG( _L( "CDRMDbSession::GetRecordL" ) );
+
+ CDRMPermission* object = NULL;
+ TInt size = 0;
+ TPckg< TInt > package( size );
+ TDRMUniqueID id;
+ HBufC8* CID = NULL;
+ TPtr8 data( reinterpret_cast< TUint8* >( &id ), 0, sizeof( id ) );
+
+ // Cleanup.
+ if ( iPreparedData )
+ {
+ delete iPreparedData;
+ iPreparedData = NULL;
+ }
+
+ IPCREAD2L( data );
+
+ SanitizeL( aMessage.GetDesLength(3) );
+ CID = HBufC8::NewLC( IPCGETDESLEN3 );
+
+ data.Set( CID->Des() );
+ IPCREAD3L( data );
+
+ object = DRMDB.GetDBEntryByContentIDL( *CID, id );
+ CleanupStack::PushL( object );
+
+ // modify the times in the rights object to UI time
+ UpdateSecureTime();
+ TTime currentTime;
+ currentTime.HomeTime();
+ TTimeIntervalMicroSeconds change = currentTime.Int64() - iTrustedTime.Int64();
+ ModifyRightsObjectByTimeL( object, change, ETrue );
+
+ iPreparedData = object->ExportL();
+ size = iPreparedData->Length();
+
+ IPCWRITE0L( package );
+
+ CleanupStack::PopAndDestroy( object );
+ CleanupStack::PopAndDestroy( CID );
+
+ aMessage.Complete( KErrNone );
+
+ DRMLOG( _L( "CDRMDbSession::GetRecordL ok" ) );
+ }
+
+// -----------------------------------------------------------------------------
+// CDRMRightsServer::GetEntryListL
+// Create a temporary file from RPointerArray list the database created.
+// Return the file name to the client. In case of an error, the temporary file
+// is deleted.
+// -----------------------------------------------------------------------------
+//
+void CDRMDbSession::GetEntryListL( const RMessage2& aMessage )
+ {
+ DRMLOG( _L( "CDRMDbSession::GetEntryListL" ) );
+ __UHEAP_MARK;
+
+ TFileName tmpFile( KNullDesC );
+ HBufC8* CID = NULL;
+ TPtr8 data( NULL, 0 );
+
+ SanitizeL( aMessage.GetDesLength(1));
+
+ CID = HBufC8::NewLC( IPCGETDESLEN1 );
+
+
+ TDeleteFile dodeletefile =
+ {
+ &RFSSESSION,
+ &tmpFile
+ };
+
+ CDRMPermissionList* list = CDRMPermissionList::NewLC();
+ list->SetAutoCleanup( ETrue );
+
+ data.Set( CID->Des() );
+ IPCREAD1L( data );
+
+ DRMDB.GetDBEntryByContentIDL( *CID, *list );
+
+ // Exclude domain rights where we are not part of the domain
+ RemoveInvalidPermissionsL( list );
+ if ( list->Count() == 0 )
+ {
+ User::Leave( KErrCANoRights );
+ }
+
+ // modify the times in the rights object to UI time
+ UpdateSecureTime();
+ TTime currentTime;
+ currentTime.HomeTime();
+ TTimeIntervalMicroSeconds change = currentTime.Int64() - iTrustedTime.Int64();
+ ModifyTimesInListL( list, change, ETrue );
+
+ // Delete the file if something goes wrong.
+ TCleanupItem fileCleanup( DeleteFile, &dodeletefile );
+ CleanupStack::PushL( fileCleanup );
+
+ // Convert the list to a permanent file store.
+ ListToFileL( *list, tmpFile );
+
+ // It is virtually impossible to make WriteL to leave in this case,
+ // but anything is still possible...
+ IPCWRITE0L( tmpFile );
+
+ CleanupStack::Pop( &dodeletefile );
+ CleanupStack::PopAndDestroy( 2 ); // list, CID
+
+ __UHEAP_MARKEND;
+
+ // All done
+ aMessage.Complete( KErrNone );
+
+ DRMLOG( _L( "CDRMDbSession::GetEntryListL: ok" ) );
+ }
+
+// -----------------------------------------------------------------------------
+// CDRMRightsServer::DeleteL
+// Delete all rights objects with a certain CID.
+// -----------------------------------------------------------------------------
+//
+void CDRMDbSession::DeleteL( const RMessage2& aMessage )
+ {
+ DRMLOG( _L( "CDRMDbSession::DeleteL" ) );
+ __UHEAP_MARK;
+ TPtr8 data( NULL, 0 );
+
+ // Check for VendorId
+
+ _LIT_SECURITY_POLICY_V0(vidCheck, VID_DEFAULT); // Check Default VID
+ if ( !vidCheck().CheckPolicy(iClient) )
+ {
+ User::Leave( KErrAccessDenied );
+ }
+
+ CDRMEventAddRemove* event = CDRMEventAddRemove::NewLC( ERightsObjectDeletedAll );
+ TRequestStatus status;
+
+ HBufC8* CID = HBufC8::NewLC(
+ User::LeaveIfError( IPCGETDESLEN2 ) );
+
+ data.Set( CID->Des() );
+
+ IPCREAD2L( data );
+
+
+ // Check if deletion is allowed:
+ if( DeleteAllowedL( *CID ) )
+ {
+ DRMDB.DeleteDBEntryL( *CID );
+
+ // Notify
+ event->SetContentIDL(CID->Des());
+
+ DRMNOTIFIER.SendEventL(*event,status);
+ User::WaitForRequest(status);
+ }
+ CleanupStack::PopAndDestroy( 2 ); // CID, event
+ aMessage.Complete( KErrNone );
+ __UHEAP_MARKEND;
+ DRMLOG( _L( "CDRMDbSession::DeleteL ok" ) );
+ }
+
+// -----------------------------------------------------------------------------
+// CDRMRightsServer::DeleteRecordL
+// Delete a single RO.
+// -----------------------------------------------------------------------------
+//
+void CDRMDbSession::DeleteRecordL( const RMessage2& aMessage )
+ {
+ DRMLOG( _L( "CDRMDbSession::DeleteRecordL" ) );
+ __UHEAP_MARK;
+ TDRMUniqueID id;
+
+ _LIT_SECURITY_POLICY_V0(vidCheck, VID_DEFAULT); // Check Default VID
+ if ( !vidCheck().CheckPolicy(iClient) )
+ {
+ User::Leave( KErrAccessDenied );
+ }
+
+ CDRMEventAddRemove* event = CDRMEventAddRemove::NewLC( ERightsObjectDeleted );
+ TRequestStatus status;
+
+ TPtr8 data(
+ reinterpret_cast< TUint8* >( &id ), 0, sizeof( TDRMUniqueID ) );
+
+ HBufC8* CID = HBufC8::NewLC(
+ User::LeaveIfError( IPCGETDESLEN3 ) );
+
+ IPCREAD0L( data );
+
+ data.Set( CID->Des() );
+ IPCREAD3L( data );
+
+ // Check if deletion is allowed:
+ if( DeleteAllowedL( *CID ) )
+ {
+ DRMDB.DeleteDBEntryL( *CID, id );
+
+ event->SetContentIDL( CID->Des() );
+
+ DRMNOTIFIER.SendEventL( *event, status );
+ User::WaitForRequest( status );
+ }
+
+ CleanupStack::PopAndDestroy( 2 ); // CID, event
+
+ aMessage.Complete( KErrNone );
+ __UHEAP_MARKEND;
+ DRMLOG( _L( "CDRMDbSession::DeleteRecordL ok" ) );
+ }
+
+// -----------------------------------------------------------------------------
+// CDRMRightsServer::ExportCIDsL
+// Create a temporary file for rights database to export the CIDs,
+// and write the file name to the client.
+// -----------------------------------------------------------------------------
+//
+void CDRMDbSession::ExportCIDsL( const RMessage2& aMessage )
+ {
+ DRMLOG( _L( "CDRMDbSession::ExportCIDsL" ) );
+ __UHEAP_MARK;
+
+ TFileName fileName( KNullDesC );
+ TDeleteFile deletefile =
+ {
+ &RFSSESSION,
+ &fileName
+ };
+
+ TCleanupItem item( DeleteFile, &deletefile );
+ CleanupStack::PushL( item );
+
+ DRMDB.ExportContentIDListL( fileName );
+
+ IPCWRITE0L( fileName );
+
+ CleanupStack::Pop( &deletefile );
+
+ aMessage.Complete( KErrNone );
+ __UHEAP_MARKEND;
+ DRMLOG( _L( "CDRMDbSession::ExportCIDsL: ok" ) );
+ }
+
+// -----------------------------------------------------------------------------
+// CDRMRightsServer::GetKeyL
+// Ask for a list of rights object based on the given CID.
+// If there is even one rights object which allows the required consuming
+// operation, get the key from database updating the RO if necessary.
+// -----------------------------------------------------------------------------
+//
+void CDRMDbSession::GetKeyL( const RMessage2& aMessage )
+ {
+ DRMLOG( _L( "CDRMDbSession::GetKeyL" ) );
+ __UHEAP_MARK;
+ // If credentials haven't been checked, don't return the key
+ if (iCredentialsChecked == ECheckedAndAllowed)
+ {
+ if (iCek.Length() > 0)
+ {
+ aMessage.Write(2, iCek);
+ aMessage.Complete(KErrNone);
+ }
+ else
+ {
+ aMessage.Complete(KErrCANoRights);
+ }
+ }
+ else
+ {
+ aMessage.Complete(KErrAccessDenied);
+ }
+ __UHEAP_MARKEND;
+ DRMLOG( _L( "CDRMDbSession::GetKeyL: Ok" ) );
+ }
+
+// -----------------------------------------------------------------------------
+// CDRMRightsServer::CheckRightsL
+// Check if there are sufficient rights at the moment. Nothing is changed from
+// the database.
+// -----------------------------------------------------------------------------
+//
+void CDRMDbSession::CheckRightsL( const RMessage2& aMessage )
+ {
+ DRMLOG( _L( "CDRMDbSession::CheckRightsL" ) );
+ TIntent intent;
+ TInt length = 0;
+ CDRMPermission* child = NULL;
+ HBufC8* cid = NULL;
+ HBufC8* buffer = NULL;
+ TPtr8 tmp( NULL, 0, 0 );
+ TInt r = KErrNone;
+ TInt size = 0;
+ TPckg<TInt> package( size );
+ TTime currentTime;
+ TTimeIntervalMicroSeconds change;
+ TUint32 reason = 0;
+ TPckg<TUint32> package2( reason );
+ TInt error = KErrNone;
+ HBufC8* uri = NULL;
+
+ delete iPreparedData;
+ iPreparedData = NULL;
+ intent = static_cast<TIntent>( aMessage.Int0() );
+ DRMLOG2(_L("Intent: %d"), intent);
+
+ if ( intent == EPlay || intent == EView ||
+ intent == EExecute || intent == EPrint || intent == EUnknown )
+ {
+ length = User::LeaveIfError( aMessage.GetDesLength( 1 ) );
+ cid = HBufC8::NewLC( length );
+ tmp.Set( cid->Des() );
+ aMessage.ReadL( 1, tmp );
+ DRMLOG(_L("CID:"));
+ DRMLOGHEX(tmp);
+ error = FindRightsObject( intent, *cid, child, uri, reason );
+ delete uri;
+ uri = NULL; // URI not used anywhere
+
+ // if an error occurs we still need to write the information to the client,
+ // but then we can leave
+ if( error )
+ {
+ aMessage.WriteL( 3, package2 );
+ User::Leave( error );
+ }
+
+ CleanupStack::PopAndDestroy( cid );
+ CleanupStack::PushL( child );
+ }
+ else if ( intent == EInstall || intent == EPeek )
+ {
+ length = User::LeaveIfError( aMessage.GetDesLength( 1 ) );
+ cid = HBufC8::NewLC( length );
+ tmp.Set( cid->Des() );
+ aMessage.ReadL( 1, tmp );
+ DRMLOG(_L("CID:"));
+ DRMLOGHEX(tmp);
+
+ // If we have the key, install and peek always have full rights
+ buffer = DRMDB.GetDecryptionKeyL( *cid );
+ CleanupStack::PopAndDestroy( cid );
+
+ if ( buffer )
+ {
+ delete buffer;
+ child = CDRMPermission::NewL();
+ CleanupStack::PushL( child );
+ child->iAvailableRights = ERightsAll;
+ }
+ else
+ {
+ r = KErrCANoRights;
+ }
+ }
+ else if ( ( intent == EPause || intent == EContinue || intent == EStop ) &&
+ iConsume )
+ {
+ // These intents only make sense if we have an ongoing session
+ child = CDRMPermission::NewL();
+ CleanupStack::PushL( child );
+ child->DuplicateL( iConsume->GetChild() );
+ }
+ else
+ {
+ r = KErrArgument;
+ }
+
+ if ( child )
+ {
+ UpdateSecureTime();
+ currentTime.HomeTime();
+ change = currentTime.Int64() - iTrustedTime.Int64();
+ ModifyRightsObjectByTimeL( child, change, ETrue );
+ iPreparedData = child->ExportL();
+ size = iPreparedData->Length();
+ aMessage.WriteL( 2, package );
+ CleanupStack::PopAndDestroy( child );
+ }
+
+ aMessage.Complete( r );
+
+ DRMLOG2( _L( "CDRMDbSession::CheckRightsL: ok (%d)" ), r );
+ }
+
+// -----------------------------------------------------------------------------
+// CDRMRightsServer::CountL
+// Tell the client how many ROs there are.
+// -----------------------------------------------------------------------------
+//
+void CDRMDbSession::CountL( const RMessage2& aMessage )
+ {
+ DRMLOG( _L( "CDRMDbSession::CountL" ) );
+ __UHEAP_MARK;
+ TInt count = DRMDB.GetAmountOfRightsObjectsL();
+
+ TPtr8 data( reinterpret_cast< TUint8* >( &count ),
+ sizeof( TInt ),
+ sizeof( TInt ) );
+
+ IPCWRITE0L( data );
+
+ aMessage.Complete( KErrNone );
+ __UHEAP_MARKEND;
+ DRMLOG( _L( "CDRMDbSession::CountL: ok" ) );
+ }
+
+// -----------------------------------------------------------------------------
+// CDRMRightsServer::DeleteAll
+// Delete all ROs.
+// -----------------------------------------------------------------------------
+//
+void CDRMDbSession::DeleteAllL( const RMessage2& aMessage )
+ {
+ DRMLOG( _L( "CDRMDbSession::DeleteAllL" ) );
+
+ User::LeaveIfError( VerifyCredentials(NULL, NULL, EUnknown) );
+ if( iCredentialsChecked == ECheckedAndDenied )
+ {
+ User::Leave( KErrPermissionDenied );
+ }
+
+ //__UHEAP_MARK;
+
+ DRMDB.DeleteDBL();
+
+ REPLAYCACHE.Close();
+
+#ifndef RD_MULTIPLE_DRIVE
+
+ #ifdef RD_DRM_METERING
+ METERINGDB.Close();
+ RFSSESSION.Delete( KMeteringDataBaseFile );
+ METERINGDB.InitL( KMeteringDataBaseFile );
+ #endif
+
+ RFSSESSION.Delete( KTimedReplayCacheFile );
+ RFSSESSION.Delete( KPlainReplayCacheFile );
+
+ REPLAYCACHE.InitL( KTimedReplayCacheFile, KPlainReplayCacheFile );
+
+#else //RD_MULTIPLE_DRIVE
+
+ TFileName tempPath;
+ TFileName tempPath2;
+ TInt driveNumber( -1 );
+ TChar driveLetter;
+ DriveInfo::GetDefaultDrive( DriveInfo::EDefaultSystem, driveNumber );
+
+ RFSSESSION.DriveToChar( driveNumber, driveLetter );
+
+ #ifdef RD_DRM_METERING
+ tempPath.Format( KMeteringDataBaseFile, (TUint)driveLetter );
+
+ METERINGDB.Close();
+ RFSSESSION.Delete( tempPath );
+ METERINGDB.InitL( tempPath );
+ #endif
+
+ tempPath.Format( KTimedReplayCacheFile, (TUint)driveLetter );
+ tempPath2.Format( KPlainReplayCacheFile, (TUint)driveLetter );
+
+ RFSSESSION.Delete( tempPath );
+ RFSSESSION.Delete( tempPath2 );
+
+ REPLAYCACHE.InitL( tempPath, tempPath2 );
+
+#endif
+
+ if ( !iRoapClientConnected )
+ {
+ User::LeaveIfError( iRoapClient.Connect() );
+ iRoapClientConnected = ETrue;
+ }
+
+ iRoapClient.DeleteAllL();
+
+ aMessage.Complete( KErrNone );
+ //__UHEAP_MARKEND;
+ DRMLOG( _L( "CDRMDbSession::DeleteAllL ok" ) );
+ }
+
+// -----------------------------------------------------------------------------
+// CDRMRightsServer::ListToFileL
+// Convert the list to a file representation.
+// -----------------------------------------------------------------------------
+//
+void CDRMDbSession::ListToFileL( RPointerArray< CDRMPermission >& aList,
+ TFileName& aFile )
+ {
+ __UHEAP_MARK;
+ DRMLOG( _L( "CDRMDbSession::ListToFileL" ) );
+
+ TInt count( 0 );
+
+
+ RFileWriteStream fileStream;
+
+#ifndef RD_MULTIPLE_DRIVE
+
+ User::LeaveIfError(
+ fileStream.Temp( RFSSESSION,
+ KDRMDbTempPath,
+ aFile,
+ EFileWrite | EFileStream ) );
+
+#else //RD_MULTIPLE_DRIVE
+
+ TInt driveNumber( -1 );
+ TChar driveLetter;
+ DriveInfo::GetDefaultDrive( DriveInfo::EDefaultSystem, driveNumber );
+
+ RFSSESSION.DriveToChar( driveNumber, driveLetter );
+
+ TFileName dbTempPath;
+ dbTempPath.Format( KDbTempPath, (TUint)driveLetter );
+
+ User::LeaveIfError(
+ fileStream.Temp( RFSSESSION,
+ dbTempPath,
+ aFile,
+ EFileWrite | EFileStream ) );
+
+#endif
+
+ CleanupClosePushL( fileStream );
+
+ TInt size( sizeof( TUint32 ) ); // streams store also other info there.
+
+ for( count = 0; count < aList.Count(); count++ )
+ {
+ size += aList[ count ]->Size();
+ }
+
+ // Reset count variable:
+ count = 0;
+
+#ifndef RD_MULTIPLE_DRIVE
+
+ if ( SysUtil::DiskSpaceBelowCriticalLevelL( &RFSSESSION,
+ size,
+ EDriveC ) )
+
+#else //RD_MULTIPLE_DRIVE
+
+ if ( SysUtil::DiskSpaceBelowCriticalLevelL( &RFSSESSION,
+ size,
+ driveNumber ) )
+
+#endif
+ {
+ DRMLOG( _L( "CDRMDbSession::ListToFileL: KErrDiskFull" ) );
+ User::Leave( KErrDiskFull );
+ }
+
+ fileStream.WriteInt32L( aList.Count() );
+
+ // Write the whole stuff into the file.
+ // URIs are ignored. No use to put them to file (always the same
+ // and the client knows it already).
+ while( count < aList.Count() )
+ {
+ aList[ count ]->ExternalizeL( fileStream );
+ ++count;
+ }
+
+ fileStream.CommitL();
+
+ CleanupStack::PopAndDestroy( &fileStream );
+
+ DRMLOG( _L( "CDRMDbSession::ListToFileL: ok" ) );
+ __UHEAP_MARKEND;
+ }
+
+
+// -----------------------------------------------------------------------------
+// CDRMRightsServer::FindRightsObjectL
+// Try to locate the best RO from the given list which allows consuming of
+// content.
+// If end time is defined or an interval activated, the smallest endtime
+// is always chosen first.
+// -----------------------------------------------------------------------------
+//
+void CDRMDbSession::FindRightsObjectL( TIntent aIntent,
+ const TDesC8& aURI,
+ CDRMPermission*& aChild,
+ HBufC8*& aUsedURI,
+ TUint32& aReason )
+ {
+ DRMLOG( _L( "CDRMDbSession::FindRightsObjectL" ) );
+ TInt res = KErrNotFound;
+
+ if ( aUsedURI || aChild )
+ {
+ // Check that return parameters are null initially.
+ User::Leave( KErrArgument );
+ }
+
+ CDRMPermissionList *perms = CDRMPermissionList::NewLC();
+ TTime time;
+
+ perms->SetAutoCleanup( ETrue );
+ DRMDB.GetDBEntryByContentIDL( aURI , *perms );
+
+ UpdateSecureTime();
+
+ if ( iSecureTime )
+ {
+ time = iTrustedTime;
+ }
+ else
+ {
+ time = Time::NullTTime();
+ }
+
+ if ( aIntent == EPeek || aIntent == EInstall )
+ {
+ // There is at least one RO available.
+ // Use any RO, whether they are valid or not.
+ // Pick the first RO in the list.
+
+ aChild = (*perms)[0];
+ (*perms).Remove( 0 );
+
+ CleanupStack::PopAndDestroy( perms );
+ return;
+ }
+ else if ( aIntent == EUnknown )
+ {
+ // Pick one that works, no matter what the intent is
+ for ( TInt i = 0; res == KErrNotFound && i < perms->Count(); i++ )
+ {
+ if ( (*perms)[i]->Valid( time, IMSI, aReason ) )
+ {
+ res = i;
+ }
+ }
+ if ( res != KErrNotFound )
+ {
+ aChild = (*perms)[res];
+ perms->Remove( res );
+ }
+ else
+ {
+ User::Leave( KErrCANoPermission );
+ }
+ }
+ else
+ {
+ res = FindBestROsL( *perms, aURI, aIntent, aUsedURI, aReason );
+ if ( res >= 0 )
+ {
+ aChild = (*perms)[res];
+ perms->Remove( res );
+ }
+ else
+ {
+ User::Leave( KErrCANoPermission );
+ }
+ }
+ CleanupStack::PopAndDestroy( perms );
+ }
+
+
+// -----------------------------------------------------------------------------
+// CDRMRightsServer::FindRightsObject
+// Try to locate the best RO from the given list which allows consuming of
+// content.
+// If end time is defined or an interval activated, the smallest endtime
+// is always chosen first.
+// -----------------------------------------------------------------------------
+//
+TInt CDRMDbSession::FindRightsObject( TIntent aIntent,
+ const TDesC8& aURI,
+ CDRMPermission*& aChild,
+ HBufC8*& aUsedURI,
+ TUint32& aReason )
+ {
+ DRMLOG( _L( "CDRMDbSession::FindRightsObject" ) );
+ TInt error = KErrNone;
+
+ TRAP( error, FindRightsObjectL( aIntent, aURI, aChild, aUsedURI, aReason ) );
+ if ( ( error == KErrCANoRights || error == KErrCANoPermission ) &&
+ PendingRights(aURI) )
+ {
+ error = KErrCAPendingRights;
+ }
+ return error;
+ }
+
+// -----------------------------------------------------------------------------
+// CDRMDbSession::CheckConsumeL
+// Check if Consume is possible
+// -----------------------------------------------------------------------------
+//
+void CDRMDbSession::CheckConsumeL( const RMessage2& aMessage )
+ {
+ DRMLOG( _L( "CDRMDbSession::CheckConsumeL" ) );
+
+ __UHEAP_MARK;
+
+ HBufC8* CID = NULL;
+ TPtr8 cid( NULL, 0, 0 );
+ TInt length = 0;
+ TIntent intent;
+ TUint32 reason = 0;
+
+ length = User::LeaveIfError( IPCGETDESLEN1 );
+ CID = HBufC8::NewLC( length );
+ cid.Set( CID->Des() );
+ IPCREAD1L( cid );
+ intent = static_cast<TIntent>(aMessage.Int0());
+
+ // Check only intents which are actually consuming something. All others
+ // always succeed, because CheckConsume is called by default when a file
+ // is opened.
+ if ( intent == EPlay || intent == EView ||
+ intent == EExecute || intent == EPrint || intent == EUnknown )
+ {
+ // Count constraints are valid for the duration of the
+ // session after they have been consumed earlier
+ if ( !( iConsume && iConsume->CountConstraintActive() ||
+ SERVER->HasActiveCountConstraint( *CID ) ) )
+ {
+ CDRMPermission* child( NULL );
+ HBufC8* uri( NULL );
+ TInt error( FindRightsObject( intent, *CID, child, uri, reason ) );
+ delete child;
+ delete uri;
+ User::LeaveIfError( error );
+ }
+ }
+/* Enable this code as soon as clients use EUnknown, and it is safe to fail
+ when no key is available
+ else if ( intent == EPeek || EInstall )
+ {
+ // We need at least the key for peek and install. This will leave if no
+ // key is there.
+ HBufC8* key = DRMDB.GetDecryptionKeyL( *CID );
+ delete key;
+ }
+*/
+
+ CleanupStack::PopAndDestroy( CID );
+ aMessage.Complete( KErrNone );
+ __UHEAP_MARKEND;
+ DRMLOG( _L( "CDRMDbSession::CheckConsumeL: ok" ) );
+ }
+
+// -----------------------------------------------------------------------------
+// CDRMDbSession::ConsumeL
+// Consume the right and register the consumption.
+// -----------------------------------------------------------------------------
+//
+void CDRMDbSession::ConsumeL( const RMessage2& aMessage )
+ {
+ DRMLOG( _L( "CDRMDbSession::ConsumeL" ) );
+
+ const TIntent intent = static_cast<TIntent>(aMessage.Int0());
+ HBufC8* CID = NULL;
+ TInt length = 0;
+ TPtr8 cid( NULL, 0, 0 );
+
+ length = User::LeaveIfError( IPCGETDESLEN1 );
+
+ CID = HBufC8::NewLC( length );
+
+ cid.Set( CID->Des() );
+ IPCREAD1L( cid );
+
+ if ( intent != EUnknown )
+ {
+ if ( intent == EPeek || intent == EInstall )
+ {
+ User::LeaveIfError( VerifyCredentials( CID, NULL, intent ) );
+ }
+ else
+ {
+ if ( intent == EPlay ||
+ intent == EView ||
+ intent == EExecute ||
+ intent == EPrint ||
+ intent == EStop )
+ {
+
+ if ( iConsume )
+ {
+ delete iConsume;
+ iConsume = NULL;
+ }
+ if ( intent != EStop )
+ {
+ CDRMConsume* consume( NULL );
+ consume = CDRMConsume::NewLC( *this, *CID, NULL );
+ consume->HandleL( intent );
+ CleanupStack::Pop( consume );
+ iConsume = consume;
+ }
+ }
+ else
+ {
+ if ( !iConsume )
+ {
+ User::Leave( KErrNotReady );
+ }
+
+ if ( intent == EPause )
+ {
+ iConsume->Pause();
+ }
+ else if ( intent == EContinue )
+ {
+ iConsume->ContinueL();
+ }
+ else
+ {
+ iConsume->Stop();
+ }
+ }
+ }
+ }
+ else
+ {
+ // None of the other intents are allowed here, fail
+ User::Leave( KErrArgument );
+ }
+
+
+ CleanupStack::PopAndDestroy( CID );
+ aMessage.Complete( KErrNone );
+ DRMLOG( _L( "CDRMDbSession::ConsumeL: ok" ) );
+ }
+
+// -----------------------------------------------------------------------------
+// CDRMDbSession::CalculatePaddingL
+//
+// -----------------------------------------------------------------------------
+//
+void CDRMDbSession::CalculatePaddingL( const RMessage2& aMessage )
+ {
+ __UHEAP_MARK;
+ DRMLOG( _L( "CDRMDbSession::CalculatePaddingL" ) );
+
+ CAESDecryptor* decryptor( NULL );
+ TInt i( 0 );
+
+ TBuf8<KDCFKeySize * 2> data;
+ TBuf8<KDCFKeySize> iv;
+ TBuf8<KDCFKeySize> block;
+ TPtr8 tmp( NULL, 0, 0 );
+
+ aMessage.ReadL( 0, data );
+
+ // Check that the data we read is actually of the proper length
+ if( data.Length() != KDCFKeySize*2 )
+ {
+ User::Leave(KErrArgument);
+ }
+
+ iv.Copy(data.Left(KDCFKeySize));
+ block.Copy(data.Right(KDCFKeySize));
+
+ if( iCek.Length() != KDRMKeyLength )
+ {
+ User::Leave(KErrNotReady);
+ }
+
+ decryptor = CAESDecryptor::NewLC(iCek);
+ decryptor->Transform(block);
+ CleanupStack::PopAndDestroy( decryptor );
+
+ for (i = 0; i < KDCFKeySize; i++)
+ {
+ block[i] ^= iv[i];
+ }
+
+ if ( block[ KDCFKeySize - 1 ] > 0 && block[ KDCFKeySize - 1 ] <= 16 )
+ {
+ for ( i = KDCFKeySize - block[ KDCFKeySize - 1 ];
+ i < KDCFKeySize - 1;
+ ++i )
+ {
+ if ( block[ i ] != block[ KDCFKeySize - 1 ] )
+ {
+ User::Leave( KErrCorrupt );
+ }
+ }
+
+ aMessage.Complete( block[ KDCFKeySize - 1 ] );
+ DRMLOG2( _L( "CDRMDbSession::CalculatePaddingL: Padding = %d" ),
+ block[ KDCFKeySize - 1 ] );
+
+ return;
+ }
+
+ User::Leave( KErrCorrupt );
+
+__UHEAP_MARKEND;
+ }
+
+// -----------------------------------------------------------------------------
+// CDRMDbSession::SecureTimeL
+// returns the secure time
+// -----------------------------------------------------------------------------
+//
+void CDRMDbSession::SecureTimeL( const RMessage2& aMessage )
+ {
+ DRMLOG( _L( "CDRMDbSession::SecureTimeL" ) );
+ __UHEAP_MARK;
+ TPckgBuf< TInt64 > time;
+ TPckg< TBool > levelPckg( iSecureTime );
+
+ UpdateSecureTime();
+
+ time() = iTrustedTime.Int64();
+
+ IPCWRITE0L( time );
+ IPCWRITE1L( levelPckg );
+
+ aMessage.Complete( KErrNone );
+ __UHEAP_MARKEND;
+ DRMLOG( _L( "CDRMDbSession::SecureTime: ok" ) );
+ }
+
+// -----------------------------------------------------------------------------
+// CDRMDbSession::EncryptL
+//
+// -----------------------------------------------------------------------------
+//
+void CDRMDbSession::EncryptL(const RMessage2& aMessage)
+ {
+ TBuf8<KDCFKeySize> iv;
+ HBufC8* data = NULL;
+ TPtr8 ptr(NULL, 0, 0);
+ TBool addPadding;
+ __UHEAP_MARK;
+
+ DRMLOG(_L("CDRMDbSession::EncryptL"));
+
+ if( iCek.Length() != KDRMKeyLength )
+ {
+ User::Leave( KErrNotReady );
+ }
+
+ SanitizeL( aMessage.GetDesLength(0) );
+
+ addPadding = aMessage.Int2() != 0 ? ETrue : EFalse;
+ aMessage.Read(0, iv);
+ data = HBufC8::NewLC(aMessage.GetDesMaxLength(1));
+ ptr.Set(data->Des());
+ aMessage.Read(1, ptr);
+
+ AesEncryptL( iCek, iv, addPadding, ptr );
+
+ aMessage.Write(1, ptr);
+ aMessage.Complete(KErrNone);
+ CleanupStack::PopAndDestroy( data );
+ __UHEAP_MARKEND;
+ DRMLOG(_L("CDRMDbSession::EncryptL: Ok"));
+ }
+
+// -----------------------------------------------------------------------------
+// CDRMDbSession::DecryptL
+// Decrypt data and return it to the caller, using the CEK for this session
+// -----------------------------------------------------------------------------
+//
+void CDRMDbSession::DecryptL(const RMessage2& aMessage)
+ {
+ DRMLOG(_L("CDRMDbSession::DecryptL"));
+
+ // If credentials haven't been checked, do it now, check for expired rights
+ if (iCredentialsChecked == ECheckedAndDenied ||
+ iCredentialsChecked == ENotChecked &&
+ VerifyCredentials(iContentId, NULL, EUnknown) != KErrNone)
+ {
+ DRMLOG(_L("Decrypt failed: untrusted client"));
+ aMessage.Complete(KErrAccessDenied);
+ }
+ else if ( iConsume && iConsume->IsExpired() )
+ {
+ DRMLOG(_L("Decrypt failed: rights expired"));
+ aMessage.Complete(KErrCANoPermission);
+ }
+ else
+ {
+ if (iCek.Length() > 0)
+ {
+ TBuf8<KDCFKeySize> iv;
+ HBufC8* data = NULL;
+ TPtr8 ptr(NULL, 0, 0);
+ TBool removePadding;
+
+ removePadding = aMessage.Int2() != 0 ? ETrue : EFalse;
+ aMessage.Read(0, iv);
+
+ data = HBufC8::NewMaxLC(aMessage.GetDesMaxLength(1));
+
+ ptr.Set(data->Des());
+ aMessage.Read(1, ptr);
+
+ AesDecryptL( iCek,
+ iv,
+ removePadding,
+ ptr );
+
+ aMessage.Write(1, ptr);
+ aMessage.Complete(KErrNone);
+ CleanupStack::PopAndDestroy( data );
+ }
+ else
+ {
+ aMessage.Complete(KErrCANoRights);
+ }
+ }
+ DRMLOG(_L("CDRMDbSession::DecryptL: Ok"));
+ }
+
+// -----------------------------------------------------------------------------
+// CDRMDbSession::InitializeKeyL
+// Initialize the CEK for this session based on the content ID. Also sets the
+// content ID for later usage.
+// -----------------------------------------------------------------------------
+//
+void CDRMDbSession::InitializeKeyL( const RMessage2& aMessage )
+ {
+ TPtr8 tmp(NULL, 0, 0);
+ HBufC8* key = NULL;
+ TInt error = KErrNone;
+
+ DRMLOG( _L( "CDRMDbSession::InitializeKeyL"));
+ if ( iContentId )
+ {
+ delete iContentId;
+ iContentId = NULL;
+ }
+ iContentId = HBufC8::NewL( User::LeaveIfError( IPCGETDESLEN0 ) );
+ tmp.Set( iContentId->Des() );
+ IPCREAD0L( tmp );
+
+ __UHEAP_MARK;
+ TRAP( error, key = DRMDB.GetDecryptionKeyL( *iContentId ) );
+ if ( ( error == KErrCANoRights || error == KErrCANoPermission ) &&
+ PendingRights( *iContentId , EFalse ) )
+ {
+ error = KErrCAPendingRights;
+ }
+
+ if ( error == KErrNone )
+ {
+ iCek.Copy( *key );
+ delete key;
+ aMessage.Complete( KErrNone );
+ }
+ else
+ {
+ aMessage.Complete( error );
+ }
+ __UHEAP_MARKEND;
+ DRMLOG2( _L( "CDRMDbSession::InitializeKeyL: %d" ), error );
+ }
+
+// -----------------------------------------------------------------------------
+// CDRMDbSession::InitializeGroupKeyL
+// Initialize the CEK for this session from a given group key
+// -----------------------------------------------------------------------------
+//
+void CDRMDbSession::InitializeGroupKeyL(const RMessage2& aMessage )
+ {
+ HBufC8* groupId = NULL;
+ HBufC8* groupKey = NULL;
+ TPtr8 tmp(NULL, 0, 0 );
+ HBufC8* key = NULL;
+ TRequestStatus status;
+ CAESDecryptor* aes = NULL;
+ CModeCBCDecryptor* cbc = NULL;
+
+ __UHEAP_MARK;
+
+ SanitizeL( aMessage.GetDesLength(0) );
+ SanitizeL( aMessage.GetDesLength(1) );
+
+ DRMLOG(_L("CDRMDbSession::InitializeGroupKeyL"));
+ if (aMessage.Int2() == EMethodAES_128_CBC)
+ {
+ groupId = HBufC8::NewLC(aMessage.GetDesLength(0));
+ tmp.Set(groupId->Des());
+ aMessage.Read(0, tmp);
+
+ groupKey = HBufC8::NewLC(aMessage.GetDesLength(1));
+ tmp.Set(groupKey->Des());
+ aMessage.Read(1, tmp);
+
+ key = DRMDB.GetDecryptionKeyL(*groupId);
+ CleanupStack::PushL(key);
+
+ if ( key )
+ {
+ aes = CAESDecryptor::NewLC(*key);
+ cbc = CModeCBCDecryptor::NewL(aes, groupKey->Left(KDCFKeySize));
+ CleanupStack::Pop( aes );
+ iCek.Copy(groupKey->Mid(KDCFKeySize, KDCFKeySize));
+ cbc->Transform(iCek);
+ delete cbc;
+ aMessage.Complete(KErrNone);
+ }
+ else
+ {
+ aMessage.Complete(KErrCANoRights);
+ }
+ CleanupStack::PopAndDestroy(3); // key, groupKey, groupId
+ }
+ else
+ {
+ aMessage.Complete(KErrNotSupported);
+ }
+
+ __UHEAP_MARKEND;
+ DRMLOG(_L("CDRMDbSession::InitializeGroupKeyL: Ok"));
+ }
+
+// -----------------------------------------------------------------------------
+// CDRMDbSession::GetPreparedDataL
+// Returns data which has been allocated before
+// -----------------------------------------------------------------------------
+//
+void CDRMDbSession::GetPreparedDataL( const RMessage2& aMessage )
+ {
+ DRMLOG( _L( "CDRMDbSession::GetPreparedDataL" ) );
+
+ if( !iPreparedData )
+ {
+ User::Leave( KErrNotReady );
+ }
+
+ if( iPreparedData->Length() > aMessage.GetDesMaxLength(0) )
+ {
+ User::Leave(KErrArgument);
+ }
+
+ IPCWRITE0L( iPreparedData->Des() );
+
+ aMessage.Complete( KErrNone );
+ DRMLOG( _L( "CDRMDbSession::GetPreparedDataL: ok" ) );
+
+ // Delete the data
+ delete iPreparedData;
+ iPreparedData = NULL;
+ }
+
+// -----------------------------------------------------------------------------
+// CDRMDbSession::IsInCacheL
+// Checks whether the given entry is in replay cache or not.
+// -----------------------------------------------------------------------------
+void CDRMDbSession::IsInCacheL( const RMessage2& aMessage )
+ {
+ DRMLOG( _L( "CDRMDbSession::IsInCacheL" ) );
+
+ HBufC8* buf = HBufC8::NewLC(
+ User::LeaveIfError( IPCGETDESLEN0 ) );
+
+ TPckgBuf< TBool > res;
+ TPtr8 data( buf->Des() );
+
+ IPCREAD0L( data );
+
+ if ( aMessage.Ptr1() )
+ {
+ TPckgBuf< TTime > time;
+
+ IPCREAD1L( time );
+
+ res = REPLAYCACHE.InCacheL( *buf, time() );
+ }
+ else
+ {
+ res = REPLAYCACHE.InCacheL( *buf );
+ }
+
+ CleanupStack::PopAndDestroy( buf );
+
+ IPCWRITE2L( res );
+
+ aMessage.Complete( KErrNone );
+
+ DRMLOG( _L( "CDRMDbSession::IsInCache ok" ) );
+ }
+
+// -----------------------------------------------------------------------------
+// CDRMDbSession::AddToCacheL
+// Adds an entry to replay cache.
+// -----------------------------------------------------------------------------
+void CDRMDbSession::AddToCacheL( const RMessage2& aMessage )
+ {
+ DRMLOG( _L( "CDRMDbSession::AddToCacheL" ) );
+
+ HBufC8* buf = NULL;
+
+ UpdateSecureTime();
+
+ if ( !iSecureTime )
+ {
+ // DoSomething!
+ }
+
+ buf = HBufC8::NewLC(
+ User::LeaveIfError( IPCGETDESLEN0 ) );
+
+ TPtr8 data( buf->Des() );
+
+ IPCREAD0L( data );
+
+ if ( aMessage.Ptr1() )
+ {
+ TPckgBuf< TTime > time;
+
+ IPCREAD1L( time );
+
+ REPLAYCACHE.AddL( *buf, time(), iTrustedTime );
+ }
+
+ else
+ {
+ REPLAYCACHE.AddL( *buf, iTrustedTime );
+ }
+
+ CleanupStack::PopAndDestroy( buf );
+
+ aMessage.Complete( KErrNone );
+
+ DRMLOG( _L( "CDRMDbSession::AddToCacheL ok" ) );
+ }
+
+// -----------------------------------------------------------------------------
+// CDRMDbSession::AddDomainROL
+// Add domain ro xml data
+// -----------------------------------------------------------------------------
+//
+void CDRMDbSession::AddDomainROL( const RMessage2& aMessage )
+ {
+ DRMLOG( _L( "CDRMDbSession::AddDomainROL" ) );
+ __UHEAP_MARK;
+ HBufC8* RoId = NULL;
+ HBufC8* XMLData = NULL;
+ TInt size = 0;
+ TPtr8 data( NULL, 0 );
+
+ size = User::LeaveIfError( IPCGETDESLEN0 );
+ RoId = HBufC8::NewLC( size );
+
+ size = User::LeaveIfError( IPCGETDESLEN1 );
+ XMLData = HBufC8::NewLC( size );
+
+ data.Set( RoId->Des() );
+ IPCREAD0L( data );
+
+ data.Set( XMLData->Des() );
+ IPCREAD1L( data );
+
+ DRMDB.AddDomainROL( *RoId, *XMLData );
+
+ CleanupStack::PopAndDestroy( 2 ); // RoId, XMLData
+
+ aMessage.Complete( KErrNone );
+ __UHEAP_MARKEND;
+ DRMLOG( _L( "CDRMDbSession::AddDomainROL done" ) );
+ };
+
+// -----------------------------------------------------------------------------
+// CDRMDbSession::GetDomainROL
+// Get domain ro xml data
+// -----------------------------------------------------------------------------
+//
+void CDRMDbSession::GetDomainROL( const RMessage2& aMessage )
+ {
+ DRMLOG( _L( "CDRMDbSession::GetDomainROL" ) );
+
+ TInt size = 0;
+ TPckg< TInt > package( size );
+ HBufC8* RoId = NULL;
+ TPtr8 data(NULL, 0);
+
+ // Cleanup.
+ if ( iPreparedData )
+ {
+ delete iPreparedData;
+ iPreparedData = NULL;
+ }
+
+ size = User::LeaveIfError( IPCGETDESLEN1 );
+
+ RoId = HBufC8::NewLC( size );
+
+ data.Set( RoId->Des() );
+ IPCREAD1L( data );
+
+ iPreparedData = DRMDB.GetDomainROL( *RoId );
+
+ size = iPreparedData->Length();
+
+ IPCWRITE0L( package );
+
+ CleanupStack::PopAndDestroy( RoId );
+
+ aMessage.Complete( KErrNone );
+
+ DRMLOG( _L( "CDRMDbSession::GetDomainROL ok" ) );
+ };
+
+// -----------------------------------------------------------------------------
+// CDRMDbSession::DeleteDomainROL
+// Delete domain ro xml data
+// -----------------------------------------------------------------------------
+//
+void CDRMDbSession::DeleteDomainROL( const RMessage2& aMessage )
+ {
+ DRMLOG( _L( "CDRMDbSession::DeleteDomainROL" ) );
+ __UHEAP_MARK;
+ TPtr8 data( NULL, 0 );
+ TInt size = 0;
+
+ size = User::LeaveIfError( IPCGETDESLEN0 );
+
+
+ HBufC8* RoId = HBufC8::NewLC( size );
+
+ data.Set( RoId->Des() );
+
+ IPCREAD0L( data );
+
+ DRMDB.DeleteDomainROL( *RoId );
+
+ CleanupStack::PopAndDestroy( RoId );
+
+ aMessage.Complete( KErrNone );
+ __UHEAP_MARKEND;
+ DRMLOG( _L( "CDRMDbSession::DeleteDomainROL ok" ) );
+ };
+
+
+// -----------------------------------------------------------------------------
+// CDRMDbSession::GetDomainRosForCidL
+// Return the domain ROs for a content ID in a buffer. Each RO is preceded
+// by a length field
+// -----------------------------------------------------------------------------
+//
+void CDRMDbSession::GetDomainRosForCidL(
+ const RMessage2& aMessage)
+ {
+ DRMLOG(_L("CDRMDbSession::GetDomainRosForCidL"));
+ TInt size(0);
+ TInt roSize(0);
+ TInt pos = 0;
+ TInt indexLatest = -1;
+ TTime timeStamp = 0;
+ TTime timeLatest = 0;
+ TPckg<TInt> pkg(size);
+ TPtr8 ptr(NULL, 0);
+ TPtrC8 elementPtr(KNullDesC8);
+ TPckg<TInt> roSizePkg(roSize);
+ HBufC8* element = NULL;
+ HBufC8* id(NULL);
+ HBufC8* ro(NULL);
+ CDRMPointerArray<CDRMPermission>*
+ rights( CDRMPointerArray<CDRMPermission>::NewLC() );
+ rights->SetAutoCleanup(ETrue);
+
+ delete iPreparedData;
+ iPreparedData = NULL;
+
+ SanitizeL( aMessage.GetDesLength(0) );
+
+ id = HBufC8::NewLC(aMessage.GetDesLength(0));
+ ptr.Set(id->Des());
+ aMessage.Read(0, ptr);
+
+ TRAPD(r, DRMDB.GetDBEntryByContentIDL(*id, *rights));
+
+ if (r == KErrCANoRights || r == KErrCANoPermission )
+ {
+ r = KErrNone;
+ }
+ User::LeaveIfError(r);
+
+ for (TInt i(0); i < rights->Count(); i++)
+ {
+ if ( (*rights)[i]->iDomainID )
+ {
+ ro = DRMDB.GetDomainROL(*(*rights)[i]->iRoID);
+ CleanupStack::PushL(ro);
+
+ elementPtr.Set(ExtractElement(*ro, KTimeStamp, pos));
+
+ /* Check whether the timestamp was found or not and whether it is
+ the newest one so far or not */
+ if (pos >= 0)
+ {
+ element = elementPtr.AllocLC();
+ timeStamp = Iso8601ToTime(*element);
+ CleanupStack::PopAndDestroy(element);
+
+ if (timeStamp > timeLatest)
+ {
+ indexLatest = i;
+ }
+ }
+ CleanupStack::PopAndDestroy(ro);
+ ro = NULL;
+ }
+ pos = 0;
+ }
+
+ /* At least one timestamp was found */
+ if (indexLatest >= 0 && indexLatest < rights->Count())
+ {
+ ro = DRMDB.GetDomainROL(*(*rights)[indexLatest]->iRoID);
+ CleanupStack::PushL(ro);
+
+ roSize = ro->Size();
+ if ( !iPreparedData )
+ {
+ iPreparedData = HBufC8::NewL(sizeof (TInt) + roSize);
+ }
+ else
+ {
+ iPreparedData = iPreparedData->ReAllocL(
+ size + sizeof (TInt) + roSize );
+ }
+ ptr.Set(iPreparedData->Des());
+ ptr.Append(roSizePkg);
+ ptr.Append(*ro);
+ size += sizeof (TInt) + roSize;
+ CleanupStack::PopAndDestroy(ro);
+ }
+
+ aMessage.Write(1, pkg);
+ CleanupStack::PopAndDestroy( id );
+ CleanupStack::PopAndDestroy( rights );
+
+ aMessage.Complete(KErrNone);
+ DRMLOG(_L("CDRMDbSession::GetDomainRosForCidL ok"));
+ }
+
+
+//------------------------------------------------------------------------------
+// CDRMDbSession::DeleteExpiredPermissionsL
+// Delete expired permissions if we have secure time.
+//------------------------------------------------------------------------------
+void CDRMDbSession::DeleteExpiredPermissionsL( const RMessage2& aMessage )
+ {
+ DRMLOG( _L( "CDRMDbSession::DeleteExpiredPermissionsL" ) );
+ CDRMActiveOperation* active( NULL );
+ TTime time;
+
+ User::LeaveIfError( VerifyCredentials(NULL, NULL, EUnknown) );
+ if( iCredentialsChecked == ECheckedAndDenied )
+ {
+ User::Leave( KErrPermissionDenied );
+ }
+
+ UpdateSecureTime();
+
+ if ( iSecureTime )
+ {
+ time = iTrustedTime;
+ }
+ else
+ {
+ time = Time::NullTTime();
+ }
+
+ if ( iPendingRequest )
+ {
+ User::Leave( KErrAlreadyExists );
+ }
+
+ active = CDRMActiveOperation::NewLC( aMessage, *this,
+ CDRMActiveOperation::EOperationDeleteExpired );
+ active->ActivateL( DRMDB, iTrustedTime );
+
+ iPendingRequest = active;
+
+ CleanupStack::Pop( active );
+
+ DRMLOG( _L( "CDRMDbSession::DeleteExpiredPermissionsL ok" ) );
+ }
+
+// -----------------------------------------------------------------------------
+// CDRMDbSession::SetEstimatedArrivalL
+// set the estimated arrival time for the content uri
+// -----------------------------------------------------------------------------
+//
+void CDRMDbSession::SetEstimatedArrivalL( const RMessage2& aMessage )
+ {
+ HBufC8* CID = NULL;
+ TFileName fileName;
+ TInt length = 0;
+ TPtr8 inRead( NULL, 0 );
+ TTimeIntervalSeconds interval = 0;
+ TPckg<TTimeIntervalSeconds> package( interval );
+ RPointerArray<CDRMXOma>& array = XOMAHEADER;
+ CDRMXOma* omaData = NULL;
+
+ // Read the content id
+ length = User::LeaveIfError( IPCGETDESLEN0 );
+ CID = HBufC8::NewLC( length );
+ inRead.Set( CID->Des() );
+ IPCREAD0L( inRead );
+
+ // Read the interval
+ IPCREAD1L( package );
+
+
+ for( TInt i = 0; i < array.Count(); i++ )
+ {
+ if( !CID->Compare( (array)[i]->ContentID() ) )
+ {
+ omaData = (array)[i];
+ break;
+ }
+ }
+
+ // Update the secure time
+ UpdateSecureTime();
+
+ if( omaData ) // Exists, update
+ {
+ omaData->SetWaitTimeL( interval );
+ omaData->SetTimeStampL( iTrustedTime );
+ }
+ else // Doesn't exist, create a new one
+ {
+ omaData = CDRMXOma::NewLC( *CID, iTrustedTime, interval );
+ array.AppendL( omaData );
+ CleanupStack::Pop( omaData );
+ }
+
+ CleanupStack::PopAndDestroy( CID );
+
+ // Complete the command
+ aMessage.Complete( KErrNone );
+ };
+
+// -----------------------------------------------------------------------------
+// CDRMDbSession::GetEstimatedArrivalL
+// get the estimated arrival time for the content uri
+// -----------------------------------------------------------------------------
+//
+void CDRMDbSession::GetEstimatedArrivalL( const RMessage2& aMessage )
+ {
+ HBufC8* CID = NULL;
+ TInt length = 0;
+ TPtr8 inRead( NULL, 0 );
+ RPointerArray<CDRMXOma>& array = XOMAHEADER;
+ CDRMXOma* omaData = NULL;
+ TInt64 interval = 0;
+ TInt i = 0;
+ TTimeIntervalSeconds result = 0;
+
+ // Read the content id
+ length = User::LeaveIfError( IPCGETDESLEN0 );
+ CID = HBufC8::NewLC( length );
+ inRead.Set( CID->Des() );
+ IPCREAD0L( inRead );
+
+ for( ; i < array.Count(); i++ )
+ {
+ if( !CID->Compare( (array)[i]->ContentID() ) )
+ {
+ omaData = (array)[i];
+ break;
+ }
+ }
+
+ // Update the secure time
+ UpdateSecureTime();
+
+ if( omaData ) // Exists, update
+ {
+
+ // Special case, the rights have expired before, but have not been removed
+ // so that we do not lose the notification
+ if( omaData->WaitTime().Int() == KErrCAPendingRights )
+ {
+ interval = -1; // Fixed value for this case:
+ // -1 means the rights should have arrived already
+
+ delete omaData;
+ omaData = 0;
+
+ array.Remove( i );
+ }
+ else
+ {
+ // Update the secure time
+ UpdateSecureTime();
+
+ interval = omaData->WaitTime().Int();
+ interval -= ( iTrustedTime.Int64() - omaData->TimeStamp().Int64() ) /
+ KMicrosecondsToSecond;
+
+ if( interval <= 0 )
+ {
+ interval = -1; // Fixed value for this case:
+ // -1 means the rights should have arrived already
+
+ // Clean up the data: if the function fails before this
+ // the instance remains like it should
+ delete omaData;
+ omaData = 0;
+
+ array.Remove( i ); // Remove from the array
+ }
+ }
+ result = I64INT(interval);
+ TPckg<TTimeIntervalSeconds> package( result );
+ IPCWRITE1L( package );
+ }
+ else // Doesn't exist, create a new one
+ {
+ User::Leave( KErrNotFound );
+ }
+
+ CleanupStack::PopAndDestroy( CID );
+
+ // Complete the command
+ aMessage.Complete( KErrNone );
+ };
+
+
+
+//------------------------------------------------------------------------------
+// CDRMDbSession::PendingRights
+// Check if rights are pending
+//------------------------------------------------------------------------------
+TBool CDRMDbSession::PendingRights(const TDesC8& aCid, TBool aRemoval)
+ {
+ TBool f = EFalse;
+ RPointerArray<CDRMXOma>& array = XOMAHEADER;
+ CDRMXOma* omaData = NULL;
+ TInt64 interval = 0;
+ TInt i = 0;
+ TTimeIntervalSeconds result = 0;
+
+ for( ; i < array.Count() && !f; i++ )
+ {
+ if( !aCid.Compare( (array)[i]->ContentID() ) )
+ {
+ omaData = (array)[i];
+ // Exists and is different from KErrCAPendingRights -> update
+ if( omaData && omaData->WaitTime().Int() != KErrCAPendingRights )
+ {
+ // Update the secure time
+ UpdateSecureTime();
+ interval = omaData->WaitTime().Int();
+ interval -= ( iTrustedTime.Int64() - omaData->TimeStamp().Int64() ) /
+ KMicrosecondsToSecond;
+
+ // check if removal from the list is needed
+ if( aRemoval && interval <= 0 )
+ {
+ TRAPD( error, omaData->SetWaitTimeL( KErrCAPendingRights ) );
+ error = error; // remove error
+ }
+ f = ETrue;
+ }
+ }
+ }
+ return f;
+ }
+
+
+
+//------------------------------------------------------------------------------
+// CDRMDbSession::GetUdtDataL
+// Gets the user data transfer header data
+//------------------------------------------------------------------------------
+void CDRMDbSession::GetUdtDataL( const RMessage2& aMessage )
+ {
+ DRMLOG( _L( "CDRMDbSession::GetUdtDataL" ) );
+ __UHEAP_MARK;
+ // Usage intent.
+ HBufC8* udtData = NULL;
+
+ // Get the key
+ udtData = DRMDB.GetUdtDataLC();
+
+ // Write the udt data to the client.
+ // This shouldn't fail anyway.
+ IPCWRITE0L( *udtData );
+
+ CleanupStack::PopAndDestroy( udtData );
+
+ aMessage.Complete( KErrNone );
+ __UHEAP_MARKEND;
+ DRMLOG( _L( "CDRMDbSession::GetUdtDataL: Ok" ) );
+ };
+
+//------------------------------------------------------------------------------
+// CDRMDbSession::InitiateUdtL
+// Initiate user data transfer
+//------------------------------------------------------------------------------
+void CDRMDbSession::InitiateUdtL( const RMessage2& aMessage )
+ {
+ DRMLOG( _L( "CDRMDbSession::InitiateUdtL" ) );
+ __UHEAP_MARK;
+
+ HBufC8* encryptionKey = NULL;
+ TInt size = 0;
+ TPtr8 data( NULL, 0 );
+
+ SanitizeL( aMessage.GetDesLength(0));
+
+ size = User::LeaveIfError( IPCGETDESLEN0 );
+ encryptionKey = HBufC8::NewLC( size );
+
+ data.Set( encryptionKey->Des() );
+ IPCREAD0L( data );
+
+ // The encrypted data is encrypted with 2048 byte key, it always needs to be atleast this long
+ if( encryptionKey->Length() < 254)
+ {
+ User::Leave(KErrArgument);
+ }
+
+ DRMDB.InitiateUdtL( *encryptionKey );
+
+ CleanupStack::PopAndDestroy( encryptionKey );
+
+ aMessage.Complete( KErrNone );
+ __UHEAP_MARKEND;
+
+ DRMLOG( _L( "CDRMDbSession::InitiateUdtL done" ) );
+ };
+
+//------------------------------------------------------------------------------
+// CDRMDbSession::InitExportOrhanedCIDsL
+// Create and export the list of orphaned content id's
+//------------------------------------------------------------------------------
+void CDRMDbSession::InitExportOrphanedCIDsL( const RMessage2& aMessage )
+ {
+ DRMLOG( _L( "CDRMDbSession::InitExportOrphanedCIDsL" ) );
+ CDRMActiveOperation* active( NULL );
+ TBool performScan = EFalse;
+
+ User::LeaveIfError( VerifyCredentials(NULL,NULL,ContentAccess::EUnknown) );
+
+ if ( iPendingRequest )
+ {
+ User::Leave( KErrAlreadyExists );
+ }
+
+ // if the old filename exists, delete it, a new operation starts
+ if( iFileName )
+ {
+ delete iFileName;
+ iFileName = NULL;
+ }
+
+ // Read the scan data:
+ performScan = aMessage.Int0() != 0 ? ETrue : EFalse;
+
+
+ active = CDRMActiveOperation::NewLC( aMessage, *this,
+ CDRMActiveOperation::EOperationExportObsolete );
+
+#ifndef RD_MULTIPLE_DRIVE
+
+ active->ActivateL( DRMDB, RFSSESSION, KDRMDbTempPath, performScan );
+
+#else //RD_MULTIPLE_DRIVE
+
+ TInt driveNumber( -1 );
+ TChar driveLetter;
+ DriveInfo::GetDefaultDrive( DriveInfo::EDefaultSystem, driveNumber );
+
+ RFSSESSION.DriveToChar( driveNumber, driveLetter );
+
+ TFileName dbTempPath;
+ dbTempPath.Format( KDbTempPath, (TUint)driveLetter );
+
+ active->ActivateL( DRMDB, RFSSESSION, dbTempPath, performScan );
+
+#endif
+
+ iPendingRequest = active;
+
+ CleanupStack::Pop( active );
+
+ DRMLOG( _L( "CDRMDbSession::InitExportOrphanedCIDsL: ok" ) );
+ };
+
+
+//------------------------------------------------------------------------------
+// CDRMDbSession::ExportOrhanedCIDsL
+// Create and export the list of orphaned content id's
+//------------------------------------------------------------------------------
+void CDRMDbSession::ExportOrphanedCIDsL( const RMessage2& aMessage )
+ {
+ DRMLOG( _L( "CDRMDbSession::ExportOrphanedCIDsL" ) );
+ if( !iFileName )
+ {
+ aMessage.Complete( KErrNotReady );
+ return;
+ }
+
+ if( iFileName->Length() > aMessage.GetDesMaxLength(0) )
+ {
+ User::Leave(KErrArgument);
+ }
+
+ // It is virtually impossible to make WriteL to leave in this case,
+ // but anything is still possible...
+ IPCWRITE0L( *iFileName );
+
+ // if everything went well, delete the filename if not leave it
+ delete iFileName;
+ iFileName = NULL;
+
+ // All done
+ aMessage.Complete( KErrNone );
+
+ DRMLOG( _L( "CDRMDbSession::ExportOrphanedCIDsL: ok" ) );
+ };
+
+// ----------------------------------------------------------------------------
+// CDRMDbSession::UnwrapMacAndRekL
+// Unwraps public key encrypted MAC and REK keys
+// ----------------------------------------------------------------------------
+//
+void CDRMDbSession::UnwrapMacAndRekL( const RMessage2& aMessage, TBool aDomainRo )
+ {
+ DRMLOG( _L( "CDRMDbSession::UnwrapMacAndRekL" ) );
+
+ __UHEAP_MARK;
+
+ MDrmKeyStorage* storage;
+ TBuf8<OmaCrypto::KMacSize> mac;
+ TBuf8<OmaCrypto::KKeySize> rek;
+ HBufC8* data = NULL;
+ TPtr8 dataPtr(0, 0);
+ TPtrC8 macAndRekPtr(0, 0);
+ HBufC8* riId = NULL;
+ TPtr8 riIdPtr(0, 0);
+ HBufC8* domainId = NULL;
+ TPtr8 domainIdPtr(0, 0);
+ CDRMRIContext* riContext = NULL;
+ TInt size = 0;
+ TKeyTransportScheme transport;
+ HBufC8* unwrappedMacAndRek = NULL;
+ CDRMDomainContext* domainContext;
+ HBufC8* domainKey = NULL;
+
+ DRMLOG(_L("CDRMDbSession::UnwrapMacAndRekL"));
+
+
+
+ SanitizeL( aMessage.GetDesLength(0) );
+ SanitizeL( aMessage.GetDesLength(1) );
+
+ size = User::LeaveIfError( IPCGETDESLEN0 );
+ data = HBufC8::NewLC( size );
+
+ size = User::LeaveIfError( IPCGETDESLEN1 );
+ riId = HBufC8::NewLC( size );
+
+ if(aDomainRo)
+ {
+ SanitizeL( aMessage.GetDesLength(2) );
+ size = User::LeaveIfError( IPCGETDESLEN2 );
+ domainId = HBufC8::NewLC( size );
+ }
+
+ dataPtr.Set( data->Des() );
+ IPCREAD0L( dataPtr );
+
+ riIdPtr.Set( riId->Des() );
+ IPCREAD1L( riIdPtr );
+
+ if(aDomainRo)
+ {
+ domainIdPtr.Set( domainId->Des() );
+ IPCREAD2L( domainIdPtr );
+ }
+
+ // The first byte defines the transport scheme
+ transport = static_cast<TKeyTransportScheme>(dataPtr[0]);
+ macAndRekPtr.Set(dataPtr.Mid(1));
+
+ DRMLOG2(_L("Transport scheme: %d"), transport);
+ DRMLOG(_L("MAC + REK:"));
+ DRMLOGHEX(macAndRekPtr);
+
+ if ( !iRoapClientConnected )
+ {
+ User::LeaveIfError( iRoapClient.Connect() );
+ iRoapClientConnected = ETrue;
+ }
+
+ if (!aDomainRo)
+ {
+ // get the trusted root from the rights issuer context
+ riContext = iRoapClient.GetRIContextL(riIdPtr);
+ if ( !riContext )
+ {
+ DRMLOG(_L("RI not registered"));
+ User::Leave(KErrRightsServerRiNotRegistered);
+ }
+ CleanupStack::PushL(riContext);
+ // connect to the storage of our PKI keys
+ storage = DrmKeyStorageNewL();
+ TCleanupItem storageCleanup( DeleteObject, storage );
+ CleanupStack::PushL(storageCleanup);
+ storage->SelectTrustedRootL(riContext->SelectedDeviceRoot());
+
+ if (transport == EOma)
+ {
+ OmaCrypto::RsaKemKwsDecryptL(storage, macAndRekPtr, rek, mac);
+ }
+ else
+ {
+ CmlaCrypto::CmlaIpDecryptL(transport, storage, macAndRekPtr, rek, mac);
+ }
+ CleanupStack::PopAndDestroy(4, data);
+ }
+ else
+ {
+ domainContext = iRoapClient.GetDomainContextL(domainIdPtr);
+ if ( !domainContext )
+ {
+ DRMLOG(_L("Domain not registered"));
+ User::Leave(KErrRightsServerDomainNotRegistered);
+ }
+ CleanupStack::PushL(domainContext);
+
+ // last three digits presents the domain generation
+ TInt generation = 0;
+ TLex8 lex( domainIdPtr.Right(3));
+ lex.Val(generation);
+
+ domainKey = domainContext->DomainKeyL(generation);
+ CleanupStack::PushL( domainKey );
+
+ // unwrap MAC and REK first with the domain key, the CEK with REK
+ unwrappedMacAndRek = OmaCrypto::AesUnwrapL(*domainKey, macAndRekPtr);
+ CleanupStack::PushL(unwrappedMacAndRek);
+
+ mac.Copy( unwrappedMacAndRek->Left( OmaCrypto::KKeySize) );
+ rek.Copy( unwrappedMacAndRek->Right( OmaCrypto::KKeySize) );
+ CleanupStack::PopAndDestroy(6, data);
+ }
+
+ DRMLOG(_L("REK:"));
+ DRMLOGHEX(rek);
+ DRMLOG(_L("MAC:"));
+ DRMLOGHEX(mac);
+
+ iMac.Copy(mac);
+ iRek.Copy(rek);
+
+ aMessage.Complete( KErrNone );
+
+ __UHEAP_MARKEND;
+
+ DRMLOG( _L( "CDRMDbSession::UnwrapMacAndRekL: ok" ) );
+ }
+
+//------------------------------------------------------------------------------
+// CDRMDbSession::FindParentsAndRemoveUnusableL()
+// Find the best ROs from aList and store references to aBest.
+//------------------------------------------------------------------------------
+void CDRMDbSession::FindParentsAndRemoveUnusableL( RDRMPermissionList& aList,
+ const TDesC8& aURI,
+ CDRMPointerArray<HBufC8>& aCids,
+ const TIntent aIntent,
+ const TTime& aDrmTime,
+ TUint32& aReason )
+ {
+
+ CDRMPermissionList *permList = NULL;
+ TInt error = KErrNone;
+ HBufC8* uri = NULL;
+
+ aCids.ResetAndDestroy();
+
+
+ // to separate parents and children we store the content id, since the content id is needed
+ // by drm consume:
+ for( TInt count = 0; count < aList.Count(); count++ )
+ {
+ uri = aURI.AllocLC();
+ aCids.AppendL( uri );
+ CleanupStack::Pop( uri ); // uri
+ }
+
+
+ // Go though the list and remove the unusable RO's
+ for( TInt i = aList.Count() - 1 ; i >= 0; i-- )
+ {
+ // If the RO has valid parent rights add them to the list
+ if( aList[i]->iParentUID )
+ {
+ permList = CDRMPermissionList::NewLC();
+ permList->SetAutoCleanup( ETrue );
+
+ TRAP( error, DRMDB.GetDBEntryByContentIDL( *aList[i]->iParentUID, *permList ));
+ if( !error )
+ {
+ for( TInt j = 0; j < permList->Count(); j++ )
+ {
+ // check if the permission is valid and if the RI ID for child and parent
+ // match
+ if ( aList[i]->iRiId.Compare( (*permList)[j]->iRiId ) == 0 &&
+ IsValidPermissionL( *(*permList)[j], aIntent, aDrmTime, aReason ) )
+ {
+ aList.AppendL( (*permList)[j] );
+ (*permList)[j] = 0;
+ uri = aList[i]->iParentUID->AllocLC();
+ aCids.AppendL( uri );
+ CleanupStack::Pop( uri );
+ }
+ }
+ }
+ CleanupStack::PopAndDestroy( permList );
+ }
+
+ // If the child is not valid remove it from the list
+ if ( !IsValidPermissionL( *aList[i], aIntent, aDrmTime, aReason ) )
+ {
+ CDRMPermission* perm = aList[i];
+ delete perm;
+ aList.Remove( i );
+
+ uri = aCids[i];
+ delete uri;
+ aCids.Remove( i );
+ perm = NULL;
+ uri = NULL;
+ }
+ }
+ // Now the list should contain only valid RO's or parents of the RO's
+ // which are valid
+ }
+
+
+//------------------------------------------------------------------------------
+// CDRMDbSession::FindBestROsL
+// Find the best ROs from aList and store references to aBest.
+//------------------------------------------------------------------------------
+TInt CDRMDbSession::FindBestROsL(
+ RDRMPermissionList& aList,
+ const TDesC8& aURI,
+ const TIntent aIntent,
+ HBufC8*& aUsedURI,
+ TUint32& aReason )
+ {
+ TTime time = Time::NullTTime();
+ CDRMPointerArray<HBufC8>* uriList = CDRMPointerArray<HBufC8>::NewLC();
+ uriList->SetAutoCleanup(ETrue);
+
+ TInt bestRo = -1;
+
+ if ( iSecureTime )
+ {
+ time = iTrustedTime;
+ }
+ else
+ {
+ time = Time::NullTTime();
+ }
+
+ FindParentsAndRemoveUnusableL( aList, aURI, *uriList, aIntent, time, aReason );
+
+ if( aList.Count() == 0 )
+ {
+ User::Leave(KErrCANoPermission);
+ }
+
+ bestRo = GetBestROL( aList, aIntent, aReason );
+
+ // Delete if it already exists
+ if( aUsedURI )
+ {
+ delete aUsedURI;
+ }
+ aUsedURI = NULL;
+
+ // if it's not the same as the normal URI return a value otherwise NULL
+ if( (*uriList)[ bestRo ]->Compare( aURI ) )
+ {
+ aUsedURI = (*uriList)[ bestRo ]->AllocL();
+ }
+
+ CleanupStack::PopAndDestroy( uriList );
+ return bestRo;
+ }
+
+// -----------------------------------------------------------------------------
+// CDRMDbSession::IsValidPermissionL
+// ETrue if not expired. If the candidate has expired permission (intent,
+// not top level), ETrue is returned if the child knows it is a child.
+// -----------------------------------------------------------------------------
+TBool CDRMDbSession::IsValidPermissionL(
+ CDRMPermission& aPermission,
+ const ContentAccess::TIntent aIntent,
+ const TTime& aTime,
+ TUint32& aReason )
+ {
+ CDRMConstraint* toplevel = NULL;
+ CDRMConstraint* constraint = NULL;
+ CDRMDomainContext* domainContext = NULL;
+ TBool r = ETrue;
+ #ifdef RD_DRM_METERING
+ CDRMRIContext* riContext = NULL;
+ #endif
+
+ toplevel = aPermission.TopLevelConstraint();
+ if ( toplevel && ( !( toplevel->Valid( aTime, IMSI, aReason ) ) ) )
+ {
+ r = EFalse;
+ }
+ else
+ {
+ constraint = aPermission.ConstraintForIntent( aIntent );
+ if ( !constraint || constraint &&
+ ( !( constraint->Valid( aTime, IMSI, aReason ) ) ) )
+ {
+ r = EFalse;
+ }
+ else if ( aPermission.iDomainID )
+ {
+ if ( !iRoapClientConnected )
+ {
+ User::LeaveIfError( iRoapClient.Connect() );
+ iRoapClientConnected = ETrue;
+ }
+ domainContext = iRoapClient.GetDomainContextL( *aPermission.iDomainID );
+ if ( domainContext )
+ {
+ delete domainContext;
+ }
+ else
+ {
+ r = EFalse;
+ }
+
+ }
+
+ // If the constraint is software constrained and the sw secureid does not match
+ // remove it from the list handling
+ if( r && aPermission.SoftwareConstrained() )
+ {
+ _LIT_SECURITY_POLICY_S0(swSidCheck, constraint->iSecureId.iUid);
+ if (constraint->iActiveConstraints & EConstraintSoftware)
+ {
+ if (!swSidCheck().CheckPolicy(iClient))
+ {
+ r = EFalse;
+ }
+ }
+ }
+ }
+
+ #ifdef RD_DRM_METERING
+
+ // Check if metering restricts the content usage
+ if ( r != EFalse && constraint->iDrmMeteringInfo &&
+ !constraint->iDrmMeteringInfo->iAllowUseWithoutMetering )
+ {
+ if ( !iRoapClientConnected )
+ {
+ User::LeaveIfError( iRoapClient.Connect() );
+ iRoapClientConnected = ETrue;
+ }
+ riContext = iRoapClient.GetRIContextL( aPermission.iRiId );
+ if ( !riContext || !riContext->IsMeteringAllowed() )
+ {
+ aReason |= EConstraintMetering;
+ return EFalse;
+ }
+ }
+
+ delete riContext;
+
+ #endif
+
+ return r;
+ }
+
+//------------------------------------------------------------------------------
+// CDRMDbSession::GetBestROL
+// Find the best ROs from aList and store references to aBest.
+//------------------------------------------------------------------------------
+TInt CDRMDbSession::GetBestROL(
+ RDRMPermissionList& aList,
+ const TIntent aIntent,
+ TUint32& aReason )
+ {
+ TInt count( 0 );
+ TTime time;
+
+ CDRMConstraint* normalized = CDRMConstraint::NewLC();
+ CDRMConstraint* bestOne = CDRMConstraint::NewLC();
+
+ TInt bestRo( -1 );
+
+ if ( iSecureTime )
+ {
+ time = iTrustedTime;
+ }
+ else
+ {
+ time = Time::NullTTime();
+ }
+
+ // 'count' is updated if something useful is found, and aList is
+ // updated if the permission cannot be used.
+ while ( count < aList.Count() )
+ {
+ CDRMPermission* perm = aList[ count ];
+ TBool found( EFalse );
+
+ // If there is no constraint for the intent, there is no need to normalize
+ // There can be no rights to use in that permission
+ if( perm->ConstraintForIntent( aIntent ) )
+ {
+ Normalize( *perm, *normalized, aIntent );
+ if ( normalized->Valid( time, IMSI, aReason ) )
+ {
+ found = ETrue;
+ }
+ }
+
+ if ( found )
+ {
+ // Compare whether "normalized" is more suitable than "bestOne".
+ // If this is the first usable child & parent combination,
+ // take it.
+ if ( ( bestRo < 0 ) || BetterPermission( *normalized, *bestOne ) )
+ {
+ // "normalized" is the new "bestOne"
+ CDRMConstraint* temp = bestOne;
+ bestOne = normalized;
+ normalized = temp;
+
+ bestRo = count;
+
+ ++count;
+ }
+ else
+ {
+ // This isn't any better than the previous ones. Throw it away.
+ found = EFalse;
+ }
+ }
+
+ if ( !found )
+ {
+ // Unusable child.
+ delete perm; perm = NULL;
+ aList.Remove( count );
+ }
+ }
+
+ CleanupStack::PopAndDestroy( 2 ); // bestOne, normalized
+
+ return bestRo;
+ }
+
+// -----------------------------------------------------------------------------
+// CDRMDbSession::Normalize
+// Normalizes a permission.
+// -----------------------------------------------------------------------------
+void CDRMDbSession::Normalize( CDRMPermission& aPermission,
+ CDRMConstraint& aNormalized,
+ const ContentAccess::TIntent aIntent )
+ {
+ __ASSERT_DEBUG( aPermission.ConstraintForIntent( aIntent ), User::Invariant() );
+
+ TRAPD( error, aNormalized.DuplicateL( *( aPermission.ConstraintForIntent( aIntent ) ) ) );
+ if( !error )
+ {
+ if ( aPermission.TopLevelConstraint() )
+ {
+ aNormalized.Merge( *( aPermission.TopLevelConstraint() ) );
+ }
+ }
+ }
+// -----------------------------------------------------------------------------
+// CDRMDbSession::BetterPermission
+// Compares two permissions, and returns ETrue if aNewOne is more suitable
+// for the usage. Assumes both are valid, i.e. not expired.
+// -----------------------------------------------------------------------------
+TBool CDRMDbSession::BetterPermission( const CDRMConstraint& aNewOne,
+ const CDRMConstraint& aOldOne )
+ {
+ // Check Order:
+ // 1. Full
+ // 2. Start End, closest end time first
+ // 3. Interval, shortest first
+ // 4. Accumulated, shortest first
+ // 5. Timed Counter, least counters first, longest time first
+ // 6. Counter, least counters first or the first one found
+
+ const TTime nullTime = Time::NullTTime();
+ TTime oldTime = nullTime;
+ TTime newTime = nullTime;
+ TTime oldTimePos = nullTime;
+ TTime newTimePos = nullTime;
+
+ // 1. Full
+ // If the old or new one is the ultimate one, don't bother to
+ // check anything else.
+ if ( aOldOne.iActiveConstraints == EConstraintNone )
+ {
+ return EFalse;
+ }
+
+ if ( aNewOne.iActiveConstraints == EConstraintNone )
+ {
+ return ETrue;
+ }
+
+ // 2. Start & End Time
+ // Choose the one with the closest end time first
+ // All RO's to this check are already checked to be valid
+ // ActiveIntervals Also hit this spot
+
+ // First get the start and end times from the intervals if they are active or inactive:
+ if ( aOldOne.iActiveConstraints & EConstraintInterval )
+ {
+ if( aOldOne.iIntervalStart == nullTime )
+ {
+ oldTimePos = iTrustedTime;
+ oldTimePos += TTimeIntervalSeconds( aOldOne.iInterval );
+ }
+ else
+ {
+ oldTime = aOldOne.iIntervalStart;
+ oldTime += TTimeIntervalSeconds( aOldOne.iInterval );
+ }
+ }
+
+ if( aNewOne.iActiveConstraints & EConstraintInterval )
+ {
+ if( aNewOne.iIntervalStart == nullTime )
+ {
+ newTimePos = iTrustedTime;
+ newTimePos += TTimeIntervalSeconds( aNewOne.iInterval );
+ }
+ else
+ {
+ newTime = aNewOne.iIntervalStart;
+ newTime += TTimeIntervalSeconds( aNewOne.iInterval );
+ }
+ }
+
+ if ( aOldOne.iActiveConstraints & EConstraintEndTime || oldTime != nullTime )
+ {
+ oldTime = EndTime( oldTime, aOldOne.iEndTime );
+
+ if ( aNewOne.iActiveConstraints & EConstraintEndTime || newTime != nullTime )
+ {
+ newTime = EndTime( newTime, aNewOne.iEndTime );
+
+ if( newTime != oldTime )
+ {
+ return ( newTime < oldTime );
+ }
+ }
+ else
+ {
+ return EFalse;
+ }
+ }
+ else if ( aNewOne.iActiveConstraints & EConstraintEndTime || newTime != nullTime )
+ {
+ return ETrue;
+ }
+
+
+ // 3. Inactive Intervals:
+ // Choose the one with the interval ending first:
+ // Continue here if the no SE's exist or SE's are the same
+ if( aOldOne.iActiveConstraints & EConstraintInterval )
+ {
+ if( aNewOne.iActiveConstraints & EConstraintInterval )
+ {
+ oldTimePos = EndTime( oldTime, oldTimePos );
+ newTimePos = EndTime( newTime, newTimePos );
+
+ if( oldTimePos != newTimePos )
+ {
+ return ( newTimePos < oldTimePos );
+ }
+ }
+ else
+ {
+ if( aNewOne.iActiveConstraints & EConstraintAccumulated ||
+ aNewOne.iActiveConstraints & EConstraintTimedCounter ||
+ aNewOne.iActiveConstraints & EConstraintCounter )
+ {
+ return EFalse;
+ }
+ else
+ {
+ return ETrue;
+ }
+ }
+ }
+ else if( aNewOne.iActiveConstraints & EConstraintInterval )
+ {
+ if( aOldOne.iActiveConstraints & EConstraintAccumulated ||
+ aOldOne.iActiveConstraints & EConstraintTimedCounter ||
+ aOldOne.iActiveConstraints & EConstraintCounter )
+ {
+ return ETrue;
+ }
+ else
+ {
+ return EFalse;
+ }
+ }
+
+ // 4. Accumulated:
+ // Choose the shortest accumulated first
+ // Continue here if SE's or intervals do not exist or they are the same
+ if( aOldOne.iActiveConstraints & EConstraintAccumulated )
+ {
+ if( aNewOne.iActiveConstraints & EConstraintAccumulated )
+ {
+ if( aNewOne.iAccumulatedTime != aOldOne.iAccumulatedTime )
+ {
+ return ( aNewOne.iAccumulatedTime < aOldOne.iAccumulatedTime );
+ }
+ }
+ else
+ {
+ if( aNewOne.iActiveConstraints & EConstraintTimedCounter ||
+ aNewOne.iActiveConstraints & EConstraintCounter )
+ {
+ return EFalse;
+ }
+ else
+ {
+ return ETrue;
+ }
+ }
+ }
+ else if( aNewOne.iActiveConstraints & EConstraintAccumulated )
+ {
+ if( aOldOne.iActiveConstraints & EConstraintTimedCounter ||
+ aOldOne.iActiveConstraints & EConstraintCounter )
+ {
+ return ETrue;
+ }
+ else
+ {
+ return EFalse;
+ }
+ }
+
+
+ // 5. Timed Counter
+ // Choose the one with least counters first. If there is an equal number of counters
+ // left, use the one with the longest time
+ // Continue here if SE's or intervals or accumulateds do not exist or they are the same
+ if( aOldOne.iActiveConstraints & EConstraintTimedCounter )
+ {
+ if( aNewOne.iActiveConstraints & EConstraintTimedCounter )
+ {
+ if( aNewOne.iTimedCounter == aOldOne.iTimedCounter )
+ {
+ if( aNewOne.iTimedInterval != aOldOne.iTimedInterval )
+ {
+ return ( aNewOne.iTimedInterval < aOldOne.iTimedInterval );
+ }
+ else
+ {
+ if( aNewOne.iActiveConstraints & EConstraintCounter )
+ {
+
+ }
+ }
+ }
+ else
+ {
+ return ( aNewOne.iTimedCounter < aOldOne.iTimedCounter );
+ }
+
+ }
+ else
+ {
+ if( aNewOne.iActiveConstraints & EConstraintCounter )
+ {
+ return EFalse;
+ }
+ else
+ {
+ return ETrue;
+ }
+ }
+ }
+ else if( aNewOne.iActiveConstraints & EConstraintTimedCounter )
+ {
+ if( aOldOne.iActiveConstraints & EConstraintCounter )
+ {
+ return ETrue;
+ }
+ else
+ {
+ return EFalse;
+ }
+ }
+
+ // 6. Counter
+ // Choose the one with least counters:
+ // if they are the same choose the first one.
+ // Continue here if SE's or intervals or accumulateds or timed counters
+ // do not exist or they are the same
+ if( aOldOne.iActiveConstraints & EConstraintCounter )
+ {
+ if( aNewOne.iActiveConstraints & EConstraintCounter )
+ {
+ return ( aNewOne.iCounter < aOldOne.iCounter );
+ }
+ else
+ {
+ return ETrue;
+ }
+ }
+
+ // If all else fails use the old one:
+ return EFalse;
+ }
+
+
+// -----------------------------------------------------------------------------
+// CDRMDbSession::BetterPermission
+// Compares two permissions, and returns ETrue if aNewOne is more suitable
+// for the usage. Assumes both are valid, i.e. not expired.
+// -----------------------------------------------------------------------------
+TBool BetterPermissionOld( const CDRMConstraint& aNewOne,
+ const CDRMConstraint& aOldOne ) //const
+ {
+
+ const TTime nullTime = Time::NullTTime();
+ TTime oldTime = nullTime;
+ TTime newTime = nullTime;
+ TBool inactiveIntervals = EFalse;
+
+ // If the old or new one is the ultimate one, don't bother to
+ // check anything else.
+ if ( aOldOne.iActiveConstraints == EConstraintNone )
+ {
+ return EFalse;
+ }
+
+ if ( aNewOne.iActiveConstraints == EConstraintNone )
+ {
+ return ETrue;
+ }
+
+ // If old one has count constraints but the new doesn't, the new
+ // is better. If the old one doesn't have counters but the
+ // new has, the old one is better.
+ if ( aOldOne.iActiveConstraints & EConstraintCounter )
+ {
+ if ( !( aNewOne.iActiveConstraints & EConstraintCounter ) ||
+ ( aNewOne.iCounter < aOldOne.iCounter ) )
+ {
+ return ETrue;
+ }
+ }
+ else
+ {
+ if ( aNewOne.iActiveConstraints & EConstraintCounter )
+ {
+ return EFalse;
+ }
+ }
+
+ if ( aOldOne.iActiveConstraints & EConstraintTimedCounter )
+ {
+ if ( !( aNewOne.iActiveConstraints & EConstraintTimedCounter ) ||
+ ( aNewOne.iTimedCounter < aOldOne.iTimedCounter ) )
+ {
+ return ETrue;
+ }
+ }
+ else
+ {
+ if ( aNewOne.iActiveConstraints & EConstraintTimedCounter )
+ {
+ return EFalse;
+ }
+ }
+
+ if ( aOldOne.iActiveConstraints & EConstraintAccumulated )
+ {
+ if ( !( aNewOne.iActiveConstraints & EConstraintAccumulated ) ||
+ ( aNewOne.iAccumulatedTime < aOldOne.iAccumulatedTime ) )
+ {
+ return ETrue;
+ }
+ }
+ else
+ {
+ if ( aNewOne.iActiveConstraints & EConstraintAccumulated )
+ {
+ return EFalse;
+ }
+ }
+
+ // - No intervals is better than inactive intervals.
+ // - No intervals compared to activated interval goes to
+ // end time constraint comparison.
+ // - Activated interval is better than inactive interval.
+ // - Two inactive intervals go to end time constraint comparison.
+ if ( aOldOne.iActiveConstraints & EConstraintInterval )
+ {
+ if ( aNewOne.iActiveConstraints & EConstraintInterval )
+ {
+ if ( aOldOne.iIntervalStart == nullTime )
+ {
+ if ( aNewOne.iIntervalStart != nullTime )
+ {
+ return ETrue;
+ }
+
+ // Both have inactive intervals.
+ inactiveIntervals = ETrue;
+
+// oldTime = iTrustedTime;
+ oldTime += TTimeIntervalSeconds( aOldOne.iInterval );
+
+// newTime = iTrustedTime;
+ newTime += TTimeIntervalSeconds( aNewOne.iInterval );
+ }
+ else
+ {
+ // Old one has activated interval.
+ if ( aNewOne.iIntervalStart == nullTime )
+ {
+ return EFalse;
+ }
+
+ // Both have activated intervals.
+ oldTime = aOldOne.iIntervalStart;
+ oldTime += TTimeIntervalSeconds( aOldOne.iInterval );
+
+ newTime = aNewOne.iIntervalStart;
+ newTime += TTimeIntervalSeconds( aNewOne.iInterval );
+ }
+ }
+ else
+ {
+ // No intervals in the new one.
+ if ( aOldOne.iIntervalStart == nullTime )
+ {
+ return ETrue;
+ }
+
+ oldTime = aOldOne.iIntervalStart;
+ oldTime += TTimeIntervalSeconds( aOldOne.iInterval );
+ }
+ }
+ else
+ {
+ // The old one doesn't have intervals.
+ if ( aNewOne.iActiveConstraints & EConstraintInterval )
+ {
+ if ( aNewOne.iIntervalStart == nullTime )
+ {
+ return EFalse;
+ }
+
+ newTime = aNewOne.iIntervalStart + TTimeIntervalSeconds( aNewOne.iInterval );
+ }
+ }
+
+ if ( inactiveIntervals )
+ {
+ // The one with end time goes first.
+ if ( aOldOne.iActiveConstraints & EConstraintEndTime )
+ {
+ if ( aNewOne.iActiveConstraints & EConstraintEndTime )
+ {
+ oldTime = EndTime( oldTime, aOldOne.iEndTime );
+ newTime = EndTime( newTime, aNewOne.iEndTime );
+
+ return ( newTime < oldTime );
+ }
+
+ return EFalse;
+ }
+
+ if( aNewOne.iActiveConstraints & EConstraintEndTime )
+ {
+ return ETrue;
+ }
+
+ // Both have just inactive intervals.
+ return ( newTime < oldTime );
+ }
+
+ // Check end times and/or activated intervals.
+ if ( aOldOne.iActiveConstraints & EConstraintEndTime || oldTime != nullTime )
+ {
+ oldTime = EndTime( oldTime, aOldOne.iEndTime );
+
+ if ( aNewOne.iActiveConstraints & EConstraintEndTime || newTime != nullTime )
+ {
+ newTime = EndTime( newTime, aNewOne.iEndTime );
+
+ return ( newTime < oldTime );
+ }
+
+ // The new one doesn't have end time constraint and/or activated intervals.
+ return EFalse;
+ }
+
+ if ( aNewOne.iActiveConstraints & EConstraintEndTime || newTime != nullTime )
+ {
+ return ETrue;
+ }
+
+ // Start time does not expire, so let's keep the old one.
+
+ return EFalse;
+ }
+
+
+// ----------------------------------------------------------------------------
+// UnwrapProtectedCekL
+// Unwraps the protected CEK aProtectedCek. Caller owns the returned buffer.
+// ----------------------------------------------------------------------------
+//
+HBufC8* CDRMDbSession::UnwrapProtectedCekL(
+ const TDesC8& aProtectedCek )
+ {
+ MDrmKeyStorage* storage;
+ TBuf8<OmaCrypto::KMacSize> mac;
+ TBuf8<OmaCrypto::KKeySize> rek;
+ HBufC8* cek = NULL;
+ TPtrC8 macAndRek(0, 0);
+ TPtrC8 wrappedCek(0, 0);
+ TKeyTransportScheme transport;
+ TBuf8<KRiIdSize> rightsIssuer;
+ CDRMRIContext* riContext = NULL;
+ TInt i;
+ TInt len;
+
+ DRMLOG(_L("CDRMDbSession::UnwrapProtectedCekL"));
+
+ // first element: one byte for the transport scheme
+ i = 0;
+ transport = static_cast<TKeyTransportScheme>(aProtectedCek[i]);
+ i++;
+
+ DRMLOG2(_L("Transport scheme: %d"), transport);
+
+ // second element: the concatenated MAC and REK wrapped with the KEK
+ len = aProtectedCek[i];
+ macAndRek.Set(aProtectedCek.Mid(i + 1, len));
+ i = i + 1 + len;
+ DRMLOG(_L("MAC + REK:"));
+ DRMLOGHEX(macAndRek);
+
+ // third element: 20 bytes with the rights issuer ID
+ len = aProtectedCek[i];
+ rightsIssuer.Copy(aProtectedCek.Mid(i + 1, len));
+ i = i + 1 + len;
+ DRMLOG(_L("RI ID:"));
+ DRMLOGHEX(rightsIssuer);
+
+ // get the trusted root from the rights issuer context
+ if ( !iRoapClientConnected )
+ {
+ User::LeaveIfError( iRoapClient.Connect() );
+ iRoapClientConnected = ETrue;
+ }
+ riContext = iRoapClient.GetRIContextL(rightsIssuer);
+ if ( !riContext )
+ {
+ DRMLOG(_L("RI not registered"));
+ User::Leave(KErrRightsServerRiNotRegistered);
+ }
+ CleanupStack::PushL(riContext);
+
+ // connect to the storage of our PKI keys
+ storage = DrmKeyStorageNewL();
+ TCleanupItem storageCleanup( DeleteObject, storage );
+ CleanupStack::PushL(storageCleanup);
+ storage->SelectTrustedRootL(riContext->SelectedDeviceRoot());
+
+ if (transport == EOma)
+ {
+ OmaCrypto::RsaKemKwsDecryptL(storage, macAndRek, rek, mac);
+ }
+ else
+ {
+ CmlaCrypto::CmlaIpDecryptL(transport, storage, macAndRek, rek, mac);
+ }
+
+ DRMLOG(_L("REK:"));
+ DRMLOGHEX(rek);
+ DRMLOG(_L("MAC:"));
+ DRMLOGHEX(mac);
+
+ iMac.Copy(mac);
+ iRek.Copy(rek);
+
+ // fourth element: 24 bytes for the CEK (wrapped with the REK),
+ // this can be empty, e.g. for a parent RO (indicated by a zero length)
+ len = aProtectedCek[i];
+ if (len > 0)
+ {
+ wrappedCek.Set(aProtectedCek.Mid(i + 1, len));
+ DRMLOG(_L("Wrapped CEK:"));
+ DRMLOGHEX(wrappedCek);
+ cek = OmaCrypto::AesUnwrapL(rek, wrappedCek);
+ DRMLOG(_L("CEK:"));
+ DRMLOGHEX(( *cek ));
+ }
+ else
+ {
+ DRMLOG(_L("No CEK"));
+ cek = KNullDesC8().AllocL();
+ }
+
+ CleanupStack::PopAndDestroy(2); // riContext, storageCleanup
+ return cek;
+ }
+
+// ----------------------------------------------------------------------------
+// UnwrapDomainCekL
+// Unwraps CEK with is wrapped with a domain key. Caller owns the returned
+// buffer.
+// ----------------------------------------------------------------------------
+//
+HBufC8* CDRMDbSession::UnwrapDomainCekL(
+ const TDesC8& aProtectedCek,
+ const TDesC8& aDomainId )
+ {
+ HBufC8* unwrappedMacAndRek = NULL;
+ HBufC8* cek = NULL;
+ TPtrC8 macAndRek(0, 0);
+ TPtrC8 wrappedCek(0, 0);
+ CDRMDomainContext* domainContext;
+ HBufC8* domainKey = NULL;
+ TInt i;
+ TInt len;
+
+ DRMLOG(_L("CDRMDbSession::UnwrapDomainCekL"));
+
+ // first element (one byte for the transport scheme) is ignored
+ i = 1;
+
+ // second element: MAC and REK wrapped with the domain key (40 bytes)
+ len = aProtectedCek[i];
+ macAndRek.Set(aProtectedCek.Mid(i + 1, len));
+ i = i + 1 + len;
+ DRMLOG(_L("MAC + REK:"));
+ DRMLOGHEX(macAndRek);
+
+ // third element: 20 bytes with the rights issuer ID, is ignored
+ len = aProtectedCek[i];
+ i = i + 1 + len;
+
+ // fourth element: 24 bytes for the CEK (wrapped with the REK)
+ len = aProtectedCek[i];
+ wrappedCek.Set(aProtectedCek.Mid(i + 1, len));
+ DRMLOG(_L("Wrapped CEK:"));
+ DRMLOGHEX(wrappedCek);
+
+ // get the domain key from the domain context
+ if ( !iRoapClientConnected )
+ {
+ User::LeaveIfError( iRoapClient.Connect() );
+ iRoapClientConnected = ETrue;
+ }
+ domainContext = iRoapClient.GetDomainContextL(aDomainId);
+ if ( !domainContext )
+ {
+ DRMLOG(_L("Domain not registered"));
+ User::Leave(KErrRightsServerDomainNotRegistered);
+ }
+ CleanupStack::PushL(domainContext);
+
+ // last three digits presents the domain generation
+ TInt generation = 0;
+ TLex8 lex( aDomainId.Right(3));
+ lex.Val(generation);
+
+ domainKey = domainContext->DomainKeyL(generation);
+ CleanupStack::PushL( domainKey );
+
+ // unwrap MAC and REK first with the domain key, the CEK with REK
+ unwrappedMacAndRek = OmaCrypto::AesUnwrapL(*domainKey, macAndRek);
+ CleanupStack::PushL(unwrappedMacAndRek);
+ cek = OmaCrypto::AesUnwrapL(unwrappedMacAndRek->Right(
+ OmaCrypto::KKeySize), wrappedCek);
+ iMac.Copy( unwrappedMacAndRek->Left( OmaCrypto::KKeySize) );
+ CleanupStack::PopAndDestroy(3); // unwrappedMacAndRek, domainKey, domainContext
+
+ return cek;
+ }
+
+// ----------------------------------------------------------------------------
+// CDRMDbSession::VerifyCredentials
+// Check if the client has enough credentials to grant access to later
+// decryption.
+// ----------------------------------------------------------------------------
+//
+TInt CDRMDbSession::VerifyCredentials(
+ HBufC8* aContentId,
+ CDRMPermission* aPermission,
+ TIntent aIntent)
+ {
+ CDRMConstraint* constraint = NULL;
+ _LIT_SECURITY_POLICY_C1(drmCheck, ECapabilityDRM);
+ _LIT_SECURITY_POLICY_V0(vidCheck, VID_DEFAULT); // Check Default VID
+ RPointerArray<CDRMPermission> permissions;
+ TInt r = KErrAccessDenied;
+ TBool hasOma2Permissions = EFalse;
+ TBool hasSoftwareConstraints = EFalse;
+ TInt i;
+
+ __UHEAP_MARK;
+ // Get the applicable permission, and check if there are OMA 2 permissions or
+ // software constraints
+ if (aPermission)
+ {
+ constraint = aPermission->ConstraintForIntent(aIntent);
+ }
+ if ( aContentId )
+ {
+ TRAP_IGNORE( DRMDB.GetDBEntryByContentIDL(*aContentId, permissions) );
+ for (i = 0; i < permissions.Count(); i++)
+ {
+ if (permissions[i]->iRightsObjectVersion.iVersionMain == EOma2Rights ||
+ permissions[i]->iRightsObjectVersion.iVersionMain == ECmlaRights)
+ {
+ hasOma2Permissions = ETrue;
+ }
+ if (permissions[i]->SoftwareConstrained())
+ {
+ hasSoftwareConstraints = ETrue;
+ }
+ }
+ permissions.ResetAndDestroy();
+ permissions.Close();
+ }
+
+ // First, check for DRM capability, access granted only if there are no software
+ // constraints.
+ if (drmCheck().CheckPolicy(iClient) && !hasSoftwareConstraints)
+ {
+ r = KErrNone;
+ }
+
+ // If a permission is given, check for license manager cases as well as
+ // OMA DRM 1.0 case
+ if ( r != KErrNone && aPermission )
+ {
+ // Fallback: Check if the vendor ID is the default vendor ID,
+ // allow access for OMA DRM 1.0 rights
+ if ((aPermission->iRightsObjectVersion.iVersionMain == EOma1Rights &&
+ vidCheck().CheckPolicy(iClient)))
+ {
+ r = KErrNone;
+ }
+
+ // Check the software constraint, this can override the fallback above!
+ if ( constraint )
+ {
+ _LIT_SECURITY_POLICY_S0(swSidCheck, constraint->iSecureId.iUid);
+ _LIT_SECURITY_POLICY_V0(swVidCheck, constraint->iVendorId.iUid);
+ if (constraint->iActiveConstraints & EConstraintVendor)
+ {
+ if (swVidCheck().CheckPolicy(iClient))
+ {
+ r = KErrNone;
+ }
+ else
+ {
+ r = KErrAccessDenied;
+ }
+ }
+ if (constraint->iActiveConstraints & EConstraintSoftware)
+ {
+ if (swSidCheck().CheckPolicy(iClient))
+ {
+ r = KErrNone;
+ }
+ else
+ {
+ r = KErrAccessDenied;
+ }
+ }
+ }
+
+ }
+
+ // Application installer needs to be able to use the content even if it has SW constraints
+ _LIT_SECURITY_POLICY_S0(swSidCheck2, KAppInstSrv);
+
+ if( swSidCheck2().CheckPolicy(iClient) && hasSoftwareConstraints )
+ {
+ r = KErrNone;
+ }
+
+
+ // Check if access can be granted when only
+ // OMA DRM 1.0 permissions are currently available, and the client
+ // has the default vendor ID
+ if ( r != KErrNone && !hasOma2Permissions &&
+ !hasSoftwareConstraints && vidCheck().CheckPolicy( iClient ) )
+ {
+ r = KErrNone;
+ }
+ __UHEAP_MARKEND;
+
+ if ( r == KErrNone )
+ {
+ iCredentialsChecked = ECheckedAndAllowed;
+ }
+ else
+ {
+ iCredentialsChecked = ECheckedAndDenied;
+ }
+ return r;
+ }
+
+// ----------------------------------------------------------------------------
+// CDRMDbSession::RemoveInvalidPermissionsL
+// Remove all permissions where the domain context is not available
+// ----------------------------------------------------------------------------
+//
+void CDRMDbSession::RemoveInvalidPermissionsL(
+ CDRMPermissionList* aList )
+ {
+ CDRMDomainContext* domainContext = NULL;
+ TInt i;
+ if ( !iRoapClientConnected )
+ {
+ User::LeaveIfError( iRoapClient.Connect() );
+ iRoapClientConnected = ETrue;
+ }
+ for ( i = aList->Count() - 1; i >= 0; i-- )
+ {
+ if ( (*aList)[i]->iDomainID )
+ {
+ domainContext = iRoapClient.GetDomainContextL(
+ *(*aList)[i]->iDomainID );
+ if ( domainContext )
+ {
+ delete domainContext;
+ }
+ else
+ {
+ aList->Remove( i );
+ }
+ }
+ }
+ }
+
+// ----------------------------------------------------------------------------
+// CDRMDbSession::
+//
+// ----------------------------------------------------------------------------
+//
+void CDRMDbSession::SetNameL( const RMessage2& aMessage )
+ {
+ DRMLOG( _L( "CDRMDbSession::SetNameL" ) );
+ __UHEAP_MARK;
+
+ SanitizeL( aMessage.GetDesLength( 0 ) );
+ SanitizeL( aMessage.GetDesLength( 1 ) );
+
+ TInt namelength = User::LeaveIfError( IPCGETDESLEN1 );
+ HBufC8* cid = HBufC8::NewLC( IPCGETDESLEN0 );
+ HBufC* name = HBufC::NewLC( namelength > 0 ? namelength : 1 );
+ TPtr8 tmp( cid->Des() );
+
+ IPCREAD0L( tmp );
+ if ( namelength )
+ {
+ TPtr tmp2( name->Des() );
+ IPCREAD1L( tmp2 );
+ }
+
+ DRMDB.NameContentL( *cid, *name );
+
+ CleanupStack::PopAndDestroy( 2 );
+ __UHEAP_MARKEND;
+ aMessage.Complete( KErrNone );
+ }
+
+// ----------------------------------------------------------------------------
+// CDRMDbSession::
+//
+// ----------------------------------------------------------------------------
+//
+void CDRMDbSession::GetNameL( const RMessage2& aMessage )
+ {
+ DRMLOG( _L( "CDRMDbSession::GetNameL" ) );
+ HBufC8* cid = NULL;
+ TPckgBuf< TInt > size( 0 );
+
+ // Cleanup.
+ if ( iWidePreparedData )
+ {
+ delete iWidePreparedData;
+ iWidePreparedData = NULL;
+ }
+
+ SanitizeL( aMessage.GetDesLength( 0 ) );
+ cid = HBufC8::NewLC( IPCGETDESLEN0 );
+ TPtr8 tmp( cid->Des() );
+ IPCREAD0L( tmp );
+
+ iWidePreparedData = DRMDB.ContentNameLC( *cid );
+
+ CleanupStack::Pop( iWidePreparedData );
+ CleanupStack::PopAndDestroy( cid );
+
+ size() = iWidePreparedData->Length();
+ if ( iWidePreparedData->Length() == 0 )
+ {
+ // Empty name --> not asked.
+ delete iWidePreparedData;
+ iWidePreparedData = NULL;
+ }
+
+ IPCWRITE1L( size );
+
+ aMessage.Complete( KErrNone );
+ }
+
+// ----------------------------------------------------------------------------
+// CDRMDbSession::
+//
+// ----------------------------------------------------------------------------
+//
+void CDRMDbSession::GetWideDataL( const RMessage2& aMessage )
+ {
+ DRMLOG( _L( "CDRMDbSesion::GetWideDataL" ) );
+ if ( iWidePreparedData )
+ {
+ if( iWidePreparedData->Length() > aMessage.GetDesMaxLength(0) )
+ {
+ User::Leave(KErrArgument);
+ }
+
+ IPCWRITE0L( *iWidePreparedData );
+
+ delete iWidePreparedData;
+ iWidePreparedData = NULL;
+
+ aMessage.Complete( KErrNone );
+ return;
+ }
+
+ aMessage.Complete( KErrNotReady );
+ }
+
+// ----------------------------------------------------------------------------
+// CDRMDbSession::
+//
+// ----------------------------------------------------------------------------
+//
+void CDRMDbSession::Cancel( const RMessage2& aMessage )
+ {
+ DRMLOG( _L( "CDRMDbSession::Cancel" ) );
+ if ( iPendingRequest )
+ {
+ static_cast<CDRMActiveOperation*>(iPendingRequest)->Remove();
+ }
+
+ aMessage.Complete( KErrNone );
+ }
+
+// ----------------------------------------------------------------------------
+// CDRMDbSession::
+//
+// ----------------------------------------------------------------------------
+//
+void CDRMDbSession::GetFLUriL( const RMessage2& aMessage )
+ {
+ DRMLOG( _L( "CDRMDbSession::GetFLUriL" ) );
+
+ TBuf8< KMaxOmaV1CIDLength > URI;
+
+ GetFlURI( URI );
+
+ if( URI.Length() > aMessage.GetDesMaxLength(0) )
+ {
+ User::Leave(KErrArgument);
+ }
+
+ IPCWRITE0L( URI );
+ aMessage.Complete( KErrNone );
+ }
+
+// ----------------------------------------------------------------------------
+// CDRMDbSession::
+//
+// ----------------------------------------------------------------------------
+//
+void CDRMDbSession::EncodeRightsIssuerL( const RMessage2& aMessage )
+ {
+ __UHEAP_MARK;
+
+ DRMLOG( _L( "CRMDbSession::EncodeRightsIssuerL" ) );
+ TBuf8< KDCFKeySize > iv;
+ HBufC8* data( NULL );
+ HBufC8* tmp( NULL );
+ iv.SetLength( KDCFKeySize );
+
+ TInt size( User::LeaveIfError( IPCGETDESLEN0 ) );
+ TPtr8 des( NULL, 0, 0 );
+
+ if ( size < 1 )
+ {
+ User::Leave( KErrArgument );
+ }
+
+ // Calculate the size. It could be retrieved also from GetDesMaxLength,
+ // but at least now we can be sure we won't panic in case of
+ // descriptor overflow.
+ size += KDCFKeySize - ( size % KDCFKeySize ); //padding
+ size += KDCFKeySize; //iv
+ size = ( size + 2 ) / 3 * 4; //base64
+ size += IMEI.Length();
+ size += KFLPrefixLength;
+
+ data = HBufC8::NewLC( size < KMaxOmaV1CIDLength ? KMaxOmaV1CIDLength : size );
+ des.Set( data->Des() );
+
+ GetFlURI( des );
+
+ tmp = DRMDB.GetDecryptionKeyL( *data );
+ CleanupStack::PushL( tmp );
+
+ // Get the data from client.
+ IPCREAD0L( des );
+ GenerateIVL( iv );
+
+ // Fits ok.
+ AesEncryptL( *tmp, iv, ETrue, des );
+
+ CleanupStack::PopAndDestroy( tmp );
+
+ // Fits ok.
+ des.Insert( 0, iv );
+
+ tmp = Base64EncodeL( *data );
+
+ __ASSERT_DEBUG( tmp->Length() + KFLPrefixLength + IMEI.Length() <= size,
+ User::Invariant() );
+
+ // Overwrite the original data.
+ des = KFLPrefix;
+ des.Append( IMEI );
+ des.Append( *tmp );
+
+ delete tmp;
+ tmp = NULL;
+
+ IPCWRITE0L( *data );
+
+ CleanupStack::PopAndDestroy( data );
+
+ aMessage.Complete( KErrNone );
+
+ __UHEAP_MARKEND;
+ }
+
+
+// ----------------------------------------------------------------------------
+// CDRMDbSession::
+//
+// ----------------------------------------------------------------------------
+//
+void CDRMDbSession::DecodeRightsIssuerL( const RMessage2& aMessage )
+ {
+ DRMLOG( _L( "CDRMDbSession::DecodeRightsIssuerL" ) );
+ __UHEAP_MARK;
+
+ HBufC8* data( NULL );
+ TInt size( IPCGETDESLEN0 );
+ TPtr8 des( NULL, 0, 0 );
+
+ if ( !size )
+ {
+ User::Leave( KErrArgument );
+ }
+
+ SanitizeL( size );
+
+ data = HBufC8::NewLC( size );
+ des.Set( data->Des() );
+
+ IPCREAD0L( des );
+
+ if ( des.Left( KFLPrefixLength ).Compare( KFLPrefix ) == 0 )
+ {
+ HBufC8* tmp( NULL );
+ HBufC8* tmp2( NULL );
+ TPtr8 des2( NULL, 0, 0 );
+
+ tmp = CnvUtfConverter::ConvertFromUnicodeToUtf8L( IMEI );
+ CleanupStack::PushL( tmp );
+
+ if ( des.Mid( KFLPrefixLength, IMEI.Length() ).Compare( *tmp ) )
+ {
+ User::Leave( KErrCANoPermission );
+ }
+
+ tmp2 = Base64DecodeL( des.Mid( KFLPrefixLength + tmp->Length() ) );
+
+ *data = *tmp2;
+
+ delete tmp2;
+ tmp2 = NULL;
+
+ CleanupStack::PopAndDestroy( tmp );
+
+ if ( ( data->Length() % KDCFKeySize ) ||
+ data->Length() < ( KDCFKeySize << 1 ) )
+ {
+ User::Leave( KErrArgument );
+ }
+
+ tmp = HBufC8::NewLC( KMaxOmaV1CIDLength );
+
+ des.Set( tmp->Des() );
+
+ GetFlURI( des );
+
+ tmp2 = DRMDB.GetDecryptionKeyL( *tmp );
+
+ CleanupStack::PopAndDestroy( tmp );
+ CleanupStack::PushL( tmp2 );
+
+ des2.Set( const_cast< TText8* >( data->Ptr() ),
+ KDCFKeySize,
+ KDCFKeySize );
+
+ // AesDecrypt overwrites the data.
+ des.Set( const_cast< TText8* >( data->Ptr() ) + KDCFKeySize,
+ data->Length() - KDCFKeySize,
+ data->Length() - KDCFKeySize );
+
+ AesDecryptL( *tmp2, des2, ETrue, des );
+
+ // Erase the key.
+ des2.Set( tmp2->Des() );
+ des2.FillZ();
+
+ CleanupStack::PopAndDestroy( tmp2 );
+
+ if( des.Length() > aMessage.GetDesMaxLength(1) )
+ {
+ User::Leave(KErrArgument);
+ }
+ IPCWRITE1L( des );
+ }
+
+ // Something else, can't handle it. Leave it as it is.
+ CleanupStack::PopAndDestroy( data );
+
+ aMessage.Complete( KErrNone );
+
+ __UHEAP_MARKEND;
+
+ DRMLOG( _L( "CDRMDbSession::DecodeRightsIssuerL ok" ) );
+ }
+
+// ----------------------------------------------------------------------------
+// CDRMDbSession::
+//
+// ----------------------------------------------------------------------------
+//
+void CDRMDbSession::GetFlURI( TDes8& aURI )
+ {
+ aURI = KFLLongPrefix;
+ aURI.Append( IMEI );
+ aURI.Append( KFLSuffix );
+ }
+
+// ----------------------------------------------------------------------------
+// CDRMDbSession::AesEncryptL
+// Encrypt data using a given key
+// ----------------------------------------------------------------------------
+//
+void CDRMDbSession::AesEncryptL( const TDesC8& aKey,
+ const TDesC8& aIV,
+ const TBool aAddPadding,
+ TDes8& aData )
+ {
+ DRMLOG( _L( "CDRMDbSession::AesEncryptL" ) );
+
+ __UHEAP_MARK;
+
+ CModeCBCEncryptor* cbc( NULL );
+ TInt lastBlockStart( 0 );
+ TPtr8 data( NULL, 0, 0 );
+
+ if( aIV.Length() % KDCFKeySize ||
+ aKey.Length() % KDCFKeySize )
+ {
+ User::Leave( KErrArgument );
+ }
+
+ cbc = CModeCBCEncryptor::NewL( CAESEncryptor::NewLC( aKey ), aIV );
+ CleanupStack::Pop(); // CAESEncryptor, owned by cbc.
+ CleanupStack::PushL( cbc );
+
+ lastBlockStart = aData.Length() - ( aData.Length() % KDCFKeySize );
+ for ( TInt i = 0; i < lastBlockStart; i+= KDCFKeySize )
+ {
+ data.Set( aData.MidTPtr( i, KDCFKeySize ) );
+
+ cbc->Transform( data );
+ }
+
+ if ( aAddPadding )
+ {
+ TInt dataLength = aData.Length();
+ TUint8 padding( static_cast< TUint8 >
+ ( lastBlockStart + KDCFKeySize - dataLength ) );
+
+ __ASSERT_DEBUG( lastBlockStart + KDCFKeySize - dataLength <= KDCFKeySize,
+ User::Invariant() );
+
+ aData.SetLength( lastBlockStart + KDCFKeySize );
+
+ for ( TInt i = dataLength; i < aData.Length(); ++i )
+ {
+ aData[ i ] = padding;
+ }
+
+ data.Set( aData.MidTPtr( lastBlockStart, KDCFKeySize ) );
+ cbc->Transform( data );
+ }
+
+ CleanupStack::PopAndDestroy( cbc );
+
+ __UHEAP_MARKEND;
+
+ DRMLOG( _L( "CDRMDbSession::AesEncryptL ok" ) );
+ }
+
+// ----------------------------------------------------------------------------
+// CDRMDbSession::AesDecryptL
+// Decrypt data using a given key
+// ----------------------------------------------------------------------------
+//
+void CDRMDbSession::AesDecryptL( const TDesC8& aKey,
+ const TDesC8& aIV,
+ const TBool aRemovePadding,
+ TDes8& aData )
+ {
+ DRMLOG( _L( "CDRMDbSession::AesDecryptL" ) );
+
+ __UHEAP_MARK;
+
+ CModeCBCDecryptor* cbc( NULL );
+
+ cbc = CModeCBCDecryptor::NewL(
+ CAESDecryptor::NewLC( aKey ), aIV );
+
+ CleanupStack::Pop(); // CAESDecryptor
+
+ __ASSERT_DEBUG( ( aData.Length() >= 0 ) &&
+ ( aData.Length() % KDCFKeySize == 0 ),
+ User::Invariant() );
+
+ for ( TInt count = 0; count < aData.Length(); count += KDCFKeySize )
+ {
+ TPtr8 d( aData.MidTPtr( count, KDCFKeySize ) );
+
+ cbc->Transform( d );
+ }
+
+ delete cbc; cbc = NULL;
+
+ if ( aRemovePadding )
+ {
+ TInt count( aData.Length() );
+ TUint8 c( aData[ count - 1 ] );
+
+ if ( c > KDCFKeySize )
+ {
+ User::Leave( KErrCorrupt );
+ }
+
+ aData.SetLength( count - c );
+ }
+
+ __UHEAP_MARKEND;
+
+ DRMLOG( _L( "CDRMDbSession::AesDecryptL ok" ) );
+ }
+
+// ----------------------------------------------------------------------------
+// CDRMDbSession::
+//
+// ----------------------------------------------------------------------------
+//
+void CDRMDbSession::GenerateIVL( TDes8& aIV )
+ {
+ DRMLOG( _L( "CDRMDbSession::GenerateIVL" ) );
+ __UHEAP_MARK;
+
+ __ASSERT_DEBUG( aIV.MaxSize() >= KDCFKeySize, User::Invariant() );
+ MDrmKeyStorage* storage = DrmKeyStorageNewL();
+ TCleanupItem storageCleanup( DeleteObject, storage );
+ CleanupStack::PushL(storageCleanup);
+
+ storage->RandomDataGetL(aIV,KDCFKeySize);
+ CleanupStack::PopAndDestroy( storage );
+
+ DRMLOG(_L("random aIV:"));
+ DRMLOGHEX(aIV);
+
+
+ __UHEAP_MARKEND;
+ DRMLOG( _L( "CDRMDbSession::GenerateIVL ok" ) );
+ }
+
+// ----------------------------------------------------------------------------
+// CDRMDbSession::
+//
+// ----------------------------------------------------------------------------
+//
+void CDRMDbSession::AsyncOperationDone()
+ {
+ DRMLOG( _L( "CDRMDbSession::AsyncOperationDone" ) );
+ // All done.
+ delete iPendingRequest;
+ iPendingRequest = NULL;
+ }
+
+// ----------------------------------------------------------------------------
+// CDRMDbSession::
+//
+// ----------------------------------------------------------------------------
+//
+void CDRMDbSession::AsyncOperationDone( TFileName* aFileName )
+ {
+ DRMLOG( _L( "CDRMDbSession::AsyncOperationDone" ) );
+ // All done.
+ delete iPendingRequest;
+ iPendingRequest = NULL;
+
+ iFileName = aFileName;
+ }
+
+
+// ----------------------------------------------------------------------------
+// CDRMDbSession::SetAuthenticationSeedL
+// Sets the authentication seed for a content ID. Requires that the REK and KEK
+// have been set during a previous AddRecord operation
+// ----------------------------------------------------------------------------
+//
+void CDRMDbSession::SetAuthenticationSeedL( const RMessage2& aMessage )
+ {
+ DRMLOG(_L("CDRMDbSession::SetAuthenticationSeedL"));
+
+ __UHEAP_MARK;
+ SanitizeL( aMessage.GetDesLength(0));
+ SanitizeL( aMessage.GetDesLength(1));
+
+ HBufC8* cid = HBufC8::NewLC(IPCGETDESLEN0);
+ HBufC8* wrappedSeed = HBufC8::NewLC(IPCGETDESLEN1);
+ HBufC8* seed = NULL;
+
+ if (iRek.Length() == 0)
+ {
+ User::Leave(KErrNotReady);
+ }
+
+ TPtr8 tmp(cid->Des());
+ IPCREAD0L(tmp );
+ TPtr8 tmp2(wrappedSeed->Des());
+ IPCREAD1L(tmp2);
+
+ seed = OmaCrypto::AesUnwrapL(iRek, *wrappedSeed);
+ CleanupStack::PushL(seed);
+ DRMDB.SetAuthenticationSeedL(*cid, *seed);
+ CleanupStack::PopAndDestroy(3); // seed, wrappedSeed, cid
+ __UHEAP_MARKEND;
+ aMessage.Complete(KErrNone);
+ }
+
+// ----------------------------------------------------------------------------
+// CDRMDbSession::GetAuthenticationSeedL
+// Returns the authentication seed for a content ID
+// ----------------------------------------------------------------------------
+//
+void CDRMDbSession::GetAuthenticationSeedL( const RMessage2& aMessage )
+ {
+ DRMLOG(_L("CDRMDbSession::GetAuthenticationSeedL"));
+
+ __UHEAP_MARK;
+ HBufC8* cid = NULL;
+ HBufC8* seed = NULL;
+
+ SanitizeL( aMessage.GetDesLength(0));
+ cid = HBufC8::NewLC(IPCGETDESLEN0);
+
+ TPtr8 tmp(cid->Des());
+ IPCREAD0L(tmp);
+ User::LeaveIfError(VerifyCredentials(cid, NULL, EUnknown));
+ seed = DRMDB.GetAuthenticationSeedL(*cid);
+ CleanupStack::PushL(seed);
+
+ if( seed->Length() > aMessage.GetDesMaxLength(1) )
+ {
+ User::Leave(KErrArgument);
+ }
+
+ IPCWRITE1L(*seed);
+ CleanupStack::PopAndDestroy(2); // seed, cid
+ __UHEAP_MARKEND;
+ aMessage.Complete(KErrNone);
+ }
+
+// ----------------------------------------------------------------------------
+// CDRMDbSession::VerifyMacL
+// Integrity protection for protecets ROs
+// ----------------------------------------------------------------------------
+//
+void CDRMDbSession::VerifyMacL( const RMessage2& aMessage )
+ {
+ DRMLOG(_L("CDRMDbSession::VerifyMacL"));
+
+ if( !iMac.Length() )
+ {
+ User::Leave(KErrNotReady);
+ }
+
+ __UHEAP_MARK;
+
+ CHMAC* hMac = NULL;
+ CSHA1* sha = NULL;
+ TPtrC8 hmac_value( KNullDesC8 );
+ TPtrC8 sha1_value( KNullDesC8 );
+ HBufC8* signedInfo = NULL;
+ HBufC8* macValue = NULL;
+ TInt ret = KErrNone;
+
+ signedInfo = HBufC8::NewLC(IPCGETDESLEN0);
+ TPtr8 signedInfoPtr(signedInfo->Des());
+ macValue = HBufC8::NewLC(IPCGETDESLEN1);
+ TPtr8 macValuePtr(macValue->Des());
+
+ IPCREAD0L(signedInfoPtr);
+ IPCREAD1L(macValuePtr);
+
+ DRMLOG(_L("Signed info:"));
+ DRMLOGHEX(signedInfoPtr);
+ DRMLOG(_L("MAC value:"));
+ DRMLOGHEX(macValuePtr);
+
+ sha = CSHA1::NewL();
+ CleanupStack::PushL( sha );
+ hMac = CHMAC::NewL( iMac, sha );
+ CleanupStack::Pop( sha ); // sha is now owned by hMac
+ CleanupStack::PushL( hMac );
+ hMac->Update( signedInfoPtr );
+ hmac_value.Set( hMac->Final() );
+
+ DRMLOG(_L("Calculated MAC value:"));
+ DRMLOGHEX(hmac_value);
+ if ( hmac_value.Compare( macValuePtr ) != 0 )
+ {
+ // MAC validation failed
+ ret = KErrRightsServerMacFailed;
+ }
+
+ CleanupStack::PopAndDestroy(3, signedInfo); // hMac, macValue, signedInfo
+ __UHEAP_MARKEND;
+ aMessage.Complete(ret);
+ }
+
+// ----------------------------------------------------------------------------
+// CDRMDbSession::GetSupportedIndividualsL
+// ----------------------------------------------------------------------------
+//
+void CDRMDbSession::GetSupportedIndividualsL( const RMessage2& aMessage )
+ {
+ DRMLOG( _L( "CDRMDbSession::GetSupportedIndividualsL" ) );
+ TPckgBuf< TInt > size( 0 );
+ TInt stringSize = 0;
+ TInt offset = 0;
+ TUint8* ptr = 0;
+
+ // Cleanup.
+ if ( iPreparedData )
+ {
+ delete iPreparedData;
+ iPreparedData = NULL;
+ }
+
+ for ( TInt i = 0; i < IMSI.Count(); i++ )
+ {
+ stringSize += sizeof(TInt);
+ stringSize += IMSI[i]->Size();
+ }
+
+
+ // If it's empty, just return right away
+ if( !stringSize )
+ {
+ IPCWRITE0L( size );
+ aMessage.Complete(KErrNone);
+ return;
+ }
+
+ // Otherwise create a buffer and fill it:
+ iPreparedData = HBufC8::NewMaxL( stringSize );
+ ptr = const_cast<TUint8*>( iPreparedData->Ptr() );
+
+ size() = stringSize;
+
+ for( TInt i = 0; i < IMSI.Count(); i++ )
+ {
+ // Write the size:
+ stringSize = IMSI[i]->Size();
+ Mem::Copy(ptr+offset, &stringSize, sizeof(TInt));
+ offset += sizeof(TInt);
+
+ // Write the data:
+ Mem::Copy(ptr+offset, IMSI[i]->Ptr(), IMSI[i]->Size());
+ offset += IMSI[i]->Size();
+ }
+ IPCWRITE0L( size );
+
+ aMessage.Complete( KErrNone );
+ }
+
+// ----------------------------------------------------------------------------
+// CDRMDbSession::StopWatchingL
+// ----------------------------------------------------------------------------
+//
+void CDRMDbSession::StopWatchingL( const RMessage2& aMessage )
+ {
+ _LIT_SECURITY_POLICY_S0( sidCheck, KTrustedShutdownClient );
+ if ( sidCheck.CheckPolicy( aMessage ) )
+ {
+ SERVER->StopWatchingL();
+ }
+ aMessage.Complete( KErrNone );
+ }
+
+// ----------------------------------------------------------------------------
+// CDRMDbSession::DeleteAllowedL
+// ----------------------------------------------------------------------------
+//
+TBool CDRMDbSession::DeleteAllowedL( const TDesC8& aContentId )
+ {
+ TBuf8< KMaxOmaV1CIDLength > URI;
+
+ // Get the FL uri
+ GetFlURI( URI );
+
+ if( aContentId.Compare( URI ) &&
+ aContentId.Compare( KDCMUri ) &&
+ aContentId.Compare( KLDFUri ) )
+ {
+ return ETrue;
+ }
+ return EFalse;
+ }
+
+// ----------------------------------------------------------------------------
+// CDRMDbSession::GetRandomDataL
+// ----------------------------------------------------------------------------
+//
+void CDRMDbSession::GetRandomDataL( const RMessage2& aMessage )
+ {
+ DRMLOG(_L("CDRMDbSession::GetRandomDataL"));
+
+ HBufC8* data = NULL;
+ SanitizeL( aMessage.GetDesMaxLength(0) );
+ SanitizeL( aMessage.GetDesLength(0));
+
+ data = HBufC8::NewMaxLC(IPCGETDESLEN0);
+ TPtr8 ptr(data->Des());
+
+ MDrmKeyStorage* storage = DrmKeyStorageNewL();
+ TCleanupItem storageCleanup( DeleteObject, storage );
+ CleanupStack::PushL(storageCleanup);
+ storage->RandomDataGetL(ptr,ptr.Size());
+ IPCWRITE0L(*data);
+
+ CleanupStack::PopAndDestroy(2, data);
+ aMessage.Complete( KErrNone );
+ }
+
+// -----------------------------------------------------------------------------
+// CDRMDbSession::GetMeteringDataL
+// -----------------------------------------------------------------------------
+//
+void CDRMDbSession::GetMeteringDataL( const RMessage2& aMessage )
+ {
+#ifndef RD_DRM_METERING
+ aMessage.Complete ( KErrNotSupported );
+#else
+ HBufC8* riId = NULL;
+ HBufC8* meteringData = NULL;
+ CDRMPointerArray<CDrmMeteringDbData>* meteringArray =
+ CDRMPointerArray<CDrmMeteringDbData>::NewLC();
+ meteringArray->SetAutoCleanup( ETrue );
+
+ TInt size = 0;
+ TPtr8 data( NULL, 0 );
+ TPckg<TInt> package( size );
+
+ SanitizeL( aMessage.GetDesLength(0));
+ // Empty old data
+ delete iPreparedData;
+ iPreparedData = NULL;
+
+ riId = HBufC8::NewLC( User::LeaveIfError( IPCGETDESLEN1 ) );
+ data.Set( riId->Des() );
+ IPCREAD1L( data );
+
+ if ( METERINGDB.GetL( *riId, *meteringArray ) )
+ {
+ meteringData = CreateMeteringDataL( meteringArray );
+ CleanupStack::PushL( meteringData );
+ }
+ else
+ {
+ _LIT8( KEmptyMetering, "<rawMeteringReportData>\r\n</rawMeteringReportData>");
+ meteringData = KEmptyMetering().AllocLC();
+ }
+ DRMLOGHEX( *meteringData );
+ size = meteringData->Size();
+ iPreparedData = meteringData;
+ CleanupStack::Pop( meteringData );
+
+ IPCWRITE0L( package );
+ CleanupStack::PopAndDestroy( 2 ); // riId, meteringArray
+ if ( !iPreparedData )
+ {
+ aMessage.Complete( KErrNotFound );
+ return;
+ }
+ aMessage.Complete( KErrNone );
+#endif
+ }
+
+// -----------------------------------------------------------------------------
+// CDRMDbSession::DeleteMeteringDataL
+// -----------------------------------------------------------------------------
+//
+void CDRMDbSession::DeleteMeteringDataL( const RMessage2& aMessage )
+ {
+#ifndef RD_DRM_METERING
+ aMessage.Complete ( KErrNotSupported );
+#else
+// Metering supported
+ HBufC8* riId = NULL;
+ TPtr8 data( NULL, 0 );
+ TBool meteringDataDeleted;
+
+ riId = HBufC8::NewLC( User::LeaveIfError( IPCGETDESLEN0 ) );
+ data.Set( riId->Des() );
+ IPCREAD0L( data );
+ meteringDataDeleted = METERINGDB.DeleteL( *riId );
+
+ if( meteringDataDeleted )
+ {
+ DRMLOG( _L("CDRMDbSession::DeleteMeteringDataL -> some records were destroyed") );
+ }
+ // Do we have to do something else?
+ CleanupStack::PopAndDestroy( riId );
+ aMessage.Complete( KErrNone );
+#endif
+ }
+// -----------------------------------------------------------------------------
+// CDRMDbSession::ConnectRoapClient()
+// -----------------------------------------------------------------------------
+//
+TInt CDRMDbSession::ConnectRoapClient()
+ {
+ if( iRoapClientConnected )
+ {
+ return KErrNone;
+ }
+ TInt err( iRoapClient.Connect() );
+ if ( !err )
+ {
+ iRoapClientConnected = ETrue;
+ }
+ return err;
+ }
+
+// End of File