emailservices/emailstore/message_store/server/src/ContainerStoreEncryption.cpp
changeset 0 8466d47a6819
child 66 084b5b1f02a7
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/emailservices/emailstore/message_store/server/src/ContainerStoreEncryption.cpp	Thu Dec 17 08:39:21 2009 +0200
@@ -0,0 +1,341 @@
+/*
+* Copyright (c) 2006 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:  Container store encryption implementation.
+*
+*/
+
+
+
+// ========
+// INCLUDES
+// ========
+
+#include <bautils.h>
+#include <utf.h>
+
+#include "ContainerStoreEncryption.h"
+#include "ContainerStoreUtils.h"
+
+class CCryptoBase: public CBase {};
+
+// =========
+// CONSTANTS
+// =========
+
+// This length is more than sufficient.
+const TInt KMaxAuthenticationBufferLength = 100;
+
+// ======================
+// METHOD IMPLEMENTATIONS
+// ======================
+
+// ==========================================================================
+// FUNCTION: NewL
+// ==========================================================================
+CContainerStoreEncryption* CContainerStoreEncryption::NewL()
+	{
+	CContainerStoreEncryption* self = new(ELeave) CContainerStoreEncryption;
+	return self;
+	} // end NewL
+	
+// ==========================================================================
+// FUNCTION: Constructor
+// ==========================================================================
+CContainerStoreEncryption::CContainerStoreEncryption() 
+: iAuthenticationRequired( EFalse ), iEncryptionFlag (EFalse)
+	{
+	__LOG_CONSTRUCT( "msg", "CContainerStoreEncryption" )
+	__LOG_CLOSE_BETWEEN_WRITES
+	} // end constructor
+	
+// ==========================================================================
+// FUNCTION: Destructor
+// ==========================================================================
+CContainerStoreEncryption::~CContainerStoreEncryption()
+	{
+    ClearAuthentication();
+	__LOG_DESTRUCT
+	} // end destructor
+	
+// ==========================================================================
+// FUNCTION: Authenticated
+// ==========================================================================
+TBool CContainerStoreEncryption::Authenticated()
+    {
+    //always return true if authentication is not required
+    return ( iCryptoLibrary != NULL || !iAuthenticationRequired ); 
+    } // end Authenticated
+
+// ==========================================================================
+// FUNCTION: ClearAuthentication
+// ==========================================================================
+void CContainerStoreEncryption::ClearAuthentication()
+    {
+    delete iCryptoLibrary;
+    iCryptoLibrary = NULL;
+    } // end ClearAuthentication  
+
+// ==========================================================================
+// FUNCTION: CreateAuthenticationBufferL
+// ==========================================================================
+void CContainerStoreEncryption::CreateAuthenticationBufferL( const TDesC& aPassword, 
+                                                             RBuf8&       aAuthenticationBuffer )
+    {
+    RBuf8 unencryptedAuthenticationBuffer;
+    unencryptedAuthenticationBuffer.CreateL( KMaxAuthenticationBufferLength );
+    CleanupClosePushL( unencryptedAuthenticationBuffer );
+    
+    if( !iCryptoLibrary )
+        {        
+        iCryptoLibrary = new(ELeave) CCryptoBase;
+        } // end if
+    
+    const TUint size = 5; 
+    HBufC8* key = HBufC8::NewL(size);
+    _LIT8( K12345, "12345" );
+    key->Des().Copy( K12345 );
+    
+    // Add the encryption key to the authentication buffer.    
+    unencryptedAuthenticationBuffer.Append( *key );
+    delete key;
+
+    RBuf8 sha1Checksum;
+    CleanupClosePushL( sha1Checksum );
+
+    // Use the password length as the "SHA-1 Checksum"
+    sha1Checksum.CreateL( 1 );
+    sha1Checksum.Append( aPassword.Length() );   
+    
+    // Add the SHA-1 checksum of the key to the authentication buffer.
+    unencryptedAuthenticationBuffer.Append( sha1Checksum );
+
+    // Add the length of the SHA-1 checksum to the authentication buffer.
+    unencryptedAuthenticationBuffer.Append( TUint8(sha1Checksum.Length()) );
+    
+    CleanupStack::PopAndDestroy( &sha1Checksum );   
+    
+    // Add PKCS5 padding to the buffer.
+    AddPaddingL( unencryptedAuthenticationBuffer, BlockSizeL() );
+                
+    // Encrypt the buffer using the given password.
+    aAuthenticationBuffer.ReAllocL( unencryptedAuthenticationBuffer.Length() );                
+    aAuthenticationBuffer.Copy( unencryptedAuthenticationBuffer );
+
+    CleanupStack::PopAndDestroy( &unencryptedAuthenticationBuffer );
+    
+    } // end DoGenerateAuthenticationBufferL
+
+// ==========================================================================
+// FUNCTION: AuthenticateL
+// ==========================================================================
+TBool CContainerStoreEncryption::AuthenticateL( const TDesC&  aPassword, 
+                                                const TDesC8& aAuthenticationBuffer )
+    {
+    TBool returnValue = EFalse;
+    
+    RBuf8 decryptedBuffer;
+    CleanupClosePushL( decryptedBuffer );
+
+    decryptedBuffer.CreateL( aAuthenticationBuffer.Length() );
+    decryptedBuffer.Copy( aAuthenticationBuffer );
+    TInt result = KErrNone;
+
+    if( result == KErrNone )
+        {            
+        // Verify that the PKCS5 padding is still intact.
+        TUint8 padLength = decryptedBuffer[decryptedBuffer.Length()-1];
+    
+        TBool paddingOk = (padLength >= 1 && padLength < aAuthenticationBuffer.Length() );
+    
+        for( TInt i = 0; paddingOk && i < padLength; i++ )
+            {
+            paddingOk = decryptedBuffer[decryptedBuffer.Length()-i-1] == padLength;
+            } // end for  
+            
+        // Verify the SHA-1 checksum of the encryption key.            
+        if( paddingOk && (padLength < decryptedBuffer.Length()) )
+            {
+            // Remove the pad characters.
+            decryptedBuffer.SetLength( decryptedBuffer.Length() - padLength );
+
+            // Get the length of the checksum.
+            TUint8 checksumLength = decryptedBuffer[decryptedBuffer.Length()-1];
+            decryptedBuffer.SetLength( decryptedBuffer.Length() - 1 ); 
+            
+            if( checksumLength < decryptedBuffer.Length() )
+                {
+                // Create a pointer to the encryption key.
+                TPtrC8 encryptionKey( decryptedBuffer.Left( decryptedBuffer.Length() - checksumLength ) );
+            
+                // Compute the expected SHA-1 checksum.
+                RBuf8 expectedChecksum;
+                CleanupClosePushL( expectedChecksum );
+                expectedChecksum.CreateL(1);
+                expectedChecksum.Append( aPassword.Length() );                                    
+
+                // Verify the SHA-1 checksum.
+                if( expectedChecksum.Compare(decryptedBuffer.Right(checksumLength)) == 0 )
+                    {
+                    // Password is OK.
+                    returnValue = ETrue;
+                                    
+                    // Save the encryption key for later use.
+                    if( !iCryptoLibrary )
+                        {
+                        iCryptoLibrary = new(ELeave) CCryptoBase;
+                        } // end if
+
+                    } // end if
+
+                CleanupStack::PopAndDestroy( &expectedChecksum );
+                
+                } // end if
+
+            } // end if
+        
+        } // end if
+            
+    CleanupStack::PopAndDestroy( &decryptedBuffer );
+
+    return returnValue;
+    
+    } // end AuthenticateL
+
+// ==========================================================================
+// FUNCTION: CheckForAuthenticationL
+// ==========================================================================
+void CContainerStoreEncryption::CheckForAuthenticationL()
+    {    
+    __LOG_ENTER_SUPPRESS( "CheckForAuthenticationL" )
+    
+    //leave if authentication is required is ON and library is NULL
+	if( !iCryptoLibrary && iAuthenticationRequired )
+	    {
+	    __LOG_WRITE_ERROR( "not authenticated" )
+	    User::Leave( KErrNotReady );
+	    } // end if
+	    
+    } // end CheckForAuthenticationL
+
+// ==========================================================================
+// FUNCTION: DecryptL
+// ==========================================================================
+void CContainerStoreEncryption::DecryptL( const TDesC8& aEncryptedBuffer,
+                                          TDes8&        aUnencryptedBuffer )
+    {
+    __LOG_ENTER_SUPPRESS( "DecryptL" )
+    
+    CheckForAuthenticationL();
+
+    __LOG_HEX_DUMP_DEBUG1( "before", aEncryptedBuffer )
+            
+    EncryptL( aEncryptedBuffer, aUnencryptedBuffer );
+    
+    __LOG_HEX_DUMP_DEBUG1( "after", aUnencryptedBuffer )
+            
+    } // end DecryptL
+
+// ==========================================================================
+// FUNCTION: EncryptL
+// ==========================================================================
+void CContainerStoreEncryption::EncryptL( const TDesC8& aUnencryptedBuffer,
+                                          TDes8&        aEncryptedBuffer )
+    {
+    __LOG_ENTER_SUPPRESS( "EncryptL" )
+    
+    CheckForAuthenticationL();
+
+    __LOG_HEX_DUMP_DEBUG1( "before", aUnencryptedBuffer )
+            
+    // Use a dummy encryption method (i.e. just XOR a fixed value to each byte).
+    aEncryptedBuffer.SetLength( 0 );    
+    for( TInt i = 0 ; i < aUnencryptedBuffer.Length(); i++ )
+        {
+        aEncryptedBuffer.Append( aUnencryptedBuffer[i] ^ 0xA7 );        
+        }
+        
+    __LOG_HEX_DUMP_DEBUG1( "after", aEncryptedBuffer )
+            
+    } // end EncryptL
+
+// ==========================================================================
+// FUNCTION: RemovePaddingL
+// ==========================================================================
+void CContainerStoreEncryption::RemovePaddingL( TDes8& aBuffer )
+    {
+    TUint8 padChar = aBuffer[aBuffer.Length()-1];
+    
+    TInt newLength = aBuffer.Length() - padChar;        
+    
+    if( newLength < 0 || aBuffer[newLength] != padChar )
+        {
+        User::Leave( KErrCorrupt );
+        }
+    else
+        {            
+        aBuffer.SetLength( newLength );        
+        } // end if
+    
+    } // end RemovePaddingL
+        
+// ==========================================================================
+// FUNCTION: AddPaddingL
+// ==========================================================================
+void CContainerStoreEncryption::AddPaddingL( TDes8& aBuffer,
+                                             TInt   aBlockLength )
+    {
+    TUint8 padChar = aBlockLength - (aBuffer.Length() % aBlockLength);        
+    
+    aBuffer.SetLength( aBuffer.Length() + padChar );
+    aBuffer.RightTPtr(padChar).Fill( padChar );
+        
+    } // end AddPaddingL
+
+// ==========================================================================
+// FUNCTION: BlockSizeL
+// ==========================================================================
+TInt CContainerStoreEncryption::BlockSizeL()
+    {
+    CheckForAuthenticationL();
+    
+    const TUint KBlockSize = 16;
+    return KBlockSize;    
+    } // end BlockSize
+
+// ==========================================================================
+// FUNCTION: PasswordToEncryptionKeyL
+// ==========================================================================
+void CContainerStoreEncryption::PasswordToEncryptionKeyL( const TDesC& aPassword, RBuf8& aEncryptionKey )
+    {
+    const TInt   KMinimumEncryptionKeyLength = 16;
+    const TUint8 KPadChar                    = 'x';
+
+    // Allocate the encryption key buffer.  (Not that aPassword.Length * 2 is used to account for Unicode
+    // to UTF conversions.  In some worst case situations, the password could be truncated if certain
+    // characters are present, but that is OK for this authentication logic).
+    aEncryptionKey.CreateL( Max( aPassword.Length() * 2, KMinimumEncryptionKeyLength ) );
+
+    // Convert the password from Unicode to UTF-8.
+   	CnvUtfConverter::ConvertFromUnicodeToUtf8( aEncryptionKey, aPassword );
+	
+	// Pad the password to the minimum length, if needed.
+    if( aEncryptionKey.Length() < KMinimumEncryptionKeyLength )
+        {        
+        TInt padLength = KMinimumEncryptionKeyLength - aEncryptionKey.Length();
+        
+        aEncryptionKey.SetLength( KMinimumEncryptionKeyLength );
+        aEncryptionKey.RightTPtr(padLength).Fill( KPadChar );
+        } // end if
+
+    } // end PasswordToEncryptionKeyL