|
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 |