--- /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