# HG changeset patch # User Tom Pritchard # Date 1288182242 -3600 # Node ID ca165d35976d87c9b8d8023b6e0b2599ea706f56 # Parent e9fb2728ea8bacacf5200e7cdd6a12d50f7d79c0 Adding parts of the DRM Engine to be rebuilt diff -r e9fb2728ea8b -r ca165d35976d breakdeps/DRMEngine/DRMClock.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/breakdeps/DRMEngine/DRMClock.cpp Wed Oct 27 13:24:02 2010 +0100 @@ -0,0 +1,402 @@ +/* +* Copyright (c) 2003-2009 Nokia Corporation and/or its subsidiary(-ies). +* All rights reserved. +* This component and the accompanying materials are made available +* under the terms of "Eclipse Public License v1.0" +* which accompanies this distribution, and is available +* at the URL "http://www.eclipse.org/legal/epl-v10.html". +* +* Initial Contributors: +* Nokia Corporation - initial contribution. +* +* Contributors: +* +* Description: Implementation of the DRM Clock +* +*/ + + +// INCLUDE FILES + +#include + +#include "DRMClock.h" +#include "drmlog.h" +#include "DRMEventTimeChange.h" +#include "wmdrmfileserverclient.h" + +#include +#include +#include +#include +#include + +#ifdef RD_MULTIPLE_DRIVE +#include +#endif + +#include "DRMNitzObserver.h" +#include "GPSWatcher.h" + +// EXTERNAL DATA STRUCTURES + +// EXTERNAL FUNCTION PROTOTYPES + +// CONSTANTS +const TInt KMinuteInMicroseconds = 60000000; +const TInt KTimeZoneIncrement = 15; + +// The time zones sanity check values, not sure if -13 hours exists +// But atleast +13 does in: Nuku'Alofa +const TInt KTimeZoneLow = -52; // -13 hours +const TInt KTimeZoneHigh = 55; // +13 hours 45 minutes Some NZ owned island + + +// MACROS + +// LOCAL CONSTANTS AND MACROS + +// MODULE DATA STRUCTURES + +// LOCAL FUNCTION PROTOTYPES + +// FORWARD DECLARATIONS + +// ============================= LOCAL FUNCTIONS =============================== + + +// ============================ MEMBER FUNCTIONS =============================== + + +// ----------------------------------------------------------------------------- +// CDRMRightsDB::CDRMRightsDB +// C++ default constructor can NOT contain any code, that +// might leave. +// ----------------------------------------------------------------------------- +// +CDRMClock::CDRMClock() + { + }; + +// ----------------------------------------------------------------------------- +// CDRMRightsDB::ConstructL +// Symbian 2nd phase constructor can leave. +// ----------------------------------------------------------------------------- +// +void CDRMClock::ConstructL() + { + DRMLOG( _L( "DRM Clock Starting: " ) ); + TInt error = KErrNone; + + // Create a notifier instance + iNotifier = CDRMNotifier::NewL(); + +#ifndef __WINS__ + ConnectToPhoneL(); + + iObserver = CDRMNitzObserver::NewL( iPhone, const_cast(this)); + + iObserver->Start(); + + TRAP( error, iGpsWatcher = CGPSWatcher::NewL( const_cast(this) )); + DRMLOG2( _L("DRMClock: GPS watcher started: %d"), error ); +#endif + + DRMLOG( _L( "DRM Clock started" ) ); + }; + +// ----------------------------------------------------------------------------- +// CDRMClock::NewLC +// Two-phased constructor +// ----------------------------------------------------------------------------- +// +CDRMClock* CDRMClock::NewLC() + { + DRMLOG( _L( "CDRMClock::NewLC" ) ); + + CDRMClock* self = new(ELeave) CDRMClock; + CleanupStack::PushL( self ); + self->ConstructL(); + + DRMLOG( _L( "CDRMClock::NewLC ok" ) ); + + return self; + }; + +// ----------------------------------------------------------------------------- +// CDRMClock::NewL +// Two-phased constructor +// ----------------------------------------------------------------------------- +// +CDRMClock* CDRMClock::NewL() + { + DRMLOG( _L( "CDRMClock::NewL" ) ); + + CDRMClock* self = NewLC(); + CleanupStack::Pop(); + + DRMLOG( _L( "CDRMClock::NewL ok" ) ); + + return self; + }; + +// --------------------------------------------------------- +// CDRMClock::~CDRMClock +// Destructor +// --------------------------------------------------------- +// +CDRMClock::~CDRMClock() + { + DRMLOG( _L( "CDRMClock::~CDRMClock" ) ); + + if( iNotifier ) + { + delete iNotifier; + iNotifier = 0; + } + +#ifndef __WINS__ + if(iObserver) + { + iObserver->Cancel(); + delete iObserver; + iObserver = 0; + } + + if( iGpsWatcher ) + { + iGpsWatcher->Cancel(); + delete iGpsWatcher; + iGpsWatcher = 0; + } +#endif // __WINS__ + }; + +// ----------------------------------------------------------------------------- +// CDRMClock::GetSecureTime +// returns time and security level +// ----------------------------------------------------------------------------- +// +void CDRMClock::GetSecureTime(TTime& aTime, TInt& aTimeZone, + DRMClock::ESecurityLevel& aSecurityLevel) + { + DRMLOG( _L( "CDRMClock::GetSecureTime" ) ); + + TTime currentUniversal; + TTime currentHome; + TInt error = KErrNone; + + // if there is an error it's not initialized + error = aTime.UniversalTimeSecure(); + + if( error == KErrNoSecureTime ) + { + currentHome.HomeTime(); + currentUniversal.UniversalTime(); + + aTimeZone = ( currentHome.Int64() - currentUniversal.Int64() ) / + ( KMinuteInMicroseconds* KTimeZoneIncrement ); + + + aTime.UniversalTime(); + + aSecurityLevel = DRMClock::KInsecure; + + DRMLOG( _L( "CDRMClock::GetSecureTime: DRMClock is Insecure" ) ); + } + else + { + currentHome.HomeTimeSecure(); + currentUniversal.UniversalTimeSecure(); + + aTimeZone = ( currentHome.Int64() - currentUniversal.Int64() ) / + ( KMinuteInMicroseconds* KTimeZoneIncrement ); + + aSecurityLevel = DRMClock::KSecure; + DRMLOG( _L( "CDRMClock::GetSecureTime: DRMClock is Secure" ) ); + } + + DRMLOG( _L( "CDRMClock::GetSecureTime ok" ) ); + }; + + +// ----------------------------------------------------------------------------- +// CDRMClock::ResetSecureTimeL +// resets the secure time and recalculates the offsets +// should not reset to 0 +// ----------------------------------------------------------------------------- +// +// Do not reset the timezone, use whatever has been set or retrieved from the UI time +// However check that the timezone is a valid one just in case +void CDRMClock::ResetSecureTimeL( const TTime& aTime, const TInt& aTimeZone ) + { + DRMLOG( _L( "CDRMClock::ResetSecureTimeL" ) ); + + TRequestStatus status; + TInt error = KErrNone; + CDRMEventTimeChange* change = CDRMEventTimeChange::NewLC(); + TTime previousTime; + TTime previousTimeLocal; + TTime newTime; + TInt timezone = 0; + TDateTime temppi; // Only for logging + + // check for param that the time is even reasonably valid: + if( aTime.Int64() == 0 ) + { + DRMLOG( _L("Trying to reset to zero time") ); + User::Leave( KErrArgument ); + } + + // Sanity check: Time zone has to be +/- certail hours + // for this check -13h to +13.75h + if( aTimeZone < KTimeZoneLow || aTimeZone > KTimeZoneHigh ) + { + DRMLOG2( _L("TimeZone invalid, time may be as well, aborting change: %d"), aTimeZone ); + User::Leave( KErrArgument ); + } + + + // Get the current secure time with timezone + // Ask the hometime first so that rounding of any divider goes correctly + error = previousTimeLocal.HomeTimeSecure(); + + // If there is an error, the secure hometime has not been set + // Which means that the UI clock has the valid data + if( error ) + { + previousTimeLocal.HomeTime(); + previousTime.UniversalTime(); + timezone = ( previousTimeLocal.Int64() - previousTime.Int64() ) / + ( KMinuteInMicroseconds* KTimeZoneIncrement ); + change->SetOldSecurityLevel( DRMClock::KInsecure ); + } + else + { + previousTime.UniversalTimeSecure(); + + timezone = ( previousTimeLocal.Int64() - previousTime.Int64() ) / + ( KMinuteInMicroseconds* KTimeZoneIncrement ); + + change->SetOldSecurityLevel( DRMClock::KSecure ); + change->SetNewSecurityLevel( DRMClock::KSecure ); + } + + // Since it's not important to get the timezone we keep what is set or reset it: + previousTimeLocal = aTime.Int64() + ( timezone * ( KMinuteInMicroseconds* KTimeZoneIncrement ) ); + + // Do the actual updating: + // Update using the wmdrm fileserver since it has TCB capability + RWmDrmFileServerClient resetclient; + User::LeaveIfError( resetclient.Connect() ); + CleanupClosePushL( resetclient ); + + newTime = aTime; + User::LeaveIfError( resetclient.UpdateSecureTime( previousTimeLocal, newTime ) ); + + CleanupStack::PopAndDestroy(); + + + DRMLOG( _L( "CDRMClock::ResetSecureTimeL: AFTER RESET." )); + + // DRM Notifier data: + // send info about the change: + + change->SetNewSecurityLevel( DRMClock::KSecure ); + + change->SetOldTime( previousTime ); + change->SetOldTimeZone( timezone ); + + change->SetNewTime( aTime ); + change->SetNewTimeZone( timezone ); + + // Notify clients + + iNotifier->SendEventL(*change,status); + User::WaitForRequest(status); + CleanupStack::PopAndDestroy(); + + DRMLOG( _L( "CDRMClock::ResetSecureTimeL ok" ) ); + }; + +// --------------------------------------------------------- +// CDRMClock::Notify +// Notify DRM clock about an event +// --------------------------------------------------------- +// +void CDRMClock::Notify( TInt aNotify ) + { + switch( aNotify ) + { + case ENotifyGPSTimeReceived: + // GPS time received, listen again after the next boot, destroy GPS watcher: + DRMLOG(_L("Notify: ENotifyGPSTimeReceived, Deleting GPS watcher")); + delete iGpsWatcher; + iGpsWatcher = NULL; + DRMLOG(_L("Notify: GPS Watcher deleted")); + break; + case ENotifyNone: + default: + break; // Do nothing + } + } + + + + + +// --------------------------------------------------------- +// CDRMClock::ConnectToPhoneL(const TDateTime& aDateTime) +// Gets the nitz time from iNitzInfo +// --------------------------------------------------------- +// +void CDRMClock::ConnectToPhoneL() + { + DRMLOG( _L( "CDRMClock::ConnectToPhoneL" ) ); + + const TInt KTriesToConnectServer(10); + const TInt KTimeBeforeRetryingServerConnection(100000); + TInt thisTry(0); + TInt err(KErrNone); + TInt numPhone; + TName tsyName; + RTelServer::TPhoneInfo phoneInfo; + RMobilePhone::TMobilePhoneSubscriberId imsi; + TRequestStatus status; + + + while ((err = iEtelServer.Connect()) != KErrNone && + (thisTry++) <= KTriesToConnectServer) + { + User::After(KTimeBeforeRetryingServerConnection); + } + User::LeaveIfError(err); + + User::LeaveIfError(iEtelServer.LoadPhoneModule(KMmTsyModuleName)); + User::LeaveIfError(iEtelServer.EnumeratePhones(numPhone)); + + for (TInt i(0); i < numPhone; i++) + { + User::LeaveIfError(iEtelServer.GetPhoneInfo(i, phoneInfo)); + User::LeaveIfError(iEtelServer.GetTsyName(i,tsyName)); + + if (tsyName.CompareF(KMmTsyModuleName) == 0) + { + break; + } + } + + User::LeaveIfError(iPhone.Open(iEtelServer, phoneInfo.iName)); + + iPhone.GetSubscriberId( status, imsi ); + User::WaitForRequest( status ); + + DRMLOG( imsi ); + DRMLOG( _L( "CDRMClock::ConnectToPhoneL ok" ) ); + }; + + +// ========================== OTHER EXPORTED FUNCTIONS ========================= + + +// End of File diff -r e9fb2728ea8b -r ca165d35976d breakdeps/DRMEngine/DRMClock.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/breakdeps/DRMEngine/DRMClock.h Wed Oct 27 13:24:02 2010 +0100 @@ -0,0 +1,170 @@ +/* +* Copyright (c) 2003-2009 Nokia Corporation and/or its subsidiary(-ies). +* All rights reserved. +* This component and the accompanying materials are made available +* under the terms of "Eclipse Public License v1.0" +* which accompanies this distribution, and is available +* at the URL "http://www.eclipse.org/legal/epl-v10.html". +* +* Initial Contributors: +* Nokia Corporation - initial contribution. +* +* Contributors: +* +* Description: Interface for the DRMClock +* +*/ + + +#ifndef DRMCLOCK_H +#define DRMCLOCK_H + +// INCLUDES + +#include // CBase +#include +#include // Type definitions +#include +#include +#include +#include + +// CONSTANTS + +// MACROS + +// DATA TYPES + +// FUNCTION PROTOTYPES + +// FORWARD DECLARATIONS +class CDRMNitzObserver; +class CDRMNotifier; +class CGPSWatcher; + +// CLASS DECLARATION + +/** +* CDRMClock implements the drm clock required by DRM Engine +* +* @lib unipertar.exe +* @since 2.8 +*/ +NONSHARABLE_CLASS( CDRMClock ) + { + public: + // Notifications: + enum + { + ENotifyNone = 0, + ENotifyGPSTimeReceived = 1 + }; + + public: + + /** + * NewLC + * + * Creates an instance of the CDRMClock class and returns a pointer to it + * The function leaves the object into the cleanup stack + * + * @since 2.8 + * @return Functional CDRMClock object, Function leaves if an error occurs. + */ + static CDRMClock* NewLC(); + + /** + * NewL + * + * Creates an instance of the CDRMClock class and returns a pointer to it + * + * @since 2.8 + * @return Functional CDRMClock object, Function leaves if an error occurs. + */ + static CDRMClock* NewL(); + + /** + * Destructor + */ + virtual ~CDRMClock(); + + /** + * GetSecureTime + * + * Return the current time and the security of the current time + * + * @since 2.8 + * @param aTime : return parameter for time in UTC + * @param aTimeZone : return parameter for the timezone in +/-15 minutes + * @param aSecurityLevel : return parameter for security level + * @return none + */ + void GetSecureTime(TTime& aTime, TInt& aTimeZone, + DRMClock::ESecurityLevel& aSecurityLevel); + + /** + * ResetSecureTimeL + * + * Resets the secure time source and recalculates the offsets + * + * @since 2.8 + * @param aSecureTime, the new secure time in UTC + * @param aTimeZone, the time zone of the new secure time in +/- 15 minutes + * @return none, Function leaves with Symbian OS error code if an + * error occurs + */ + void ResetSecureTimeL( const TTime& aSecureTime, const TInt& aTimeZone ); + + + /** + * Notify + * + * Notifies about an event to the DRM Clock + * + * @since 9.2 + * @param Message The notification event + * + */ + void Notify( TInt aMessage ); + + protected: + private: + /** + * Default Constructor - First phase + */ + CDRMClock(); + + /** + * ConstructL + * + * Second phase constructor + * + * @since 2.8 + * @return Leaves if an error occurs + */ + void ConstructL(); + + /** + * ConnectToPhoneL + * + * Connects to the phone services + * + * @since 2.8 + * @return Leaves with symbian os error codes if an error occurs + */ + void ConnectToPhoneL(); + + // Variables + CDRMNotifier* iNotifier; + + // Nitz information handles + RTelServer iEtelServer; + RMobilePhone iPhone; + CDRMNitzObserver* iObserver; + + // GPS watcher component, updates DRM time from GPS if available + CGPSWatcher* iGpsWatcher; + }; +#endif // DRMCLOCK_H + +// End of File diff -r e9fb2728ea8b -r ca165d35976d breakdeps/DRMEngine/DRMRightsServer.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/breakdeps/DRMEngine/DRMRightsServer.cpp Wed Oct 27 13:24:02 2010 +0100 @@ -0,0 +1,1543 @@ +/* +* Copyright (c) 2003 - 2007 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: DRM3 Engine manages all DRM related database operations. +* +*/ + + +// INCLUDE FILES +#include +#include +#include +#include +#include +#include + +#ifdef RD_MULTIPLE_DRIVE +#include +#endif + +#include "DRMRightsServer.h" +#include "drmrightsdb.h" +#include "DRMDbSession.h" +#include "DRMEngineClientServer.h" +#include "drmlog.h" +#include "DRMNotifier.h" +#include "DrmKeyStorage.h" +#include "DRMNotifierServer.h" +#include "RoapStorageServer.h" +#include "drmnotifierclientserver.h" +#include "drmroapclientserver.h" +#include "DRMXOma.h" +#include "DRMBackupObserver.h" +#include "DRMBackup.h" +#include "flogger.h" +#include "DrmRightsParser.h" +#include "DRMRights.h" +#include "DRMHelperCommon.h" + +#include "wmdrmclientwrapper.h" + + + +#ifdef __DRM_CLOCK +#include "DRMClockServer.h" +#include "drmclockclientserver.h" +#endif + +#include +#include + +/* +_LIT( KLogDir, "drm"); +_LIT( KLogName, "backup.log"); +*/ + +// EXTERNAL DATA STRUCTURES +// EXTERNAL FUNCTION PROTOTYPES +// CONSTANTS +LOCAL_C const TUint KMaxHeapsize = 0x7A120; + +_LIT8( KImsiId,"IMSI:"); + +// MACROS +#ifdef _DRM_TESTING +_LIT( KDateTimeFormat, "%F%Y%M%D%H%T%S%C" ); +#endif + +// LOCAL CONSTANTS AND MACROS +const TUint8 KMaxStartTries = 30; +const TInt KWaitingTime = 2000000; // 2 sec +_LIT( KRightsServerThread, "RightsServer" ); + +#ifdef RD_MULTIPLE_DRIVE + +_LIT( KDbTempPath, "%c:\\system\\temp\\" ); +_LIT( KIndividualConstraintExtensionDll, "%c:\\sys\\bin\\DRMIndividualConstraintExtension.dll" ); +_LIT( KRightsDir, "%c:\\private\\101F51F2\\rdb\\" ); +_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 + +#define USE_RO_IMPORT + +#ifdef USE_RO_IMPORT +_LIT( KInternalImportDir, "%c:\\private\\101F51F2\\import\\" ); +_LIT( KUserDiskImportDir, "%c:\\import\\" ); // usually embedded MMC +_LIT( KUserRemovableDiskImportDir, "%c:\\import\\" ); // usually external MMC +_LIT( KDrSuffix, ".dr" ); +#endif + +#else + +_LIT( KRightsDir, "c:\\private\\101F51F2\\rdb\\" ); +_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 + +#define USE_RO_IMPORT + +#ifdef USE_RO_IMPORT +_LIT( KInternalImportDir, "c:\\private\\101F51F2\\import\\" ); +_LIT( KUserDiskImportDir, "e:\\import\\" ); +_LIT( KDrSuffix, ".dr" ); +#endif + +#endif + +_LIT(KWmDrmClientWrapperName, "wmdrmclientwrapper.dll"); + +// MODULE DATA STRUCTURES + +NONSHARABLE_STRUCT( TUnloadModule ) + { + RTelServer* iServer; + const TDesC* iName; + }; + +// LOCAL FUNCTION PROTOTYPES + +LOCAL_C TInt Startup( void ); +LOCAL_C void SignalClient(); +LOCAL_C TInt StartDBServer( void ); + +#if defined( __WINS__ ) +#else +#define DRM_USE_SERIALNUMBER_URI +#include +#endif + + +#ifdef DRM_USE_SERIALNUMBER_URI +LOCAL_C void DoUnloadPhoneModule( TAny* aAny ); +#endif + +// #define USE_RO_IMPORT + +// FORWARD DECLARATIONS + +// ============================= LOCAL FUNCTIONS =============================== +// ----------------------------------------------------------------------------- +// Function Startup(). +// This function starts the actual DRM Rights server after initializing +// the cleanup stack and active scheduler. +// Returns: TInt: Symbian OS error code. +// ----------------------------------------------------------------------------- +// +LOCAL_C TInt Startup( void ) + { + TInt error = KErrNone; + CTrapCleanup* trap = CTrapCleanup::New(); + CActiveScheduler* scheduler = new CActiveScheduler(); + + if ( trap && scheduler ) + { + CActiveScheduler::Install( scheduler ); + + error = StartDBServer(); + } + else + { + error = KErrNoMemory; + } + + delete scheduler; + scheduler = NULL; + + delete trap; + trap = NULL; + + if ( error ) + { + // Something went wrong. Release the client (if any). + SignalClient(); + + if ( error == KErrAlreadyExists ) + { + error = KErrNone; + } + } + + return error; + } + +// ----------------------------------------------------------------------------- +// Function SignalClient(). +// Signal the waiting client (one of them if any exists). +// ----------------------------------------------------------------------------- +// +void SignalClient( void ) + { + RSemaphore semaphore; + if ( !semaphore.OpenGlobal( DRMEngine::KDRMSemaphore ) ) + { + semaphore.Signal(); + semaphore.Close(); + } + } + +// ----------------------------------------------------------------------------- +// Function StartDBServer(). +// This function starts the actual server under TRAP harness and starts +// waiting for connections. This function returns only if there has been +// errors during server startup or the server is stopped for some reason. +// +// Returns: TInt: Symbian OS error code. +// ----------------------------------------------------------------------------- +TInt StartDBServer( void ) + { + TInt error = KErrNone; + CDRMRightsServer* server = NULL; + TUint8 count = 0; + + do + { + DRMLOG2( _L( "RightsServer.exe: StartDBServer: %d" ), error ); + + ++count; + + TRAP( error, ( server = CDRMRightsServer::NewL() ) ); + + if ( error ) + { + User::After( TTimeIntervalMicroSeconds32(KWaitingTime) ); + } + + } while( error && ( count <= KMaxStartTries ) ); + + if( error ) + { + DRMLOG2( _L( "RightsServer.exe: CDRMRightsServer::NewL failed: %d " ), error ); + // Failed + return error; + } + + // Release the semaphore if necessary. + SignalClient(); + + // Start waiting for connections + CActiveScheduler::Start(); + + // Dying... + // Delete CDRMRigntsServer + + DRMLOG( _L( "RightsServer.exe: DB server dying..." ) ); + + delete server; + + return KErrNone; + } + +#ifdef DRM_USE_SERIALNUMBER_URI +// ----------------------------------------------------------------------------- +// Function DoUnloadPhoneModule +// Unload phone module +// ----------------------------------------------------------------------------- +// +void DoUnloadPhoneModule( TAny* aAny ) + { + __ASSERT_DEBUG( aAny, User::Invariant() ); + TUnloadModule* module = ( TUnloadModule* ) aAny; + module->iServer->UnloadPhoneModule( *( module->iName ) ); + } +#endif + +#ifdef USE_RO_IMPORT +// ----------------------------------------------------------------------------- +// PointerArrayResetDestroyAndClose +// Template method used to push RPointerArrays to the cleanup stack. Takes +// care of deleting all pointers in the array. +// ----------------------------------------------------------------------------- +// +template +void PointerArrayResetDestroyAndClose(TAny* aPtr) + { + (reinterpret_cast*>(aPtr))->ResetAndDestroy(); + (reinterpret_cast*>(aPtr))->Close(); + } +#endif + +// ============================ MEMBER FUNCTIONS =============================== + +// CUsageUrl: + +//-------------------------------------------------------------------------- +// CUsageUrl::CUsageUrl +// Storage class default constructor +//-------------------------------------------------------------------------- +// +CUsageUrl::CUsageUrl() + { + } + +//-------------------------------------------------------------------------- +// CUsageUrl::~CUsageUrl +// Storage class destructor +//-------------------------------------------------------------------------- +// +CUsageUrl::~CUsageUrl() + { + delete iUrl; + } + +// CDRMRightsServer: + +// ----------------------------------------------------------------------------- +// CDRMRightsServer::NewLC +// Two-phased constructor. +// ----------------------------------------------------------------------------- +// +CDRMRightsServer* CDRMRightsServer::NewL() + { + CDRMRightsServer* self = new( ELeave ) CDRMRightsServer(); + + CleanupStack::PushL( self ); + + self->ConstructL(); + + CleanupStack::Pop( self ); + + return self; + } + +// ----------------------------------------------------------------------------- +// Destructor +// ----------------------------------------------------------------------------- +CDRMRightsServer::~CDRMRightsServer() + { + DRMLOG( _L( "CDRMRightsServer::~" ) ); + + delete iIMEI; iIMEI = NULL; + + delete iIMSI; iIMSI = NULL; + + delete iDb; iDb = NULL; + + iClock.Close(); + iCache.Close(); + + iMeteringDb.Close(); + + iFs.Close(); + iActiveCountConstraints.ResetAndDestroy(); + iActiveCountConstraints.Close(); + + delete iBackupObserver; + delete iBackupHandler; + delete iActiveBackupClient; + delete iDbWatcher; + +#if 0 + // Close and delete the shared data client + if( iSharedDataClient ) + { + iSharedDataClient->Close(); + delete iSharedDataClient; + iSharedDataClient = NULL; + } +#endif + + if( iNotifier ) + { + delete iNotifier; iNotifier = NULL; + } + + iActiveUrls.ResetAndDestroy(); + + //An empty semaphore + RSemaphore semaphore; + } + +// ----------------------------------------------------------------------------- +// CDRMRightsServer::GetSecureTime +// Fetch the time from (secure) source. +// ----------------------------------------------------------------------------- +// +TBool CDRMRightsServer::GetSecureTime( TTime& aTime ) const + { + DRMClock::ESecurityLevel secLevel = DRMClock::KInsecure; + + TInt timezone( 0 ); + + iClock.GetSecureTime( aTime, timezone, secLevel ); + + if( secLevel == DRMClock::KSecure ) + { + DRMLOG( _L( "CDRMRightsServer::GetSecureTime: Time is secure\r\n" ) ); + return ETrue; + } + + DRMLOG( _L( "CDRMRightsServer::GetSecureTime: Time is not secure\r\n" ) ); + + return EFalse; + } + +// ----------------------------------------------------------------------------- +// CDRMRightsServer::Notifier +// Return a handle to DRM Notifier. +// ----------------------------------------------------------------------------- +// +CDRMNotifier& CDRMRightsServer::Notifier() + { + return *iNotifier; + } + +// ----------------------------------------------------------------------------- +// CDRMRightsServer::Notifier +// Return a handle to DRM Notifier. +// ----------------------------------------------------------------------------- +// +CDRMRightsDB& CDRMRightsServer::Database() + { + return *iDb; + } + +RFs& CDRMRightsServer::FileServerSession() + { + return iFs; + } + + +RDRMReplayCache& CDRMRightsServer::ReplayCache() + { + return iCache; + } + + +RDrmMeteringDb& CDRMRightsServer::MeteringDatabase() + { + return iMeteringDb; + } + +// ----------------------------------------------------------------------------- +// CDRMRightsServer::HandleNotifyL +// Forward the event to the database. +// ----------------------------------------------------------------------------- +// +void CDRMRightsServer::HandleNotifyL(const TUid /*aUid*/, + const TDesC& /*aKey*/, + const TDesC& /*aValue*/) + { + /* XXX Backup via Publish/Subscribe + __ASSERT_DEBUG( iDb, User::Invariant() ); + TInt value = -1; + TLex16 parser( aValue ); + + if ( aUid == KSDUidSystem ) + { + // Check if it's a backup / restore status event + if( !aKey.Compare( KBackupRestoreStatus ) ) + { + User::LeaveIfError( parser.Val( value ) ); + if( value == 3 ) // Complete + { + iDb->MergeDBL(); + } + } + // Check if it's a drm backup restore status event + else if ( aUid == KSDUidSystem ) + { + if( !aKey.Compare( KDRMBackupRestoreStatus ) ) + { + User::LeaveIfError( parser.Val( value ) ); + + if( value == 1 ) // PrepareForBackup + { + TRAPD( error, iDb->BackupDBL( KNullDesC, + KNullDesC8 ) ); + // Notify that it's done + User::LeaveIfError( iSharedDataClient->AssignToTemporaryFile( + KSDUidSystem ) ); + User::LeaveIfError( iSharedDataClient->SetInt( + KDRMBackupRestoreStatus, 0 ) ); + iSharedDataClient->Flush(); + } + } + } + } + */ + } + +// ----------------------------------------------------------------------------- +// CDRMRightsServer::RunErrorL +// From CActive. Complete the request and restart the scheduler. +// ----------------------------------------------------------------------------- +// +TInt CDRMRightsServer::RunError( TInt aError ) + { + DRMLOG2( _L( "CDRMRightsServer::RunError: %d" ), aError ); + + // Inform the client. + if ( !Message().IsNull() ) + { + Message().Complete( aError ); + } + + // Restart the scheduler. + ReStart(); + + // Error handled. + return KErrNone; + } + +// ----------------------------------------------------------------------------- +// CDRMRightsServer::NewSessionL +// Called when a client requires a new instance. +// ----------------------------------------------------------------------------- +CSession2* CDRMRightsServer::NewSessionL( const TVersion& aVersion, + const RMessage2& /*aMessage*/ ) const + { + DRMLOG( _L( "CDRMRightsServer::NewSessionL" ) ); + + if ( ! User::QueryVersionSupported( TVersion( DRMEngine::KServerMajorVersion, + DRMEngine::KServerMinorVersion, + DRMEngine::KServerBuildVersion ), + aVersion ) ) + { + // Sorry, no can do. + User::Leave( KErrNotSupported ); + } + + DRMLOG( _L( "CDRMRightsServer::NewSessionL: Creating a new session" ) ); + + return CDRMDbSession::NewL(); + } +// ----------------------------------------------------------------------------- +// CDRMRightsServer::CDRMRightsServer +// C++ default constructor can NOT contain any code, that +// might leave. +// ----------------------------------------------------------------------------- +// +CDRMRightsServer::CDRMRightsServer() : + CServer2( EPriorityStandard ), + iIMEI( NULL ), + iArmed( EFalse ), + iIMSI( NULL ), + iGetImsi( ETrue ) + { + // Nothing + } + +// ----------------------------------------------------------------------------- +// CDRMRightsServer::ConstructL +// Symbian 2nd phase constructor can leave. +// ----------------------------------------------------------------------------- +// +void CDRMRightsServer::ConstructL() + { + DRMLOG( _L( "CDRMRightsServer::ConstructL" ) ); + + TDRMKey key; + RSemaphore semaphore; + RProcess currentprocess; + + // Ignore errors + User::RenameThread( KRightsServerThread ); + User::LeaveIfError( iFs.Connect() ); + +#ifndef RD_MULTIPLE_DRIVE + + // Ignore errors + iFs.MkDirAll( KDRMDbTempPath ); + +#else //RD_MULTIPLE_DRIVE + + TFileName tempPath; + TFileName tempPath2; + TFileName tempRemovablePath; + TInt driveNumber( -1 ); + TChar driveLetter; + TChar driveLetterRemovable; + DriveInfo::GetDefaultDrive( DriveInfo::EDefaultSystem, driveNumber ); + iFs.DriveToChar( driveNumber, driveLetter ); + + tempPath.Format( KDbTempPath, (TUint)driveLetter ); + + // Ignore errors + iFs.MkDirAll( tempPath ); + +#endif + + DRMLOG( _L( "CDRMRightsServer::ConstructL: SharedDataClient" ) ); + + // Create and instance of the shared data client + // iSharedDataClient = new (ELeave) RSharedDataClient(this); + + // Connecting to the shared data server + // User::LeaveIfError(iSharedDataClient->Connect()); + + /* XXX Backup via Publish/Subscribe + User::LeaveIfError(iSharedDataClient->NotifyChange( + KSDUidSystem, &KBackupRestoreStatus ) ); + User::LeaveIfError(iSharedDataClient->NotifyChange( + KSDUidSystem, &KDRMBackupRestoreStatus) ); + */ + + + GetDbKeyL( key ); + + + DRMLOG( _L( "CDRMRightsServer::ConstructL: database" ) ); + + GetIMEIL(); + + // Create the imsi pointer array: + iIMSI = CDRMPointerArray::NewL(); + iIMSI->SetAutoCleanup(ETrue); + + GetIMSIL(); + +#ifndef RD_MULTIPLE_DRIVE + + iDb = CDRMRightsDB::NewL( iFs, KRightsDir, key, *iIMEI, const_cast(this) ); + +#else //RD_MULTIPLE_DRIVE + + tempPath.Format( KRightsDir, (TUint)driveLetter ); + + iDb = CDRMRightsDB::NewL( iFs, tempPath, key, *iIMEI, const_cast(this) ); + +#endif + + key.FillZ(); + + DRMLOG( _L( "CDRMRightsServer::ConstructL: DB started." ) ); + + DRMLOG( _L( "CDRMRightsServer::ConstructL: Starting Notifier ." ) ); + + User::LeaveIfError( semaphore.CreateGlobal( KDRMEngCommonSemaphore, 0 ) ); + CleanupClosePushL( semaphore ); + + StartThreadL( DRMNotifier::KServerName, StartupNotifier, semaphore ); + DRMLOG( _L( "CDRMRightsServer::ConstructL: Notifier thread created." ) ); + + StartThreadL( Roap::KServerName, StartupRoapStorage, semaphore ); + DRMLOG( _L( "CDRMRightsServer::ConstructL: ROAP thread created." ) ); + +#ifdef __DRM_CLOCK + StartThreadL( DRMClock::KServerName, StartupClock, semaphore ); + DRMLOG( _L( "CDRMRightsServer::ConstructL: clock thread created." ) ); +#endif + + CleanupStack::PopAndDestroy(); // semaphore + + iNotifier = CDRMNotifier::NewL(); + + iCache.Set( iFs ); + +#ifndef RD_MULTIPLE_DRIVE + + iCache.InitL( KTimedReplayCacheFile, KPlainReplayCacheFile ); + +#ifdef RD_DRM_METERING + iMeteringDb.Set( iFs ); + iMeteringDb.InitL( KMeteringDataBaseFile ); +#endif + +#else //RD_MULTIPLE_DRIVE + + tempPath.Format( KTimedReplayCacheFile, (TUint)driveLetter ); + tempPath2.Format( KPlainReplayCacheFile, (TUint)driveLetter ); + + iCache.InitL( tempPath, tempPath2 ); + +#ifdef RD_DRM_METERING + + tempPath.Format( KMeteringDataBaseFile, (TUint)driveLetter ); + + iMeteringDb.Set( iFs ); + iMeteringDb.InitL( tempPath ); + +#endif + +#endif + + User::LeaveIfError( iClock.Connect() ); + + // xoma header list creation + iXOmaHeaders = new (ELeave) RPointerArray< CDRMXOma >(); + + // p/s + iBackupObserver = CDRMBackupObserver::NewL( *(const_cast(this))); + iBackupObserver->Start(); + +#ifdef USE_RO_IMPORT + // Import any OMA DRM 1.0 RO in the import directory, ignore all errors (except + // when checking the default removable mass storage) + TInt r = KErrNone; + +#ifndef RD_MULTIPLE_DRIVE + + TRAP( r, ImportRightsObjectsL( KInternalImportDir ) ); + TRAP( r, ImportRightsObjectsL( KUserDiskImportDir ) ); + +#else //RD_MULTIPLE_DRIVE + + tempPath.Format( KInternalImportDir, (TUint)driveLetter ); + + DriveInfo::GetDefaultDrive( DriveInfo::EDefaultMassStorage, driveNumber ); + iFs.DriveToChar( driveNumber, driveLetter ); + + // Default mass storage is usually eMMC + tempPath2.Format( KUserDiskImportDir, (TUint)driveLetter ); + + // Find out if a removable mass storage also exists + r = DriveInfo::GetDefaultDrive( DriveInfo::EDefaultRemovableMassStorage, driveNumber ); + iFs.DriveToChar( driveNumber, driveLetterRemovable ); + + // Import is not needed from the default removable mass storage drive if the drive + // letter of the default mass storage and the default removable mass storage are + // the same or the removable mass storage is not supported + if ( ( driveLetter != driveLetterRemovable ) && ( r == KErrNone ) ) + { + tempRemovablePath.Format( KUserRemovableDiskImportDir, (TUint)driveLetterRemovable ); + TRAP( r, ImportRightsObjectsL( tempRemovablePath ) ); + } + + TRAP( r, ImportRightsObjectsL( tempPath ) ); + TRAP( r, ImportRightsObjectsL( tempPath2 ) ); + +#endif + +#endif + + // Add the server to the scheduler. + StartL( DRMEngine::KServerName ); + + // Start watching our RDB + iDbWatcher = CDbWatcher::NewL( *this ); + iDbWatcher->StartWatching(); + + // Start watching the helper server + iProcWatcher = CProcWatcher::NewL( *this, _L( "*DcfRepSrv*" ), _L( "DcfRepSrv" ) ); + iProcWatcher->StartWatching(); + + // Ready to watch + iArmed = ETrue; + + __UHEAP_MARK; + TRAP( r, FeatureManager::InitializeLibL() ); + if( !r && FeatureManager::FeatureSupported( KFeatureIdWindowsMediaDrm ) ) + { + static const TInt KGateOrdinal = 1; + RLibrary library; + r = library.Load( KWmDrmClientWrapperName ); + if( !r ) + { + CWmDrmClientWrapper* wrapper = NULL; + TLibraryFunction function = library.Lookup( KGateOrdinal ); + if( function != NULL ) + { + __UHEAP_MARK; + TRAP( r, wrapper = reinterpret_cast( function() ) ); + if( !r ) + { + r = wrapper->Connect(); + } + delete wrapper; + __UHEAP_MARKEND; + } + } + library.Close(); + } + FeatureManager::UnInitializeLib(); + __UHEAP_MARKEND; + } + +// ----------------------------------------------------------------------------- +// CDRMRightsServer::StartThreadL +// Start a new thread. +// ----------------------------------------------------------------------------- +void CDRMRightsServer::StartThreadL( const TDesC& aThreadName, + TThreadFunction aFunc, + RSemaphore& aSemaphore ) + { + RThread thread; + + User::LeaveIfError( + thread.Create( aThreadName, + aFunc, + KDefaultStackSize, + KMinHeapSize, + KMaxHeapsize, + NULL ) ); + + thread.Resume(); + + aSemaphore.Wait(); + + thread.Close(); + } + +// ----------------------------------------------------------------------------- +// CDRMRightsServer::GetDbKeyL +// Fetches the rights database key from Wallet or uses a constant +// key if Wallet is not supported. +// ----------------------------------------------------------------------------- +// +void CDRMRightsServer::GetDbKeyL( TDRMKey& aKey ) + { + TInt r = KErrNone; + + DRMLOG( _L( "CDRMRightsServer::GetDbKey" ) ); + MDrmKeyStorage* storage = DrmKeyStorageNewL(); + TRAP( r, storage->GetDeviceSpecificKeyL( aKey ) ); + delete storage; + User::LeaveIfError( r ); + } + +// ----------------------------------------------------------------------------- +// CDRMRightsServer::GenerateKeyL +// Generates the actual key based on the given key seed. +// ----------------------------------------------------------------------------- +// +void CDRMRightsServer::GenerateKeyL( HBufC*& aKeySeed, + TDRMKey& aKey ) const + { + __ASSERT_ALWAYS( aKeySeed->Size() >= KDRMKeyLength, + User::Leave( KErrUnderflow ) ); + + TPtrC8 key( reinterpret_cast< TUint8* >( const_cast< TUint16* >( aKeySeed->Ptr() ) ), + KDRMKeyLength ); + + aKey = key; + } + + +// ----------------------------------------------------------------------------- +// CDRMRightsServer::XOmaHeaders() +// return the pointer of the X-Oma headers list +// ----------------------------------------------------------------------------- +// +RPointerArray< CDRMXOma >& CDRMRightsServer::XOmaHeaders( void ) + { + return *iXOmaHeaders; + } + + + +// ----------------------------------------------------------------------------- +// CDRMRightsServer::GetIMEIL +// ----------------------------------------------------------------------------- +// +const TDesC& CDRMRightsServer::GetIMEIL() + { + if ( iIMEI ) + { + return *iIMEI; + } + +#ifdef DRM_USE_SERIALNUMBER_URI + TInt error( KErrNone ); + TInt count( 0 ); + TInt count2( 0 ); + TUint32 caps( 0 ); + TBool found (EFalse); + + RTelServer etelServer; + RMobilePhone phone; + + TUint KMaxImeiTries = 5; + + for ( TUint8 i = 0; i < KMaxImeiTries; ++i ) + { + error = etelServer.Connect(); + if ( error ) + { + User::After( TTimeIntervalMicroSeconds32( KWaitingTime ) ); + } + else + { + break; + } + } + + User::LeaveIfError( error ); + CleanupClosePushL( etelServer ); + + User::LeaveIfError( etelServer.LoadPhoneModule( KMmTsyModuleName ) ); + + TUnloadModule unload; + unload.iServer = &etelServer; + unload.iName = &KMmTsyModuleName; + + TCleanupItem item( DoUnloadPhoneModule, &unload ); + CleanupStack::PushL( item ); + User::LeaveIfError( etelServer.EnumeratePhones( count ) ); + + for ( count2 = 0; count2 < count && !found; ++count2 ) + { + RTelServer::TPhoneInfo phoneInfo; + User::LeaveIfError( etelServer.GetTsyName( count2, phoneInfo.iName ) ); + + if ( phoneInfo.iName.CompareF(KMmTsyModuleName()) == 0 ) + { + User::LeaveIfError( etelServer.GetPhoneInfo( count2, phoneInfo ) ); + User::LeaveIfError( phone.Open( etelServer, phoneInfo.iName ) ); + CleanupClosePushL( phone ); + found = ETrue; + } + } + + if ( !found ) + { + // Not found. + User::Leave( KErrNotFound ); + } + + User::LeaveIfError( phone.GetIdentityCaps( caps ) ); + if ( caps & RMobilePhone::KCapsGetSerialNumber ) + { + RMobilePhone::TMobilePhoneIdentityV1 id; + TRequestStatus status; + + phone.GetPhoneId( status, id ); + + User::WaitForRequest( status ); + + User::LeaveIfError( status.Int() ); + + iIMEI = id.iSerialNumber.AllocL(); + + CleanupStack::PopAndDestroy( 3 ); // phone, item, etelServer + + HBufC8* buf = HBufC8::NewL( iIMEI->Size() ); + TPtr8 ptr( buf->Des() ); + ptr.Copy( *iIMEI ); + + DRMLOG(_L("IMEI:")); + DRMLOGHEX(ptr); + delete buf; + + return *iIMEI; + } + + User::Leave( KErrNotFound ); + + // Never happens... + return *iIMEI; + +#else + _LIT( KDefaultSerialNumber, "123456789123456789" ); + iIMEI = KDefaultSerialNumber().AllocL(); + + return *iIMEI; +#endif + } + +// ----------------------------------------------------------------------------- +// CDRMRightsServer::GetIMSIL +// ----------------------------------------------------------------------------- +// +const CDRMPointerArray& CDRMRightsServer::GetIMSIL() + { + + if ( !iGetImsi ) + { + return *iIMSI; + } + +#ifndef __WINS__ + TInt error( KErrNone ); + TInt count( 0 ); + TInt count2( 0 ); + TUint32 caps( 0 ); + TBool found (EFalse); + HBufC8* imsi = NULL; + HBufC8* imsiNumber = NULL; + + RTelServer etelServer; + RMobilePhone phone; + + TUint KMaxImeiTries = 5; + for ( TUint8 i = 0; i < KMaxImeiTries; ++i ) + { + error = etelServer.Connect(); + if ( error ) + { + User::After( TTimeIntervalMicroSeconds32( KWaitingTime ) ); + } + else + { + break; + } + } + + User::LeaveIfError( error ); + CleanupClosePushL( etelServer ); + User::LeaveIfError( etelServer.LoadPhoneModule( KMmTsyModuleName ) ); + + TUnloadModule unload; + unload.iServer = &etelServer; + unload.iName = &KMmTsyModuleName; + + TCleanupItem item( DoUnloadPhoneModule, &unload ); + CleanupStack::PushL( item ); + + User::LeaveIfError( etelServer.EnumeratePhones( count ) ); + + for ( count2 = 0; count2 < count && !found; ++count2 ) + { + RTelServer::TPhoneInfo phoneInfo; + User::LeaveIfError( etelServer.GetTsyName( count2, phoneInfo.iName ) ); + + if ( phoneInfo.iName.CompareF(KMmTsyModuleName()) == 0 ) + { + User::LeaveIfError( etelServer.GetPhoneInfo( count2, phoneInfo ) ); + User::LeaveIfError( phone.Open( etelServer, phoneInfo.iName ) ); + CleanupClosePushL( phone ); + found = ETrue; + } + } + + if ( !found ) + { + // Not found. + User::Leave( KErrNotFound ); + } + + + User::LeaveIfError( phone.GetIdentityCaps( caps ) ); + + if( caps & RMobilePhone::KCapsGetSubscriberId ) + { + RMobilePhone::TMobilePhoneSubscriberId imsiId; + TRequestStatus status; + + phone.GetSubscriberId( status, imsiId ); + + User::WaitForRequest( status ); + + if( ! status.Int() ) + { + imsi = HBufC8::NewMaxLC( imsiId.Length() + KImsiId().Size() ); + TPtr8 imsiPtr(const_cast(imsi->Ptr()), 0, imsi->Size()); + + imsiNumber = CnvUtfConverter::ConvertFromUnicodeToUtf8L( imsiId ); + CleanupStack::PushL( imsiNumber ); + + imsiPtr.Copy( KImsiId() ); + imsiPtr.Append( *imsiNumber ); + CleanupStack::PopAndDestroy(); // imsiNumber + } + else + { + imsi = NULL; + } + } + else + { + imsi = NULL; + } + + + // Clean up whatever is in there + iIMSI->ResetAndDestroy(); + + if( imsi ) + { + // if we got it we wont try again + iIMSI->AppendL( imsi ); + CleanupStack::Pop(); // imsi + iGetImsi = EFalse; + } + + // Check for possible extra IMSI individual constraints + AppendExtendedIndividualConstraintsL(&phone); + + CleanupStack::PopAndDestroy(); // phone + CleanupStack::PopAndDestroy(); // cleanup item + CleanupStack::PopAndDestroy(); // etel server + + return *iIMSI; + +#else + HBufC8* imsi = NULL; + + if( iGetImsi ) + { + iGetImsi = EFalse; + _LIT8( KDefaultSerialNumber, "IMSI:123456789123456789" ); + imsi = KDefaultSerialNumber().AllocLC(); + iIMSI->AppendL( imsi ); + CleanupStack::Pop(); + AppendExtendedIndividualConstraintsL(); + } + + + return *iIMSI; +#endif // __WINS__ + } + +// ----------------------------------------------------------------------------- +// CDRMRightsServer::AppendExtendedIndividualConstraintsL +// If the extension DLL exists it is loaded and used to obtain additional +// valid individual constraints +// ----------------------------------------------------------------------------- +void CDRMRightsServer::AppendExtendedIndividualConstraintsL(RMobilePhone* aMobilePhone) + { + // Load the externsion DLL + RLibrary lib; + +#ifndef RD_MULTIPLE_DRIVE + + if (lib.LoadRomLibrary(KDRMIndividualConstraintExtensionDll,KNullDesC)==KErrNone) + +#else //RD_MULTIPLE_DRIVE + + TInt driveNumber( -1 ); + TChar driveLetter; + DriveInfo::GetDefaultDrive( DriveInfo::EDefaultRom, driveNumber ); + iFs.DriveToChar( driveNumber, driveLetter ); + + TFileName individualConstraindExtensionDll; + individualConstraindExtensionDll.Format( + KIndividualConstraintExtensionDll, (TUint)driveLetter ); + + if ( lib.LoadRomLibrary( individualConstraindExtensionDll, KNullDesC ) == KErrNone ) + +#endif + + { + CleanupClosePushL(lib); + + // Get first exported ordinal - factory method returning + // MDRMIndividualConstraintExtension* + TLibraryFunction factory = lib.Lookup(1); + + if (factory) + { + // Instantiate object + MDRMIndividualConstraintExtension* extendedConstraints = + reinterpret_cast(factory()); + + if (extendedConstraints) + { + CleanupStack::PushL(TCleanupItem(Release,extendedConstraints)); + extendedConstraints->AppendConstraintsL(*iIMSI,aMobilePhone); + CleanupStack::PopAndDestroy(extendedConstraints); //calls Release + } + } + + // unload library + CleanupStack::PopAndDestroy(&lib); //close + } + } + +// ----------------------------------------------------------------------------- +// CDRMRightsServer::Release +// ----------------------------------------------------------------------------- +void CDRMRightsServer::Release(TAny* aIndividualConstraintExtension) + { + MDRMIndividualConstraintExtension* extendedConstraints = + reinterpret_cast(aIndividualConstraintExtension); + extendedConstraints->Release(); //free resources + } + +// ----------------------------------------------------------------------------- +// CDRMRightsServer::HandleBackupEventL +// Handle Backup Events +// ----------------------------------------------------------------------------- +// + +void CDRMRightsServer::HandleBackupEventL( TInt aBackupEvent ) + { + //RFileLogger::Write(KLogDir, KLogName, EFileLoggingModeAppend, _L8("Handle::BackupCalled\n\r")); + + //conn::TBURPartType eventType; + //conn::TBackupIncType incType; + TDriveList aDriveList; + + //RFileLogger::WriteFormat(KLogDir, KLogName, EFileLoggingModeAppend, _L8("backupevent: %d"), aBackupEvent); + + // If there is no operation going or state is normal + // Delete the client and handler + + if( aBackupEvent == conn::EBURUnset || + aBackupEvent & conn::EBURNormal ) + { + /* + if( aBackupEvent == conn::EBURUnset ) + { + RFileLogger::Write(KLogDir, KLogName, EFileLoggingModeAppend, _L8("Handle::Unset\n\r")); + } + else + { + RFileLogger::Write(KLogDir, KLogName, EFileLoggingModeAppend, _L8("Handle::Normal\n\r")); + } + */ + if( iActiveBackupClient ) + { + delete iActiveBackupClient; + iActiveBackupClient = NULL; + } + + if( iBackupHandler ) + { + delete iBackupHandler; + iBackupHandler = NULL; + } + } + else if( aBackupEvent & conn::EBURBackupFull || + aBackupEvent & conn::EBURRestoreFull ) + { + //RFileLogger::Write(KLogDir, KLogName, EFileLoggingModeAppend, _L8("Handle::Full\n\r")); + // ab handler + iBackupHandler = CDRMBackup::NewL( iDb, iFs ); + + // ab client + iActiveBackupClient = conn::CActiveBackupClient::NewL( iBackupHandler ); + + // Confirm that we have done everything if there even was anything to do + //RFileLogger::Write(KLogDir, KLogName, EFileLoggingModeAppend, _L8("Handle::Confirm F \n\r")); + iActiveBackupClient->ConfirmReadyForBURL( KErrNone ); + } + else if( aBackupEvent & conn::EBURBackupPartial || + aBackupEvent & conn::EBURRestorePartial ) + { + //RFileLogger::Write(KLogDir, KLogName, EFileLoggingModeAppend, _L8("Handle::Partial\n\r")); + // ab handler + iBackupHandler = CDRMBackup::NewL( iDb, iFs ); + + // ab client + iActiveBackupClient = conn::CActiveBackupClient::NewL( iBackupHandler ); + + if( !iActiveBackupClient->DoesPartialBURAffectMeL() ) + { + //RFileLogger::Write(KLogDir, KLogName, EFileLoggingModeAppend, _L8("Handle::NotMe\n\r")); + delete iActiveBackupClient; + iActiveBackupClient = NULL; + + delete iBackupHandler; + iBackupHandler = NULL; + } + else + { + //RFileLogger::Write(KLogDir, KLogName, EFileLoggingModeAppend, _L8("Handle::Confirm P \n\r")); + // Confirm that we have done everything if there even was anything to do + iActiveBackupClient->ConfirmReadyForBURL( KErrNone ); + //RFileLogger::Write(KLogDir, KLogName, EFileLoggingModeAppend, _L8("Handle::Confirm P Done \n\r")); + } + } + else + { + //RFileLogger::Write(KLogDir, KLogName, EFileLoggingModeAppend, _L8("Handle::Argument\n\r")); + // Unknown operation + User::Leave(KErrArgument); + } + }; + +// ----------------------------------------------------------------------------- +// CDRMRightsServer::WatchedObjectChangedL +// Handle Backup Events +// ----------------------------------------------------------------------------- +// +void CDRMRightsServer::WatchedObjectChangedL( const TDesC& aObject ) + { + DRMLOG( _L( "CDRMRightsServer::WatchedObjectChangedL ->" ) ); + DRMLOG( aObject ); + + if ( aObject.Left( KDirIdentifier().Length() ) == KDirIdentifier && + !iDb->Updating() && iArmed ) + { +#ifdef _DEBUG + DRMLOG( _L( "RDB modified by outside party (DEBUG mode, not deleting the DB)" ) ); +#else + DRMLOG( _L( "RDB modified by outside party, deleting the DB" ) ); + iDb->MarkAsCorrupted(); + RStarterSession starter; + User::LeaveIfError( starter.Connect() ); + starter.Reset( RStarterSession::EDRMReset ); + starter.Close(); +#endif + } + else if ( aObject.Left( KProcIdentifier().Length() ) == KProcIdentifier && iArmed ) + { +#ifdef _DEBUG + DRMLOG( _L( "Peer process killed (DEBUG mode, not rebooting)" ) ); +#else + DRMLOG( _L( "Peer process killed, rebooting" ) ); + RStarterSession starter; + User::LeaveIfError( starter.Connect() ); + starter.Reset( RStarterSession::EDRMReset ); + starter.Close(); +#endif + } + + DRMLOG( _L( "CDRMRightsServer::WatchedObjectChangedL <-" ) ); + } + +// ----------------------------------------------------------------------------- +// CDRMRightsServer::HasActiveCountConstraint +// Check ID for active count constraint +// ----------------------------------------------------------------------------- +// +TBool CDRMRightsServer::HasActiveCountConstraint( const TDesC8& aContentId ) + { + TInt i; + TBool r = EFalse; + + for ( i = 0; r == EFalse && i < iActiveCountConstraints.Count(); i++ ) + { + if ( iActiveCountConstraints[i]->CompareF( aContentId ) == 0 ) + { + r = ETrue; + } + } + return r; + } + +// ----------------------------------------------------------------------------- +// CDRMRightsServer::RemoveActiveCountConstraint +// Remove ID from count constraint list +// ----------------------------------------------------------------------------- +// +void CDRMRightsServer::RemoveActiveCountConstraint( const TDesC8& aContentId ) + { + TInt i; + TInt r = KErrNotFound; + HBufC8* id = NULL; + + for ( i = 0; r == KErrNotFound && i < iActiveCountConstraints.Count(); i++ ) + { + if ( iActiveCountConstraints[i]->CompareF( aContentId ) == 0 ) + { + r = i; + } + } + if ( r != KErrNotFound ) + { + id = iActiveCountConstraints[r]; + iActiveCountConstraints.Remove( r ); + delete id; + id = NULL; + } + } + +// ----------------------------------------------------------------------------- +// CDRMRightsServer::AddActiveCountConstraint +// Add ID to count constraint list +// ----------------------------------------------------------------------------- +// +void CDRMRightsServer::AddActiveCountConstraintL( const TDesC8& aContentId ) + { + if ( !HasActiveCountConstraint( aContentId ) ) + { + iActiveCountConstraints.AppendL( aContentId.AllocL() ); + } + } + + + +// ----------------------------------------------------------------------------- +// CDRMRightsServer::IsAccessingUrl +// Add ID to count constraint list +// ----------------------------------------------------------------------------- +// +TInt CDRMRightsServer::IsAccessingUrl( const TDesC8& aContentId ) + { + for( TInt i = 0; i < iActiveUrls.Count(); i++ ) + { + if( !iActiveUrls[i]->iUrl->Compare( aContentId ) ) + { + return i; + } + } + return KErrNotFound; + } + +// ----------------------------------------------------------------------------- +// CDRMRightsServer::RemoveAccessingUrl +// Add ID to count constraint list +// ----------------------------------------------------------------------------- +// +void CDRMRightsServer::RemoveAccessingUrl( const TDesC8& aContentId ) + { + CUsageUrl* usage = NULL; + TInt index = KErrNotFound; + + index = IsAccessingUrl( aContentId ); + + if( index != KErrNotFound ) + { + // If there are negative or 0 values in the list for some reason + // remove them + if( iActiveUrls[index]->iRefCounter <= 1 ) + { + usage = iActiveUrls[index]; + iActiveUrls.Remove( index ); + delete usage; + } + else + { + iActiveUrls[index]->iRefCounter--; + } + } + } + +// ----------------------------------------------------------------------------- +// CDRMRightsServer::AddAccessingUrlL +// Add ID to count constraint list +// ----------------------------------------------------------------------------- +// +void CDRMRightsServer::AddAccessingUrlL( const TDesC8& aContentId ) + { + CUsageUrl* usage = NULL; + TInt index = KErrNotFound; + + index = IsAccessingUrl( aContentId ); + + if( index == KErrNotFound ) + { + usage = new ( ELeave ) CUsageUrl(); + CleanupStack::PushL( usage ); + usage->iUrl = aContentId.AllocL(); + usage->iRefCounter = 1; + iActiveUrls.AppendL( usage ); + CleanupStack::Pop( usage ); + } + else + { + usage = iActiveUrls[index]; + usage->iRefCounter++; + } + } + + + + +// ----------------------------------------------------------------------------- +// CDRMRightsServer::StopWatchingL +// Delete the watchers +// ----------------------------------------------------------------------------- +// +void CDRMRightsServer::StopWatchingL() + { + iArmed = EFalse; + } + +#ifdef USE_RO_IMPORT +// ----------------------------------------------------------------------------- +// CDRMRightsServer::ImportRightsObjectsL +// Open the import directory and add all ROs that can be found there. ROs file +// names must end with .dr. Only OMA DRM 1.0 ROs in XML format are supported for +// security reasons +// ----------------------------------------------------------------------------- +// +void CDRMRightsServer::ImportRightsObjectsL( const TDesC& aImportDir ) + { + CDrmRightsParser* p; + HBufC8* d = NULL; + HBufC8* k = NULL; + RFs fs; + RFile file; + TInt size; + RPointerArray rights; + CDir* dir; + TFileName name; + TPtr8 ptr( NULL, 0 ); + TInt i; + TInt r = KErrNone; + TCleanupItem listCleanup(PointerArrayResetDestroyAndClose, + &rights); + TDRMUniqueID id; + TTime time; + + DRMLOG( _L( "CDRMRightsServer::ImportRightsObjectsL" ) ); + DRMLOG( aImportDir ); + __UHEAP_MARK; + GetSecureTime( time ); + p = CDrmRightsParser::NewL(); + CleanupStack::PushL( p ); + User::LeaveIfError( iFs.GetDir( aImportDir, KEntryAttNormal, + ESortNone, dir ) ); + CleanupStack::PushL( dir ); + for (i = 0; i < dir->Count(); i++) + { + name.Copy( aImportDir ); + name.Append( (*dir)[i].iName ); + if ( ( name.Length() > 3 && name.Right(3).CompareF( KDrSuffix ) == 0 ) ) + { + User::LeaveIfError( file.Open( iFs, name, EFileRead ) ); + CleanupClosePushL( file ); + User::LeaveIfError( file.Size( size ) ); + d = HBufC8::NewLC( size ); + ptr.Set( d->Des() ); + User::LeaveIfError( file.Read( ptr ) ); + p->ParseL( ptr, rights ); + if ( rights.Count() > 0 ) + { + k = NULL; + CleanupStack::PushL( listCleanup ); + CDRMPermission& permission = rights[0]->GetPermission(); + CDRMAsset& asset = rights[0]->GetAsset(); + + // Add RO only if no rights are available at all for this content + TRAP( r, k = iDb->GetDecryptionKeyL( *asset.iUid ) ); + if (k == NULL ) + { + iDb->AddDBEntryL( *asset.iUid, permission, asset.iKey, id ); + } + else + { + delete k; + } + CleanupStack::PopAndDestroy(); // listCleanup + } + CleanupStack::PopAndDestroy( 2 ); // d, file + iFs.Delete( name ); + } + } + CleanupStack::PopAndDestroy( 2 ); // dir, p + __UHEAP_MARKEND; + DRMLOG( _L( "CDRMRightsServer::ImportRightsObjectsL done" ) ); + } +#endif + + + +// ========================== OTHER EXPORTED FUNCTIONS ========================= + + +TInt E32Main() + { + return Startup(); + } + + +// End of File diff -r e9fb2728ea8b -r ca165d35976d breakdeps/DRMEngine/DrmStdKeyStorage.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/breakdeps/DRMEngine/DrmStdKeyStorage.cpp Wed Oct 27 13:24:02 2010 +0100 @@ -0,0 +1,1186 @@ +/* +* Copyright (c) 2002-2010 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: OMA DRM 2.0 Key Storage +* +*/ + + +// INCLUDE FILES +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef RD_MULTIPLE_DRIVE +#include +#endif + +#include "DrmKeyStorage.h" +#include "DrmStdKeyStorage.h" + +#ifdef _DEBUG +#define LOGGING +#endif + +#ifdef LOGGING +_LIT(KLogDir, "DRM"); +_LIT(KLogName, "KeyStorage.log"); +#include "flogger.h" +#define LOG(string) \ + RFileLogger::Write(KLogDir, KLogName, \ + EFileLoggingModeAppend, string); +#define LOGHEX(buffer) \ + RFileLogger::HexDump(KLogDir, KLogName, \ + EFileLoggingModeAppend, _S(""), _S(""), \ + buffer.Ptr(), buffer.Length()); +#else +#define LOG(string) +#define LOGHEX(buffer) +#endif + +#pragma message("Compiling DRM Std KeyStorage..") + + +// LOCAL CONSTANTS AND MACROS + +const TInt KKeyLength = 128; +const TInt KWaitingTime = 2000000; // 2 sec + +#ifdef RD_MULTIPLE_DRIVE +_LIT(KKeyStoragePath, "%c:\\private\\101F51F2\\PKI\\"); +_LIT(KRomKeyStoragePath, "%c:\\private\\101F51F2\\PKI\\"); + +#else +_LIT(KKeyStoragePath, "c:\\private\\101F51F2\\PKI\\"); +_LIT(KRomKeyStoragePath, "z:\\private\\101F51F2\\PKI\\"); +#endif + +_LIT(KDeviceKeyFileName, "DevicePrivateKey.der"); +_LIT(KDeviceCertFileName, "DeviceCert.der"); +_LIT(KSingingCertFmt, "SigningCert%02d.der"); +_LIT(KSingingCertPattern, "SigningCert*"); +_LIT8(KDefaultKey, "0000000000000000"); + +#ifdef RD_MULTIPLE_DRIVE +_LIT(KSerialNumberFile, "%c:\\private\\101F51F2\\rdbserial.dat"); +_LIT(KUdtCertFileName, "%c:\\private\\101F51F2\\PKI\\UdtCertificate.der"); +#else +_LIT(KSerialNumberFile, "c:\\private\\101F51F2\\rdbserial.dat"); +_LIT(KUdtCertFileName, "z:\\private\\101F51F2\\PKI\\UdtCertificate.der"); +#endif + +_LIT(KCmla, "CMLA"); +_LIT(KPadding, "\x0"); + +NONSHARABLE_STRUCT( TUnloadModule ) + { + RTelServer* iServer; + const TDesC* iName; + }; + + +// ============================ LOCAL FUNCTIONS ================================ +LOCAL_C void DoUnloadPhoneModule( TAny* aAny ); + +LOCAL_C void WriteFileL(RFs& aFs, const TDesC& aName, const TDesC8& aData) + { + RFile file; + + User::LeaveIfError(file.Replace(aFs, aName, EFileWrite)); + User::LeaveIfError(file.Write(aData)); + file.Close(); + } + +LOCAL_C void ReadFileL(RFs& aFs, const TDesC& aName, HBufC8*& aContent) + { + RFile file; + TInt size = 0; + + User::LeaveIfError(file.Open(aFs, aName, EFileRead)); + CleanupClosePushL(file); + User::LeaveIfError(file.Size(size)); + aContent = HBufC8::NewLC(size); + TPtr8 ptr(aContent->Des()); + User::LeaveIfError(file.Read(ptr, size)); + CleanupStack::Pop(); //aContent + CleanupStack::PopAndDestroy(); // file + } + +HBufC8* I2OSPL( + RInteger& aInt, TInt& aKeySize ) + { + HBufC8* integer = aInt.BufferLC(); + if (integer->Length() < aKeySize) + { + HBufC8* r = HBufC8::NewLC(aKeySize); + TPtr8 ptr(r->Des()); + for(TInt i = integer->Length(); i < aKeySize; i++) + { + ptr.Append(KPadding()); + } + ptr.Append(*integer); + CleanupStack::Pop(r); + CleanupStack::PopAndDestroy(integer); + return r; + } + else + { + CleanupStack::Pop(integer); + return integer; + } + } + +RInteger OS2IPL( + const TDesC8& aOctetStream) + { + RInteger r; + TInt i; + + r = RInteger::NewL(0); + for (i = 0; i < aOctetStream.Length(); i++) + { + r *= 256; + r += aOctetStream[i]; + } + return r; + } + +void DoUnloadPhoneModule( TAny* aAny ) + { + __ASSERT_DEBUG( aAny, User::Invariant() ); + TUnloadModule* module = ( TUnloadModule* ) aAny; + module->iServer->UnloadPhoneModule( *( module->iName ) ); + } + + +// ============================ MEMBER FUNCTIONS =============================== + +// ----------------------------------------------------------------------------- +// CDrmStdKeyStorage* CDrmStdKeyStorage::NewL +// +// ----------------------------------------------------------------------------- +// +EXPORT_C CDrmStdKeyStorage* CDrmStdKeyStorage::NewL(RLibrary aLibrary) + { + CDrmStdKeyStorage* self = new (ELeave) CDrmStdKeyStorage(aLibrary); + CleanupStack::PushL(self); + self->ConstructL(); + CleanupStack::Pop(); + return self; + } + +// ----------------------------------------------------------------------------- +// CDrmStdKeyStorage::CDrmStdKeyStorage +// +// ----------------------------------------------------------------------------- +// +CDrmStdKeyStorage::CDrmStdKeyStorage(RLibrary aLibrary): + iFileMan(NULL), + iRootSelected(EFalse), + iKey(NULL), + iImei(NULL), + iLibrary(aLibrary) + { + } + +// ----------------------------------------------------------------------------- +// CDrmStdKeyStorage::ConstructL +// +// ----------------------------------------------------------------------------- +// +void CDrmStdKeyStorage::ConstructL() + { + + LOG(_L("CDrmStdKeyStorage::ConstructL ->")); + User::LeaveIfError(iFs.Connect()); + iFileMan = CFileMan::NewL(iFs); + + FeatureManager::InitializeLibL(); + +#ifdef __DRM_OMA2 + if ( FeatureManager::FeatureSupported( KFeatureIdFfOmadrm2Support ) ) + { + TRAP_IGNORE( SelectDefaultRootL() ); + } +#endif + + FeatureManager::UnInitializeLib(); + + iDeviceSpecificKey.Copy(KDefaultKey); + + LOG(_L("CDrmStdKeyStorage::ConstructL <-")); + } + +// ----------------------------------------------------------------------------- +// MDrmKeyStorage::~MDrmKeyStorage +// +// ----------------------------------------------------------------------------- +// + +MDrmKeyStorage::~MDrmKeyStorage() + { + } +// ----------------------------------------------------------------------------- +// DrmStdKeyStorage::~CDrmStdKeyStorage +// +// ----------------------------------------------------------------------------- +// + +CDrmStdKeyStorage::~CDrmStdKeyStorage() + { + LOG(_L("CDrmStdKeyStorage::~CDrmStdKeyStorage ->")); + delete iFileMan; + delete iKey; + delete iImei; iImei = NULL; + iFs.Close(); + //iLibrary.Close(); + LOG(_L("CDrmStdKeyStorage::~CDrmStdKeyStorage <-")); + } + +// ----------------------------------------------------------------------------- +// DrmStdKeyStorage::ModulusSize +// +// ----------------------------------------------------------------------------- +// + +TInt CDrmStdKeyStorage::ModulusSize() + { + LOG(_L("CDrmStdKeyStorage::ModulusSize ->")); + + if(iKey == NULL) + { + return KErrGeneral; + } + LOG(_L("CDrmStdKeyStorage::ModulusSize <-")); + return iKey->N().BitCount(); + } + +// ----------------------------------------------------------------------------- +// DrmStdKeyStorage::SelectTrustedRootL +// +// ----------------------------------------------------------------------------- +// +void CDrmStdKeyStorage::SelectTrustedRootL( + const TDesC8& aRootKeyHash) + { + TFileName fileName; + TEntry entry; + TInt i; + + LOG(_L("CDrmStdKeyStorage::SelectTrustedRootL ->")); + LOG(aRootKeyHash); + if (aRootKeyHash.Length() != 0) + { + +#ifndef RD_MULTIPLE_DRIVE + + fileName.Copy(KKeyStoragePath); + +#else //RD_MULTIPLE_DRIVE + + TFileName tempPath; + TInt driveNumber( -1 ); + TChar driveLetter; + DriveInfo::GetDefaultDrive( DriveInfo::EDefaultSystem, driveNumber ); + iFs.DriveToChar( driveNumber, driveLetter ); + + tempPath.Format( KKeyStoragePath, (TUint)driveLetter ); + + fileName.Copy(tempPath); + +#endif + + for (i = 0; i < SHA1_HASH; i++) + { + fileName.AppendNumFixedWidth(aRootKeyHash[i], EHex, 2); + } + fileName.Append('\\'); + if (iFs.Entry(fileName, entry) != KErrNone) + { + +#ifndef RD_MULTIPLE_DRIVE + + fileName.Copy(KRomKeyStoragePath); + +#else //RD_MULTIPLE_DRIVE + + DriveInfo::GetDefaultDrive( DriveInfo::EDefaultRom, driveNumber ); + iFs.DriveToChar( driveNumber, driveLetter ); + + tempPath.Format( KRomKeyStoragePath, (TUint)driveLetter ); + + fileName.Copy(tempPath); + +#endif + + for (i = 0; i < SHA1_HASH; i++) + { + fileName.AppendNumFixedWidth(aRootKeyHash[i], EHex, 2); + } + fileName.Append('\\'); + // check that the path exists + User::LeaveIfError(iFs.Entry(fileName, entry)); + } + User::LeaveIfError(iFs.SetSessionPath(fileName)); + InitializeKeyL(); + CheckRootForCmlaL(); + iRootSelected = ETrue; + } + else + { + SelectDefaultRootL(); + } + LOG(_L("CDrmStdKeyStorage::SelectTrustedRootL <-")); + } + +// ----------------------------------------------------------------------------- +// DrmStdKeyStorage::SelectDefaultRootL +// +// ----------------------------------------------------------------------------- +// +void CDrmStdKeyStorage::SelectDefaultRootL() + { + CDir* dir = NULL; + TFileName dirName; + TBool found = EFalse; + + LOG(_L("CDrmStdKeyStorage::SelectDefaultRootL ->")); + +#ifndef RD_MULTIPLE_DRIVE + + if (iFs.GetDir(KKeyStoragePath, KEntryAttDir, ESortByName, dir) == KErrNone) + +#else //RD_MULTIPLE_DRIVE + + TFileName tempPath; + TInt driveNumber( -1 ); + TChar driveLetter; + DriveInfo::GetDefaultDrive( DriveInfo::EDefaultSystem, driveNumber ); + iFs.DriveToChar( driveNumber, driveLetter ); + + tempPath.Format( KKeyStoragePath, (TUint)driveLetter ); + + if (iFs.GetDir(tempPath, KEntryAttDir, ESortByName, dir) == KErrNone) + +#endif + + { + __UHEAP_MARK; + LOG(_L(" Checking keys on C:")); + CleanupStack::PushL(dir); + if (dir->Count() >= 1) + { + +#ifndef RD_MULTIPLE_DRIVE + + dirName.Copy(KKeyStoragePath); + +#else //RD_MULTIPLE_DRIVE + + dirName.Copy(tempPath); + +#endif + + dirName.Append((*dir)[0].iName); + dirName.Append('\\'); + User::LeaveIfError(iFs.SetSessionPath(dirName)); + found = ETrue; + } + CleanupStack::PopAndDestroy(dir); + __UHEAP_MARKEND; + } + +#ifndef RD_MULTIPLE_DRIVE + + if (!found && iFs.GetDir(KRomKeyStoragePath, KEntryAttDir, ESortByName, dir) == KErrNone) + +#else //RD_MULTIPLE_DRIVE + + DriveInfo::GetDefaultDrive( DriveInfo::EDefaultRom, driveNumber ); + iFs.DriveToChar( driveNumber, driveLetter ); + + tempPath.Format( KRomKeyStoragePath, (TUint)driveLetter ); + + if (!found && iFs.GetDir(tempPath, KEntryAttDir, ESortByName, dir) == KErrNone) + +#endif + { + LOG(_L(" Checking keys on Z:")); + CleanupStack::PushL(dir); + if (dir->Count() < 1) + { + User::Leave(KErrGeneral); + } + +#ifndef RD_MULTIPLE_DRIVE + + dirName.Copy(KRomKeyStoragePath); + +#else //RD_MULTIPLE_DRIVE + + dirName.Copy(tempPath); + +#endif + + dirName.Append((*dir)[0].iName); + dirName.Append('\\'); + User::LeaveIfError(iFs.SetSessionPath(dirName)); + CleanupStack::PopAndDestroy(dir); + found = ETrue; + } + if (!found) + { + User::Leave(KErrGeneral); + } + InitializeKeyL(); + CheckRootForCmlaL(); + iRootSelected = ETrue; + LOG(_L("CDrmStdKeyStorage::SelectDefaultRootL <-")); + } + +TBool CDrmStdKeyStorage::SelectedRootIsCmla() + { + return iRootIsCmla; + } + +// ----------------------------------------------------------------------------- +// DrmStdKeyStorage::GetTrustedRootsL +// +// ----------------------------------------------------------------------------- +// + +void CDrmStdKeyStorage::GetTrustedRootsL( + RPointerArray& aRootList) + { + CDir* dir = NULL; + TInt i; + TInt j; + TBuf8 hash; + TEntry entry; + TUint8 c; + TInt r = KErrNone; + + LOG(_L("CDrmStdKeyStorage::GetTrustedRootsL ->")); + aRootList.ResetAndDestroy(); + +#ifndef RD_MULTIPLE_DRIVE + + if (iFs.GetDir(KKeyStoragePath, KEntryAttDir, ESortByName, dir) == KErrNone) + +#else //RD_MULTIPLE_DRIVE + + TFileName tempPath; + TInt driveNumber( -1 ); + TChar driveLetter; + DriveInfo::GetDefaultDrive( DriveInfo::EDefaultSystem, driveNumber ); + iFs.DriveToChar( driveNumber, driveLetter ); + + tempPath.Format( KKeyStoragePath, (TUint)driveLetter ); + + if (iFs.GetDir(tempPath, KEntryAttDir, ESortByName, dir) == KErrNone) + +#endif + { + LOG(_L(" Getting roots on C:")); + CleanupStack::PushL(dir); + for (i = 0; i < dir->Count(); i++) + { + entry = (*dir)[i]; + hash.SetLength(0); + LOG(entry.iName); + r = KErrNone; + for (j = 0; r == KErrNone && j < SHA1_HASH; j++) + { + TLex lex(entry.iName.Mid(j * 2, 2)); + r = lex.Val(c, EHex); + hash.Append(c); + } + if (r == KErrNone) + { + aRootList.Append(hash.AllocL()); + } + } + CleanupStack::PopAndDestroy(dir); + } + +#ifndef RD_MULTIPLE_DRIVE + + if (iFs.GetDir(KRomKeyStoragePath, KEntryAttDir, ESortByName, dir) == KErrNone) + +#else //RD_MULTIPLE_DRIVE + + DriveInfo::GetDefaultDrive( DriveInfo::EDefaultRom, driveNumber ); + iFs.DriveToChar( driveNumber, driveLetter ); + + tempPath.Format( KRomKeyStoragePath, (TUint)driveLetter ); + + if (iFs.GetDir(tempPath, KEntryAttDir, ESortByName, dir) == KErrNone) + +#endif + { + LOG(_L(" Getting roots on Z:")); + CleanupStack::PushL(dir); + for (i = 0; i < dir->Count(); i++) + { + LOG(entry.iName); + entry = (*dir)[i]; + hash.SetLength(0); + r = KErrNone; + for (j = 0; r == KErrNone && j < SHA1_HASH; j++) + { + TLex lex(entry.iName.Mid(j * 2, 2)); + r = lex.Val(c, EHex); + hash.Append(c); + } + if (r == KErrNone) + { + aRootList.Append(hash.AllocL()); + } + } + CleanupStack::PopAndDestroy(dir); + } + LOG(_L("CDrmStdKeyStorage::GetTrustedRootsL <-")); + } + +// ----------------------------------------------------------------------------- +// DrmStdKeyStorage::GetCertificateChainL +// +// ----------------------------------------------------------------------------- +// +void CDrmStdKeyStorage::GetCertificateChainL( + RPointerArray& aCertChain) + { + TFileName fileName; + TInt i; + CDir* dir = NULL; + HBufC8* cert = NULL; + + LOG(_L("CDrmStdKeyStorage::GetCertificateChainL ->")); + if (!iRootSelected) + { + User::Leave(KErrGeneral); + } + aCertChain.ResetAndDestroy(); + ReadFileL(iFs, KDeviceCertFileName, cert); + aCertChain.Append(cert); + iFs.GetDir(KSingingCertPattern, KEntryAttNormal, ESortByName, dir); + CleanupStack::PushL(dir); + for (i = 0; i < dir->Count(); i++) + { + ReadFileL(iFs, (*dir)[i].iName, cert); + aCertChain.AppendL(cert); + } + CleanupStack::PopAndDestroy(); // dir + LOG(_L("CDrmStdKeyStorage::GetCertificateChainL <-")); + } + +// ----------------------------------------------------------------------------- +// CDrmStdKeyStorage::RsaSignL +// ----------------------------------------------------------------------------- +// +HBufC8* CDrmStdKeyStorage::RsaSignL( + const TDesC8& aInput) + { + return ModularExponentiateWithKeyL(aInput); + } + +// ----------------------------------------------------------------------------- +// CDrmStdKeyStorage::RsaDecryptL +// ----------------------------------------------------------------------------- +// +HBufC8* CDrmStdKeyStorage::RsaDecryptL( + const TDesC8& aInput) + { + return ModularExponentiateWithKeyL(aInput); + } + +// ----------------------------------------------------------------------------- +// CDrmStdKeyStorage::ImportDataL +// ----------------------------------------------------------------------------- +// +void CDrmStdKeyStorage::ImportDataL( + const TDesC8& aPrivateKey, + const RArray& aCertificateChain) + { + TInt i; + TInt n; + HBufC8* publicKey = NULL; + CX509Certificate* cert = NULL; + CSHA1* hasher = NULL; + TBuf8 publicKeyHash; + TFileName fileName; + + LOG(_L("CDrmStdKeyStorage::ImportDataL ->")); + n = aCertificateChain.Count(); + cert = CX509Certificate::NewLC(aCertificateChain[n - 1]); + publicKey = cert->DataElementEncoding( + CX509Certificate::ESubjectPublicKeyInfo)->AllocL(); + CleanupStack::PushL(publicKey); + hasher = CSHA1::NewL(); + CleanupStack::PushL(hasher); + hasher->Update(*publicKey); + publicKeyHash.Copy(hasher->Final()); + +#ifndef RD_MULTIPLE_DRIVE + + fileName.Copy(KKeyStoragePath); + +#else //RD_MULTIPLE_DRIVE + + TInt driveNumber( -1 ); + TChar driveLetter; + DriveInfo::GetDefaultDrive( DriveInfo::EDefaultSystem, driveNumber ); + iFs.DriveToChar( driveNumber, driveLetter ); + + TFileName keyStorageDir; + keyStorageDir.Format( KKeyStoragePath, (TUint)driveLetter ); + + fileName.Copy(keyStorageDir); + +#endif + + for (i = 0; i < SHA1_HASH; i++) + { + fileName.AppendNumFixedWidth(publicKeyHash[i], EHex, 2); + } + fileName.Append('\\'); + iFileMan->Delete(fileName, CFileMan::ERecurse); + iFs.MkDirAll(fileName); + iFs.SetSessionPath(fileName); + WriteFileL(iFs, KDeviceKeyFileName, aPrivateKey); + fileName.Copy(fileName); + WriteFileL(iFs, KDeviceCertFileName, aCertificateChain[0]); + for (i = 1; i < n; i++) + { + fileName.SetLength(0); + fileName.AppendFormat(KSingingCertFmt, i - 1); + WriteFileL(iFs, fileName, aCertificateChain[i]); + } + CleanupStack::PopAndDestroy(3); // hasher, publicKey, cert + LOG(_L("CDrmStdKeyStorage::ImportDataL <-")); + } + +// ----------------------------------------------------------------------------- +// CDrmStdKeyStorage::GetDeviceSpecificKeyL +// ----------------------------------------------------------------------------- +// +void CDrmStdKeyStorage::GetDeviceSpecificKeyL( + TBuf8& aKey) + { + + HBufC8* key = NULL; + TInt n; + CSHA1* hasher = NULL; + TBuf8 hash; + + if (iDeviceSpecificKey.Compare(KDefaultKey) == 0) + { + + GetImeiL(); + + HBufC8* buf = HBufC8::NewLC( iImei->Size() + sizeof(VID_DEFAULT) ); + TPtr8 ptr( buf->Des() ); + ptr.Copy( *iImei ); + ptr.Append(VID_DEFAULT); + + hasher = CSHA1::NewL(); + CleanupStack::PushL(hasher); + hasher->Update(ptr); + hash.Copy(hasher->Final()); + key=hash.AllocL(); + CleanupStack::PopAndDestroy(2,buf); // hasher,buf; + + n = Min(key->Length(), KDeviceSpecificKeyLength); + iDeviceSpecificKey.Copy(key->Right(n)); + delete key; + n = KDeviceSpecificKeyLength - n; + while (n > 0) + { + iDeviceSpecificKey.Append(0); + n--; + } + } + + aKey.Copy(iDeviceSpecificKey); + } + +// ----------------------------------------------------------------------------- +// CDrmStdKeyStorage::InitializeKeyL +// ----------------------------------------------------------------------------- +// +void CDrmStdKeyStorage::InitializeKeyL() + { + HBufC8* key = NULL; + TASN1DecInteger encInt; + TInt pos = 0; + + LOG(_L("CDrmStdKeyStorage::InitializeKeyL ->")); + delete iKey; + iKey = NULL; + ReadFileL(iFs, KDeviceKeyFileName, key); + CleanupStack::PushL(key); + TASN1DecGeneric gen(*key); + gen.InitL(); + pos += gen.LengthDERHeader(); + if (gen.Tag() != EASN1Sequence) + { + User::Leave(KErrArgument); + } + encInt.DecodeDERShortL(*key, pos); // version + RInteger modulus = encInt.DecodeDERLongL(*key, pos); + CleanupStack::PushL(modulus); + RInteger publicExponent = encInt.DecodeDERLongL(*key, pos); + CleanupStack::PushL(publicExponent); + RInteger privateExponent = encInt.DecodeDERLongL(*key, pos); + CleanupStack::PushL(privateExponent); + iKey = CRSAPrivateKeyStandard::NewL(modulus, privateExponent); + CleanupStack::Pop(); // privateExponent + CleanupStack::PopAndDestroy();// publicExponent + CleanupStack::Pop(); // modulus + CleanupStack::PopAndDestroy(); // key + LOG(_L("CDrmStdKeyStorage::InitializeKeyL <-")); + } + +// ----------------------------------------------------------------------------- +// CDrmStdKeyStorage::ModularExponentiateWithKeyL +// ----------------------------------------------------------------------------- +// +HBufC8* CDrmStdKeyStorage::ModularExponentiateWithKeyL( + const TDesC8& aInput) + { + RInteger result; + RInteger input; + HBufC8* output; + TInt keyLength = KKeyLength; + + LOG(_L("CDrmStdKeyStorage::ModularExponentiateWithKeyL ->")); + input = OS2IPL(aInput); + CleanupClosePushL(input); + result = TInteger::ModularExponentiateL(input,iKey->D(), iKey->N()); + CleanupClosePushL(result); + output = I2OSPL(result, keyLength); + CleanupStack::PopAndDestroy(2); // result, input + LOG(_L("CDrmStdKeyStorage::ModularExponentiateWithKeyL <-")); + return output; + } + +// ----------------------------------------------------------------------------- +// CDrmStdKeyStorage::CheckRootForCmlaL +// ----------------------------------------------------------------------------- +// +void CDrmStdKeyStorage::CheckRootForCmlaL() + { + CDir* dir = NULL; + HBufC8* buffer = NULL; + HBufC* name = NULL; + CX509Certificate* cert = NULL; + + LOG(_L("CDrmStdKeyStorage::CheckRootForCmlaL ->")); + __UHEAP_MARK; + iFs.GetDir(KSingingCertPattern, KEntryAttNormal, ESortByName, dir); + CleanupStack::PushL(dir); + ReadFileL(iFs, (*dir)[dir->Count() - 1].iName, buffer); + CleanupStack::PushL(buffer); + cert = CX509Certificate::NewL(*buffer); + CleanupStack::PushL(cert); + name = cert->SubjectName().DisplayNameL(); + CleanupStack::PushL(name); + if (name->Find(KCmla) != KErrNotFound) + { + iRootIsCmla = ETrue; + } + else + { + iRootIsCmla = EFalse; + } + CleanupStack::PopAndDestroy(4); // name, cert, buffer, dir + LOG(_L("CDrmStdKeyStorage::CheckRootForCmlaL <-")); + __UHEAP_MARKEND; + } + +// ----------------------------------------------------------------------------- +// CDrmStdKeyStorage::GetRdbSerialNumberL +// ----------------------------------------------------------------------------- +// +void CDrmStdKeyStorage::GetRdbSerialNumberL( + TBuf8& aSerialNumber) + { + HBufC8* buffer = NULL; + TUint att; + +#ifndef RD_MULTIPLE_DRIVE + + if (iFs.Att(KSerialNumberFile, att) != KErrNone) + +#else //RD_MULTIPLE_DRIVE + + TInt driveNumber( -1 ); + TChar driveLetter; + DriveInfo::GetDefaultDrive( DriveInfo::EDefaultSystem, driveNumber ); + iFs.DriveToChar( driveNumber, driveLetter ); + + TFileName serialNoFile; + serialNoFile.Format( KSerialNumberFile, (TUint)driveLetter ); + + if (iFs.Att(serialNoFile, att) != KErrNone) + +#endif + { + GenerateNewRdbSerialNumberL(); + } + +#ifndef RD_MULTIPLE_DRIVE + + ReadFileL(iFs, KSerialNumberFile, buffer); + +#else //RD_MULTIPLE_DRIVE + + ReadFileL(iFs, serialNoFile, buffer); + +#endif + + aSerialNumber.Copy(*buffer); + delete buffer; + } + +// ----------------------------------------------------------------------------- +// CDrmStdKeyStorage::GenerateNewRdbSerialNumberL +// ----------------------------------------------------------------------------- +// +void CDrmStdKeyStorage::GenerateNewRdbSerialNumberL() + { + TBuf8 serialNumber; + TPtr8 random( const_cast(serialNumber.Ptr()), + KRdbSerialNumberLength, + KRdbSerialNumberLength ); + + RandomDataGetL(random,KRdbSerialNumberLength); + +#ifndef RD_MULTIPLE_DRIVE + + WriteFileL(iFs, KSerialNumberFile, random); + +#else //RD_MULTIPLE_DRIVE + + TInt driveNumber( -1 ); + TChar driveLetter; + DriveInfo::GetDefaultDrive( DriveInfo::EDefaultSystem, driveNumber ); + iFs.DriveToChar( driveNumber, driveLetter ); + + TFileName serialNoFile; + serialNoFile.Format( KSerialNumberFile, (TUint)driveLetter ); + + WriteFileL(iFs, serialNoFile, random); + +#endif + + } + +// ----------------------------------------------------------------------------- +// CDrmStdKeyStorage::UdtEncryptL +// ----------------------------------------------------------------------------- +// +HBufC8* CDrmStdKeyStorage::UdtEncryptL( + const TDesC8& aInput) + { + HBufC8* buffer = NULL; + HBufC8* output = HBufC8::NewMaxLC( 256 ); + CX509Certificate* cert = NULL; + CRSAPublicKey* key = NULL; + TX509KeyFactory factory; + CRSAPKCS1v15Encryptor* encryptor = NULL; + TPtr8 result(const_cast(output->Ptr()), 0, 256); + +#ifndef RD_MULTIPLE_DRIVE + + ReadFileL(iFs, KUdtCertFileName, buffer); + +#else //RD_MULTIPLE_DRIVE + + TInt driveNumber( -1 ); + TChar driveLetter; + DriveInfo::GetDefaultDrive( DriveInfo::EDefaultRom, driveNumber ); + iFs.DriveToChar( driveNumber, driveLetter ); + + TFileName udtCertFile; + udtCertFile.Format( KUdtCertFileName, (TUint)driveLetter ); + + ReadFileL(iFs, udtCertFile, buffer); + +#endif + + CleanupStack::PushL(buffer); + cert = CX509Certificate::NewL(*buffer); + CleanupStack::PushL(cert); + key = factory.RSAPublicKeyL(cert->PublicKey().KeyData()); + CleanupStack::PushL(key); + + encryptor = CRSAPKCS1v15Encryptor::NewLC(*key); + encryptor->EncryptL(aInput, result); + + CleanupStack::PopAndDestroy(4); // encryptor, key, cert, buffer + CleanupStack::Pop();// output + return output; + }; + +// ----------------------------------------------------------------------------- +// CDrmStdKeyStorage::GetRootCertificatesL +// ----------------------------------------------------------------------------- +// +void CDrmStdKeyStorage::GetRootCertificatesL( + RPointerArray& aRootCerts) + { + CDir* dir = NULL; + CDir* rootCerts = NULL; + TFileName dirName; + HBufC8* cert = NULL; + TInt i = 0; + TBuf<256> path; + + iFs.SessionPath( path ); + +#ifndef RD_MULTIPLE_DRIVE + + if (iFs.GetDir(KKeyStoragePath, KEntryAttDir, ESortByName, dir) == KErrNone) + +#else //RD_MULTIPLE_DRIVE + + TFileName tempPath; + TInt driveNumber( -1 ); + TChar driveLetter; + DriveInfo::GetDefaultDrive( DriveInfo::EDefaultSystem, driveNumber ); + iFs.DriveToChar( driveNumber, driveLetter ); + + tempPath.Format( KKeyStoragePath, (TUint)driveLetter ); + + if (iFs.GetDir(tempPath, KEntryAttDir, ESortByName, dir) == KErrNone) + +#endif + { + CleanupStack::PushL(dir); + for(i = 0; i < dir->Count(); i++) + { + if ((*dir)[i].IsDir()) + { + +#ifndef RD_MULTIPLE_DRIVE + + dirName.Copy(KKeyStoragePath); + +#else //RD_MULTIPLE_DRIVE + + dirName.Copy(tempPath); + +#endif + + dirName.Append((*dir)[i].iName); + dirName.Append('\\'); + User::LeaveIfError(iFs.SetSessionPath(dirName)); + User::LeaveIfError(iFs.GetDir(KSingingCertPattern, KEntryAttNormal, ESortByName, rootCerts)); + CleanupStack::PushL(rootCerts); + ReadFileL(iFs, (*rootCerts)[rootCerts->Count() - 1].iName, cert); + CleanupStack::PushL(cert); + aRootCerts.AppendL(cert); + CleanupStack::Pop(cert); + CleanupStack::PopAndDestroy(); // rootCerts + } + } + CleanupStack::PopAndDestroy(dir); + } + +#ifndef RD_MULTIPLE_DRIVE + + if (iFs.GetDir(KRomKeyStoragePath, KEntryAttDir, ESortByName, dir) == KErrNone) + +#else //RD_MULTIPLE_DRIVE + + DriveInfo::GetDefaultDrive( DriveInfo::EDefaultRom, driveNumber ); + iFs.DriveToChar( driveNumber, driveLetter ); + + tempPath.Format( KRomKeyStoragePath, (TUint)driveLetter ); + + if (iFs.GetDir(tempPath, KEntryAttDir, ESortByName, dir) == KErrNone) + +#endif + { + CleanupStack::PushL(dir); + for(i = 0; i < dir->Count(); i++) + { + if ((*dir)[i].IsDir()) + { + +#ifndef RD_MULTIPLE_DRIVE + + dirName.Copy(KRomKeyStoragePath); + +#else //RD_MULTIPLE_DRIVE + + dirName.Copy(tempPath); + +#endif + + dirName.Append((*dir)[i].iName); + dirName.Append('\\'); + User::LeaveIfError(iFs.SetSessionPath(dirName)); + User::LeaveIfError(iFs.GetDir(KSingingCertPattern, KEntryAttNormal, ESortByName, rootCerts)); + CleanupStack::PushL(rootCerts); + ReadFileL(iFs, (*rootCerts)[rootCerts->Count() - 1].iName, cert); + CleanupStack::PushL(cert); + aRootCerts.AppendL(cert); + CleanupStack::Pop(cert); + CleanupStack::PopAndDestroy(); // rootCerts + } + } + CleanupStack::PopAndDestroy(dir); + } + iFs.SetSessionPath( path ); + } + +// ----------------------------------------------------------------------------- +// CDrmStdKeyStorage::GetIMEIL +// ----------------------------------------------------------------------------- +// +const TDesC& CDrmStdKeyStorage::GetImeiL() + { + if ( iImei ) + { + return *iImei; + } + +#if (defined __WINS__ || defined WINSCW) + // Default IMEI used for emulator + _LIT( KDefaultSerialNumber, "123456789123456789" ); + iImei = KDefaultSerialNumber().AllocL(); + + return *iImei; +#else + + TInt error( KErrNone ); + TInt count( 0 ); + TInt count2( 0 ); + TUint32 caps( 0 ); + TBool found (EFalse); + + RTelServer etelServer; + RMobilePhone phone; + + TUint KMaxImeiTries = 5; + + for ( TUint8 i = 0; i < KMaxImeiTries; ++i ) + { + error = etelServer.Connect(); + if ( error ) + { + User::After( TTimeIntervalMicroSeconds32( KWaitingTime ) ); + } + else + { + break; + } + } + + User::LeaveIfError( error ); + CleanupClosePushL( etelServer ); + + User::LeaveIfError( etelServer.LoadPhoneModule( KMmTsyModuleName ) ); + + TUnloadModule unload; + unload.iServer = &etelServer; + unload.iName = &KMmTsyModuleName; + + TCleanupItem item( DoUnloadPhoneModule, &unload ); + CleanupStack::PushL( item ); + User::LeaveIfError( etelServer.EnumeratePhones( count ) ); + + for ( count2 = 0; count2 < count && !found; ++count2 ) + { + RTelServer::TPhoneInfo phoneInfo; + User::LeaveIfError( etelServer.GetTsyName( count2, phoneInfo.iName ) ); + + if ( phoneInfo.iName.CompareF(KMmTsyModuleName()) == 0 ) + { + User::LeaveIfError( etelServer.GetPhoneInfo( count2, phoneInfo ) ); + User::LeaveIfError( phone.Open( etelServer, phoneInfo.iName ) ); + CleanupClosePushL( phone ); + found = ETrue; + } + } + + if ( !found ) + { + // Not found. + User::Leave( KErrNotFound ); + } + + User::LeaveIfError( phone.GetIdentityCaps( caps ) ); + if (!( caps & RMobilePhone::KCapsGetSerialNumber )) + { + User::Leave( KErrNotFound ); + } + + RMobilePhone::TMobilePhoneIdentityV1 id; + TRequestStatus status; + + phone.GetPhoneId( status, id ); + + User::WaitForRequest( status ); + + User::LeaveIfError( status.Int() ); + + iImei = id.iSerialNumber.AllocL(); + + CleanupStack::PopAndDestroy( 3 ); // phone, item, etelServer + + HBufC8* buf = HBufC8::NewL( iImei->Size() ); + TPtr8 ptr( buf->Des() ); + ptr.Copy( *iImei ); + + LOG(_L("IMEI:")); + LOGHEX(ptr); + delete buf; + + return *iImei; +#endif /* __WINS__ , WINSCW */ + + } + + +// ----------------------------------------------------------------------------- +// CDrmStdKeyStorage::RandomDataGetL +// ----------------------------------------------------------------------------- +// + +void CDrmStdKeyStorage::RandomDataGetL( TDes8& aData, const TInt aLength ) + { + if ( aLength <= 0 ) + { + User::Leave(KErrArgument); + } + + TInt size = aData.MaxSize(); + + if( size < aLength ) + { + User::Leave(KErrOverflow); + } + + TRandom::Random( aData ); + } + +// end of file diff -r e9fb2728ea8b -r ca165d35976d breakdeps/DRMEngine/DrmStdKeyStorage.mmp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/breakdeps/DRMEngine/DrmStdKeyStorage.mmp Wed Oct 27 13:24:02 2010 +0100 @@ -0,0 +1,68 @@ +/* +* Copyright (c) 2004-2006 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: DRM Std Key Storage Module +* +*/ + + +#include + +TARGET DrmStdKeyStorage.dll +TARGETTYPE DLL +UID 0x1000008D 0x10205CAF +CAPABILITY CAP_GENERAL_DLL DRM CommDD +VENDORID VID_DEFAULT + +USERINCLUDE ../keystorage/inc +USERINCLUDE ../utils/inc +USERINCLUDE ../../../inc // ADo level inc dir + +// Default system include paths for middleware layer modules. +MW_LAYER_SYSTEMINCLUDE +SYSTEMINCLUDE /epoc32/include/libc +SYSTEMINCLUDE /epoc32/include/ecom + +SOURCEPATH ../keystorage/src +SOURCE DrmStdKeyStorage.cpp + +LIBRARY euser.lib +LIBRARY efsrv.lib +LIBRARY asn1.lib +LIBRARY cryptography.lib +LIBRARY crypto.lib +LIBRARY x500.lib +LIBRARY x509.lib +LIBRARY pkixcert.lib +LIBRARY random.lib +LIBRARY hash.lib +LIBRARY etel.lib +LIBRARY etelmm.lib +LIBRARY flogger.lib +LIBRARY featmgr.lib + +#ifdef RD_MULTIPLE_DRIVE +LIBRARY platformenv.lib +#endif + +#if defined(ARMCC) +deffile ../eabi/ +#elif defined( WINSCW ) +deffile ../bwinscw/ +#elif defined( WINS ) +deffile ../bwins/ +#else +deffile ../bmarm/ +#endif + +SMPSAFE diff -r e9fb2728ea8b -r ca165d35976d breakdeps/DRMEngine/ROAPHandler.mmp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/breakdeps/DRMEngine/ROAPHandler.mmp Wed Oct 27 13:24:02 2010 +0100 @@ -0,0 +1,141 @@ +/* +* Copyright (c) 2004-2008 Nokia Corporation and/or its subsidiary(-ies). +* All rights reserved. +* This component and the accompanying materials are made available +* under the terms of "Eclipse Public License v1.0" +* which accompanies this distribution, and is available +* at the URL "http://www.eclipse.org/legal/epl-v10.html". +* +* Initial Contributors: +* Nokia Corporation - initial contribution. +* +* Contributors: +* +* Description: ROAP Handler build configuration +* +*/ + + +#include +#include + +TARGET ROAPHandler.dll +TARGETTYPE DLL +UID 0x1000008D 0x101F6DB5 +CAPABILITY CAP_GENERAL_DLL DRM +VENDORID VID_DEFAULT + +USERINCLUDE ../dcf/inc +USERINCLUDE ../dm/inc +USERINCLUDE ../agentv2/inc +USERINCLUDE ../ro/inc +USERINCLUDE ../roap/inc +USERINCLUDE ../utils/inc +USERINCLUDE ../server/inc +USERINCLUDE ../roapstorage/inc +USERINCLUDE ../drmclock/Inc +USERINCLUDE ../dcfrepository/client/inc +USERINCLUDE ../../../inc // ADo level inc dir + +// Default system include paths for middleware layer modules. +APP_LAYER_SYSTEMINCLUDE +SYSTEMINCLUDE /epoc32/include/libc +SYSTEMINCLUDE /epoc32/include/ecom + +SOURCEPATH ../roap/src + +SOURCE RoapEngBase.cpp +SOURCE RoapEng.cpp +SOURCE RoapTrigger.cpp +SOURCE RoapHttpHandler.cpp +SOURCE RoapConnection.cpp +SOURCE RoapResponse.cpp +SOURCE RoapSyncWrapper.cpp + +SOURCE RoapSigner.cpp + +SOURCE RoapParser.cpp +SOURCE JoinDomainRespParser.cpp +SOURCE LeaveDomainRespParser.cpp +SOURCE RegistrationRespParser.cpp +SOURCE RightsRespParser.cpp +SOURCE RIHelloParser.cpp +SOURCE RoapTriggerParser.cpp + +SOURCE RoapMessage.cpp +SOURCE DeviceHello.cpp +SOURCE RIHello.cpp +SOURCE RegistrationReq.cpp +SOURCE RegistrationResp.cpp +SOURCE RightsReq.cpp +SOURCE RightsResp.cpp +SOURCE JoinDomainReq.cpp +SOURCE JoinDomainResp.cpp +SOURCE LeaveDomainReq.cpp +SOURCE LeaveDomainResp.cpp + +#ifdef RD_DRM_METERING +SOURCE MeteringReportReq.cpp +SOURCE MeteringReportResp.cpp +SOURCE MeteringReportRespParser.cpp +#endif + +SOURCEPATH ../utils/src +SOURCE MultipartHandler.cpp + +LIBRARY euser.lib +LIBRARY estor.lib +LIBRARY efsrv.lib +LIBRARY commdb.lib +LIBRARY bafl.lib +LIBRARY esock.lib +LIBRARY http.lib +LIBRARY inetprotutil.lib +LIBRARY XmlFramework.lib +LIBRARY apmime.lib +LIBRARY asn1.lib +LIBRARY cryptography.lib +LIBRARY crypto.lib +LIBRARY ecom.lib +LIBRARY x509.lib +LIBRARY x500.lib +LIBRARY pkixcert.lib +LIBRARY random.lib +LIBRARY hash.lib +LIBRARY etel.lib +LIBRARY etelmm.lib +LIBRARY CharConv.lib +LIBRARY drmcrypto.lib +LIBRARY DrmParsers.lib +LIBRARY DrmDcf.lib +LIBRARY DrmRights.lib +LIBRARY DrmServerInterfaces.lib +LIBRARY DcfRep.lib +LIBRARY caf.lib // Embedding domain ROs +LIBRARY cafutils.lib // Embedding domain ROs +LIBRARY centralrepository.lib // Browser default AP +LIBRARY cmmanager.lib +LIBRARY featmgr.lib + +LIBRARY SysUtil.lib +LIBRARY HttpFilterCommon.lib +LIBRARY CommonUI.lib +LIBRARY PlatformEnv.lib +LIBRARY drmroapwbxmlparser.lib + + +// Uncomment the following lines to enable internal logging. +macro _ROAP_TESTING +LIBRARY flogger.lib + +#if defined(ARMCC) +deffile ../eabi/ +#elif defined( WINSCW ) +deffile ../bwinscw/ +#elif defined( WINS ) +deffile ../bwins/ +#else +deffile ../bmarm/ +#endif + +SMPSAFE diff -r e9fb2728ea8b -r ca165d35976d breakdeps/DRMEngine/RightsServer.mmp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/breakdeps/DRMEngine/RightsServer.mmp Wed Oct 27 13:24:02 2010 +0100 @@ -0,0 +1,187 @@ +/* +* 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: Makefile of DRM Engine & DRM Rights Database +* +*/ + + +#include + +TARGET RightsServer.exe +TARGETTYPE EXE + +UID 0x1000008d 0x101F51F2 +CAPABILITY CAP_SERVER DRM CommDD ProtServ PowerMgmt Location +VENDORID VID_DEFAULT + +// Default system include paths for middleware layer modules. +MW_LAYER_SYSTEMINCLUDE +SYSTEMINCLUDE /epoc32/include/libc +SYSTEMINCLUDE /epoc32/include/connect + +USERINCLUDE ../server/inc +USERINCLUDE ../agentv2/inc +USERINCLUDE ../ro/inc +USERINCLUDE ../dcf/inc +USERINCLUDE ../notifier/inc +USERINCLUDE ../utils/inc +USERINCLUDE ../roap/inc +USERINCLUDE ../roapstorage/inc +USERINCLUDE ../drmclock/Inc +USERINCLUDE ../keystorage/inc +USERINCLUDE ../drmbackup/inc +USERINCLUDE ../../../inc // ADo level inc dir + +SOURCEPATH ../server/src + +// DRM Engine (server side) +SOURCE DRMRightsServer.cpp +SOURCE DRMDbSession.cpp +// SOURCE drmpermissionlist.cpp +SOURCE drmparentstorage.cpp +// SOURCE drmpermissionitem.cpp +SOURCE DRMReplayCache.cpp +SOURCE DRMXOma.cpp +SOURCE DRMActiveOperation.cpp +SOURCE DRMObsoleteFinder.cpp +SOURCE drmconsume.cpp + +// DRM Rights Database +SOURCE drmrightsdb.cpp +SOURCE DRMRightsData.cpp +SOURCE DRMCommonData.cpp +SOURCE DRMRightsCleaner.cpp + +// DRM Metering +#ifdef RD_DRM_METERING +SOURCE drmmeteringdbdata.cpp +#endif +SOURCE drmmeteringdb.cpp + +// DRM Backup implementation +SOURCEPATH ../drmbackup/src +SOURCE DRMBackup.cpp +SOURCE DRMBackupObserver.cpp + +// DRM Notifier +SOURCEPATH ../notifier/src + +SOURCE DRMMessageStorage.cpp +SOURCE DRMNotifierServer.cpp +SOURCE DRMNotifierSession.cpp + +// RoapStorage +SOURCEPATH ../roapstorage/src + +SOURCE RoapStorageClient.cpp +SOURCE RoapStorageServer.cpp +SOURCE RoapStorageSession.cpp +SOURCE DRMContextDB.cpp +// OCSP cert classes +SOURCE responsedecoder.cpp +SOURCE response.cpp +SOURCE responsecertinfo.cpp +SOURCE certid.cpp + + +// DRM Clock +#ifdef __DRM_CLOCK +SOURCEPATH ../drmclock/Src +SOURCE DRMClock.cpp +SOURCE DRMClockServer.cpp +SOURCE DRMClockSession.cpp + +SOURCE DRMNitzObserver.cpp +SOURCE GPSWatcher.cpp +SOURCE GPSTimeUpdater.cpp + +#else +#ifdef __DRM_OMA2 +SOURCEPATH ../DRMClock/src +SOURCE OMA2NotSupportedWithoutDRMClock:define__DRM_CLOCKvariation.cpp +#endif // __DRM_OMA2 +#endif // __DRM_CLOCK + +// RDB and Process Watcher +SOURCEPATH ../utils/src +SOURCE dbwatcher.cpp +SOURCE dirwatcher.cpp +SOURCE procwatcher.cpp + +LIBRARY drmdcf.lib +LIBRARY drmrights.lib +LIBRARY drmserverinterfaces.lib +LIBRARY euser.lib +LIBRARY estor.lib +LIBRARY efsrv.lib +LIBRARY hash.lib +LIBRARY cryptography.lib +LIBRARY crypto.lib +LIBRARY asn1.lib +LIBRARY x509.lib +LIBRARY x500.lib +LIBRARY pkixcert.lib +LIBRARY drmcrypto.lib +LIBRARY drmkeystorage.lib +LIBRARY edbms.lib +LIBRARY bafl.lib +LIBRARY etel.lib +LIBRARY etelmm.lib +LIBRARY abclient.lib +LIBRARY charconv.lib +LIBRARY dcfrep.lib +LIBRARY drmparsers.lib // DRM message parser for RO import +LIBRARY centralrepository.lib // Browser default AP +LIBRARY InetProtUtil.lib // URI parser +LIBRARY flogger.lib +LIBRARY featmgr.lib // Feature Manager +LIBRARY wmdrmfileserverclient.lib +LIBRARY lbs.lib // GPS libraries +LIBRARY eposindicator.lib // GPS positioner indicator lib +#ifdef RD_DRM_METERING +LIBRARY random.lib +#endif + +LIBRARY StarterClient.lib // reset + +#ifdef RD_MULTIPLE_DRIVE +LIBRARY platformenv.lib +#endif + +LIBRARY SysUtil.lib +// LIBRARY commonengine.lib // Backup + +/* +#if !defined(WINS) +MACRO DRM_USE_SERIALNUMBER +LIBRARY etel.lib +#endif +*/ +// Uncomment the following lines to enable internal logging. +/* +macro _DRM_TESTING +USERINCLUDE ../internal/tsrc_internal +SOURCEPATH ../internal/tsrc_internal +LIBRARY drmdebugtools.lib +LIBRARY HAL.lib +LIBRARY charconv.lib +*/ + +#if defined( WINSCW ) +deffile ../bwinscw/ +#elif defined( WINS ) +deffile ../bwins/ +#endif + +//SMPSAFE diff -r e9fb2728ea8b -r ca165d35976d breakdeps/DRMEngine/RoapEng.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/breakdeps/DRMEngine/RoapEng.cpp Wed Oct 27 13:24:02 2010 +0100 @@ -0,0 +1,2695 @@ +/* +* Copyright (c) 2002-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: Roap engine + * +*/ + + +// INCLUDE FILES + +#include + +#include + +#ifdef RD_MULTIPLE_DRIVE +#include +#include +#else +#include +#endif + +#ifndef __WINS__ +#include +#include +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include // CleanupResetAndDestroyPushL dependencies + +#include "cleanupresetanddestroy.h" // CleanupResetAndDestroyPushL +#include "DRMRights.h" +#include "RoapEng.h" +#include "RoapTrigger.h" +#include "wbxmlroaptriggerparser.h" +#include "RoapResponse.h" +#include "RoapMessage.h" +#include "RoapParser.h" +#include "RoapSigner.h" +#include "DeviceHello.h" +#include "RIHello.h" +#include "RegistrationReq.h" +#include "RegistrationResp.h" +#include "RightsReq.h" +#include "RightsResp.h" +#include "JoinDomainReq.h" +#include "JoinDomainResp.h" +#include "LeaveDomainReq.h" +#include "LeaveDomainResp.h" +#ifdef RD_DRM_METERING +#include "MeteringReportReq.h" +#include "MeteringReportResp.h" +#endif +#include "RoapStorageClient.h" +#include "RoapDef.h" +#include "RoapLog.h" +#include "RoapObserver.h" +#include "CmlaCrypto.h" +#include "DRMRIContext.h" +#include "DRMDomainContext.h" +#include "DRMProtectedRoParser.h" +#include "DRMClockClient.h" +#include "DcfRep.h" +#include "DcfEntry.h" +#include "Base64.h" +#include "drmsettingsplugininternalcrkeys.h" + + +#define STUB_C_CLASS_IN_NAMESPACE( n, c ) namespace n { class c: public CBase { private: c(); public: virtual ~c(); }; } n::c::c() {} n::c::~c() {} +#define STUB_C_CLASS( c ) class c : public CBase { private: c(); public: virtual ~c(); }; c::c() {} c::~c() {} +// This class does not do anything. +// It is defined here only to keep binary compatibility, +// because of unintentional class name leak in +// armv5 export history. +// Don't ever use this class for anything. +STUB_C_CLASS_IN_NAMESPACE( Roap , CWbxmlRoapTriggerToXmlParser ) + +// Yet another stub classes because of moved classes +// which have leaked virtual table entries +STUB_C_CLASS( COCSPResponse ) +STUB_C_CLASS( COCSPResponseCertInfo ) + + +using namespace Roap; +// ================= CONSTANTS ======================= +// For parsing multipart content +_LIT8(KCmlaIp1, "http://www.cm-la.com/tech/cmlaip/cmlaip#cmlaip-1"); +_LIT8(KLeaveDomainElement, "leaveDomain"); +_LIT8(KSignedInfoElement, "SignedInfo"); +_LIT(KBOM1, "\xFFFE"); +_LIT(KBOM2, "\xFEFF"); +#ifdef RD_DRM_METERING +_LIT8( KRoapVersion11, "1.1" ); +#endif + +static const TInt KDomainGenerationLength( 3 ); +static const TInt KMinCertChainLength( 3 ); +// ================= LOCAL FUNCTIONS ======================= + +LOCAL_C TBool SortArrays( + RPointerArray& aKeys, + RPointerArray& aMacs, + RPointerArray& aElements, + RArray& aOrder ) + { + TInt i; + TInt j; + TInt index; + HBufC8* temp1 = NULL; + HBufC8* temp2 = NULL; + HBufC8* temp3 = NULL; + TBool isInOrder = ETrue; + + if ( aOrder.Count() != aKeys.Count() || aKeys.Count() != aMacs.Count() + || aMacs.Count() != aElements.Count() ) + { + return EFalse; + } + + for ( i = 0; i < aKeys.Count(); i++ ) + { + index = aOrder[i]; + temp1 = aKeys[i]; + temp2 = aMacs[i]; + temp3 = aElements[i]; + j = i; + while ( ( j > 0 ) && ( aOrder[j - 1] > index ) ) + { + isInOrder = EFalse; + aOrder[j] = aOrder[j - 1]; + aKeys[j] = aKeys[j - 1]; + aMacs[j] = aMacs[j - 1]; + aElements[j] = aElements[j - 1]; + j = j - 1; + } + aOrder[j] = index; + aKeys[j] = temp1; + aMacs[j] = temp2; + aElements[j] = temp3; + } + return isInOrder; + } + +// ================= MEMBER FUNCTIONS ======================= + +// --------------------------------------------------------- +// CRoapEng::NewL() +// --------------------------------------------------------- +// +EXPORT_C CRoapEng* CRoapEng::NewL() + { + CRoapEng* engine = new ( ELeave ) CRoapEng(); + CleanupStack::PushL( engine ); + engine->ConstructL(); + CleanupStack::Pop( engine ); + return engine; + } + +// --------------------------------------------------------- +// CRoapEng::~CRoapEng() +// --------------------------------------------------------- +// +EXPORT_C CRoapEng::~CRoapEng() + { + if ( iStorageClient ) + { + iStorageClient->Close(); + } + delete iStorageClient; + if ( iClockClient ) + { + iClockClient->Close(); + } + delete iClockClient; + delete iParser; + delete iSigner; + delete iDeviceId; + delete iRoParser; + delete iDcfRep; + iRiAlgorithms.ResetAndDestroy(); + } + +// --------------------------------------------------------- +// CRoapEng::~CRoapEng() +// --------------------------------------------------------- +// +void CRoapEng::ConstructL() + { + LOGLIT( "CRoapEng::ConstructL" ) + + CRoapEngBase::ConstructL(); + iParser = CRoapParser::NewL(); + iStorageClient = new ( ELeave ) RRoapStorageClient; + User::LeaveIfError( iStorageClient->Connect() ); + iClockClient = new ( ELeave ) RDRMClockClient; + User::LeaveIfError( iClockClient->Connect() ); + TBuf8 deviceId; + iStorageClient->GetDevicePublicKeyHashL( deviceId ); + iDeviceId = deviceId.AllocL(); + iSigner = CRoapSigner::NewL( *iStorageClient ); + iRoParser = CDrmProtectedRoParser::NewL(); + iDcfRep = CDcfRep::NewL(); + iCertNeeded = ETrue; + iRiSupportsCertCaching = EFalse; + iTransStatus = ENotAsked; + iSelectedAlgorithms = EOma; + iSelectedRoot = KNullDesC8; + iStorageClient->SelectTrustedRootL( KNullDesC8 ); + iDeviceTimeError = EFalse; + iDomainId.SetLength( 0 ); + iSecureTime = ETrue; + iZone = 0; + } + +// --------------------------------------------------------- +// CRoapEng::CRoapEng() +// --------------------------------------------------------- +// +CRoapEng::CRoapEng() : + CRoapEngBase() + { + } + +// --------------------------------------------------------- +// CRoapEng::ParseTriggerL() +// --------------------------------------------------------- +// +CRoapTrigger* CRoapEng::ParseTriggerL( const TDesC8& aTrigger ) + { + LOGLIT( "CRoapEng::ParseTriggerL" ) + + CRoapTrigger* trigger( NULL ); + RBuf8 xmlTrigger; + CleanupClosePushL( xmlTrigger ); + _LIT8( KRoap, "ParseL( aTrigger ) ); + if ( parseError == KErrNone ) + { + xmlTrigger.Assign( b ); + b = NULL; + LOGLIT( " We have a WBXML trigger" ) + } + else + { // OMA BCAST: Check if this is an XML trigger after all.. + LOGLIT( " We have an XML trigger after all" ) + xmlTrigger.CreateL( aTrigger ); + } + CleanupStack::PopAndDestroy( wbParser ); + } + else + { + xmlTrigger.CreateL( aTrigger ); + } + trigger = iParser->ParseRoapTriggerL( xmlTrigger ); + + CleanupStack::PushL( trigger ); + if ( !trigger || !trigger->ValidTrigger() ) + { + User::Leave( KErrRoapGeneral ); + } + + // check that SilentRightsUrl is on the white list + // URL is searched from pre-configured white list + TBool fromPreConfiguredWhiteList( ETrue ); + if ( iStorageClient->WhiteListURLExistsL( *trigger->iRoapUrl, fromPreConfiguredWhiteList ) ) + { + iAllowedToContactRi = ETrue; + } + + if ( trigger->iTriggerType == ELeaveDomainTrigger && trigger->iSignature ) + { + if ( !VerifyTriggerSignatureL( xmlTrigger, *trigger ) ) + { + User::Leave( KErrRoapServerFatal ); + } + } + + CleanupStack::Pop( trigger ); + CleanupStack::PopAndDestroy( &xmlTrigger ); + + return trigger; + } + +// --------------------------------------------------------- +// CRoapEng::GetRIContextL() +// --------------------------------------------------------- +// +void CRoapEng::GetRIContextL( TBool& aRegistered, const TDesC8& aRiId ) + { + LOGLIT( "CRoapEng::GetRIContextL" ) + + CDRMRIContext* context = NULL; + + aRegistered = EFalse; + + // delete old RI context and obtain a new one + delete iStoredRiContext; + iStoredRiContext = NULL; + context = iStorageClient->GetRIContextL( aRiId ); + if ( !context ) + { + return; + } + + iStoredRiContext = context; + iRiSupportsCertCaching = iStoredRiContext->DeviceCertCached(); + iSelectedRoot = iStoredRiContext->SelectedDeviceRoot(); + iStorageClient->SelectTrustedRootL( iSelectedRoot ); + + if ( context->CertificateChain().Count() && context->ExpiryTime() + > GetDrmTimeL() ) + { + aRegistered = ETrue; + iUseRiContextUrl = EFalse; + } + else + { + // Received Context was invalid or expired + iUseRiContextUrl = EFalse; + delete iStoredRiContext; + iStoredRiContext = NULL; + } + } + +// --------------------------------------------------------- +// CRoapEng::GetDomainContextL() +// --------------------------------------------------------- +// +void CRoapEng::GetDomainContextL( + TBool& aIsJoined, + TBool& aIsValidGeneration, + const TDesC8& aDomainId ) + { + LOGLIT( "CRoapEng::GetDomainContextL" ) + + TInt generation = 0; + CDRMDomainContext* context = NULL; + + aIsJoined = EFalse; + aIsValidGeneration = EFalse; + + // last 3 digits are for Domain generation + context = iStorageClient->GetDomainContextL( aDomainId ); + + if ( !context ) + { + return; + } + + if ( context->ExpiryTime() > GetDrmTimeL() || context->ExpiryTime() + == Time::NullTTime() ) + { + aIsJoined = ETrue; + } + + TLex8 lex( aDomainId.Right( KDomainGenerationLength ) ); + lex.Val( generation ); + + if ( context->DomainGeneration() >= generation ) + { + aIsValidGeneration = ETrue; + } + + delete context; + } + +// --------------------------------------------------------- +// CRoapEng::CreateReqMessageL() +// --------------------------------------------------------- +// +void CRoapEng::CreateReqMessageL() + { + LOGLIT( "CRoapEng::CreateReqMessageL" ) + + __ASSERT_ALWAYS( iTrigger, User::Invariant() ); + __ASSERT_ALWAYS( !iRequest, User::Invariant() ); + + switch ( iReqMessage ) + { + case EDeviceHello: + { + iRequest = CreateDeviceHelloL(); + break; + } + case ERegistration: + { + iRequest = CreateRegistrationRequestL(); + break; + } + case EROAcquisition: + { + iRequest = CreateRightsRequestL(); + break; + } + case EJoinDomain: + { + iRequest = CreateJoinDomainRequestL(); + break; + } + case ELeaveDomain: + { + iRequest = CreateLeaveDomainRequestL(); + break; + } +#ifdef RD_DRM_METERING + case EMeteringRequest: + { + iRequest = CreateMeteringReportRequestL(); + break; + } +#endif + default: + { + User::Leave( KErrArgument ); + } + } + } + +// --------------------------------------------------------- +// CRoapEng::CreateDeviceHelloL() +// --------------------------------------------------------- +// +CRoapMessage* CRoapEng::CreateDeviceHelloL() + { + LOGLIT( "CRoapEng::CreateDeviceHelloL" ) + PERFORMANCE_LOGLIT( "Registration protocol started" ) + + RPointerArray idArray; + CDeviceHello* req = CDeviceHello::NewL(); + CleanupStack::PushL( req ); + + // Multi-PKI addition + CleanupResetAndDestroyPushL( idArray ); + CreateDeviceIdHashArrayL( idArray ); + for ( TInt i = 0; i < idArray.Count(); i++ ) + { + req->iDeviceIdArray.AppendL( *idArray[i] ); + } + CleanupStack::PopAndDestroy( &idArray ); + // Multi-PKI + +#ifndef RD_DRM_METERING + req->iVersion.Copy( KRoapVersion ); // Version 1.0 +#else + req->iVersion.Copy( KRoapVersion11 ); +#endif + if ( iTrigger->iNonce ) + { + req->iTriggerNonce = iTrigger->iNonce->AllocL(); + } + CmlaCrypto::SupportedAlgorithmsL( req->iAlgorithms ); + iSelectedAlgorithms = EOma; + + CleanupStack::Pop( req ); + return req; + } + +// --------------------------------------------------------- +// CRoapEng::CreateRegistrationRequestL() +// --------------------------------------------------------- +// +CRoapMessage* CRoapEng::CreateRegistrationRequestL() + { + LOGLIT( "CRoapEng::CreateRegistrationRequestL ->" ) + + __ASSERT_ALWAYS( iResponse, User::Invariant() ); + + CRegistrationReq* req = NULL; + CRIHello* resp = NULL; + RPointerArray trustedRootArray; + HBufC8* temp = NULL; + + resp = STATIC_CAST( CRIHello*, iResponse ); + req = CRegistrationReq::NewL(); + CleanupStack::PushL( req ); + if ( resp->iSession ) + { + req->iSession = resp->iSession->AllocL(); + } + else + { + User::Leave( KErrRoapServerFatal ); + } + + req->iNonce.SetLength( KDeviceNonceLength ); + TRandom::Random( req->iNonce ); + + req->iTime = GetDrmTimeL(); + + // store the nonce for DRM Time sync + iRegReqNonce = req->iNonce; + + if ( iCertNeeded ) + { + req->iCertificateChain = GetCertificateChainL(); + if ( resp->iCertificateCaching ) + { + iCertNeeded = EFalse; + } + } + + // Send all our trusted roots to the RI + CleanupResetAndDestroyPushL( trustedRootArray ); + + LOGLIT( " Getting trusted roots" ) + + iStorageClient->GetTrustedRootsL( trustedRootArray ); + + if ( !trustedRootArray.Count() ) + { + // No trusted roots found! + LOGLIT( " No trusted roots found!" ) + User::Leave( KErrRoapDevice ); + } + for ( TInt i = 0; i < trustedRootArray.Count(); i++ ) + { + temp = trustedRootArray[i]->AllocLC(); + req->iTrustedAuthorities.AppendL( temp ); + CleanupStack::Pop( temp ); + } + + LOGLIT( " Setting server info" ) + if ( resp->iServerInfo && resp->iServerInfo->Size() ) + { + req->iServerInfo = resp->iServerInfo->AllocL(); + } + + if ( iStoredRiContext ) + { + LOGLIT( " RI context available" ) + req->iPeerKeyIdentifier = iStoredRiContext->RIID(); + + if ( iStoredRiContext->OCSPResponse().Count() && !iDeviceTimeError ) + { + req->iOcspInfoStored = ETrue; + req->iOcspResponderKeyId = GetOCSPResponderKeyHashL(); + } + } + if ( resp->iNeedDeviceDetails ) + { + LOGLIT( " Getting device details" ) + GetDeviceDetailsL( req->iDeviceDetailsManufacturer, + req->iDeviceDetailsModel, req->iDeviceDetailsVersion ); + } + + if ( iTrigger->iNonce ) + { + req->iTriggerNonce = iTrigger->iNonce->AllocL(); + } + + CleanupStack::PopAndDestroy( &trustedRootArray ); + CleanupStack::Pop( req ); + + LOGLIT( "CRoapEng::CreateRegistrationRequestL <-" ) + + return req; + } + +// --------------------------------------------------------- +// CRoapEng::CreateRightsRequestL() +// --------------------------------------------------------- +// +CRoapMessage* CRoapEng::CreateRightsRequestL() + { + LOGLIT( "CRoapEng::CreateRightsRequestL" ) + PERFORMANCE_LOGLIT( "RO acquisition protocol started" ) + + __ASSERT_ALWAYS( iStoredRiContext, User::Invariant() ); + + CRightsReq* req = NULL; + RPointerArray ttIDs; + RPointerArray cids; + HBufC8* temp = NULL; + TBuf8 deviceId; + + req = CRightsReq::NewL(); + CleanupStack::PushL( req ); + + req->iNonce.SetLength( KDeviceNonceLength ); + TRandom::Random( req->iNonce ); + + req->iTime = GetDrmTimeL(); + + iStorageClient->GetDevicePublicKeyHashL( deviceId ); + delete iDeviceId; + iDeviceId = NULL; + iDeviceId = deviceId.AllocL(); + req->iDeviceId = *iDeviceId; + + req->iRiId.Copy( iTrigger->iRiId ); + + if ( !iRiSupportsCertCaching ) + { + req->iCertificateChain = GetCertificateChainL(); + } + if ( iTrigger->iDomainId ) + { + req->iDomainId = iTrigger->iDomainId->AllocL(); + } + + for ( TInt i = 0; i < iTrigger->iRoIdList.Count(); i++ ) + { + temp = iTrigger->iRoIdList[i]->AllocLC(); + req->iRoIdList.AppendL( temp ); + CleanupStack::Pop( temp ); + } + + if ( iStoredRiContext ) + { + req->iPeerKeyIdentifier = iStoredRiContext->RIID(); + + if ( iStoredRiContext->OCSPResponse().Count() ) + { + req->iOcspInfoStored = ETrue; + req->iOcspResponderKeyId = GetOCSPResponderKeyHashL(); + } + } + + CleanupResetAndDestroyPushL( cids ); + + CleanupResetAndDestroyPushL( ttIDs ); + + FetchTransactionIDL( ttIDs, cids ); + + for ( TInt i = 0; i < ttIDs.Count() && i < cids.Count(); i++ ) + { + temp = ttIDs[i]->AllocLC(); + req->iTransTrackIDs.AppendL( temp ); + CleanupStack::Pop( temp ); + temp = cids[i]->AllocLC(); + req->iContentIDs.AppendL( temp ); + CleanupStack::Pop( temp ); + } + + CleanupStack::PopAndDestroy( &ttIDs ); + CleanupStack::PopAndDestroy( &cids ); + + if ( iTrigger->iNonce ) + { + req->iTriggerNonce = iTrigger->iNonce->AllocL(); + } + + CleanupStack::Pop( req ); + return req; + } + +// --------------------------------------------------------- +// CRoapEng::CreateJoinDomainRequestL() +// --------------------------------------------------------- +// +CRoapMessage* CRoapEng::CreateJoinDomainRequestL() + { + LOGLIT( "CRoapEng::CreateJoinDomainRequestL" ) + PERFORMANCE_LOGLIT( "Join domain protocol started" ) + + __ASSERT_ALWAYS( iStoredRiContext, User::Invariant() ); + + CJoinDomainReq* req = NULL; + TBuf8 deviceId; + + req = CJoinDomainReq::NewL(); + CleanupStack::PushL( req ); + + req->iNonce.SetLength( KDeviceNonceLength ); + TRandom::Random( req->iNonce ); + + req->iTime = GetDrmTimeL(); + + iStorageClient->GetDevicePublicKeyHashL( deviceId ); + delete iDeviceId; + iDeviceId = NULL; + iDeviceId = deviceId.AllocL(); + req->iDeviceId = *iDeviceId; + + req->iRiId.Copy( iTrigger->iRiId ); + + if ( !iRiSupportsCertCaching ) + { + req->iCertificateChain = GetCertificateChainL(); + } + if ( iTrigger->iDomainId ) + { + req->iDomainId = iTrigger->iDomainId->AllocL(); + iDomainId.Copy( *req->iDomainId ); + } + else if ( iDomainId.Length() && iTrigger->iTriggerType + == ERoAcquisitionTrigger ) + { + req->iDomainId = iDomainId.AllocL(); + } + else + { + User::Leave( KErrRoapServerFatal ); + } + + if ( iStoredRiContext ) + { + req->iPeerKeyIdentifier = iStoredRiContext->RIID(); + + if ( iStoredRiContext->OCSPResponse().Count() ) + { + req->iOcspInfoStored = ETrue; + req->iOcspResponderKeyId = GetOCSPResponderKeyHashL(); + } + } + +#ifdef _DISABLE_HASH_CHAIN_GENERATION + req->iHashChainSupport = EFalse; +#endif + + if ( iTrigger->iNonce ) + { + req->iTriggerNonce = iTrigger->iNonce->AllocL(); + } + + CleanupStack::Pop( req ); + return req; + } + +// --------------------------------------------------------- +// CRoapEng::CreateLeaveDomainRequestL() +// --------------------------------------------------------- +// +CRoapMessage* CRoapEng::CreateLeaveDomainRequestL() + { + LOGLIT( "CRoapEng::CreateLeaveDomainRequestL" ) + PERFORMANCE_LOGLIT( "Leave domain protocol started" ) + + __ASSERT_ALWAYS( iStoredRiContext, User::Invariant() ); + + if ( !iTrigger->iDomainId ) + { + User::Leave( KErrRoapServerFatal ); + } + // delete Domain context before sending LeaveDomain req + TRAPD( ret, iStorageClient->DeleteDomainContextL( *iTrigger->iDomainId )); + + CLeaveDomainReq* req = NULL; + TBuf8 deviceId; + + req = CLeaveDomainReq::NewL(); + CleanupStack::PushL( req ); + + if ( ret == KErrNotFound ) + { + req->iNotMember = ETrue; + } + else + { + req->iNotMember = EFalse; + User::LeaveIfError( ret ); + } + + req->iNonce.SetLength( KDeviceNonceLength ); + TRandom::Random( req->iNonce ); + + req->iTime = GetDrmTimeL(); + + iStorageClient->GetDevicePublicKeyHashL( deviceId ); + delete iDeviceId; + iDeviceId = NULL; + iDeviceId = deviceId.AllocL(); + req->iDeviceId = *iDeviceId; + + req->iRiId.Copy( iTrigger->iRiId ); + + if ( !iRiSupportsCertCaching ) + { + req->iCertificateChain = GetCertificateChainL(); + } + if ( iTrigger->iDomainId ) + { + req->iDomainId = iTrigger->iDomainId->AllocL(); + } + + if ( iTrigger->iNonce ) + { + req->iTriggerNonce = iTrigger->iNonce->AllocL(); + } + + CleanupStack::Pop( req ); + return req; + } +// --------------------------------------------------------- +// CRoapEng::CreateMeteringReportRequestL() +// --------------------------------------------------------- +// +CRoapMessage* CRoapEng::CreateMeteringReportRequestL() + { +#ifndef RD_DRM_METERING + return NULL; +#else + + LOGLIT( "CRoapEng::CreateMeteringReportRequestL" ) + PERFORMANCE_LOGLIT( "Metering report creation started" ) + + CMeteringReportReq* req = NULL; + TBuf8 deviceId; + TBuf8 macKey; + TBool registered( EFalse ); + + req = CMeteringReportReq::NewL(); + CleanupStack::PushL( req ); + req->iAlgorithmInUse = iSelectedAlgorithms; + // check if we are not using OMA algorithms + // and update selected algorithm accordingly + GetRIContextL( registered, iTrigger->iRiId ); + if ( registered && iStoredRiContext ) + { + for ( TInt i = 0; i < iStoredRiContext->Algorithms().Count(); i++ ) + { + if ( iStoredRiContext->Algorithms()[i]->CompareF( KCmlaIp1() ) + == KErrNone ) + { + // note currently assumed that only + // 1 of 7 ppossible algorithms used + req->iAlgorithmInUse = ECmlaIp1; + break; + } + } + } + + // generate DeviceNonce + req->iNonce.SetLength( KDeviceNonceLength ); + TRandom::Random( req->iNonce ); + + // generate MeteringNonce + req->iReportNonce.SetLength( KDeviceNonceLength ); + TRandom::Random( req->iReportNonce ); + + // fetch secure time for request + req->iTime = GetDrmTimeL(); + + // insert DeviceId + iStorageClient->GetDevicePublicKeyHashL( deviceId ); + delete iDeviceId; + iDeviceId = NULL; + iDeviceId = deviceId.AllocL(); + req->iDeviceId = *iDeviceId; + + // insert RiId + req->iRiId.Copy( iTrigger->iRiId ); + + // insert Certificate chain if needed + if ( !iRiSupportsCertCaching ) + { + req->iCertificateChain = GetCertificateChainL(); + } + + // add trigger Nonce + if ( iTrigger->iNonce ) + { + req->iTriggerNonce = iTrigger->iNonce->AllocL(); + } + + // Get from server encrypted metering report mac key as plain, + // MEK and MAC key as encypted, and hash of + // PKI public key used in encryition + req->iCipherValue = iStorageClient->GetMeteringDataL( req->iRiId, macKey, + req->iEncKeyHash, req->iEncryptedMekAndMak ); + + // calculate mac over + req->InsertMacL( macKey ); + + CleanupStack::Pop( req ); + return req; + +#endif //RD_DRM_METERING + } + +// --------------------------------------------------------- +// CRoapEng::HandleRoapResponseL() +// --------------------------------------------------------- +// +void CRoapEng::HandleRoapResponseL( const TDesC8& aXmlResponse ) + { + LOGLIT( "CRoapEng::HandleRoapMessageL" ) + + delete iResponse; + iResponse = NULL; + + switch ( iReqMessage ) + { + case EDeviceHello: + { + HandleRIHelloPduL( aXmlResponse ); + break; + } + case ERegistration: + { + HandleReqResponsePduL( aXmlResponse ); + break; + } + case EROAcquisition: + { + HandleRightsResponsePduL( aXmlResponse, EFalse ); + break; + } + case EJoinDomain: + { + HandleJoinDomainResponsePduL( aXmlResponse ); + break; + } + case ELeaveDomain: + { + HandleLeaveDomainResponsePduL( aXmlResponse ); + break; + } +#ifdef RD_DRM_METERING + case EMeteringRequest: + { + HandleMeteringReportResponsePduL( aXmlResponse ); + break; + } +#endif + default: + { + User::Leave( KErrArgument ); + } + } + } + +// --------------------------------------------------------- +// CRoapEng::HandleRIHelloPduL() +// --------------------------------------------------------- +// +void CRoapEng::HandleRIHelloPduL( const TDesC8& aRiHello ) + { + LOGLIT( "CRoapEng::HandleRIHelloPduL" ) + + CRIHello* resp = NULL; + HBufC8* temp = NULL; + + resp = iParser->ParseRIHelloL( aRiHello ); + iRoapStatus = resp->iStatus; + iResponse = resp; + if ( iRoapStatus == ESuccess ) + { + iCertNeeded = ETrue; + iRiSupportsCertCaching = EFalse; + + if ( resp->iPeerKeyIdentifier ) + { + iRiSupportsCertCaching = ETrue; + if ( resp->iPeerKeyId.Length() ) + { + if ( resp->iPeerKeyId.CompareF( *iDeviceId ) == KErrNone ) + { + iCertNeeded = EFalse; + } + } + else + { + iCertNeeded = EFalse; + } + } + else if ( resp->iCertificateCaching ) + { + iRiSupportsCertCaching = ETrue; + } + + if ( resp->iAlgorithms.Count() ) + { + iRiAlgorithms.ResetAndDestroy(); + for ( TInt i = 0; i < resp->iAlgorithms.Count(); i++ ) + { + if ( resp->iAlgorithms[i]->CompareF( KCmlaIp1() ) == KErrNone ) + { + iSelectedAlgorithms = ECmlaIp1; + } + temp = resp->iAlgorithms[i]->AllocLC(); + iRiAlgorithms.AppendL( temp ); + CleanupStack::Pop( temp ); + } + } + iRiId.Copy( resp->iRiId ); + iRiVersion.Copy( resp->iSelectedVersion ); + + /*** + This is needed when the multiple PKIs are supported. + ***/ + if ( resp->iTrustedAuthorities.Count() ) + { + // select the first matching root from the list + LOGLIT( "Choose the first matching trust anchor" ) + iStorageClient->SelectTrustedRootL( resp->iTrustedAuthorities, + iSelectedRoot ); + LOGLIT( "The trust anchor selected" ) + DETAILLOGHEX( iSelectedRoot.Ptr(), iSelectedRoot.Length() ) + } + else + { + if ( iStoredRiContext && iStoredRiContext->RIID() == iRiId ) + { + if ( iSelectedRoot != iStoredRiContext->SelectedDeviceRoot() ) + { + DETAILLOGLIT( "Changing trusted root to that of saved RI context" ) + DETAILLOGLIT( "old root" ) + DETAILLOGHEX( iSelectedRoot.Ptr(), iSelectedRoot.Length() ) + + iSelectedRoot = iStoredRiContext->SelectedDeviceRoot(); + iStorageClient->SelectTrustedRootL( iSelectedRoot ); + } + DETAILLOGLIT( "Using trusted root of saved RI context" ) + DETAILLOGHEX( iSelectedRoot.Ptr(), iSelectedRoot.Length() ) + } + else + { + DETAILLOGLIT( "Using default trusted root" ) + iSelectedRoot = KNullDesC8; + iStorageClient->SelectTrustedRootL( iSelectedRoot ); + } + } + + iSigner->AddRequestL( aRiHello ); + } + else if ( resp->iErrorUrl ) + { + if ( iObserver ) + { + iObserver->ErrorUrlL( *resp->iErrorUrl ); + } + } + } + +// --------------------------------------------------------- +// CRoapEng::HandleReqResponsePduL() +// --------------------------------------------------------- +// +void CRoapEng::HandleReqResponsePduL( const TDesC8& aRegResp ) + { + LOGLIT( "CRoapEng::HandleReqResponsePduL" ) + + CRegistrationResp* resp = NULL; + CDRMRIContext* context = NULL; + CX509Certificate* cert = NULL; + TTime riExpiry; + TBool status = EFalse; + TUint8 riCertCaching = EFalse; + + resp = iParser->ParseRegistrationRespL( aRegResp ); + iRoapStatus = resp->iStatus; + iResponse = resp; + if ( iRoapStatus == ESuccess ) + { + if ( resp->iOcspResponse.Count() > 0 ) + { + // adjust DRM Time according to OCSP response + // All needed verifications done in server side + TBool deviceTimeUpdated( EFalse ); + if ( resp->iCertificateChain.Count() > 0 ) + { + deviceTimeUpdated = iStorageClient->UpdateDrmTimeL( + resp->iCertificateChain, resp->iOcspResponse, + iRegReqNonce ); + } + else if ( iStoredRiContext ) + { + deviceTimeUpdated = iStorageClient->UpdateDrmTimeL( + iStoredRiContext->CertificateChain(), + resp->iOcspResponse, iRegReqNonce ); + } + if ( deviceTimeUpdated ) + { + LOGLIT( "drm time updated" ) + iDeviceTimeError = EFalse; + } + } + + if ( !iStoredRiContext || ( resp->iCertificateChain.Count() + && resp->iOcspResponse.Count() ) ) + { + status = VerifyCertificateChainL( resp->iCertificateChain, + resp->iOcspResponse ); + if ( !status ) + { + LOGLIT( "Certificate chain validation failed" ) + User::Leave( KErrRoapServerFatal ); + } + status = ValidateRiIdL( iRiId, *resp->iCertificateChain[0] ); + if ( !status ) + { + LOGLIT( "RI ID validation failed" ) + User::Leave( KErrRoapServerFatal ); + } + } + + if ( iStoredRiContext ) + { + // if we have already stored certificates -> use those. + status = VerifySignatureL( aRegResp, *resp->iSignature, + iStoredRiContext->CertificateChain() ); + } + else + { + // otherwise use the received certificates + status = VerifySignatureL( aRegResp, *resp->iSignature, + resp->iCertificateChain ); + } + + if ( !status ) + { + LOGLIT( "Signature verification failed" ) + User::Leave( KErrRoapServerFatal ); + } + + if ( resp->iCertificateChain.Count() ) + { + // Validate RI certificate + cert = CX509Certificate::NewLC( *resp->iCertificateChain[0] ); + + status = ValidateRiCertificateL( cert ); + if ( !status ) + { + User::LeaveIfError( KErrRoapServerFatal ); + } + + riExpiry = cert->ValidityPeriod().Finish(); + + iRiSupportsCertCaching ? riCertCaching = ETrue : riCertCaching + = EFalse; + + context = CDRMRIContext::NewLC( iRiId, *iRiAlias, iRiVersion, + iRiAlgorithms, resp->iWhiteList, *resp->iRiUrl, riExpiry, + resp->iCertificateChain, resp->iOcspResponse, riCertCaching, + iSelectedRoot, ETrue ); + + iStorageClient->AddRIContextL( *context ); + delete iStoredRiContext; + iStoredRiContext = context; + CleanupStack::Pop( context ); + CleanupStack::PopAndDestroy( cert ); + } + } + else + { + if ( resp->iErrorUrl ) + { + if ( iObserver ) + { + iObserver->ErrorUrlL( *resp->iErrorUrl ); + } + } + iSigner->ResetResponses(); + } + + PERFORMANCE_LOGLIT( "Registration protocol completed" ) + } + +// --------------------------------------------------------- +// CRoapEng::HandleRightsResponseL() +// --------------------------------------------------------- +// +void CRoapEng::HandleRightsResponsePduL( + const TDesC8& aRightsResp, + TBool aOnePass ) + { + LOGLIT( "CRoapEng::HandleRightsResponsePduL" ) + + CRightsResp* resp = NULL; + TBool status = EFalse; + + resp = iParser->ParseRightsRespL( aRightsResp ); + + CleanupStack::PushL( resp ); + + if ( resp->iStatus == ESuccess ) + { + if ( !aOnePass ) + { + // 2-pass protocol + __ASSERT_ALWAYS( iStoredRiContext, User::Invariant() ); + + CRightsReq* request = NULL; + request = STATIC_CAST( CRightsReq*, iRequest ); + if ( resp->iDeviceId.CompareF( request->iDeviceId ) != KErrNone + || resp->iRiId.CompareF( request->iRiId ) != KErrNone + || resp->iNonce->CompareF( request->iNonce ) != KErrNone ) + { + User::Leave( KErrRoapServerFatal ); + } + } + else + { + LOGLIT( "1-pass ROAP" ) + // 1-pass protocol + TBool registered = EFalse; + GetRIContextL( registered, resp->iRiId ); + if ( !registered ) + { + // Recoverable error by re-registering the device + // (after receiving user consent or iv device belongs to whiteliust) + LOGLIT( "Device not registered to RI" ) + User::Leave( KErrRoapNotRegistered ); + } + if ( resp->iDeviceId.CompareF( *iDeviceId ) != KErrNone ) + { + // Unrecoverable error + LOGLIT( "Device ID mismatch!" ) + User::Leave( KErrRoapServerFatal ); + } + } + + if ( !iStoredRiContext || ( resp->iCertificateChain.Count() + && resp->iOcspResponse.Count() ) ) + { + status = VerifyCertificateChainL( resp->iCertificateChain, + resp->iOcspResponse ); + if ( !status ) + { + LOGLIT( "Certificate chain validation failed" ) + User::Leave( KErrRoapServerFatal ); + } + status = ValidateRiIdL( resp->iRiId, *resp->iCertificateChain[0] ); + if ( !status ) + { + LOGLIT( "RI ID validation failed" ) + User::Leave( KErrRoapServerFatal ); + } + } + + status = VerifySignatureL( aRightsResp, *resp->iSignature, + iStoredRiContext->CertificateChain() ); + if ( !status ) + { + LOGLIT( "Signature verification failed" ) + User::Leave( KErrRoapServerFatal ); + } + + iReturnedROs.ResetAndDestroy(); + TRAPD( r, iRoParser->ParseAndStoreL( aRightsResp, iReturnedROs )); + + if ( r == KErrRightsServerDomainNotRegistered ) + { + // perform implicit Join Domain + LOGLIT( "Domain RO received - Not joined" ) + LOGLIT( "Perform impicit Join Domain before storing the RO" ) + + HBufC8* domainID = NULL; + + domainID = iRoParser->GetDomainIdL( aRightsResp ); + + if ( domainID && domainID->Length() <= KDomainIdLength ) + { + iDomainId.Copy( *domainID ); + delete domainID; + domainID = NULL; + } + else + { + LOGLIT( "No Domain ID available!" ) + User::Leave( KErrRoapServerFatal ); + } + + delete iDomainRightsResp; + iDomainRightsResp = NULL; + iDomainRightsResp = aRightsResp.AllocL(); + iImplicitJoinDomain = ETrue; + } + else + { + User::LeaveIfError( r ); + + if ( !aOnePass ) + { + if ( iObserver ) + { + iObserver->RightsObjectDetailsL( iReturnedROs ); // pass RO details to UI + } + } + } + + TRAP( r, InsertTransactionIDL( resp->iTransTrackIDs, resp->iContentIDs ) ); + TRAP( r, InsertDomainRosL() ); + + // Device DRM Time is insecure, but server thinks that the time is correct + // -> Set DRM Time as secure + if ( !iSecureTime ) + { + SetDrmTimeSecureL(); + } + } + else + { + if ( resp->iErrorUrl ) + { + if ( iObserver ) + { + iObserver->ErrorUrlL( *resp->iErrorUrl ); + } + } + iSigner->ResetResponses(); + } + + CleanupStack::Pop( resp ); + + if ( !aOnePass ) + { + iRoapStatus = resp->iStatus; + iResponse = resp; + } + + PERFORMANCE_LOGLIT( "RO acquisition protocol completed" ) + } + +// --------------------------------------------------------- +// CRoapEng::HandleJoinDomainResponseL() +// --------------------------------------------------------- +// +void CRoapEng::HandleJoinDomainResponsePduL( const TDesC8& aJoinResp ) + { + LOGLIT( "CRoapEng::HandleJoinDomainResponsePduL" ) + + __ASSERT_ALWAYS( iStoredRiContext, User::Invariant() ); + + CJoinDomainResp* resp = NULL; + CDRMDomainContext* context = NULL; + RPointerArray domainKeyElements; + TBool status = EFalse; + + CleanupResetAndDestroyPushL( domainKeyElements ); + + resp = iParser->ParseJoinDomainRespL( aJoinResp, domainKeyElements ); + + iResponse = resp; + iRoapStatus = resp->iStatus; + + if ( iRoapStatus == ESuccess ) + { + if ( resp->iDomainKeyRiId != resp->iRiId ) + { + LOGLIT( "resp->iDomainKeyRiId != resp->iRiId" ) + User::Leave( KErrRoapServerFatal ); + } + + if ( !iStoredRiContext || ( resp->iCertificateChain.Count() + && resp->iOcspResponse.Count() ) ) + { + status = VerifyCertificateChainL( resp->iCertificateChain, + resp->iOcspResponse ); + if ( !status ) + { + LOGLIT( "Certificate chain validation failed" ) + User::Leave( KErrRoapServerFatal ); + } + status = ValidateRiIdL( resp->iRiId, *resp->iCertificateChain[0] ); + if ( !status ) + { + LOGLIT( "RI ID validation failed" ) + User::Leave( KErrRoapServerFatal ); + } + } + + status = VerifySignatureL( aJoinResp, *resp->iSignature, + iStoredRiContext->CertificateChain() ); + if ( !status ) + { + LOGLIT( "Signature verification failed" ) + User::Leave( KErrRoapServerFatal ); + } + + if ( resp->iDomainKeys.Count() > 1 && resp->iDomainKeyIDs.Count() > 1 + && resp->iDomainKeys.Count() == resp->iDomainKeyIDs.Count() ) + { + // Sort domain keys by generation (000 generation is first) + TLex8 lex; + TInt generation = 0; + RArray generations; + CleanupClosePushL( generations ); + + for ( TInt i = 0; i < resp->iDomainKeyIDs.Count(); i++ ) + { + lex = resp->iDomainKeyIDs[i]->Right( KDomainGenerationLength ); + lex.Val( generation ); + generations.AppendL( generation ); + } + + SortArrays( resp->iDomainKeys, resp->iMacs, domainKeyElements, + generations ); + + CleanupStack::PopAndDestroy( &generations ); + } + + if ( !resp->iDomainKeys.Count() ) + { + LOGLIT( "No valid domain keys present!" ) + User::Leave( KErrRoapServerFatal ); + } + +#ifdef _DISABLE_HASH_CHAIN_GENERATION + resp->iHashChainSupport = EFalse; +#endif + + if ( resp->iHashChainSupport ) + { + if ( resp->iDomainKeys.Count() > 1 ) + { + LOGLIT( "More than one Domain key present, hash chain key generation is supported!" ) + // Might be KErrRoapServerFatal server error + } + } + + context = CDRMDomainContext::NewLC( iDomainId, + resp->iDomainExpiration, resp->iHashChainSupport, + resp->iDomainKeys, resp->iRiId, + iStoredRiContext->RightsIssuerURL() ); + iStorageClient->AddDomainContextL( *context, resp->iMacs, + domainKeyElements, resp->iTransportScheme ); + iDomainId.SetLength( 0 ); + CleanupStack::PopAndDestroy( context ); + + if ( iDomainRightsResp ) + { + // It's a implicit Join Domain case + // We still need to store the domain RO + StoreDomainRightsL(); + } + + // Device DRM Time is insecure, but server thinks that the time is correct + // -> Set DRM Time as secure + if ( !iSecureTime ) + { + SetDrmTimeSecureL(); + } + } + else + { + if ( resp->iErrorUrl ) + { + if ( iObserver ) + { + iObserver->ErrorUrlL( *resp->iErrorUrl ); + } + } + iSigner->ResetResponses(); + } + CleanupStack::PopAndDestroy( &domainKeyElements ); + } + +// --------------------------------------------------------- +// CRoapEng::HandleLeaveDomainResponseL() +// --------------------------------------------------------- +// +void CRoapEng::HandleLeaveDomainResponsePduL( const TDesC8& aLeaveResp ) + { + LOGLIT( "CRoapEng::HandleLeaveDomainResponsePduL" ) + + __ASSERT_ALWAYS( iStoredRiContext, User::Invariant() ); + + CLeaveDomainResp* resp = NULL; + resp = iParser->ParseLeaveDomainRespL( aLeaveResp ); + iRoapStatus = resp->iStatus; + iResponse = resp; + if ( iRoapStatus == ESuccess ) + { + + } + else if ( resp->iErrorUrl ) + { + if ( iObserver ) + { + iObserver->ErrorUrlL( *resp->iErrorUrl ); + } + } + + PERFORMANCE_LOGLIT( "Leave domain protocol completed" ) + } + +// --------------------------------------------------------- +// CRoapEng::HandleMeteringReportResponsePduL() +// --------------------------------------------------------- +// +#ifndef RD_DRM_METERING +void CRoapEng::HandleMeteringReportResponsePduL( const TDesC8& /*aMeteringResp*/) + { + } +#else +void CRoapEng::HandleMeteringReportResponsePduL( const TDesC8& aMeteringResp ) + { + LOGLIT( "CRoapEng::HandleMeteringReportResponsePduL" ) + __ASSERT_ALWAYS( iStoredRiContext, User::Invariant() ); + + CMeteringResp* resp = NULL; + CMeteringReportReq* request = NULL; + + resp = iParser->ParseMeteringRespL( aMeteringResp ); + + request = static_cast ( iRequest ); + + iRoapStatus = resp->iStatus; + iResponse = resp; + if ( iRoapStatus == ESuccess ) + { + if ( resp->iDeviceId.CompareF( *iDeviceId ) != KErrNone + || resp->iDeviceNonce->CompareF( request->iNonce ) != KErrNone ) + { + LOGLIT( "Mismatch in deviceId or in nonce" ) + LOGLIT( "Observed DeviceId" ) + LOGHEX( resp->iDeviceId.Ptr(), resp->iDeviceId.Length() ) + LOGLIT( "Expected DeviceId" ) + LOGHEX( request->iDeviceId.Ptr(), request->iDeviceId.Length() ) + LOGLIT( "Observed nonce" ) + LOGHEX( resp->iDeviceNonce->Ptr(), resp->iDeviceNonce->Length() ) + LOGLIT( "Expected nonce" ) + User::Leave( KErrRoapServerFatal ); + } + + if ( !iStoredRiContext || ( resp->iCertificateChain.Count() + && resp->iOcspResponse.Count() ) ) + { + if ( !VerifyCertificateChainL( resp->iCertificateChain, + resp->iOcspResponse ) ) + { + LOGLIT( "Certificate chain validation failed" ) + User::Leave( KErrRoapServerFatal ); + } + if ( !ValidateRiIdL( resp->iRiId, *resp->iCertificateChain[0] ) ) + { + LOGLIT( "RI ID validation failed" ) + User::Leave( KErrRoapServerFatal ); + } + } + + if ( !VerifySignatureL( aMeteringResp, *resp->iSignature, + iStoredRiContext->CertificateChain() ) ) + { + LOGLIT( "Signature verification failed" ) + User::Leave( KErrRoapServerFatal ); + } + + // Everything is fine, we can delete metering data + iStorageClient->DeleteMeteringDataL( resp->iRiId ); + + // notify PostResponseUrl for iObserver + if ( resp->iPrUrl ) + { + HBufC8* prUrl( resp->iPrUrl ); + LOGLIT( "PrUrl" ) + LOGHEX( prUrl->Ptr(), prUrl->Length() ) + if ( iObserver ) + { + iObserver->PostResponseUrlL( *prUrl ); + LOGLIT( "Notified observer with PostResponseUrl" ) + } + else + { + LOGLIT( "Warning no observer for PostResponseUrl" ) + } + } + } + return; + } +#endif //RD_DRM_METERING +// --------------------------------------------------------- +// CRoapEng::HandleMultipartL() +// --------------------------------------------------------- +// +void CRoapEng::HandleMultipartL() + { + LOGLIT( "CRoapEng::HandleMultipartL" ) + + TInt rightsErr( KErrNone ); + TInt err( KErrNone ); + TInt docErr( KErrNone ); + TDataType type = TDataType(); + TBool mmcAllowed( EFalse ); + HBufC* contentName( NULL ); + RBuf newPath; + TUid app_uid; + RBuf rootPath; + + TRAP( rightsErr, HandleRoapResponseL( iRoapResp->ProtocolUnit() ) ); + + newPath.CreateL( KMaxFileName ); + CleanupClosePushL( newPath ); + + CDocumentHandler* docHandler( CDocumentHandler::NewLC() ); + + if ( iRoapResp->DcfFileName().Left( 1 ).CompareF( _L ("e") ) == 0 ) + { + mmcAllowed = ETrue; + } + + RFs fs; + User::LeaveIfError( fs.Connect() ); + CleanupClosePushL( fs ); + +#ifndef RD_MULTIPLE_DRIVE + rootPath.CreateL( mmcAllowed ? + PathInfo::MemoryCardRootPath() : + PathInfo::PhoneMemoryRootPath() ); + +#else //RD_MULTIPLE_DRIVE + _LIT( KSysDriveRoot, "_:\\Data\\"); + _LIT( KMassDriveRoot, "_:\\" ); + TInt driveNumber( -1 ); + TChar driveLetter; + + if ( mmcAllowed ) + { + // Set root path to memory card root + rootPath.CreateL( KMassDriveRoot() ); + DriveInfo::GetDefaultDrive( DriveInfo::EDefaultMassStorage, driveNumber ); + } + else + { + // Set root path to system root + rootPath.CreateL( KSysDriveRoot() ); + DriveInfo::GetDefaultDrive( DriveInfo::EDefaultSystem, driveNumber ); + } + fs.DriveToChar( driveNumber, driveLetter ); + __ASSERT_ALWAYS( rootPath.Length()>0, User::Invariant() ); + rootPath[0] = (TUint)driveLetter; + + +#endif + CleanupClosePushL( rootPath ); + + iRoapResp->GetContentNameLC( contentName ); + + if ( contentName && contentName->Length() + && fs.IsValidName( *contentName ) ) + { + if ( !rightsErr ) + { + TRAP( err, docErr = docHandler->SilentMoveL( iRoapResp->DcfFileName(), + *contentName, rootPath, type, KEntryAttNormal ) ); + } + else + { + // when an error occured during RO storing -> show "saved to" note + TRAP( err, docErr = docHandler->MoveL( iRoapResp->DcfFileName(), + *contentName, type, KEntryAttNormal ) ); + } + + } + else + { + if ( !rightsErr ) + { + // use the default name + User::LeaveIfError( docHandler->SilentMoveL( + iRoapResp->DcfFileName(), KNullDesC(), rootPath, type, + KEntryAttNormal ) ); + } + else + { + // when an error occured during RO storing -> show "saved to" note + docHandler->MoveL( iRoapResp->DcfFileName(), KNullDesC(), type, + KEntryAttNormal ); + } + } + + if ( err || docErr ) + { + if ( !rightsErr ) + { + // use the default name + User::LeaveIfError( docHandler->SilentMoveL( + iRoapResp->DcfFileName(), KNullDesC(), rootPath, type, + KEntryAttNormal ) ); + } + else + { + // when an error occured during RO storing -> show "saved to" note + docHandler->MoveL( iRoapResp->DcfFileName(), KNullDesC(), type, + KEntryAttNormal ); + } + } + User::LeaveIfError( rightsErr ); + + User::LeaveIfError( docHandler->GetPath( newPath ) ); + User::LeaveIfError( docHandler->HandlerAppUid( app_uid ) ); + + if ( iObserver ) + { + iObserver->ContentDetailsL( newPath, type.Des8(), app_uid ); + } + + CleanupStack::PopAndDestroy( contentName ); + CleanupStack::PopAndDestroy( &rootPath ); + + CleanupStack::PopAndDestroy( &fs ); + CleanupStack::PopAndDestroy( docHandler ); + CleanupStack::PopAndDestroy( &newPath ); + } + +// --------------------------------------------------------- +// CRoapEng::SignMessageL() +// --------------------------------------------------------- +// +HBufC8* CRoapEng::SignMessageL( const TDesC8& aMessage ) const + { + LOGLIT( "CRoapEng::SignMessageL" ) + HBufC8* r = NULL; + + if ( iReqMessage == EDeviceHello ) + { + // Device Hello always resets signing chain!! + iSigner->ResetRequests(); + iSigner->ResetResponses(); + // Device Hello or RI Hello is not signed + iSigner->AddRequestL( aMessage ); + r = aMessage.AllocL(); + } + else + { + r = iSigner->SignAndAddRequestL( aMessage ); + iSigner->ResetRequests(); + + if ( iReqMessage == ERegistration ) + { + // Add signed request to the signer for verifying signature on + // response (for Registration protocol only). + iSigner->AddResponseL( *r ); + } + } + return r; + } + +// --------------------------------------------------------- +// CRoapEng::VerifySignatureL() +// --------------------------------------------------------- +// +TBool CRoapEng::VerifySignatureL( + const TDesC8& aMessage, + const TDesC8& aSignature, + const RPointerArray& aCertificateChain ) const + { + LOGLIT( "CRoapEng::VerifySignatureL" ) + + TBool isValid = ETrue; + + if ( iReqMessage != EDeviceHello && iReqMessage != ELeaveDomain ) + { + // RI Hello and Leave Domain resp are not signed + isValid = iSigner->VerifyAndAddResponseL( aMessage, aSignature, + aCertificateChain ); + iSigner->ResetResponses(); + } + +#ifdef _DISABLE_SIGNATURE_CHECK + isValid = ETrue; +#endif + return isValid; + } + +// --------------------------------------------------------- +// CRoapEng::VerifyTriggerSignatureL() +// --------------------------------------------------------- +// +TBool CRoapEng::VerifyTriggerSignatureL( + const TDesC8& aXmlTrigger, + const CRoapTrigger& aTrigger ) const + { + LOGLIT( "CRoapEng::ValidateTriggerSignatureL" ) + + TPtrC8 element( KNullDesC8 ); + TPtrC8 signedInfo( KNullDesC8 ); + CDRMDomainContext* context( NULL ); + HBufC8* domainKey( NULL ); + HBufC8* unwrappedMacKey( NULL ); + CSHA1* digest( NULL ); + CMessageDigest* hMac( NULL ); + TBool result( ETrue ); + TInt pos( 0 ); + TInt generation( 0 ); + + element.Set( iParser->ExtractElement( aXmlTrigger, KLeaveDomainElement(), + pos ) ); + pos = 0; + signedInfo.Set( iParser->ExtractElement( aXmlTrigger, + KSignedInfoElement(), pos ) ); + + if ( !element.Length() || !signedInfo.Length() || !aTrigger.iEncKey + || !aTrigger.iSignature ) + { + User::Leave( KErrRoapServerFatal ); + } + + context = iStorageClient->GetDomainContextL( *aTrigger.iDomainId ); + + if ( !context ) + { + // we are not member of the domain + LOGLIT( "No DomainContext for the domain -> Cannot verify Trigger signature" ) + return ETrue; + } + CleanupStack::PushL( context ); + + TLex8 lex( aTrigger.iDomainId->Right( KDomainGenerationLength ) ); + lex.Val( generation ); + domainKey = context->DomainKeyL( generation ); + User::LeaveIfNull( domainKey ); + CleanupStack::PushL( domainKey ); + + unwrappedMacKey = OmaCrypto::AesUnwrapL( *domainKey, *aTrigger.iEncKey ); + CleanupStack::PopAndDestroy( domainKey ); + CleanupStack::PushL( unwrappedMacKey ); + + // hash the leaveDomain element + digest = CSHA1::NewL(); + CleanupStack::PushL( digest ); + digest->Update( element ); + + if ( digest->Final().CompareF( *aTrigger.iDigestValue ) ) + { + LOGLIT( "Reference Validation failed!" ) + result = EFalse; + } + + if ( result ) + { + // calculate HMAC signature + hMac = CMessageDigestFactory::NewHMACLC( CMessageDigest::ESHA1, + *unwrappedMacKey ); + hMac->Update( signedInfo ); + + if ( hMac->Final().CompareF( *aTrigger.iSignature ) != 0 ) + { + LOGLIT( "Signature Validation failed!" ) + result = EFalse; + } + CleanupStack::PopAndDestroy( hMac ); + } + + CleanupStack::PopAndDestroy( digest ); + CleanupStack::PopAndDestroy( unwrappedMacKey ); + CleanupStack::PopAndDestroy( context ); + + if ( !result ) + { + LOGLIT( "Trigger signature check failed!" ) + } + +#ifdef _DISABLE_SIGNATURE_CHECK + result = ETrue; +#endif + return result; + } + +// --------------------------------------------------------- +// CRoapEng::VerifyCertificateChainL() +// --------------------------------------------------------- +// +TBool CRoapEng::VerifyCertificateChainL( + const RPointerArray& aCertificateChain, + const RPointerArray& aOcspResponses ) const + { + LOGLIT( "CRoapEng::VerifyCertificateChainL" ) + + CX509Certificate* cert = NULL; + CX509Certificate* signingCert = NULL; + CX509Certificate* riCA = NULL; + TBool result = EFalse; + RPointerArray serialNums; + CX500DistinguishedName* rootDistName = NULL; + HBufC* rootName = NULL; + HBufC8* rootCert = NULL; + HBufC8* temp = NULL; + + if ( !aCertificateChain.Count() || !aOcspResponses.Count() ) + { + User::Leave( KErrRoapServerFatal ); + } + + // Get the last cert from the chain. It is signed by some of our trusted anchor + riCA = CX509Certificate::NewLC( + *( aCertificateChain[aCertificateChain.Count() - 1] ) ); + rootDistName = CX500DistinguishedName::NewLC( riCA->IssuerName() ); + rootName = rootDistName->DisplayNameL(); + CleanupStack::PushL( rootName ); + // Get the correct root cert for validating the whole chain + rootCert = iStorageClient->GetRootCertificateL( *rootName ); + CleanupStack::PopAndDestroy( rootName ); + CleanupStack::PopAndDestroy( rootDistName ); + CleanupStack::PopAndDestroy( riCA ); + + if ( !rootCert ) + { + LOGLIT( "No root certificate present!" ) + LOGLIT( "Certificate chain verification failed." ) + return EFalse; + } + CleanupStack::PushL( rootCert ); + + CleanupResetAndDestroyPushL( serialNums ); + + for ( TInt i = 0; i < aCertificateChain.Count(); i++ ) + { + cert = CX509Certificate::NewLC( *aCertificateChain[i] ); + temp = cert->SerialNumber().AllocLC(); + serialNums.AppendL( temp ); + CleanupStack::Pop( temp ); + if ( aCertificateChain.Count() - 1 == i ) + { + // signingCert = Trusted root cert + signingCert = CX509Certificate::NewLC( *rootCert ); + } + else + { + signingCert = CX509Certificate::NewLC( *aCertificateChain[i + 1] ); + } + result = cert->VerifySignatureL( signingCert->PublicKey().KeyData() ); + +#ifdef _DISABLE_CERT_CHECK + result = ETrue; +#endif + CleanupStack::PopAndDestroy( signingCert ); + CleanupStack::PopAndDestroy( cert ); + if ( !result ) + { + LOGLIT( "Certificate chain verification failed." ) + CleanupStack::PopAndDestroy( 2, rootCert ); + return result; + } + } + + if ( aCertificateChain.Count() >= 2 ) + { + result = VerifyOcspResponsesL( aOcspResponses, *aCertificateChain[1], + serialNums ); + + if ( !result ) + { + // CoreMedia's OCSP responder cert is signed by the root -> against CMLA spec + LOGLIT( "Try to verify OCSP response cert using root cert" ) + result = VerifyOcspResponsesL( aOcspResponses, *rootCert, + serialNums ); + } + } + else if ( aCertificateChain.Count() == 1 ) + { + // There is only one cert in the cert chain -> the OCSP response cert is verified with root cert + result = VerifyOcspResponsesL( aOcspResponses, *rootCert, serialNums ); + } + else + { + result = EFalse; + } + + if ( iStoredRiContext && aCertificateChain.Count() && result ) + { + cert = CX509Certificate::NewLC( *aCertificateChain[0] ); + if ( iStoredRiContext->ExpiryTime() < cert->ValidityPeriod().Finish() ) + { + iStoredRiContext->SetCertificateChainL( aCertificateChain ); + iStoredRiContext->SetOCSPResponseL( aOcspResponses ); + + // update RI Context + iStorageClient->AddRIContextL( *iStoredRiContext ); + } + CleanupStack::PopAndDestroy( cert ); + } + + CleanupStack::PopAndDestroy( 2, rootCert ); // serialNums, rootCert + +#ifdef _ROAP_TESTING + if ( result ) + { + LOGLIT( "Certificate chain verification ok." ) + } + else + { + LOGLIT( "Certificate chain verification failed." ) + } +#endif +#ifdef _DISABLE_CERT_CHECK + result = ETrue; +#endif + + return result; + } + +// --------------------------------------------------------- +// CRoapEng::VerifyOcspResponsesL() +// --------------------------------------------------------- +// +TBool CRoapEng::VerifyOcspResponsesL( + const RPointerArray& aOcspResponses, + const TDesC8& aRiCaCert, + const RPointerArray& aCertSerialNums ) const + { + LOGLIT( "CRoapEng::VerifyOcspResponsesL" ) + +#ifdef _DISABLE_OCSP_CHECK + TBool result( ETrue ); +#else + // Get verification result from the server + TBool result( iStorageClient->VerifyOcspResponsesL( aOcspResponses, + aRiCaCert, aCertSerialNums ) ); +#endif + +#ifdef _ROAP_TESTING + if ( result ) + { + LOGLIT( "OCSP response verification ok." ) + } + else + { + LOGLIT( "OCSP response verification failed." ) + } +#endif + + return result; + } + +// --------------------------------------------------------- +// CRoapEng::ValidateRiCertificateL() +// --------------------------------------------------------- +// +TBool CRoapEng::ValidateRiCertificateL( const CX509Certificate* aCert ) + { + LOGLIT( "CRoapEng::ValidateRiCertificateL" ) + + TBool ret = ETrue; + const CX509CertExtension* ext = NULL; + CX509KeyUsageExt* keyUsageExt = NULL; + CX509ExtendedKeyUsageExt* extendedKeyUsage = NULL; + TTime riExpiry; + TInt count = 0; + + if ( iSelectedAlgorithms == ECmlaIp1 ) + { + // Check RI certificate extensions only in CMLA case + ext = aCert->Extension( KKeyUsage() ); + if ( !ext || !( ext->Critical() ) ) + { + LOGLIT( "RI cert KeyUsage extension missing or not critical!" ) + ret = EFalse; + } + + if ( ext && ret ) + { + keyUsageExt = CX509KeyUsageExt::NewLC( ext->Data() ); + if ( !keyUsageExt->IsSet( EX509DigitalSignature ) ) + { + LOGLIT( "DigitalSignature bit is not set in KeyUsageExt of RI cert!" ) + ret = EFalse; + } + CleanupStack::PopAndDestroy( keyUsageExt ); + } + + ext = aCert->Extension( KExtendedKeyUsage() ); + if ( !ext || !( ext->Critical() ) ) + { + LOGLIT( "RI cert ExtendedKeyUsage extension missing or not critical!" ) + ret = EFalse; + } + + if ( ext && ret ) + { + ret = EFalse; + extendedKeyUsage = CX509ExtendedKeyUsageExt::NewLC( ext->Data() ); + count = extendedKeyUsage->KeyUsages().Count(); + for ( TInt i = 0; i < count && !ret; i++ ) + { + if ( extendedKeyUsage->KeyUsages().At( i )->CompareF( + KOmaKpRightsIssuerOid() ) == 0 ) + { + ret = ETrue; + } + } + if ( !ret ) + { + LOGLIT( "OmaKpRightsIssuer OID is not set in ExtendedKeyUsageExt of RI cert!" ) + } + CleanupStack::PopAndDestroy( extendedKeyUsage ); + } + } + + riExpiry = aCert->ValidityPeriod().Finish(); + + if ( riExpiry < GetDrmTimeL() ) + { + LOGLIT( "RI Context certificate is expired!" ) + ret = EFalse; + } +#ifdef _DISABLE_CERT_CHECK + ret = ETrue; +#endif + return ret; + } + +// --------------------------------------------------------- +// CRoapEng::GetCertificateChainL() +// --------------------------------------------------------- +// +RPointerArray CRoapEng::GetCertificateChainL() const + { + LOGLIT( "CRoapEng::GetCertificateChainL ->" ) + + TInt err = KErrNone; + RPointerArray certificateChain; + HBufC8* root = NULL; + + CleanupResetAndDestroyPushL( certificateChain ); + + err = iStorageClient->GetDeviceCertificateChainL( certificateChain ); + + if ( err ) + { + User::Leave( err ); + } + + if ( certificateChain.Count() < KMinCertChainLength ) + { + // the CMLA chain must always contain: + // the device certificate, + // at lest one signing certificate (device CA), + // and the root certificate + DETAILLOGLIT( "Got improper certificate chain!!" ) + // Leaving in production devices. + User::Leave( KErrRoapDevice ); + __ASSERT_DEBUG( ETrue, User::Invariant() ); + } + + // delete and remove the root certificate (it's always the last one in the list) + root = certificateChain[certificateChain.Count() - 1]; + delete root; + certificateChain.Remove( certificateChain.Count() - 1 ); + + CleanupStack::Pop( &certificateChain ); + + LOGLIT( "CRoapEng::GetCertificateChainL <-" ) + + return certificateChain; + } + +// --------------------------------------------------------- +// CRoapEng::GetDeviceDetailsL() +// --------------------------------------------------------- +// +void CRoapEng::GetDeviceDetailsL( + HBufC8*& aManufacturer, + HBufC8*& aModel, + HBufC8*& aVersion ) + { + LOGLIT( "-> CRoapEng::GetDeviceDetailsL" ) + +#ifndef __WINS__ + TInt numPhone = 0; + TUint32 caps = 0; + TName tsyName; + RMobilePhone phone; + RTelServer etelServer; + RTelServer::TPhoneInfo phoneInfo; + HBufC* version = NULL; + + User::LeaveIfError( etelServer.Connect() ); + + CleanupClosePushL( etelServer ); + + User::LeaveIfError( etelServer.LoadPhoneModule( KMmTsyModuleName ) ); + User::LeaveIfError( etelServer.EnumeratePhones( numPhone) ); + + for (TInt i(0); i < numPhone; i++) + { + User::LeaveIfError( etelServer.GetPhoneInfo( i, phoneInfo ) ); + User::LeaveIfError( etelServer.GetTsyName( i,tsyName ) ); + + if ( tsyName.CompareF( KMmTsyModuleName ) == 0) + { + break; + } + } + + User::LeaveIfError( phone.Open( etelServer, phoneInfo.iName ) ); + CleanupClosePushL( phone ); + + phone.GetIdentityCaps( caps ); + if ( !( caps & RMobilePhone::KCapsGetManufacturer ) && + !( caps & RMobilePhone::KCapsGetModel ) ) + { + User::Leave( KErrRoapGeneral ); + } + + RMobilePhone::TMobilePhoneIdentityV1 details; + TRequestStatus status; + + phone.GetPhoneId( status, details ); + User::WaitForRequest( status ); + + User::LeaveIfError( status.Int() ); + + HBufC8* manufacturer( HBufC8::NewLC( details.iManufacturer.Length() ) ); + manufacturer->Des().Copy( details.iManufacturer ); + HBufC8* model( HBufC8::NewLC( details.iModel.Length() ) ); + model->Des().Copy( details.iModel ); + + version = HBufC::NewLC( KSysUtilVersionTextLength ); + TPtr ptr( version->Des() ); + User::LeaveIfError( SysUtil::GetSWVersion( ptr ) ); + + // remove possible BOM from the end + if ( ptr.Right( KBOM1().Length() ).CompareF( KBOM1 ) == KErrNone ) + { + ptr.Delete( ptr.Length() - KBOM1().Length(), KBOM1().Length() ); + } + if ( ptr.Right( KBOM2().Length() ).CompareF( KBOM2 ) == KErrNone ) + { + ptr.Delete( ptr.Length() - KBOM2().Length(), KBOM2().Length() ); + } + + aVersion = CnvUtfConverter::ConvertFromUnicodeToUtf8L( ptr ); + + CleanupStack::PopAndDestroy( version ); + CleanupStack::Pop( model ); + CleanupStack::Pop( manufacturer ); + aManufacturer = manufacturer; + aModel = model; + CleanupStack::PopAndDestroy( &phone ); + CleanupStack::PopAndDestroy( &etelServer ); +#else + aManufacturer = _L8("Nokia").AllocL(); + aModel = _L8("Emulator").AllocL(); + aVersion = _L8("9.0").AllocL(); +#endif + + LOGLIT( "Device details:" ) + LOGLIT( " Manufacturer: " ) + LOG( aManufacturer->Des() ) + LOGLIT( " Model: " ) + LOG( aModel->Des() ) + LOGLIT( " Revision: " ) + LOG( aVersion->Des() ) + + LOGLIT( "<- CRoapEng::GetDeviceDetailsL" ) + } + +// --------------------------------------------------------- +// CRoapEng::FetchTransactionIDL() +// --------------------------------------------------------- +// +void CRoapEng::FetchTransactionIDL( + RPointerArray& aTransIDs, + RPointerArray& aContentIDs ) + { + LOGLIT( "CRoapEng::FetchTransactionIDL" ) + + __ASSERT_ALWAYS( iTrigger, User::Invariant() ); + + RArray array; + TInt err = KErrNone; + + CleanupClosePushL( array ); + + if ( !iTrigger->iContentIdList.Count() ) + { + CleanupStack::PopAndDestroy( &array ); + return; + } + + if ( iTransStatus == ENotAsked && iObserver ) + { + UpdateTransactionTrackingStatusL(); + } + if ( iTransStatus == EAllowed ) + { + for ( TInt i = 0; i < iTrigger->iContentIdList.Count(); i++ ) + { + TPair pair; + pair.iCid = iTrigger->iContentIdList[i]->Alloc(); // duplicate contentID, + pair.iTtid = NULL; // pair.iCid is deleted by iRequest + err = array.Append( pair ); + if ( err ) + { + delete pair.iCid; + pair.iCid = NULL; + } + } + + TRAP_IGNORE(iDcfRep->GetTtidL( array ) ); + + for ( TInt i = 0; i < array.Count(); i++ ) + { + if ( array[i].iTtid && array[i].iCid && array[i].iTtid->Length() + && array[i].iCid->Length() ) + { + err = aContentIDs.Append( array[i].iCid ); + if ( !err ) + { + aTransIDs.Append( array[i].iTtid ); + } + else + { + delete array[i].iCid; + array[i].iCid = NULL; + delete array[i].iTtid; + array[i].iTtid = NULL; + } + } + else if ( array[i].iTtid || array[i].iCid ) + { + delete array[i].iTtid; + array[i].iTtid = NULL; + delete array[i].iCid; + array[i].iCid = NULL; + } + } + } + CleanupStack::PopAndDestroy( &array ); + } + +// --------------------------------------------------------- +// CRoapEng::InsertTransactionIDL() +// --------------------------------------------------------- +// +void CRoapEng::InsertTransactionIDL( + RPointerArray& aTransIDs, + RPointerArray& aContentIDs ) + { + LOGLIT( "CRoapEng::InsertTransactionIDL" ) + + RArray array; + TRequestStatus status; + + CleanupClosePushL( array ); + + if ( !aTransIDs.Count() || !aContentIDs.Count() ) + { + LOGLIT( "Insert ttID: Wrong input data" ) + CleanupStack::PopAndDestroy( &array ); + return; + } + + if ( aTransIDs.Count() != aContentIDs.Count() ) + { + LOGLIT( "Insert ttID: ttID.Count != cid.Count" ) + CleanupStack::PopAndDestroy( &array ); + return; + } + + if ( iTransStatus == ENotAsked && iObserver ) + { + UpdateTransactionTrackingStatusL(); + } + if ( iTransStatus == EAllowed ) + { + for ( TInt i = 0; i < aContentIDs.Count() && i < aTransIDs.Count(); i++ ) + { + TPair pair; + pair.iCid = aContentIDs[i]; + pair.iTtid = aTransIDs[i]; + array.Append( pair ); + } + + iDcfRep->SetTtid( array, status ); + User::WaitForRequest( status ); + } + + CleanupStack::PopAndDestroy( &array ); + } + +// --------------------------------------------------------- +// CRoapEng::GetOCSPResponderKeyHashL() +// --------------------------------------------------------- +// +HBufC8* CRoapEng::GetOCSPResponderKeyHashL() const + { + LOGLIT( "CRoapEng::GetOCSPResponderKeyHashL" ) + + if ( !iStoredRiContext ) + { + User::Leave( KErrRoapNotRegistered ); + } + return iStorageClient->GetOcspResponderIdL( iStoredRiContext->RIID() ); + } + +// --------------------------------------------------------- +// CRoapEng::GetDrmTimeL() +// --------------------------------------------------------- +// +TTime CRoapEng::GetDrmTimeL() + { + LOGLIT( "CRoapEng::GetDrmTimeL" ) + + TTime drmTime; + DRMClock::ESecurityLevel secureTime; + TInt zone( 0 ); + + User::LeaveIfError( iClockClient->GetSecureTime( drmTime, zone, + secureTime ) ); + + if ( secureTime == DRMClock::KInsecure ) + { + iSecureTime = EFalse; + } + else + { + iSecureTime = ETrue; + } + + return drmTime; + } + +// --------------------------------------------------------- +// CRoapEng::SetDrmTimeSecureL() +// --------------------------------------------------------- +// +void CRoapEng::SetDrmTimeSecureL() + { + LOGLIT( "CRoapEng::SetDrmTimeSecureL" ) + + TTime drmTime; + DRMClock::ESecurityLevel secureTime; + TInt zone( 0 ); + + User::LeaveIfError( iClockClient->GetSecureTime( drmTime, zone, + secureTime ) ); + User::LeaveIfError( iClockClient->UpdateSecureTime( drmTime, zone ) ); + + iSecureTime = ETrue; + } + +// --------------------------------------------------------- +// CRoapEng::AdjustDrmTime() +// --------------------------------------------------------- +// +void CRoapEng::AdjustDrmTimeL( + const RPointerArray& aOcspResponses, + TDesC8& aRegReqNonce ) const + { + // To be removed on next API change. + // Replace calls with direct call to RRoapStorageClient. + LOGLIT( "CRoapEng::AdjustDrmTime calling server" ) + if ( aOcspResponses.Count() > 0 ) + { + iStorageClient->UpdateDrmTimeL( iStoredRiContext->CertificateChain(), + aOcspResponses, aRegReqNonce ); + } + else + { + LOGLIT( "No OCSP responses present." ) + } + } + +// --------------------------------------------------------- +// CRoapEng::StoreDomainRightsL() +// --------------------------------------------------------- +// +void CRoapEng::StoreDomainRightsL() + { + LOGLIT( "CRoapEng::StoreDomainRightsL" ) + + RPointerArray returnedROs; + + CleanupResetAndDestroyPushL( returnedROs ); + + iRoParser->ParseAndStoreL( *iDomainRightsResp, returnedROs ); + + if ( iObserver ) + { + iObserver->RightsObjectDetailsL( returnedROs ); // pass RO details to UI + } + + delete iDomainRightsResp; + iDomainRightsResp = NULL; + + iImplicitJoinDomain = EFalse; + + CleanupStack::PopAndDestroy( &returnedROs ); + } + +// --------------------------------------------------------- +// CRoapEng::InsertDomainRosL() +// --------------------------------------------------------- +// +void CRoapEng::InsertDomainRosL() + { + CDcfRep* rep = NULL; + CDcfEntry* entry = NULL; + CContent* content = NULL; + TPtr8 ptr( NULL, 0 ); + TInt i; + RFile file; + RFs fs; + TInt error( 0 ); + + User::LeaveIfError( fs.Connect() ); + CleanupClosePushL( fs ); + rep = CDcfRep::NewL(); + CleanupStack::PushL( rep ); + for ( i = 0; i < iReturnedROs.Count(); i++ ) + { + if ( iReturnedROs[i]->GetPermission().iDomainID ) + { + rep->OrderListL( *iReturnedROs[i]->GetAsset().iUid ); + entry = rep->NextL(); + while ( entry ) + { + CleanupStack::PushL( entry ); + error = file.Open( fs, entry->FileName(), EFileWrite + | EFileShareReadersOrWriters ); + if ( !error ) + { + CleanupClosePushL( file ); + content = CContent::NewLC( file ); + content->AgentSpecificCommand( EEmbedDomainRo, + KNullDesC8, ptr ); + CleanupStack::PopAndDestroy( 2, &file ); // content, file + } + CleanupStack::PopAndDestroy( entry ); + entry = rep->NextL(); + } + } + } + CleanupStack::PopAndDestroy( 2, &fs ); // rep, fs + } + +// --------------------------------------------------------- +// CRoapEng::MapStatusL() +// --------------------------------------------------------- +// +TInt CRoapEng::MapStatusL() + { + LOGLIT( "CRoapEng::MapStatusL" ) + + if ( iRoapStatus == ESuccess ) + { + LOGLIT( "ROAP Status: success " ) + return KErrNone; + } + + if ( iRoapStatus == ENotRegistered || iRoapStatus == EDeviceTimeError ) + { + // Initiate registration protocol + LOG2( _L ( "Not Registered! Status: %d" ), iRoapStatus ) + + if ( iRoapStatus == EDeviceTimeError ) + { + iDeviceTimeError = ETrue; + } + + return KErrRoapNotRegistered; + } + + LOG2( _L ( "ROAP Error! Status: %d" ), iRoapStatus ) + + switch ( iRoapStatus ) + { + case EUnknownError: + case EAbort: + { + User::Leave( KErrRoapServer ); + } + case ENotSupported: + case EAccessDenied: + case ENotFound: + case EMalformedRequest: + case EUnknownRequest: + case EUnknownCriticalExtension: + case EUnsupportedVersion: + case EUnsupportedAlgorithm: + case ESignatureError: + case EInvalidDCFHash: + { + User::Leave( KErrRoapServerFatal ); + } + case ENoCertificateChain: + case EInvalidCertificateChain: + case ETrustedRootCertificateNotPresent: + { + User::Leave( KErrRoapDevice ); + } + case EInvalidDomain: + { + User::Leave( KErrRoapInvalidDomain ); + } + case EDomainFull: + { + User::Leave( KErrRoapDomainFull ); + } + default: + { + User::Leave( KErrRoapUnsupported ); + } + } + return KErrNone; + } + +// --------------------------------------------------------- +// CRoapEng::ValidateRiIdL() +// +// Validates that RI ID equals to public key hash of RI certificate +// --------------------------------------------------------- +// +TBool CRoapEng::ValidateRiIdL( TDesC8& aRiId, TDesC8& aCertBuf ) + { + TBool valid = EFalse; + CX509Certificate* riCert = NULL; + CSHA1* hash = NULL; + HBufC8* publicKeyHash = NULL; + + riCert = CX509Certificate::NewLC( aCertBuf ); + + // hash the SubjectPublicKeyInfo element + hash = CSHA1::NewL(); + CleanupStack::PushL( hash ); + hash->Hash( *riCert->DataElementEncoding( + CX509Certificate::ESubjectPublicKeyInfo ) ); + publicKeyHash = hash->Final().AllocLC(); + + if ( aRiId.Compare( *publicKeyHash ) == KErrNone ) + { + valid = ETrue; + } + + CleanupStack::PopAndDestroy( publicKeyHash ); + CleanupStack::PopAndDestroy( hash ); + CleanupStack::PopAndDestroy( riCert ); + + return valid; + } + +// --------------------------------------------------------- +// CRoapEng::UpdateTransactionTrackingStatusL() +// +// Update the status of transaction tracking variable +// --------------------------------------------------------- +// +void CRoapEng::UpdateTransactionTrackingStatusL() + { + TInt value = KErrNone; + CRepository* repository = CRepository::NewL( KCRUidDRMSettings ); + repository->Get( KDRMSettingsTransactionTracking, value ); + delete repository; + iTransStatus = value ? EAllowed : EForbidden; + } + +// --------------------------------------------------------- +// CRoapEng::CreateDeviceIdHashArrayL() +// --------------------------------------------------------- +// +TInt CRoapEng::CreateDeviceIdHashArrayL( RPointerArray& aIdArray ) + { + TInt err( KErrNone ); + RPointerArray certChain; + CSHA1* hasher = NULL; + HBufC8* publicKey = NULL; + CX509Certificate* cert = NULL; + + err = iStorageClient->GetDeviceCertificateChainL( certChain ); + + CleanupResetAndDestroyPushL( certChain ); + + hasher = CSHA1::NewL(); + CleanupStack::PushL( hasher ); + // take the hash of device certificate + if (certChain.Count()<=0) + { + LOGLIT( "Could get Device id Hash!!!" ) + User::Leave( KErrGeneral ); + } + cert = CX509Certificate::NewL( *certChain[0] ); + CleanupStack::PushL( cert ); + publicKey = cert->DataElementEncoding( + CX509Certificate::ESubjectPublicKeyInfo )->AllocLC(); + + hasher->Hash( *publicKey ); + + HBufC8 *elem( hasher->Final().AllocLC() ); + aIdArray.AppendL( elem ); + CleanupStack::Pop( elem ); + + CleanupStack::PopAndDestroy( publicKey ); + CleanupStack::PopAndDestroy( cert ); + + CleanupStack::PopAndDestroy( hasher ); + CleanupStack::PopAndDestroy( &certChain ); + return err; + } + +// End of file diff -r e9fb2728ea8b -r ca165d35976d group/bld.inf --- a/group/bld.inf Tue Oct 19 14:23:00 2010 +0100 +++ b/group/bld.inf Wed Oct 27 13:24:02 2010 +0100 @@ -40,3 +40,8 @@ // Rebuild the "original" TimeZone localisation resources as they're eclipsed by something else in the PDK /sf/mw/appsupport/tzservices/tzlocrscfactory/group/TzLocalizationRscFactory.mmp +// based on /sf/mw/drm +../breakdeps/DRMEngine/ROAPHandler.mmp +../breakdeps/DRMEngine/RightsServer.mmp +../breakdeps/DRMEngine/DrmStdKeyStorage.mmp +