vpnengine/ikev1lib/src/ikev1crypto.cpp
changeset 0 33413c0669b9
equal deleted inserted replaced
-1:000000000000 0:33413c0669b9
       
     1 /*
       
     2 * Copyright (c) 2005-2009 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: 
       
    15 * Crypto Layer to use and change any cryptolibrary easily.
       
    16 * Contains all the cryptographic functions used in IKEv1.
       
    17 *
       
    18 */
       
    19 
       
    20 
       
    21 
       
    22 #include "ikev1crypto.h"
       
    23 #include "ikemsgheader.h"
       
    24 #include "dhparameters.h"
       
    25 #include "utlcrypto.h"
       
    26 
       
    27 CIkeKeys* CIkeKeys::NewL(const TDesC8& aN, const TDesC8& aG)
       
    28 {
       
    29     CIkeKeys *keys = new (ELeave) CIkeKeys();
       
    30     keys->iDHKey = TUtlCrypto::MakeDiffieHellmanL(aN, aG);
       
    31 	keys->iModuluslength = aN.Length();
       
    32     return keys;
       
    33 }
       
    34 
       
    35 CIkeKeys::~CIkeKeys()
       
    36 {
       
    37     delete iDHKey;
       
    38 }
       
    39 
       
    40 
       
    41 HBufC8* CIkeKeys::GetPubKey()
       
    42 {
       
    43     HBufC8* DHPublicKey = (HBufC8*)iPubKey;
       
    44     iPubKey = NULL; // Exclusive ownership of iPubKey buffer is returned to caller
       
    45     return DHPublicKey;
       
    46 }
       
    47 
       
    48 void CIkeKeys::XValueL()
       
    49 {
       
    50     iPubKey = iDHKey->GenerateXL();
       
    51 }
       
    52 
       
    53 
       
    54 const HBufC8* CIkeKeys::KValueL(const TDesC8& aY) const 
       
    55 {
       
    56     return iDHKey->CompleteKL(aY);
       
    57 }
       
    58 
       
    59 
       
    60 
       
    61 
       
    62 //Generates a group of parameters depending on the group.
       
    63 CIkeKeys *CreateDHKeyL(TUint aGroupDesc)
       
    64 {
       
    65     TPtrC8 prime_ptr(NULL, 0);
       
    66     TPtrC8 gen_ptr(NULL, 0);
       
    67 
       
    68     switch (aGroupDesc)
       
    69     {
       
    70     case MODP_768:
       
    71         prime_ptr.Set((TUint8 *)&MODP_768_PRIME[0], MODP_768_PRIME_LENGTH);
       
    72         gen_ptr.Set((TUint8 *)&MODP_768_GENERATOR[0], MODP_768_GENERATOR_LENGTH);
       
    73         break;
       
    74     case MODP_1024:
       
    75         prime_ptr.Set((TUint8 *)&MODP_1024_PRIME[0], MODP_1024_PRIME_LENGTH);
       
    76         gen_ptr.Set((TUint8 *)&MODP_1024_GENERATOR[0], MODP_1024_GENERATOR_LENGTH);
       
    77         break;
       
    78     case MODP_1536:
       
    79         prime_ptr.Set((TUint8 *)&MODP_1536_PRIME[0], MODP_1536_PRIME_LENGTH);
       
    80         gen_ptr.Set((TUint8 *)&MODP_1536_GENERATOR[0], MODP_1536_GENERATOR_LENGTH);
       
    81         break;
       
    82     case MODP_2048:
       
    83         prime_ptr.Set((TUint8 *)&MODP_2048_PRIME[0], MODP_2048_PRIME_LENGTH);
       
    84         gen_ptr.Set((TUint8 *)&MODP_2048_GENERATOR[0], MODP_2048_GENERATOR_LENGTH);
       
    85         break;
       
    86     case EC2N_155:
       
    87     case EC2N_185:
       
    88         return NULL;
       
    89     default:    //Cannot happen because checked before!!!
       
    90         return NULL;
       
    91     }
       
    92     
       
    93     CIkeKeys *arg = CIkeKeys::NewL(prime_ptr, gen_ptr);
       
    94     
       
    95     return arg;
       
    96 }
       
    97 
       
    98 CIkeKeys *GeneratePubPrivKeysL(TUint aGroupDesc)
       
    99 {
       
   100     CIkeKeys *dh_key = CreateDHKeyL(aGroupDesc);
       
   101     if (!dh_key)
       
   102         return NULL;
       
   103     dh_key->XValueL();    //Initializes the public and private keys.
       
   104 
       
   105     return dh_key;
       
   106 
       
   107 }
       
   108 
       
   109 HBufC8* ComputeAgreedKeyL(TUint /*aGroupDesc*/, const TDesC8 &aPeerPublicKey, CIkeKeys *aOwnKeys)
       
   110 {
       
   111     if(!aOwnKeys)
       
   112         return NULL;
       
   113 
       
   114 	return (HBufC8*)aOwnKeys->KValueL(aPeerPublicKey);
       
   115 }
       
   116 
       
   117 void DecryptL(const TUint8* aInputPayload, TUint8* aOutputPayload, TUint32 aLength, TDes8& aIV, TDesC8& aKey, TUint16 aEncrAlg)
       
   118 {
       
   119     TUtlCrypto::TUtlSymmetricCipherId CipherId = TUtlCrypto::EUtlSymmetricCipherAesCbc;  // Defaults
       
   120     TInt IVLth = AESCBC_IV_LEN;
       
   121 	
       
   122     if ( aEncrAlg == DES3_CBC )
       
   123 	{
       
   124 		CipherId = TUtlCrypto::EUtlSymmetricCipher3DesCbc;
       
   125 		IVLth    = DESCBC_IV_LEN;
       
   126     }    
       
   127     else if ( aEncrAlg == DES_CBC)
       
   128 	{
       
   129 		CipherId = TUtlCrypto::EUtlSymmetricCipherDesCbc;
       
   130 		IVLth    = DESCBC_IV_LEN;		
       
   131     }       
       
   132     //
       
   133     //  Construct cipher object for symmetric decrypt operation
       
   134     //
       
   135     TPtrC8 iv_ptr(aIV.Ptr(), IVLth);
       
   136     TPtrC8 ciphertext(aInputPayload, aLength);
       
   137     TPtr8  plaintext(aOutputPayload, aLength);
       
   138 	
       
   139 	CUtlSymmetricCipher* UtlCipher = TUtlCrypto::MakeSymmetricDecryptorL(CipherId,
       
   140 		                                                                 aKey,
       
   141 	                                                                     iv_ptr);
       
   142 	
       
   143     CleanupStack::PushL(UtlCipher);
       
   144     UtlCipher->ProcessFinalL(ciphertext, plaintext);
       
   145     CleanupStack::PopAndDestroy();
       
   146     aIV.Copy(&aInputPayload[aLength - IVLth], IVLth);   //Next IV (last 8 bytes of ciphertext)     
       
   147                                                                            
       
   148 }
       
   149 
       
   150 TBool EncryptL(TDes8& aInputPayload, TDes8& aOutputPayload, TDes8& aIV, TDesC8& aKey, TUint16 aEncrAlg)
       
   151 {
       
   152     TUtlCrypto::TUtlSymmetricCipherId CipherId = TUtlCrypto::EUtlSymmetricCipherAesCbc;  // Defaults
       
   153     TInt CbLth = AESCBC_IV_LEN;
       
   154 	
       
   155     if ( aEncrAlg == DES3_CBC )
       
   156 	{
       
   157         CipherId = TUtlCrypto::EUtlSymmetricCipher3DesCbc;
       
   158 		CbLth    = DESCBC_IV_LEN;
       
   159     }    
       
   160     else if ( aEncrAlg == DES_CBC)
       
   161 	{
       
   162         CipherId = TUtlCrypto::EUtlSymmetricCipherDesCbc;
       
   163 		CbLth    = DESCBC_IV_LEN;
       
   164     }
       
   165     TPtrC8 iv_ptr(aIV.Ptr(), CbLth);
       
   166     //
       
   167     // Add padding, if needed
       
   168     //
       
   169     TUint padding_bytes = (aInputPayload.Length() - ISAKMP_HDR_SIZE) % CbLth;
       
   170     if (padding_bytes != 0)   //Padd with 0 at the end if needed
       
   171     {
       
   172         TChar c(0);
       
   173         aInputPayload.AppendFill(c,CbLth-padding_bytes);    //Append at the end
       
   174     }
       
   175     //
       
   176     // ISAKMP fixed header not encrypted
       
   177     //
       
   178     TPtrC8 plaintext(aInputPayload.Ptr() + ISAKMP_HDR_SIZE, aInputPayload.Length() - ISAKMP_HDR_SIZE);//skip hdr
       
   179     aOutputPayload.Copy(aInputPayload.Ptr(), ISAKMP_HDR_SIZE);  //The same HDR in output
       
   180     
       
   181     TPtr8 ciphertext((TUint8 *)aOutputPayload.Ptr() + ISAKMP_HDR_SIZE, 0, aInputPayload.Length() - ISAKMP_HDR_SIZE);//skip hdr  
       
   182     //
       
   183     //  Construct cipher object for symmetric decrypt operation
       
   184     //
       
   185 	CUtlSymmetricCipher* UtlCipher = TUtlCrypto::MakeSymmetricEncryptorL(CipherId,
       
   186 	                                                                     aKey,
       
   187 		                                                                 iv_ptr);
       
   188     CleanupStack::PushL(UtlCipher);     
       
   189     UtlCipher->ProcessFinalL(plaintext, ciphertext);
       
   190     CleanupStack::PopAndDestroy();     
       
   191     //
       
   192     // Next IV (last cipher block of encrypted buffer)
       
   193     //
       
   194     aOutputPayload.SetLength(ISAKMP_HDR_SIZE + ciphertext.Length());
       
   195     aIV.Copy(aOutputPayload.Ptr() + aOutputPayload.Length() - CbLth, CbLth); 
       
   196     
       
   197     return ETrue;
       
   198                                                                            
       
   199 }
       
   200 
       
   201 
       
   202 void MD5HashL(const TDesC8 &aInData, TDes8& aOutData)
       
   203 {
       
   204     CUtlMessageDigest* Digest = TUtlCrypto::MakeMessageDigesterL(TUtlCrypto::EUtlMessageDigestMd5);
       
   205     aOutData.Copy(Digest->Final(aInData));
       
   206     delete Digest;
       
   207 }
       
   208 
       
   209 void SHA1HashL(const TDesC8 &aInData, TDes8& aOutData)
       
   210 {
       
   211     CUtlMessageDigest* Digest = TUtlCrypto::MakeMessageDigesterL(TUtlCrypto::EUtlMessageDigestSha1);
       
   212     aOutData.Copy(Digest->Final(aInData));
       
   213     delete Digest;
       
   214 }
       
   215 
       
   216 void MD5HmacL(const TDesC8 &aInData, TDes8& aOutData, const TDesC8& aKeyData)
       
   217 {
       
   218     CUtlMessageDigest* Digest = TUtlCrypto::MakeMessageDigesterL(TUtlCrypto::EUtlMessageDigestMd5,
       
   219                                                                  aKeyData);
       
   220     aOutData.Copy(Digest->Final(aInData));  
       
   221     delete Digest;
       
   222 }
       
   223 
       
   224 void SHA1HmacL(const TDesC8 &aInData, TDes8& aOutData, const TDesC8& aKeyData)
       
   225 {
       
   226     CUtlMessageDigest* Digest = TUtlCrypto::MakeMessageDigesterL(TUtlCrypto::EUtlMessageDigestSha1,
       
   227                                                                  aKeyData);
       
   228     aOutData.Copy(Digest->Final(aInData));  
       
   229     delete Digest;
       
   230 }
       
   231 
       
   232 void Hmac3DesCbcL(const TDesC8 &aInData, TDes8& aOutData, const TDesC8& aKeyData)
       
   233 {
       
   234     TUint8 *pad = new (ELeave) TUint8[PAD_SIZE];
       
   235     TInt pad_len = 0;
       
   236     CleanupStack::PushL(pad);
       
   237     TBuf8<8> iv;
       
   238     TBuf8<24> prf_key2;
       
   239     TPtrC8 prf_key_ptr;
       
   240         
       
   241     if ( aKeyData.Length() < 24)  //if less than 24 bits the rest must be 0's
       
   242     {
       
   243        prf_key2.FillZ(24);
       
   244        prf_key2.Copy(aKeyData);
       
   245        prf_key2.SetLength(24);
       
   246        prf_key_ptr.Set(prf_key2);
       
   247     }
       
   248     else
       
   249     {   
       
   250        prf_key_ptr.Set(aKeyData);
       
   251     }   
       
   252     iv.FillZ(8);
       
   253     Mem::Copy(pad, aInData.Ptr(), aInData.Length());
       
   254     pad_len = aInData.Length();
       
   255     if ( pad_len & 0x07 ) //Add padding to align to byte pieces??????????
       
   256     {
       
   257        Mem::FillZ(&pad[pad_len], 7);
       
   258        pad_len += 7;
       
   259        pad_len = (pad_len & 65528) + 8;
       
   260     }
       
   261     Cipher3DesL(pad, pad_len, prf_key_ptr, iv, aOutData);
       
   262 
       
   263     CleanupStack::PopAndDestroy();  //pad       
       
   264     
       
   265 }
       
   266 
       
   267 void Cipher3DesL(TUint8 *aInData, TInt aInDataLen, const TDesC8 &aPrfKey, TDes8 &aIV, TDes8 &aOutData)
       
   268 {
       
   269 
       
   270     TPtrC8 iv_ptr(aIV.Ptr(), DESCBC_IV_LEN);
       
   271     TPtrC8 key_ptr(aPrfKey.Ptr(), 3*DESCBC_KEY_LEN);
       
   272     
       
   273     HBufC8 *des_input = HBufC8::NewL(aInDataLen + 8);
       
   274     CleanupStack::PushL(des_input);         
       
   275     TPtr8 des_input_ptr((TUint8 *)des_input->Des().Ptr(), aInDataLen + 8, aInDataLen + 8);  //Contains the PRF input text
       
   276     TPtrC8 plain_input_text(aInData, aInDataLen);//skip hdr
       
   277     //
       
   278     //  Construct cipher object for symmetric decrypt operation
       
   279     //
       
   280     CUtlSymmetricCipher* UtlCipher = TUtlCrypto::MakeSymmetricEncryptorL(TUtlCrypto::EUtlSymmetricCipher3DesCbc,
       
   281                                                                          key_ptr,
       
   282                                                                          iv_ptr);
       
   283     CleanupStack::PushL(UtlCipher);
       
   284     
       
   285     HBufC8 *des_output= HBufC8::NewL(des_input_ptr.Length() + UtlCipher->BlockSize());
       
   286     CleanupStack::PushL(des_output);            
       
   287     TPtr8 des_output_ptr((TUint8 *)des_output->Des().Ptr(), des_input_ptr.Length() + UtlCipher->BlockSize());
       
   288 
       
   289     UtlCipher->ProcessFinalL(plain_input_text, des_output_ptr);
       
   290     TPtrC8 tmp_input_data(&des_output_ptr[des_output_ptr.Length() - 8], 8); //Input Data to the 2nd 8-bit chunk encryption  
       
   291     UtlCipher->Reset();    //Restart
       
   292     UtlCipher->ProcessFinalL(tmp_input_data, aOutData); 
       
   293     
       
   294     // Do second eight bytes
       
   295     des_input_ptr.Copy(aOutData);
       
   296     des_input_ptr.Append(plain_input_text); //reattach the input data
       
   297     UtlCipher->Reset();    //Restart
       
   298     UtlCipher->ProcessFinalL(des_input_ptr, des_output_ptr);
       
   299     
       
   300     tmp_input_data.Set(&des_output_ptr[des_output_ptr.Length() - 8], 8);
       
   301     TPtr8 out_data_ptr((TUint8 *)aOutData.Ptr() + 8, 0, 8);
       
   302     UtlCipher->Reset();    //Restart
       
   303     UtlCipher->ProcessFinalL(tmp_input_data, out_data_ptr);
       
   304     
       
   305     // Do third eight bytes 
       
   306     Mem::Copy((TUint8 *)des_input_ptr.Ptr(), aOutData.Ptr() + 8, 8);    //last 8 bytes of previous result put at the beginning
       
   307     //The length of des_input_ptr won't change so the data after byte 8 is still used!!!    
       
   308     UtlCipher->Reset();    //Restart
       
   309     UtlCipher->ProcessFinalL(des_input_ptr, des_output_ptr);
       
   310     
       
   311     tmp_input_data.Set(&des_output_ptr[des_output_ptr.Length() - 8], 8);
       
   312     out_data_ptr.Set((TUint8 *)aOutData.Ptr() + 16, 0, 8);  //the last 8 bytes (16 to 23)
       
   313     UtlCipher->Reset();    //Restart
       
   314     UtlCipher->ProcessFinalL(tmp_input_data, out_data_ptr);
       
   315     
       
   316     aOutData.SetLength(24);
       
   317 
       
   318     CleanupStack::PopAndDestroy(3); // des_output, UtlCipher and  des_input     
       
   319 }
       
   320 
       
   321 TInt SymmetricCipherL(TUint8 *aInput,  TUint8 *aOutput, TInt aLength,
       
   322 				      TUint8 *aKey,    TUint8 *aIV, TBool aEncr, TInt aEncAlg)
       
   323 {
       
   324 	(void)aEncAlg;
       
   325 	TPtrC8 iv_ptr(aIV, DESCBC_IV_LEN );
       
   326 	TPtrC8 key_ptr(aKey, DESCBC_IV_LEN);
       
   327 
       
   328 	CUtlSymmetricCipher* UtlCipher; 
       
   329 	if ( aEncr ) {
       
   330     	//
       
   331 	    // Add padding (according RFC 1423) and encrypt data 
       
   332 	    //
       
   333        TInt PaddingBytes = 8 - (aLength % 8);
       
   334 	   for ( TInt i = 0; i < PaddingBytes; i++ ) {
       
   335 		   *(aInput + aLength + i) = (TUint8)PaddingBytes;
       
   336 	   }
       
   337 	   aLength += PaddingBytes;
       
   338 	   UtlCipher = TUtlCrypto::MakeSymmetricEncryptorL(TUtlCrypto::EUtlSymmetricCipherDesCbc,
       
   339 			                                            key_ptr, iv_ptr);
       
   340 	}	 
       
   341 	else {
       
   342 		//
       
   343 		// Decrypt data 
       
   344 		//
       
   345 	   UtlCipher = TUtlCrypto::MakeSymmetricDecryptorL(TUtlCrypto::EUtlSymmetricCipherDesCbc,
       
   346 		                                               key_ptr, iv_ptr);
       
   347 	}
       
   348 	CleanupStack::PushL(UtlCipher);
       
   349 	TPtrC8 inp(aInput, aLength);
       
   350 	TPtr8 outp(aOutput, aLength);
       
   351 	UtlCipher->ProcessFinalL(inp, outp);
       
   352 	CleanupStack::PopAndDestroy();
       
   353 
       
   354 	if ( !aEncr ) {
       
   355 	   //
       
   356 	   // Remove padding from decrypted data
       
   357 	   //
       
   358 	   TUint8 PaddingLth = *(aOutput + aLength - 1);
       
   359 	   if ( PaddingLth < 9 )
       
   360 		    aLength -= (TInt)PaddingLth;      // Ok padding count
       
   361 	   else aLength = 0;
       
   362 	}
       
   363 
       
   364 	return aLength;
       
   365 		
       
   366 }
       
   367 
       
   368 
       
   369