pkiutilities/PKCS12/CrPkcs12/Src/crcrypto.cpp
changeset 0 164170e6151a
child 5 3b17fc5c9564
equal deleted inserted replaced
-1:000000000000 0:164170e6151a
       
     1 /*
       
     2 * Copyright (c) 2000, 2004 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:   This file contains the implementation of CCrCrypto class. 
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 
       
    20 //  INCLUDE FILES
       
    21 #include "crcrypto.h"
       
    22 #include <e32def.h>  // REINTERPRET_CAST
       
    23 #include "crdata.h"
       
    24 #include <bigint.h>  // Big integer.
       
    25 #include <hash.h>
       
    26 #include <symmetric.h>
       
    27 
       
    28 
       
    29 // -----------------------------------------------------------------------------
       
    30 // CCrCrypto
       
    31 // Constructor.
       
    32 // -----------------------------------------------------------------------------
       
    33 CCrCrypto::CCrCrypto()
       
    34     : iAlgorithmInfos(0)
       
    35     {
       
    36     }
       
    37 
       
    38 // -----------------------------------------------------------------------------
       
    39 // ~CCrCrypto
       
    40 // Destructor.
       
    41 // -----------------------------------------------------------------------------
       
    42 CCrCrypto::~CCrCrypto()
       
    43     {
       
    44     Reset();
       
    45 
       
    46     if( iAlgorithmInfos )
       
    47         {
       
    48         iAlgorithmInfos->Reset();
       
    49         delete iAlgorithmInfos;
       
    50         iAlgorithmInfos = NULL;
       
    51         }
       
    52     }
       
    53 
       
    54 // -----------------------------------------------------------------------------
       
    55 // CCrCrypto::ConstructL
       
    56 // This function initializes this object's members.
       
    57 // -----------------------------------------------------------------------------
       
    58 void CCrCrypto::ConstructL()
       
    59     {
       
    60     iAlgorithmInfos = new (ELeave) CArrayPtrFlat<CCrAlgInfo>(1);
       
    61     }
       
    62 
       
    63 // -----------------------------------------------------------------------------
       
    64 // CCrCrypto::NewLC
       
    65 // -----------------------------------------------------------------------------
       
    66 CCrCrypto* CCrCrypto::NewLC()
       
    67     {
       
    68     CCrCrypto* self = new (ELeave) CCrCrypto();
       
    69     CleanupStack::PushL(self);
       
    70 
       
    71     self->ConstructL();
       
    72 
       
    73     return self; 
       
    74     }
       
    75 
       
    76 // -----------------------------------------------------------------------------
       
    77 // CCrCrypto::NewL
       
    78 // -----------------------------------------------------------------------------
       
    79 CCrCrypto* CCrCrypto::NewL()
       
    80     {
       
    81     CCrCrypto* self = NewLC();
       
    82     CleanupStack::Pop();
       
    83 
       
    84     return self; 
       
    85     }
       
    86 
       
    87 // -----------------------------------------------------------------------------
       
    88 // CCrCrypto::Reset
       
    89 // Reset all algorithms initialized into this object and free
       
    90 // memory associated to them. Note that GetDigest etc. functions are
       
    91 // meaningles after this until new ones are initialized and finalized.
       
    92 // -----------------------------------------------------------------------------
       
    93 void CCrCrypto::Reset()
       
    94     {
       
    95     TInt        i = 0;
       
    96     TInt        size = 0;
       
    97     CCrAlgInfo* algInfo = 0;
       
    98 
       
    99     size = iAlgorithmInfos->Count();
       
   100 
       
   101     for (i = 0; i < size; i++)
       
   102         {    
       
   103         algInfo = (*iAlgorithmInfos)[i];
       
   104 
       
   105 		if (algInfo)
       
   106 			{
       
   107 			switch (algInfo->iType)
       
   108 				{
       
   109 				case ECrDES2:
       
   110 				case ECrDES3:
       
   111 					{
       
   112                     if (algInfo->iAlgorithmObject)
       
   113                         {
       
   114 						delete algInfo->iAlgorithmObject;
       
   115                         algInfo->iAlgorithmObject = NULL;
       
   116                         }
       
   117                     if (algInfo->iPadding)
       
   118                         {
       
   119                         delete algInfo->iPadding;
       
   120                         algInfo->iPadding = NULL;
       
   121                         }
       
   122 
       
   123                     break;
       
   124                     }
       
   125 				default:
       
   126 					{
       
   127                     if (algInfo->iAlgorithmObject)
       
   128                         {
       
   129                         delete algInfo->iAlgorithmObject;
       
   130                         algInfo->iAlgorithmObject = NULL;
       
   131                         }
       
   132 
       
   133                     if (algInfo->iPadding)
       
   134                         {
       
   135                         delete algInfo->iPadding;
       
   136                         algInfo->iPadding = NULL;
       
   137                         }
       
   138 
       
   139                     break;
       
   140 					}
       
   141                 }
       
   142             }
       
   143         }
       
   144 
       
   145     iAlgorithmInfos->ResetAndDestroy();
       
   146     }
       
   147 
       
   148 // -----------------------------------------------------------------------------
       
   149 // CCrCrypto::InitCrypt3DESL
       
   150 // Initialize encryption or decryption with 3DES algorithm.
       
   151 // -----------------------------------------------------------------------------
       
   152 TCrStatus CCrCrypto::InitCrypt3DESL(
       
   153     const TDesC8& aKey1,
       
   154     const TDesC8& aKey2,
       
   155     const TDesC8& aKey3,
       
   156     const TDesC8& aIV,              
       
   157     TBool         aEncrypt,   // ETrue  
       
   158     TCrSymmMode   aMode,      // ECrCBC
       
   159     TPaddingRule  /*aPadRule*/)   // ECrPKCS1
       
   160     {
       
   161     // Number of items pushed to CleanupStack
       
   162     TUint pushedToCStack = 0;
       
   163 
       
   164     // Combined keys.
       
   165     HBufC8* keys = HBufC8::NewLC(
       
   166         aKey1.Length() + aKey2.Length() + aKey3.Length());
       
   167     ++pushedToCStack;
       
   168 
       
   169     TPtr8 ptrKeys = keys->Des();
       
   170 
       
   171     // Combine given keys to be able to give them to algorithm info object.
       
   172     ptrKeys = aKey1;
       
   173     ptrKeys.Append(aKey2);
       
   174     ptrKeys.Append(aKey3);
       
   175 
       
   176     // Create new algorithm info object.
       
   177     CCrAlgInfo* algInfo = CCrAlgInfo::NewLC(
       
   178         ECrDES3,
       
   179         *keys,
       
   180         aIV,
       
   181         aEncrypt,
       
   182         ETrue,
       
   183         aMode);
       
   184     ++pushedToCStack;
       
   185     
       
   186     switch (aMode)
       
   187         {
       
   188         case ECrCBC:
       
   189             {
       
   190 			    if (aEncrypt)
       
   191 				    {
       
   192 				    C3DESEncryptor* tripleDes = C3DESEncryptor::NewL(*algInfo->iKey);
       
   193 				    CleanupStack::PushL(tripleDes);
       
   194 
       
   195 				    CModeCBCEncryptor* cbcEncryptor = CModeCBCEncryptor::NewL(tripleDes, aIV);
       
   196 				    CleanupStack::Pop(tripleDes); // CModeCBCEncryptor takes care of tripleDes now
       
   197 				    CleanupStack::PushL(cbcEncryptor);
       
   198 
       
   199 				    CPaddingPKCS7* padding = CPaddingPKCS7::NewL(tripleDes->BlockSize());							
       
   200 				    CleanupStack::PushL(padding);
       
   201 
       
   202 				    CBufferedEncryptor* encryptor = CBufferedEncryptor::NewL(cbcEncryptor, padding);
       
   203 				    CleanupStack::Pop(2); // CBufferedEncryptor takes care of freeing	
       
   204 
       
   205 				    algInfo->iAlgorithmObject = encryptor;
       
   206 				    }
       
   207 			    else
       
   208 				    {			
       
   209 				    C3DESDecryptor* tripleDes = C3DESDecryptor::NewL(*algInfo->iKey);
       
   210 				    CleanupStack::PushL(tripleDes);
       
   211 
       
   212 				    CModeCBCDecryptor* cbcDecryptor = CModeCBCDecryptor::NewL(tripleDes, aIV);
       
   213 				    CleanupStack::Pop(tripleDes); // CModeCBCEncryptor takes care of tripleDes now
       
   214 				    CleanupStack::PushL(cbcDecryptor);
       
   215 
       
   216 				    CPaddingPKCS7* padding = CPaddingPKCS7::NewL(tripleDes->BlockSize());
       
   217 				    CleanupStack::PushL(padding);
       
   218 
       
   219 				    CBufferedDecryptor* decryptor = CBufferedDecryptor::NewL(cbcDecryptor, padding);
       
   220 				    CleanupStack::Pop(2); // CBufferedDecryptor takes care of freeing	
       
   221 
       
   222 				    algInfo->iAlgorithmObject = decryptor;							
       
   223 				    }	                    
       
   224             break;
       
   225             }
       
   226         case ECrCFB:
       
   227             {
       
   228 		    return KCrCrypto | KCrUnknownMode;
       
   229             }
       
   230         case ECrECB:
       
   231             {
       
   232             return KCrCrypto | KCrUnknownMode;
       
   233             }
       
   234         case ECrOFB:
       
   235             {
       
   236 		    return KCrCrypto | KCrUnknownMode;
       
   237             }
       
   238         default:
       
   239             {
       
   240             return KCrCrypto | KCrUnknownMode;
       
   241             }
       
   242         }
       
   243 
       
   244     CleanupStack::PushL(algInfo->iAlgorithmObject);
       
   245     ++pushedToCStack;
       
   246 
       
   247     // Append new algorithm info object into member set.
       
   248     iAlgorithmInfos->AppendL(algInfo);
       
   249  
       
   250     CleanupStack::Pop(pushedToCStack);
       
   251 
       
   252     delete keys;
       
   253     keys = NULL;
       
   254 
       
   255     return KCrOK;
       
   256     }
       
   257 
       
   258 // -----------------------------------------------------------------------------
       
   259 // CCrCrypto::InitCryptRC2L
       
   260 // Initialize encryption or decryption with RC2 algorithm.
       
   261 // -----------------------------------------------------------------------------
       
   262 TCrStatus CCrCrypto::InitCryptRC2L(
       
   263     const TDesC8& aKey,             
       
   264     const TDesC8& aIV,
       
   265     TBool         aEncrypt,          // ETrue
       
   266     TInt          aEffectiveKeyLen,  // If 0 given, key len is used.
       
   267     TCrSymmMode   aMode,             // ECrCBC
       
   268     TPaddingRule  /*aPadRule */)          // ECrPKCS1
       
   269     {
       
   270     // Number of items pushed to CleanupStack
       
   271     TUint pushedToCStack = 0;
       
   272 
       
   273     // Create new algorithm info object.
       
   274     CCrAlgInfo* algInfo = CCrAlgInfo::NewLC(
       
   275         ECrRC2,
       
   276         aKey,
       
   277         aIV,
       
   278         aEncrypt,
       
   279         ETrue,
       
   280         aMode);
       
   281     ++pushedToCStack;
       
   282 
       
   283     // If given effective key length is zero, use key length.
       
   284     if (aEffectiveKeyLen == 0)
       
   285         {
       
   286         aEffectiveKeyLen = algInfo->iKey->Length() * 8;
       
   287         }
       
   288     
       
   289     // Create cipher object.
       
   290     switch (aMode)
       
   291         {
       
   292         case ECrCBC:
       
   293             {
       
   294 			if (aEncrypt)
       
   295 				{
       
   296 				CRC2Encryptor* rc2 = CRC2Encryptor::NewL(*algInfo->iKey, aEffectiveKeyLen);
       
   297 				CleanupStack::PushL(rc2);
       
   298 
       
   299 				CModeCBCEncryptor* cbcEncryptor = CModeCBCEncryptor::NewL(rc2, aIV);
       
   300 				CleanupStack::Pop(rc2); // CModeCBCEncryptor takes care of rc2 now
       
   301 				CleanupStack::PushL(cbcEncryptor);
       
   302 
       
   303 				CPaddingPKCS7* padding = CPaddingPKCS7::NewL(rc2->BlockSize());
       
   304 				CleanupStack::PushL(padding);
       
   305 
       
   306 				CBufferedEncryptor* encryptor = CBufferedEncryptor::NewL(cbcEncryptor, padding);
       
   307 				CleanupStack::Pop(2); // CBufferedEncryptor takes care of freeing
       
   308 
       
   309 				algInfo->iAlgorithmObject = encryptor;							
       
   310 				}
       
   311 			else
       
   312 				{			
       
   313 				CRC2Decryptor* rc2 = CRC2Decryptor::NewL(*algInfo->iKey, aEffectiveKeyLen);
       
   314 				CleanupStack::PushL(rc2);
       
   315 
       
   316 				CModeCBCDecryptor* cbcDecryptor = CModeCBCDecryptor::NewL(rc2, aIV);
       
   317 				CleanupStack::Pop(rc2); // CModeCBCEncryptor takes care of rc2 now
       
   318 				CleanupStack::PushL(cbcDecryptor);
       
   319 
       
   320 				CPaddingPKCS7* padding = CPaddingPKCS7::NewL(rc2->BlockSize());
       
   321 				CleanupStack::PushL(padding);
       
   322 
       
   323 				CBufferedDecryptor* decryptor = CBufferedDecryptor::NewL(cbcDecryptor, padding);
       
   324 				CleanupStack::Pop(2); // CBufferedDecryptor takes care of freeing
       
   325 
       
   326 				algInfo->iAlgorithmObject = decryptor;							
       
   327 				}	                    
       
   328             algInfo->iMode = ECrCBC;
       
   329             break;
       
   330             }
       
   331         case ECrCFB:
       
   332             {
       
   333             return KCrCrypto | KCrUnknownMode;
       
   334             }
       
   335         case ECrECB:
       
   336             {          
       
   337             return KCrCrypto | KCrUnknownMode;
       
   338             }
       
   339         case ECrOFB:
       
   340             {
       
   341 			return KCrCrypto | KCrUnknownMode;
       
   342             }
       
   343         default:
       
   344             {
       
   345             return KCrCrypto | KCrUnknownMode;
       
   346             }
       
   347         }
       
   348 
       
   349     CleanupStack::PushL(algInfo->iAlgorithmObject);
       
   350     ++pushedToCStack;
       
   351 
       
   352 
       
   353     // Append new algorithm info object into member set.
       
   354     iAlgorithmInfos->AppendL(algInfo);
       
   355 
       
   356     CleanupStack::Pop(pushedToCStack);
       
   357  
       
   358     return KCrOK;
       
   359     }
       
   360 
       
   361 // -----------------------------------------------------------------------------
       
   362 // CCrCrypto::InitDigestL
       
   363 // Initialize message digest with MD2 algorithm.
       
   364 // -----------------------------------------------------------------------------
       
   365 TCrStatus CCrCrypto::InitDigestL(TCrAlgorithm aAlgorithm)    
       
   366     {
       
   367     // Number of items pushed to CleanupStack
       
   368     TUint pushedToCStack = 0;
       
   369 
       
   370     // Create new algorithm info object.
       
   371     CCrAlgInfo *algInfo = CCrAlgInfo::NewLC(aAlgorithm);
       
   372     pushedToCStack++;
       
   373 
       
   374     switch(aAlgorithm)
       
   375         {
       
   376         case ECrSHA1:
       
   377             {
       
   378             // Create digest object.
       
   379             algInfo->iAlgorithmObject  = CSHA1::NewL();
       
   380             break;
       
   381             }
       
   382         case ECrMD5:
       
   383             {
       
   384             // Create digest object.
       
   385             algInfo->iAlgorithmObject  = CMD5::NewL();
       
   386             break;
       
   387             }
       
   388         case ECrMD2:
       
   389             {
       
   390             // Create digest object.
       
   391             algInfo->iAlgorithmObject = CMD2::NewL();
       
   392             break;
       
   393             }
       
   394         case ECrSHA:
       
   395             {  
       
   396             // Create digest object.
       
   397             algInfo->iAlgorithmObject  = CSHA::NewL();
       
   398             break;
       
   399             }
       
   400         default:
       
   401             {
       
   402             return KCrCrypto | KCrNotSupportedAlg;
       
   403             }
       
   404         }
       
   405 
       
   406     CleanupStack::PushL(algInfo->iAlgorithmObject);
       
   407     pushedToCStack++;
       
   408 
       
   409     // Append new algorithm info object into member set.
       
   410     iAlgorithmInfos->AppendL(algInfo);
       
   411 
       
   412     CleanupStack::Pop(pushedToCStack);
       
   413 
       
   414     return KCrOK;
       
   415     }
       
   416 
       
   417 // -----------------------------------------------------------------------------
       
   418 // CCrCrypto::InitDigestHMACL
       
   419 // Initialize message digest with HMAC algorithm.
       
   420 // -----------------------------------------------------------------------------
       
   421 TCrStatus CCrCrypto::InitDigestHMACL(
       
   422     const TDesC8& aKey, 
       
   423     TCrAlgorithm aDigestAlg)     
       
   424     {
       
   425     // Number of items pushed to CleanupStack
       
   426     TUint pushedToCStack = 0;
       
   427 
       
   428     TCrAlgorithm hmacDigest;
       
   429 
       
   430     switch (aDigestAlg)
       
   431         {
       
   432         case ECrSHA1:
       
   433             {
       
   434             hmacDigest = ECrHMAC_SHA1;
       
   435 
       
   436             break;
       
   437             }
       
   438         case ECrMD5:
       
   439             {
       
   440             hmacDigest = ECrHMAC_MD5;
       
   441 
       
   442             break;
       
   443             }
       
   444         default:
       
   445             {
       
   446             return KCrCrypto | KCrNotSupportedAlg;
       
   447             }
       
   448         }
       
   449 
       
   450     // Create new algorithm info object.
       
   451     CCrAlgInfo *algInfo = CCrAlgInfo::NewLC(hmacDigest);
       
   452     pushedToCStack++;
       
   453 
       
   454     CMessageDigest* digest = 0;
       
   455 
       
   456     switch(aDigestAlg)
       
   457         {
       
   458         case ECrSHA1:
       
   459             {
       
   460             // Create digest object.
       
   461             digest = CSHA1::NewL();
       
   462             break;
       
   463             }
       
   464         case ECrMD5:
       
   465             {
       
   466             // Create digest object.
       
   467             digest = CMD5::NewL();
       
   468             break;
       
   469             }
       
   470         case ECrMD2:
       
   471             {
       
   472             // Create digest object.
       
   473             digest = CMD2::NewL();
       
   474             break;
       
   475             }
       
   476         case ECrSHA:
       
   477             {   
       
   478             // Create digest object.
       
   479             digest = CSHA::NewL();
       
   480             break;  
       
   481             }   
       
   482         default:
       
   483             {
       
   484             return KCrCrypto | KCrNotSupportedAlg;
       
   485             }
       
   486         }
       
   487     CleanupStack::PushL(digest);
       
   488     ++pushedToCStack;
       
   489     // Create digest object.
       
   490     algInfo->iAlgorithmObject  = CHMAC::NewL(aKey, digest);
       
   491     CleanupStack::PushL(algInfo->iAlgorithmObject);
       
   492     ++pushedToCStack;
       
   493     
       
   494     // Append new algorithm info object into member set.
       
   495     iAlgorithmInfos->AppendL(algInfo);
       
   496 
       
   497     CleanupStack::Pop(pushedToCStack);
       
   498 
       
   499     return KCrOK;
       
   500     }
       
   501 
       
   502 
       
   503 // -----------------------------------------------------------------------------
       
   504 // CCrCrypto::ProcessL
       
   505 // Process given source data with initialized crypto operations.
       
   506 // If symmetric crypto is initialized sets to aTrg encrypted
       
   507 // or decrypted data without last portion. If aProcessFinalBlock
       
   508 // is ETrue, appends also last portion. If only digest algorithm
       
   509 // is initialized, aTrg is not used.
       
   510 // -----------------------------------------------------------------------------
       
   511 TCrStatus CCrCrypto::ProcessL(const TDesC8& aSrc, TDes8& aTrg) 
       
   512     {
       
   513     TInt              i, size;
       
   514     TUint             pushedToCStack = 0;
       
   515     CCrAlgInfo* algInfo = 0;
       
   516 
       
   517     size = iAlgorithmInfos->Count();
       
   518 
       
   519     for (i = 0; i < size; i++)
       
   520         {
       
   521         algInfo = (*iAlgorithmInfos)[i];
       
   522 
       
   523         // Message digest algorithm
       
   524         if (algInfo->iType < ECrLAST_DIGEST)
       
   525             {
       
   526             // Casting to right type
       
   527             CMessageDigest* digest = STATIC_CAST(
       
   528                 CMessageDigest*, algInfo->iAlgorithmObject);
       
   529 
       
   530             // Store the digest to buf
       
   531             //algInfo->iDigest = HBufC8::NewL(digest->HashSize());
       
   532 			TPtr8 ptr = algInfo->iDigest->Des();
       
   533 			ptr.Copy(digest->Hash(aSrc));
       
   534             }   
       
   535         // Symmetric crypto algorithm
       
   536         else if (algInfo->iType > ECrLAST_DIGEST && algInfo->iType < ECrLAST_SYMM_CRYPTO)
       
   537             {
       
   538             // Casting to right type
       
   539             CSymmetricCipher* cipherSymm =
       
   540                 STATIC_CAST(CSymmetricCipher*, algInfo->iAlgorithmObject);
       
   541 
       
   542 
       
   543 			// This is not incremental
       
   544 			cipherSymm->ProcessFinalL(aSrc, aTrg);			
       
   545 			
       
   546             CleanupStack::Pop(pushedToCStack);
       
   547             }
       
   548         else 
       
   549             {
       
   550             return KCrCrypto | KCrNotSupportedAlg;
       
   551             }
       
   552         }
       
   553     return KCrOK;
       
   554     }
       
   555 
       
   556 // -----------------------------------------------------------------------------
       
   557 // CCrCrypto::FinalCryptL
       
   558 // Finalize symmetric algorithms objects.
       
   559 // -----------------------------------------------------------------------------
       
   560 TCrStatus CCrCrypto::FinalCryptL(TDes8& aTrg)
       
   561     {
       
   562     TInt        i, size;
       
   563     CCrAlgInfo *algInfo = 0;
       
   564     TCrStatus   status = KCrOK;
       
   565     size = iAlgorithmInfos->Count();
       
   566 
       
   567     for (i = 0; i < size; i++)
       
   568         {
       
   569         algInfo = (*iAlgorithmInfos)[i];
       
   570 
       
   571         if (algInfo->iType > ECrLAST_DIGEST && 
       
   572             algInfo->iType < ECrLAST_SYMM_CRYPTO) 
       
   573             { 
       
   574             TUint8 pushedToCStack = 0;
       
   575 
       
   576             CSymmetricCipher* cipherSymm = 
       
   577                 STATIC_CAST(CSymmetricCipher*, algInfo->iAlgorithmObject);
       
   578             
       
   579             HBufC8 *lastBlock =
       
   580                 HBufC8::NewLC(algInfo->iLastPortion->Size());
       
   581             pushedToCStack++;
       
   582 
       
   583             TPtr8 ptrLastBlock = lastBlock->Des();
       
   584 
       
   585 		    if (cipherSymm->MaxFinalOutputLength(ptrLastBlock.Size()) > 0)
       
   586 		    {
       
   587 			    cipherSymm->ProcessFinalL(ptrLastBlock, aTrg);                    
       
   588 		    }
       
   589 
       
   590             CleanupStack::Pop(pushedToCStack);
       
   591 
       
   592             delete lastBlock;
       
   593             lastBlock = 0;
       
   594 
       
   595             delete cipherSymm;
       
   596             cipherSymm = 0;
       
   597             algInfo->iAlgorithmObject = 0;
       
   598         
       
   599             }                 
       
   600         }
       
   601     return status;
       
   602     }
       
   603 
       
   604 
       
   605 TCrStatus CCrCrypto::FinalDigest(TDes8& aTrg)
       
   606     {
       
   607     TInt              i, size;
       
   608     CCrAlgInfo *algInfo = 0;
       
   609     TCrStatus         status = KCrOK;
       
   610 
       
   611     size = iAlgorithmInfos->Count();
       
   612 
       
   613     for (i = 0; i < size; i++)
       
   614         {
       
   615         algInfo = (*iAlgorithmInfos)[i];
       
   616 
       
   617         if ((algInfo->iType < ECrLAST_DIGEST) && (status == KCrOK))
       
   618             {
       
   619     
       
   620             aTrg.Copy(*algInfo->iDigest);
       
   621 
       
   622             CMessageDigest* digest = STATIC_CAST(
       
   623                 CMessageDigest*, algInfo->iAlgorithmObject);
       
   624 
       
   625             delete digest;
       
   626             digest = 0;
       
   627             algInfo->iAlgorithmObject = 0;
       
   628             }
       
   629         }
       
   630     return status;
       
   631     }
       
   632 
       
   633 
       
   634 
       
   635 // -----------------------------------------------------------------------------
       
   636 // CCrCrypto::RemoveLastBlock
       
   637 // Checks that aOriginSrc length is multiple of the block size, If not, 
       
   638 // removes data from the end so that it is multiple of the block size.
       
   639 // Parameters:     aSrc            Original data to remove the last block 
       
   640 //                 aBlockSize      Size of the block
       
   641 //                 alginfo         Pointer to object where last portion is 
       
   642 //                                 stored.
       
   643 // Return Values:  true if size of aOriginSrc is bigger than blockSize
       
   644 //                 otherwise false. If false the whole aOriginSrc is stored 
       
   645 //                 to alginfo.
       
   646 // -----------------------------------------------------------------------------
       
   647 TInt CCrCrypto::RemoveLastBlock(
       
   648     TDesC8&           aSrc,
       
   649     const TInt        aBlockSize,
       
   650     CCrAlgInfo*       algInfo)    
       
   651     { 
       
   652     TUint number_of_blocks = aSrc.Size() / aBlockSize;
       
   653     TUint size_of_last_block = aSrc.Size() % aBlockSize;     
       
   654 
       
   655     TUint size_of_checked; 
       
   656     
       
   657     // If aOriginSrc's size is smaller or equal than aBlocksize
       
   658     if (number_of_blocks == 0 || (number_of_blocks == 1 && size_of_last_block == 0))
       
   659         {
       
   660         *algInfo->iLastPortion = aSrc;
       
   661         
       
   662         return false;
       
   663         }
       
   664     else if (size_of_last_block == 0 && number_of_blocks > 0)
       
   665         {
       
   666         // 3des fix begins:
       
   667         // Don't do anything if size of data already is multiple of
       
   668         // blocksize. Otherwise padding will be ruined. Return true anyway.
       
   669         if(!algInfo->iEncrypt)
       
   670             {
       
   671             size_of_checked = aSrc.Size() - aBlockSize;
       
   672         
       
   673             *algInfo->iLastPortion = aSrc.Right(aBlockSize);
       
   674 
       
   675             aSrc = aSrc.Left(size_of_checked);
       
   676             }
       
   677         
       
   678         // 3des fix ends.
       
   679 
       
   680         return true;
       
   681         }
       
   682     else
       
   683         {
       
   684         size_of_checked = aSrc.Size() - size_of_last_block;
       
   685         
       
   686         *algInfo->iLastPortion = aSrc.Right(size_of_last_block);
       
   687 
       
   688         aSrc = aSrc.Left(size_of_checked);
       
   689 
       
   690         return true;
       
   691         }     
       
   692     }
       
   693 
       
   694 // -----------------------------------------------------------------------------
       
   695 // CCrCrypto::DeriveKeyPKCS12L
       
   696 // Derives key(s) or IV vector from password, salt and iterarion count.
       
   697 // Return Values:  KCrOK
       
   698 //                 KCrNotSupportedAlg
       
   699 //                 KCrUndefinedLibrary
       
   700 //                 KCrUnknownLibrary
       
   701 //                 KCrUnknownMode
       
   702 //                 KCrErrorGeneral
       
   703 // -----------------------------------------------------------------------------
       
   704 TCrStatus CCrCrypto::DeriveKeyPKCS12L(
       
   705     const TDesC8&   aPassword, 
       
   706     const TDesC8&   aSalt,
       
   707     const TInt      aIterationCount,
       
   708     TCrAlgorithm    aHashFunc,
       
   709     const TUint8    aID,
       
   710     const TInt      aNumberOfBytes,
       
   711     TDes8&          aTrg)               // Output data, possible keys and IV
       
   712     {
       
   713     TInt remainder = 0;
       
   714     TInt rounds = 0;
       
   715     TInt pushedToCStack = 0;
       
   716     TInt inputSize = MesDigestInputSize(aHashFunc);
       
   717     TInt outputSize = MesDigestOutputSize(aHashFunc);
       
   718 
       
   719     // Step 1: Construct D by concatenating copies of ID.
       
   720     // Construct a string D
       
   721     HBufC8* D_buf = HBufC8::NewLC(inputSize);
       
   722     ++pushedToCStack;
       
   723 
       
   724     TPtr8 D_ptr = D_buf->Des();
       
   725 	TInt i(0);
       
   726     for (i = 0; i < inputSize; ++i)
       
   727         {
       
   728         D_ptr.Append(aID);
       
   729         }
       
   730 
       
   731     // Step 2, 3, 4:
       
   732     TInt s_length = 0;
       
   733     TInt p_length = 0;
       
   734 
       
   735     s_length = inputSize * ((aSalt.Size() + inputSize - 1) / inputSize);
       
   736     p_length = inputSize * ((aPassword.Size() + inputSize - 1) / inputSize);
       
   737     
       
   738     HBufC8* I_buf = HBufC8::NewLC(s_length + p_length);
       
   739     ++pushedToCStack;
       
   740     TPtr8 I_ptr = I_buf->Des();
       
   741 
       
   742     if (aSalt.Size() != 0)
       
   743         {
       
   744         rounds = s_length / aSalt.Size();
       
   745         for (i = 0; i < rounds; ++i)
       
   746             {
       
   747             I_ptr.Append(aSalt);
       
   748             }
       
   749         remainder = s_length % aSalt.Size();
       
   750         if (remainder != 0)
       
   751             {
       
   752             I_ptr.Append(aSalt.Ptr(), remainder);
       
   753             }
       
   754         }
       
   755              
       
   756     
       
   757     if (aPassword.Size() != 0)
       
   758         {
       
   759         rounds = p_length / aPassword.Size();
       
   760         for (i = 0; i < rounds; ++i)
       
   761             {
       
   762             I_ptr.Append(aPassword);
       
   763             }
       
   764         remainder = p_length % aPassword.Size();
       
   765         if (remainder != 0)
       
   766             {
       
   767             I_ptr.Append(aPassword.Ptr(), remainder);
       
   768             }
       
   769         }
       
   770 
       
   771     // Step 5: Set c.
       
   772     TInt c = 0;
       
   773     c = (aNumberOfBytes + outputSize - 1) / outputSize; 
       
   774     
       
   775     // Step 6: Loop
       
   776     TCrStatus status = KCrCrypto | KCrErrorGeneral;
       
   777     
       
   778     CCrCrypto* hash = 0;
       
   779 
       
   780     HBufC8* B_buf = HBufC8::NewLC(inputSize);
       
   781     ++pushedToCStack;
       
   782     TPtr8 B_ptr = B_buf->Des();
       
   783 
       
   784     HBufC8* A_buf = HBufC8::NewLC(D_ptr.Size() + I_ptr.Size());    
       
   785     ++pushedToCStack;
       
   786     TPtr8 A_ptr = A_buf->Des();
       
   787     
       
   788     TInt j = 0;
       
   789     RInteger B_int;
       
   790     RInteger Ij_int;
       
   791     TInt N = aNumberOfBytes;
       
   792 
       
   793     rounds = inputSize / outputSize;
       
   794     remainder = inputSize % outputSize;
       
   795 
       
   796     for (i = 0; i < c; ++i)
       
   797         {
       
   798         A_ptr.Zero();
       
   799         A_ptr.Append(D_ptr);
       
   800         A_ptr.Append(I_ptr);
       
   801         
       
   802         hash = CCrCrypto::NewLC();
       
   803 
       
   804         for (TInt ii = 0; ii < aIterationCount; ++ii)
       
   805             {
       
   806             status = hash->InitDigestL(aHashFunc);
       
   807             status = hash->ProcessL(A_ptr, A_ptr); 
       
   808             A_ptr.Zero();
       
   809             status = hash->FinalDigest(A_ptr);
       
   810             hash->Reset();
       
   811             }
       
   812         
       
   813         CleanupStack::PopAndDestroy(); // hash
       
   814 
       
   815         if (outputSize < N)
       
   816             {
       
   817             aTrg.Append(A_ptr);
       
   818             }
       
   819         else
       
   820             {
       
   821             aTrg.Append(A_ptr.Ptr(), N);
       
   822             }
       
   823 
       
   824         if (outputSize >= N)
       
   825             {
       
   826             status = KCrOK;
       
   827             break;
       
   828             }
       
   829 
       
   830         N -= outputSize;
       
   831 
       
   832         rounds = inputSize / A_ptr.Size();
       
   833         remainder = inputSize % A_ptr.Size();
       
   834         for (j = 0; j < rounds; ++j)
       
   835             {
       
   836             B_ptr.Append(A_ptr);
       
   837             }
       
   838         if (remainder != 0)
       
   839             {
       
   840             B_ptr.Append(A_ptr.Ptr(), remainder);
       
   841             }
       
   842         
       
   843         B_int = RInteger::NewL(B_ptr);  
       
   844 		CleanupStack::PushL(B_int);
       
   845         
       
   846         B_int += 1;
       
   847 
       
   848         for (j = 0; j < I_ptr.Size(); j += inputSize)
       
   849             {
       
   850             Ij_int = RInteger::NewL(I_ptr.Mid(j, inputSize));
       
   851 			CleanupStack::PushL(Ij_int);
       
   852             Ij_int += B_int;
       
   853             
       
   854             I_ptr.Replace(j, inputSize, Ij_int.BufferLC()->Right(inputSize));
       
   855 
       
   856             CleanupStack::PopAndDestroy(2); // Ij_int, BufferLC            
       
   857             }
       
   858 
       
   859         CleanupStack::PopAndDestroy(); // B_int
       
   860         }
       
   861 
       
   862     CleanupStack::PopAndDestroy(pushedToCStack); 
       
   863 
       
   864     return status;          
       
   865 }
       
   866 
       
   867 // -----------------------------------------------------------------------------
       
   868 // CCrCrypto::MesDigestInputSize
       
   869 // Returns input size of the message digest algorithm. 
       
   870 // Return Values:      Input size of the message digest algorithm in bytes.
       
   871 //                     If unknown algorithm returns -1.      
       
   872 // -----------------------------------------------------------------------------
       
   873 TInt CCrCrypto::MesDigestInputSize(TCrAlgorithm aDigestAlg)
       
   874     {
       
   875     switch(aDigestAlg)
       
   876         {
       
   877         case ECrSHA1:
       
   878         case ECrMD5:
       
   879         case ECrMD2:
       
   880             {
       
   881             return KDigestInputSize;
       
   882             }
       
   883         default:
       
   884             {
       
   885             return -1;
       
   886             }
       
   887         }
       
   888     }
       
   889 
       
   890 // -----------------------------------------------------------------------------
       
   891 // CCrCrypto::MesDigestOutputSize
       
   892 // Returns output size of the message digest algorithm. 
       
   893 // Parameters:         aDigestAlg           message digest algortihm
       
   894 // Return Values:      Output size of the message digest algorithm in bytes.
       
   895 //                     If unknown algorithm returns -1.      
       
   896 // -----------------------------------------------------------------------------
       
   897 TInt CCrCrypto::MesDigestOutputSize(TCrAlgorithm aDigestAlg)
       
   898     {
       
   899     switch(aDigestAlg)
       
   900         {
       
   901         case ECrSHA1:
       
   902             {
       
   903             return KCrLongDigestLength;
       
   904             }
       
   905         case ECrMD5:
       
   906         case ECrMD2:
       
   907             {
       
   908             return KCrMediumDigestLength;
       
   909             }
       
   910         default:
       
   911             {
       
   912             return -1;
       
   913             }
       
   914         }
       
   915     }
       
   916 
       
   917 // End Of Line
       
   918 
       
   919