xmlsecurityengine/xmlseccrypto/src/xmlsecc_cryptowrapper.cpp
changeset 0 e35f40988205
child 8 e65204f75c47
equal deleted inserted replaced
-1:000000000000 0:e35f40988205
       
     1 /*
       
     2 * Copyright (c) 2005-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:  Methods that allows to encrypt and decrypt data.
       
    15 *
       
    16 */
       
    17 
       
    18 #include <e32def.h>
       
    19 #include <string.h>
       
    20 #include <random.h>
       
    21 #include <stdlib.h>
       
    22 
       
    23 // reading different cipher algorithm
       
    24 #include <3des.h>
       
    25 #include <des.h>
       
    26 #include <rijndael.h>
       
    27 #include <nullcipher.h>
       
    28 #include <blocktransformation.h>
       
    29 #include <padding.h>
       
    30 #include <cbcmode.h>
       
    31 #include <bufferedtransformation.h>
       
    32 #include <msymmetriccipher.h>
       
    33 
       
    34 /** A port of gnu useful functions to Symbian **/
       
    35 #include "xmlsecc_config.h"
       
    36 #include "xmlsecc_globals.h"
       
    37 
       
    38 #include "xmlsec_error_flag.h"
       
    39 #include "xmlsecc_padding.h"
       
    40 
       
    41 #include "xmlsecc_cryptowrapper.h"
       
    42 
       
    43 // set block size according to "Symmetric ciphers - How To"
       
    44 //#define MAX_BLOCKSIZE 16
       
    45 const TInt KBlockSize( 8 );
       
    46 const TInt KAESBlockSize( 16 );
       
    47 
       
    48 #define CTX_MAGIC_NORMAL 0x24091964
       
    49 #define CTX_MAGIC_SECURE 0x46919042
       
    50 
       
    51 const TInt KDESKeySize( 8 );
       
    52 const TInt K3DESKeySize( 24 );
       
    53 const TInt KAESKeySize128( 16 );
       
    54 const TInt KAESKeySize192( 24 );
       
    55 const TInt KAESKeySize256( 32 );
       
    56 
       
    57 
       
    58 /* The handle structure.  */
       
    59 struct sc_cipher_handle
       
    60 {
       
    61   int magic;
       
    62   size_t actual_handle_size;     /* Allocated size of this handle. */
       
    63   CSymmetricCipher* iEncryptor;				// CBlockTransformation
       
    64   CSymmetricCipher* iDecryptor;
       
    65   HBufC8* iKey;
       
    66   TInt algo;
       
    67   size_t blocksize;
       
    68   int mode;
       
    69   unsigned int flags;
       
    70   HBufC8* iv; 
       
    71   int unused;  /* in IV */
       
    72 
       
    73 };
       
    74 
       
    75 
       
    76 // Call Symbian random generator 
       
    77 void doRandomizeL(unsigned char* buffer, size_t length)
       
    78     {  
       
    79 	HBufC8* hbuf = HBufC8::NewLC(length);   
       
    80     TPtr8 ptr = hbuf->Des();
       
    81     ptr.FillZ(ptr.MaxLength());
       
    82     
       
    83     CSystemRandom* rand=CSystemRandom::NewLC();
       
    84     rand->GenerateBytesL(ptr);
       
    85     memcpy(buffer, hbuf->Ptr(), length);
       
    86     CleanupStack::PopAndDestroy(rand);    
       
    87     CleanupStack::PopAndDestroy(hbuf);	
       
    88     }
       
    89 
       
    90 
       
    91 /**
       
    92   - Function: void sc_randomize (unsigned char *BUFFER, size_t LENGTH,
       
    93            enum sc_random_level LEVEL)
       
    94  **/
       
    95 TInt sc_randomize(unsigned char* buffer, size_t length, enum sc_random_level level)
       
    96     {
       
    97 	TInt leaveValue( KErrNone );
       
    98     TRAP(leaveValue, doRandomizeL (buffer, length));
       
    99 
       
   100     if ( leaveValue != KErrNone )
       
   101         {
       
   102         xmlSecSetErrorFlag( leaveValue );
       
   103         }
       
   104     return leaveValue;
       
   105     }
       
   106 
       
   107 /* Retrieve the block length used with algorithm A. */
       
   108 size_t sc_cipher_get_algo_blklen (int algo)
       
   109 {
       
   110     switch (algo) {
       
   111     	// set block size according to "Symmetric ciphers - How To"
       
   112     	case SC_CIPHER_AES128:
       
   113     	case SC_CIPHER_AES192: 
       
   114     	case SC_CIPHER_AES256: 
       
   115     	 	return KAESBlockSize;				 	
       
   116 		case SC_CIPHER_NONE:
       
   117 		case SC_CIPHER_3DES:
       
   118 		case SC_CIPHER_DES:
       
   119 		default:
       
   120 		    return KBlockSize;	// 8 bytes
       
   121 
       
   122     }
       
   123 
       
   124 }
       
   125 
       
   126 /* Set the IV to be used for the encryption context C to IV with
       
   127    length IVLEN.  The length should match the required length. */
       
   128 TInt
       
   129 sc_cipher_setiv( sc_cipher_hd_t c, const byte *iv, unsigned int ivlen )
       
   130     {
       
   131     TInt error( KErrNone );
       
   132    
       
   133     if( iv ) {
       
   134     
       
   135 	    if (c->iv) 
       
   136 	    {
       
   137 	    	delete c->iv;
       
   138 	    	c->iv = NULL;
       
   139 	    }    
       
   140     
       
   141     
       
   142 		if( ivlen != c->blocksize )
       
   143 		{
       
   144 		/*
       
   145 		    log_info("WARNING: cipher_setiv: ivlen=%u blklen=%u\n",
       
   146 			     ivlen, (unsigned) c->blocksize );	
       
   147 		 */     		
       
   148 		}
       
   149 		if (ivlen > c->blocksize)
       
   150 		  ivlen = c->blocksize;
       
   151 
       
   152 		TInt len = ivlen;
       
   153 	 	TRAP( error, c->iv = HBufC8::NewL(ivlen) );
       
   154         if ( error )    //!= KErrNone
       
   155             {
       
   156             xmlSecSetErrorFlag( error );
       
   157             }
       
   158 	 	else
       
   159 	 	    {
       
   160 	 	    TPtrC8 ptr(iv, ivlen);
       
   161 		    *(c->iv) = ptr;   
       
   162 	 	    }
       
   163 		 
       
   164     }
       
   165     c->unused = 0;
       
   166     
       
   167     return error;
       
   168     }
       
   169 
       
   170 /* Set the proper Symbian data structures */
       
   171 void
       
   172 cipher_encrypt_prerequisiteL (sc_cipher_hd_t c)
       
   173 {
       
   174 
       
   175   if (c->iEncryptor)
       
   176     return;
       
   177   
       
   178   	// Generate key and encryptor/decryptor
       
   179   	CBlockTransformation* bT_encrypt = NULL;
       
   180   	CBlockTransformation* encryptor = NULL;
       
   181 
       
   182   	switch(c->algo)
       
   183   	{
       
   184   	
       
   185 		case SC_CIPHER_AES128:
       
   186 		case SC_CIPHER_AES192:
       
   187 		case SC_CIPHER_AES256:
       
   188 			bT_encrypt = CAESEncryptor::NewLC(c->iKey->Des());			
       
   189 			CleanupStack::Pop(bT_encrypt);		
       
   190 		 	break;			 	
       
   191 		case SC_CIPHER_3DES:
       
   192 			bT_encrypt = C3DESEncryptor::NewLC(c->iKey->Des());
       
   193 			CleanupStack::Pop(bT_encrypt);			
       
   194 			break;
       
   195 		case SC_CIPHER_DES:
       
   196 			bT_encrypt = CDESEncryptor::NewLC(c->iKey->Des());
       
   197 			CleanupStack::Pop(bT_encrypt);	
       
   198 			break;		
       
   199   		case SC_CIPHER_NONE:
       
   200 		 	c->iEncryptor = CNullCipher::NewL();
       
   201 			break;	  	
       
   202 		default:
       
   203 			User::Leave(KErrNotSupported);
       
   204 		    break;	  		
       
   205   	}
       
   206   	
       
   207   	switch (c->mode)
       
   208   	{
       
   209   		case SC_CIPHER_MODE_ECB:
       
   210   			break;
       
   211       	case SC_CIPHER_MODE_CBC:
       
   212 						
       
   213 			CleanupStack::PushL(bT_encrypt);			
       
   214 			encryptor = CModeCBCEncryptor::NewLC(bT_encrypt, c->iv->Des());		
       
   215 			CleanupStack::Pop(encryptor);		
       
   216 			CleanupStack::Pop(bT_encrypt);	
       
   217 									
       
   218 	  		break;
       
   219   		default:
       
   220   			break;
       
   221   	}
       
   222   	
       
   223 	CleanupStack::PushL(encryptor);
       
   224 
       
   225 	if (!c->iEncryptor)
       
   226 	{
       
   227 		if (!encryptor)
       
   228 			{
       
   229 			User::Leave(KErrGeneral);
       
   230 			}
       
   231 		CPadding* ePadding = CXmlSecPadding::NewLC(encryptor->BlockSize());
       
   232 		c->iEncryptor = CBufferedEncryptor::NewL(encryptor, ePadding);
       
   233 		CleanupStack::Pop(ePadding);
       
   234 		
       
   235 	}
       
   236 
       
   237 	CleanupStack::Pop(encryptor); 	
       
   238 }
       
   239 
       
   240 
       
   241 static TInt
       
   242 cipher_encrypt_doProcessL (sc_cipher_hd_t c, byte *outbuf, const byte *inbuf,
       
   243 		unsigned int nbytes, int last)
       
   244     {
       
   245 	TInt rc(KErrNone);
       
   246 	
       
   247     switch( c->mode ) {
       
   248     
       
   249 	  case SC_CIPHER_MODE_ECB:
       
   250       case SC_CIPHER_MODE_CBC:
       
   251         {
       
   252         TUint blockSize = c->iEncryptor->BlockSize();     
       
   253 	 	 
       
   254 		if ((c->mode == SC_CIPHER_MODE_CBC) 
       
   255 				&& (nbytes%blockSize && !last)
       
   256 	            && !(nbytes > blockSize
       
   257 	                && (c->flags & SC_CIPHER_CBC_CTS)))
       
   258 		{
       
   259 			rc = KErrArgument;
       
   260 		}
       
   261 		else if ((c->mode == SC_CIPHER_MODE_ECB) 
       
   262 					&& (nbytes%blockSize && !last))
       
   263 		{
       
   264 			rc = KErrArgument;	
       
   265 		}
       
   266 		else 
       
   267 		{
       
   268 			TInt outlen;
       
   269 			if (last)
       
   270 				outlen = c->iEncryptor->MaxFinalOutputLength(nbytes);
       
   271 			else
       
   272 				outlen = c->iEncryptor->MaxOutputLength(nbytes);
       
   273 			HBufC8 *result = HBufC8::NewLC(outlen);
       
   274 			TPtr8 resultActual= result->Des();
       
   275 			resultActual.FillZ(resultActual.MaxLength());
       
   276 			resultActual.SetLength(0);
       
   277 			
       
   278 			// could improve memory usage later by allocating a smaller buffer
       
   279 			HBufC8 *input = HBufC8::NewLC(nbytes);
       
   280 			TPtrC8 inbufPtr(inbuf, nbytes);
       
   281 			*input = inbufPtr;
       
   282 		   
       
   283 		    TInt j(0);
       
   284 			for(; j+blockSize<nbytes; j+=blockSize)
       
   285 			{//	encryption in blocks of size blocksize
       
   286 				c->iEncryptor->Process(input->Mid(j,blockSize), resultActual);
       
   287 			}
       
   288 		
       
   289 			if (last)	
       
   290 			{
       
   291 				c->iEncryptor->ProcessFinalL(input->Mid(j), resultActual);
       
   292 				// we delete iEncryptor once the decryption finishes
       
   293 				// so that the next decryption can use a different key or iv
       
   294 				delete c->iEncryptor;
       
   295 				c->iEncryptor = NULL;		
       
   296 			}
       
   297 			else
       
   298 				c->iEncryptor->Process(input->Mid(j,blockSize), resultActual);
       
   299 			
       
   300 			memcpy(outbuf, result->Ptr(), result->Size());
       
   301 			CleanupStack::PopAndDestroy(input);
       
   302 			CleanupStack::PopAndDestroy(result);
       
   303 	    }
       
   304         }	
       
   305 	break;
       
   306 	/*
       
   307       case SC_CIPHER_MODE_CFB:
       
   308 	do_cfb_encrypt(c, outbuf, inbuf, nbytes );
       
   309 	break;
       
   310       case SC_CIPHER_MODE_CTR:
       
   311 	do_ctr_encrypt(c, outbuf, inbuf, nbytes );
       
   312 	break;
       
   313       case SC_CIPHER_MODE_STREAM:
       
   314         c->cipher->stencrypt ( &c->context.c,
       
   315                                outbuf, (byte*)inbuf, nbytes );
       
   316         break;
       
   317       case SC_CIPHER_MODE_NONE:
       
   318 	if( inbuf != outbuf )
       
   319 	    memmove( outbuf, inbuf, nbytes );
       
   320 	break;
       
   321 	*/
       
   322       default:
       
   323         rc = KErrNotSupported;
       
   324         break;
       
   325         
       
   326     }
       
   327 
       
   328 	return rc;		
       
   329     }
       
   330 
       
   331 /****************
       
   332  * Encrypt INBUF to OUTBUF with the mode selected at open.
       
   333  * inbuf and outbuf may overlap or be the same.
       
   334  * Depending on the mode some contraints apply to NBYTES.
       
   335  */
       
   336 static TInt
       
   337 cipher_encrypt (sc_cipher_hd_t c, byte *outbuf,
       
   338 		const byte *inbuf, unsigned int nbytes, int last)
       
   339 {
       
   340 	TInt leaveValue;
       
   341 	TInt ret(KErrNone);
       
   342 	    
       
   343 	// Perform Symbian prerequisite data structure initialization
       
   344     TRAP(leaveValue, cipher_encrypt_prerequisiteL (c));
       
   345 	if (leaveValue) //!= KErrNone;
       
   346 	    {
       
   347 	    xmlSecSetErrorFlag( leaveValue );
       
   348 		return leaveValue;
       
   349 	    }
       
   350 	
       
   351 	// Symbian encryption
       
   352 	TRAP(leaveValue, ret=cipher_encrypt_doProcessL (c, outbuf, inbuf, nbytes, last));
       
   353 	if (leaveValue) //!= KErrNone
       
   354 	    {
       
   355 	    xmlSecSetErrorFlag( leaveValue );
       
   356 		return leaveValue;
       
   357 	    }
       
   358     return ret;
       
   359 }
       
   360 
       
   361 /****************
       
   362  * Encrypt IN and write it to OUT.  If IN is NULL, in-place encryption has
       
   363  * been requested.
       
   364  */
       
   365 int
       
   366 sc_cipher_encrypt (sc_cipher_hd_t h, void *out, size_t outsize,
       
   367                      const void *in, size_t inlen, int last)
       
   368 {
       
   369   int err;
       
   370 
       
   371   if (!in)
       
   372     /* Caller requested in-place encryption. */
       
   373     /* Actullay cipher_encrypt() does not need to know about it, but
       
   374      * we may change this to get better performance. */
       
   375     
       
   376     err = cipher_encrypt (h, (byte *)out, (byte *)out, outsize, last);
       
   377   else if (outsize < ((h->flags & SC_CIPHER_CBC_MAC) ?
       
   378                       h->blocksize : inlen))
       
   379     err = KErrArgument;
       
   380   else if ((h->mode == SC_CIPHER_MODE_ECB
       
   381 	    || (h->mode == SC_CIPHER_MODE_CBC
       
   382 		&& (! ((h->flags & SC_CIPHER_CBC_CTS)
       
   383 		       && (inlen > h->blocksize)))))
       
   384 	   && ((inlen % h->blocksize) && !last))	// let Symbian do the padding
       
   385     err = KErrArgument;
       
   386   else
       
   387     err = cipher_encrypt (h, (byte *)out, (byte *)in, inlen, last);
       
   388   
       
   389   if (err && out)
       
   390     memset (out, 0x42, outsize); /* Failsafe: Make sure that the
       
   391                                     plaintext will never make it into
       
   392                                     OUT. */
       
   393 
       
   394   return err;
       
   395 }
       
   396 
       
   397 /* Set the proper Symbian data structures */
       
   398 void
       
   399 cipher_decrypt_prerequisiteL (sc_cipher_hd_t c)
       
   400 {
       
   401 
       
   402   if (c->iDecryptor)
       
   403     return;
       
   404   
       
   405   	// Generate key and encryptor/decryptor
       
   406   	CBlockTransformation* bT_decrypt = NULL;
       
   407   	CBlockTransformation* decryptor = NULL;
       
   408 
       
   409   	switch(c->algo)
       
   410   	{
       
   411   	
       
   412 		case SC_CIPHER_AES128:
       
   413 		case SC_CIPHER_AES192:
       
   414 		case SC_CIPHER_AES256:		
       
   415 			bT_decrypt = CAESDecryptor::NewLC(c->iKey->Des());
       
   416 			CleanupStack::Pop(bT_decrypt);		
       
   417 		 	break;			 
       
   418 		case SC_CIPHER_3DES:
       
   419 			bT_decrypt = C3DESDecryptor::NewLC(c->iKey->Des());
       
   420 			CleanupStack::Pop(bT_decrypt);	
       
   421 			break;
       
   422 		case SC_CIPHER_DES:
       
   423 			bT_decrypt = CDESDecryptor::NewLC(c->iKey->Des());
       
   424 			CleanupStack::Pop(bT_decrypt);	
       
   425 			break;		
       
   426   		case SC_CIPHER_NONE:
       
   427 			c->iDecryptor = CNullCipher::NewL();
       
   428 			break;	  	
       
   429 		default:
       
   430 			User::Leave(KErrNotSupported);
       
   431 		    break;	  		
       
   432   	}
       
   433   	
       
   434   	switch (c->mode)
       
   435   	{
       
   436   		case SC_CIPHER_MODE_ECB:
       
   437   			break;
       
   438       	case SC_CIPHER_MODE_CBC:						
       
   439 			CleanupStack::PushL(bT_decrypt);
       
   440 			decryptor = CModeCBCDecryptor::NewLC(bT_decrypt, c->iv->Des());		
       
   441 			CleanupStack::Pop(decryptor);	
       
   442 			CleanupStack::Pop(bT_decrypt);	
       
   443 									
       
   444 	  		break;
       
   445   		default:
       
   446   			break;
       
   447   	}
       
   448   	
       
   449 	CleanupStack::PushL(decryptor);
       
   450 
       
   451 	if (!c->iDecryptor)
       
   452 	{
       
   453 		if (!decryptor)
       
   454 			{
       
   455 			User::Leave(KErrGeneral);
       
   456 			}
       
   457 		CPadding* dPadding = CXmlSecPadding::NewLC(decryptor->BlockSize());
       
   458 		c->iDecryptor = CBufferedDecryptor::NewL(decryptor, dPadding);
       
   459 		CleanupStack::Pop(dPadding);
       
   460 		
       
   461 	}
       
   462 
       
   463 	CleanupStack::Pop(decryptor); 	
       
   464 }
       
   465 
       
   466 static TInt
       
   467 cipher_decrypt_doProcessL (sc_cipher_hd_t c, byte *outbuf, const byte *inbuf,
       
   468 		unsigned int nbytes, int* outputLen, int last)
       
   469     {
       
   470 	TInt rc(KErrNone);
       
   471 	
       
   472     switch( c->mode ) {
       
   473 	  case SC_CIPHER_MODE_ECB:
       
   474       case SC_CIPHER_MODE_CBC:
       
   475         {
       
   476         TUint blockSize = c->iDecryptor->BlockSize();     
       
   477 	 	 
       
   478 		if ((c->mode == SC_CIPHER_MODE_CBC) 
       
   479 				&& nbytes%blockSize
       
   480 	            && !(nbytes > blockSize
       
   481 	                && (c->flags & SC_CIPHER_CBC_CTS)))
       
   482 		{
       
   483 			rc = KErrArgument;
       
   484 		}
       
   485 		else if ((c->mode == SC_CIPHER_MODE_ECB) 
       
   486 					&& nbytes%blockSize)
       
   487 		{
       
   488 			rc = KErrArgument;
       
   489 		}	
       
   490 		else
       
   491 		{
       
   492 			TInt outlen;
       
   493 			if (last)
       
   494 				outlen = c->iDecryptor->MaxFinalOutputLength(nbytes);
       
   495 			else
       
   496 				outlen = c->iDecryptor->MaxOutputLength(nbytes);			
       
   497 			HBufC8 *result = HBufC8::NewLC(outlen);
       
   498 			TPtr8 resultActual= result->Des();
       
   499 			resultActual.FillZ(resultActual.MaxLength());
       
   500 			resultActual.SetLength(0);
       
   501 			
       
   502 			//  could improve memory usage later by allocating a smaller buffer
       
   503 			HBufC8* input = HBufC8::NewLC(nbytes);
       
   504 			TPtrC8 inbufPtr(inbuf, nbytes);
       
   505 			*input = inbufPtr;
       
   506 
       
   507 		    TInt j=0;
       
   508 		    
       
   509 			for(; j+blockSize<nbytes; j+=blockSize)
       
   510 			{	//	decryption in blocks of size blocksize
       
   511 				c->iDecryptor->Process(input->Mid(j,blockSize), resultActual);
       
   512 			}			
       
   513 		
       
   514 			if (last)	
       
   515 			{
       
   516 				c->iDecryptor->ProcessFinalL(input->Mid(j), resultActual);
       
   517 				*outputLen = result->Size();
       
   518 				
       
   519 				// we delete iDecryptor once the decryption finishes
       
   520 				// so that the next decryption can use a different key or iv
       
   521 				delete c->iDecryptor;
       
   522 				c->iDecryptor = NULL;		
       
   523 			}
       
   524 			else
       
   525 				c->iDecryptor->Process(input->Mid(j,blockSize), resultActual);
       
   526 			
       
   527 			memcpy(outbuf, result->Ptr(), result->Size());				
       
   528 			
       
   529 			CleanupStack::PopAndDestroy(input);
       
   530 			CleanupStack::PopAndDestroy(result);	
       
   531 			
       
   532 		}
       
   533         }
       
   534 	break;
       
   535 	/*
       
   536       case SC_CIPHER_MODE_CFB:
       
   537 	do_cfb_decrypt(c, outbuf, inbuf, nbytes );
       
   538 	break;
       
   539       case SC_CIPHER_MODE_CTR:
       
   540 	do_ctr_decrypt(c, outbuf, inbuf, nbytes );
       
   541 	break;
       
   542       case SC_CIPHER_MODE_STREAM:
       
   543         c->cipher->stdecrypt ( &c->context.c,
       
   544                                outbuf, (byte*) inbuf, nbytes );
       
   545         break;
       
   546       case SC_CIPHER_MODE_NONE:
       
   547 	if( inbuf != outbuf )
       
   548 	    memmove( outbuf, inbuf, nbytes );
       
   549 	break;
       
   550 	    */
       
   551       default:
       
   552         rc = KErrNotSupported;
       
   553         break;
       
   554         
       
   555     }	
       
   556     
       
   557     return rc;
       
   558     }
       
   559 
       
   560 /****************
       
   561  * Decrypt INBUF to OUTBUF with the mode selected at open.
       
   562  * inbuf and outbuf may overlap or be the same.
       
   563  * Depending on the mode some some contraints apply to NBYTES.
       
   564  */
       
   565 static TInt
       
   566 cipher_decrypt (sc_cipher_hd_t c, byte *outbuf, const byte *inbuf,
       
   567 		unsigned int nbytes, int *outlen, int last)
       
   568 {
       
   569     TInt rc( KErrNone );
       
   570     TInt leaveValue;
       
   571 
       
   572 	// Perform Symbian prerequisite data structure initialization
       
   573     TRAP(leaveValue, cipher_decrypt_prerequisiteL (c));
       
   574 	if (leaveValue != KErrNone)
       
   575 	    {
       
   576 	    xmlSecSetErrorFlag( leaveValue );
       
   577 		return leaveValue;
       
   578 	    }
       
   579 		
       
   580 	// Symbian decryption
       
   581 	TRAP(leaveValue, rc=cipher_decrypt_doProcessL (c, outbuf, inbuf, nbytes, outlen, last));
       
   582 	if (leaveValue != KErrNone)
       
   583 	    {
       
   584 	    xmlSecSetErrorFlag( leaveValue );
       
   585 	    return leaveValue;
       
   586 	    }
       
   587     return rc;
       
   588 }
       
   589 
       
   590 
       
   591 
       
   592 int
       
   593 sc_cipher_decrypt (sc_cipher_hd_t h, void *out, size_t outsize,
       
   594 		     const void *in, size_t inlen, int* outlen, int last)
       
   595 {
       
   596   TInt err( KErrNone );
       
   597 
       
   598   if (last && !outlen)
       
   599     err = KErrArgument;
       
   600   else if (! in)
       
   601     /* Caller requested in-place encryption. */
       
   602     /* Actullay cipher_encrypt() does not need to know about it, but
       
   603      * we may chnage this to get better performance. */
       
   604     err = cipher_decrypt (h, (byte*)out, (byte*)out, outsize, outlen, last);
       
   605   else if (inlen == 0)
       
   606     return err;
       
   607   else if (outsize < inlen)
       
   608     err = KErrArgument;
       
   609   else if (((h->mode == SC_CIPHER_MODE_ECB)
       
   610 	    || ((h->mode == SC_CIPHER_MODE_CBC)
       
   611 		&& (! ((h->flags & SC_CIPHER_CBC_CTS)
       
   612 		       && (inlen > h->blocksize)))))
       
   613 	   && (inlen % h->blocksize))
       
   614     err = KErrArgument;
       
   615   else
       
   616     err = cipher_decrypt (h, (byte*)out, (byte*)in, inlen, outlen, last);
       
   617 
       
   618   return err;
       
   619 }
       
   620 
       
   621 /*
       
   622    Open a cipher handle for use with cipher algorithm ALGORITHM, using
       
   623    the cipher mode MODE (one of the SC_CIPHER_MODE_*) and return a
       
   624    handle in HANDLE.  Put NULL into HANDLE and return an error code if
       
   625    something goes wrong.  FLAGS may be used to modify the
       
   626    operation.  The defined flags are:
       
   627 
       
   628    SC_CIPHER_SECURE:  allocate all internal buffers in secure memory.
       
   629    SC_CIPHER_ENABLE_SYNC:  Enable the sync operation as used in OpenPGP.
       
   630    SC_CIPHER_CBC_CTS:  Enable CTS mode.
       
   631    SC_CIPHER_CBC_MAC:  Enable MAC mode.
       
   632 
       
   633    Values for these flags may be combined using OR.
       
   634  */
       
   635 TInt 
       
   636 sc_cipher_open (sc_cipher_hd_t *handle,
       
   637 		  int algo, int mode, unsigned int flags)
       
   638 {
       
   639   int secure = (flags & SC_CIPHER_SECURE);
       
   640   CSymmetricCipher* encryptor = NULL;	//CBlockTransformation
       
   641   CSymmetricCipher* decryptor = NULL;
       
   642   sc_cipher_hd_t h = NULL;
       
   643   TInt err( KErrNone );
       
   644 
       
   645   /* If the application missed to call the random poll function, we do
       
   646      it here to ensure that it is used once in a while. */
       
   647   
       
   648   /* check flags */
       
   649   if ((! err)
       
   650       && ((flags & ~(0 
       
   651 		     | SC_CIPHER_SECURE
       
   652 		     | SC_CIPHER_ENABLE_SYNC
       
   653 		     | SC_CIPHER_CBC_CTS
       
   654 		     | SC_CIPHER_CBC_MAC))
       
   655 	  || (flags & SC_CIPHER_CBC_CTS & SC_CIPHER_CBC_MAC)))
       
   656     err = KErrArgument;
       
   657 
       
   658   /* check that a valid mode has been requested */
       
   659   if (! err)
       
   660     switch (mode)
       
   661       {//
       
   662       case SC_CIPHER_MODE_ECB:
       
   663       case SC_CIPHER_MODE_CBC:
       
   664       case SC_CIPHER_MODE_CFB:
       
   665       case SC_CIPHER_MODE_CTR:
       
   666       case SC_CIPHER_MODE_STREAM:
       
   667 	break;
       
   668       case SC_CIPHER_MODE_NONE:
       
   669 	break;
       
   670 
       
   671       default:
       
   672 	err = KErrNotSupported;
       
   673       }
       
   674 
       
   675 
       
   676   if (! err)
       
   677     {
       
   678 	size_t size = sizeof(*h);
       
   679 	h = (sc_cipher_hd_t)malloc(size);
       
   680 	
       
   681     if ( !h )
       
   682         {
       
   683 	    err = KErrNoMemory;
       
   684         xmlSecSetErrorFlag( KErrNoMemory );
       
   685         }
       
   686       else
       
   687 	{
       
   688 	  h->magic = secure ? CTX_MAGIC_SECURE : CTX_MAGIC_NORMAL;
       
   689           h->actual_handle_size = size;
       
   690 	  h->iEncryptor = encryptor;
       
   691 	  h->iDecryptor = decryptor;
       
   692 	  h->iKey = NULL;
       
   693 	  h->algo = algo;  
       
   694 	  h->iv = NULL;
       
   695 
       
   696 	  h->mode = mode;
       
   697 	  h->flags = flags;
       
   698 	  
       
   699 	  if (algo == SC_CIPHER_NONE)
       
   700 	  {
       
   701 	  TRAPD(leaveValue,h->iEncryptor = CNullCipher::NewL());
       
   702             if (leaveValue) //!= KErrNone
       
   703                 {
       
   704                 xmlSecSetErrorFlag( leaveValue );
       
   705                 return leaveValue;
       
   706                 }	
       
   707             TRAP(leaveValue,h->iDecryptor = CNullCipher::NewL());
       
   708             if (leaveValue) //!= KErrNone
       
   709                 {
       
   710                 xmlSecSetErrorFlag( leaveValue );
       
   711                 return leaveValue;
       
   712                 }	
       
   713             	  	
       
   714 	  }
       
   715 	}
       
   716     }
       
   717 
       
   718   *handle = err ? NULL : h;
       
   719 
       
   720   return err;
       
   721 }
       
   722 
       
   723 
       
   724 /* Release all resources associated with the cipher handle H. H may be
       
   725    NULL in which case this is a no-operation. */
       
   726 void
       
   727 sc_cipher_close (sc_cipher_hd_t h)
       
   728 {
       
   729   if (! h)
       
   730     return;
       
   731 
       
   732   if ((h->magic != CTX_MAGIC_SECURE)
       
   733       && (h->magic != CTX_MAGIC_NORMAL))
       
   734   {
       
   735   /*
       
   736     _sc_fatal_error(GPG_ERR_INTERNAL,
       
   737 		      "sc_cipher_close: already closed/invalid handle");  
       
   738   */	
       
   739      return;
       
   740   }
       
   741 
       
   742   else
       
   743     h->magic = 0;
       
   744 
       
   745   if (h->iEncryptor)
       
   746   {
       
   747   	delete h->iEncryptor;
       
   748   	h->iEncryptor = NULL;
       
   749   }
       
   750   
       
   751   if (h->iDecryptor)
       
   752   {
       
   753   	delete h->iDecryptor;
       
   754   	h->iDecryptor = NULL;
       
   755   }
       
   756   
       
   757   if (h->iv)
       
   758   {
       
   759   	delete h->iv;
       
   760   	h->iv = NULL;
       
   761   }
       
   762   
       
   763   if (h->iKey)
       
   764   {
       
   765   	delete h->iKey;
       
   766   	h->iKey = NULL;
       
   767   }
       
   768   
       
   769 
       
   770   /* We always want to wipe out the memory even when the context has
       
   771      been allocated in secure memory.  The user might have disabled
       
   772      do the wiping.  To accomplish this we need to keep track of the
       
   773      actual size of this structure because we have no way to known
       
   774      how large the allocated area was when using a standard malloc. */
       
   775   /*
       
   776   TInt len = h->actual_handle_size;
       
   777   memset(h, 'a', len);	// fill with something
       
   778   */
       
   779 
       
   780   free (h);
       
   781 }
       
   782 
       
   783 size_t
       
   784 sc_cipher_get_algo_keylen (int algo) 
       
   785 {
       
   786   switch (algo) {
       
   787 
       
   788 	case SC_CIPHER_AES128:
       
   789 	 	return KAESKeySize128;
       
   790 	case SC_CIPHER_AES192:
       
   791 	 	return KAESKeySize192;
       
   792 	case SC_CIPHER_AES256:
       
   793 	 	return KAESKeySize256;	 		 	
       
   794 	case SC_CIPHER_3DES:
       
   795 		return K3DESKeySize;
       
   796 	case SC_CIPHER_DES:
       
   797 		return KDESKeySize;
       
   798 	case SC_CIPHER_NONE:		
       
   799 	default:
       
   800 	    return 0;	
       
   801 
       
   802   }
       
   803 
       
   804 }
       
   805 
       
   806 
       
   807 /* Set the key to be used for the encryption context C to KEY with
       
   808    length KEYLEN.  The length should match the required length. */
       
   809 //sc_error_t
       
   810 TInt sc_cipher_setkey (sc_cipher_hd_t c, byte *key, unsigned int keylen)
       
   811     {
       
   812     
       
   813     // Change key into the right format
       
   814     TRAPD(error, c->iKey = HBufC8::NewL(keylen));
       
   815     if(error == KErrNone)
       
   816         {
       
   817         TPtrC8 keyPtr(key, keylen);
       
   818         *(c->iKey) = keyPtr;
       
   819         }
       
   820     else 
       
   821         {
       
   822         xmlSecSetErrorFlag( error );
       
   823         }
       
   824     return error;
       
   825     }
       
   826 
       
   827 /* Set specification blocksize in context */
       
   828 void set_ctx_blocksize(sc_cipher_hd_t c, size_t bklen)
       
   829 {
       
   830 	c->blocksize = bklen;
       
   831 }