diff -r 000000000000 -r 95b198f216e5 wmdrm/wmdrmengine/wmdrmserver/server/src/clock.cpp --- /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 +#include +#include +#include + +#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 encryptedData; + TBuf8 decryptedData; + TBuf8 key; + TBuf8 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( &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 encryptedData; + TBuf8 decryptedData; + TBuf8 key; + TBuf8 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( &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( 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 ); + }