vpnengine/ikev2lib/src/ikecrypto.cpp
changeset 0 33413c0669b9
child 8 032d3a818f49
equal deleted inserted replaced
-1:000000000000 0:33413c0669b9
       
     1 /*
       
     2 * Copyright (c) 2003-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: Intermediate class between IKEv2 and crypto library.
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 #include "dhparameters.h"
       
    20 #include "ikecrypto.h"
       
    21 #include "ikev2const.h"
       
    22 
       
    23 CDHKeys* CDHKeys::NewL(const TDesC8& aN, const TDesC8& aG)
       
    24 {
       
    25     CDHKeys *keys = new (ELeave) CDHKeys();
       
    26     keys->iDHKey = TUtlCrypto::MakeDiffieHellmanL(aN, aG);
       
    27 	keys->iModuluslength = aN.Length();
       
    28     return keys;
       
    29 }
       
    30 
       
    31 CDHKeys* CDHKeys::CreateDHKeyL(TUint aGroupDesc)
       
    32 {
       
    33 	TPtrC8 prime_ptr(NULL, 0);
       
    34 	TPtrC8 gen_ptr(NULL, 0);
       
    35 
       
    36 	switch (aGroupDesc)
       
    37 	{
       
    38 		case DH_GROUP_768:
       
    39 			prime_ptr.Set((TUint8 *)&MODP_768_PRIME[0], MODP_768_PRIME_LENGTH);
       
    40 			gen_ptr.Set((TUint8 *)&MODP_768_GENERATOR[0], MODP_768_GENERATOR_LENGTH);
       
    41 			break;
       
    42 		case DH_GROUP_1024:
       
    43 			prime_ptr.Set((TUint8 *)&MODP_1024_PRIME[0], MODP_1024_PRIME_LENGTH);
       
    44 			gen_ptr.Set((TUint8 *)&MODP_1024_GENERATOR[0], MODP_1024_GENERATOR_LENGTH);
       
    45 			break;
       
    46 		case DH_GROUP_1536:
       
    47 			prime_ptr.Set((TUint8 *)&MODP_1536_PRIME[0], MODP_1536_PRIME_LENGTH);
       
    48 			gen_ptr.Set((TUint8 *)&MODP_1536_GENERATOR[0], MODP_1536_GENERATOR_LENGTH);
       
    49 			break;
       
    50     case DH_GROUP_2048:
       
    51 			prime_ptr.Set((TUint8 *)&MODP_2048_PRIME[0], MODP_2048_PRIME_LENGTH);
       
    52 			gen_ptr.Set((TUint8 *)&MODP_2048_GENERATOR[0], MODP_2048_GENERATOR_LENGTH);
       
    53 			break;
       
    54 		default:    //Cannot happen because checked before!!!
       
    55 			User::Leave(KErrNotSupported);
       
    56 	}
       
    57 
       
    58 	CDHKeys *DhKeys = CDHKeys::NewL(prime_ptr, gen_ptr);
       
    59 
       
    60 	return DhKeys;
       
    61 }
       
    62 
       
    63 HBufC8* CDHKeys::ComputeAgreedKeyL(const TDesC8 &aPeerPublicKey)
       
    64 {
       
    65 	return (HBufC8*)KValueL(aPeerPublicKey);
       
    66 }
       
    67 
       
    68 
       
    69 HBufC8* CDHKeys::GetPubKey()
       
    70 {
       
    71     HBufC8* DHPublicKey = (HBufC8*)iPubKey;
       
    72     iPubKey = NULL; // Exclusive ownership of iPubKey buffer is returned to caller
       
    73     return DHPublicKey;
       
    74 }
       
    75 
       
    76 void CDHKeys::XValueL()
       
    77 {
       
    78 	if ( !iPubKey ) 
       
    79        iPubKey = iDHKey->GenerateXL();
       
    80 }
       
    81 
       
    82 CDHKeys::~CDHKeys()
       
    83 {
       
    84     delete iDHKey;
       
    85 }
       
    86 
       
    87 
       
    88 void IkeCrypto::DecryptL(const TUint8* aInput, TUint8* aOutput, TInt aLength, 
       
    89                          TUint8* aIV, const TDesC8& aKey, TUint16 aEncrAlg)
       
    90 {
       
    91 	TUtlCrypto::TUtlSymmetricCipherId CipherId;
       
    92 	TInt IVLth;
       
    93 	IkeCrypto::AlgorithmInfo(IKEV2_ENCR, aEncrAlg, &IVLth, &CipherId);
       
    94 	
       
    95 	if ( !aInput || !aOutput || !aIV )
       
    96 		User::Leave(KErrArgument);
       
    97 	
       
    98 	TPtrC8 IvPtr(aIV, IVLth);
       
    99 	TPtrC8 CipherText(aInput, aLength);
       
   100 	TPtr8  PlainText(aOutput, aLength);
       
   101 
       
   102 	CUtlSymmetricCipher* UtlCipher = 
       
   103 	    TUtlCrypto::MakeSymmetricDecryptorL(CipherId, aKey, IvPtr);
       
   104 	CleanupStack::PushL(UtlCipher);
       
   105 	UtlCipher->ProcessFinalL(CipherText, PlainText);
       
   106 	CleanupStack::PopAndDestroy(UtlCipher);
       
   107 }
       
   108 
       
   109 
       
   110 void IkeCrypto::EncryptL(const TDesC8& aInput, TPtr8& aOutput, 
       
   111                          const TDesC8& aIv, const TDesC8& aKey, TUint16 aEncrAlg)
       
   112 {
       
   113 	TUtlCrypto::TUtlSymmetricCipherId CipherId;
       
   114 	TInt CbLth;
       
   115 	IkeCrypto::AlgorithmInfo(IKEV2_ENCR, aEncrAlg, &CbLth, &CipherId);
       
   116 
       
   117 	__ASSERT_DEBUG(CbLth == aIv.Length(), User::Invariant());
       
   118 	__ASSERT_DEBUG(aInput.Length() % CbLth == 0, User::Invariant());
       
   119 	__ASSERT_DEBUG(aInput.Length() <= aOutput.MaxLength(), User::Invariant());
       
   120 
       
   121 	CUtlSymmetricCipher* UtlCipher = 
       
   122 	    TUtlCrypto::MakeSymmetricEncryptorL(CipherId, aKey, aIv);
       
   123 	CleanupStack::PushL(UtlCipher);     
       
   124 	UtlCipher->ProcessFinalL(aInput, aOutput);
       
   125 	CleanupStack::PopAndDestroy(UtlCipher);
       
   126 }
       
   127 
       
   128 TInt IkeCrypto::IntegHMACL(const TDesC8& aInput, TDes8& aChecksum, const TDesC8& aKeyData, TUint16 aIntegAlg)
       
   129 {
       
   130 	TUtlCrypto::TUtlMessageDigestId DigestId;
       
   131 	TInt HmacLth;	
       
   132 	IkeCrypto::AlgorithmInfo(IKEV2_INTEG, aIntegAlg, &HmacLth, NULL, &DigestId);	
       
   133 	CUtlMessageDigest* Digest = TUtlCrypto::MakeMessageDigesterL(DigestId, aKeyData);
       
   134 		
       
   135 	const TPtrC8 hash = Digest->Final(aInput); 
       
   136 	
       
   137 	//We don't always use the whole hash. 
       
   138 	//(e.g., HMAC-SHA1-96 uses only first 12 bytes)
       
   139 	__ASSERT_DEBUG(hash.Length() >= HmacLth, User::Invariant());
       
   140 	
       
   141 	aChecksum = hash.Left(HmacLth);	
       
   142 	delete Digest;
       
   143 
       
   144 	return HmacLth;
       
   145 }
       
   146 
       
   147 HBufC8* IkeCrypto::PrfhmacL(const TDesC8& aInput, const TDesC8& aKeyData, TUint16 aPrfAlg)
       
   148 {
       
   149 	TUtlCrypto::TUtlMessageDigestId DigestId;
       
   150 	TInt PrfLth;	
       
   151 	IkeCrypto::AlgorithmInfo(IKEV2_PRF, aPrfAlg, &PrfLth, NULL, &DigestId);	
       
   152 	CUtlMessageDigest* Digest = TUtlCrypto::MakeMessageDigesterL(DigestId, aKeyData);
       
   153 	CleanupStack::PushL(Digest);
       
   154 	
       
   155 	HBufC8* checksum = Digest->Final(aInput).AllocL();
       
   156 	
       
   157 	CleanupStack::PopAndDestroy(Digest);
       
   158 
       
   159 	return checksum;
       
   160 	
       
   161 }
       
   162 
       
   163 HBufC8* IkeCrypto::PrfL(const TDesC8& aInput, TUint16 aPrfAlg)
       
   164 {
       
   165 	TUtlCrypto::TUtlMessageDigestId DigestId;
       
   166 	TInt PrfLth;	
       
   167 	IkeCrypto::AlgorithmInfo(IKEV2_PRF, aPrfAlg, &PrfLth, NULL, &DigestId);	
       
   168 	CUtlMessageDigest* digest = TUtlCrypto::MakeMessageDigesterL(DigestId);
       
   169 	CleanupStack::PushL(digest);
       
   170 	
       
   171 	HBufC8* hash = digest->Final(aInput).AllocL();
       
   172 			
       
   173 	CleanupStack::PopAndDestroy(digest);
       
   174 
       
   175 	return hash;
       
   176 
       
   177 }
       
   178 
       
   179 TInt IkeCrypto::AlgorithmInfo(TUint16 aTransform, TUint16 aAlgCode, TInt* aBlockLth,
       
   180 							  TUtlCrypto::TUtlSymmetricCipherId* aCipherId,
       
   181 							  TUtlCrypto::TUtlMessageDigestId*   aDigestId) 
       
   182 {
       
   183 	TInt KeyLth   = 0;
       
   184 	TInt BlockLth = 0;
       
   185     	
       
   186 	switch ( aTransform  )
       
   187 	{
       
   188 		case IKEV2_ENCR:
       
   189 			switch ( aAlgCode )
       
   190 			{
       
   191 				case ENCR_DES:
       
   192 					KeyLth   = 8;
       
   193 					BlockLth = 8;
       
   194 					if ( aCipherId )
       
   195 						*aCipherId = TUtlCrypto::EUtlSymmetricCipherDesCbc;
       
   196 					break;
       
   197 					
       
   198 				case ENCR_3DES:
       
   199 					KeyLth   = 24;
       
   200 					BlockLth = 8;
       
   201 				    if ( aCipherId )
       
   202 					   *aCipherId = TUtlCrypto::EUtlSymmetricCipher3DesCbc;
       
   203 					break;
       
   204 
       
   205 				case ENCR_AES_CBC:
       
   206 					KeyLth   = 0;
       
   207 					BlockLth = 16;
       
   208 					if ( aCipherId )
       
   209 						*aCipherId = TUtlCrypto::EUtlSymmetricCipherAesCbc;
       
   210 				   break;
       
   211 
       
   212 				case ENCR_NULL:
       
   213 					KeyLth   = 0;
       
   214 					BlockLth = 0;
       
   215 					break;
       
   216 				default:
       
   217 					break;
       
   218 			}	
       
   219 			break;
       
   220 
       
   221 		case IKEV2_PRF:
       
   222 			switch ( aAlgCode )
       
   223 			{
       
   224 				case PRF_HMAC_MD5:
       
   225 					KeyLth   = 16;
       
   226 					BlockLth = 16;
       
   227 					if ( aDigestId )
       
   228 						*aDigestId = TUtlCrypto::EUtlMessageDigestMd5;
       
   229 					break;
       
   230 
       
   231 				case PRF_HMAC_SHA1:
       
   232 					KeyLth   = 20;
       
   233 					BlockLth = 20;
       
   234 					if ( aDigestId )
       
   235 						*aDigestId = TUtlCrypto::EUtlMessageDigestSha1;
       
   236 					break;
       
   237 
       
   238 				default:
       
   239 					break;
       
   240 			}
       
   241 			break;
       
   242 
       
   243 		case IKEV2_INTEG:
       
   244 			switch ( aAlgCode )
       
   245 			{
       
   246 				case AUTH_HMAC_MD5_96:
       
   247 					KeyLth   = 16;
       
   248 					BlockLth = 12;
       
   249 					if ( aDigestId )
       
   250 						*aDigestId = TUtlCrypto::EUtlMessageDigestMd5;
       
   251 					break;
       
   252 
       
   253 				case AUTH_HMAC_SHA1_96:
       
   254 					KeyLth   = 20;
       
   255 					BlockLth = 12;
       
   256 					if ( aDigestId )
       
   257 						*aDigestId = TUtlCrypto::EUtlMessageDigestSha1;
       
   258 					break;
       
   259 
       
   260 				default:
       
   261 					break;
       
   262 			}
       
   263 			break;			
       
   264 
       
   265 		default:
       
   266 			break;
       
   267 			
       
   268 	}
       
   269 	
       
   270 	if ( aBlockLth )
       
   271 		*aBlockLth = BlockLth;
       
   272 
       
   273 	return KeyLth;
       
   274 
       
   275 }
       
   276 
       
   277 HBufC8* IkeCrypto::GenerateKeyingMaterialL(const TDesC8& aK, const TDesC8& aS, TInt aKeyMatLth, TUint16 aPRFAlg)
       
   278 {
       
   279     //
       
   280     //  Since the amount of keying material needed may be greater than
       
   281     //  the size of the output of the prf algorithm prf+ is used as
       
   282     //  follows    prf+ (K,S) = T1 | T2 | T3 | T4 | ...
       
   283     //    where:   T1 = prf (K, S | 0x01)
       
   284     //             T2 = prf (K, T1 | S | 0x02) ..
       
   285     //             TN = prf (K, TN-1 | S | 0xN ) ;[ N < 256 ]
       
   286     //
       
   287     TInt PrfKeyLth    = IkeCrypto::AlgorithmInfo(IKEV2_PRF, aPRFAlg, NULL);
       
   288     TInt S_Lth        = aS.Length();
       
   289     TUint8 IterCount  = (TUint8)((aKeyMatLth/PrfKeyLth) + 1);
       
   290     HBufC8* KeyMat    = HBufC8::NewL((IterCount * PrfKeyLth) + S_Lth + 1);
       
   291     CleanupStack::PushL(KeyMat);
       
   292     TPtr8 KeyMatPtr(KeyMat->Des());
       
   293             
       
   294     TUint8 i = 1;
       
   295     //
       
   296     // Produce key material T1 | T2 | T3 | T4 | ...
       
   297     //
       
   298     
       
   299     HBufC8* tValue = NULL;
       
   300     HBufC8* inputBuffer = HBufC8::NewLC(PrfKeyLth + aS.Length() + sizeof(i));
       
   301     TPtr8 inputBufferPtr(inputBuffer->Des());
       
   302     while ( i <= IterCount )
       
   303     {
       
   304         inputBufferPtr.Zero();
       
   305         if (tValue != NULL)
       
   306             {
       
   307             inputBufferPtr.Append(*tValue);
       
   308             }
       
   309         //
       
   310         // Append value S into key material buffer and concatenate 8 bit integer
       
   311         // value i into S
       
   312         //
       
   313         inputBufferPtr.Append(aS);
       
   314         inputBufferPtr.Append(&i, sizeof(i));
       
   315 
       
   316         delete tValue;
       
   317         tValue = NULL;
       
   318         //
       
   319         // Calculate TN = prf (SKEYSEED, TN-1 | S | 0xN)
       
   320         //
       
   321         tValue = IkeCrypto::PrfhmacL(*inputBuffer, aK, aPRFAlg);
       
   322         KeyMatPtr.Append(*tValue);
       
   323         i++;
       
   324     }
       
   325     delete tValue;
       
   326         
       
   327     CleanupStack::PopAndDestroy(inputBuffer);
       
   328     CleanupStack::Pop();  // Keymat
       
   329     
       
   330     return KeyMat;
       
   331 }
       
   332