--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/wmdrm/wmdrmengine/wmdrmserver/server/src/clock.cpp Thu Dec 17 08:52:27 2009 +0200
@@ -0,0 +1,452 @@
+/*
+* Copyright (c) 2007-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: WMDRM Server implementation
+*
+*/
+
+
+#include <ezlib.h>
+#include <e32math.h>
+#include <symmetric.h>
+#include <bacntf.h>
+
+#include "wmdrmkeystorage.h"
+#include "slotdatacache.h"
+#include "clock.h"
+#include "wmdrmserver.h"
+#include "drmserviceapiwrapper.h"
+#include "drmrightsstoringlocation.h"
+#include "drmutilityinternaltypes.h"
+
+#define _LOGGING_FILE L"wmdrmserver.txt"
+
+#include "flogger.h"
+#include "logfn.h"
+
+
+// Constants
+
+#if defined(FF_PLATFORM_SIMULATOR) || defined(__WINSCW__)
+_LIT8( KDummyKey, "0123456789012345" );
+#endif
+
+_LIT(KDrmServiceApiWrapperName, "drmserviceapiwrapper.dll");
+static const TInt KDrmServiceApiWrapperGateOrdinal = 1;
+
+//---------------------------------------------------------------------------
+// CClock::NewL
+// Second phase constructor
+//---------------------------------------------------------------------------
+//
+CClock* CClock::NewL( CWmDrmServer* aServer )
+ {
+ LOGFN( "CClock::NewL" );
+ CClock* self = new (ELeave) CClock( aServer );
+ CleanupStack::PushL( self );
+ self->ConstructL();
+ CleanupStack::Pop( self );
+ return self;
+ }
+
+//---------------------------------------------------------------------------
+// CClock::CClock
+// Constructor
+//---------------------------------------------------------------------------
+//
+CClock::CClock( CWmDrmServer* aServer ):
+ CTimer( -1 ),
+ iTimeIsGood( EFalse ),
+ iServer( aServer ),
+ iServiceApiLoaded( EFalse ),
+ iServiceApi( NULL )
+ {
+ CActiveScheduler::Add( this );
+ }
+
+//---------------------------------------------------------------------------
+// CClock::~CClock
+// Destructor
+//---------------------------------------------------------------------------
+//
+CClock::~CClock()
+ {
+ delete iChangeNotifier;
+ delete iServiceApi;
+ iServiceApiLib.Close();
+ }
+
+//---------------------------------------------------------------------------
+// CClock::TimeIsGood
+//---------------------------------------------------------------------------
+//
+TBool CClock::TimeIsGood()
+ {
+ return iTimeIsGood;
+ }
+
+//---------------------------------------------------------------------------
+// CClock::SetTimeAsGoodL
+//---------------------------------------------------------------------------
+//
+void CClock::SetTimeAsGoodL( TBool aGood )
+ {
+ iTimeIsGood = aGood;
+ if ( iTimeIsGood )
+ {
+ iTime.UniversalTime();
+ WriteTimeL();
+ }
+ }
+
+//---------------------------------------------------------------------------
+// CClock::ConstructL
+//---------------------------------------------------------------------------
+//
+void CClock::ConstructL()
+ {
+ TInt r = KErrNone;
+ TInt trap = KErrNone;
+
+ LOGFN( "CClock::ConstructL" );
+ CTimer::ConstructL();
+ iChangeNotifier = CEnvironmentChangeNotifier::NewL( EPriorityNormal,
+ TCallBack( CClock::ChangeCallback, this ) );
+ TRAP( trap, r = ReadTimeL() );
+ if ( trap != KErrNone || r != KErrNone )
+ {
+ // Init Change: init to a date prior to the manufacturing date:
+ // 00:00:00:000000 October 2nd, 2007.
+ // iTime.UniversalTime();
+ iTime = TDateTime(2007,EOctober,1,0,0,0,0);
+ WriteTimeL();
+ }
+ }
+
+//---------------------------------------------------------------------------
+// CClock::Start
+//---------------------------------------------------------------------------
+//
+void CClock::Start()
+ {
+ LOGFN( "CClock::Start" );
+ After( KClockInterval );
+ iChangeNotifier->Start();
+ }
+
+//---------------------------------------------------------------------------
+// CClock::ChangeCallback
+//---------------------------------------------------------------------------
+//
+TInt CClock::ChangeCallback( TAny* aClock )
+ {
+ LOGFN( "CClock::ChangeCallback" );
+ reinterpret_cast< CClock*>( aClock )->HandleChange();
+ return KErrNone;
+ }
+
+//---------------------------------------------------------------------------
+// CClock::EvaluateCurrentTime
+//---------------------------------------------------------------------------
+//
+void CClock::EvaluateCurrentTime()
+ {
+ TTime time;
+ TTimeIntervalSeconds delta;
+ TDateTime dateTime;
+
+ LOGFN( "CClock::EvaluateCurrentTime" );
+ time.UniversalTime();
+ dateTime = iTime.DateTime();
+
+ if( time.Int64() < iTime.Int64() )
+ {
+ iTimeIsGood = EFalse;
+ LOG1( "Time invalid" );
+ }
+ else
+ {
+ iTimeIsGood = ETrue;
+ LOG1( "Time valid" );
+ }
+ }
+
+//---------------------------------------------------------------------------
+// CClock::ReadTimeL
+//---------------------------------------------------------------------------
+//
+TInt CClock::ReadTimeL()
+ {
+ RFile file;
+ TBuf8<sizeof( TTime ) + 2 * KAESKeyLength> encryptedData;
+ TBuf8<sizeof( TTime ) + 2 * KAESKeyLength> decryptedData;
+ TBuf8<KAESKeyLength> key;
+ TBuf8<KAESKeyLength> iv;
+ CBufferedDecryptor* decryptor = NULL;
+ CModeCBCDecryptor* cbcDecryptor = NULL;
+ CAESDecryptor* aesDecryptor = NULL;
+ CPaddingPKCS7* padding = NULL;
+ TInt r = KErrNone;
+ TInt size = 0;
+ TDrmScheme drmScheme( EDrmSchemeWmDrm );
+ TChar driveLetter;
+ TBool wmDrmRightsConfigFound( EFalse );
+ TFileName timeSaverFile;
+
+ LOGFNR( "CClock::ReadTimeL", r );
+
+ // Check which drive is configured in the Central Repository Key
+ // for the desired storing location of WM DRM rights. Time saver
+ // file should be read from that location, too.
+ wmDrmRightsConfigFound = DrmRightsStoringLocation::CheckDrmRightsStorageDriveL(
+ iServer->Fs(), drmScheme, driveLetter );
+
+ if( wmDrmRightsConfigFound )
+ {
+ LOG1( "ReadTimeL: Rights Config Found" );
+ }
+
+ timeSaverFile.Format( KTimeSaverFile, (TUint)driveLetter );
+
+ r = file.Open( iServer->Fs(), timeSaverFile, EFileRead );
+ if ( r == KErrNone )
+ {
+ CleanupClosePushL( file );
+
+ User::LeaveIfError( file.Size( size ) );
+
+ if( size != ( 2 * KAESKeyLength ) )
+ {
+ User::Leave(KErrCorrupt);
+ }
+
+ User::LeaveIfError( file.Read( iv ) );
+ User::LeaveIfError( file.Read( encryptedData ) );
+#if defined(FF_PLATFORM_SIMULATOR) || defined(__WINSCW__)
+ key.Copy( KDummyKey );
+#else
+ iServer->Cache()->iKeyStorage->GetDeviceSpecificKeyL( key );
+#endif
+
+ aesDecryptor = CAESDecryptor::NewL( key );
+ CleanupStack::PushL( aesDecryptor );
+
+ cbcDecryptor = CModeCBCDecryptor::NewL( aesDecryptor, iv );
+ CleanupStack::Pop( aesDecryptor );
+ CleanupStack::PushL( cbcDecryptor );
+
+ padding = CPaddingPKCS7::NewL( KAESKeyLength );
+ CleanupStack::PushL( padding );
+
+ decryptor = CBufferedDecryptor::NewL( cbcDecryptor, padding );
+ CleanupStack::Pop( 2, cbcDecryptor ); //padding, cbcDecryptor
+ CleanupStack::PushL( decryptor );
+
+ decryptor->ProcessFinalL( encryptedData, decryptedData );
+ TPtr8 ptr( reinterpret_cast<TUint8*>( &iTime ), sizeof( iTime ) );
+ ptr.Copy( decryptedData.Left( sizeof( TTime ) ) );
+ EvaluateCurrentTime();
+ CleanupStack::PopAndDestroy( 2, &file ); //decryptor, file
+ }
+ return r;
+ }
+
+//---------------------------------------------------------------------------
+// CClock::WriteTimeL
+//---------------------------------------------------------------------------
+//
+TInt CClock::WriteTimeL()
+ {
+ RFile file;
+ TBuf8<sizeof( TTime ) + 2 * KAESKeyLength> encryptedData;
+ TBuf8<sizeof( TTime ) + 2 * KAESKeyLength> decryptedData;
+ TBuf8<KAESKeyLength> key;
+ TBuf8<KAESKeyLength> iv;
+ CBufferedEncryptor* encryptor = NULL;
+ CModeCBCEncryptor* cbcEncryptor = NULL;
+ CAESEncryptor* aesEncryptor = NULL;
+ CPaddingPKCS7* padding = NULL;
+ TInt r = KErrNone;
+ TInt pos = 0;
+ TDrmScheme drmScheme( EDrmSchemeWmDrm );
+ TChar driveLetter;
+ TBool wmDrmRightsConfigFound( EFalse );
+ TFileName tempFile;
+
+ LOGFNR( "CClock::WriteTime", r );
+
+ // Check which drive is configured in the Central Repository Key
+ // for the desired storing location of WM DRM rights. Time saver
+ // file should be stored to that location, too.
+ wmDrmRightsConfigFound = DrmRightsStoringLocation::CheckDrmRightsStorageDriveL(
+ iServer->Fs(), drmScheme, driveLetter );
+
+ if( wmDrmRightsConfigFound )
+ {
+ LOG1( "WriteTimeL: Rights Config Found" );
+ }
+
+ tempFile.Format( KPrivateDir, (TUint)driveLetter );
+ iServer->Fs().MkDirAll( tempFile );
+
+ tempFile.Format( KTimeSaverFile, (TUint)driveLetter );
+ User::LeaveIfError( file.Replace( iServer->Fs(), tempFile, EFileRead | EFileWrite ) );
+ CleanupClosePushL( file );
+
+ iv.SetLength( KAESKeyLength );
+ TRandom::RandomL( iv );
+#if defined(FF_PLATFORM_SIMULATOR) || defined(__WINSCW__)
+ key.Copy( KDummyKey );
+#else
+ iServer->Cache()->iKeyStorage->GetDeviceSpecificKeyL( key );
+#endif
+ aesEncryptor = CAESEncryptor::NewL( key );
+ CleanupStack::PushL( aesEncryptor );
+
+ cbcEncryptor = CModeCBCEncryptor::NewL( aesEncryptor, iv );
+ CleanupStack::Pop( aesEncryptor );
+ CleanupStack::PushL( cbcEncryptor );
+
+ padding = CPaddingPKCS7::NewL( KAESKeyLength );
+ CleanupStack::PushL( padding );
+
+ encryptor = CBufferedEncryptor::NewL( cbcEncryptor, padding );
+ CleanupStack::Pop( 2, cbcEncryptor ); //padding, cbcEncryptor
+ CleanupStack::PushL( encryptor );
+
+ TPtr8 ptr( reinterpret_cast<TUint8*>( &iTime ), sizeof( iTime ), sizeof( iTime ) );
+ decryptedData.Copy( ptr.Left( sizeof( TTime ) ) );
+ encryptor->ProcessFinalL( decryptedData, encryptedData );
+ User::LeaveIfError( file.Seek( ESeekStart, pos ) );
+ User::LeaveIfError( file.SetSize( 0 ) );
+ User::LeaveIfError( file.Write( iv ) );
+ User::LeaveIfError( file.Write( encryptedData ) );
+ iTimeIsGood = ETrue;
+ CleanupStack::PopAndDestroy( 2, &file ); //encryptor, file
+ return r;
+ }
+
+//---------------------------------------------------------------------------
+// CClock::HandleChange
+//---------------------------------------------------------------------------
+//
+void CClock::HandleChange()
+ {
+ TInt change;
+
+ LOGFN( "CClock::HandleChange" );
+ change = iChangeNotifier->Change();
+ LOG2( "Change: %d", change );
+ if ( ( change & EChangesSystemTime ) )
+ {
+ EvaluateCurrentTime();
+ if ( iTimeIsGood )
+ {
+ iTime.UniversalTime();
+ TRAP_IGNORE( WriteTimeL() );
+ }
+ }
+ }
+
+
+//---------------------------------------------------------------------------
+// CClock::LoadServiceApi
+//---------------------------------------------------------------------------
+//
+TInt CClock::LoadServiceApi()
+ {
+#ifdef __DRM_CLOCK
+ TInt err = KErrNone;
+
+ if( !iServiceApiLoaded )
+ {
+ err = iServiceApiLib.Load( KDrmServiceApiWrapperName );
+ if( err )
+ {
+ iServiceApiLoaded = EFalse;
+ return err;
+ }
+ iServiceApiLoaded = ETrue;
+ }
+
+ if( !iServiceApi )
+ {
+ TLibraryFunction function = iServiceApiLib.Lookup( KDrmServiceApiWrapperGateOrdinal );
+ if( function )
+ {
+ iServiceApi = reinterpret_cast<DRM::CDrmServiceApiWrapper*>( function() );
+ if( !iServiceApi )
+ {
+ iServiceApi = NULL;
+ return KErrGeneral;
+ }
+ }
+ else
+ {
+ return KErrNotFound;
+ }
+ }
+#endif
+ return KErrNone;
+ }
+
+//----------------------------------------------------------------------------
+// CClock::GetTimeL
+// This function gets the time from DRM Clock checks the validity and
+// then returns this information
+// flagged for use with DRM Clock, if clock is not there, use the old implementation
+//----------------------------------------------------------------------------
+//
+void CClock::GetTimeL( TTime& aTime, TBool& aValid )
+ {
+ TInt timeZone = 0;
+
+#ifdef __DRM_CLOCK
+
+ DRMClock::ESecurityLevel secLevel;
+
+ // If it's already loaded then this just returns KErrNone
+ User::LeaveIfError( LoadServiceApi() );
+
+ User::LeaveIfError( iServiceApi->GetSecureTime( aTime, timeZone, secLevel ) );
+
+ if( secLevel == DRMClock::KSecure )
+ {
+ aValid = ETrue;
+ }
+ else
+ {
+ aValid = EFalse;
+ }
+#else
+ aTime.UniversalTime();
+ aValid = EFalse;
+#endif
+ }
+
+//----------------------------------------------------------------------------
+// CClock::RunL
+//----------------------------------------------------------------------------
+//
+void CClock::RunL()
+ {
+ LOGFN( "CClock::RunL" );
+ LOG2( "Status: %d", iStatus.Int() );
+ EvaluateCurrentTime();
+ if ( iTimeIsGood )
+ {
+ iTime.UniversalTime();
+ TRAP_IGNORE( WriteTimeL() );
+ }
+ After( KClockInterval );
+ }