vpnengine/ikev1lib/src/ikev1crypto.cpp
changeset 0 33413c0669b9
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vpnengine/ikev1lib/src/ikev1crypto.cpp	Thu Dec 17 09:14:51 2009 +0200
@@ -0,0 +1,369 @@
+/*
+* Copyright (c) 2005-2009 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: 
+* Crypto Layer to use and change any cryptolibrary easily.
+* Contains all the cryptographic functions used in IKEv1.
+*
+*/
+
+
+
+#include "ikev1crypto.h"
+#include "ikemsgheader.h"
+#include "dhparameters.h"
+#include "utlcrypto.h"
+
+CIkeKeys* CIkeKeys::NewL(const TDesC8& aN, const TDesC8& aG)
+{
+    CIkeKeys *keys = new (ELeave) CIkeKeys();
+    keys->iDHKey = TUtlCrypto::MakeDiffieHellmanL(aN, aG);
+	keys->iModuluslength = aN.Length();
+    return keys;
+}
+
+CIkeKeys::~CIkeKeys()
+{
+    delete iDHKey;
+}
+
+
+HBufC8* CIkeKeys::GetPubKey()
+{
+    HBufC8* DHPublicKey = (HBufC8*)iPubKey;
+    iPubKey = NULL; // Exclusive ownership of iPubKey buffer is returned to caller
+    return DHPublicKey;
+}
+
+void CIkeKeys::XValueL()
+{
+    iPubKey = iDHKey->GenerateXL();
+}
+
+
+const HBufC8* CIkeKeys::KValueL(const TDesC8& aY) const 
+{
+    return iDHKey->CompleteKL(aY);
+}
+
+
+
+
+//Generates a group of parameters depending on the group.
+CIkeKeys *CreateDHKeyL(TUint aGroupDesc)
+{
+    TPtrC8 prime_ptr(NULL, 0);
+    TPtrC8 gen_ptr(NULL, 0);
+
+    switch (aGroupDesc)
+    {
+    case MODP_768:
+        prime_ptr.Set((TUint8 *)&MODP_768_PRIME[0], MODP_768_PRIME_LENGTH);
+        gen_ptr.Set((TUint8 *)&MODP_768_GENERATOR[0], MODP_768_GENERATOR_LENGTH);
+        break;
+    case MODP_1024:
+        prime_ptr.Set((TUint8 *)&MODP_1024_PRIME[0], MODP_1024_PRIME_LENGTH);
+        gen_ptr.Set((TUint8 *)&MODP_1024_GENERATOR[0], MODP_1024_GENERATOR_LENGTH);
+        break;
+    case MODP_1536:
+        prime_ptr.Set((TUint8 *)&MODP_1536_PRIME[0], MODP_1536_PRIME_LENGTH);
+        gen_ptr.Set((TUint8 *)&MODP_1536_GENERATOR[0], MODP_1536_GENERATOR_LENGTH);
+        break;
+    case MODP_2048:
+        prime_ptr.Set((TUint8 *)&MODP_2048_PRIME[0], MODP_2048_PRIME_LENGTH);
+        gen_ptr.Set((TUint8 *)&MODP_2048_GENERATOR[0], MODP_2048_GENERATOR_LENGTH);
+        break;
+    case EC2N_155:
+    case EC2N_185:
+        return NULL;
+    default:    //Cannot happen because checked before!!!
+        return NULL;
+    }
+    
+    CIkeKeys *arg = CIkeKeys::NewL(prime_ptr, gen_ptr);
+    
+    return arg;
+}
+
+CIkeKeys *GeneratePubPrivKeysL(TUint aGroupDesc)
+{
+    CIkeKeys *dh_key = CreateDHKeyL(aGroupDesc);
+    if (!dh_key)
+        return NULL;
+    dh_key->XValueL();    //Initializes the public and private keys.
+
+    return dh_key;
+
+}
+
+HBufC8* ComputeAgreedKeyL(TUint /*aGroupDesc*/, const TDesC8 &aPeerPublicKey, CIkeKeys *aOwnKeys)
+{
+    if(!aOwnKeys)
+        return NULL;
+
+	return (HBufC8*)aOwnKeys->KValueL(aPeerPublicKey);
+}
+
+void DecryptL(const TUint8* aInputPayload, TUint8* aOutputPayload, TUint32 aLength, TDes8& aIV, TDesC8& aKey, TUint16 aEncrAlg)
+{
+    TUtlCrypto::TUtlSymmetricCipherId CipherId = TUtlCrypto::EUtlSymmetricCipherAesCbc;  // Defaults
+    TInt IVLth = AESCBC_IV_LEN;
+	
+    if ( aEncrAlg == DES3_CBC )
+	{
+		CipherId = TUtlCrypto::EUtlSymmetricCipher3DesCbc;
+		IVLth    = DESCBC_IV_LEN;
+    }    
+    else if ( aEncrAlg == DES_CBC)
+	{
+		CipherId = TUtlCrypto::EUtlSymmetricCipherDesCbc;
+		IVLth    = DESCBC_IV_LEN;		
+    }       
+    //
+    //  Construct cipher object for symmetric decrypt operation
+    //
+    TPtrC8 iv_ptr(aIV.Ptr(), IVLth);
+    TPtrC8 ciphertext(aInputPayload, aLength);
+    TPtr8  plaintext(aOutputPayload, aLength);
+	
+	CUtlSymmetricCipher* UtlCipher = TUtlCrypto::MakeSymmetricDecryptorL(CipherId,
+		                                                                 aKey,
+	                                                                     iv_ptr);
+	
+    CleanupStack::PushL(UtlCipher);
+    UtlCipher->ProcessFinalL(ciphertext, plaintext);
+    CleanupStack::PopAndDestroy();
+    aIV.Copy(&aInputPayload[aLength - IVLth], IVLth);   //Next IV (last 8 bytes of ciphertext)     
+                                                                           
+}
+
+TBool EncryptL(TDes8& aInputPayload, TDes8& aOutputPayload, TDes8& aIV, TDesC8& aKey, TUint16 aEncrAlg)
+{
+    TUtlCrypto::TUtlSymmetricCipherId CipherId = TUtlCrypto::EUtlSymmetricCipherAesCbc;  // Defaults
+    TInt CbLth = AESCBC_IV_LEN;
+	
+    if ( aEncrAlg == DES3_CBC )
+	{
+        CipherId = TUtlCrypto::EUtlSymmetricCipher3DesCbc;
+		CbLth    = DESCBC_IV_LEN;
+    }    
+    else if ( aEncrAlg == DES_CBC)
+	{
+        CipherId = TUtlCrypto::EUtlSymmetricCipherDesCbc;
+		CbLth    = DESCBC_IV_LEN;
+    }
+    TPtrC8 iv_ptr(aIV.Ptr(), CbLth);
+    //
+    // Add padding, if needed
+    //
+    TUint padding_bytes = (aInputPayload.Length() - ISAKMP_HDR_SIZE) % CbLth;
+    if (padding_bytes != 0)   //Padd with 0 at the end if needed
+    {
+        TChar c(0);
+        aInputPayload.AppendFill(c,CbLth-padding_bytes);    //Append at the end
+    }
+    //
+    // ISAKMP fixed header not encrypted
+    //
+    TPtrC8 plaintext(aInputPayload.Ptr() + ISAKMP_HDR_SIZE, aInputPayload.Length() - ISAKMP_HDR_SIZE);//skip hdr
+    aOutputPayload.Copy(aInputPayload.Ptr(), ISAKMP_HDR_SIZE);  //The same HDR in output
+    
+    TPtr8 ciphertext((TUint8 *)aOutputPayload.Ptr() + ISAKMP_HDR_SIZE, 0, aInputPayload.Length() - ISAKMP_HDR_SIZE);//skip hdr  
+    //
+    //  Construct cipher object for symmetric decrypt operation
+    //
+	CUtlSymmetricCipher* UtlCipher = TUtlCrypto::MakeSymmetricEncryptorL(CipherId,
+	                                                                     aKey,
+		                                                                 iv_ptr);
+    CleanupStack::PushL(UtlCipher);     
+    UtlCipher->ProcessFinalL(plaintext, ciphertext);
+    CleanupStack::PopAndDestroy();     
+    //
+    // Next IV (last cipher block of encrypted buffer)
+    //
+    aOutputPayload.SetLength(ISAKMP_HDR_SIZE + ciphertext.Length());
+    aIV.Copy(aOutputPayload.Ptr() + aOutputPayload.Length() - CbLth, CbLth); 
+    
+    return ETrue;
+                                                                           
+}
+
+
+void MD5HashL(const TDesC8 &aInData, TDes8& aOutData)
+{
+    CUtlMessageDigest* Digest = TUtlCrypto::MakeMessageDigesterL(TUtlCrypto::EUtlMessageDigestMd5);
+    aOutData.Copy(Digest->Final(aInData));
+    delete Digest;
+}
+
+void SHA1HashL(const TDesC8 &aInData, TDes8& aOutData)
+{
+    CUtlMessageDigest* Digest = TUtlCrypto::MakeMessageDigesterL(TUtlCrypto::EUtlMessageDigestSha1);
+    aOutData.Copy(Digest->Final(aInData));
+    delete Digest;
+}
+
+void MD5HmacL(const TDesC8 &aInData, TDes8& aOutData, const TDesC8& aKeyData)
+{
+    CUtlMessageDigest* Digest = TUtlCrypto::MakeMessageDigesterL(TUtlCrypto::EUtlMessageDigestMd5,
+                                                                 aKeyData);
+    aOutData.Copy(Digest->Final(aInData));  
+    delete Digest;
+}
+
+void SHA1HmacL(const TDesC8 &aInData, TDes8& aOutData, const TDesC8& aKeyData)
+{
+    CUtlMessageDigest* Digest = TUtlCrypto::MakeMessageDigesterL(TUtlCrypto::EUtlMessageDigestSha1,
+                                                                 aKeyData);
+    aOutData.Copy(Digest->Final(aInData));  
+    delete Digest;
+}
+
+void Hmac3DesCbcL(const TDesC8 &aInData, TDes8& aOutData, const TDesC8& aKeyData)
+{
+    TUint8 *pad = new (ELeave) TUint8[PAD_SIZE];
+    TInt pad_len = 0;
+    CleanupStack::PushL(pad);
+    TBuf8<8> iv;
+    TBuf8<24> prf_key2;
+    TPtrC8 prf_key_ptr;
+        
+    if ( aKeyData.Length() < 24)  //if less than 24 bits the rest must be 0's
+    {
+       prf_key2.FillZ(24);
+       prf_key2.Copy(aKeyData);
+       prf_key2.SetLength(24);
+       prf_key_ptr.Set(prf_key2);
+    }
+    else
+    {   
+       prf_key_ptr.Set(aKeyData);
+    }   
+    iv.FillZ(8);
+    Mem::Copy(pad, aInData.Ptr(), aInData.Length());
+    pad_len = aInData.Length();
+    if ( pad_len & 0x07 ) //Add padding to align to byte pieces??????????
+    {
+       Mem::FillZ(&pad[pad_len], 7);
+       pad_len += 7;
+       pad_len = (pad_len & 65528) + 8;
+    }
+    Cipher3DesL(pad, pad_len, prf_key_ptr, iv, aOutData);
+
+    CleanupStack::PopAndDestroy();  //pad       
+    
+}
+
+void Cipher3DesL(TUint8 *aInData, TInt aInDataLen, const TDesC8 &aPrfKey, TDes8 &aIV, TDes8 &aOutData)
+{
+
+    TPtrC8 iv_ptr(aIV.Ptr(), DESCBC_IV_LEN);
+    TPtrC8 key_ptr(aPrfKey.Ptr(), 3*DESCBC_KEY_LEN);
+    
+    HBufC8 *des_input = HBufC8::NewL(aInDataLen + 8);
+    CleanupStack::PushL(des_input);         
+    TPtr8 des_input_ptr((TUint8 *)des_input->Des().Ptr(), aInDataLen + 8, aInDataLen + 8);  //Contains the PRF input text
+    TPtrC8 plain_input_text(aInData, aInDataLen);//skip hdr
+    //
+    //  Construct cipher object for symmetric decrypt operation
+    //
+    CUtlSymmetricCipher* UtlCipher = TUtlCrypto::MakeSymmetricEncryptorL(TUtlCrypto::EUtlSymmetricCipher3DesCbc,
+                                                                         key_ptr,
+                                                                         iv_ptr);
+    CleanupStack::PushL(UtlCipher);
+    
+    HBufC8 *des_output= HBufC8::NewL(des_input_ptr.Length() + UtlCipher->BlockSize());
+    CleanupStack::PushL(des_output);            
+    TPtr8 des_output_ptr((TUint8 *)des_output->Des().Ptr(), des_input_ptr.Length() + UtlCipher->BlockSize());
+
+    UtlCipher->ProcessFinalL(plain_input_text, des_output_ptr);
+    TPtrC8 tmp_input_data(&des_output_ptr[des_output_ptr.Length() - 8], 8); //Input Data to the 2nd 8-bit chunk encryption  
+    UtlCipher->Reset();    //Restart
+    UtlCipher->ProcessFinalL(tmp_input_data, aOutData); 
+    
+    // Do second eight bytes
+    des_input_ptr.Copy(aOutData);
+    des_input_ptr.Append(plain_input_text); //reattach the input data
+    UtlCipher->Reset();    //Restart
+    UtlCipher->ProcessFinalL(des_input_ptr, des_output_ptr);
+    
+    tmp_input_data.Set(&des_output_ptr[des_output_ptr.Length() - 8], 8);
+    TPtr8 out_data_ptr((TUint8 *)aOutData.Ptr() + 8, 0, 8);
+    UtlCipher->Reset();    //Restart
+    UtlCipher->ProcessFinalL(tmp_input_data, out_data_ptr);
+    
+    // Do third eight bytes 
+    Mem::Copy((TUint8 *)des_input_ptr.Ptr(), aOutData.Ptr() + 8, 8);    //last 8 bytes of previous result put at the beginning
+    //The length of des_input_ptr won't change so the data after byte 8 is still used!!!    
+    UtlCipher->Reset();    //Restart
+    UtlCipher->ProcessFinalL(des_input_ptr, des_output_ptr);
+    
+    tmp_input_data.Set(&des_output_ptr[des_output_ptr.Length() - 8], 8);
+    out_data_ptr.Set((TUint8 *)aOutData.Ptr() + 16, 0, 8);  //the last 8 bytes (16 to 23)
+    UtlCipher->Reset();    //Restart
+    UtlCipher->ProcessFinalL(tmp_input_data, out_data_ptr);
+    
+    aOutData.SetLength(24);
+
+    CleanupStack::PopAndDestroy(3); // des_output, UtlCipher and  des_input     
+}
+
+TInt SymmetricCipherL(TUint8 *aInput,  TUint8 *aOutput, TInt aLength,
+				      TUint8 *aKey,    TUint8 *aIV, TBool aEncr, TInt aEncAlg)
+{
+	(void)aEncAlg;
+	TPtrC8 iv_ptr(aIV, DESCBC_IV_LEN );
+	TPtrC8 key_ptr(aKey, DESCBC_IV_LEN);
+
+	CUtlSymmetricCipher* UtlCipher; 
+	if ( aEncr ) {
+    	//
+	    // Add padding (according RFC 1423) and encrypt data 
+	    //
+       TInt PaddingBytes = 8 - (aLength % 8);
+	   for ( TInt i = 0; i < PaddingBytes; i++ ) {
+		   *(aInput + aLength + i) = (TUint8)PaddingBytes;
+	   }
+	   aLength += PaddingBytes;
+	   UtlCipher = TUtlCrypto::MakeSymmetricEncryptorL(TUtlCrypto::EUtlSymmetricCipherDesCbc,
+			                                            key_ptr, iv_ptr);
+	}	 
+	else {
+		//
+		// Decrypt data 
+		//
+	   UtlCipher = TUtlCrypto::MakeSymmetricDecryptorL(TUtlCrypto::EUtlSymmetricCipherDesCbc,
+		                                               key_ptr, iv_ptr);
+	}
+	CleanupStack::PushL(UtlCipher);
+	TPtrC8 inp(aInput, aLength);
+	TPtr8 outp(aOutput, aLength);
+	UtlCipher->ProcessFinalL(inp, outp);
+	CleanupStack::PopAndDestroy();
+
+	if ( !aEncr ) {
+	   //
+	   // Remove padding from decrypted data
+	   //
+	   TUint8 PaddingLth = *(aOutput + aLength - 1);
+	   if ( PaddingLth < 9 )
+		    aLength -= (TInt)PaddingLth;      // Ok padding count
+	   else aLength = 0;
+	}
+
+	return aLength;
+		
+}
+
+
+