--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/vpnengine/ikev2lib/src/ikecrypto.cpp Thu Dec 17 09:14:51 2009 +0200
@@ -0,0 +1,332 @@
+/*
+* Copyright (c) 2003-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: Intermediate class between IKEv2 and crypto library.
+*
+*/
+
+
+#include "dhparameters.h"
+#include "ikecrypto.h"
+#include "ikev2const.h"
+
+CDHKeys* CDHKeys::NewL(const TDesC8& aN, const TDesC8& aG)
+{
+ CDHKeys *keys = new (ELeave) CDHKeys();
+ keys->iDHKey = TUtlCrypto::MakeDiffieHellmanL(aN, aG);
+ keys->iModuluslength = aN.Length();
+ return keys;
+}
+
+CDHKeys* CDHKeys::CreateDHKeyL(TUint aGroupDesc)
+{
+ TPtrC8 prime_ptr(NULL, 0);
+ TPtrC8 gen_ptr(NULL, 0);
+
+ switch (aGroupDesc)
+ {
+ case DH_GROUP_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 DH_GROUP_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 DH_GROUP_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 DH_GROUP_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;
+ default: //Cannot happen because checked before!!!
+ User::Leave(KErrNotSupported);
+ }
+
+ CDHKeys *DhKeys = CDHKeys::NewL(prime_ptr, gen_ptr);
+
+ return DhKeys;
+}
+
+HBufC8* CDHKeys::ComputeAgreedKeyL(const TDesC8 &aPeerPublicKey)
+{
+ return (HBufC8*)KValueL(aPeerPublicKey);
+}
+
+
+HBufC8* CDHKeys::GetPubKey()
+{
+ HBufC8* DHPublicKey = (HBufC8*)iPubKey;
+ iPubKey = NULL; // Exclusive ownership of iPubKey buffer is returned to caller
+ return DHPublicKey;
+}
+
+void CDHKeys::XValueL()
+{
+ if ( !iPubKey )
+ iPubKey = iDHKey->GenerateXL();
+}
+
+CDHKeys::~CDHKeys()
+{
+ delete iDHKey;
+}
+
+
+void IkeCrypto::DecryptL(const TUint8* aInput, TUint8* aOutput, TInt aLength,
+ TUint8* aIV, const TDesC8& aKey, TUint16 aEncrAlg)
+{
+ TUtlCrypto::TUtlSymmetricCipherId CipherId;
+ TInt IVLth;
+ IkeCrypto::AlgorithmInfo(IKEV2_ENCR, aEncrAlg, &IVLth, &CipherId);
+
+ if ( !aInput || !aOutput || !aIV )
+ User::Leave(KErrArgument);
+
+ TPtrC8 IvPtr(aIV, IVLth);
+ TPtrC8 CipherText(aInput, aLength);
+ TPtr8 PlainText(aOutput, aLength);
+
+ CUtlSymmetricCipher* UtlCipher =
+ TUtlCrypto::MakeSymmetricDecryptorL(CipherId, aKey, IvPtr);
+ CleanupStack::PushL(UtlCipher);
+ UtlCipher->ProcessFinalL(CipherText, PlainText);
+ CleanupStack::PopAndDestroy(UtlCipher);
+}
+
+
+void IkeCrypto::EncryptL(const TDesC8& aInput, TPtr8& aOutput,
+ const TDesC8& aIv, const TDesC8& aKey, TUint16 aEncrAlg)
+{
+ TUtlCrypto::TUtlSymmetricCipherId CipherId;
+ TInt CbLth;
+ IkeCrypto::AlgorithmInfo(IKEV2_ENCR, aEncrAlg, &CbLth, &CipherId);
+
+ __ASSERT_DEBUG(CbLth == aIv.Length(), User::Invariant());
+ __ASSERT_DEBUG(aInput.Length() % CbLth == 0, User::Invariant());
+ __ASSERT_DEBUG(aInput.Length() <= aOutput.MaxLength(), User::Invariant());
+
+ CUtlSymmetricCipher* UtlCipher =
+ TUtlCrypto::MakeSymmetricEncryptorL(CipherId, aKey, aIv);
+ CleanupStack::PushL(UtlCipher);
+ UtlCipher->ProcessFinalL(aInput, aOutput);
+ CleanupStack::PopAndDestroy(UtlCipher);
+}
+
+TInt IkeCrypto::IntegHMACL(const TDesC8& aInput, TDes8& aChecksum, const TDesC8& aKeyData, TUint16 aIntegAlg)
+{
+ TUtlCrypto::TUtlMessageDigestId DigestId;
+ TInt HmacLth;
+ IkeCrypto::AlgorithmInfo(IKEV2_INTEG, aIntegAlg, &HmacLth, NULL, &DigestId);
+ CUtlMessageDigest* Digest = TUtlCrypto::MakeMessageDigesterL(DigestId, aKeyData);
+
+ const TPtrC8 hash = Digest->Final(aInput);
+
+ //We don't always use the whole hash.
+ //(e.g., HMAC-SHA1-96 uses only first 12 bytes)
+ __ASSERT_DEBUG(hash.Length() >= HmacLth, User::Invariant());
+
+ aChecksum = hash.Left(HmacLth);
+ delete Digest;
+
+ return HmacLth;
+}
+
+HBufC8* IkeCrypto::PrfhmacL(const TDesC8& aInput, const TDesC8& aKeyData, TUint16 aPrfAlg)
+{
+ TUtlCrypto::TUtlMessageDigestId DigestId;
+ TInt PrfLth;
+ IkeCrypto::AlgorithmInfo(IKEV2_PRF, aPrfAlg, &PrfLth, NULL, &DigestId);
+ CUtlMessageDigest* Digest = TUtlCrypto::MakeMessageDigesterL(DigestId, aKeyData);
+ CleanupStack::PushL(Digest);
+
+ HBufC8* checksum = Digest->Final(aInput).AllocL();
+
+ CleanupStack::PopAndDestroy(Digest);
+
+ return checksum;
+
+}
+
+HBufC8* IkeCrypto::PrfL(const TDesC8& aInput, TUint16 aPrfAlg)
+{
+ TUtlCrypto::TUtlMessageDigestId DigestId;
+ TInt PrfLth;
+ IkeCrypto::AlgorithmInfo(IKEV2_PRF, aPrfAlg, &PrfLth, NULL, &DigestId);
+ CUtlMessageDigest* digest = TUtlCrypto::MakeMessageDigesterL(DigestId);
+ CleanupStack::PushL(digest);
+
+ HBufC8* hash = digest->Final(aInput).AllocL();
+
+ CleanupStack::PopAndDestroy(digest);
+
+ return hash;
+
+}
+
+TInt IkeCrypto::AlgorithmInfo(TUint16 aTransform, TUint16 aAlgCode, TInt* aBlockLth,
+ TUtlCrypto::TUtlSymmetricCipherId* aCipherId,
+ TUtlCrypto::TUtlMessageDigestId* aDigestId)
+{
+ TInt KeyLth = 0;
+ TInt BlockLth = 0;
+
+ switch ( aTransform )
+ {
+ case IKEV2_ENCR:
+ switch ( aAlgCode )
+ {
+ case ENCR_DES:
+ KeyLth = 8;
+ BlockLth = 8;
+ if ( aCipherId )
+ *aCipherId = TUtlCrypto::EUtlSymmetricCipherDesCbc;
+ break;
+
+ case ENCR_3DES:
+ KeyLth = 24;
+ BlockLth = 8;
+ if ( aCipherId )
+ *aCipherId = TUtlCrypto::EUtlSymmetricCipher3DesCbc;
+ break;
+
+ case ENCR_AES_CBC:
+ KeyLth = 0;
+ BlockLth = 16;
+ if ( aCipherId )
+ *aCipherId = TUtlCrypto::EUtlSymmetricCipherAesCbc;
+ break;
+
+ case ENCR_NULL:
+ KeyLth = 0;
+ BlockLth = 0;
+ break;
+ default:
+ break;
+ }
+ break;
+
+ case IKEV2_PRF:
+ switch ( aAlgCode )
+ {
+ case PRF_HMAC_MD5:
+ KeyLth = 16;
+ BlockLth = 16;
+ if ( aDigestId )
+ *aDigestId = TUtlCrypto::EUtlMessageDigestMd5;
+ break;
+
+ case PRF_HMAC_SHA1:
+ KeyLth = 20;
+ BlockLth = 20;
+ if ( aDigestId )
+ *aDigestId = TUtlCrypto::EUtlMessageDigestSha1;
+ break;
+
+ default:
+ break;
+ }
+ break;
+
+ case IKEV2_INTEG:
+ switch ( aAlgCode )
+ {
+ case AUTH_HMAC_MD5_96:
+ KeyLth = 16;
+ BlockLth = 12;
+ if ( aDigestId )
+ *aDigestId = TUtlCrypto::EUtlMessageDigestMd5;
+ break;
+
+ case AUTH_HMAC_SHA1_96:
+ KeyLth = 20;
+ BlockLth = 12;
+ if ( aDigestId )
+ *aDigestId = TUtlCrypto::EUtlMessageDigestSha1;
+ break;
+
+ default:
+ break;
+ }
+ break;
+
+ default:
+ break;
+
+ }
+
+ if ( aBlockLth )
+ *aBlockLth = BlockLth;
+
+ return KeyLth;
+
+}
+
+HBufC8* IkeCrypto::GenerateKeyingMaterialL(const TDesC8& aK, const TDesC8& aS, TInt aKeyMatLth, TUint16 aPRFAlg)
+{
+ //
+ // Since the amount of keying material needed may be greater than
+ // the size of the output of the prf algorithm prf+ is used as
+ // follows prf+ (K,S) = T1 | T2 | T3 | T4 | ...
+ // where: T1 = prf (K, S | 0x01)
+ // T2 = prf (K, T1 | S | 0x02) ..
+ // TN = prf (K, TN-1 | S | 0xN ) ;[ N < 256 ]
+ //
+ TInt PrfKeyLth = IkeCrypto::AlgorithmInfo(IKEV2_PRF, aPRFAlg, NULL);
+ TInt S_Lth = aS.Length();
+ TUint8 IterCount = (TUint8)((aKeyMatLth/PrfKeyLth) + 1);
+ HBufC8* KeyMat = HBufC8::NewL((IterCount * PrfKeyLth) + S_Lth + 1);
+ CleanupStack::PushL(KeyMat);
+ TPtr8 KeyMatPtr(KeyMat->Des());
+
+ TUint8 i = 1;
+ //
+ // Produce key material T1 | T2 | T3 | T4 | ...
+ //
+
+ HBufC8* tValue = NULL;
+ HBufC8* inputBuffer = HBufC8::NewLC(PrfKeyLth + aS.Length() + sizeof(i));
+ TPtr8 inputBufferPtr(inputBuffer->Des());
+ while ( i <= IterCount )
+ {
+ inputBufferPtr.Zero();
+ if (tValue != NULL)
+ {
+ inputBufferPtr.Append(*tValue);
+ }
+ //
+ // Append value S into key material buffer and concatenate 8 bit integer
+ // value i into S
+ //
+ inputBufferPtr.Append(aS);
+ inputBufferPtr.Append(&i, sizeof(i));
+
+ delete tValue;
+ tValue = NULL;
+ //
+ // Calculate TN = prf (SKEYSEED, TN-1 | S | 0xN)
+ //
+ tValue = IkeCrypto::PrfhmacL(*inputBuffer, aK, aPRFAlg);
+ KeyMatPtr.Append(*tValue);
+ i++;
+ }
+ delete tValue;
+
+ CleanupStack::PopAndDestroy(inputBuffer);
+ CleanupStack::Pop(); // Keymat
+
+ return KeyMat;
+}
+