emailservices/emailstore/message_store/server/src/ContainerStoreEncryption.cpp
changeset 0 8466d47a6819
child 66 084b5b1f02a7
equal deleted inserted replaced
-1:000000000000 0:8466d47a6819
       
     1 /*
       
     2 * Copyright (c) 2006 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:  Container store encryption implementation.
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 
       
    20 // ========
       
    21 // INCLUDES
       
    22 // ========
       
    23 
       
    24 #include <bautils.h>
       
    25 #include <utf.h>
       
    26 
       
    27 #include "ContainerStoreEncryption.h"
       
    28 #include "ContainerStoreUtils.h"
       
    29 
       
    30 class CCryptoBase: public CBase {};
       
    31 
       
    32 // =========
       
    33 // CONSTANTS
       
    34 // =========
       
    35 
       
    36 // This length is more than sufficient.
       
    37 const TInt KMaxAuthenticationBufferLength = 100;
       
    38 
       
    39 // ======================
       
    40 // METHOD IMPLEMENTATIONS
       
    41 // ======================
       
    42 
       
    43 // ==========================================================================
       
    44 // FUNCTION: NewL
       
    45 // ==========================================================================
       
    46 CContainerStoreEncryption* CContainerStoreEncryption::NewL()
       
    47 	{
       
    48 	CContainerStoreEncryption* self = new(ELeave) CContainerStoreEncryption;
       
    49 	return self;
       
    50 	} // end NewL
       
    51 	
       
    52 // ==========================================================================
       
    53 // FUNCTION: Constructor
       
    54 // ==========================================================================
       
    55 CContainerStoreEncryption::CContainerStoreEncryption() 
       
    56 : iAuthenticationRequired( EFalse ), iEncryptionFlag (EFalse)
       
    57 	{
       
    58 	__LOG_CONSTRUCT( "msg", "CContainerStoreEncryption" )
       
    59 	__LOG_CLOSE_BETWEEN_WRITES
       
    60 	} // end constructor
       
    61 	
       
    62 // ==========================================================================
       
    63 // FUNCTION: Destructor
       
    64 // ==========================================================================
       
    65 CContainerStoreEncryption::~CContainerStoreEncryption()
       
    66 	{
       
    67     ClearAuthentication();
       
    68 	__LOG_DESTRUCT
       
    69 	} // end destructor
       
    70 	
       
    71 // ==========================================================================
       
    72 // FUNCTION: Authenticated
       
    73 // ==========================================================================
       
    74 TBool CContainerStoreEncryption::Authenticated()
       
    75     {
       
    76     //always return true if authentication is not required
       
    77     return ( iCryptoLibrary != NULL || !iAuthenticationRequired ); 
       
    78     } // end Authenticated
       
    79 
       
    80 // ==========================================================================
       
    81 // FUNCTION: ClearAuthentication
       
    82 // ==========================================================================
       
    83 void CContainerStoreEncryption::ClearAuthentication()
       
    84     {
       
    85     delete iCryptoLibrary;
       
    86     iCryptoLibrary = NULL;
       
    87     } // end ClearAuthentication  
       
    88 
       
    89 // ==========================================================================
       
    90 // FUNCTION: CreateAuthenticationBufferL
       
    91 // ==========================================================================
       
    92 void CContainerStoreEncryption::CreateAuthenticationBufferL( const TDesC& aPassword, 
       
    93                                                              RBuf8&       aAuthenticationBuffer )
       
    94     {
       
    95     RBuf8 unencryptedAuthenticationBuffer;
       
    96     unencryptedAuthenticationBuffer.CreateL( KMaxAuthenticationBufferLength );
       
    97     CleanupClosePushL( unencryptedAuthenticationBuffer );
       
    98     
       
    99     if( !iCryptoLibrary )
       
   100         {        
       
   101         iCryptoLibrary = new(ELeave) CCryptoBase;
       
   102         } // end if
       
   103     
       
   104     const TUint size = 5; 
       
   105     HBufC8* key = HBufC8::NewL(size);
       
   106     _LIT8( K12345, "12345" );
       
   107     key->Des().Copy( K12345 );
       
   108     
       
   109     // Add the encryption key to the authentication buffer.    
       
   110     unencryptedAuthenticationBuffer.Append( *key );
       
   111     delete key;
       
   112 
       
   113     RBuf8 sha1Checksum;
       
   114     CleanupClosePushL( sha1Checksum );
       
   115 
       
   116     // Use the password length as the "SHA-1 Checksum"
       
   117     sha1Checksum.CreateL( 1 );
       
   118     sha1Checksum.Append( aPassword.Length() );   
       
   119     
       
   120     // Add the SHA-1 checksum of the key to the authentication buffer.
       
   121     unencryptedAuthenticationBuffer.Append( sha1Checksum );
       
   122 
       
   123     // Add the length of the SHA-1 checksum to the authentication buffer.
       
   124     unencryptedAuthenticationBuffer.Append( TUint8(sha1Checksum.Length()) );
       
   125     
       
   126     CleanupStack::PopAndDestroy( &sha1Checksum );   
       
   127     
       
   128     // Add PKCS5 padding to the buffer.
       
   129     AddPaddingL( unencryptedAuthenticationBuffer, BlockSizeL() );
       
   130                 
       
   131     // Encrypt the buffer using the given password.
       
   132     aAuthenticationBuffer.ReAllocL( unencryptedAuthenticationBuffer.Length() );                
       
   133     aAuthenticationBuffer.Copy( unencryptedAuthenticationBuffer );
       
   134 
       
   135     CleanupStack::PopAndDestroy( &unencryptedAuthenticationBuffer );
       
   136     
       
   137     } // end DoGenerateAuthenticationBufferL
       
   138 
       
   139 // ==========================================================================
       
   140 // FUNCTION: AuthenticateL
       
   141 // ==========================================================================
       
   142 TBool CContainerStoreEncryption::AuthenticateL( const TDesC&  aPassword, 
       
   143                                                 const TDesC8& aAuthenticationBuffer )
       
   144     {
       
   145     TBool returnValue = EFalse;
       
   146     
       
   147     RBuf8 decryptedBuffer;
       
   148     CleanupClosePushL( decryptedBuffer );
       
   149 
       
   150     decryptedBuffer.CreateL( aAuthenticationBuffer.Length() );
       
   151     decryptedBuffer.Copy( aAuthenticationBuffer );
       
   152     TInt result = KErrNone;
       
   153 
       
   154     if( result == KErrNone )
       
   155         {            
       
   156         // Verify that the PKCS5 padding is still intact.
       
   157         TUint8 padLength = decryptedBuffer[decryptedBuffer.Length()-1];
       
   158     
       
   159         TBool paddingOk = (padLength >= 1 && padLength < aAuthenticationBuffer.Length() );
       
   160     
       
   161         for( TInt i = 0; paddingOk && i < padLength; i++ )
       
   162             {
       
   163             paddingOk = decryptedBuffer[decryptedBuffer.Length()-i-1] == padLength;
       
   164             } // end for  
       
   165             
       
   166         // Verify the SHA-1 checksum of the encryption key.            
       
   167         if( paddingOk && (padLength < decryptedBuffer.Length()) )
       
   168             {
       
   169             // Remove the pad characters.
       
   170             decryptedBuffer.SetLength( decryptedBuffer.Length() - padLength );
       
   171 
       
   172             // Get the length of the checksum.
       
   173             TUint8 checksumLength = decryptedBuffer[decryptedBuffer.Length()-1];
       
   174             decryptedBuffer.SetLength( decryptedBuffer.Length() - 1 ); 
       
   175             
       
   176             if( checksumLength < decryptedBuffer.Length() )
       
   177                 {
       
   178                 // Create a pointer to the encryption key.
       
   179                 TPtrC8 encryptionKey( decryptedBuffer.Left( decryptedBuffer.Length() - checksumLength ) );
       
   180             
       
   181                 // Compute the expected SHA-1 checksum.
       
   182                 RBuf8 expectedChecksum;
       
   183                 CleanupClosePushL( expectedChecksum );
       
   184                 expectedChecksum.CreateL(1);
       
   185                 expectedChecksum.Append( aPassword.Length() );                                    
       
   186 
       
   187                 // Verify the SHA-1 checksum.
       
   188                 if( expectedChecksum.Compare(decryptedBuffer.Right(checksumLength)) == 0 )
       
   189                     {
       
   190                     // Password is OK.
       
   191                     returnValue = ETrue;
       
   192                                     
       
   193                     // Save the encryption key for later use.
       
   194                     if( !iCryptoLibrary )
       
   195                         {
       
   196                         iCryptoLibrary = new(ELeave) CCryptoBase;
       
   197                         } // end if
       
   198 
       
   199                     } // end if
       
   200 
       
   201                 CleanupStack::PopAndDestroy( &expectedChecksum );
       
   202                 
       
   203                 } // end if
       
   204 
       
   205             } // end if
       
   206         
       
   207         } // end if
       
   208             
       
   209     CleanupStack::PopAndDestroy( &decryptedBuffer );
       
   210 
       
   211     return returnValue;
       
   212     
       
   213     } // end AuthenticateL
       
   214 
       
   215 // ==========================================================================
       
   216 // FUNCTION: CheckForAuthenticationL
       
   217 // ==========================================================================
       
   218 void CContainerStoreEncryption::CheckForAuthenticationL()
       
   219     {    
       
   220     __LOG_ENTER_SUPPRESS( "CheckForAuthenticationL" )
       
   221     
       
   222     //leave if authentication is required is ON and library is NULL
       
   223 	if( !iCryptoLibrary && iAuthenticationRequired )
       
   224 	    {
       
   225 	    __LOG_WRITE_ERROR( "not authenticated" )
       
   226 	    User::Leave( KErrNotReady );
       
   227 	    } // end if
       
   228 	    
       
   229     } // end CheckForAuthenticationL
       
   230 
       
   231 // ==========================================================================
       
   232 // FUNCTION: DecryptL
       
   233 // ==========================================================================
       
   234 void CContainerStoreEncryption::DecryptL( const TDesC8& aEncryptedBuffer,
       
   235                                           TDes8&        aUnencryptedBuffer )
       
   236     {
       
   237     __LOG_ENTER_SUPPRESS( "DecryptL" )
       
   238     
       
   239     CheckForAuthenticationL();
       
   240 
       
   241     __LOG_HEX_DUMP_DEBUG1( "before", aEncryptedBuffer )
       
   242             
       
   243     EncryptL( aEncryptedBuffer, aUnencryptedBuffer );
       
   244     
       
   245     __LOG_HEX_DUMP_DEBUG1( "after", aUnencryptedBuffer )
       
   246             
       
   247     } // end DecryptL
       
   248 
       
   249 // ==========================================================================
       
   250 // FUNCTION: EncryptL
       
   251 // ==========================================================================
       
   252 void CContainerStoreEncryption::EncryptL( const TDesC8& aUnencryptedBuffer,
       
   253                                           TDes8&        aEncryptedBuffer )
       
   254     {
       
   255     __LOG_ENTER_SUPPRESS( "EncryptL" )
       
   256     
       
   257     CheckForAuthenticationL();
       
   258 
       
   259     __LOG_HEX_DUMP_DEBUG1( "before", aUnencryptedBuffer )
       
   260             
       
   261     // Use a dummy encryption method (i.e. just XOR a fixed value to each byte).
       
   262     aEncryptedBuffer.SetLength( 0 );    
       
   263     for( TInt i = 0 ; i < aUnencryptedBuffer.Length(); i++ )
       
   264         {
       
   265         aEncryptedBuffer.Append( aUnencryptedBuffer[i] ^ 0xA7 );        
       
   266         }
       
   267         
       
   268     __LOG_HEX_DUMP_DEBUG1( "after", aEncryptedBuffer )
       
   269             
       
   270     } // end EncryptL
       
   271 
       
   272 // ==========================================================================
       
   273 // FUNCTION: RemovePaddingL
       
   274 // ==========================================================================
       
   275 void CContainerStoreEncryption::RemovePaddingL( TDes8& aBuffer )
       
   276     {
       
   277     TUint8 padChar = aBuffer[aBuffer.Length()-1];
       
   278     
       
   279     TInt newLength = aBuffer.Length() - padChar;        
       
   280     
       
   281     if( newLength < 0 || aBuffer[newLength] != padChar )
       
   282         {
       
   283         User::Leave( KErrCorrupt );
       
   284         }
       
   285     else
       
   286         {            
       
   287         aBuffer.SetLength( newLength );        
       
   288         } // end if
       
   289     
       
   290     } // end RemovePaddingL
       
   291         
       
   292 // ==========================================================================
       
   293 // FUNCTION: AddPaddingL
       
   294 // ==========================================================================
       
   295 void CContainerStoreEncryption::AddPaddingL( TDes8& aBuffer,
       
   296                                              TInt   aBlockLength )
       
   297     {
       
   298     TUint8 padChar = aBlockLength - (aBuffer.Length() % aBlockLength);        
       
   299     
       
   300     aBuffer.SetLength( aBuffer.Length() + padChar );
       
   301     aBuffer.RightTPtr(padChar).Fill( padChar );
       
   302         
       
   303     } // end AddPaddingL
       
   304 
       
   305 // ==========================================================================
       
   306 // FUNCTION: BlockSizeL
       
   307 // ==========================================================================
       
   308 TInt CContainerStoreEncryption::BlockSizeL()
       
   309     {
       
   310     CheckForAuthenticationL();
       
   311     
       
   312     const TUint KBlockSize = 16;
       
   313     return KBlockSize;    
       
   314     } // end BlockSize
       
   315 
       
   316 // ==========================================================================
       
   317 // FUNCTION: PasswordToEncryptionKeyL
       
   318 // ==========================================================================
       
   319 void CContainerStoreEncryption::PasswordToEncryptionKeyL( const TDesC& aPassword, RBuf8& aEncryptionKey )
       
   320     {
       
   321     const TInt   KMinimumEncryptionKeyLength = 16;
       
   322     const TUint8 KPadChar                    = 'x';
       
   323 
       
   324     // Allocate the encryption key buffer.  (Not that aPassword.Length * 2 is used to account for Unicode
       
   325     // to UTF conversions.  In some worst case situations, the password could be truncated if certain
       
   326     // characters are present, but that is OK for this authentication logic).
       
   327     aEncryptionKey.CreateL( Max( aPassword.Length() * 2, KMinimumEncryptionKeyLength ) );
       
   328 
       
   329     // Convert the password from Unicode to UTF-8.
       
   330    	CnvUtfConverter::ConvertFromUnicodeToUtf8( aEncryptionKey, aPassword );
       
   331 	
       
   332 	// Pad the password to the minimum length, if needed.
       
   333     if( aEncryptionKey.Length() < KMinimumEncryptionKeyLength )
       
   334         {        
       
   335         TInt padLength = KMinimumEncryptionKeyLength - aEncryptionKey.Length();
       
   336         
       
   337         aEncryptionKey.SetLength( KMinimumEncryptionKeyLength );
       
   338         aEncryptionKey.RightTPtr(padLength).Fill( KPadChar );
       
   339         } // end if
       
   340 
       
   341     } // end PasswordToEncryptionKeyL