|
1 // Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies). |
|
2 // All rights reserved. |
|
3 // This component and the accompanying materials are made available |
|
4 // under the terms of "Eclipse Public License v1.0" |
|
5 // which accompanies this distribution, and is available |
|
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
7 // |
|
8 // Initial Contributors: |
|
9 // Nokia Corporation - initial contribution. |
|
10 // |
|
11 // Contributors: |
|
12 // |
|
13 // Description: |
|
14 // |
|
15 |
|
16 /** |
|
17 @file tlsstepbase.cpp |
|
18 @internalTechnology |
|
19 */ |
|
20 #include "tlsstepbase.h" |
|
21 |
|
22 #include <f32file.h> |
|
23 #include <tlsprovinterface.h> |
|
24 #include <asymmetric.h> |
|
25 #include <asymmetrickeys.h> |
|
26 #include <symmetric.h> |
|
27 #include <asnpkcs.h> |
|
28 #include "tlsgenericactive.h" |
|
29 #include "psuedorandom.h" |
|
30 #include "dhparamreader.h" |
|
31 #include "testpadding.h" |
|
32 |
|
33 CTlsStepBase::~CTlsStepBase() |
|
34 { |
|
35 delete iActive; |
|
36 delete iProvider; |
|
37 delete iSched; |
|
38 iSuites.Close(); |
|
39 // iGenerator.Close(); |
|
40 // iPrime.Close(); |
|
41 delete iKeyPair; |
|
42 delete iClientMacSecret; |
|
43 delete iServerMacSecret; |
|
44 delete iClientWriteSecret; |
|
45 delete iServerWriteSecret; |
|
46 delete iClientInitVector; |
|
47 delete iServerInitVector; |
|
48 |
|
49 } |
|
50 |
|
51 void CTlsStepBase::ConstructL() |
|
52 { |
|
53 iSched=new(ELeave) CActiveScheduler; |
|
54 CActiveScheduler::Install(iSched); |
|
55 |
|
56 iProvider = CTLSProvider::ConnectL(); |
|
57 iActive = new (ELeave) CGenericActive; |
|
58 } |
|
59 |
|
60 // Test methods |
|
61 |
|
62 TInt CTlsStepBase::GetCipherSuitesL() |
|
63 { |
|
64 iSuites.Reset(); |
|
65 iProvider->CipherSuitesL(iSuites, iActive->iStatus); |
|
66 iActive->Start(); |
|
67 return iActive->iStatus.Int(); |
|
68 } |
|
69 |
|
70 TInt CTlsStepBase::GetCipherSuitesWithCancelL() |
|
71 { |
|
72 iSuites.Reset(); |
|
73 iProvider->CipherSuitesL(iSuites, iActive->iStatus); |
|
74 iProvider->CancelRequest(); |
|
75 iActive->Start(); |
|
76 return iActive->iStatus.Int(); |
|
77 } |
|
78 |
|
79 |
|
80 TInt CTlsStepBase::GetCipherSuitesL(CTLSProvider* & aTLSProviderInstance, RArray<TTLSCipherSuite> & aCipherSuites) |
|
81 { |
|
82 aTLSProviderInstance->CipherSuitesL(aCipherSuites, iActive->iStatus); |
|
83 iActive->Start(); |
|
84 return iActive->iStatus.Int(); |
|
85 } |
|
86 |
|
87 TInt CTlsStepBase::VerifyServerCertificateL(CX509Certificate*& aCertOut) |
|
88 { |
|
89 HBufC8* cert = ServerCertificateL(); |
|
90 iProvider->VerifyServerCertificate(*cert, aCertOut, iActive->iStatus); |
|
91 iActive->Start(); |
|
92 delete cert; |
|
93 return iActive->iStatus.Int(); |
|
94 } |
|
95 |
|
96 TInt CTlsStepBase::VerifyServerCertificateL(CTLSProvider* & aTLSProviderInstance, CX509Certificate*& aCertOut) |
|
97 { |
|
98 HBufC8* cert = ServerCertificateL(); |
|
99 aTLSProviderInstance->VerifyServerCertificate(*cert, aCertOut, iActive->iStatus); |
|
100 iActive->Start(); |
|
101 delete cert; |
|
102 return iActive->iStatus.Int(); |
|
103 } |
|
104 |
|
105 TInt CTlsStepBase::VerifyServerCertificateWithCancelL(CX509Certificate*& aCertOut) |
|
106 { |
|
107 HBufC8* cert = ServerCertificateL(); |
|
108 iProvider->VerifyServerCertificate(*cert, aCertOut, iActive->iStatus); |
|
109 iProvider->CancelRequest(); |
|
110 iActive->Start(); |
|
111 delete cert; |
|
112 return iActive->iStatus.Int(); |
|
113 } |
|
114 |
|
115 TInt CTlsStepBase::RetrieveServerCert(CX509Certificate*& aCertOut) |
|
116 { |
|
117 iSession->ServerCertificate(aCertOut,iActive->iStatus); |
|
118 iActive->Start(); |
|
119 return iActive->iStatus.Int(); |
|
120 } |
|
121 |
|
122 TInt CTlsStepBase::CreateSessionL() |
|
123 { |
|
124 iProvider->CreateL(iSession, iActive->iStatus); |
|
125 iActive->Start(); |
|
126 return iActive->iStatus.Int(); |
|
127 } |
|
128 |
|
129 TInt CTlsStepBase::CreateSessionWithCancelL() |
|
130 { |
|
131 iProvider->CreateL(iSession, iActive->iStatus); |
|
132 iProvider->CancelRequest(); |
|
133 iActive->Start(); |
|
134 return iActive->iStatus.Int(); |
|
135 } |
|
136 |
|
137 TInt CTlsStepBase::CreateSessionL(CTLSProvider* & aTLSProviderInstance, CTLSSession* aCTLSSession) |
|
138 { |
|
139 aTLSProviderInstance->CreateL(aCTLSSession, iActive->iStatus); |
|
140 iActive->Start(); |
|
141 return iActive->iStatus.Int(); |
|
142 } |
|
143 |
|
144 |
|
145 TInt CTlsStepBase ::VerifyGetSessionL(TTLSServerAddr& aServerName,TInt& aSessionIdLength) |
|
146 { |
|
147 TTLSSessionId sessionId; |
|
148 iProvider->GetSessionL( |
|
149 aServerName, |
|
150 sessionId, |
|
151 iActive->iStatus ); |
|
152 iActive->Start(); |
|
153 aSessionIdLength = sessionId.Length(); |
|
154 return iActive->iStatus.Int(); |
|
155 } |
|
156 |
|
157 TInt CTlsStepBase ::VerifyGetSessionL(CTLSProvider* & aTLSProviderInstance , TTLSServerAddr& aServerName, TInt& aSessionIdLength) |
|
158 { |
|
159 TTLSSessionId sessionId; |
|
160 aTLSProviderInstance->GetSessionL( |
|
161 aServerName, |
|
162 sessionId, |
|
163 iActive->iStatus ); |
|
164 iActive->Start(); |
|
165 aSessionIdLength = sessionId.Length(); |
|
166 return iActive->iStatus.Int(); |
|
167 } |
|
168 |
|
169 |
|
170 TInt CTlsStepBase ::CreateSessionAddedL(TInt aHiByte,TInt aLoByte) |
|
171 { |
|
172 |
|
173 CTlsCryptoAttributes* TlsCryptoAttributes = iProvider->Attributes(); |
|
174 TlsCryptoAttributes->iNegotiatedProtocol = KTLS1_0; |
|
175 TlsCryptoAttributes->iCurrentCipherSuite.iHiByte = aHiByte; |
|
176 TlsCryptoAttributes->iCurrentCipherSuite.iLoByte = aLoByte; |
|
177 iProvider->CreateL(iSession, iActive->iStatus); |
|
178 iActive->Start(); |
|
179 return iActive->iStatus.Int(); |
|
180 } |
|
181 |
|
182 TInt CTlsStepBase::ClearSessionCacheL(TTLSSessionNameAndID &aSessionNameAndId) |
|
183 { |
|
184 iProvider->ClearSessionCacheL( |
|
185 aSessionNameAndId, |
|
186 iActive->iStatus); |
|
187 iActive->Start(); |
|
188 return iActive->iStatus.Int(); |
|
189 } |
|
190 |
|
191 TInt CTlsStepBase::ClearSessionCacheWithCancelL(TTLSSessionNameAndID &aSessionNameAndId) |
|
192 { |
|
193 iProvider->ClearSessionCacheL( |
|
194 aSessionNameAndId, |
|
195 iActive->iStatus); |
|
196 iProvider->CancelRequest(); |
|
197 iActive->Start(); |
|
198 return iActive->iStatus.Int(); |
|
199 } |
|
200 |
|
201 TInt CTlsStepBase::ClearSessionCacheL(CTLSProvider* & aTLSProviderInstance ,TTLSSessionNameAndID &aSessionNameAndId) |
|
202 { |
|
203 aTLSProviderInstance->ClearSessionCacheL( |
|
204 aSessionNameAndId, |
|
205 iActive->iStatus); |
|
206 iActive->Start(); |
|
207 return iActive->iStatus.Int(); |
|
208 } |
|
209 |
|
210 void CTlsStepBase::SessionCancelReq() |
|
211 { |
|
212 iSession->CancelRequest(); |
|
213 } |
|
214 |
|
215 void CTlsStepBase::ProviderCancelReq() |
|
216 { |
|
217 iProvider->CancelRequest(); |
|
218 } |
|
219 |
|
220 TInt CTlsStepBase::ClientKeyExchange(HBufC8*& aMessageOut) |
|
221 { |
|
222 iSession->ClientKeyExchange(aMessageOut, iActive->iStatus); |
|
223 iActive->Start(); |
|
224 return iActive->iStatus.Int(); |
|
225 } |
|
226 |
|
227 TInt CTlsStepBase::ClientKeyExchange(CTLSSession* &aCTLSSession, HBufC8*& aMessageOut) |
|
228 { |
|
229 aCTLSSession->ClientKeyExchange(aMessageOut, iActive->iStatus); |
|
230 iActive->Start(); |
|
231 return iActive->iStatus.Int(); |
|
232 } |
|
233 |
|
234 |
|
235 TInt CTlsStepBase::ClientKeyExchangeWithCancel(HBufC8*& aMessageOut) |
|
236 { |
|
237 iSession->ClientKeyExchange(aMessageOut, iActive->iStatus); |
|
238 iSession->CancelRequest(); |
|
239 iActive->Start(); |
|
240 return iActive->iStatus.Int(); |
|
241 } |
|
242 |
|
243 |
|
244 TInt CTlsStepBase::GenerateClientFinishedL(CMessageDigest* aShaDigest, CMessageDigest* aMd5Digest, HBufC8*& aMessageOut) |
|
245 { |
|
246 iSession->ClientFinishedMsgL(aMd5Digest, aShaDigest, aMessageOut, iActive->iStatus); |
|
247 iActive->Start(); |
|
248 return iActive->iStatus.Int(); |
|
249 } |
|
250 |
|
251 TInt CTlsStepBase::VerifyServerFinishedL(CMessageDigest* aShaDigest, CMessageDigest* aMd5Digest, const TDesC8& aMessage) |
|
252 { |
|
253 iSession->VerifyServerFinishedMsgL(aMd5Digest, aShaDigest, aMessage, iActive->iStatus); |
|
254 iActive->Start(); |
|
255 return iActive->iStatus.Int(); |
|
256 } |
|
257 |
|
258 TInt CTlsStepBase::CipherSuiteIndex(const TTLSCipherSuite& aSuite) |
|
259 { |
|
260 for (TInt i = 0 ; i < CipherSuites().Count() ; ++i) |
|
261 { |
|
262 if (CipherSuites()[i] == aSuite) |
|
263 { |
|
264 return i; |
|
265 }; |
|
266 } |
|
267 return KErrNotFound; |
|
268 } |
|
269 |
|
270 HBufC8* CTlsStepBase::DerivePreMasterSecretL(const TDesC8& aClientKeyExMessage) |
|
271 { |
|
272 return DerivePreMasterSecretL(iProvider, aClientKeyExMessage); |
|
273 } |
|
274 |
|
275 HBufC8* CTlsStepBase::DerivePreMasterSecretL(CTLSProvider* & aTLSProviderInstance, const TDesC8& aClientKeyExMessage) |
|
276 { |
|
277 // Look up the cipher suite we used for this test |
|
278 CTlsCryptoAttributes* atts = aTLSProviderInstance->Attributes(); |
|
279 |
|
280 TInt index = CipherSuiteIndex(atts->iCurrentCipherSuite); |
|
281 if (index < 0) |
|
282 { |
|
283 INFO_PRINTF3(_L("Failed! Could not find cipher 0x%02x.0x%02x, did the ECOM plugin load okay?"), |
|
284 atts->iCurrentCipherSuite.iHiByte, atts->iCurrentCipherSuite.iLoByte); |
|
285 User::Leave(index); |
|
286 } |
|
287 |
|
288 HBufC8* ret = NULL; |
|
289 |
|
290 // currently, we only support three key exhange algorithms, so that is what we test here |
|
291 switch (CipherSuites()[index].CipherDetails()->iKeyExAlg) |
|
292 { |
|
293 case ERsa: |
|
294 // decrypt the key exhange message with the "server" private key, and |
|
295 // verify the version and that the premaster key is the right size... |
|
296 { |
|
297 CDecPKCS8Data* keyData = ServerPrivateKeyL(); |
|
298 CleanupStack::PushL(keyData); |
|
299 |
|
300 // we don't own this pointer... |
|
301 CPKCS8KeyPairRSA* key = static_cast<CPKCS8KeyPairRSA*>(keyData->KeyPairData()); |
|
302 |
|
303 CRSAPKCS1v15Decryptor* decryptor = CRSAPKCS1v15Decryptor::NewLC(key->PrivateKey()); |
|
304 |
|
305 ret = HBufC8::NewLC(decryptor->MaxOutputLength()); |
|
306 TPtr8 ptr = ret->Des(); |
|
307 decryptor->DecryptL(aClientKeyExMessage, ptr); |
|
308 |
|
309 CleanupStack::Pop(ret); |
|
310 CleanupStack::PopAndDestroy(2, keyData); // decryptor |
|
311 } |
|
312 break; |
|
313 |
|
314 case EDHE: |
|
315 { |
|
316 RInteger clientX = RInteger::NewL(aClientKeyExMessage); |
|
317 CleanupClosePushL(clientX); |
|
318 |
|
319 RInteger prime = RInteger::NewL(iPrime); |
|
320 CleanupClosePushL(prime); |
|
321 |
|
322 RInteger gen = RInteger::NewL(iGenerator); |
|
323 CleanupClosePushL(gen); |
|
324 |
|
325 CDHPublicKey* clientKey = CDHPublicKey::NewL(prime, gen, clientX); |
|
326 CleanupStack::Pop(3, &clientX); // prime, gen, adopted by clientKey |
|
327 CleanupStack::PushL(clientKey); |
|
328 |
|
329 CDH* dh = CDH::NewLC(KeyPair()->PrivateKey()); |
|
330 // this cast is evil, but hey! it's test code. And I'm not gonna revise the interface. |
|
331 ret = const_cast<HBufC8*>(dh->AgreeL(*clientKey)); |
|
332 |
|
333 CleanupStack::PopAndDestroy(2, clientKey); // dh |
|
334 } |
|
335 break; |
|
336 |
|
337 case EPsk: |
|
338 { |
|
339 // For PSK cipher suites the premaster secret is formed as follows: |
|
340 // if the PSK is N octets long, concatenate a uint16 with the value N, |
|
341 // N zero octets, a second uint16 with the value N, and the PSK itself. |
|
342 // REF: RFC4279 |
|
343 |
|
344 ret = HBufC8::NewLC(iPskKey->Length()*2 + 4 ); |
|
345 ret->Des().FillZ(iPskKey->Length()*2 + 4); |
|
346 TPtr8 ptr = ret->Des(); |
|
347 |
|
348 // Populates first two field bytes values. |
|
349 |
|
350 ptr[0] = (iPskKey->Length() & 0xFF00 ) >> 8; |
|
351 ptr[1] = iPskKey->Length() & 0xFF; |
|
352 |
|
353 // Populates second two field bytes values. |
|
354 ptr[iPskKey->Length() + 2] = ptr[0]; |
|
355 ptr[iPskKey->Length() + 3] = ptr[1]; |
|
356 |
|
357 // Populates the actual key value. |
|
358 ptr.Replace(iPskKey->Length() + 4, iPskKey->Length(), iPskKey->Des() ); |
|
359 |
|
360 CleanupStack::Pop(ret); |
|
361 |
|
362 } |
|
363 break; |
|
364 |
|
365 default: |
|
366 User::Leave(KErrUnknown); |
|
367 break; |
|
368 } |
|
369 |
|
370 return ret; |
|
371 } |
|
372 |
|
373 HBufC8* CTlsStepBase::ComputeMasterSecretL(const TDesC8& aPremasterSecret) |
|
374 { |
|
375 return CTlsStepBase::ComputeMasterSecretL(iProvider, aPremasterSecret); |
|
376 } |
|
377 |
|
378 HBufC8* CTlsStepBase::ComputeMasterSecretL(CTLSProvider* & aTLSProviderInstance, const TDesC8& aPremasterSecret) |
|
379 { |
|
380 if (aTLSProviderInstance->Attributes()->iNegotiatedProtocol == KSSL3_0) |
|
381 { |
|
382 return ComputeSslMasterSecretL(aPremasterSecret); |
|
383 } |
|
384 else if (aTLSProviderInstance->Attributes()->iNegotiatedProtocol == KTLS1_0) |
|
385 { |
|
386 return ComputeTlsMasterSecretL(aPremasterSecret); |
|
387 } |
|
388 else |
|
389 { |
|
390 // currently unknown protocol! |
|
391 User::Leave(KErrUnknown); |
|
392 return NULL; // keep the compiler happy.. |
|
393 } |
|
394 } |
|
395 |
|
396 HBufC8* CTlsStepBase::ComputeMacL(const TDesC8& aData, TInt64 aSequenceNumber, TRecordProtocol& aType, TBool aIsServerMac) |
|
397 { |
|
398 if (Provider()->Attributes()->iNegotiatedProtocol == KSSL3_0) |
|
399 { |
|
400 return ComputeSslMacL(aData, aSequenceNumber, aType, aIsServerMac); |
|
401 } |
|
402 else if (Provider()->Attributes()->iNegotiatedProtocol == KTLS1_0) |
|
403 { |
|
404 return ComputeTlsMacL(aData, aSequenceNumber, aType, aIsServerMac); |
|
405 } |
|
406 else |
|
407 { |
|
408 // currently unknown protocol! |
|
409 User::Leave(KErrUnknown); |
|
410 return NULL; // keep the compiler happy.. |
|
411 } |
|
412 } |
|
413 |
|
414 HBufC8* CTlsStepBase::ComputeFinishedMessageL(CMessageDigest* aShaDigest, CMessageDigest* aMd5Digest, |
|
415 const TDesC8& aMasterSecret, TBool aClientFinished) |
|
416 { |
|
417 if (Provider()->Attributes()->iNegotiatedProtocol == KSSL3_0) |
|
418 { |
|
419 return ComputeSslFinishedL(aShaDigest, aMd5Digest, aMasterSecret, aClientFinished); |
|
420 } |
|
421 else if (Provider()->Attributes()->iNegotiatedProtocol == KTLS1_0) |
|
422 { |
|
423 return ComputeTlsFinishedL(aShaDigest, aMd5Digest, aMasterSecret, aClientFinished); |
|
424 } |
|
425 else |
|
426 { |
|
427 // currently unknown protocol! |
|
428 User::Leave(KErrUnknown); |
|
429 return NULL; // keep the compiler happy.. |
|
430 } |
|
431 } |
|
432 |
|
433 HBufC8* CTlsStepBase::EncryptRecordL(const TDesC8& aData, TInt64 aSequenceNumber, TRecordProtocol& aType, TBool aIsServerCrypt) |
|
434 { |
|
435 // Compute the mac for this record... |
|
436 HBufC8* mac = ComputeMacL(aData, aSequenceNumber, aType, aIsServerCrypt); |
|
437 CleanupStack::PushL(mac); |
|
438 |
|
439 // now, create an encryptor for this operation.... |
|
440 CTlsCryptoAttributes* atts = Provider()->Attributes(); |
|
441 |
|
442 TInt index = CipherSuiteIndex(atts->iCurrentCipherSuite); |
|
443 User::LeaveIfError(index); |
|
444 |
|
445 TTLSCipherSuite suite = CipherSuites()[index]; |
|
446 CSymmetricCipher* encryptor = NULL; |
|
447 HBufC8* key = aIsServerCrypt ? ServerWriteSecret() : ClientWriteSecret(); |
|
448 |
|
449 if (suite.CipherDetails()->iCipherType == EStream) |
|
450 { |
|
451 |
|
452 switch (suite.CipherDetails()->iBulkCiphAlg) |
|
453 { |
|
454 case ERc4: |
|
455 encryptor = CARC4::NewL(*key, 0); |
|
456 break; |
|
457 case ENullSymCiph: |
|
458 encryptor = CNullCipher::NewL(); |
|
459 break; |
|
460 default: |
|
461 User::Leave(KErrUnknown); // unknown cipher! |
|
462 break; |
|
463 } |
|
464 } |
|
465 else |
|
466 { |
|
467 |
|
468 CBlockTransformation* transform = NULL; |
|
469 switch (suite.CipherDetails()->iBulkCiphAlg) |
|
470 { |
|
471 case EDes: |
|
472 case EDes40: |
|
473 transform = CDESEncryptor::NewLC(*key, EFalse); |
|
474 break; |
|
475 |
|
476 case E3Des: |
|
477 transform = C3DESEncryptor::NewLC(*key); |
|
478 break; |
|
479 |
|
480 case EAes: |
|
481 transform = CAESEncryptor::NewLC(*key); |
|
482 break; |
|
483 |
|
484 default: |
|
485 User::Leave(KErrUnknown); // unknown cipher! |
|
486 break; |
|
487 } |
|
488 |
|
489 HBufC8* iv = aIsServerCrypt ? ServerInitVector() : ClientInitVector(); |
|
490 CleanupStack::Pop(transform); // ownership transfered to cbc |
|
491 CModeCBCEncryptor* cbc = CModeCBCEncryptor::NewLC(transform, *iv); |
|
492 |
|
493 CPaddingSSLv3* padding = CPaddingSSLv3::NewLC(cbc->BlockSize()); |
|
494 // Use next line instead later. Currently broken. Will be required for TLS 1.2 |
|
495 // CTlsTestPadding* padding = CTlsTestPadding::NewLC(cbc->BlockSize(), 0); |
|
496 |
|
497 encryptor = CBufferedEncryptor::NewL(cbc, padding); |
|
498 CleanupStack::Pop(2, cbc); // padding - ownership transfered to encryptor |
|
499 } |
|
500 |
|
501 CleanupStack::PushL(encryptor); |
|
502 |
|
503 // encrypt the data, and the mac... padding will be added as appropriate. |
|
504 TInt outputMaxLen = encryptor->MaxFinalOutputLength(mac->Length() + aData.Length()); |
|
505 HBufC8* ret = HBufC8::NewLC(outputMaxLen); |
|
506 TPtr8 des = ret->Des(); |
|
507 |
|
508 encryptor->Process(aData, des); |
|
509 encryptor->ProcessFinalL(*mac, des); |
|
510 |
|
511 CleanupStack::Pop(ret); |
|
512 CleanupStack::PopAndDestroy(2, mac); // encryptor |
|
513 return ret; |
|
514 } |
|
515 |
|
516 // INI Read methods |
|
517 |
|
518 HBufC8* CTlsStepBase::ServerRandomL() |
|
519 { |
|
520 return ReadRandomL(KServerRandomFile); |
|
521 } |
|
522 |
|
523 HBufC8* CTlsStepBase::ClientRandomL() |
|
524 { |
|
525 return ReadRandomL(KClientRandomFile); |
|
526 } |
|
527 |
|
528 TTLSCipherSuite CTlsStepBase::CipherSuiteL() |
|
529 { |
|
530 TTLSCipherSuite ret; |
|
531 |
|
532 TInt highByte(0); |
|
533 if (!GetIntFromConfig(ConfigSection(), KCipherHighByte, highByte)) |
|
534 { |
|
535 User::Leave(KErrNotFound); |
|
536 } |
|
537 |
|
538 TInt lowByte(0); |
|
539 if (!GetIntFromConfig(ConfigSection(), KCipherLowByte, lowByte)) |
|
540 { |
|
541 User::Leave(KErrNotFound); |
|
542 } |
|
543 |
|
544 ret.iHiByte = highByte; |
|
545 ret.iLoByte = lowByte; |
|
546 |
|
547 return ret; |
|
548 } |
|
549 |
|
550 TTLSProtocolVersion CTlsStepBase::ProtocolVersionL() |
|
551 { |
|
552 TTLSProtocolVersion ret; |
|
553 |
|
554 TInt majorVersion(0); |
|
555 if (!GetIntFromConfig(ConfigSection(), KProtocolMajorVersion, majorVersion)) |
|
556 { |
|
557 User::Leave(KErrNotFound); |
|
558 } |
|
559 |
|
560 TInt minorVersion(0); |
|
561 if (!GetIntFromConfig(ConfigSection(), KProtocolMinorVersion, minorVersion)) |
|
562 { |
|
563 User::Leave(KErrNotFound); |
|
564 } |
|
565 |
|
566 ret.iMajor = majorVersion; |
|
567 ret.iMinor = minorVersion; |
|
568 |
|
569 return ret; |
|
570 } |
|
571 |
|
572 TTLSSessionId CTlsStepBase::SessionId() |
|
573 { |
|
574 // Create a unique session ID, by filling with zeros, then setting the top |
|
575 // 8 bytes with the current time. |
|
576 TTLSSessionId ret; |
|
577 ret.SetMax(); |
|
578 ret.Fill(0); |
|
579 |
|
580 TTime now; |
|
581 now.UniversalTime(); |
|
582 |
|
583 TInt64 time = now.Int64(); |
|
584 TInt byteNum(0); |
|
585 while (time) |
|
586 { |
|
587 ret[byteNum++] = time & 0xFF; |
|
588 time >>= 8; |
|
589 } |
|
590 |
|
591 return ret; |
|
592 } |
|
593 |
|
594 HBufC8* CTlsStepBase::ServerCertificateL() |
|
595 { |
|
596 TPtrC serverCertName; |
|
597 if (!GetStringFromConfig(ConfigSection(), KServerCert, serverCertName)) |
|
598 { |
|
599 User::Leave(KErrNotFound); |
|
600 } |
|
601 |
|
602 RFs fs; |
|
603 User::LeaveIfError(fs.Connect()); |
|
604 CleanupClosePushL(fs); |
|
605 |
|
606 RFile certFile; |
|
607 User::LeaveIfError(certFile.Open(fs, serverCertName, EFileRead)); |
|
608 CleanupClosePushL(certFile); |
|
609 |
|
610 TInt size(0); |
|
611 User::LeaveIfError(certFile.Size(size)); |
|
612 HBufC8* certData = HBufC8::NewLC(size); |
|
613 TPtr8 ptr = certData->Des(); |
|
614 |
|
615 User::LeaveIfError(certFile.Read(ptr, size)); |
|
616 |
|
617 CleanupStack::Pop(certData); |
|
618 CleanupStack::PopAndDestroy(2, &fs); // certFile |
|
619 return certData; |
|
620 } |
|
621 |
|
622 void CTlsStepBase::ReadDHParamsL() |
|
623 { |
|
624 TPtrC dhParamName; |
|
625 if (!GetStringFromConfig(ConfigSection(), KDhParamFile, dhParamName)) |
|
626 { |
|
627 User::Leave(KErrNotFound); |
|
628 } |
|
629 |
|
630 CDHParamReader::DecodeDERL(dhParamName, iPrime, iGenerator); |
|
631 iKeyPair = CDHKeyPair::NewL(iPrime, iGenerator); |
|
632 } |
|
633 |
|
634 |
|
635 TPtrC CTlsStepBase::DomainNameL() |
|
636 { |
|
637 TPtrC name; |
|
638 if (!GetStringFromConfig(ConfigSection(), KDomainName, name)) |
|
639 { |
|
640 User::Leave(KErrNotFound); |
|
641 } |
|
642 return name; |
|
643 } |
|
644 |
|
645 CDecPKCS8Data* CTlsStepBase::ServerPrivateKeyL() |
|
646 { |
|
647 TPtrC serverKeyName; |
|
648 if (!GetStringFromConfig(ConfigSection(), KServerKey, serverKeyName)) |
|
649 { |
|
650 User::Leave(KErrNotFound); |
|
651 } |
|
652 |
|
653 RFs fs; |
|
654 User::LeaveIfError(fs.Connect()); |
|
655 CleanupClosePushL(fs); |
|
656 |
|
657 RFile keyFile; |
|
658 User::LeaveIfError(keyFile.Open(fs, serverKeyName, EFileRead)); |
|
659 CleanupClosePushL(keyFile); |
|
660 |
|
661 TInt size(0); |
|
662 User::LeaveIfError(keyFile.Size(size)); |
|
663 HBufC8* keyData = HBufC8::NewLC(size); |
|
664 TPtr8 ptr = keyData->Des(); |
|
665 |
|
666 User::LeaveIfError(keyFile.Read(ptr, size)); |
|
667 |
|
668 CDecPKCS8Data* ret = TASN1DecPKCS8::DecodeDERL(*keyData); |
|
669 |
|
670 CleanupStack::PopAndDestroy(3, &fs); // keyFile, keyData |
|
671 return ret; |
|
672 } |
|
673 |
|
674 HBufC8* CTlsStepBase::ReadRandomL(const TDesC& aTag) |
|
675 { |
|
676 TPtrC randomFile; |
|
677 if (!GetStringFromConfig(ConfigSection(), aTag, randomFile)) |
|
678 { |
|
679 User::Leave(KErrNotFound); |
|
680 } |
|
681 |
|
682 RFs fs; |
|
683 User::LeaveIfError(fs.Connect()); |
|
684 CleanupClosePushL(fs); |
|
685 |
|
686 RFile file; |
|
687 User::LeaveIfError(file.Open(fs, randomFile, EFileRead)); |
|
688 CleanupClosePushL(file); |
|
689 |
|
690 TInt fileSize; |
|
691 User::LeaveIfError(file.Size(fileSize)); |
|
692 |
|
693 HBufC8* random = HBufC8::NewLC(fileSize); |
|
694 TPtr8 randomDes = random->Des(); |
|
695 User::LeaveIfError(file.Read(randomDes)); |
|
696 |
|
697 CleanupStack::Pop(random); |
|
698 CleanupStack::PopAndDestroy(2, &fs); // file |
|
699 return random; |
|
700 } |
|
701 |
|
702 HBufC8* CTlsStepBase::ComputeTlsMasterSecretL(const TDesC8& aPremasterSecret) |
|
703 { |
|
704 HBufC8* random = HBufC8::NewLC(KTLSServerClientRandomLen * 2); |
|
705 |
|
706 TTLSMasterSecretInput params = iProvider->Attributes()->iMasterSecretInput; |
|
707 random->Des().Append(params.iClientRandom); |
|
708 random->Des().Append(params.iServerRandom); |
|
709 |
|
710 _LIT8(KMasterSecretLabel, "master secret"); |
|
711 HBufC8* ret = CTls10PsuedoRandom::PseudoRandomL(aPremasterSecret, KMasterSecretLabel, |
|
712 *random, KTLSMasterSecretLen); |
|
713 CleanupStack::PushL(ret); |
|
714 |
|
715 ComputeTlsCipherKeysL(*ret, *random); |
|
716 |
|
717 CleanupStack::Pop(ret); |
|
718 CleanupStack::PopAndDestroy(random); |
|
719 return ret; |
|
720 } |
|
721 |
|
722 HBufC8* CTlsStepBase::ComputeSslMasterSecretL(const TDesC8& aPremasterSecret) |
|
723 { |
|
724 HBufC8* random = HBufC8::NewLC(KTLSServerClientRandomLen * 2); |
|
725 |
|
726 TTLSMasterSecretInput params = iProvider->Attributes()->iMasterSecretInput; |
|
727 random->Des().Append(params.iClientRandom); |
|
728 random->Des().Append(params.iServerRandom); |
|
729 |
|
730 HBufC8* ret = CSsl30PsuedoRandom::PseudoRandomL(aPremasterSecret, *random, KTLSMasterSecretLen); |
|
731 CleanupStack::PushL(ret); |
|
732 |
|
733 ComputeSslCipherKeysL(*ret, *random); |
|
734 |
|
735 CleanupStack::Pop(ret); |
|
736 CleanupStack::PopAndDestroy(random); |
|
737 return ret; |
|
738 } |
|
739 |
|
740 void CTlsStepBase::ComputeTlsCipherKeysL(const TDesC8& aMasterSecret, const TDesC8& aRandom) |
|
741 { |
|
742 // Look up the cipher suite we used for this test |
|
743 CTlsCryptoAttributes* atts = Provider()->Attributes(); |
|
744 |
|
745 TInt index = CipherSuiteIndex(atts->iCurrentCipherSuite); |
|
746 User::LeaveIfError(index); |
|
747 |
|
748 TTLSCipherSuite suite = CipherSuites()[index]; |
|
749 |
|
750 // Key material is: |
|
751 // - 2 mac secrets of size hash_size |
|
752 // - 2 bulk cipher secrets of size keymaterial_size |
|
753 // - 2 initialisation vectors of size iv_size |
|
754 |
|
755 TInt hashSize = suite.CipherDetails()->iHashSize; |
|
756 TInt keySize = suite.CipherDetails()->iKeyMaterial; |
|
757 TInt ivSize = suite.CipherDetails()->iIVSize; |
|
758 |
|
759 TInt keyMaterialSize = (2*hashSize) + (2*keySize) + (2*ivSize); |
|
760 |
|
761 // This calculation uses the random data in the opposite order to the master secret |
|
762 |
|
763 HBufC8* random = HBufC8::NewLC(KTLSServerClientRandomLen * 2); |
|
764 TTLSMasterSecretInput params = atts->iMasterSecretInput; |
|
765 random->Des().Append(params.iServerRandom); |
|
766 random->Des().Append(params.iClientRandom); |
|
767 |
|
768 _LIT8(KKeyExpansionLabel, "key expansion"); |
|
769 HBufC8* keyMaterial = CTls10PsuedoRandom::PseudoRandomL(aMasterSecret, KKeyExpansionLabel, |
|
770 *random, keyMaterialSize); |
|
771 CleanupStack::PushL(keyMaterial); |
|
772 |
|
773 iClientMacSecret = keyMaterial->Left(hashSize).AllocL(); |
|
774 iServerMacSecret = keyMaterial->Mid(hashSize, hashSize).AllocL(); |
|
775 |
|
776 // if the cipher is exportable, we need to do further PRF calculations to get the keys |
|
777 if (suite.CipherDetails()->iIsExportable) |
|
778 { |
|
779 TInt expandedKeySize = suite.CipherDetails()->iExpKeySize; |
|
780 |
|
781 _LIT8(KClientWriteLabel, "client write key"); |
|
782 iClientWriteSecret = CTls10PsuedoRandom::PseudoRandomL(keyMaterial->Mid(2*hashSize, keySize), |
|
783 KClientWriteLabel, aRandom, expandedKeySize); |
|
784 |
|
785 _LIT8(KServerWriteLabel, "server write key"); |
|
786 iServerWriteSecret = CTls10PsuedoRandom::PseudoRandomL(keyMaterial->Mid((2*hashSize)+keySize, keySize), |
|
787 KServerWriteLabel, aRandom, expandedKeySize); |
|
788 |
|
789 _LIT8(KIVBlockLabel, "IV block"); |
|
790 HBufC8* ivMaterial = CTls10PsuedoRandom::PseudoRandomL(KNullDesC8, KIVBlockLabel, aRandom, 2*ivSize); |
|
791 CleanupStack::PushL(ivMaterial); |
|
792 |
|
793 iClientInitVector = ivMaterial->Left(ivSize).AllocL(); |
|
794 iServerInitVector = ivMaterial->Right(ivSize).AllocL(); |
|
795 |
|
796 CleanupStack::PopAndDestroy(ivMaterial); |
|
797 } |
|
798 else |
|
799 { |
|
800 // just devide the key material up in to its respective blocks |
|
801 iClientWriteSecret = keyMaterial->Mid(2*hashSize, keySize).AllocL(); |
|
802 iServerWriteSecret = keyMaterial->Mid((2*hashSize)+keySize, keySize).AllocL(); |
|
803 iClientInitVector = keyMaterial->Mid((2*hashSize)+(2*keySize), ivSize).AllocL(); |
|
804 iServerInitVector = keyMaterial->Right(ivSize).AllocL(); |
|
805 } |
|
806 |
|
807 CleanupStack::PopAndDestroy(2, random); // keyMaterial |
|
808 } |
|
809 |
|
810 void CTlsStepBase::ComputeSslCipherKeysL(const TDesC8& aMasterSecret, const TDesC8& aRandom) |
|
811 { |
|
812 // Look up the cipher suite we used for this test |
|
813 CTlsCryptoAttributes* atts = Provider()->Attributes(); |
|
814 |
|
815 TInt index = CipherSuiteIndex(atts->iCurrentCipherSuite); |
|
816 User::LeaveIfError(index); |
|
817 |
|
818 TTLSCipherSuite suite = CipherSuites()[index]; |
|
819 |
|
820 // Key material is: |
|
821 // - 2 mac secrets of size hash_size |
|
822 // - 2 bulk cipher secrets of size keymaterial_size |
|
823 // - 2 initialisation vectors of size iv_size |
|
824 |
|
825 TInt hashSize = suite.CipherDetails()->iHashSize; |
|
826 TInt keySize = suite.CipherDetails()->iKeyMaterial; |
|
827 TInt ivSize = suite.CipherDetails()->iIVSize; |
|
828 |
|
829 TInt keyMaterialSize = (2*hashSize) + (2*keySize) + (2*ivSize); |
|
830 |
|
831 // This calculation uses the random data in the opposite order to the master secret |
|
832 |
|
833 HBufC8* random = HBufC8::NewLC(KTLSServerClientRandomLen * 2); |
|
834 TTLSMasterSecretInput params = atts->iMasterSecretInput; |
|
835 random->Des().Append(params.iServerRandom); |
|
836 random->Des().Append(params.iClientRandom); |
|
837 |
|
838 HBufC8* keyMaterial = CSsl30PsuedoRandom::PseudoRandomL(aMasterSecret, *random, keyMaterialSize); |
|
839 CleanupStack::PushL(keyMaterial); |
|
840 |
|
841 iClientMacSecret = keyMaterial->Left(hashSize).AllocL(); |
|
842 iServerMacSecret = keyMaterial->Mid(hashSize, hashSize).AllocL(); |
|
843 |
|
844 // if the cipher is exportable, we need to do further MD5 calculations to get the keys |
|
845 if (suite.CipherDetails()->iIsExportable) |
|
846 { |
|
847 TInt expandedKeySize = suite.CipherDetails()->iExpKeySize; |
|
848 |
|
849 CMessageDigest* md5dig = CMessageDigestFactory::NewDigestLC(CMessageDigest::EMD5); |
|
850 |
|
851 md5dig->Update(keyMaterial->Mid((2*hashSize), keySize)); |
|
852 iClientWriteSecret = md5dig->Hash(aRandom).Left(expandedKeySize).AllocL(); |
|
853 md5dig->Reset(); |
|
854 |
|
855 md5dig->Update(keyMaterial->Mid((2*hashSize)+keySize, keySize)); |
|
856 iServerWriteSecret = md5dig->Hash(*random).Left(expandedKeySize).AllocL(); |
|
857 md5dig->Reset(); |
|
858 |
|
859 iClientInitVector = md5dig->Hash(aRandom).Left(ivSize).AllocL(); |
|
860 md5dig->Reset(); |
|
861 |
|
862 iServerInitVector = md5dig->Hash(*random).Left(ivSize).AllocL(); |
|
863 |
|
864 CleanupStack::PopAndDestroy(md5dig); |
|
865 } |
|
866 else |
|
867 { |
|
868 // just devide the key material up in to its respective blocks |
|
869 iClientWriteSecret = keyMaterial->Mid(2*hashSize, keySize).AllocL(); |
|
870 iServerWriteSecret = keyMaterial->Mid((2*hashSize)+keySize, keySize).AllocL(); |
|
871 iClientInitVector = keyMaterial->Mid((2*hashSize)+(2*keySize), ivSize).AllocL(); |
|
872 iServerInitVector = keyMaterial->Right(ivSize).AllocL(); |
|
873 } |
|
874 |
|
875 CleanupStack::PopAndDestroy(2, random); // keyMaterial |
|
876 } |
|
877 |
|
878 HBufC8* CTlsStepBase::ComputeTlsMacL(const TDesC8& aData, TInt64 aSequenceNumber, TRecordProtocol& aType, TBool aIsServerMac) |
|
879 { |
|
880 HBufC8* macSecret = aIsServerMac ? ServerMacSecret() : ClientMacSecret(); |
|
881 |
|
882 // look up the cipher suite |
|
883 CTlsCryptoAttributes* atts = Provider()->Attributes(); |
|
884 |
|
885 TInt index = CipherSuiteIndex(atts->iCurrentCipherSuite); |
|
886 User::LeaveIfError(index); |
|
887 |
|
888 TTLSCipherSuite suite = CipherSuites()[index]; |
|
889 |
|
890 // use the hash algorithm associated with it for the mac. |
|
891 CMessageDigest::THashId hashId = CMessageDigest::ESHA1; |
|
892 switch (suite.CipherDetails()->iMacAlg) |
|
893 { |
|
894 case EMd5: |
|
895 hashId = CMessageDigest::EMD5; |
|
896 break; |
|
897 case ESha: |
|
898 hashId = CMessageDigest::ESHA1; |
|
899 break; |
|
900 default: |
|
901 User::Leave(KErrUnknown); // unknown mac algorithm |
|
902 break; |
|
903 } |
|
904 |
|
905 CMessageDigest* digest = CMessageDigestFactory::NewHMACLC(hashId, *macSecret); |
|
906 |
|
907 // construct the mac header, which consists of: |
|
908 // - The 8 byte sequence number |
|
909 // - The one byte record type |
|
910 // - The two byte version |
|
911 // - The two byte record length |
|
912 // = 13 bytes |
|
913 |
|
914 TBuf8<13> macHeader; |
|
915 macHeader.SetLength(13); |
|
916 |
|
917 TUint len = aData.Length(); |
|
918 TInt64 seq = aSequenceNumber; |
|
919 for (TInt i = 7; i >= 0; --i) |
|
920 { |
|
921 macHeader[i] = seq; |
|
922 seq >>= 8; |
|
923 } |
|
924 |
|
925 macHeader[8] = aType; |
|
926 macHeader[9] = atts->iNegotiatedProtocol.iMajor; |
|
927 macHeader[10] = atts->iNegotiatedProtocol.iMinor; |
|
928 macHeader[11] = (len >> 8); |
|
929 macHeader[12] = len; |
|
930 |
|
931 // now, hash the header and the data to get the final mac |
|
932 digest->Update(macHeader); |
|
933 HBufC8* ret = digest->Hash(aData).AllocL(); |
|
934 |
|
935 CleanupStack::PopAndDestroy(digest); |
|
936 return ret; |
|
937 } |
|
938 |
|
939 |
|
940 HBufC8* CTlsStepBase::ComputeSslMacL(const TDesC8& aData, TInt64 aSequenceNumber, TRecordProtocol& aType, TBool aIsServerMac) |
|
941 { |
|
942 HBufC8* macSecret = aIsServerMac ? ServerMacSecret() : ClientMacSecret(); |
|
943 |
|
944 // look up the cipher suite |
|
945 CTlsCryptoAttributes* atts = Provider()->Attributes(); |
|
946 |
|
947 TInt index = CipherSuiteIndex(atts->iCurrentCipherSuite); |
|
948 User::LeaveIfError(index); |
|
949 |
|
950 TTLSCipherSuite suite = CipherSuites()[index]; |
|
951 |
|
952 // use the hash algorithm associated with it for the mac. |
|
953 CMessageDigest::THashId hashId = CMessageDigest::ESHA1; |
|
954 TInt paddingLen = 0; |
|
955 switch (suite.CipherDetails()->iMacAlg) |
|
956 { |
|
957 case EMd5: |
|
958 hashId = CMessageDigest::EMD5; |
|
959 paddingLen = 48; |
|
960 break; |
|
961 case ESha: |
|
962 hashId = CMessageDigest::ESHA1; |
|
963 paddingLen = 40; |
|
964 break; |
|
965 default: |
|
966 User::Leave(KErrUnknown); // unknown mac algorithm |
|
967 break; |
|
968 } |
|
969 |
|
970 CMessageDigest* digest = CMessageDigestFactory::NewDigestLC(hashId); |
|
971 |
|
972 // construct the mac header, which consists of: |
|
973 // - The 8 byte sequence number |
|
974 // - The one byte record type |
|
975 // - The two byte record length |
|
976 // = 11 bytes |
|
977 |
|
978 TBuf8<11> macHeader; |
|
979 macHeader.SetLength(11); |
|
980 |
|
981 TUint len = aData.Length(); |
|
982 TInt64 seq = aSequenceNumber; |
|
983 for (TInt i = 7; i >= 0; --i) |
|
984 { |
|
985 macHeader[i] = seq; |
|
986 seq >>= 8; |
|
987 } |
|
988 |
|
989 macHeader[8] = aType; |
|
990 macHeader[9] = (len >> 8); |
|
991 macHeader[10] = len; |
|
992 |
|
993 // construct the padding. |
|
994 HBufC8* padding = HBufC8::NewLC(paddingLen); |
|
995 TPtr8 paddingBuf = padding->Des(); |
|
996 paddingBuf.SetLength(paddingLen); |
|
997 |
|
998 // fill padding buffer for padding 1 |
|
999 paddingBuf.Fill(0x36); |
|
1000 |
|
1001 // compute the inner hash |
|
1002 digest->Update(*macSecret); |
|
1003 digest->Update(*padding); |
|
1004 digest->Update(macHeader); |
|
1005 digest->Update(aData); |
|
1006 HBufC8* inner = digest->Final().AllocL(); |
|
1007 |
|
1008 digest->Reset(); |
|
1009 // fill padding buffer for padding 2 |
|
1010 paddingBuf.Fill(0x5c); |
|
1011 |
|
1012 // compute the outer hash |
|
1013 digest->Update(*macSecret); |
|
1014 digest->Update(*padding); |
|
1015 digest->Update(*inner); |
|
1016 delete inner; |
|
1017 |
|
1018 HBufC8* ret = digest->Final().AllocL(); |
|
1019 CleanupStack::PopAndDestroy(2, digest); // padding |
|
1020 return ret; |
|
1021 } |
|
1022 |
|
1023 HBufC8* CTlsStepBase::ComputeTlsFinishedL(CMessageDigest* aShaDigest, CMessageDigest* aMd5Digest, |
|
1024 const TDesC8& aMasterSecret, TBool aClientFinished) |
|
1025 { |
|
1026 CMessageDigest* ourSha = aShaDigest->CopyL(); |
|
1027 CleanupStack::PushL(ourSha); |
|
1028 |
|
1029 CMessageDigest* ourMd = aMd5Digest->CopyL(); |
|
1030 CleanupStack::PushL(ourMd); |
|
1031 |
|
1032 TInt len = ourSha->HashSize() + ourMd->HashSize(); |
|
1033 HBufC8* hashBuf = HBufC8::NewLC(len); |
|
1034 |
|
1035 hashBuf->Des().Append(ourMd->Final()); |
|
1036 hashBuf->Des().Append(ourSha->Final()); |
|
1037 |
|
1038 _LIT8(KClientLabel, "client finished"); |
|
1039 _LIT8(KServerLabel, "server finished"); |
|
1040 |
|
1041 TPtrC8 label; |
|
1042 if (aClientFinished) |
|
1043 { |
|
1044 label.Set(KClientLabel); |
|
1045 } |
|
1046 else |
|
1047 { |
|
1048 label.Set(KServerLabel); |
|
1049 } |
|
1050 |
|
1051 HBufC8* ret = CTls10PsuedoRandom::PseudoRandomL(aMasterSecret, label, *hashBuf, 12); |
|
1052 CleanupStack::PopAndDestroy(3, ourSha); |
|
1053 return ret; |
|
1054 } |
|
1055 |
|
1056 HBufC8* CTlsStepBase::ComputeSslFinishedL(CMessageDigest* aShaDigest, CMessageDigest* aMd5Digest, |
|
1057 const TDesC8& aMasterSecret, TBool aClientFinished) |
|
1058 { |
|
1059 CMessageDigest* ourSha = aShaDigest->CopyL(); |
|
1060 CleanupStack::PushL(ourSha); |
|
1061 |
|
1062 CMessageDigest* ourMd = aMd5Digest->CopyL(); |
|
1063 CleanupStack::PushL(ourMd); |
|
1064 |
|
1065 _LIT8(KClientLabel, "CLNT"); |
|
1066 _LIT8(KServerLabel, "SRVR"); |
|
1067 |
|
1068 TPtrC8 label; |
|
1069 if (aClientFinished) |
|
1070 { |
|
1071 label.Set(KClientLabel); |
|
1072 } |
|
1073 else |
|
1074 { |
|
1075 label.Set(KServerLabel); |
|
1076 } |
|
1077 |
|
1078 // hash the label and master secret |
|
1079 ourSha->Update(label); |
|
1080 ourMd->Update(label); |
|
1081 |
|
1082 ourSha->Update(aMasterSecret); |
|
1083 ourMd->Update(aMasterSecret); |
|
1084 |
|
1085 // add the padding |
|
1086 HBufC8* shaPadding = HBufC8::NewLC(40); |
|
1087 TPtr8 shaPaddingBuf = shaPadding->Des(); |
|
1088 shaPaddingBuf.SetLength(40); |
|
1089 |
|
1090 HBufC8* mdPadding = HBufC8::NewLC(48); |
|
1091 TPtr8 mdPaddingBuf = mdPadding->Des(); |
|
1092 mdPaddingBuf.SetLength(48); |
|
1093 |
|
1094 shaPaddingBuf.Fill(0x36); |
|
1095 mdPaddingBuf.Fill(0x36); |
|
1096 |
|
1097 ourSha->Update(shaPaddingBuf); |
|
1098 ourMd->Update(mdPaddingBuf); |
|
1099 |
|
1100 // finalise the inner hashes |
|
1101 HBufC8* innerSha = ourSha->Final().AllocLC(); |
|
1102 HBufC8* innerMd = ourMd->Final().AllocLC(); |
|
1103 |
|
1104 // reset for the outer hashes |
|
1105 ourSha->Reset(); |
|
1106 ourMd->Reset(); |
|
1107 |
|
1108 // hash master secret and padding for outer hashes |
|
1109 ourSha->Update(aMasterSecret); |
|
1110 ourMd->Update(aMasterSecret); |
|
1111 |
|
1112 shaPaddingBuf.Fill(0x5c); |
|
1113 mdPaddingBuf.Fill(0x5c); |
|
1114 |
|
1115 ourSha->Update(shaPaddingBuf); |
|
1116 ourMd->Update(mdPaddingBuf); |
|
1117 |
|
1118 // and finally, the inner hash. |
|
1119 ourSha->Update(*innerSha); |
|
1120 ourMd->Update(*innerMd); |
|
1121 |
|
1122 // create the final buffer |
|
1123 HBufC8* ret = HBufC8::NewL(ourSha->HashSize() + ourMd->HashSize()); |
|
1124 ret->Des().Append(ourMd->Final()); |
|
1125 ret->Des().Append(ourSha->Final()); |
|
1126 |
|
1127 CleanupStack::PopAndDestroy(6, ourSha); // ourMd, shaPadding, mdPadding, innerSha, innerMd |
|
1128 return ret; |
|
1129 } |
|
1130 |
|
1131 TInt CTlsStepBase::ClientCertificate(CX509Certificate* aCert) |
|
1132 { |
|
1133 iSession->ClientCertificate(aCert,iActive->iStatus); |
|
1134 iActive->Start(); |
|
1135 return iActive->iStatus.Int(); |
|
1136 } |
|
1137 |
|
1138 TInt CTlsStepBase::ClientCertificate(HBufC8*& aCertBuf) |
|
1139 { |
|
1140 iActive->iStatus = KRequestPending; |
|
1141 iSession->ClientCertificate(aCertBuf, iActive->iStatus); |
|
1142 iActive->Start(); |
|
1143 return iActive->iStatus.Int(); |
|
1144 } |
|
1145 |
|
1146 TInt CTlsStepBase::ClientCertificate(RPointerArray<HBufC8>* aClientCertArray) |
|
1147 { |
|
1148 iActive->iStatus = KRequestPending; |
|
1149 iSession->ClientCertificate(aClientCertArray, iActive->iStatus); |
|
1150 iActive->Start(); |
|
1151 return iActive->iStatus.Int(); |
|
1152 } |
|
1153 |
|
1154 TInt CTlsStepBase::CertificateVerifySignatureL( |
|
1155 CMessageDigest* iMd5DigestInput, |
|
1156 CMessageDigest* iShaDigestInput, |
|
1157 HBufC8*& aOutput) |
|
1158 { |
|
1159 iActive->iStatus = KRequestPending; |
|
1160 iSession->CertificateVerifySignatureL( |
|
1161 iMd5DigestInput, |
|
1162 iShaDigestInput, |
|
1163 aOutput, |
|
1164 iActive->iStatus); |
|
1165 iActive->Start(); |
|
1166 return iActive->iStatus.Int(); |
|
1167 } |
|
1168 |
|
1169 TBool CTlsStepBase::ReadPskToBeUsedL() |
|
1170 { |
|
1171 |
|
1172 TBool theReturn = ETrue; |
|
1173 |
|
1174 |
|
1175 TBool usePsk; |
|
1176 if(GetBoolFromConfig(ConfigSection(), KUsePsk, usePsk)) |
|
1177 { |
|
1178 iUsePsk = usePsk; |
|
1179 } |
|
1180 else |
|
1181 { |
|
1182 iUsePsk = EFalse; |
|
1183 theReturn = EFalse; |
|
1184 } |
|
1185 |
|
1186 // Reads key 1 value |
|
1187 if (iUsePsk) |
|
1188 { |
|
1189 TPtrC8 pskKey; |
|
1190 if(GetKeyFromConfigL(ConfigSection(),KPskKey ,pskKey ) ) |
|
1191 { |
|
1192 iPskKey = pskKey.AllocL(); |
|
1193 } |
|
1194 else |
|
1195 { |
|
1196 ERR_PRINTF1(_L("Couldn't read PSK key") ); |
|
1197 User::Leave(KErrGeneral); |
|
1198 } |
|
1199 } |
|
1200 |
|
1201 // Reads PSK identity |
|
1202 if (iUsePsk) |
|
1203 { |
|
1204 TPtrC pskIdentity; |
|
1205 if(GetStringFromConfig(ConfigSection(), KPskIdentity, pskIdentity) ) |
|
1206 { |
|
1207 iPskIdentity = HBufC8::New(pskIdentity.Length()); |
|
1208 iPskIdentity->Des().Copy(pskIdentity); |
|
1209 } |
|
1210 else |
|
1211 { |
|
1212 ERR_PRINTF1(_L("Couldn't read PSK identity") ); |
|
1213 User::Leave(KErrGeneral); |
|
1214 } |
|
1215 } |
|
1216 |
|
1217 return theReturn; |
|
1218 } |
|
1219 |
|
1220 void CTlsStepBase::ReadUseNullCipher() |
|
1221 { |
|
1222 TBool useNullCipher; |
|
1223 if(GetBoolFromConfig(ConfigSection(), KUseNullCipher, useNullCipher)) |
|
1224 { |
|
1225 iUseNullCipher = useNullCipher; |
|
1226 } |
|
1227 else |
|
1228 { |
|
1229 iUseNullCipher = EFalse; |
|
1230 } |
|
1231 } |
|
1232 |
|
1233 TInt CTlsStepBase::ReadGetSessionDelayL() |
|
1234 { |
|
1235 TInt sessionDelay; |
|
1236 |
|
1237 if(GetIntFromConfig(ConfigSection(), KSessionDelay, sessionDelay)) |
|
1238 { |
|
1239 return sessionDelay; |
|
1240 } |
|
1241 else |
|
1242 { |
|
1243 ERR_PRINTF1(_L("Couldn't read session delay INI value") ); |
|
1244 User::Leave(KErrNotFound); |
|
1245 } |
|
1246 // Keeps compiler happy, will not hit. |
|
1247 return 0; |
|
1248 } |
|
1249 |
|
1250 HBufC8* CTlsStepBase::StringToHexLC(const TDes8 &aString) |
|
1251 /** |
|
1252 * Function to convert the contents of a TDes8 into a Binary format |
|
1253 * |
|
1254 * @param - cosnt TDes8 aString: String to convert into Hexadecimal |
|
1255 * @return - HBufC8*: Converted Binary string representation |
|
1256 **/ |
|
1257 { |
|
1258 HBufC8* parsedString = HBufC8::NewLC(aString.Length()/2); |
|
1259 |
|
1260 TBuf8<1> binChar; |
|
1261 _LIT8(KFormatBinary,"%c"); |
|
1262 |
|
1263 TPtr8 ptr(parsedString->Des()); |
|
1264 |
|
1265 for(TInt i = 0; i<aString.Length()/2 ; i++) |
|
1266 { |
|
1267 TPtrC8 tempPtr(aString.Mid(i*2,2)); |
|
1268 TLex8 lex(tempPtr); |
|
1269 TUint val=0; |
|
1270 lex.Val(val, EHex); |
|
1271 binChar.Format(KFormatBinary,val); |
|
1272 ptr.Append(binChar); |
|
1273 |
|
1274 } |
|
1275 |
|
1276 |
|
1277 return parsedString; |
|
1278 } |
|
1279 |
|
1280 |
|
1281 |
|
1282 |
|
1283 TBool CTlsStepBase::GetKeyFromConfigL(const TDesC& aSectName, const TDesC& aIniValueName, TPtrC8 & aResult) |
|
1284 { |
|
1285 |
|
1286 |
|
1287 TBool theReturn(ETrue); |
|
1288 // The buffer with key read form ini file as a string converted to a buffer of hex. |
|
1289 |
|
1290 TPtrC iniString; |
|
1291 if(GetStringFromConfig(aSectName, aIniValueName, iniString)) |
|
1292 { |
|
1293 |
|
1294 |
|
1295 TInt stringLength(iniString.Length()); |
|
1296 // Assumes that keys must be formed by Hex pairs (full bytes) |
|
1297 // example: ABC1 is acceptable. ABC is not acceptable |
|
1298 if( stringLength % 2 > 0) |
|
1299 { |
|
1300 // not pairs. |
|
1301 theReturn = EFalse; |
|
1302 } |
|
1303 // Pairs |
|
1304 else |
|
1305 { |
|
1306 |
|
1307 HBufC8* keyBuf = HBufC8::New(iniString.Length()); |
|
1308 TPtr8 ptrKey = keyBuf->Des(); |
|
1309 ptrKey.Copy(iniString); |
|
1310 |
|
1311 HBufC8* key = StringToHexLC(keyBuf->Des()); |
|
1312 delete keyBuf; |
|
1313 aResult.Set(key->Des()); |
|
1314 CleanupStack::PopAndDestroy(key); |
|
1315 |
|
1316 } |
|
1317 |
|
1318 } |
|
1319 |
|
1320 return theReturn; |
|
1321 } |
|
1322 |
|
1323 TInt CTlsStepBase::SessionServerCertificate(CX509Certificate*& aCertOut) |
|
1324 { |
|
1325 iActive->iStatus = KRequestPending; |
|
1326 iSession->ServerCertificate(aCertOut, iActive->iStatus ); |
|
1327 iActive->Start(); |
|
1328 return iActive->iStatus.Int(); |
|
1329 |
|
1330 } |
|
1331 |
|
1332 TInt CTlsStepBase::SessionServerCertificateWithCancel(CX509Certificate*& aCertOut) |
|
1333 { |
|
1334 iActive->iStatus = KRequestPending; |
|
1335 iSession->ServerCertificate(aCertOut, iActive->iStatus ); |
|
1336 iSession->CancelRequest(); |
|
1337 iActive->Start(); |
|
1338 return iActive->iStatus.Int(); |
|
1339 } |
|
1340 |
|
1341 void CTlsStepBase::StandardAttrInit( CTlsCryptoAttributes* tlsCryptoAttributes) |
|
1342 { |
|
1343 tlsCryptoAttributes->iClientAuthenticate = EFalse; |
|
1344 tlsCryptoAttributes->iDialogNonAttendedMode = ETrue; |
|
1345 |
|
1346 tlsCryptoAttributes->iSessionNameAndID.iServerName.iAddress.Copy( KNServer1 ); |
|
1347 tlsCryptoAttributes->iSessionNameAndID.iServerName.iPort = 10; |
|
1348 tlsCryptoAttributes->iSessionNameAndID.iSessionId.Append( KSessionId1 ); |
|
1349 |
|
1350 tlsCryptoAttributes->iCompressionMethod = ENullCompression; |
|
1351 tlsCryptoAttributes->iCurrentCipherSuite.iHiByte = 0; |
|
1352 tlsCryptoAttributes->iCurrentCipherSuite.iLoByte = 3; |
|
1353 |
|
1354 tlsCryptoAttributes->iNegotiatedProtocol.iMajor = 3; |
|
1355 tlsCryptoAttributes->iNegotiatedProtocol.iMinor = 1; |
|
1356 |
|
1357 tlsCryptoAttributes->iProposedProtocol.iMajor = 3; |
|
1358 tlsCryptoAttributes->iProposedProtocol.iMinor = 1; |
|
1359 |
|
1360 tlsCryptoAttributes->iPublicKeyParams->iKeyType = ERsa; |
|
1361 tlsCryptoAttributes->iClientAuthenticate = EFalse; |
|
1362 tlsCryptoAttributes->iDialogNonAttendedMode = ETrue; |
|
1363 } |
|
1364 |
|
1365 void CTlsStepBase::DeleteSecureDialogFilesL() |
|
1366 { |
|
1367 RFs fs; |
|
1368 User::LeaveIfError(fs.Connect()); |
|
1369 CleanupClosePushL(fs); |
|
1370 |
|
1371 CFileMan* fileMan = CFileMan::NewL(fs); |
|
1372 CleanupStack::PushL(fileMan); |
|
1373 |
|
1374 TDriveUnit sysDrive (RFs::GetSystemDrive()); |
|
1375 TDriveName sysDriveName (sysDrive.Name()); |
|
1376 |
|
1377 TBuf<128> fileName (sysDriveName); |
|
1378 fileName.Append(KInputFile); |
|
1379 TInt err = fileMan->Delete(fileName); |
|
1380 if ( err != KErrNotFound && err != KErrNone ) |
|
1381 { |
|
1382 User::LeaveIfError(err); |
|
1383 } |
|
1384 |
|
1385 fileName.Copy(sysDriveName); |
|
1386 fileName.Append(KOutputFile); |
|
1387 err = fileMan->Delete(fileName); |
|
1388 if (err != KErrNotFound && err != KErrNone ) |
|
1389 { |
|
1390 User::LeaveIfError(err); |
|
1391 } |
|
1392 CleanupStack::PopAndDestroy(2, &fs);// and fileMan |
|
1393 } |
|
1394 |
|
1395 void CTlsStepBase::SetDialogRecordL(RFileWriteStream& aStream, TSecurityDialogOperation aOp, const TDesC& aLabelSpec, |
|
1396 const TDesC& aResponse1, const TDesC& aResponse2) |
|
1397 { |
|
1398 MStreamBuf* streamBuf = aStream.Sink(); |
|
1399 streamBuf->SeekL(MStreamBuf::EWrite, EStreamEnd); |
|
1400 aStream.WriteInt32L(aOp); |
|
1401 aStream.WriteInt32L(aLabelSpec.Length()); |
|
1402 aStream.WriteL(aLabelSpec); |
|
1403 aStream.WriteInt32L(aResponse1.Length()); |
|
1404 aStream.WriteL(aResponse1); |
|
1405 aStream.WriteInt32L(aResponse2.Length()); |
|
1406 aStream.WriteL(aResponse2); |
|
1407 } |
|
1408 |
|
1409 |
|
1410 |