wmdrm/wmdrmengine/wmdrmserver/server/src/slotdata.cpp
changeset 0 95b198f216e5
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/wmdrm/wmdrmengine/wmdrmserver/server/src/slotdata.cpp	Thu Dec 17 08:52:27 2009 +0200
@@ -0,0 +1,390 @@
+/*
+* Copyright (c) 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:  WMDRM Server implementation
+*
+*/
+
+
+#include <ezlib.h>
+#include <e32math.h>
+#include <symmetric.h>
+#include <bacntf.h>
+#include <random.h>
+
+#include "wmdrmkeystorage.h"
+#include "slotdata.h"
+#include "wmdrmserver.h"
+#include "slotdatacache.h"
+#include "slotenumeratorcache.h"
+#include "wmdrmdb.h"
+
+#define _LOGGING_FILE L"wmdrmserver.txt"
+
+#include "flogger.h"
+#include "logfn.h"
+
+#ifdef __WINSCW__
+_LIT8( KDummyKey, "0123456789012345" );
+#endif
+
+CSlotData* CSlotData::NewL( 
+    CWmDrmServer* aServer, 
+    const TDesC8& aStore,
+    const TDesC8& aNamespace,
+    const TDesC8& aHashKey,
+    const TDesC8& aUniqueKey )
+    {
+    LOGFN( "CSlotData::NewL" );
+    CSlotData* self = new (ELeave) CSlotData( aServer,
+                                              aStore,
+                                              aNamespace,
+                                              aHashKey,
+                                              aUniqueKey );
+    return self;
+    }
+
+CSlotData::CSlotData( 
+    CWmDrmServer* aServer, 
+    const TDesC8& aStore,
+    const TDesC8& aNamespace,
+    const TDesC8& aHashKey,
+    const TDesC8& aUniqueKey ) : iServer( aServer ),
+                                 iDirty( EFalse ),
+                                 iExists( ETrue ),
+                                 iReferences( 0 )
+    {
+    LOGFN( "CSlotData::CSlotData" );
+    iStore.Copy( aStore );
+    iNamespace.Copy( aNamespace );
+    LOG( iNamespace );
+    iHashKey.Copy( aHashKey );
+    LOG( iHashKey );
+    iUniqueKey.Copy( aUniqueKey );
+    LOG( iUniqueKey );
+    }
+
+CSlotData::~CSlotData()
+    {
+    LOGFN( "CSlotData::~CSlotData" );
+    //FlushL();
+    iData.Close();
+    }
+
+void CSlotData::CreateL( TInt& aInitialSize )
+    {
+    LOGFN( "CSlotData::CreateL" );
+    LOG2( "Size: %d", aInitialSize );
+    LOG1( "*** Create record" );
+    if ( aInitialSize > KMaxSlotSize )
+        {
+        User::Leave( KErrArgument );
+        }
+	iServer->Db()->CreateRecordL( iStore, iNamespace, iHashKey, iUniqueKey, aInitialSize );
+    iData.Close();
+    iData.CreateL( aInitialSize );
+    iData.SetLength( iData.MaxLength() );
+    iData.FillZ();
+    iDirty = ETrue;
+    iExists = ETrue;
+    iOpen = ETrue;
+	iServer->EnumeratorCache()->AddEntryL( iStore, iNamespace, iHashKey, iUniqueKey );
+    //FlushL();
+    }
+
+TInt CSlotData::OpenL( TInt& aCurrentSize )
+    {
+    TInt r = KErrNone;
+    RBuf8 compressedData;
+    TUint32 uncompressedSize;
+    TPckg<TUint32> pckg( uncompressedSize );
+    RBuf8 encryptedData;
+    CBufferedDecryptor* decryptor = NULL;
+    CModeCBCDecryptor* cbcDecryptor = NULL;
+    CAESDecryptor* aesDecryptor = NULL;
+    CPaddingPKCS7* padding = NULL;
+    TInt size;
+    
+    LOGFN( "CSlotData::OpenL" );
+	LOG3( "Size: %d, data size: %d", aCurrentSize, iData.Length() );
+	if ( !IsOpen() )
+	    {
+	    if ( iExists )
+	        {
+    	    LOG1( "*** Opening record" );
+            TRAP( r, iServer->Db()->ReadRecordL( iStore, iNamespace, iHashKey, iUniqueKey ) );
+    	    if ( !r )
+    	        {
+    	        TBuf8<KAESKeyLength> key;
+    	        TBuf8<KAESKeyLength> iv;
+                RBuf8 buffer;
+
+                iServer->Db()->GetDataSizeL( size );
+                LOG2( "Record size: %d", size );
+                if( size <= 0 )
+                    {
+                    iServer->Db()->DeleteData();
+                    iServer->Db()->DeleteRecordL( iStore, iNamespace, iHashKey, iUniqueKey );
+                    User::Leave( KErrArgument );
+                    }
+                    
+                encryptedData.CreateL( size - sizeof( TUint32 ) - KAESKeyLength );
+                encryptedData.CleanupClosePushL();
+                
+                compressedData.CreateL( size - sizeof( TUint32 ) - KAESKeyLength );
+                compressedData.CleanupClosePushL();
+                
+
+                buffer.CreateL( size );
+                buffer.CleanupClosePushL();
+                iServer->Db()->ReadDataL( buffer );
+                //LOGHEX( buffer.Ptr(), buffer.Size() );
+                pckg.Copy( buffer.Left( sizeof( TUint32 ) ) );
+                LOG2( "Uncompressed size: %d", uncompressedSize );
+                iv.Copy( buffer.Mid ( sizeof( TUint32 ), KAESKeyLength ) );
+                //LOGHEX( iv.Ptr(), iv.Size () );
+                encryptedData.Copy( buffer.Right( size - sizeof( TUint32 ) - KAESKeyLength ) );
+                //LOGHEX( encryptedData.Ptr(), encryptedData.Size() );
+#ifdef __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, compressedData );
+
+                iData.Close();
+                iData.CreateMaxL( uncompressedSize );
+                User::LeaveIfError( uncompress( const_cast<TUint8*>( iData.Ptr() ), &uncompressedSize, 
+                                                                     compressedData.Ptr(), compressedData.Size() ) );
+                CleanupStack::PopAndDestroy( 4, &encryptedData ); //decryptor, buffer, compressedData, encryptedData
+                TRandom::RandomL( key );
+                iOpen = ETrue;
+                }
+            else 
+                {
+                iExists = EFalse;
+                if ( r == KErrPathNotFound )
+                    {
+                    r = KErrNotFound;
+                    }
+                }
+            }
+        else
+            {
+            r = KErrNotFound;
+            }
+        }
+	else
+	    {
+	    LOG1( "Record already open" );
+	    }
+    aCurrentSize = iData.Length();
+
+    return r;
+    }
+
+TInt CSlotData::Read( TInt aPosition, TDes8& aBuffer )
+    {
+    TInt r = KErrNone;
+    TInt length;
+
+    LOGFNR( "CSlotData::Read", r );
+	if ( IsOpen() )
+	    {
+	    length = Min( aBuffer.MaxLength(), iData.Length() - aPosition );
+	    LOG4( "Read %d bytes from %d, buffer size: %d", length, aPosition, aBuffer.MaxLength() );
+        aBuffer.Copy( iData.Mid( aPosition, length ) );
+//        LOGHEX( aBuffer.Ptr(), aBuffer.Size() );
+        }
+    else
+        {
+        r = KErrNotReady;
+        iServer->Cache()->Release( this );
+        }
+    return r;
+    }
+
+TInt CSlotData::WriteL( TInt aPosition, const TDesC8& aBuffer )
+    {
+    TInt r = KErrNone;
+
+	LOGFNR( "CSlotData::Write", r );
+	if ( IsOpen() )
+	    {
+	    LOG3( "Write %d bytes at %d", aBuffer.Length(), aPosition );
+//        LOGHEX( aBuffer.Ptr(), aBuffer.Size() );
+	    if ( aBuffer.Length() + aPosition > iData.Length() )
+	        {
+	        iData.ReAllocL( aBuffer.Length() + aPosition );
+	        iData.SetLength( iData.MaxLength() );
+	        }
+	    iData.Replace( aPosition, aBuffer.Length(), aBuffer );
+	    iDirty = ETrue;
+	    FlushL();
+        }
+    else
+        {
+        r = KErrNotReady;
+        iServer->Cache()->Release( this );
+        }
+    return r;
+    }
+
+TInt CSlotData::ResizeL( TInt aNewSize )
+    {
+    TInt r = KErrNone;
+
+	LOGFNR( "CSlotData::Resize", r );
+	if ( IsOpen() )
+        {
+    	LOG2( "New size: %d", aNewSize );
+    	if ( aNewSize > iData.Size() )
+    	    {
+            iData.ReAllocL( aNewSize );
+            }
+        iData.SetLength( aNewSize );
+        }
+    else
+        {
+        r = KErrNotReady;
+        iServer->Cache()->Release( this );
+        }
+    return r;
+    }
+
+TInt CSlotData::DeleteL()
+    {
+    TInt r = KErrNone;
+    
+	LOGFNR( "CSlotData::Delete", r );
+	iServer->EnumeratorCache()->DeleteEntryL( iStore, iNamespace, iHashKey, iUniqueKey );
+	r = iServer->Cache()->Delete( this );
+	return r;
+    }
+
+TInt CSlotData::Size()
+    {
+    TInt r;
+    
+    LOGFNR( "CSlotData::Size", r );
+	if ( IsOpen() )
+	    {
+	    r = iData.Length();
+	    }
+    else
+        {
+        r = KErrNotReady;
+        iServer->Cache()->Release( this );
+        }
+	return r;
+    }
+
+void CSlotData::Close()
+    {
+    LOGFN( "CSlotData::Close" );
+    iServer->Cache()->Release( this );
+    }
+
+void CSlotData::CloseFile()
+    {
+    LOGFN( "CSlotData::CloseFile" );
+    iOpen = EFalse;
+    }
+
+void CSlotData::FlushL()
+    {
+    LOGFN( "CSlotData::FlushL" );
+    __UHEAP_MARK;
+	if ( IsOpen() && iDirty )
+	    {
+        TBuf8<KAESKeyLength> iv;
+        TBuf8<KAESKeyLength> key;
+        TInt size = iData.Size();
+        RBuf8 compressedData;
+        TUint32 compressedDataLen = size + size / 10 + 12;
+        TUint8* compressedDataPtr;
+        RBuf8 encryptedData;
+        CBufferedEncryptor* encryptor = NULL;
+        CModeCBCEncryptor* cbcEncryptor = NULL;
+        CAESEncryptor* aesEncryptor = NULL;
+        CPaddingPKCS7* padding = NULL;
+        RBuf8 buffer;
+      
+        compressedData.CreateL( compressedDataLen );
+        compressedData.CleanupClosePushL();
+        compressedDataPtr = const_cast<TUint8*>( compressedData.Ptr() );
+        User::LeaveIfError( compress( compressedDataPtr, &compressedDataLen, iData.Ptr(), size ) );
+        compressedData.SetLength( compressedDataLen );
+        
+        encryptedData.CreateL( compressedData.Size() + 2 * KAESKeyLength );
+        encryptedData.CleanupClosePushL();
+
+        iv.SetLength( KAESKeyLength );
+        TRandom::RandomL( iv );
+#ifdef __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 );
+        
+        encryptor->ProcessFinalL( compressedData, encryptedData );
+        
+        LOG1( "*** Write record" );
+        LOG3( "Uncompressed size: %d, compresseded size: %d", size, encryptedData.Size() );
+        buffer.CreateL( sizeof( TUint32 ) + iv.Size() + encryptedData.Size() );
+        buffer.CleanupClosePushL();
+        buffer.Append( TPckgC<TUint32>( size ) );
+        buffer.Append( iv );
+        buffer.Append( encryptedData );
+        //LOGHEX( buffer.Ptr(), buffer.Size() );
+
+        iServer->Db()->WriteDataL( iStore, iNamespace, iHashKey, iUniqueKey, buffer );
+        iDirty = EFalse;
+        TRandom::RandomL( key );
+        CleanupStack::PopAndDestroy( 4, &compressedData ); //buffer, encryptor, encryptedData, compressedData
+        }
+    __UHEAP_MARKEND;        
+    }
+
+TBool CSlotData::IsOpen()
+    {
+    return iOpen;
+    }
+