stdlibs/libcrypt/src/encrypt.cpp
changeset 0 e4d67989cc36
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stdlibs/libcrypt/src/encrypt.cpp	Tue Feb 02 02:01:42 2010 +0200
@@ -0,0 +1,454 @@
+/*
+* Copyright (c) 2005-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:  Contains implementation for encryption/decryption.
+*
+*/
+
+
+// INCLUDE FILES
+
+#define EMULATOR ((defined(__WINS__) || defined(__WINSCW__)))
+
+#include <e32def.h>
+//#include <des.h>
+#include <hash.h>
+#include <errno.h>
+#include <string.h>
+
+// EXTERNAL FUNCTION PROTOTYPES
+extern "C" char *crypt_des(const char *key, const char *setting);
+extern "C" char *crypt_md5(const char *pw, const char *salt);
+
+// LOCAL CONSTANTS AND MACROS
+#define BYTE_SIZE	8
+#define ENCRYPTION  0
+#define DECRYPTION  1
+
+// STATIC DATA
+#if !EMULATOR
+TBuf8<BYTE_SIZE> desKey;				// For persistence between calls 
+										// to setkey() and encrypt()
+static TInt bSetkeyInvoked = 0;
+#else
+#include <sys/types.h>
+#include "wsd_solution.h"
+#define bSetkeyInvoked (GetGlobals()->bSetkeyInvoked)
+#endif
+
+// LOCAL FUNCTION PROTOTYPES
+static unsigned char GetByte(const char *bitVector);
+static void DesEncryptionL(const TDes8& aKey, TDes8& aInputBlock);
+static void DesDecryptionL(const TDes8& aKey, TDes8& aInputBlock);
+
+// LOCAL class declaration
+class CEncDecHack : public CBase
+{
+public:
+	virtual void Transform(TDes8& aBlock){}
+};
+
+typedef CEncDecHack* (*LookupFuncEncDecObjCreator)(const TDesC8& aKey, TBool aCheckWeakKey);
+
+_LIT(KCryptoDll,"cryptography.dll");
+
+// -----------------------------------------------------------------------------
+// function_name: _setkey
+//
+// Prepares a byte array for the key from the contents of the incoming bit vector.
+// Key thus constructed is statically stored for use during encryption/decryption.
+//
+// Returns: void
+// -----------------------------------------------------------------------------
+//
+extern "C"
+void _setkey (const char *key)
+{
+#if !EMULATOR
+    // Reset the contents of the 'key' descriptor
+    desKey.Delete(0,desKey.Length());
+#endif
+
+#if !EMULATOR    
+	// Pack the contents of the bit vector into a TDes derived object
+	for( int i = 0 ; i < BYTE_SIZE ; ++i)
+	{
+		desKey.Append( GetByte( &key[i * BYTE_SIZE] ) );
+	}
+#else
+	for(int i=0 ; i<64 ; ++i)
+	{
+		(GetGlobals()->desKey)[i] = key[i];
+	}
+#endif
+
+	bSetkeyInvoked = 1;
+}
+
+// -----------------------------------------------------------------------------
+// function_name: _encrypt
+//
+// Performs either encryption or decryption of the data block. Prior to invoking
+// Symbian OS cryptography APIs for encryptions/decryption, this function
+// packs the contents of the bit vector into a byte array of size eight. The byte
+// array obtained after encryption/decryption is unpacked to present the output
+// in the form of a bit vector. The incoming data block is modified in place 
+// during the process.
+//
+// Assumption: User of the libcrypt library is expected the create a cleanupstack
+//
+// Returns: void
+// -----------------------------------------------------------------------------
+//
+extern "C"
+void _encrypt (char block[], int edflag)
+{
+#if EMULATOR
+	TBuf8<BYTE_SIZE> desKey;
+#endif
+
+	// Determine if setkey() is invoked by the user
+	if(!bSetkeyInvoked)
+	{
+		// Initialize the key with default values
+		for(int i = 0 ; i < BYTE_SIZE ; ++i)
+		{
+			desKey.Append((unsigned char)0);
+		}
+		bSetkeyInvoked = 1;
+	}
+#if EMULATOR
+	else
+	{
+		for(int i=0 ; i<BYTE_SIZE ; ++i)
+		{
+			desKey.Append( GetByte( (const char*)&(GetGlobals()->desKey)[i * BYTE_SIZE] ));
+		}
+	}
+#endif
+
+	// Determine whether encryption or decryption is requested
+	if(edflag != ENCRYPTION)
+	{
+		if(edflag != DECRYPTION)
+		{
+			// Unrecognized flag parameter
+			errno = EPERM;
+			return;
+		}
+	}
+	
+	// Pack the contents of the input bit vector into a "byte" array
+	TBuf8<BYTE_SIZE> inputBlock;
+	TInt nIterator;
+	for(nIterator = 0 ; nIterator < BYTE_SIZE ; ++nIterator)
+	{
+		inputBlock.Append( GetByte( &block[nIterator * BYTE_SIZE] ) );
+	}
+	
+	TInt error = KErrNone;
+	typedef void (*DesOperation)(const TDes8&, TDes8&);
+	DesOperation funcOperationL = NULL;
+
+	switch(edflag)
+	{
+		case ENCRYPTION:		  // Encryption
+		funcOperationL = DesEncryptionL;
+		break;
+
+		case DECRYPTION:		  // Decryption
+		funcOperationL = DesDecryptionL;
+		break;
+	}
+
+	TRAP(error, (*funcOperationL)(desKey, inputBlock));
+	
+	if(error == KErrNone)
+	{
+		unsigned char chTemp;
+		int k = 0;
+
+		// Create the bit vector from the "byte" array (unpack)
+		for(int i = 0 ; i < BYTE_SIZE ; ++i)
+		{
+			chTemp = inputBlock[i];
+			for(int j = 0 ; j < BYTE_SIZE ; ++j)
+			{
+				block[k++] = ((chTemp & 0x80) >> 7);
+				chTemp <<= 1;
+			}
+		}
+	}
+	else
+	{
+		// Set the errno flag to indicate failure
+		errno = EPERM;
+	}
+}
+
+// -----------------------------------------------------------------------------
+// function_name: _crypt
+//
+// Uses MD5-based algorithm or DES encryption mechanism to encode a constant
+// string using "key" as the key. Salt determines the algorithm to be used.
+//
+// Returns: pointer to a static data buffer containing the encoded "string"
+// -----------------------------------------------------------------------------
+//
+extern "C" 
+char* _crypt (const char *key, const char *salt)
+{
+	// Identify the algorithm to be used as part of crypt
+	if(strstr(salt, "$1$"))
+	{
+		// MD5-based algorithm
+		return crypt_md5(key, salt);
+	}
+	else
+	{
+		return crypt_des(key, salt);
+	}
+}
+
+// -----------------------------------------------------------------------------
+// function_name: GetByte
+//
+// Packs the "bits" in the bit vector into a byte
+//
+// Returns: Byte composed of the bits from the bit vector
+// -----------------------------------------------------------------------------
+//
+LOCAL_C unsigned char GetByte(const char *bitVector)
+{
+	unsigned char chTemp = 0;
+
+	for(int nIterator = 0 ; nIterator < BYTE_SIZE ; ++nIterator)
+	{
+		chTemp |= ( bitVector[nIterator] << (BYTE_SIZE - nIterator - 1) );
+	}
+	return chTemp;
+}
+
+// -----------------------------------------------------------------------------
+// function_name: DesEncryptionL
+//
+// Function to encrypt the input data bytes by invoking Symbian OS API for
+// DES algorithm for encryption
+//
+// Assumption: 1. BLOCKSIZE within the cryptography library is 8 for 
+// 				  DES encryption
+//			   2. The input key is not checked against a set of known
+//				  weak key values
+//
+// Returns: void, however, this function leaves if there is insufficient
+//          memory
+// -----------------------------------------------------------------------------
+//
+LOCAL_C void DesEncryptionL(const TDes8& aKey, TDes8& aInputBlock)
+{
+	// Construct the encryptor object
+/*	CDESEncryptor *pEncryptor = CDESEncryptor::NewL(aKey, EFalse);
+	
+	if(!pEncryptor)
+	{
+		User::Leave(KErrNoMemory);
+	}
+	
+	// Invoke DES trasnformation to encrypt the input data
+	pEncryptor->Transform(aInputBlock);
+	
+	delete pEncryptor;
+*/
+	RLibrary library;
+    User::LeaveIfError(library.Load(KCryptoDll));
+    
+    #ifdef __WINSCW__
+   	TLibraryFunction func = library.Lookup(102); // CDESEncryptor::NewL
+    #else
+    TLibraryFunction func = library.Lookup(59);  //CDESEncryptor::NewL
+	#endif // ifdef __WINSCW__
+	
+    if (func == NULL)
+    {
+        library.Close();
+        User::Leave(KErrNotFound);
+    }
+    LookupFuncEncDecObjCreator  objCreatorFuncion = reinterpret_cast<LookupFuncEncDecObjCreator> (func);
+    CEncDecHack* pEncryptor = reinterpret_cast<CEncDecHack*>(objCreatorFuncion(aKey, EFalse));
+    pEncryptor->Transform(aInputBlock);
+    delete pEncryptor;
+    library.Close();
+}
+
+// -----------------------------------------------------------------------------
+// function_name: DesDecryptionL
+//
+// Function to encrypt the input data bytes by invoking Symbian OS API for
+// DES algorithm for decryption
+//
+// Assumption: 1. BLOCKSIZE within the cryptography library is 8 for 
+// 				  DES decryption
+//			   2. The input key is not checked against a set of known
+//				  weak key values
+//
+// Returns: void, however, this function leaves if there is insufficient
+//          memory
+// -----------------------------------------------------------------------------
+//
+LOCAL_C void DesDecryptionL(const TDes8& aKey, TDes8& aInputBlock)
+{
+	// Construct the decryptor object
+/*	CDESDecryptor *pDecryptor = CDESDecryptor::NewL(aKey, EFalse);
+	
+	if(!pDecryptor)
+	{
+		User::Leave(KErrNoMemory);
+	}
+	
+	// Invoke DES decryption on the cipher text
+	pDecryptor->Transform(aInputBlock);
+	
+	delete pDecryptor;
+*/
+    RLibrary library;
+    User::LeaveIfError(library.Load(KCryptoDll));
+    
+	#ifdef __WINSCW__
+    TLibraryFunction func = library.Lookup(101); // CDESDecryptor::NewL
+	#else
+    TLibraryFunction func = library.Lookup(57);  //CDESDecryptor::NewL
+	#endif // ifdef __WINSCW
+	
+    if (func == NULL)
+    {
+        library.Close();
+        return;
+    }
+    LookupFuncEncDecObjCreator  objCreatorFuncion = reinterpret_cast<LookupFuncEncDecObjCreator> (func);
+    CEncDecHack* pDecryptor = reinterpret_cast<CEncDecHack*>(objCreatorFuncion(aKey, EFalse));
+    pDecryptor->Transform(aInputBlock);
+    delete pDecryptor;
+    library.Close();
+}
+
+extern "C" {
+
+// -----------------------------------------------------------------------------
+// function_name: Deallocate2DimensionalUchar
+//
+// To deallocate storage alloted for the two dimensional array
+//
+// Returns: void
+// -----------------------------------------------------------------------------
+//
+void Deallocate2DimensionalUchar(unsigned char **buffer, int row)
+{
+		int m;
+		for(m=0 ; m<row ; ++m)
+		{
+			User::Free((TAny *)buffer[m]);
+		}
+		User::Free((TAny *)buffer);
+}
+	
+// -----------------------------------------------------------------------------
+// function_name: Deallocate2DimensionalUint
+//
+// To deallocate storage alloted for the two dimensional array
+//
+// Returns: void
+// -----------------------------------------------------------------------------
+//
+void Deallocate2DimensionalUint(__uint32_t **buffer, int row)
+{
+		int m;
+		for(m=0 ; m<row ; ++m)
+		{
+			User::Free((TAny *)buffer[m]);
+		}
+		User::Free((TAny *)buffer);
+}
+
+// -----------------------------------------------------------------------------
+// function_name: Allocate2DimensionalUchar
+//
+// Function to allocate storage for a two dimensional array from the heap. 
+// If heap exhaustion occurs during the course of allocating memory to the array,
+// the previously allocated storage will be deleted prior to returning to the
+// caller.
+//
+// Returns: non-zero if allocation is successful, 0 if it fails
+// -----------------------------------------------------------------------------
+//
+int Allocate2DimensionalUchar(unsigned char ***buffer, int row, int column)
+{
+	*buffer = (unsigned char **)User::Alloc(row * sizeof(unsigned char *));
+	if(NULL == *buffer)
+	{
+		return 0;
+	}
+	for(int m=0 ; m<row ; ++m)
+	{
+		(*buffer)[m] = (unsigned char *)User::Alloc(column * sizeof(unsigned char));
+		if(NULL == (*buffer)[m])
+		{
+			// Insufficient heap memory
+			if(m)
+			{
+				// Deallocate the previously allocated storage
+				Deallocate2DimensionalUchar(*buffer, m);
+			}
+			return 0;
+		}
+	}
+	
+	return 1;
+}
+
+// -----------------------------------------------------------------------------
+// function_name: Allocate2DimensionalUint
+//
+// Function to allocate storage for a two dimensional array of type unsigned int
+// from the heap. If heap exhaustion occurs while allocating memory to the array,
+// the previously allocated storage will be deleted prior to returning to the
+// caller.
+//
+// Returns: non-zero if allocation is successful, 0 if it fails
+// -----------------------------------------------------------------------------
+//
+int Allocate2DimensionalUint(__uint32_t ***buffer, int row, int column)
+{
+	*buffer = (__uint32_t **)User::Alloc(row * sizeof(__uint32_t *));
+	if(NULL == *buffer)
+	{
+		return 0;
+	}
+	for(int m=0 ; m<row ; ++m)
+	{
+		(*buffer)[m] = (__uint32_t *)User::Alloc(column * sizeof(__uint32_t));
+		if(NULL == (*buffer)[m])
+		{
+			// Insufficient heap memory
+			if(m)
+			{
+				// Deallocate the previously allocated storage
+				Deallocate2DimensionalUint(*buffer, m);
+			}
+			return 0;
+		}
+	}
+	
+	return 1;
+}
+
+}	// <<end extern "C">>