xmlsecurityengine/xmlseccrypto/src/xmlsecc_cryptowrapper.cpp
changeset 0 e35f40988205
child 8 e65204f75c47
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/xmlsecurityengine/xmlseccrypto/src/xmlsecc_cryptowrapper.cpp	Thu Dec 17 09:29:21 2009 +0200
@@ -0,0 +1,831 @@
+/*
+* 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:  Methods that allows to encrypt and decrypt data.
+*
+*/
+
+#include <e32def.h>
+#include <string.h>
+#include <random.h>
+#include <stdlib.h>
+
+// reading different cipher algorithm
+#include <3des.h>
+#include <des.h>
+#include <rijndael.h>
+#include <nullcipher.h>
+#include <blocktransformation.h>
+#include <padding.h>
+#include <cbcmode.h>
+#include <bufferedtransformation.h>
+#include <msymmetriccipher.h>
+
+/** A port of gnu useful functions to Symbian **/
+#include "xmlsecc_config.h"
+#include "xmlsecc_globals.h"
+
+#include "xmlsec_error_flag.h"
+#include "xmlsecc_padding.h"
+
+#include "xmlsecc_cryptowrapper.h"
+
+// set block size according to "Symmetric ciphers - How To"
+//#define MAX_BLOCKSIZE 16
+const TInt KBlockSize( 8 );
+const TInt KAESBlockSize( 16 );
+
+#define CTX_MAGIC_NORMAL 0x24091964
+#define CTX_MAGIC_SECURE 0x46919042
+
+const TInt KDESKeySize( 8 );
+const TInt K3DESKeySize( 24 );
+const TInt KAESKeySize128( 16 );
+const TInt KAESKeySize192( 24 );
+const TInt KAESKeySize256( 32 );
+
+
+/* The handle structure.  */
+struct sc_cipher_handle
+{
+  int magic;
+  size_t actual_handle_size;     /* Allocated size of this handle. */
+  CSymmetricCipher* iEncryptor;				// CBlockTransformation
+  CSymmetricCipher* iDecryptor;
+  HBufC8* iKey;
+  TInt algo;
+  size_t blocksize;
+  int mode;
+  unsigned int flags;
+  HBufC8* iv; 
+  int unused;  /* in IV */
+
+};
+
+
+// Call Symbian random generator 
+void doRandomizeL(unsigned char* buffer, size_t length)
+    {  
+	HBufC8* hbuf = HBufC8::NewLC(length);   
+    TPtr8 ptr = hbuf->Des();
+    ptr.FillZ(ptr.MaxLength());
+    
+    CSystemRandom* rand=CSystemRandom::NewLC();
+    rand->GenerateBytesL(ptr);
+    memcpy(buffer, hbuf->Ptr(), length);
+    CleanupStack::PopAndDestroy(rand);    
+    CleanupStack::PopAndDestroy(hbuf);	
+    }
+
+
+/**
+  - Function: void sc_randomize (unsigned char *BUFFER, size_t LENGTH,
+           enum sc_random_level LEVEL)
+ **/
+TInt sc_randomize(unsigned char* buffer, size_t length, enum sc_random_level level)
+    {
+	TInt leaveValue( KErrNone );
+    TRAP(leaveValue, doRandomizeL (buffer, length));
+
+    if ( leaveValue != KErrNone )
+        {
+        xmlSecSetErrorFlag( leaveValue );
+        }
+    return leaveValue;
+    }
+
+/* Retrieve the block length used with algorithm A. */
+size_t sc_cipher_get_algo_blklen (int algo)
+{
+    switch (algo) {
+    	// set block size according to "Symmetric ciphers - How To"
+    	case SC_CIPHER_AES128:
+    	case SC_CIPHER_AES192: 
+    	case SC_CIPHER_AES256: 
+    	 	return KAESBlockSize;				 	
+		case SC_CIPHER_NONE:
+		case SC_CIPHER_3DES:
+		case SC_CIPHER_DES:
+		default:
+		    return KBlockSize;	// 8 bytes
+
+    }
+
+}
+
+/* Set the IV to be used for the encryption context C to IV with
+   length IVLEN.  The length should match the required length. */
+TInt
+sc_cipher_setiv( sc_cipher_hd_t c, const byte *iv, unsigned int ivlen )
+    {
+    TInt error( KErrNone );
+   
+    if( iv ) {
+    
+	    if (c->iv) 
+	    {
+	    	delete c->iv;
+	    	c->iv = NULL;
+	    }    
+    
+    
+		if( ivlen != c->blocksize )
+		{
+		/*
+		    log_info("WARNING: cipher_setiv: ivlen=%u blklen=%u\n",
+			     ivlen, (unsigned) c->blocksize );	
+		 */     		
+		}
+		if (ivlen > c->blocksize)
+		  ivlen = c->blocksize;
+
+		TInt len = ivlen;
+	 	TRAP( error, c->iv = HBufC8::NewL(ivlen) );
+        if ( error )    //!= KErrNone
+            {
+            xmlSecSetErrorFlag( error );
+            }
+	 	else
+	 	    {
+	 	    TPtrC8 ptr(iv, ivlen);
+		    *(c->iv) = ptr;   
+	 	    }
+		 
+    }
+    c->unused = 0;
+    
+    return error;
+    }
+
+/* Set the proper Symbian data structures */
+void
+cipher_encrypt_prerequisiteL (sc_cipher_hd_t c)
+{
+
+  if (c->iEncryptor)
+    return;
+  
+  	// Generate key and encryptor/decryptor
+  	CBlockTransformation* bT_encrypt = NULL;
+  	CBlockTransformation* encryptor = NULL;
+
+  	switch(c->algo)
+  	{
+  	
+		case SC_CIPHER_AES128:
+		case SC_CIPHER_AES192:
+		case SC_CIPHER_AES256:
+			bT_encrypt = CAESEncryptor::NewLC(c->iKey->Des());			
+			CleanupStack::Pop(bT_encrypt);		
+		 	break;			 	
+		case SC_CIPHER_3DES:
+			bT_encrypt = C3DESEncryptor::NewLC(c->iKey->Des());
+			CleanupStack::Pop(bT_encrypt);			
+			break;
+		case SC_CIPHER_DES:
+			bT_encrypt = CDESEncryptor::NewLC(c->iKey->Des());
+			CleanupStack::Pop(bT_encrypt);	
+			break;		
+  		case SC_CIPHER_NONE:
+		 	c->iEncryptor = CNullCipher::NewL();
+			break;	  	
+		default:
+			User::Leave(KErrNotSupported);
+		    break;	  		
+  	}
+  	
+  	switch (c->mode)
+  	{
+  		case SC_CIPHER_MODE_ECB:
+  			break;
+      	case SC_CIPHER_MODE_CBC:
+						
+			CleanupStack::PushL(bT_encrypt);			
+			encryptor = CModeCBCEncryptor::NewLC(bT_encrypt, c->iv->Des());		
+			CleanupStack::Pop(encryptor);		
+			CleanupStack::Pop(bT_encrypt);	
+									
+	  		break;
+  		default:
+  			break;
+  	}
+  	
+	CleanupStack::PushL(encryptor);
+
+	if (!c->iEncryptor)
+	{
+		if (!encryptor)
+			{
+			User::Leave(KErrGeneral);
+			}
+		CPadding* ePadding = CXmlSecPadding::NewLC(encryptor->BlockSize());
+		c->iEncryptor = CBufferedEncryptor::NewL(encryptor, ePadding);
+		CleanupStack::Pop(ePadding);
+		
+	}
+
+	CleanupStack::Pop(encryptor); 	
+}
+
+
+static TInt
+cipher_encrypt_doProcessL (sc_cipher_hd_t c, byte *outbuf, const byte *inbuf,
+		unsigned int nbytes, int last)
+    {
+	TInt rc(KErrNone);
+	
+    switch( c->mode ) {
+    
+	  case SC_CIPHER_MODE_ECB:
+      case SC_CIPHER_MODE_CBC:
+        {
+        TUint blockSize = c->iEncryptor->BlockSize();     
+	 	 
+		if ((c->mode == SC_CIPHER_MODE_CBC) 
+				&& (nbytes%blockSize && !last)
+	            && !(nbytes > blockSize
+	                && (c->flags & SC_CIPHER_CBC_CTS)))
+		{
+			rc = KErrArgument;
+		}
+		else if ((c->mode == SC_CIPHER_MODE_ECB) 
+					&& (nbytes%blockSize && !last))
+		{
+			rc = KErrArgument;	
+		}
+		else 
+		{
+			TInt outlen;
+			if (last)
+				outlen = c->iEncryptor->MaxFinalOutputLength(nbytes);
+			else
+				outlen = c->iEncryptor->MaxOutputLength(nbytes);
+			HBufC8 *result = HBufC8::NewLC(outlen);
+			TPtr8 resultActual= result->Des();
+			resultActual.FillZ(resultActual.MaxLength());
+			resultActual.SetLength(0);
+			
+			// could improve memory usage later by allocating a smaller buffer
+			HBufC8 *input = HBufC8::NewLC(nbytes);
+			TPtrC8 inbufPtr(inbuf, nbytes);
+			*input = inbufPtr;
+		   
+		    TInt j(0);
+			for(; j+blockSize<nbytes; j+=blockSize)
+			{//	encryption in blocks of size blocksize
+				c->iEncryptor->Process(input->Mid(j,blockSize), resultActual);
+			}
+		
+			if (last)	
+			{
+				c->iEncryptor->ProcessFinalL(input->Mid(j), resultActual);
+				// we delete iEncryptor once the decryption finishes
+				// so that the next decryption can use a different key or iv
+				delete c->iEncryptor;
+				c->iEncryptor = NULL;		
+			}
+			else
+				c->iEncryptor->Process(input->Mid(j,blockSize), resultActual);
+			
+			memcpy(outbuf, result->Ptr(), result->Size());
+			CleanupStack::PopAndDestroy(input);
+			CleanupStack::PopAndDestroy(result);
+	    }
+        }	
+	break;
+	/*
+      case SC_CIPHER_MODE_CFB:
+	do_cfb_encrypt(c, outbuf, inbuf, nbytes );
+	break;
+      case SC_CIPHER_MODE_CTR:
+	do_ctr_encrypt(c, outbuf, inbuf, nbytes );
+	break;
+      case SC_CIPHER_MODE_STREAM:
+        c->cipher->stencrypt ( &c->context.c,
+                               outbuf, (byte*)inbuf, nbytes );
+        break;
+      case SC_CIPHER_MODE_NONE:
+	if( inbuf != outbuf )
+	    memmove( outbuf, inbuf, nbytes );
+	break;
+	*/
+      default:
+        rc = KErrNotSupported;
+        break;
+        
+    }
+
+	return rc;		
+    }
+
+/****************
+ * Encrypt INBUF to OUTBUF with the mode selected at open.
+ * inbuf and outbuf may overlap or be the same.
+ * Depending on the mode some contraints apply to NBYTES.
+ */
+static TInt
+cipher_encrypt (sc_cipher_hd_t c, byte *outbuf,
+		const byte *inbuf, unsigned int nbytes, int last)
+{
+	TInt leaveValue;
+	TInt ret(KErrNone);
+	    
+	// Perform Symbian prerequisite data structure initialization
+    TRAP(leaveValue, cipher_encrypt_prerequisiteL (c));
+	if (leaveValue) //!= KErrNone;
+	    {
+	    xmlSecSetErrorFlag( leaveValue );
+		return leaveValue;
+	    }
+	
+	// Symbian encryption
+	TRAP(leaveValue, ret=cipher_encrypt_doProcessL (c, outbuf, inbuf, nbytes, last));
+	if (leaveValue) //!= KErrNone
+	    {
+	    xmlSecSetErrorFlag( leaveValue );
+		return leaveValue;
+	    }
+    return ret;
+}
+
+/****************
+ * Encrypt IN and write it to OUT.  If IN is NULL, in-place encryption has
+ * been requested.
+ */
+int
+sc_cipher_encrypt (sc_cipher_hd_t h, void *out, size_t outsize,
+                     const void *in, size_t inlen, int last)
+{
+  int err;
+
+  if (!in)
+    /* Caller requested in-place encryption. */
+    /* Actullay cipher_encrypt() does not need to know about it, but
+     * we may change this to get better performance. */
+    
+    err = cipher_encrypt (h, (byte *)out, (byte *)out, outsize, last);
+  else if (outsize < ((h->flags & SC_CIPHER_CBC_MAC) ?
+                      h->blocksize : inlen))
+    err = KErrArgument;
+  else if ((h->mode == SC_CIPHER_MODE_ECB
+	    || (h->mode == SC_CIPHER_MODE_CBC
+		&& (! ((h->flags & SC_CIPHER_CBC_CTS)
+		       && (inlen > h->blocksize)))))
+	   && ((inlen % h->blocksize) && !last))	// let Symbian do the padding
+    err = KErrArgument;
+  else
+    err = cipher_encrypt (h, (byte *)out, (byte *)in, inlen, last);
+  
+  if (err && out)
+    memset (out, 0x42, outsize); /* Failsafe: Make sure that the
+                                    plaintext will never make it into
+                                    OUT. */
+
+  return err;
+}
+
+/* Set the proper Symbian data structures */
+void
+cipher_decrypt_prerequisiteL (sc_cipher_hd_t c)
+{
+
+  if (c->iDecryptor)
+    return;
+  
+  	// Generate key and encryptor/decryptor
+  	CBlockTransformation* bT_decrypt = NULL;
+  	CBlockTransformation* decryptor = NULL;
+
+  	switch(c->algo)
+  	{
+  	
+		case SC_CIPHER_AES128:
+		case SC_CIPHER_AES192:
+		case SC_CIPHER_AES256:		
+			bT_decrypt = CAESDecryptor::NewLC(c->iKey->Des());
+			CleanupStack::Pop(bT_decrypt);		
+		 	break;			 
+		case SC_CIPHER_3DES:
+			bT_decrypt = C3DESDecryptor::NewLC(c->iKey->Des());
+			CleanupStack::Pop(bT_decrypt);	
+			break;
+		case SC_CIPHER_DES:
+			bT_decrypt = CDESDecryptor::NewLC(c->iKey->Des());
+			CleanupStack::Pop(bT_decrypt);	
+			break;		
+  		case SC_CIPHER_NONE:
+			c->iDecryptor = CNullCipher::NewL();
+			break;	  	
+		default:
+			User::Leave(KErrNotSupported);
+		    break;	  		
+  	}
+  	
+  	switch (c->mode)
+  	{
+  		case SC_CIPHER_MODE_ECB:
+  			break;
+      	case SC_CIPHER_MODE_CBC:						
+			CleanupStack::PushL(bT_decrypt);
+			decryptor = CModeCBCDecryptor::NewLC(bT_decrypt, c->iv->Des());		
+			CleanupStack::Pop(decryptor);	
+			CleanupStack::Pop(bT_decrypt);	
+									
+	  		break;
+  		default:
+  			break;
+  	}
+  	
+	CleanupStack::PushL(decryptor);
+
+	if (!c->iDecryptor)
+	{
+		if (!decryptor)
+			{
+			User::Leave(KErrGeneral);
+			}
+		CPadding* dPadding = CXmlSecPadding::NewLC(decryptor->BlockSize());
+		c->iDecryptor = CBufferedDecryptor::NewL(decryptor, dPadding);
+		CleanupStack::Pop(dPadding);
+		
+	}
+
+	CleanupStack::Pop(decryptor); 	
+}
+
+static TInt
+cipher_decrypt_doProcessL (sc_cipher_hd_t c, byte *outbuf, const byte *inbuf,
+		unsigned int nbytes, int* outputLen, int last)
+    {
+	TInt rc(KErrNone);
+	
+    switch( c->mode ) {
+	  case SC_CIPHER_MODE_ECB:
+      case SC_CIPHER_MODE_CBC:
+        {
+        TUint blockSize = c->iDecryptor->BlockSize();     
+	 	 
+		if ((c->mode == SC_CIPHER_MODE_CBC) 
+				&& nbytes%blockSize
+	            && !(nbytes > blockSize
+	                && (c->flags & SC_CIPHER_CBC_CTS)))
+		{
+			rc = KErrArgument;
+		}
+		else if ((c->mode == SC_CIPHER_MODE_ECB) 
+					&& nbytes%blockSize)
+		{
+			rc = KErrArgument;
+		}	
+		else
+		{
+			TInt outlen;
+			if (last)
+				outlen = c->iDecryptor->MaxFinalOutputLength(nbytes);
+			else
+				outlen = c->iDecryptor->MaxOutputLength(nbytes);			
+			HBufC8 *result = HBufC8::NewLC(outlen);
+			TPtr8 resultActual= result->Des();
+			resultActual.FillZ(resultActual.MaxLength());
+			resultActual.SetLength(0);
+			
+			//  could improve memory usage later by allocating a smaller buffer
+			HBufC8* input = HBufC8::NewLC(nbytes);
+			TPtrC8 inbufPtr(inbuf, nbytes);
+			*input = inbufPtr;
+
+		    TInt j=0;
+		    
+			for(; j+blockSize<nbytes; j+=blockSize)
+			{	//	decryption in blocks of size blocksize
+				c->iDecryptor->Process(input->Mid(j,blockSize), resultActual);
+			}			
+		
+			if (last)	
+			{
+				c->iDecryptor->ProcessFinalL(input->Mid(j), resultActual);
+				*outputLen = result->Size();
+				
+				// we delete iDecryptor once the decryption finishes
+				// so that the next decryption can use a different key or iv
+				delete c->iDecryptor;
+				c->iDecryptor = NULL;		
+			}
+			else
+				c->iDecryptor->Process(input->Mid(j,blockSize), resultActual);
+			
+			memcpy(outbuf, result->Ptr(), result->Size());				
+			
+			CleanupStack::PopAndDestroy(input);
+			CleanupStack::PopAndDestroy(result);	
+			
+		}
+        }
+	break;
+	/*
+      case SC_CIPHER_MODE_CFB:
+	do_cfb_decrypt(c, outbuf, inbuf, nbytes );
+	break;
+      case SC_CIPHER_MODE_CTR:
+	do_ctr_decrypt(c, outbuf, inbuf, nbytes );
+	break;
+      case SC_CIPHER_MODE_STREAM:
+        c->cipher->stdecrypt ( &c->context.c,
+                               outbuf, (byte*) inbuf, nbytes );
+        break;
+      case SC_CIPHER_MODE_NONE:
+	if( inbuf != outbuf )
+	    memmove( outbuf, inbuf, nbytes );
+	break;
+	    */
+      default:
+        rc = KErrNotSupported;
+        break;
+        
+    }	
+    
+    return rc;
+    }
+
+/****************
+ * Decrypt INBUF to OUTBUF with the mode selected at open.
+ * inbuf and outbuf may overlap or be the same.
+ * Depending on the mode some some contraints apply to NBYTES.
+ */
+static TInt
+cipher_decrypt (sc_cipher_hd_t c, byte *outbuf, const byte *inbuf,
+		unsigned int nbytes, int *outlen, int last)
+{
+    TInt rc( KErrNone );
+    TInt leaveValue;
+
+	// Perform Symbian prerequisite data structure initialization
+    TRAP(leaveValue, cipher_decrypt_prerequisiteL (c));
+	if (leaveValue != KErrNone)
+	    {
+	    xmlSecSetErrorFlag( leaveValue );
+		return leaveValue;
+	    }
+		
+	// Symbian decryption
+	TRAP(leaveValue, rc=cipher_decrypt_doProcessL (c, outbuf, inbuf, nbytes, outlen, last));
+	if (leaveValue != KErrNone)
+	    {
+	    xmlSecSetErrorFlag( leaveValue );
+	    return leaveValue;
+	    }
+    return rc;
+}
+
+
+
+int
+sc_cipher_decrypt (sc_cipher_hd_t h, void *out, size_t outsize,
+		     const void *in, size_t inlen, int* outlen, int last)
+{
+  TInt err( KErrNone );
+
+  if (last && !outlen)
+    err = KErrArgument;
+  else if (! in)
+    /* Caller requested in-place encryption. */
+    /* Actullay cipher_encrypt() does not need to know about it, but
+     * we may chnage this to get better performance. */
+    err = cipher_decrypt (h, (byte*)out, (byte*)out, outsize, outlen, last);
+  else if (inlen == 0)
+    return err;
+  else if (outsize < inlen)
+    err = KErrArgument;
+  else if (((h->mode == SC_CIPHER_MODE_ECB)
+	    || ((h->mode == SC_CIPHER_MODE_CBC)
+		&& (! ((h->flags & SC_CIPHER_CBC_CTS)
+		       && (inlen > h->blocksize)))))
+	   && (inlen % h->blocksize))
+    err = KErrArgument;
+  else
+    err = cipher_decrypt (h, (byte*)out, (byte*)in, inlen, outlen, last);
+
+  return err;
+}
+
+/*
+   Open a cipher handle for use with cipher algorithm ALGORITHM, using
+   the cipher mode MODE (one of the SC_CIPHER_MODE_*) and return a
+   handle in HANDLE.  Put NULL into HANDLE and return an error code if
+   something goes wrong.  FLAGS may be used to modify the
+   operation.  The defined flags are:
+
+   SC_CIPHER_SECURE:  allocate all internal buffers in secure memory.
+   SC_CIPHER_ENABLE_SYNC:  Enable the sync operation as used in OpenPGP.
+   SC_CIPHER_CBC_CTS:  Enable CTS mode.
+   SC_CIPHER_CBC_MAC:  Enable MAC mode.
+
+   Values for these flags may be combined using OR.
+ */
+TInt 
+sc_cipher_open (sc_cipher_hd_t *handle,
+		  int algo, int mode, unsigned int flags)
+{
+  int secure = (flags & SC_CIPHER_SECURE);
+  CSymmetricCipher* encryptor = NULL;	//CBlockTransformation
+  CSymmetricCipher* decryptor = NULL;
+  sc_cipher_hd_t h = NULL;
+  TInt err( KErrNone );
+
+  /* If the application missed to call the random poll function, we do
+     it here to ensure that it is used once in a while. */
+  
+  /* check flags */
+  if ((! err)
+      && ((flags & ~(0 
+		     | SC_CIPHER_SECURE
+		     | SC_CIPHER_ENABLE_SYNC
+		     | SC_CIPHER_CBC_CTS
+		     | SC_CIPHER_CBC_MAC))
+	  || (flags & SC_CIPHER_CBC_CTS & SC_CIPHER_CBC_MAC)))
+    err = KErrArgument;
+
+  /* check that a valid mode has been requested */
+  if (! err)
+    switch (mode)
+      {//
+      case SC_CIPHER_MODE_ECB:
+      case SC_CIPHER_MODE_CBC:
+      case SC_CIPHER_MODE_CFB:
+      case SC_CIPHER_MODE_CTR:
+      case SC_CIPHER_MODE_STREAM:
+	break;
+      case SC_CIPHER_MODE_NONE:
+	break;
+
+      default:
+	err = KErrNotSupported;
+      }
+
+
+  if (! err)
+    {
+	size_t size = sizeof(*h);
+	h = (sc_cipher_hd_t)malloc(size);
+	
+    if ( !h )
+        {
+	    err = KErrNoMemory;
+        xmlSecSetErrorFlag( KErrNoMemory );
+        }
+      else
+	{
+	  h->magic = secure ? CTX_MAGIC_SECURE : CTX_MAGIC_NORMAL;
+          h->actual_handle_size = size;
+	  h->iEncryptor = encryptor;
+	  h->iDecryptor = decryptor;
+	  h->iKey = NULL;
+	  h->algo = algo;  
+	  h->iv = NULL;
+
+	  h->mode = mode;
+	  h->flags = flags;
+	  
+	  if (algo == SC_CIPHER_NONE)
+	  {
+	  TRAPD(leaveValue,h->iEncryptor = CNullCipher::NewL());
+            if (leaveValue) //!= KErrNone
+                {
+                xmlSecSetErrorFlag( leaveValue );
+                return leaveValue;
+                }	
+            TRAP(leaveValue,h->iDecryptor = CNullCipher::NewL());
+            if (leaveValue) //!= KErrNone
+                {
+                xmlSecSetErrorFlag( leaveValue );
+                return leaveValue;
+                }	
+            	  	
+	  }
+	}
+    }
+
+  *handle = err ? NULL : h;
+
+  return err;
+}
+
+
+/* Release all resources associated with the cipher handle H. H may be
+   NULL in which case this is a no-operation. */
+void
+sc_cipher_close (sc_cipher_hd_t h)
+{
+  if (! h)
+    return;
+
+  if ((h->magic != CTX_MAGIC_SECURE)
+      && (h->magic != CTX_MAGIC_NORMAL))
+  {
+  /*
+    _sc_fatal_error(GPG_ERR_INTERNAL,
+		      "sc_cipher_close: already closed/invalid handle");  
+  */	
+     return;
+  }
+
+  else
+    h->magic = 0;
+
+  if (h->iEncryptor)
+  {
+  	delete h->iEncryptor;
+  	h->iEncryptor = NULL;
+  }
+  
+  if (h->iDecryptor)
+  {
+  	delete h->iDecryptor;
+  	h->iDecryptor = NULL;
+  }
+  
+  if (h->iv)
+  {
+  	delete h->iv;
+  	h->iv = NULL;
+  }
+  
+  if (h->iKey)
+  {
+  	delete h->iKey;
+  	h->iKey = NULL;
+  }
+  
+
+  /* We always want to wipe out the memory even when the context has
+     been allocated in secure memory.  The user might have disabled
+     do the wiping.  To accomplish this we need to keep track of the
+     actual size of this structure because we have no way to known
+     how large the allocated area was when using a standard malloc. */
+  /*
+  TInt len = h->actual_handle_size;
+  memset(h, 'a', len);	// fill with something
+  */
+
+  free (h);
+}
+
+size_t
+sc_cipher_get_algo_keylen (int algo) 
+{
+  switch (algo) {
+
+	case SC_CIPHER_AES128:
+	 	return KAESKeySize128;
+	case SC_CIPHER_AES192:
+	 	return KAESKeySize192;
+	case SC_CIPHER_AES256:
+	 	return KAESKeySize256;	 		 	
+	case SC_CIPHER_3DES:
+		return K3DESKeySize;
+	case SC_CIPHER_DES:
+		return KDESKeySize;
+	case SC_CIPHER_NONE:		
+	default:
+	    return 0;	
+
+  }
+
+}
+
+
+/* Set the key to be used for the encryption context C to KEY with
+   length KEYLEN.  The length should match the required length. */
+//sc_error_t
+TInt sc_cipher_setkey (sc_cipher_hd_t c, byte *key, unsigned int keylen)
+    {
+    
+    // Change key into the right format
+    TRAPD(error, c->iKey = HBufC8::NewL(keylen));
+    if(error == KErrNone)
+        {
+        TPtrC8 keyPtr(key, keylen);
+        *(c->iKey) = keyPtr;
+        }
+    else 
+        {
+        xmlSecSetErrorFlag( error );
+        }
+    return error;
+    }
+
+/* Set specification blocksize in context */
+void set_ctx_blocksize(sc_cipher_hd_t c, size_t bklen)
+{
+	c->blocksize = bklen;
+}