omadrm/drmengine/agentv2/src/DcfCache.cpp
changeset 0 95b198f216e5
child 12 8a03a285ab14
equal deleted inserted replaced
-1:000000000000 0:95b198f216e5
       
     1 /*
       
     2 * Copyright (c) 2002-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:  Implementation of the DCF cache class
       
    15 *
       
    16 */
       
    17 
       
    18 // INCLUDE FILES
       
    19 #include <f32file.h>
       
    20 #include <e32base.h>
       
    21 #include <symmetric.h>
       
    22 #include <rijndael.h>
       
    23 #include "DcfCache.h"
       
    24 #include "DcfCommon.h"
       
    25 #include "DrmRightsClient.h"
       
    26 
       
    27 // ============================ MEMBER FUNCTIONS ===============================
       
    28 
       
    29 // -----------------------------------------------------------------------------
       
    30 // CDcfCache::CDcfCache
       
    31 // C++ default constructor can NOT contain any code, that
       
    32 // might leave.
       
    33 // -----------------------------------------------------------------------------
       
    34 //
       
    35 #ifdef ASYNC_READ
       
    36 
       
    37 CDcfCache::CDcfCache(
       
    38     RDRMRightsClient& aRightsClient,
       
    39     RFile& aFile,
       
    40     CDcfCommon& aDcf,
       
    41     TInt aPageSize,
       
    42     TInt aPageCount ) :
       
    43 CActive( CActive::EPriorityStandard ),
       
    44 iFile( aFile ),
       
    45 iRightsClient(aRightsClient ),
       
    46 iDcf( aDcf ),
       
    47 iPageSize( aPageSize ),
       
    48 iPageCount( aPageCount ),
       
    49 iDecryptionMode( EServerSide ),
       
    50 iDes( 0 ),
       
    51 iAsyncReadingOngoing( EFalse )
       
    52     {
       
    53     }
       
    54 
       
    55 #else
       
    56 
       
    57 CDcfCache::CDcfCache(
       
    58     RDRMRightsClient& aRightsClient,
       
    59     RFile& aFile,
       
    60     CDcfCommon& aDcf,
       
    61     TInt aPageSize,
       
    62     TInt aPageCount ) :
       
    63 iFile( aFile ),
       
    64 iRightsClient( aRightsClient ),
       
    65 iDcf( aDcf ),
       
    66 iPageSize( aPageSize ),
       
    67 iPageCount( aPageCount ),
       
    68 iDecryptionMode( EServerSide )
       
    69     {
       
    70     }
       
    71 #endif
       
    72 // -----------------------------------------------------------------------------
       
    73 // CDcfCache::ConstructL
       
    74 // Symbian 2nd phase constructor can leave.
       
    75 // -----------------------------------------------------------------------------
       
    76 //
       
    77 void CDcfCache::ConstructL()
       
    78     {
       
    79     for ( TInt i = 0; i < iPageCount; i++ )
       
    80         {
       
    81         iPage.AppendL( new ( ELeave ) TUint8[iPageSize] );
       
    82         iPageUsageCount.AppendL( -1 );
       
    83         iPagePosition.AppendL( -1 );
       
    84         }
       
    85     }
       
    86 
       
    87 // -----------------------------------------------------------------------------
       
    88 // CDcfCache::NewL
       
    89 // Two-phased constructor.
       
    90 // -----------------------------------------------------------------------------
       
    91 //
       
    92 CDcfCache* CDcfCache::NewL( RDRMRightsClient& aRightsClient, RFile& aFile,
       
    93     CDcfCommon& aDcf, TInt aPageSize, TInt aPageCount )
       
    94     {
       
    95     CDcfCache* self = new ( ELeave ) CDcfCache( aRightsClient, aFile, aDcf,
       
    96         aPageSize, aPageCount );
       
    97 
       
    98     CleanupStack::PushL( self );
       
    99     self->ConstructL();
       
   100     CleanupStack::Pop( self );
       
   101 
       
   102     return self;
       
   103     }
       
   104 
       
   105 // -----------------------------------------------------------------------------
       
   106 // CDcfCache::~CDcfCache
       
   107 // Destructor
       
   108 // -----------------------------------------------------------------------------
       
   109 //
       
   110 CDcfCache::~CDcfCache()
       
   111     {
       
   112 
       
   113 #ifdef ASYNC_READ
       
   114     if ( IsActive() )
       
   115         {
       
   116         if ( iAsyncReadingOngoing )
       
   117             {
       
   118             Cancel();
       
   119             }
       
   120         else
       
   121             {
       
   122             TRequestStatus* status = &iStatus;
       
   123             User::RequestComplete( status, KErrNone );
       
   124             Cancel();
       
   125             }
       
   126         }
       
   127 #endif
       
   128 
       
   129     iPage.ResetAndDestroy();
       
   130     iPage.Close();
       
   131     iPagePosition.Close();
       
   132     iPageUsageCount.Close();
       
   133     }
       
   134 
       
   135 // -----------------------------------------------------------------------------
       
   136 // CDcfCache::Read
       
   137 // -----------------------------------------------------------------------------
       
   138 //
       
   139 TInt CDcfCache::Read( TInt& aPos, TDes8& aDes, TInt aLength )
       
   140     {
       
   141     TInt r = KErrNone;
       
   142 
       
   143     // Check that the position is valid and the length is valid
       
   144     if ( aPos < 0 || aLength < 0 )
       
   145         {
       
   146         return KErrArgument;
       
   147         }
       
   148 
       
   149     if ( iPageCount > 0 )
       
   150         {
       
   151         TRAP(r, CachedReadL(aPos, aDes, aLength));
       
   152         }
       
   153     else
       
   154         {
       
   155         TRAP(r, UncachedReadL(aPos, aDes, aLength));
       
   156         }
       
   157     if ( r != KErrNone )
       
   158         {
       
   159         RDebug::Printf( "CDcfCache::Read error: %d", r );
       
   160         }
       
   161     return r;
       
   162     }
       
   163 
       
   164 // -----------------------------------------------------------------------------
       
   165 // CDcfCache::Read
       
   166 // -----------------------------------------------------------------------------
       
   167 //
       
   168 
       
   169 #ifdef ASYNC_READ
       
   170 
       
   171 TInt CDcfCache::Read( TInt aPos, TDes8& aDes, TInt aLength,
       
   172     TRequestStatus& aStatus )
       
   173     {
       
   174 
       
   175     // Check that the position is valid and the length is valid
       
   176     if ( aPos < 0 || aLength < 0 )
       
   177         {
       
   178         return KErrArgument;
       
   179         }
       
   180 
       
   181     if ( !IsAdded() )
       
   182         {
       
   183         CActiveScheduler::Add( this );
       
   184         }
       
   185 
       
   186     if ( iAsyncReadingOngoing )
       
   187         {
       
   188         return KErrInUse;
       
   189         }
       
   190 
       
   191     iError = KErrNone;
       
   192 
       
   193     iAsyncReadingOngoing = ETrue;
       
   194 
       
   195     iPos = aPos;
       
   196     iLength = aLength;
       
   197     iDes = &aDes;
       
   198     iOperation = EPosRead;
       
   199 
       
   200     iAsyncStatus = &aStatus;
       
   201     *iAsyncStatus = KRequestPending;
       
   202 
       
   203     TRequestStatus* ownStatus = &iStatus;
       
   204     *ownStatus = KRequestPending;
       
   205 
       
   206     SetActive();
       
   207     User::RequestComplete( ownStatus, KErrNone );
       
   208     return KErrNone;
       
   209     }
       
   210 
       
   211 // -----------------------------------------------------------------------------
       
   212 // CDcfCache::ReadCancel
       
   213 // -----------------------------------------------------------------------------
       
   214 //
       
   215 void CDcfCache::ReadCancel( TRequestStatus& aStatus )
       
   216     {
       
   217     // only cancel if needed
       
   218     TRequestStatus* status( &aStatus );
       
   219     if ( IsActive() && iAsyncStatus == status )
       
   220         {
       
   221         if ( iAsyncReadingOngoing )
       
   222             {
       
   223             Cancel();
       
   224             iAsyncReadingOngoing = EFalse;
       
   225             iAsyncStatus = NULL;
       
   226             User::RequestComplete( status, KErrCancel );
       
   227             }
       
   228         }
       
   229     }
       
   230 
       
   231 #endif
       
   232 
       
   233 // -----------------------------------------------------------------------------
       
   234 // CDcfCache::CachedReadL
       
   235 // -----------------------------------------------------------------------------
       
   236 //
       
   237 void CDcfCache::CachedReadL( TInt& aPos, TDes8& aDes, TInt aLength )
       
   238     {
       
   239     TInt i;
       
   240 
       
   241     // Check that the position is valid and the length is valid
       
   242     if ( aPos < 0 || aLength < 0 )
       
   243         {
       
   244         User::Leave( KErrArgument );
       
   245         }
       
   246 
       
   247     aDes.SetLength( 0 );
       
   248     while ( aLength > 0 )
       
   249         {
       
   250         for ( i = 0; aLength > 0 && i < iPageCount; i++ )
       
   251             {
       
   252             if ( InPage( i, aPos ) )
       
   253                 {
       
   254                 CopyOut( i, aDes, aPos, aLength );
       
   255                 }
       
   256             }
       
   257         if ( i == iPageCount && aLength > 0 )
       
   258             {
       
   259             i = GetFreePage();
       
   260             if ( iDcf.iEncryptionMethod == EMethodAES_128_CBC )
       
   261                 {
       
   262                 ReadAndDecryptPageL( i, aPos );
       
   263                 CopyOut( i, aDes, aPos, aLength );
       
   264                 }
       
   265             else
       
   266                 {
       
   267                 ReadPageL( i, aPos );
       
   268                 CopyOut( i, aDes, aPos, aLength );
       
   269                 }
       
   270             }
       
   271         }
       
   272     }
       
   273 
       
   274 // -----------------------------------------------------------------------------
       
   275 // CDcfCache::UncachedReadL
       
   276 // -----------------------------------------------------------------------------
       
   277 //
       
   278 void CDcfCache::UncachedReadL( TInt& aPos, TDes8& aDes, TInt aLength )
       
   279     {
       
   280     HBufC8* buffer = NULL;
       
   281     TPtr8 ptr( NULL, 0 );
       
   282     TBuf8<KDCFKeySize> iv;
       
   283     TInt pos;
       
   284     TInt length;
       
   285 
       
   286     // Check that the position is valid and the length is valid
       
   287     if ( aPos < 0 || aLength < 0 )
       
   288         {
       
   289         User::Leave( KErrArgument );
       
   290         }
       
   291 
       
   292     if ( aPos + aLength > iDcf.iPlainTextLength )
       
   293         {
       
   294         if ( aPos < iDcf.iPlainTextLength )
       
   295             {
       
   296             aLength = iDcf.iPlainTextLength - aPos;
       
   297             }
       
   298         else
       
   299             {
       
   300             aLength = 0;
       
   301             }
       
   302         }
       
   303 
       
   304     if ( iDcf.iEncryptionMethod == EMethodAES_128_CBC )
       
   305         {
       
   306 
       
   307         // Nothing to read:
       
   308         if ( aLength == 0 )
       
   309             {
       
   310             aDes.SetLength( aLength );
       
   311             return;
       
   312             }
       
   313 
       
   314         buffer = HBufC8::NewLC( aLength + 2 * KDCFKeySize );
       
   315         ptr.Set( buffer->Des() );
       
   316         pos = ( ( aPos / KDCFKeySize ) * KDCFKeySize ) + iDcf.iOffset;
       
   317         User::LeaveIfError( iFile.Read( pos, iv, KDCFKeySize ) );
       
   318         length = ( ( aLength / KDCFKeySize ) * KDCFKeySize ) + 2
       
   319             * KDCFKeySize;
       
   320         User::LeaveIfError( iFile.Read( ptr, length ) );
       
   321 
       
   322         // Make sure we have the correct amount of data
       
   323         if ( ptr.Length() % KDCFKeySize )
       
   324             {
       
   325             length = ( ( ptr.Length() / KDCFKeySize ) * KDCFKeySize );
       
   326             ptr.SetLength( length );
       
   327             }
       
   328 
       
   329         // If not enough was read to get any content return an empty descriptor
       
   330         if ( ptr.Length() == 0 )
       
   331             {
       
   332             aDes.SetLength( 0 );
       
   333             CleanupStack::PopAndDestroy( buffer );
       
   334             return;
       
   335             }
       
   336 
       
   337         DecryptL( iv, ptr );
       
   338         length = Min( aDes.MaxLength(), ptr.Length() - aPos % KDCFKeySize );
       
   339         aDes.Copy( ptr.Mid( aPos % KDCFKeySize, length ) );
       
   340         if ( aDes.Length() > aLength )
       
   341             {
       
   342             aDes.SetLength( aLength );
       
   343             }
       
   344         CleanupStack::PopAndDestroy( buffer );
       
   345         }
       
   346     else
       
   347         {
       
   348         User::LeaveIfError( iFile.Read( aPos + iDcf.iOffset, aDes, aLength ) );
       
   349         }
       
   350     aPos += aDes.Length();
       
   351     }
       
   352 
       
   353 // -----------------------------------------------------------------------------
       
   354 // CDcfCache::GetFreePage
       
   355 // -----------------------------------------------------------------------------
       
   356 //
       
   357 TInt CDcfCache::GetFreePage()
       
   358     {
       
   359     TInt i;
       
   360     TInt n = -1;
       
   361     TUint c = KMaxTUint32;
       
   362 
       
   363     for ( i = 0; i < iPageCount; i++ )
       
   364         {
       
   365         if ( iPageUsageCount[i] == -1 )
       
   366             {
       
   367             n = i;
       
   368             break;
       
   369             }
       
   370         else if ( iPageUsageCount[i] < c )
       
   371             {
       
   372             c = iPageUsageCount[i];
       
   373             n = i;
       
   374             }
       
   375         }
       
   376     return n;
       
   377     }
       
   378 
       
   379 // -----------------------------------------------------------------------------
       
   380 // CDcfCache::ReadPageL
       
   381 // -----------------------------------------------------------------------------
       
   382 //
       
   383 void CDcfCache::ReadPageL( TInt aPage, TInt aPosition )
       
   384     {
       
   385     TInt pos;
       
   386     TBuf8<KDCFKeySize> iv;
       
   387 
       
   388     iPageUsageCount[aPage] = 0;
       
   389     iPagePosition[aPage] = ( aPosition / iPageSize ) * iPageSize;
       
   390     pos = iPagePosition[aPage] + iDcf.iOffset;
       
   391     iFile.Seek( ESeekStart, pos );
       
   392     TPtr8 ptr( iPage[aPage], iPageSize );
       
   393     User::LeaveIfError( iFile.Read( ptr ) );
       
   394     }
       
   395 
       
   396 // -----------------------------------------------------------------------------
       
   397 // CDcfCache::ReadAndDecryptPageL
       
   398 // -----------------------------------------------------------------------------
       
   399 //
       
   400 void CDcfCache::ReadAndDecryptPageL( TInt aPage, TInt aPosition )
       
   401     {
       
   402     TInt pos;
       
   403     TBuf8<KDCFKeySize> iv;
       
   404 
       
   405     iPageUsageCount[aPage] = 0;
       
   406     iPagePosition[aPage] = ( aPosition / iPageSize ) * iPageSize;
       
   407     pos = iPagePosition[aPage] + iDcf.iOffset;
       
   408     User::LeaveIfError( iFile.Seek( ESeekStart, pos ) );
       
   409     User::LeaveIfError( iFile.Read( iv ) );
       
   410     TPtr8 ptr( iPage[aPage], iPageSize );
       
   411     pos += KDCFKeySize;
       
   412     User::LeaveIfError( iFile.Read( ptr ) );
       
   413     ptr.SetLength( iPageSize );
       
   414     DecryptL( iv, ptr );
       
   415     }
       
   416 
       
   417 // -----------------------------------------------------------------------------
       
   418 // CDcfCache::CopyOut
       
   419 // -----------------------------------------------------------------------------
       
   420 //
       
   421 void CDcfCache::CopyOut( TInt aPage, TDes8& aDes, TInt& aPosition,
       
   422     TInt& aLength )
       
   423     {
       
   424     TInt n;
       
   425     TInt offset;
       
   426 
       
   427     aLength = Min( aLength, iDcf.iPlainTextLength - aPosition );
       
   428     aLength = Min( aLength, aDes.MaxLength() - aDes.Length() );
       
   429     offset = aPosition - iPagePosition[aPage];
       
   430     n = Min( aLength, iPageSize - offset );
       
   431     aDes.Append( iPage[aPage] + offset, n );
       
   432     aLength -= n;
       
   433     aPosition += n;
       
   434     iPageUsageCount[aPage]++;
       
   435     }
       
   436 
       
   437 // -----------------------------------------------------------------------------
       
   438 // CDcfCache::InPage
       
   439 // -----------------------------------------------------------------------------
       
   440 //
       
   441 TBool CDcfCache::InPage( TInt aPage, TInt aPosition )
       
   442     {
       
   443     return iPagePosition[aPage] != -1 && iPagePosition[aPage] <= aPosition
       
   444         && aPosition < iPagePosition[aPage] + iPageSize ? ETrue : EFalse;
       
   445     }
       
   446 
       
   447 // -----------------------------------------------------------------------------
       
   448 // CDcfCache::SetKey
       
   449 // -----------------------------------------------------------------------------
       
   450 //
       
   451 void CDcfCache::SetKey( const TDesC8& aKey )
       
   452     {
       
   453     iKey.Copy( aKey );
       
   454     iDecryptionMode = EClientSide;
       
   455     }
       
   456 
       
   457 // -----------------------------------------------------------------------------
       
   458 // CDcfCache::DecryptL
       
   459 // -----------------------------------------------------------------------------
       
   460 //
       
   461 void CDcfCache::DecryptL( const TDesC8& aIv, TPtr8& aPtr )
       
   462     {
       
   463     if ( iDecryptionMode == EClientSide )
       
   464         {
       
   465         CModeCBCDecryptor* cbc( NULL );
       
   466         CAESDecryptor* aes( CAESDecryptor::NewLC( iKey ) );
       
   467         cbc = CModeCBCDecryptor::NewL( aes, aIv );
       
   468         CleanupStack::Pop( aes );
       
   469         aes = NULL;
       
   470         CleanupStack::PushL( cbc );
       
   471         for ( TInt count = 0; count < aPtr.Length(); count += KDCFKeySize )
       
   472             {
       
   473             TPtr8 d( aPtr.MidTPtr( count, KDCFKeySize ) );
       
   474             cbc->Transform( d );
       
   475             }
       
   476         CleanupStack::PopAndDestroy( cbc );
       
   477         }
       
   478     else
       
   479         {
       
   480         User::LeaveIfError( iRightsClient.Decrypt( aIv, aPtr ) );
       
   481         }
       
   482     }
       
   483 
       
   484 #ifdef ASYNC_READ
       
   485 
       
   486 // -----------------------------------------------------------------------------
       
   487 // CDcfCache::RunL
       
   488 // -----------------------------------------------------------------------------
       
   489 //
       
   490 void CDcfCache::RunL()
       
   491     {
       
   492 
       
   493     switch ( iOperation )
       
   494         {
       
   495         case ENonPosRead:
       
   496             {
       
   497             break;
       
   498             }
       
   499 
       
   500         case EPosRead:
       
   501             {
       
   502             ReadAsyncL();
       
   503             iAsyncReadingOngoing = EFalse;
       
   504             User::RequestComplete( iAsyncStatus, KErrNone );
       
   505             iAsyncStatus = NULL;
       
   506             break;
       
   507             }
       
   508 
       
   509         default:
       
   510             {
       
   511             break;
       
   512             }
       
   513         }
       
   514     }
       
   515 
       
   516 // -----------------------------------------------------------------------------
       
   517 // CDcfCache::DoCancel
       
   518 // -----------------------------------------------------------------------------
       
   519 //
       
   520 void CDcfCache::DoCancel()
       
   521     {
       
   522     }
       
   523 
       
   524 // -----------------------------------------------------------------------------
       
   525 // CDcfCache::RunError
       
   526 // -----------------------------------------------------------------------------
       
   527 //
       
   528 TInt CDcfCache::RunError( TInt aError )
       
   529     {
       
   530     iError = aError;
       
   531     User::RequestComplete( iAsyncStatus, iError );
       
   532     return KErrNone;
       
   533     }
       
   534 
       
   535 // -----------------------------------------------------------------------------
       
   536 // CDcfCache::ReadAsyncL
       
   537 // -----------------------------------------------------------------------------
       
   538 //
       
   539 
       
   540 void CDcfCache::ReadAsyncL()
       
   541     {
       
   542     if ( iPageCount > 0 )
       
   543         {
       
   544         TRAP(iError, CachedReadL(iPos, *iDes, iLength));
       
   545         }
       
   546     else
       
   547         {
       
   548         TRAP(iError, UncachedReadL(iPos, *iDes, iLength));
       
   549         }
       
   550     }
       
   551 #endif //ASYNC_READ
       
   552 //  End of File