|
1 /* |
|
2 * Copyright (c) 2002-2008 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: Roap engine |
|
15 * |
|
16 */ |
|
17 |
|
18 |
|
19 // INCLUDE FILES |
|
20 |
|
21 #include <random.h> |
|
22 |
|
23 #include <DocumentHandler.h> |
|
24 |
|
25 #ifdef RD_MULTIPLE_DRIVE |
|
26 #include <pathinfo.h> |
|
27 #include <driveinfo.h> |
|
28 #else |
|
29 #include <pathinfo.h> |
|
30 #endif |
|
31 |
|
32 #ifndef __WINS__ |
|
33 #include <etelmm.h> |
|
34 #include <mmtsy_names.h> |
|
35 #include <SysUtil.h> |
|
36 #endif |
|
37 |
|
38 #include <flogger.h> |
|
39 #include <x509cert.h> |
|
40 #include <x509certext.h> |
|
41 #include <hash.h> |
|
42 #include <utf.h> |
|
43 #include <asn1dec.h> |
|
44 #include <centralrepository.h> |
|
45 #include <e32base.h> // CleanupResetAndDestroyPushL dependencies |
|
46 |
|
47 #include "cleanupresetanddestroy.h" // CleanupResetAndDestroyPushL |
|
48 #include "DRMRights.h" |
|
49 #include "RoapEng.h" |
|
50 #include "RoapTrigger.h" |
|
51 #include "wbxmlroaptriggerparser.h" |
|
52 #include "RoapResponse.h" |
|
53 #include "RoapMessage.h" |
|
54 #include "RoapParser.h" |
|
55 #include "RoapSigner.h" |
|
56 #include "DeviceHello.h" |
|
57 #include "RIHello.h" |
|
58 #include "RegistrationReq.h" |
|
59 #include "RegistrationResp.h" |
|
60 #include "RightsReq.h" |
|
61 #include "RightsResp.h" |
|
62 #include "JoinDomainReq.h" |
|
63 #include "JoinDomainResp.h" |
|
64 #include "LeaveDomainReq.h" |
|
65 #include "LeaveDomainResp.h" |
|
66 #ifdef RD_DRM_METERING |
|
67 #include "MeteringReportReq.h" |
|
68 #include "MeteringReportResp.h" |
|
69 #endif |
|
70 #include "RoapStorageClient.h" |
|
71 #include "RoapDef.h" |
|
72 #include "RoapLog.h" |
|
73 #include "RoapObserver.h" |
|
74 #include "CmlaCrypto.h" |
|
75 #include "DRMRIContext.h" |
|
76 #include "DRMDomainContext.h" |
|
77 #include "DRMProtectedRoParser.h" |
|
78 #include "DRMClockClient.h" |
|
79 #include "DcfRep.h" |
|
80 #include "DcfEntry.h" |
|
81 #include "Base64.h" |
|
82 #include "drmsettingsplugininternalcrkeys.h" |
|
83 |
|
84 |
|
85 #define STUB_C_CLASS_IN_NAMESPACE( n, c ) namespace n { class c: public CBase { private: c(); public: virtual ~c(); }; } n::c::c() {} n::c::~c() {} |
|
86 #define STUB_C_CLASS( c ) class c : public CBase { private: c(); public: virtual ~c(); }; c::c() {} c::~c() {} |
|
87 // This class does not do anything. |
|
88 // It is defined here only to keep binary compatibility, |
|
89 // because of unintentional class name leak in |
|
90 // armv5 export history. |
|
91 // Don't ever use this class for anything. |
|
92 STUB_C_CLASS_IN_NAMESPACE( Roap , CWbxmlRoapTriggerToXmlParser ) |
|
93 |
|
94 // Yet another stub classes because of moved classes |
|
95 // which have leaked virtual table entries |
|
96 STUB_C_CLASS( COCSPResponse ) |
|
97 STUB_C_CLASS( COCSPResponseCertInfo ) |
|
98 |
|
99 |
|
100 using namespace Roap; |
|
101 // ================= CONSTANTS ======================= |
|
102 // For parsing multipart content |
|
103 _LIT8(KCmlaIp1, "http://www.cm-la.com/tech/cmlaip/cmlaip#cmlaip-1"); |
|
104 _LIT8(KLeaveDomainElement, "leaveDomain"); |
|
105 _LIT8(KSignedInfoElement, "SignedInfo"); |
|
106 _LIT(KBOM1, "\xFFFE"); |
|
107 _LIT(KBOM2, "\xFEFF"); |
|
108 #ifdef RD_DRM_METERING |
|
109 _LIT8( KRoapVersion11, "1.1" ); |
|
110 #endif |
|
111 |
|
112 static const TInt KDomainGenerationLength( 3 ); |
|
113 static const TInt KMinCertChainLength( 3 ); |
|
114 // ================= LOCAL FUNCTIONS ======================= |
|
115 |
|
116 LOCAL_C TBool SortArrays( |
|
117 RPointerArray<HBufC8>& aKeys, |
|
118 RPointerArray<HBufC8>& aMacs, |
|
119 RPointerArray<HBufC8>& aElements, |
|
120 RArray<TInt>& aOrder ) |
|
121 { |
|
122 TInt i; |
|
123 TInt j; |
|
124 TInt index; |
|
125 HBufC8* temp1 = NULL; |
|
126 HBufC8* temp2 = NULL; |
|
127 HBufC8* temp3 = NULL; |
|
128 TBool isInOrder = ETrue; |
|
129 |
|
130 if ( aOrder.Count() != aKeys.Count() || aKeys.Count() != aMacs.Count() |
|
131 || aMacs.Count() != aElements.Count() ) |
|
132 { |
|
133 return EFalse; |
|
134 } |
|
135 |
|
136 for ( i = 0; i < aKeys.Count(); i++ ) |
|
137 { |
|
138 index = aOrder[i]; |
|
139 temp1 = aKeys[i]; |
|
140 temp2 = aMacs[i]; |
|
141 temp3 = aElements[i]; |
|
142 j = i; |
|
143 while ( ( j > 0 ) && ( aOrder[j - 1] > index ) ) |
|
144 { |
|
145 isInOrder = EFalse; |
|
146 aOrder[j] = aOrder[j - 1]; |
|
147 aKeys[j] = aKeys[j - 1]; |
|
148 aMacs[j] = aMacs[j - 1]; |
|
149 aElements[j] = aElements[j - 1]; |
|
150 j = j - 1; |
|
151 } |
|
152 aOrder[j] = index; |
|
153 aKeys[j] = temp1; |
|
154 aMacs[j] = temp2; |
|
155 aElements[j] = temp3; |
|
156 } |
|
157 return isInOrder; |
|
158 } |
|
159 |
|
160 // ================= MEMBER FUNCTIONS ======================= |
|
161 |
|
162 // --------------------------------------------------------- |
|
163 // CRoapEng::NewL() |
|
164 // --------------------------------------------------------- |
|
165 // |
|
166 EXPORT_C CRoapEng* CRoapEng::NewL() |
|
167 { |
|
168 CRoapEng* engine = new ( ELeave ) CRoapEng(); |
|
169 CleanupStack::PushL( engine ); |
|
170 engine->ConstructL(); |
|
171 CleanupStack::Pop( engine ); |
|
172 return engine; |
|
173 } |
|
174 |
|
175 // --------------------------------------------------------- |
|
176 // CRoapEng::~CRoapEng() |
|
177 // --------------------------------------------------------- |
|
178 // |
|
179 EXPORT_C CRoapEng::~CRoapEng() |
|
180 { |
|
181 if ( iStorageClient ) |
|
182 { |
|
183 iStorageClient->Close(); |
|
184 } |
|
185 delete iStorageClient; |
|
186 if ( iClockClient ) |
|
187 { |
|
188 iClockClient->Close(); |
|
189 } |
|
190 delete iClockClient; |
|
191 delete iParser; |
|
192 delete iSigner; |
|
193 delete iDeviceId; |
|
194 delete iRoParser; |
|
195 delete iDcfRep; |
|
196 iRiAlgorithms.ResetAndDestroy(); |
|
197 } |
|
198 |
|
199 // --------------------------------------------------------- |
|
200 // CRoapEng::~CRoapEng() |
|
201 // --------------------------------------------------------- |
|
202 // |
|
203 void CRoapEng::ConstructL() |
|
204 { |
|
205 LOGLIT( "CRoapEng::ConstructL" ) |
|
206 |
|
207 CRoapEngBase::ConstructL(); |
|
208 iParser = CRoapParser::NewL(); |
|
209 iStorageClient = new ( ELeave ) RRoapStorageClient; |
|
210 User::LeaveIfError( iStorageClient->Connect() ); |
|
211 iClockClient = new ( ELeave ) RDRMClockClient; |
|
212 User::LeaveIfError( iClockClient->Connect() ); |
|
213 TBuf8<SHA1_HASH> deviceId; |
|
214 iStorageClient->GetDevicePublicKeyHashL( deviceId ); |
|
215 iDeviceId = deviceId.AllocL(); |
|
216 iSigner = CRoapSigner::NewL( *iStorageClient ); |
|
217 iRoParser = CDrmProtectedRoParser::NewL(); |
|
218 iDcfRep = CDcfRep::NewL(); |
|
219 iCertNeeded = ETrue; |
|
220 iRiSupportsCertCaching = EFalse; |
|
221 iTransStatus = ENotAsked; |
|
222 iSelectedAlgorithms = EOma; |
|
223 iSelectedRoot = KNullDesC8; |
|
224 iStorageClient->SelectTrustedRootL( KNullDesC8 ); |
|
225 iDeviceTimeError = EFalse; |
|
226 iDomainId.SetLength( 0 ); |
|
227 iSecureTime = ETrue; |
|
228 iZone = 0; |
|
229 } |
|
230 |
|
231 // --------------------------------------------------------- |
|
232 // CRoapEng::CRoapEng() |
|
233 // --------------------------------------------------------- |
|
234 // |
|
235 CRoapEng::CRoapEng() : |
|
236 CRoapEngBase() |
|
237 { |
|
238 } |
|
239 |
|
240 // --------------------------------------------------------- |
|
241 // CRoapEng::ParseTriggerL() |
|
242 // --------------------------------------------------------- |
|
243 // |
|
244 CRoapTrigger* CRoapEng::ParseTriggerL( const TDesC8& aTrigger ) |
|
245 { |
|
246 LOGLIT( "CRoapEng::ParseTriggerL" ) |
|
247 |
|
248 CRoapTrigger* trigger( NULL ); |
|
249 RBuf8 xmlTrigger; |
|
250 CleanupClosePushL( xmlTrigger ); |
|
251 _LIT8( KRoap, "<roap:roapTrigger" ); |
|
252 if ( aTrigger.FindF( KRoap ) == KErrNotFound ) |
|
253 { |
|
254 DRM::CWbxmlRoapTriggerParser* wbParser( |
|
255 DRM::CWbxmlRoapTriggerParser::NewLC() ); |
|
256 HBufC8* b( NULL ); |
|
257 TRAPD( parseError, b = wbParser->ParseL( aTrigger ) ); |
|
258 if ( parseError == KErrNone ) |
|
259 { |
|
260 xmlTrigger.Assign( b ); |
|
261 b = NULL; |
|
262 LOGLIT( " We have a WBXML trigger" ) |
|
263 } |
|
264 else |
|
265 { // OMA BCAST: Check if this is an XML trigger after all.. |
|
266 LOGLIT( " We have an XML trigger after all" ) |
|
267 xmlTrigger.CreateL( aTrigger ); |
|
268 } |
|
269 CleanupStack::PopAndDestroy( wbParser ); |
|
270 } |
|
271 else |
|
272 { |
|
273 xmlTrigger.CreateL( aTrigger ); |
|
274 } |
|
275 trigger = iParser->ParseRoapTriggerL( xmlTrigger ); |
|
276 |
|
277 CleanupStack::PushL( trigger ); |
|
278 if ( !trigger || !trigger->ValidTrigger() ) |
|
279 { |
|
280 User::Leave( KErrRoapGeneral ); |
|
281 } |
|
282 |
|
283 // check that SilentRightsUrl is on the white list |
|
284 // URL is searched from pre-configured white list |
|
285 TBool fromPreConfiguredWhiteList( ETrue ); |
|
286 if ( iStorageClient->WhiteListURLExistsL( *trigger->iRoapUrl, fromPreConfiguredWhiteList ) ) |
|
287 { |
|
288 iAllowedToContactRi = ETrue; |
|
289 } |
|
290 |
|
291 if ( trigger->iTriggerType == ELeaveDomainTrigger && trigger->iSignature ) |
|
292 { |
|
293 if ( !VerifyTriggerSignatureL( xmlTrigger, *trigger ) ) |
|
294 { |
|
295 User::Leave( KErrRoapServerFatal ); |
|
296 } |
|
297 } |
|
298 |
|
299 CleanupStack::Pop( trigger ); |
|
300 CleanupStack::PopAndDestroy( &xmlTrigger ); |
|
301 |
|
302 return trigger; |
|
303 } |
|
304 |
|
305 // --------------------------------------------------------- |
|
306 // CRoapEng::GetRIContextL() |
|
307 // --------------------------------------------------------- |
|
308 // |
|
309 void CRoapEng::GetRIContextL( TBool& aRegistered, const TDesC8& aRiId ) |
|
310 { |
|
311 LOGLIT( "CRoapEng::GetRIContextL" ) |
|
312 |
|
313 CDRMRIContext* context = NULL; |
|
314 |
|
315 aRegistered = EFalse; |
|
316 |
|
317 // delete old RI context and obtain a new one |
|
318 delete iStoredRiContext; |
|
319 iStoredRiContext = NULL; |
|
320 context = iStorageClient->GetRIContextL( aRiId ); |
|
321 if ( !context ) |
|
322 { |
|
323 return; |
|
324 } |
|
325 |
|
326 iStoredRiContext = context; |
|
327 iRiSupportsCertCaching = iStoredRiContext->DeviceCertCached(); |
|
328 iSelectedRoot = iStoredRiContext->SelectedDeviceRoot(); |
|
329 iStorageClient->SelectTrustedRootL( iSelectedRoot ); |
|
330 |
|
331 if ( context->CertificateChain().Count() && context->ExpiryTime() |
|
332 > GetDrmTimeL() ) |
|
333 { |
|
334 aRegistered = ETrue; |
|
335 iUseRiContextUrl = EFalse; |
|
336 } |
|
337 else |
|
338 { |
|
339 // Received Context was invalid or expired |
|
340 iUseRiContextUrl = EFalse; |
|
341 delete iStoredRiContext; |
|
342 iStoredRiContext = NULL; |
|
343 } |
|
344 } |
|
345 |
|
346 // --------------------------------------------------------- |
|
347 // CRoapEng::GetDomainContextL() |
|
348 // --------------------------------------------------------- |
|
349 // |
|
350 void CRoapEng::GetDomainContextL( |
|
351 TBool& aIsJoined, |
|
352 TBool& aIsValidGeneration, |
|
353 const TDesC8& aDomainId ) |
|
354 { |
|
355 LOGLIT( "CRoapEng::GetDomainContextL" ) |
|
356 |
|
357 TInt generation = 0; |
|
358 CDRMDomainContext* context = NULL; |
|
359 |
|
360 aIsJoined = EFalse; |
|
361 aIsValidGeneration = EFalse; |
|
362 |
|
363 // last 3 digits are for Domain generation |
|
364 context = iStorageClient->GetDomainContextL( aDomainId ); |
|
365 |
|
366 if ( !context ) |
|
367 { |
|
368 return; |
|
369 } |
|
370 |
|
371 if ( context->ExpiryTime() > GetDrmTimeL() || context->ExpiryTime() |
|
372 == Time::NullTTime() ) |
|
373 { |
|
374 aIsJoined = ETrue; |
|
375 } |
|
376 |
|
377 TLex8 lex( aDomainId.Right( KDomainGenerationLength ) ); |
|
378 lex.Val( generation ); |
|
379 |
|
380 if ( context->DomainGeneration() >= generation ) |
|
381 { |
|
382 aIsValidGeneration = ETrue; |
|
383 } |
|
384 |
|
385 delete context; |
|
386 } |
|
387 |
|
388 // --------------------------------------------------------- |
|
389 // CRoapEng::CreateReqMessageL() |
|
390 // --------------------------------------------------------- |
|
391 // |
|
392 void CRoapEng::CreateReqMessageL() |
|
393 { |
|
394 LOGLIT( "CRoapEng::CreateReqMessageL" ) |
|
395 |
|
396 __ASSERT_ALWAYS( iTrigger, User::Invariant() ); |
|
397 __ASSERT_ALWAYS( !iRequest, User::Invariant() ); |
|
398 |
|
399 switch ( iReqMessage ) |
|
400 { |
|
401 case EDeviceHello: |
|
402 { |
|
403 iRequest = CreateDeviceHelloL(); |
|
404 break; |
|
405 } |
|
406 case ERegistration: |
|
407 { |
|
408 iRequest = CreateRegistrationRequestL(); |
|
409 break; |
|
410 } |
|
411 case EROAcquisition: |
|
412 { |
|
413 iRequest = CreateRightsRequestL(); |
|
414 break; |
|
415 } |
|
416 case EJoinDomain: |
|
417 { |
|
418 iRequest = CreateJoinDomainRequestL(); |
|
419 break; |
|
420 } |
|
421 case ELeaveDomain: |
|
422 { |
|
423 iRequest = CreateLeaveDomainRequestL(); |
|
424 break; |
|
425 } |
|
426 #ifdef RD_DRM_METERING |
|
427 case EMeteringRequest: |
|
428 { |
|
429 iRequest = CreateMeteringReportRequestL(); |
|
430 break; |
|
431 } |
|
432 #endif |
|
433 default: |
|
434 { |
|
435 User::Leave( KErrArgument ); |
|
436 } |
|
437 } |
|
438 } |
|
439 |
|
440 // --------------------------------------------------------- |
|
441 // CRoapEng::CreateDeviceHelloL() |
|
442 // --------------------------------------------------------- |
|
443 // |
|
444 CRoapMessage* CRoapEng::CreateDeviceHelloL() |
|
445 { |
|
446 LOGLIT( "CRoapEng::CreateDeviceHelloL" ) |
|
447 PERFORMANCE_LOGLIT( "Registration protocol started" ) |
|
448 |
|
449 RPointerArray<TDesC8> idArray; |
|
450 CDeviceHello* req = CDeviceHello::NewL(); |
|
451 CleanupStack::PushL( req ); |
|
452 |
|
453 // Multi-PKI addition |
|
454 CleanupResetAndDestroyPushL( idArray ); |
|
455 CreateDeviceIdHashArrayL( idArray ); |
|
456 for ( TInt i = 0; i < idArray.Count(); i++ ) |
|
457 { |
|
458 req->iDeviceIdArray.AppendL( *idArray[i] ); |
|
459 } |
|
460 CleanupStack::PopAndDestroy( &idArray ); |
|
461 // Multi-PKI |
|
462 |
|
463 #ifndef RD_DRM_METERING |
|
464 req->iVersion.Copy( KRoapVersion ); // Version 1.0 |
|
465 #else |
|
466 req->iVersion.Copy( KRoapVersion11 ); |
|
467 #endif |
|
468 if ( iTrigger->iNonce ) |
|
469 { |
|
470 req->iTriggerNonce = iTrigger->iNonce->AllocL(); |
|
471 } |
|
472 CmlaCrypto::SupportedAlgorithmsL( req->iAlgorithms ); |
|
473 iSelectedAlgorithms = EOma; |
|
474 |
|
475 CleanupStack::Pop( req ); |
|
476 return req; |
|
477 } |
|
478 |
|
479 // --------------------------------------------------------- |
|
480 // CRoapEng::CreateRegistrationRequestL() |
|
481 // --------------------------------------------------------- |
|
482 // |
|
483 CRoapMessage* CRoapEng::CreateRegistrationRequestL() |
|
484 { |
|
485 LOGLIT( "CRoapEng::CreateRegistrationRequestL ->" ) |
|
486 |
|
487 __ASSERT_ALWAYS( iResponse, User::Invariant() ); |
|
488 |
|
489 CRegistrationReq* req = NULL; |
|
490 CRIHello* resp = NULL; |
|
491 RPointerArray<HBufC8> trustedRootArray; |
|
492 HBufC8* temp = NULL; |
|
493 |
|
494 resp = STATIC_CAST( CRIHello*, iResponse ); |
|
495 req = CRegistrationReq::NewL(); |
|
496 CleanupStack::PushL( req ); |
|
497 if ( resp->iSession ) |
|
498 { |
|
499 req->iSession = resp->iSession->AllocL(); |
|
500 } |
|
501 else |
|
502 { |
|
503 User::Leave( KErrRoapServerFatal ); |
|
504 } |
|
505 |
|
506 req->iNonce.SetLength( KDeviceNonceLength ); |
|
507 TRandom::Random( req->iNonce ); |
|
508 |
|
509 req->iTime = GetDrmTimeL(); |
|
510 |
|
511 // store the nonce for DRM Time sync |
|
512 iRegReqNonce = req->iNonce; |
|
513 |
|
514 if ( iCertNeeded ) |
|
515 { |
|
516 req->iCertificateChain = GetCertificateChainL(); |
|
517 if ( resp->iCertificateCaching ) |
|
518 { |
|
519 iCertNeeded = EFalse; |
|
520 } |
|
521 } |
|
522 |
|
523 // Send all our trusted roots to the RI |
|
524 CleanupResetAndDestroyPushL( trustedRootArray ); |
|
525 |
|
526 LOGLIT( " Getting trusted roots" ) |
|
527 |
|
528 iStorageClient->GetTrustedRootsL( trustedRootArray ); |
|
529 |
|
530 if ( !trustedRootArray.Count() ) |
|
531 { |
|
532 // No trusted roots found! |
|
533 LOGLIT( " No trusted roots found!" ) |
|
534 User::Leave( KErrRoapDevice ); |
|
535 } |
|
536 for ( TInt i = 0; i < trustedRootArray.Count(); i++ ) |
|
537 { |
|
538 temp = trustedRootArray[i]->AllocLC(); |
|
539 req->iTrustedAuthorities.AppendL( temp ); |
|
540 CleanupStack::Pop( temp ); |
|
541 } |
|
542 |
|
543 LOGLIT( " Setting server info" ) |
|
544 if ( resp->iServerInfo && resp->iServerInfo->Size() ) |
|
545 { |
|
546 req->iServerInfo = resp->iServerInfo->AllocL(); |
|
547 } |
|
548 |
|
549 if ( iStoredRiContext ) |
|
550 { |
|
551 LOGLIT( " RI context available" ) |
|
552 req->iPeerKeyIdentifier = iStoredRiContext->RIID(); |
|
553 |
|
554 if ( iStoredRiContext->OCSPResponse().Count() && !iDeviceTimeError ) |
|
555 { |
|
556 req->iOcspInfoStored = ETrue; |
|
557 req->iOcspResponderKeyId = GetOCSPResponderKeyHashL(); |
|
558 } |
|
559 } |
|
560 if ( resp->iNeedDeviceDetails ) |
|
561 { |
|
562 LOGLIT( " Getting device details" ) |
|
563 GetDeviceDetailsL( req->iDeviceDetailsManufacturer, |
|
564 req->iDeviceDetailsModel, req->iDeviceDetailsVersion ); |
|
565 } |
|
566 |
|
567 if ( iTrigger->iNonce ) |
|
568 { |
|
569 req->iTriggerNonce = iTrigger->iNonce->AllocL(); |
|
570 } |
|
571 |
|
572 CleanupStack::PopAndDestroy( &trustedRootArray ); |
|
573 CleanupStack::Pop( req ); |
|
574 |
|
575 LOGLIT( "CRoapEng::CreateRegistrationRequestL <-" ) |
|
576 |
|
577 return req; |
|
578 } |
|
579 |
|
580 // --------------------------------------------------------- |
|
581 // CRoapEng::CreateRightsRequestL() |
|
582 // --------------------------------------------------------- |
|
583 // |
|
584 CRoapMessage* CRoapEng::CreateRightsRequestL() |
|
585 { |
|
586 LOGLIT( "CRoapEng::CreateRightsRequestL" ) |
|
587 PERFORMANCE_LOGLIT( "RO acquisition protocol started" ) |
|
588 |
|
589 __ASSERT_ALWAYS( iStoredRiContext, User::Invariant() ); |
|
590 |
|
591 CRightsReq* req = NULL; |
|
592 RPointerArray<HBufC8> ttIDs; |
|
593 RPointerArray<HBufC8> cids; |
|
594 HBufC8* temp = NULL; |
|
595 TBuf8<SHA1_HASH> deviceId; |
|
596 |
|
597 req = CRightsReq::NewL(); |
|
598 CleanupStack::PushL( req ); |
|
599 |
|
600 req->iNonce.SetLength( KDeviceNonceLength ); |
|
601 TRandom::Random( req->iNonce ); |
|
602 |
|
603 req->iTime = GetDrmTimeL(); |
|
604 |
|
605 iStorageClient->GetDevicePublicKeyHashL( deviceId ); |
|
606 delete iDeviceId; |
|
607 iDeviceId = NULL; |
|
608 iDeviceId = deviceId.AllocL(); |
|
609 req->iDeviceId = *iDeviceId; |
|
610 |
|
611 req->iRiId.Copy( iTrigger->iRiId ); |
|
612 |
|
613 if ( !iRiSupportsCertCaching ) |
|
614 { |
|
615 req->iCertificateChain = GetCertificateChainL(); |
|
616 } |
|
617 if ( iTrigger->iDomainId ) |
|
618 { |
|
619 req->iDomainId = iTrigger->iDomainId->AllocL(); |
|
620 } |
|
621 |
|
622 for ( TInt i = 0; i < iTrigger->iRoIdList.Count(); i++ ) |
|
623 { |
|
624 temp = iTrigger->iRoIdList[i]->AllocLC(); |
|
625 req->iRoIdList.AppendL( temp ); |
|
626 CleanupStack::Pop( temp ); |
|
627 } |
|
628 |
|
629 if ( iStoredRiContext ) |
|
630 { |
|
631 req->iPeerKeyIdentifier = iStoredRiContext->RIID(); |
|
632 |
|
633 if ( iStoredRiContext->OCSPResponse().Count() ) |
|
634 { |
|
635 req->iOcspInfoStored = ETrue; |
|
636 req->iOcspResponderKeyId = GetOCSPResponderKeyHashL(); |
|
637 } |
|
638 } |
|
639 |
|
640 CleanupResetAndDestroyPushL( cids ); |
|
641 |
|
642 CleanupResetAndDestroyPushL( ttIDs ); |
|
643 |
|
644 FetchTransactionIDL( ttIDs, cids ); |
|
645 |
|
646 for ( TInt i = 0; i < ttIDs.Count() && i < cids.Count(); i++ ) |
|
647 { |
|
648 temp = ttIDs[i]->AllocLC(); |
|
649 req->iTransTrackIDs.AppendL( temp ); |
|
650 CleanupStack::Pop( temp ); |
|
651 temp = cids[i]->AllocLC(); |
|
652 req->iContentIDs.AppendL( temp ); |
|
653 CleanupStack::Pop( temp ); |
|
654 } |
|
655 |
|
656 CleanupStack::PopAndDestroy( &ttIDs ); |
|
657 CleanupStack::PopAndDestroy( &cids ); |
|
658 |
|
659 if ( iTrigger->iNonce ) |
|
660 { |
|
661 req->iTriggerNonce = iTrigger->iNonce->AllocL(); |
|
662 } |
|
663 |
|
664 CleanupStack::Pop( req ); |
|
665 return req; |
|
666 } |
|
667 |
|
668 // --------------------------------------------------------- |
|
669 // CRoapEng::CreateJoinDomainRequestL() |
|
670 // --------------------------------------------------------- |
|
671 // |
|
672 CRoapMessage* CRoapEng::CreateJoinDomainRequestL() |
|
673 { |
|
674 LOGLIT( "CRoapEng::CreateJoinDomainRequestL" ) |
|
675 PERFORMANCE_LOGLIT( "Join domain protocol started" ) |
|
676 |
|
677 __ASSERT_ALWAYS( iStoredRiContext, User::Invariant() ); |
|
678 |
|
679 CJoinDomainReq* req = NULL; |
|
680 TBuf8<SHA1_HASH> deviceId; |
|
681 |
|
682 req = CJoinDomainReq::NewL(); |
|
683 CleanupStack::PushL( req ); |
|
684 |
|
685 req->iNonce.SetLength( KDeviceNonceLength ); |
|
686 TRandom::Random( req->iNonce ); |
|
687 |
|
688 req->iTime = GetDrmTimeL(); |
|
689 |
|
690 iStorageClient->GetDevicePublicKeyHashL( deviceId ); |
|
691 delete iDeviceId; |
|
692 iDeviceId = NULL; |
|
693 iDeviceId = deviceId.AllocL(); |
|
694 req->iDeviceId = *iDeviceId; |
|
695 |
|
696 req->iRiId.Copy( iTrigger->iRiId ); |
|
697 |
|
698 if ( !iRiSupportsCertCaching ) |
|
699 { |
|
700 req->iCertificateChain = GetCertificateChainL(); |
|
701 } |
|
702 if ( iTrigger->iDomainId ) |
|
703 { |
|
704 req->iDomainId = iTrigger->iDomainId->AllocL(); |
|
705 iDomainId.Copy( *req->iDomainId ); |
|
706 } |
|
707 else if ( iDomainId.Length() && iTrigger->iTriggerType |
|
708 == ERoAcquisitionTrigger ) |
|
709 { |
|
710 req->iDomainId = iDomainId.AllocL(); |
|
711 } |
|
712 else |
|
713 { |
|
714 User::Leave( KErrRoapServerFatal ); |
|
715 } |
|
716 |
|
717 if ( iStoredRiContext ) |
|
718 { |
|
719 req->iPeerKeyIdentifier = iStoredRiContext->RIID(); |
|
720 |
|
721 if ( iStoredRiContext->OCSPResponse().Count() ) |
|
722 { |
|
723 req->iOcspInfoStored = ETrue; |
|
724 req->iOcspResponderKeyId = GetOCSPResponderKeyHashL(); |
|
725 } |
|
726 } |
|
727 |
|
728 #ifdef _DISABLE_HASH_CHAIN_GENERATION |
|
729 req->iHashChainSupport = EFalse; |
|
730 #endif |
|
731 |
|
732 if ( iTrigger->iNonce ) |
|
733 { |
|
734 req->iTriggerNonce = iTrigger->iNonce->AllocL(); |
|
735 } |
|
736 |
|
737 CleanupStack::Pop( req ); |
|
738 return req; |
|
739 } |
|
740 |
|
741 // --------------------------------------------------------- |
|
742 // CRoapEng::CreateLeaveDomainRequestL() |
|
743 // --------------------------------------------------------- |
|
744 // |
|
745 CRoapMessage* CRoapEng::CreateLeaveDomainRequestL() |
|
746 { |
|
747 LOGLIT( "CRoapEng::CreateLeaveDomainRequestL" ) |
|
748 PERFORMANCE_LOGLIT( "Leave domain protocol started" ) |
|
749 |
|
750 __ASSERT_ALWAYS( iStoredRiContext, User::Invariant() ); |
|
751 |
|
752 if ( !iTrigger->iDomainId ) |
|
753 { |
|
754 User::Leave( KErrRoapServerFatal ); |
|
755 } |
|
756 // delete Domain context before sending LeaveDomain req |
|
757 TRAPD( ret, iStorageClient->DeleteDomainContextL( *iTrigger->iDomainId )); |
|
758 |
|
759 CLeaveDomainReq* req = NULL; |
|
760 TBuf8<SHA1_HASH> deviceId; |
|
761 |
|
762 req = CLeaveDomainReq::NewL(); |
|
763 CleanupStack::PushL( req ); |
|
764 |
|
765 if ( ret == KErrNotFound ) |
|
766 { |
|
767 req->iNotMember = ETrue; |
|
768 } |
|
769 else |
|
770 { |
|
771 req->iNotMember = EFalse; |
|
772 User::LeaveIfError( ret ); |
|
773 } |
|
774 |
|
775 req->iNonce.SetLength( KDeviceNonceLength ); |
|
776 TRandom::Random( req->iNonce ); |
|
777 |
|
778 req->iTime = GetDrmTimeL(); |
|
779 |
|
780 iStorageClient->GetDevicePublicKeyHashL( deviceId ); |
|
781 delete iDeviceId; |
|
782 iDeviceId = NULL; |
|
783 iDeviceId = deviceId.AllocL(); |
|
784 req->iDeviceId = *iDeviceId; |
|
785 |
|
786 req->iRiId.Copy( iTrigger->iRiId ); |
|
787 |
|
788 if ( !iRiSupportsCertCaching ) |
|
789 { |
|
790 req->iCertificateChain = GetCertificateChainL(); |
|
791 } |
|
792 if ( iTrigger->iDomainId ) |
|
793 { |
|
794 req->iDomainId = iTrigger->iDomainId->AllocL(); |
|
795 } |
|
796 |
|
797 if ( iTrigger->iNonce ) |
|
798 { |
|
799 req->iTriggerNonce = iTrigger->iNonce->AllocL(); |
|
800 } |
|
801 |
|
802 CleanupStack::Pop( req ); |
|
803 return req; |
|
804 } |
|
805 // --------------------------------------------------------- |
|
806 // CRoapEng::CreateMeteringReportRequestL() |
|
807 // --------------------------------------------------------- |
|
808 // |
|
809 CRoapMessage* CRoapEng::CreateMeteringReportRequestL() |
|
810 { |
|
811 #ifndef RD_DRM_METERING |
|
812 return NULL; |
|
813 #else |
|
814 |
|
815 LOGLIT( "CRoapEng::CreateMeteringReportRequestL" ) |
|
816 PERFORMANCE_LOGLIT( "Metering report creation started" ) |
|
817 |
|
818 CMeteringReportReq* req = NULL; |
|
819 TBuf8<SHA1_HASH> deviceId; |
|
820 TBuf8<OmaCrypto::KMacSize> macKey; |
|
821 TBool registered( EFalse ); |
|
822 |
|
823 req = CMeteringReportReq::NewL(); |
|
824 CleanupStack::PushL( req ); |
|
825 req->iAlgorithmInUse = iSelectedAlgorithms; |
|
826 // check if we are not using OMA algorithms |
|
827 // and update selected algorithm accordingly |
|
828 GetRIContextL( registered, iTrigger->iRiId ); |
|
829 if ( registered && iStoredRiContext ) |
|
830 { |
|
831 for ( TInt i = 0; i < iStoredRiContext->Algorithms().Count(); i++ ) |
|
832 { |
|
833 if ( iStoredRiContext->Algorithms()[i]->CompareF( KCmlaIp1() ) |
|
834 == KErrNone ) |
|
835 { |
|
836 // note currently assumed that only |
|
837 // 1 of 7 ppossible algorithms used |
|
838 req->iAlgorithmInUse = ECmlaIp1; |
|
839 break; |
|
840 } |
|
841 } |
|
842 } |
|
843 |
|
844 // generate DeviceNonce |
|
845 req->iNonce.SetLength( KDeviceNonceLength ); |
|
846 TRandom::Random( req->iNonce ); |
|
847 |
|
848 // generate MeteringNonce |
|
849 req->iReportNonce.SetLength( KDeviceNonceLength ); |
|
850 TRandom::Random( req->iReportNonce ); |
|
851 |
|
852 // fetch secure time for request |
|
853 req->iTime = GetDrmTimeL(); |
|
854 |
|
855 // insert DeviceId |
|
856 iStorageClient->GetDevicePublicKeyHashL( deviceId ); |
|
857 delete iDeviceId; |
|
858 iDeviceId = NULL; |
|
859 iDeviceId = deviceId.AllocL(); |
|
860 req->iDeviceId = *iDeviceId; |
|
861 |
|
862 // insert RiId |
|
863 req->iRiId.Copy( iTrigger->iRiId ); |
|
864 |
|
865 // insert Certificate chain if needed |
|
866 if ( !iRiSupportsCertCaching ) |
|
867 { |
|
868 req->iCertificateChain = GetCertificateChainL(); |
|
869 } |
|
870 |
|
871 // add trigger Nonce |
|
872 if ( iTrigger->iNonce ) |
|
873 { |
|
874 req->iTriggerNonce = iTrigger->iNonce->AllocL(); |
|
875 } |
|
876 |
|
877 // Get from server encrypted metering report mac key as plain, |
|
878 // MEK and MAC key as encypted, and hash of |
|
879 // PKI public key used in encryition |
|
880 req->iCipherValue = iStorageClient->GetMeteringDataL( req->iRiId, macKey, |
|
881 req->iEncKeyHash, req->iEncryptedMekAndMak ); |
|
882 |
|
883 // calculate mac over <encryptedMeteringReport> |
|
884 req->InsertMacL( macKey ); |
|
885 |
|
886 CleanupStack::Pop( req ); |
|
887 return req; |
|
888 |
|
889 #endif //RD_DRM_METERING |
|
890 } |
|
891 |
|
892 // --------------------------------------------------------- |
|
893 // CRoapEng::HandleRoapResponseL() |
|
894 // --------------------------------------------------------- |
|
895 // |
|
896 void CRoapEng::HandleRoapResponseL( const TDesC8& aXmlResponse ) |
|
897 { |
|
898 LOGLIT( "CRoapEng::HandleRoapMessageL" ) |
|
899 |
|
900 delete iResponse; |
|
901 iResponse = NULL; |
|
902 |
|
903 switch ( iReqMessage ) |
|
904 { |
|
905 case EDeviceHello: |
|
906 { |
|
907 HandleRIHelloPduL( aXmlResponse ); |
|
908 break; |
|
909 } |
|
910 case ERegistration: |
|
911 { |
|
912 HandleReqResponsePduL( aXmlResponse ); |
|
913 break; |
|
914 } |
|
915 case EROAcquisition: |
|
916 { |
|
917 HandleRightsResponsePduL( aXmlResponse, EFalse ); |
|
918 break; |
|
919 } |
|
920 case EJoinDomain: |
|
921 { |
|
922 HandleJoinDomainResponsePduL( aXmlResponse ); |
|
923 break; |
|
924 } |
|
925 case ELeaveDomain: |
|
926 { |
|
927 HandleLeaveDomainResponsePduL( aXmlResponse ); |
|
928 break; |
|
929 } |
|
930 #ifdef RD_DRM_METERING |
|
931 case EMeteringRequest: |
|
932 { |
|
933 HandleMeteringReportResponsePduL( aXmlResponse ); |
|
934 break; |
|
935 } |
|
936 #endif |
|
937 default: |
|
938 { |
|
939 User::Leave( KErrArgument ); |
|
940 } |
|
941 } |
|
942 } |
|
943 |
|
944 // --------------------------------------------------------- |
|
945 // CRoapEng::HandleRIHelloPduL() |
|
946 // --------------------------------------------------------- |
|
947 // |
|
948 void CRoapEng::HandleRIHelloPduL( const TDesC8& aRiHello ) |
|
949 { |
|
950 LOGLIT( "CRoapEng::HandleRIHelloPduL" ) |
|
951 |
|
952 CRIHello* resp = NULL; |
|
953 HBufC8* temp = NULL; |
|
954 |
|
955 resp = iParser->ParseRIHelloL( aRiHello ); |
|
956 iRoapStatus = resp->iStatus; |
|
957 iResponse = resp; |
|
958 if ( iRoapStatus == ESuccess ) |
|
959 { |
|
960 iCertNeeded = ETrue; |
|
961 iRiSupportsCertCaching = EFalse; |
|
962 |
|
963 if ( resp->iPeerKeyIdentifier ) |
|
964 { |
|
965 iRiSupportsCertCaching = ETrue; |
|
966 if ( resp->iPeerKeyId.Length() ) |
|
967 { |
|
968 if ( resp->iPeerKeyId.CompareF( *iDeviceId ) == KErrNone ) |
|
969 { |
|
970 iCertNeeded = EFalse; |
|
971 } |
|
972 } |
|
973 else |
|
974 { |
|
975 iCertNeeded = EFalse; |
|
976 } |
|
977 } |
|
978 else if ( resp->iCertificateCaching ) |
|
979 { |
|
980 iRiSupportsCertCaching = ETrue; |
|
981 } |
|
982 |
|
983 if ( resp->iAlgorithms.Count() ) |
|
984 { |
|
985 iRiAlgorithms.ResetAndDestroy(); |
|
986 for ( TInt i = 0; i < resp->iAlgorithms.Count(); i++ ) |
|
987 { |
|
988 if ( resp->iAlgorithms[i]->CompareF( KCmlaIp1() ) == KErrNone ) |
|
989 { |
|
990 iSelectedAlgorithms = ECmlaIp1; |
|
991 } |
|
992 temp = resp->iAlgorithms[i]->AllocLC(); |
|
993 iRiAlgorithms.AppendL( temp ); |
|
994 CleanupStack::Pop( temp ); |
|
995 } |
|
996 } |
|
997 iRiId.Copy( resp->iRiId ); |
|
998 iRiVersion.Copy( resp->iSelectedVersion ); |
|
999 |
|
1000 /*** |
|
1001 This is needed when the multiple PKIs are supported. |
|
1002 ***/ |
|
1003 if ( resp->iTrustedAuthorities.Count() ) |
|
1004 { |
|
1005 // select the first matching root from the list |
|
1006 LOGLIT( "Choose the first matching trust anchor" ) |
|
1007 iStorageClient->SelectTrustedRootL( resp->iTrustedAuthorities, |
|
1008 iSelectedRoot ); |
|
1009 LOGLIT( "The trust anchor selected" ) |
|
1010 DETAILLOGHEX( iSelectedRoot.Ptr(), iSelectedRoot.Length() ) |
|
1011 } |
|
1012 else |
|
1013 { |
|
1014 if ( iStoredRiContext && iStoredRiContext->RIID() == iRiId ) |
|
1015 { |
|
1016 if ( iSelectedRoot != iStoredRiContext->SelectedDeviceRoot() ) |
|
1017 { |
|
1018 DETAILLOGLIT( "Changing trusted root to that of saved RI context" ) |
|
1019 DETAILLOGLIT( "old root" ) |
|
1020 DETAILLOGHEX( iSelectedRoot.Ptr(), iSelectedRoot.Length() ) |
|
1021 |
|
1022 iSelectedRoot = iStoredRiContext->SelectedDeviceRoot(); |
|
1023 iStorageClient->SelectTrustedRootL( iSelectedRoot ); |
|
1024 } |
|
1025 DETAILLOGLIT( "Using trusted root of saved RI context" ) |
|
1026 DETAILLOGHEX( iSelectedRoot.Ptr(), iSelectedRoot.Length() ) |
|
1027 } |
|
1028 else |
|
1029 { |
|
1030 DETAILLOGLIT( "Using default trusted root" ) |
|
1031 iSelectedRoot = KNullDesC8; |
|
1032 iStorageClient->SelectTrustedRootL( iSelectedRoot ); |
|
1033 } |
|
1034 } |
|
1035 |
|
1036 iSigner->AddRequestL( aRiHello ); |
|
1037 } |
|
1038 else if ( resp->iErrorUrl ) |
|
1039 { |
|
1040 if ( iObserver ) |
|
1041 { |
|
1042 iObserver->ErrorUrlL( *resp->iErrorUrl ); |
|
1043 } |
|
1044 } |
|
1045 } |
|
1046 |
|
1047 // --------------------------------------------------------- |
|
1048 // CRoapEng::HandleReqResponsePduL() |
|
1049 // --------------------------------------------------------- |
|
1050 // |
|
1051 void CRoapEng::HandleReqResponsePduL( const TDesC8& aRegResp ) |
|
1052 { |
|
1053 LOGLIT( "CRoapEng::HandleReqResponsePduL" ) |
|
1054 |
|
1055 CRegistrationResp* resp = NULL; |
|
1056 CDRMRIContext* context = NULL; |
|
1057 CX509Certificate* cert = NULL; |
|
1058 TTime riExpiry; |
|
1059 TBool status = EFalse; |
|
1060 TUint8 riCertCaching = EFalse; |
|
1061 |
|
1062 resp = iParser->ParseRegistrationRespL( aRegResp ); |
|
1063 iRoapStatus = resp->iStatus; |
|
1064 iResponse = resp; |
|
1065 if ( iRoapStatus == ESuccess ) |
|
1066 { |
|
1067 if ( resp->iOcspResponse.Count() > 0 ) |
|
1068 { |
|
1069 // adjust DRM Time according to OCSP response |
|
1070 // All needed verifications done in server side |
|
1071 TBool deviceTimeUpdated( EFalse ); |
|
1072 if ( resp->iCertificateChain.Count() > 0 ) |
|
1073 { |
|
1074 deviceTimeUpdated = iStorageClient->UpdateDrmTimeL( |
|
1075 resp->iCertificateChain, resp->iOcspResponse, |
|
1076 iRegReqNonce ); |
|
1077 } |
|
1078 else if ( iStoredRiContext ) |
|
1079 { |
|
1080 deviceTimeUpdated = iStorageClient->UpdateDrmTimeL( |
|
1081 iStoredRiContext->CertificateChain(), |
|
1082 resp->iOcspResponse, iRegReqNonce ); |
|
1083 } |
|
1084 if ( deviceTimeUpdated ) |
|
1085 { |
|
1086 LOGLIT( "drm time updated" ) |
|
1087 iDeviceTimeError = EFalse; |
|
1088 } |
|
1089 } |
|
1090 |
|
1091 if ( !iStoredRiContext || ( resp->iCertificateChain.Count() |
|
1092 && resp->iOcspResponse.Count() ) ) |
|
1093 { |
|
1094 status = VerifyCertificateChainL( resp->iCertificateChain, |
|
1095 resp->iOcspResponse ); |
|
1096 if ( !status ) |
|
1097 { |
|
1098 LOGLIT( "Certificate chain validation failed" ) |
|
1099 User::Leave( KErrRoapServerFatal ); |
|
1100 } |
|
1101 status = ValidateRiIdL( iRiId, *resp->iCertificateChain[0] ); |
|
1102 if ( !status ) |
|
1103 { |
|
1104 LOGLIT( "RI ID validation failed" ) |
|
1105 User::Leave( KErrRoapServerFatal ); |
|
1106 } |
|
1107 } |
|
1108 |
|
1109 if ( iStoredRiContext ) |
|
1110 { |
|
1111 // if we have already stored certificates -> use those. |
|
1112 status = VerifySignatureL( aRegResp, *resp->iSignature, |
|
1113 iStoredRiContext->CertificateChain() ); |
|
1114 } |
|
1115 else |
|
1116 { |
|
1117 // otherwise use the received certificates |
|
1118 status = VerifySignatureL( aRegResp, *resp->iSignature, |
|
1119 resp->iCertificateChain ); |
|
1120 } |
|
1121 |
|
1122 if ( !status ) |
|
1123 { |
|
1124 LOGLIT( "Signature verification failed" ) |
|
1125 User::Leave( KErrRoapServerFatal ); |
|
1126 } |
|
1127 |
|
1128 if ( resp->iCertificateChain.Count() ) |
|
1129 { |
|
1130 // Validate RI certificate |
|
1131 cert = CX509Certificate::NewLC( *resp->iCertificateChain[0] ); |
|
1132 |
|
1133 status = ValidateRiCertificateL( cert ); |
|
1134 if ( !status ) |
|
1135 { |
|
1136 User::LeaveIfError( KErrRoapServerFatal ); |
|
1137 } |
|
1138 |
|
1139 riExpiry = cert->ValidityPeriod().Finish(); |
|
1140 |
|
1141 iRiSupportsCertCaching ? riCertCaching = ETrue : riCertCaching |
|
1142 = EFalse; |
|
1143 |
|
1144 context = CDRMRIContext::NewLC( iRiId, *iRiAlias, iRiVersion, |
|
1145 iRiAlgorithms, resp->iWhiteList, *resp->iRiUrl, riExpiry, |
|
1146 resp->iCertificateChain, resp->iOcspResponse, riCertCaching, |
|
1147 iSelectedRoot, ETrue ); |
|
1148 |
|
1149 iStorageClient->AddRIContextL( *context ); |
|
1150 delete iStoredRiContext; |
|
1151 iStoredRiContext = context; |
|
1152 CleanupStack::Pop( context ); |
|
1153 CleanupStack::PopAndDestroy( cert ); |
|
1154 } |
|
1155 } |
|
1156 else |
|
1157 { |
|
1158 if ( resp->iErrorUrl ) |
|
1159 { |
|
1160 if ( iObserver ) |
|
1161 { |
|
1162 iObserver->ErrorUrlL( *resp->iErrorUrl ); |
|
1163 } |
|
1164 } |
|
1165 iSigner->ResetResponses(); |
|
1166 } |
|
1167 |
|
1168 PERFORMANCE_LOGLIT( "Registration protocol completed" ) |
|
1169 } |
|
1170 |
|
1171 // --------------------------------------------------------- |
|
1172 // CRoapEng::HandleRightsResponseL() |
|
1173 // --------------------------------------------------------- |
|
1174 // |
|
1175 void CRoapEng::HandleRightsResponsePduL( |
|
1176 const TDesC8& aRightsResp, |
|
1177 TBool aOnePass ) |
|
1178 { |
|
1179 LOGLIT( "CRoapEng::HandleRightsResponsePduL" ) |
|
1180 |
|
1181 CRightsResp* resp = NULL; |
|
1182 TBool status = EFalse; |
|
1183 |
|
1184 resp = iParser->ParseRightsRespL( aRightsResp ); |
|
1185 |
|
1186 CleanupStack::PushL( resp ); |
|
1187 |
|
1188 if ( resp->iStatus == ESuccess ) |
|
1189 { |
|
1190 if ( !aOnePass ) |
|
1191 { |
|
1192 // 2-pass protocol |
|
1193 __ASSERT_ALWAYS( iStoredRiContext, User::Invariant() ); |
|
1194 |
|
1195 CRightsReq* request = NULL; |
|
1196 request = STATIC_CAST( CRightsReq*, iRequest ); |
|
1197 if ( resp->iDeviceId.CompareF( request->iDeviceId ) != KErrNone |
|
1198 || resp->iRiId.CompareF( request->iRiId ) != KErrNone |
|
1199 || resp->iNonce->CompareF( request->iNonce ) != KErrNone ) |
|
1200 { |
|
1201 User::Leave( KErrRoapServerFatal ); |
|
1202 } |
|
1203 } |
|
1204 else |
|
1205 { |
|
1206 LOGLIT( "1-pass ROAP" ) |
|
1207 // 1-pass protocol |
|
1208 TBool registered = EFalse; |
|
1209 GetRIContextL( registered, resp->iRiId ); |
|
1210 if ( !registered ) |
|
1211 { |
|
1212 // Recoverable error by re-registering the device |
|
1213 // (after receiving user consent or iv device belongs to whiteliust) |
|
1214 LOGLIT( "Device not registered to RI" ) |
|
1215 User::Leave( KErrRoapNotRegistered ); |
|
1216 } |
|
1217 if ( resp->iDeviceId.CompareF( *iDeviceId ) != KErrNone ) |
|
1218 { |
|
1219 // Unrecoverable error |
|
1220 LOGLIT( "Device ID mismatch!" ) |
|
1221 User::Leave( KErrRoapServerFatal ); |
|
1222 } |
|
1223 } |
|
1224 |
|
1225 if ( !iStoredRiContext || ( resp->iCertificateChain.Count() |
|
1226 && resp->iOcspResponse.Count() ) ) |
|
1227 { |
|
1228 status = VerifyCertificateChainL( resp->iCertificateChain, |
|
1229 resp->iOcspResponse ); |
|
1230 if ( !status ) |
|
1231 { |
|
1232 LOGLIT( "Certificate chain validation failed" ) |
|
1233 User::Leave( KErrRoapServerFatal ); |
|
1234 } |
|
1235 status = ValidateRiIdL( resp->iRiId, *resp->iCertificateChain[0] ); |
|
1236 if ( !status ) |
|
1237 { |
|
1238 LOGLIT( "RI ID validation failed" ) |
|
1239 User::Leave( KErrRoapServerFatal ); |
|
1240 } |
|
1241 } |
|
1242 |
|
1243 status = VerifySignatureL( aRightsResp, *resp->iSignature, |
|
1244 iStoredRiContext->CertificateChain() ); |
|
1245 if ( !status ) |
|
1246 { |
|
1247 LOGLIT( "Signature verification failed" ) |
|
1248 User::Leave( KErrRoapServerFatal ); |
|
1249 } |
|
1250 |
|
1251 iReturnedROs.ResetAndDestroy(); |
|
1252 TRAPD( r, iRoParser->ParseAndStoreL( aRightsResp, iReturnedROs )); |
|
1253 |
|
1254 if ( r == KErrRightsServerDomainNotRegistered ) |
|
1255 { |
|
1256 // perform implicit Join Domain |
|
1257 LOGLIT( "Domain RO received - Not joined" ) |
|
1258 LOGLIT( "Perform impicit Join Domain before storing the RO" ) |
|
1259 |
|
1260 HBufC8* domainID = NULL; |
|
1261 |
|
1262 domainID = iRoParser->GetDomainIdL( aRightsResp ); |
|
1263 |
|
1264 if ( domainID && domainID->Length() <= KDomainIdLength ) |
|
1265 { |
|
1266 iDomainId.Copy( *domainID ); |
|
1267 delete domainID; |
|
1268 domainID = NULL; |
|
1269 } |
|
1270 else |
|
1271 { |
|
1272 LOGLIT( "No Domain ID available!" ) |
|
1273 User::Leave( KErrRoapServerFatal ); |
|
1274 } |
|
1275 |
|
1276 delete iDomainRightsResp; |
|
1277 iDomainRightsResp = NULL; |
|
1278 iDomainRightsResp = aRightsResp.AllocL(); |
|
1279 iImplicitJoinDomain = ETrue; |
|
1280 } |
|
1281 else |
|
1282 { |
|
1283 User::LeaveIfError( r ); |
|
1284 |
|
1285 if ( !aOnePass ) |
|
1286 { |
|
1287 if ( iObserver ) |
|
1288 { |
|
1289 iObserver->RightsObjectDetailsL( iReturnedROs ); // pass RO details to UI |
|
1290 } |
|
1291 } |
|
1292 } |
|
1293 |
|
1294 TRAP( r, InsertTransactionIDL( resp->iTransTrackIDs, resp->iContentIDs ) ); |
|
1295 TRAP( r, InsertDomainRosL() ); |
|
1296 |
|
1297 // Device DRM Time is insecure, but server thinks that the time is correct |
|
1298 // -> Set DRM Time as secure |
|
1299 if ( !iSecureTime ) |
|
1300 { |
|
1301 SetDrmTimeSecureL(); |
|
1302 } |
|
1303 } |
|
1304 else |
|
1305 { |
|
1306 if ( resp->iErrorUrl ) |
|
1307 { |
|
1308 if ( iObserver ) |
|
1309 { |
|
1310 iObserver->ErrorUrlL( *resp->iErrorUrl ); |
|
1311 } |
|
1312 } |
|
1313 iSigner->ResetResponses(); |
|
1314 } |
|
1315 |
|
1316 CleanupStack::Pop( resp ); |
|
1317 |
|
1318 if ( !aOnePass ) |
|
1319 { |
|
1320 iRoapStatus = resp->iStatus; |
|
1321 iResponse = resp; |
|
1322 } |
|
1323 |
|
1324 PERFORMANCE_LOGLIT( "RO acquisition protocol completed" ) |
|
1325 } |
|
1326 |
|
1327 // --------------------------------------------------------- |
|
1328 // CRoapEng::HandleJoinDomainResponseL() |
|
1329 // --------------------------------------------------------- |
|
1330 // |
|
1331 void CRoapEng::HandleJoinDomainResponsePduL( const TDesC8& aJoinResp ) |
|
1332 { |
|
1333 LOGLIT( "CRoapEng::HandleJoinDomainResponsePduL" ) |
|
1334 |
|
1335 __ASSERT_ALWAYS( iStoredRiContext, User::Invariant() ); |
|
1336 |
|
1337 CJoinDomainResp* resp = NULL; |
|
1338 CDRMDomainContext* context = NULL; |
|
1339 RPointerArray<HBufC8> domainKeyElements; |
|
1340 TBool status = EFalse; |
|
1341 |
|
1342 CleanupResetAndDestroyPushL( domainKeyElements ); |
|
1343 |
|
1344 resp = iParser->ParseJoinDomainRespL( aJoinResp, domainKeyElements ); |
|
1345 |
|
1346 iResponse = resp; |
|
1347 iRoapStatus = resp->iStatus; |
|
1348 |
|
1349 if ( iRoapStatus == ESuccess ) |
|
1350 { |
|
1351 if ( resp->iDomainKeyRiId != resp->iRiId ) |
|
1352 { |
|
1353 LOGLIT( "resp->iDomainKeyRiId != resp->iRiId" ) |
|
1354 User::Leave( KErrRoapServerFatal ); |
|
1355 } |
|
1356 |
|
1357 if ( !iStoredRiContext || ( resp->iCertificateChain.Count() |
|
1358 && resp->iOcspResponse.Count() ) ) |
|
1359 { |
|
1360 status = VerifyCertificateChainL( resp->iCertificateChain, |
|
1361 resp->iOcspResponse ); |
|
1362 if ( !status ) |
|
1363 { |
|
1364 LOGLIT( "Certificate chain validation failed" ) |
|
1365 User::Leave( KErrRoapServerFatal ); |
|
1366 } |
|
1367 status = ValidateRiIdL( resp->iRiId, *resp->iCertificateChain[0] ); |
|
1368 if ( !status ) |
|
1369 { |
|
1370 LOGLIT( "RI ID validation failed" ) |
|
1371 User::Leave( KErrRoapServerFatal ); |
|
1372 } |
|
1373 } |
|
1374 |
|
1375 status = VerifySignatureL( aJoinResp, *resp->iSignature, |
|
1376 iStoredRiContext->CertificateChain() ); |
|
1377 if ( !status ) |
|
1378 { |
|
1379 LOGLIT( "Signature verification failed" ) |
|
1380 User::Leave( KErrRoapServerFatal ); |
|
1381 } |
|
1382 |
|
1383 if ( resp->iDomainKeys.Count() > 1 && resp->iDomainKeyIDs.Count() > 1 |
|
1384 && resp->iDomainKeys.Count() == resp->iDomainKeyIDs.Count() ) |
|
1385 { |
|
1386 // Sort domain keys by generation (000 generation is first) |
|
1387 TLex8 lex; |
|
1388 TInt generation = 0; |
|
1389 RArray<TInt> generations; |
|
1390 CleanupClosePushL( generations ); |
|
1391 |
|
1392 for ( TInt i = 0; i < resp->iDomainKeyIDs.Count(); i++ ) |
|
1393 { |
|
1394 lex = resp->iDomainKeyIDs[i]->Right( KDomainGenerationLength ); |
|
1395 lex.Val( generation ); |
|
1396 generations.AppendL( generation ); |
|
1397 } |
|
1398 |
|
1399 SortArrays( resp->iDomainKeys, resp->iMacs, domainKeyElements, |
|
1400 generations ); |
|
1401 |
|
1402 CleanupStack::PopAndDestroy( &generations ); |
|
1403 } |
|
1404 |
|
1405 if ( !resp->iDomainKeys.Count() ) |
|
1406 { |
|
1407 LOGLIT( "No valid domain keys present!" ) |
|
1408 User::Leave( KErrRoapServerFatal ); |
|
1409 } |
|
1410 |
|
1411 #ifdef _DISABLE_HASH_CHAIN_GENERATION |
|
1412 resp->iHashChainSupport = EFalse; |
|
1413 #endif |
|
1414 |
|
1415 if ( resp->iHashChainSupport ) |
|
1416 { |
|
1417 if ( resp->iDomainKeys.Count() > 1 ) |
|
1418 { |
|
1419 LOGLIT( "More than one Domain key present, hash chain key generation is supported!" ) |
|
1420 // Might be KErrRoapServerFatal server error |
|
1421 } |
|
1422 } |
|
1423 |
|
1424 context = CDRMDomainContext::NewLC( iDomainId, |
|
1425 resp->iDomainExpiration, resp->iHashChainSupport, |
|
1426 resp->iDomainKeys, resp->iRiId, |
|
1427 iStoredRiContext->RightsIssuerURL() ); |
|
1428 iStorageClient->AddDomainContextL( *context, resp->iMacs, |
|
1429 domainKeyElements, resp->iTransportScheme ); |
|
1430 iDomainId.SetLength( 0 ); |
|
1431 CleanupStack::PopAndDestroy( context ); |
|
1432 |
|
1433 if ( iDomainRightsResp ) |
|
1434 { |
|
1435 // It's a implicit Join Domain case |
|
1436 // We still need to store the domain RO |
|
1437 StoreDomainRightsL(); |
|
1438 } |
|
1439 |
|
1440 // Device DRM Time is insecure, but server thinks that the time is correct |
|
1441 // -> Set DRM Time as secure |
|
1442 if ( !iSecureTime ) |
|
1443 { |
|
1444 SetDrmTimeSecureL(); |
|
1445 } |
|
1446 } |
|
1447 else |
|
1448 { |
|
1449 if ( resp->iErrorUrl ) |
|
1450 { |
|
1451 if ( iObserver ) |
|
1452 { |
|
1453 iObserver->ErrorUrlL( *resp->iErrorUrl ); |
|
1454 } |
|
1455 } |
|
1456 iSigner->ResetResponses(); |
|
1457 } |
|
1458 CleanupStack::PopAndDestroy( &domainKeyElements ); |
|
1459 } |
|
1460 |
|
1461 // --------------------------------------------------------- |
|
1462 // CRoapEng::HandleLeaveDomainResponseL() |
|
1463 // --------------------------------------------------------- |
|
1464 // |
|
1465 void CRoapEng::HandleLeaveDomainResponsePduL( const TDesC8& aLeaveResp ) |
|
1466 { |
|
1467 LOGLIT( "CRoapEng::HandleLeaveDomainResponsePduL" ) |
|
1468 |
|
1469 __ASSERT_ALWAYS( iStoredRiContext, User::Invariant() ); |
|
1470 |
|
1471 CLeaveDomainResp* resp = NULL; |
|
1472 resp = iParser->ParseLeaveDomainRespL( aLeaveResp ); |
|
1473 iRoapStatus = resp->iStatus; |
|
1474 iResponse = resp; |
|
1475 if ( iRoapStatus == ESuccess ) |
|
1476 { |
|
1477 |
|
1478 } |
|
1479 else if ( resp->iErrorUrl ) |
|
1480 { |
|
1481 if ( iObserver ) |
|
1482 { |
|
1483 iObserver->ErrorUrlL( *resp->iErrorUrl ); |
|
1484 } |
|
1485 } |
|
1486 |
|
1487 PERFORMANCE_LOGLIT( "Leave domain protocol completed" ) |
|
1488 } |
|
1489 |
|
1490 // --------------------------------------------------------- |
|
1491 // CRoapEng::HandleMeteringReportResponsePduL() |
|
1492 // --------------------------------------------------------- |
|
1493 // |
|
1494 #ifndef RD_DRM_METERING |
|
1495 void CRoapEng::HandleMeteringReportResponsePduL( const TDesC8& /*aMeteringResp*/) |
|
1496 { |
|
1497 } |
|
1498 #else |
|
1499 void CRoapEng::HandleMeteringReportResponsePduL( const TDesC8& aMeteringResp ) |
|
1500 { |
|
1501 LOGLIT( "CRoapEng::HandleMeteringReportResponsePduL" ) |
|
1502 __ASSERT_ALWAYS( iStoredRiContext, User::Invariant() ); |
|
1503 |
|
1504 CMeteringResp* resp = NULL; |
|
1505 CMeteringReportReq* request = NULL; |
|
1506 |
|
1507 resp = iParser->ParseMeteringRespL( aMeteringResp ); |
|
1508 |
|
1509 request = static_cast<CMeteringReportReq*> ( iRequest ); |
|
1510 |
|
1511 iRoapStatus = resp->iStatus; |
|
1512 iResponse = resp; |
|
1513 if ( iRoapStatus == ESuccess ) |
|
1514 { |
|
1515 if ( resp->iDeviceId.CompareF( *iDeviceId ) != KErrNone |
|
1516 || resp->iDeviceNonce->CompareF( request->iNonce ) != KErrNone ) |
|
1517 { |
|
1518 LOGLIT( "Mismatch in deviceId or in nonce" ) |
|
1519 LOGLIT( "Observed DeviceId" ) |
|
1520 LOGHEX( resp->iDeviceId.Ptr(), resp->iDeviceId.Length() ) |
|
1521 LOGLIT( "Expected DeviceId" ) |
|
1522 LOGHEX( request->iDeviceId.Ptr(), request->iDeviceId.Length() ) |
|
1523 LOGLIT( "Observed nonce" ) |
|
1524 LOGHEX( resp->iDeviceNonce->Ptr(), resp->iDeviceNonce->Length() ) |
|
1525 LOGLIT( "Expected nonce" ) |
|
1526 User::Leave( KErrRoapServerFatal ); |
|
1527 } |
|
1528 |
|
1529 if ( !iStoredRiContext || ( resp->iCertificateChain.Count() |
|
1530 && resp->iOcspResponse.Count() ) ) |
|
1531 { |
|
1532 if ( !VerifyCertificateChainL( resp->iCertificateChain, |
|
1533 resp->iOcspResponse ) ) |
|
1534 { |
|
1535 LOGLIT( "Certificate chain validation failed" ) |
|
1536 User::Leave( KErrRoapServerFatal ); |
|
1537 } |
|
1538 if ( !ValidateRiIdL( resp->iRiId, *resp->iCertificateChain[0] ) ) |
|
1539 { |
|
1540 LOGLIT( "RI ID validation failed" ) |
|
1541 User::Leave( KErrRoapServerFatal ); |
|
1542 } |
|
1543 } |
|
1544 |
|
1545 if ( !VerifySignatureL( aMeteringResp, *resp->iSignature, |
|
1546 iStoredRiContext->CertificateChain() ) ) |
|
1547 { |
|
1548 LOGLIT( "Signature verification failed" ) |
|
1549 User::Leave( KErrRoapServerFatal ); |
|
1550 } |
|
1551 |
|
1552 // Everything is fine, we can delete metering data |
|
1553 iStorageClient->DeleteMeteringDataL( resp->iRiId ); |
|
1554 |
|
1555 // notify PostResponseUrl for iObserver |
|
1556 if ( resp->iPrUrl ) |
|
1557 { |
|
1558 HBufC8* prUrl( resp->iPrUrl ); |
|
1559 LOGLIT( "PrUrl" ) |
|
1560 LOGHEX( prUrl->Ptr(), prUrl->Length() ) |
|
1561 if ( iObserver ) |
|
1562 { |
|
1563 iObserver->PostResponseUrlL( *prUrl ); |
|
1564 LOGLIT( "Notified observer with PostResponseUrl" ) |
|
1565 } |
|
1566 else |
|
1567 { |
|
1568 LOGLIT( "Warning no observer for PostResponseUrl" ) |
|
1569 } |
|
1570 } |
|
1571 } |
|
1572 return; |
|
1573 } |
|
1574 #endif //RD_DRM_METERING |
|
1575 // --------------------------------------------------------- |
|
1576 // CRoapEng::HandleMultipartL() |
|
1577 // --------------------------------------------------------- |
|
1578 // |
|
1579 void CRoapEng::HandleMultipartL() |
|
1580 { |
|
1581 LOGLIT( "CRoapEng::HandleMultipartL" ) |
|
1582 |
|
1583 TInt rightsErr( KErrNone ); |
|
1584 TInt err( KErrNone ); |
|
1585 TInt docErr( KErrNone ); |
|
1586 TDataType type = TDataType(); |
|
1587 TBool mmcAllowed( EFalse ); |
|
1588 HBufC* contentName( NULL ); |
|
1589 RBuf newPath; |
|
1590 TUid app_uid; |
|
1591 RBuf rootPath; |
|
1592 |
|
1593 TRAP( rightsErr, HandleRoapResponseL( iRoapResp->ProtocolUnit() ) ); |
|
1594 |
|
1595 newPath.CreateL( KMaxFileName ); |
|
1596 CleanupClosePushL( newPath ); |
|
1597 |
|
1598 CDocumentHandler* docHandler( CDocumentHandler::NewLC() ); |
|
1599 |
|
1600 if ( iRoapResp->DcfFileName().Left( 1 ).CompareF( _L ("e") ) == 0 ) |
|
1601 { |
|
1602 mmcAllowed = ETrue; |
|
1603 } |
|
1604 |
|
1605 RFs fs; |
|
1606 User::LeaveIfError( fs.Connect() ); |
|
1607 CleanupClosePushL( fs ); |
|
1608 |
|
1609 #ifndef RD_MULTIPLE_DRIVE |
|
1610 rootPath.CreateL( mmcAllowed ? |
|
1611 PathInfo::MemoryCardRootPath() : |
|
1612 PathInfo::PhoneMemoryRootPath() ); |
|
1613 |
|
1614 #else //RD_MULTIPLE_DRIVE |
|
1615 _LIT( KSysDriveRoot, "_:\\Data\\"); |
|
1616 _LIT( KMassDriveRoot, "_:\\" ); |
|
1617 TInt driveNumber( -1 ); |
|
1618 TChar driveLetter; |
|
1619 |
|
1620 if ( mmcAllowed ) |
|
1621 { |
|
1622 // Set root path to memory card root |
|
1623 rootPath.CreateL( KMassDriveRoot() ); |
|
1624 DriveInfo::GetDefaultDrive( DriveInfo::EDefaultMassStorage, driveNumber ); |
|
1625 } |
|
1626 else |
|
1627 { |
|
1628 // Set root path to system root |
|
1629 rootPath.CreateL( KSysDriveRoot() ); |
|
1630 DriveInfo::GetDefaultDrive( DriveInfo::EDefaultSystem, driveNumber ); |
|
1631 } |
|
1632 fs.DriveToChar( driveNumber, driveLetter ); |
|
1633 __ASSERT_ALWAYS( rootPath.Length()>0, User::Invariant() ); |
|
1634 rootPath[0] = (TUint)driveLetter; |
|
1635 |
|
1636 |
|
1637 #endif |
|
1638 CleanupClosePushL( rootPath ); |
|
1639 |
|
1640 iRoapResp->GetContentNameLC( contentName ); |
|
1641 |
|
1642 if ( contentName && contentName->Length() |
|
1643 && fs.IsValidName( *contentName ) ) |
|
1644 { |
|
1645 if ( !rightsErr ) |
|
1646 { |
|
1647 TRAP( err, docErr = docHandler->SilentMoveL( iRoapResp->DcfFileName(), |
|
1648 *contentName, rootPath, type, KEntryAttNormal ) ); |
|
1649 } |
|
1650 else |
|
1651 { |
|
1652 // when an error occured during RO storing -> show "saved to" note |
|
1653 TRAP( err, docErr = docHandler->MoveL( iRoapResp->DcfFileName(), |
|
1654 *contentName, type, KEntryAttNormal ) ); |
|
1655 } |
|
1656 |
|
1657 } |
|
1658 else |
|
1659 { |
|
1660 if ( !rightsErr ) |
|
1661 { |
|
1662 // use the default name |
|
1663 User::LeaveIfError( docHandler->SilentMoveL( |
|
1664 iRoapResp->DcfFileName(), KNullDesC(), rootPath, type, |
|
1665 KEntryAttNormal ) ); |
|
1666 } |
|
1667 else |
|
1668 { |
|
1669 // when an error occured during RO storing -> show "saved to" note |
|
1670 docHandler->MoveL( iRoapResp->DcfFileName(), KNullDesC(), type, |
|
1671 KEntryAttNormal ); |
|
1672 } |
|
1673 } |
|
1674 |
|
1675 if ( err || docErr ) |
|
1676 { |
|
1677 if ( !rightsErr ) |
|
1678 { |
|
1679 // use the default name |
|
1680 User::LeaveIfError( docHandler->SilentMoveL( |
|
1681 iRoapResp->DcfFileName(), KNullDesC(), rootPath, type, |
|
1682 KEntryAttNormal ) ); |
|
1683 } |
|
1684 else |
|
1685 { |
|
1686 // when an error occured during RO storing -> show "saved to" note |
|
1687 docHandler->MoveL( iRoapResp->DcfFileName(), KNullDesC(), type, |
|
1688 KEntryAttNormal ); |
|
1689 } |
|
1690 } |
|
1691 User::LeaveIfError( rightsErr ); |
|
1692 |
|
1693 User::LeaveIfError( docHandler->GetPath( newPath ) ); |
|
1694 User::LeaveIfError( docHandler->HandlerAppUid( app_uid ) ); |
|
1695 |
|
1696 if ( iObserver ) |
|
1697 { |
|
1698 iObserver->ContentDetailsL( newPath, type.Des8(), app_uid ); |
|
1699 } |
|
1700 |
|
1701 CleanupStack::PopAndDestroy( contentName ); |
|
1702 CleanupStack::PopAndDestroy( &rootPath ); |
|
1703 |
|
1704 CleanupStack::PopAndDestroy( &fs ); |
|
1705 CleanupStack::PopAndDestroy( docHandler ); |
|
1706 CleanupStack::PopAndDestroy( &newPath ); |
|
1707 } |
|
1708 |
|
1709 // --------------------------------------------------------- |
|
1710 // CRoapEng::SignMessageL() |
|
1711 // --------------------------------------------------------- |
|
1712 // |
|
1713 HBufC8* CRoapEng::SignMessageL( const TDesC8& aMessage ) const |
|
1714 { |
|
1715 LOGLIT( "CRoapEng::SignMessageL" ) |
|
1716 HBufC8* r = NULL; |
|
1717 |
|
1718 if ( iReqMessage == EDeviceHello ) |
|
1719 { |
|
1720 // Device Hello always resets signing chain!! |
|
1721 iSigner->ResetRequests(); |
|
1722 iSigner->ResetResponses(); |
|
1723 // Device Hello or RI Hello is not signed |
|
1724 iSigner->AddRequestL( aMessage ); |
|
1725 r = aMessage.AllocL(); |
|
1726 } |
|
1727 else |
|
1728 { |
|
1729 r = iSigner->SignAndAddRequestL( aMessage ); |
|
1730 iSigner->ResetRequests(); |
|
1731 |
|
1732 if ( iReqMessage == ERegistration ) |
|
1733 { |
|
1734 // Add signed request to the signer for verifying signature on |
|
1735 // response (for Registration protocol only). |
|
1736 iSigner->AddResponseL( *r ); |
|
1737 } |
|
1738 } |
|
1739 return r; |
|
1740 } |
|
1741 |
|
1742 // --------------------------------------------------------- |
|
1743 // CRoapEng::VerifySignatureL() |
|
1744 // --------------------------------------------------------- |
|
1745 // |
|
1746 TBool CRoapEng::VerifySignatureL( |
|
1747 const TDesC8& aMessage, |
|
1748 const TDesC8& aSignature, |
|
1749 const RPointerArray<HBufC8>& aCertificateChain ) const |
|
1750 { |
|
1751 LOGLIT( "CRoapEng::VerifySignatureL" ) |
|
1752 |
|
1753 TBool isValid = ETrue; |
|
1754 |
|
1755 if ( iReqMessage != EDeviceHello && iReqMessage != ELeaveDomain ) |
|
1756 { |
|
1757 // RI Hello and Leave Domain resp are not signed |
|
1758 isValid = iSigner->VerifyAndAddResponseL( aMessage, aSignature, |
|
1759 aCertificateChain ); |
|
1760 iSigner->ResetResponses(); |
|
1761 } |
|
1762 |
|
1763 #ifdef _DISABLE_SIGNATURE_CHECK |
|
1764 isValid = ETrue; |
|
1765 #endif |
|
1766 return isValid; |
|
1767 } |
|
1768 |
|
1769 // --------------------------------------------------------- |
|
1770 // CRoapEng::VerifyTriggerSignatureL() |
|
1771 // --------------------------------------------------------- |
|
1772 // |
|
1773 TBool CRoapEng::VerifyTriggerSignatureL( |
|
1774 const TDesC8& aXmlTrigger, |
|
1775 const CRoapTrigger& aTrigger ) const |
|
1776 { |
|
1777 LOGLIT( "CRoapEng::ValidateTriggerSignatureL" ) |
|
1778 |
|
1779 TPtrC8 element( KNullDesC8 ); |
|
1780 TPtrC8 signedInfo( KNullDesC8 ); |
|
1781 CDRMDomainContext* context( NULL ); |
|
1782 HBufC8* domainKey( NULL ); |
|
1783 HBufC8* unwrappedMacKey( NULL ); |
|
1784 CSHA1* digest( NULL ); |
|
1785 CMessageDigest* hMac( NULL ); |
|
1786 TBool result( ETrue ); |
|
1787 TInt pos( 0 ); |
|
1788 TInt generation( 0 ); |
|
1789 |
|
1790 element.Set( iParser->ExtractElement( aXmlTrigger, KLeaveDomainElement(), |
|
1791 pos ) ); |
|
1792 pos = 0; |
|
1793 signedInfo.Set( iParser->ExtractElement( aXmlTrigger, |
|
1794 KSignedInfoElement(), pos ) ); |
|
1795 |
|
1796 if ( !element.Length() || !signedInfo.Length() || !aTrigger.iEncKey |
|
1797 || !aTrigger.iSignature ) |
|
1798 { |
|
1799 User::Leave( KErrRoapServerFatal ); |
|
1800 } |
|
1801 |
|
1802 context = iStorageClient->GetDomainContextL( *aTrigger.iDomainId ); |
|
1803 |
|
1804 if ( !context ) |
|
1805 { |
|
1806 // we are not member of the domain |
|
1807 LOGLIT( "No DomainContext for the domain -> Cannot verify Trigger signature" ) |
|
1808 return ETrue; |
|
1809 } |
|
1810 CleanupStack::PushL( context ); |
|
1811 |
|
1812 TLex8 lex( aTrigger.iDomainId->Right( KDomainGenerationLength ) ); |
|
1813 lex.Val( generation ); |
|
1814 domainKey = context->DomainKeyL( generation ); |
|
1815 User::LeaveIfNull( domainKey ); |
|
1816 CleanupStack::PushL( domainKey ); |
|
1817 |
|
1818 unwrappedMacKey = OmaCrypto::AesUnwrapL( *domainKey, *aTrigger.iEncKey ); |
|
1819 CleanupStack::PopAndDestroy( domainKey ); |
|
1820 CleanupStack::PushL( unwrappedMacKey ); |
|
1821 |
|
1822 // hash the leaveDomain element |
|
1823 digest = CSHA1::NewL(); |
|
1824 CleanupStack::PushL( digest ); |
|
1825 digest->Update( element ); |
|
1826 |
|
1827 if ( digest->Final().CompareF( *aTrigger.iDigestValue ) ) |
|
1828 { |
|
1829 LOGLIT( "Reference Validation failed!" ) |
|
1830 result = EFalse; |
|
1831 } |
|
1832 |
|
1833 if ( result ) |
|
1834 { |
|
1835 // calculate HMAC signature |
|
1836 hMac = CMessageDigestFactory::NewHMACLC( CMessageDigest::ESHA1, |
|
1837 *unwrappedMacKey ); |
|
1838 hMac->Update( signedInfo ); |
|
1839 |
|
1840 if ( hMac->Final().CompareF( *aTrigger.iSignature ) != 0 ) |
|
1841 { |
|
1842 LOGLIT( "Signature Validation failed!" ) |
|
1843 result = EFalse; |
|
1844 } |
|
1845 CleanupStack::PopAndDestroy( hMac ); |
|
1846 } |
|
1847 |
|
1848 CleanupStack::PopAndDestroy( digest ); |
|
1849 CleanupStack::PopAndDestroy( unwrappedMacKey ); |
|
1850 CleanupStack::PopAndDestroy( context ); |
|
1851 |
|
1852 if ( !result ) |
|
1853 { |
|
1854 LOGLIT( "Trigger signature check failed!" ) |
|
1855 } |
|
1856 |
|
1857 #ifdef _DISABLE_SIGNATURE_CHECK |
|
1858 result = ETrue; |
|
1859 #endif |
|
1860 return result; |
|
1861 } |
|
1862 |
|
1863 // --------------------------------------------------------- |
|
1864 // CRoapEng::VerifyCertificateChainL() |
|
1865 // --------------------------------------------------------- |
|
1866 // |
|
1867 TBool CRoapEng::VerifyCertificateChainL( |
|
1868 const RPointerArray<HBufC8>& aCertificateChain, |
|
1869 const RPointerArray<HBufC8>& aOcspResponses ) const |
|
1870 { |
|
1871 LOGLIT( "CRoapEng::VerifyCertificateChainL" ) |
|
1872 |
|
1873 CX509Certificate* cert = NULL; |
|
1874 CX509Certificate* signingCert = NULL; |
|
1875 CX509Certificate* riCA = NULL; |
|
1876 TBool result = EFalse; |
|
1877 RPointerArray<HBufC8> serialNums; |
|
1878 CX500DistinguishedName* rootDistName = NULL; |
|
1879 HBufC* rootName = NULL; |
|
1880 HBufC8* rootCert = NULL; |
|
1881 HBufC8* temp = NULL; |
|
1882 |
|
1883 if ( !aCertificateChain.Count() || !aOcspResponses.Count() ) |
|
1884 { |
|
1885 User::Leave( KErrRoapServerFatal ); |
|
1886 } |
|
1887 |
|
1888 // Get the last cert from the chain. It is signed by some of our trusted anchor |
|
1889 riCA = CX509Certificate::NewLC( |
|
1890 *( aCertificateChain[aCertificateChain.Count() - 1] ) ); |
|
1891 rootDistName = CX500DistinguishedName::NewLC( riCA->IssuerName() ); |
|
1892 rootName = rootDistName->DisplayNameL(); |
|
1893 CleanupStack::PushL( rootName ); |
|
1894 // Get the correct root cert for validating the whole chain |
|
1895 rootCert = iStorageClient->GetRootCertificateL( *rootName ); |
|
1896 CleanupStack::PopAndDestroy( rootName ); |
|
1897 CleanupStack::PopAndDestroy( rootDistName ); |
|
1898 CleanupStack::PopAndDestroy( riCA ); |
|
1899 |
|
1900 if ( !rootCert ) |
|
1901 { |
|
1902 LOGLIT( "No root certificate present!" ) |
|
1903 LOGLIT( "Certificate chain verification failed." ) |
|
1904 return EFalse; |
|
1905 } |
|
1906 CleanupStack::PushL( rootCert ); |
|
1907 |
|
1908 CleanupResetAndDestroyPushL( serialNums ); |
|
1909 |
|
1910 for ( TInt i = 0; i < aCertificateChain.Count(); i++ ) |
|
1911 { |
|
1912 cert = CX509Certificate::NewLC( *aCertificateChain[i] ); |
|
1913 temp = cert->SerialNumber().AllocLC(); |
|
1914 serialNums.AppendL( temp ); |
|
1915 CleanupStack::Pop( temp ); |
|
1916 if ( aCertificateChain.Count() - 1 == i ) |
|
1917 { |
|
1918 // signingCert = Trusted root cert |
|
1919 signingCert = CX509Certificate::NewLC( *rootCert ); |
|
1920 } |
|
1921 else |
|
1922 { |
|
1923 signingCert = CX509Certificate::NewLC( *aCertificateChain[i + 1] ); |
|
1924 } |
|
1925 result = cert->VerifySignatureL( signingCert->PublicKey().KeyData() ); |
|
1926 |
|
1927 #ifdef _DISABLE_CERT_CHECK |
|
1928 result = ETrue; |
|
1929 #endif |
|
1930 CleanupStack::PopAndDestroy( signingCert ); |
|
1931 CleanupStack::PopAndDestroy( cert ); |
|
1932 if ( !result ) |
|
1933 { |
|
1934 LOGLIT( "Certificate chain verification failed." ) |
|
1935 CleanupStack::PopAndDestroy( 2, rootCert ); |
|
1936 return result; |
|
1937 } |
|
1938 } |
|
1939 |
|
1940 if ( aCertificateChain.Count() >= 2 ) |
|
1941 { |
|
1942 result = VerifyOcspResponsesL( aOcspResponses, *aCertificateChain[1], |
|
1943 serialNums ); |
|
1944 |
|
1945 if ( !result ) |
|
1946 { |
|
1947 // CoreMedia's OCSP responder cert is signed by the root -> against CMLA spec |
|
1948 LOGLIT( "Try to verify OCSP response cert using root cert" ) |
|
1949 result = VerifyOcspResponsesL( aOcspResponses, *rootCert, |
|
1950 serialNums ); |
|
1951 } |
|
1952 } |
|
1953 else if ( aCertificateChain.Count() == 1 ) |
|
1954 { |
|
1955 // There is only one cert in the cert chain -> the OCSP response cert is verified with root cert |
|
1956 result = VerifyOcspResponsesL( aOcspResponses, *rootCert, serialNums ); |
|
1957 } |
|
1958 else |
|
1959 { |
|
1960 result = EFalse; |
|
1961 } |
|
1962 |
|
1963 if ( iStoredRiContext && aCertificateChain.Count() && result ) |
|
1964 { |
|
1965 cert = CX509Certificate::NewLC( *aCertificateChain[0] ); |
|
1966 if ( iStoredRiContext->ExpiryTime() < cert->ValidityPeriod().Finish() ) |
|
1967 { |
|
1968 iStoredRiContext->SetCertificateChainL( aCertificateChain ); |
|
1969 iStoredRiContext->SetOCSPResponseL( aOcspResponses ); |
|
1970 |
|
1971 // update RI Context |
|
1972 iStorageClient->AddRIContextL( *iStoredRiContext ); |
|
1973 } |
|
1974 CleanupStack::PopAndDestroy( cert ); |
|
1975 } |
|
1976 |
|
1977 CleanupStack::PopAndDestroy( 2, rootCert ); // serialNums, rootCert |
|
1978 |
|
1979 #ifdef _ROAP_TESTING |
|
1980 if ( result ) |
|
1981 { |
|
1982 LOGLIT( "Certificate chain verification ok." ) |
|
1983 } |
|
1984 else |
|
1985 { |
|
1986 LOGLIT( "Certificate chain verification failed." ) |
|
1987 } |
|
1988 #endif |
|
1989 #ifdef _DISABLE_CERT_CHECK |
|
1990 result = ETrue; |
|
1991 #endif |
|
1992 |
|
1993 return result; |
|
1994 } |
|
1995 |
|
1996 // --------------------------------------------------------- |
|
1997 // CRoapEng::VerifyOcspResponsesL() |
|
1998 // --------------------------------------------------------- |
|
1999 // |
|
2000 TBool CRoapEng::VerifyOcspResponsesL( |
|
2001 const RPointerArray<HBufC8>& aOcspResponses, |
|
2002 const TDesC8& aRiCaCert, |
|
2003 const RPointerArray<HBufC8>& aCertSerialNums ) const |
|
2004 { |
|
2005 LOGLIT( "CRoapEng::VerifyOcspResponsesL" ) |
|
2006 |
|
2007 #ifdef _DISABLE_OCSP_CHECK |
|
2008 TBool result( ETrue ); |
|
2009 #else |
|
2010 // Get verification result from the server |
|
2011 TBool result( iStorageClient->VerifyOcspResponsesL( aOcspResponses, |
|
2012 aRiCaCert, aCertSerialNums ) ); |
|
2013 #endif |
|
2014 |
|
2015 #ifdef _ROAP_TESTING |
|
2016 if ( result ) |
|
2017 { |
|
2018 LOGLIT( "OCSP response verification ok." ) |
|
2019 } |
|
2020 else |
|
2021 { |
|
2022 LOGLIT( "OCSP response verification failed." ) |
|
2023 } |
|
2024 #endif |
|
2025 |
|
2026 return result; |
|
2027 } |
|
2028 |
|
2029 // --------------------------------------------------------- |
|
2030 // CRoapEng::ValidateRiCertificateL() |
|
2031 // --------------------------------------------------------- |
|
2032 // |
|
2033 TBool CRoapEng::ValidateRiCertificateL( const CX509Certificate* aCert ) |
|
2034 { |
|
2035 LOGLIT( "CRoapEng::ValidateRiCertificateL" ) |
|
2036 |
|
2037 TBool ret = ETrue; |
|
2038 const CX509CertExtension* ext = NULL; |
|
2039 CX509KeyUsageExt* keyUsageExt = NULL; |
|
2040 CX509ExtendedKeyUsageExt* extendedKeyUsage = NULL; |
|
2041 TTime riExpiry; |
|
2042 TInt count = 0; |
|
2043 |
|
2044 if ( iSelectedAlgorithms == ECmlaIp1 ) |
|
2045 { |
|
2046 // Check RI certificate extensions only in CMLA case |
|
2047 ext = aCert->Extension( KKeyUsage() ); |
|
2048 if ( !ext || !( ext->Critical() ) ) |
|
2049 { |
|
2050 LOGLIT( "RI cert KeyUsage extension missing or not critical!" ) |
|
2051 ret = EFalse; |
|
2052 } |
|
2053 |
|
2054 if ( ext && ret ) |
|
2055 { |
|
2056 keyUsageExt = CX509KeyUsageExt::NewLC( ext->Data() ); |
|
2057 if ( !keyUsageExt->IsSet( EX509DigitalSignature ) ) |
|
2058 { |
|
2059 LOGLIT( "DigitalSignature bit is not set in KeyUsageExt of RI cert!" ) |
|
2060 ret = EFalse; |
|
2061 } |
|
2062 CleanupStack::PopAndDestroy( keyUsageExt ); |
|
2063 } |
|
2064 |
|
2065 ext = aCert->Extension( KExtendedKeyUsage() ); |
|
2066 if ( !ext || !( ext->Critical() ) ) |
|
2067 { |
|
2068 LOGLIT( "RI cert ExtendedKeyUsage extension missing or not critical!" ) |
|
2069 ret = EFalse; |
|
2070 } |
|
2071 |
|
2072 if ( ext && ret ) |
|
2073 { |
|
2074 ret = EFalse; |
|
2075 extendedKeyUsage = CX509ExtendedKeyUsageExt::NewLC( ext->Data() ); |
|
2076 count = extendedKeyUsage->KeyUsages().Count(); |
|
2077 for ( TInt i = 0; i < count && !ret; i++ ) |
|
2078 { |
|
2079 if ( extendedKeyUsage->KeyUsages().At( i )->CompareF( |
|
2080 KOmaKpRightsIssuerOid() ) == 0 ) |
|
2081 { |
|
2082 ret = ETrue; |
|
2083 } |
|
2084 } |
|
2085 if ( !ret ) |
|
2086 { |
|
2087 LOGLIT( "OmaKpRightsIssuer OID is not set in ExtendedKeyUsageExt of RI cert!" ) |
|
2088 } |
|
2089 CleanupStack::PopAndDestroy( extendedKeyUsage ); |
|
2090 } |
|
2091 } |
|
2092 |
|
2093 riExpiry = aCert->ValidityPeriod().Finish(); |
|
2094 |
|
2095 if ( riExpiry < GetDrmTimeL() ) |
|
2096 { |
|
2097 LOGLIT( "RI Context certificate is expired!" ) |
|
2098 ret = EFalse; |
|
2099 } |
|
2100 #ifdef _DISABLE_CERT_CHECK |
|
2101 ret = ETrue; |
|
2102 #endif |
|
2103 return ret; |
|
2104 } |
|
2105 |
|
2106 // --------------------------------------------------------- |
|
2107 // CRoapEng::GetCertificateChainL() |
|
2108 // --------------------------------------------------------- |
|
2109 // |
|
2110 RPointerArray<HBufC8> CRoapEng::GetCertificateChainL() const |
|
2111 { |
|
2112 LOGLIT( "CRoapEng::GetCertificateChainL ->" ) |
|
2113 |
|
2114 TInt err = KErrNone; |
|
2115 RPointerArray<HBufC8> certificateChain; |
|
2116 HBufC8* root = NULL; |
|
2117 |
|
2118 CleanupResetAndDestroyPushL( certificateChain ); |
|
2119 |
|
2120 err = iStorageClient->GetDeviceCertificateChainL( certificateChain ); |
|
2121 |
|
2122 if ( err ) |
|
2123 { |
|
2124 User::Leave( err ); |
|
2125 } |
|
2126 |
|
2127 if ( certificateChain.Count() < KMinCertChainLength ) |
|
2128 { |
|
2129 // the CMLA chain must always contain: |
|
2130 // the device certificate, |
|
2131 // at lest one signing certificate (device CA), |
|
2132 // and the root certificate |
|
2133 DETAILLOGLIT( "Got improper certificate chain!!" ) |
|
2134 // Leaving in production devices. |
|
2135 User::Leave( KErrRoapDevice ); |
|
2136 __ASSERT_DEBUG( ETrue, User::Invariant() ); |
|
2137 } |
|
2138 |
|
2139 // delete and remove the root certificate (it's always the last one in the list) |
|
2140 root = certificateChain[certificateChain.Count() - 1]; |
|
2141 delete root; |
|
2142 certificateChain.Remove( certificateChain.Count() - 1 ); |
|
2143 |
|
2144 CleanupStack::Pop( &certificateChain ); |
|
2145 |
|
2146 LOGLIT( "CRoapEng::GetCertificateChainL <-" ) |
|
2147 |
|
2148 return certificateChain; |
|
2149 } |
|
2150 |
|
2151 // --------------------------------------------------------- |
|
2152 // CRoapEng::GetDeviceDetailsL() |
|
2153 // --------------------------------------------------------- |
|
2154 // |
|
2155 void CRoapEng::GetDeviceDetailsL( |
|
2156 HBufC8*& aManufacturer, |
|
2157 HBufC8*& aModel, |
|
2158 HBufC8*& aVersion ) |
|
2159 { |
|
2160 LOGLIT( "-> CRoapEng::GetDeviceDetailsL" ) |
|
2161 |
|
2162 #ifndef __WINS__ |
|
2163 TInt numPhone = 0; |
|
2164 TUint32 caps = 0; |
|
2165 TName tsyName; |
|
2166 RMobilePhone phone; |
|
2167 RTelServer etelServer; |
|
2168 RTelServer::TPhoneInfo phoneInfo; |
|
2169 HBufC* version = NULL; |
|
2170 |
|
2171 User::LeaveIfError( etelServer.Connect() ); |
|
2172 |
|
2173 CleanupClosePushL( etelServer ); |
|
2174 |
|
2175 User::LeaveIfError( etelServer.LoadPhoneModule( KMmTsyModuleName ) ); |
|
2176 User::LeaveIfError( etelServer.EnumeratePhones( numPhone) ); |
|
2177 |
|
2178 for (TInt i(0); i < numPhone; i++) |
|
2179 { |
|
2180 User::LeaveIfError( etelServer.GetPhoneInfo( i, phoneInfo ) ); |
|
2181 User::LeaveIfError( etelServer.GetTsyName( i,tsyName ) ); |
|
2182 |
|
2183 if ( tsyName.CompareF( KMmTsyModuleName ) == 0) |
|
2184 { |
|
2185 break; |
|
2186 } |
|
2187 } |
|
2188 |
|
2189 User::LeaveIfError( phone.Open( etelServer, phoneInfo.iName ) ); |
|
2190 CleanupClosePushL( phone ); |
|
2191 |
|
2192 phone.GetIdentityCaps( caps ); |
|
2193 if ( !( caps & RMobilePhone::KCapsGetManufacturer ) && |
|
2194 !( caps & RMobilePhone::KCapsGetModel ) ) |
|
2195 { |
|
2196 User::Leave( KErrRoapGeneral ); |
|
2197 } |
|
2198 |
|
2199 RMobilePhone::TMobilePhoneIdentityV1 details; |
|
2200 TRequestStatus status; |
|
2201 |
|
2202 phone.GetPhoneId( status, details ); |
|
2203 User::WaitForRequest( status ); |
|
2204 |
|
2205 User::LeaveIfError( status.Int() ); |
|
2206 |
|
2207 HBufC8* manufacturer( HBufC8::NewLC( details.iManufacturer.Length() ) ); |
|
2208 manufacturer->Des().Copy( details.iManufacturer ); |
|
2209 HBufC8* model( HBufC8::NewLC( details.iModel.Length() ) ); |
|
2210 model->Des().Copy( details.iModel ); |
|
2211 |
|
2212 version = HBufC::NewLC( KSysUtilVersionTextLength ); |
|
2213 TPtr ptr( version->Des() ); |
|
2214 User::LeaveIfError( SysUtil::GetSWVersion( ptr ) ); |
|
2215 |
|
2216 // remove possible BOM from the end |
|
2217 if ( ptr.Right( KBOM1().Length() ).CompareF( KBOM1 ) == KErrNone ) |
|
2218 { |
|
2219 ptr.Delete( ptr.Length() - KBOM1().Length(), KBOM1().Length() ); |
|
2220 } |
|
2221 if ( ptr.Right( KBOM2().Length() ).CompareF( KBOM2 ) == KErrNone ) |
|
2222 { |
|
2223 ptr.Delete( ptr.Length() - KBOM2().Length(), KBOM2().Length() ); |
|
2224 } |
|
2225 |
|
2226 aVersion = CnvUtfConverter::ConvertFromUnicodeToUtf8L( ptr ); |
|
2227 |
|
2228 CleanupStack::PopAndDestroy( version ); |
|
2229 CleanupStack::Pop( model ); |
|
2230 CleanupStack::Pop( manufacturer ); |
|
2231 aManufacturer = manufacturer; |
|
2232 aModel = model; |
|
2233 CleanupStack::PopAndDestroy( &phone ); |
|
2234 CleanupStack::PopAndDestroy( &etelServer ); |
|
2235 #else |
|
2236 aManufacturer = _L8("Nokia").AllocL(); |
|
2237 aModel = _L8("Emulator").AllocL(); |
|
2238 aVersion = _L8("9.0").AllocL(); |
|
2239 #endif |
|
2240 |
|
2241 LOGLIT( "Device details:" ) |
|
2242 LOGLIT( " Manufacturer: " ) |
|
2243 LOG( aManufacturer->Des() ) |
|
2244 LOGLIT( " Model: " ) |
|
2245 LOG( aModel->Des() ) |
|
2246 LOGLIT( " Revision: " ) |
|
2247 LOG( aVersion->Des() ) |
|
2248 |
|
2249 LOGLIT( "<- CRoapEng::GetDeviceDetailsL" ) |
|
2250 } |
|
2251 |
|
2252 // --------------------------------------------------------- |
|
2253 // CRoapEng::FetchTransactionIDL() |
|
2254 // --------------------------------------------------------- |
|
2255 // |
|
2256 void CRoapEng::FetchTransactionIDL( |
|
2257 RPointerArray<HBufC8>& aTransIDs, |
|
2258 RPointerArray<HBufC8>& aContentIDs ) |
|
2259 { |
|
2260 LOGLIT( "CRoapEng::FetchTransactionIDL" ) |
|
2261 |
|
2262 __ASSERT_ALWAYS( iTrigger, User::Invariant() ); |
|
2263 |
|
2264 RArray<TPair> array; |
|
2265 TInt err = KErrNone; |
|
2266 |
|
2267 CleanupClosePushL( array ); |
|
2268 |
|
2269 if ( !iTrigger->iContentIdList.Count() ) |
|
2270 { |
|
2271 CleanupStack::PopAndDestroy( &array ); |
|
2272 return; |
|
2273 } |
|
2274 |
|
2275 if ( iTransStatus == ENotAsked && iObserver ) |
|
2276 { |
|
2277 UpdateTransactionTrackingStatusL(); |
|
2278 } |
|
2279 if ( iTransStatus == EAllowed ) |
|
2280 { |
|
2281 for ( TInt i = 0; i < iTrigger->iContentIdList.Count(); i++ ) |
|
2282 { |
|
2283 TPair pair; |
|
2284 pair.iCid = iTrigger->iContentIdList[i]->Alloc(); // duplicate contentID, |
|
2285 pair.iTtid = NULL; // pair.iCid is deleted by iRequest |
|
2286 err = array.Append( pair ); |
|
2287 if ( err ) |
|
2288 { |
|
2289 delete pair.iCid; |
|
2290 pair.iCid = NULL; |
|
2291 } |
|
2292 } |
|
2293 |
|
2294 TRAP_IGNORE(iDcfRep->GetTtidL( array ) ); |
|
2295 |
|
2296 for ( TInt i = 0; i < array.Count(); i++ ) |
|
2297 { |
|
2298 if ( array[i].iTtid && array[i].iCid && array[i].iTtid->Length() |
|
2299 && array[i].iCid->Length() ) |
|
2300 { |
|
2301 err = aContentIDs.Append( array[i].iCid ); |
|
2302 if ( !err ) |
|
2303 { |
|
2304 aTransIDs.Append( array[i].iTtid ); |
|
2305 } |
|
2306 else |
|
2307 { |
|
2308 delete array[i].iCid; |
|
2309 array[i].iCid = NULL; |
|
2310 delete array[i].iTtid; |
|
2311 array[i].iTtid = NULL; |
|
2312 } |
|
2313 } |
|
2314 else if ( array[i].iTtid || array[i].iCid ) |
|
2315 { |
|
2316 delete array[i].iTtid; |
|
2317 array[i].iTtid = NULL; |
|
2318 delete array[i].iCid; |
|
2319 array[i].iCid = NULL; |
|
2320 } |
|
2321 } |
|
2322 } |
|
2323 CleanupStack::PopAndDestroy( &array ); |
|
2324 } |
|
2325 |
|
2326 // --------------------------------------------------------- |
|
2327 // CRoapEng::InsertTransactionIDL() |
|
2328 // --------------------------------------------------------- |
|
2329 // |
|
2330 void CRoapEng::InsertTransactionIDL( |
|
2331 RPointerArray<HBufC8>& aTransIDs, |
|
2332 RPointerArray<HBufC8>& aContentIDs ) |
|
2333 { |
|
2334 LOGLIT( "CRoapEng::InsertTransactionIDL" ) |
|
2335 |
|
2336 RArray<TPair> array; |
|
2337 TRequestStatus status; |
|
2338 |
|
2339 CleanupClosePushL( array ); |
|
2340 |
|
2341 if ( !aTransIDs.Count() || !aContentIDs.Count() ) |
|
2342 { |
|
2343 LOGLIT( "Insert ttID: Wrong input data" ) |
|
2344 CleanupStack::PopAndDestroy( &array ); |
|
2345 return; |
|
2346 } |
|
2347 |
|
2348 if ( aTransIDs.Count() != aContentIDs.Count() ) |
|
2349 { |
|
2350 LOGLIT( "Insert ttID: ttID.Count != cid.Count" ) |
|
2351 CleanupStack::PopAndDestroy( &array ); |
|
2352 return; |
|
2353 } |
|
2354 |
|
2355 if ( iTransStatus == ENotAsked && iObserver ) |
|
2356 { |
|
2357 UpdateTransactionTrackingStatusL(); |
|
2358 } |
|
2359 if ( iTransStatus == EAllowed ) |
|
2360 { |
|
2361 for ( TInt i = 0; i < aContentIDs.Count() && i < aTransIDs.Count(); i++ ) |
|
2362 { |
|
2363 TPair pair; |
|
2364 pair.iCid = aContentIDs[i]; |
|
2365 pair.iTtid = aTransIDs[i]; |
|
2366 array.Append( pair ); |
|
2367 } |
|
2368 |
|
2369 iDcfRep->SetTtid( array, status ); |
|
2370 User::WaitForRequest( status ); |
|
2371 } |
|
2372 |
|
2373 CleanupStack::PopAndDestroy( &array ); |
|
2374 } |
|
2375 |
|
2376 // --------------------------------------------------------- |
|
2377 // CRoapEng::GetOCSPResponderKeyHashL() |
|
2378 // --------------------------------------------------------- |
|
2379 // |
|
2380 HBufC8* CRoapEng::GetOCSPResponderKeyHashL() const |
|
2381 { |
|
2382 LOGLIT( "CRoapEng::GetOCSPResponderKeyHashL" ) |
|
2383 |
|
2384 if ( !iStoredRiContext ) |
|
2385 { |
|
2386 User::Leave( KErrRoapNotRegistered ); |
|
2387 } |
|
2388 return iStorageClient->GetOcspResponderIdL( iStoredRiContext->RIID() ); |
|
2389 } |
|
2390 |
|
2391 // --------------------------------------------------------- |
|
2392 // CRoapEng::GetDrmTimeL() |
|
2393 // --------------------------------------------------------- |
|
2394 // |
|
2395 TTime CRoapEng::GetDrmTimeL() |
|
2396 { |
|
2397 LOGLIT( "CRoapEng::GetDrmTimeL" ) |
|
2398 |
|
2399 TTime drmTime; |
|
2400 DRMClock::ESecurityLevel secureTime; |
|
2401 TInt zone( 0 ); |
|
2402 |
|
2403 User::LeaveIfError( iClockClient->GetSecureTime( drmTime, zone, |
|
2404 secureTime ) ); |
|
2405 |
|
2406 if ( secureTime == DRMClock::KInsecure ) |
|
2407 { |
|
2408 iSecureTime = EFalse; |
|
2409 } |
|
2410 else |
|
2411 { |
|
2412 iSecureTime = ETrue; |
|
2413 } |
|
2414 |
|
2415 return drmTime; |
|
2416 } |
|
2417 |
|
2418 // --------------------------------------------------------- |
|
2419 // CRoapEng::SetDrmTimeSecureL() |
|
2420 // --------------------------------------------------------- |
|
2421 // |
|
2422 void CRoapEng::SetDrmTimeSecureL() |
|
2423 { |
|
2424 LOGLIT( "CRoapEng::SetDrmTimeSecureL" ) |
|
2425 |
|
2426 TTime drmTime; |
|
2427 DRMClock::ESecurityLevel secureTime; |
|
2428 TInt zone( 0 ); |
|
2429 |
|
2430 User::LeaveIfError( iClockClient->GetSecureTime( drmTime, zone, |
|
2431 secureTime ) ); |
|
2432 User::LeaveIfError( iClockClient->UpdateSecureTime( drmTime, zone ) ); |
|
2433 |
|
2434 iSecureTime = ETrue; |
|
2435 } |
|
2436 |
|
2437 // --------------------------------------------------------- |
|
2438 // CRoapEng::AdjustDrmTime() |
|
2439 // --------------------------------------------------------- |
|
2440 // |
|
2441 void CRoapEng::AdjustDrmTimeL( |
|
2442 const RPointerArray<HBufC8>& aOcspResponses, |
|
2443 TDesC8& aRegReqNonce ) const |
|
2444 { |
|
2445 // To be removed on next API change. |
|
2446 // Replace calls with direct call to RRoapStorageClient. |
|
2447 LOGLIT( "CRoapEng::AdjustDrmTime calling server" ) |
|
2448 if ( aOcspResponses.Count() > 0 ) |
|
2449 { |
|
2450 iStorageClient->UpdateDrmTimeL( iStoredRiContext->CertificateChain(), |
|
2451 aOcspResponses, aRegReqNonce ); |
|
2452 } |
|
2453 else |
|
2454 { |
|
2455 LOGLIT( "No OCSP responses present." ) |
|
2456 } |
|
2457 } |
|
2458 |
|
2459 // --------------------------------------------------------- |
|
2460 // CRoapEng::StoreDomainRightsL() |
|
2461 // --------------------------------------------------------- |
|
2462 // |
|
2463 void CRoapEng::StoreDomainRightsL() |
|
2464 { |
|
2465 LOGLIT( "CRoapEng::StoreDomainRightsL" ) |
|
2466 |
|
2467 RPointerArray<CDRMRights> returnedROs; |
|
2468 |
|
2469 CleanupResetAndDestroyPushL( returnedROs ); |
|
2470 |
|
2471 iRoParser->ParseAndStoreL( *iDomainRightsResp, returnedROs ); |
|
2472 |
|
2473 if ( iObserver ) |
|
2474 { |
|
2475 iObserver->RightsObjectDetailsL( returnedROs ); // pass RO details to UI |
|
2476 } |
|
2477 |
|
2478 delete iDomainRightsResp; |
|
2479 iDomainRightsResp = NULL; |
|
2480 |
|
2481 iImplicitJoinDomain = EFalse; |
|
2482 |
|
2483 CleanupStack::PopAndDestroy( &returnedROs ); |
|
2484 } |
|
2485 |
|
2486 // --------------------------------------------------------- |
|
2487 // CRoapEng::InsertDomainRosL() |
|
2488 // --------------------------------------------------------- |
|
2489 // |
|
2490 void CRoapEng::InsertDomainRosL() |
|
2491 { |
|
2492 CDcfRep* rep = NULL; |
|
2493 CDcfEntry* entry = NULL; |
|
2494 CContent* content = NULL; |
|
2495 TPtr8 ptr( NULL, 0 ); |
|
2496 TInt i; |
|
2497 RFile file; |
|
2498 RFs fs; |
|
2499 TInt error( 0 ); |
|
2500 |
|
2501 User::LeaveIfError( fs.Connect() ); |
|
2502 CleanupClosePushL( fs ); |
|
2503 rep = CDcfRep::NewL(); |
|
2504 CleanupStack::PushL( rep ); |
|
2505 for ( i = 0; i < iReturnedROs.Count(); i++ ) |
|
2506 { |
|
2507 if ( iReturnedROs[i]->GetPermission().iDomainID ) |
|
2508 { |
|
2509 rep->OrderListL( *iReturnedROs[i]->GetAsset().iUid ); |
|
2510 entry = rep->NextL(); |
|
2511 while ( entry ) |
|
2512 { |
|
2513 CleanupStack::PushL( entry ); |
|
2514 error = file.Open( fs, entry->FileName(), EFileWrite |
|
2515 | EFileShareReadersOrWriters ); |
|
2516 if ( !error ) |
|
2517 { |
|
2518 CleanupClosePushL( file ); |
|
2519 content = CContent::NewLC( file ); |
|
2520 content->AgentSpecificCommand( EEmbedDomainRo, |
|
2521 KNullDesC8, ptr ); |
|
2522 CleanupStack::PopAndDestroy( 2, &file ); // content, file |
|
2523 } |
|
2524 CleanupStack::PopAndDestroy( entry ); |
|
2525 entry = rep->NextL(); |
|
2526 } |
|
2527 } |
|
2528 } |
|
2529 CleanupStack::PopAndDestroy( 2, &fs ); // rep, fs |
|
2530 } |
|
2531 |
|
2532 // --------------------------------------------------------- |
|
2533 // CRoapEng::MapStatusL() |
|
2534 // --------------------------------------------------------- |
|
2535 // |
|
2536 TInt CRoapEng::MapStatusL() |
|
2537 { |
|
2538 LOGLIT( "CRoapEng::MapStatusL" ) |
|
2539 |
|
2540 if ( iRoapStatus == ESuccess ) |
|
2541 { |
|
2542 LOGLIT( "ROAP Status: success " ) |
|
2543 return KErrNone; |
|
2544 } |
|
2545 |
|
2546 if ( iRoapStatus == ENotRegistered || iRoapStatus == EDeviceTimeError ) |
|
2547 { |
|
2548 // Initiate registration protocol |
|
2549 LOG2( _L ( "Not Registered! Status: %d" ), iRoapStatus ) |
|
2550 |
|
2551 if ( iRoapStatus == EDeviceTimeError ) |
|
2552 { |
|
2553 iDeviceTimeError = ETrue; |
|
2554 } |
|
2555 |
|
2556 return KErrRoapNotRegistered; |
|
2557 } |
|
2558 |
|
2559 LOG2( _L ( "ROAP Error! Status: %d" ), iRoapStatus ) |
|
2560 |
|
2561 switch ( iRoapStatus ) |
|
2562 { |
|
2563 case EUnknownError: |
|
2564 case EAbort: |
|
2565 { |
|
2566 User::Leave( KErrRoapServer ); |
|
2567 } |
|
2568 case ENotSupported: |
|
2569 case EAccessDenied: |
|
2570 case ENotFound: |
|
2571 case EMalformedRequest: |
|
2572 case EUnknownRequest: |
|
2573 case EUnknownCriticalExtension: |
|
2574 case EUnsupportedVersion: |
|
2575 case EUnsupportedAlgorithm: |
|
2576 case ESignatureError: |
|
2577 case EInvalidDCFHash: |
|
2578 { |
|
2579 User::Leave( KErrRoapServerFatal ); |
|
2580 } |
|
2581 case ENoCertificateChain: |
|
2582 case EInvalidCertificateChain: |
|
2583 case ETrustedRootCertificateNotPresent: |
|
2584 { |
|
2585 User::Leave( KErrRoapDevice ); |
|
2586 } |
|
2587 case EInvalidDomain: |
|
2588 { |
|
2589 User::Leave( KErrRoapInvalidDomain ); |
|
2590 } |
|
2591 case EDomainFull: |
|
2592 { |
|
2593 User::Leave( KErrRoapDomainFull ); |
|
2594 } |
|
2595 default: |
|
2596 { |
|
2597 User::Leave( KErrRoapUnsupported ); |
|
2598 } |
|
2599 } |
|
2600 return KErrNone; |
|
2601 } |
|
2602 |
|
2603 // --------------------------------------------------------- |
|
2604 // CRoapEng::ValidateRiIdL() |
|
2605 // |
|
2606 // Validates that RI ID equals to public key hash of RI certificate |
|
2607 // --------------------------------------------------------- |
|
2608 // |
|
2609 TBool CRoapEng::ValidateRiIdL( TDesC8& aRiId, TDesC8& aCertBuf ) |
|
2610 { |
|
2611 TBool valid = EFalse; |
|
2612 CX509Certificate* riCert = NULL; |
|
2613 CSHA1* hash = NULL; |
|
2614 HBufC8* publicKeyHash = NULL; |
|
2615 |
|
2616 riCert = CX509Certificate::NewLC( aCertBuf ); |
|
2617 |
|
2618 // hash the SubjectPublicKeyInfo element |
|
2619 hash = CSHA1::NewL(); |
|
2620 CleanupStack::PushL( hash ); |
|
2621 hash->Hash( *riCert->DataElementEncoding( |
|
2622 CX509Certificate::ESubjectPublicKeyInfo ) ); |
|
2623 publicKeyHash = hash->Final().AllocLC(); |
|
2624 |
|
2625 if ( aRiId.Compare( *publicKeyHash ) == KErrNone ) |
|
2626 { |
|
2627 valid = ETrue; |
|
2628 } |
|
2629 |
|
2630 CleanupStack::PopAndDestroy( publicKeyHash ); |
|
2631 CleanupStack::PopAndDestroy( hash ); |
|
2632 CleanupStack::PopAndDestroy( riCert ); |
|
2633 |
|
2634 return valid; |
|
2635 } |
|
2636 |
|
2637 // --------------------------------------------------------- |
|
2638 // CRoapEng::UpdateTransactionTrackingStatusL() |
|
2639 // |
|
2640 // Update the status of transaction tracking variable |
|
2641 // --------------------------------------------------------- |
|
2642 // |
|
2643 void CRoapEng::UpdateTransactionTrackingStatusL() |
|
2644 { |
|
2645 TInt value = KErrNone; |
|
2646 CRepository* repository = CRepository::NewL( KCRUidDRMSettings ); |
|
2647 repository->Get( KDRMSettingsTransactionTracking, value ); |
|
2648 delete repository; |
|
2649 iTransStatus = value ? EAllowed : EForbidden; |
|
2650 } |
|
2651 |
|
2652 // --------------------------------------------------------- |
|
2653 // CRoapEng::CreateDeviceIdHashArrayL() |
|
2654 // --------------------------------------------------------- |
|
2655 // |
|
2656 TInt CRoapEng::CreateDeviceIdHashArrayL( RPointerArray<TDesC8>& aIdArray ) |
|
2657 { |
|
2658 TInt err( KErrNone ); |
|
2659 RPointerArray<HBufC8> certChain; |
|
2660 CSHA1* hasher = NULL; |
|
2661 HBufC8* publicKey = NULL; |
|
2662 CX509Certificate* cert = NULL; |
|
2663 |
|
2664 err = iStorageClient->GetDeviceCertificateChainL( certChain ); |
|
2665 |
|
2666 CleanupResetAndDestroyPushL( certChain ); |
|
2667 |
|
2668 hasher = CSHA1::NewL(); |
|
2669 CleanupStack::PushL( hasher ); |
|
2670 // take the hash of device certificate |
|
2671 if (certChain.Count()<=0) |
|
2672 { |
|
2673 LOGLIT( "Could get Device id Hash!!!" ) |
|
2674 User::Leave( KErrGeneral ); |
|
2675 } |
|
2676 cert = CX509Certificate::NewL( *certChain[0] ); |
|
2677 CleanupStack::PushL( cert ); |
|
2678 publicKey = cert->DataElementEncoding( |
|
2679 CX509Certificate::ESubjectPublicKeyInfo )->AllocLC(); |
|
2680 |
|
2681 hasher->Hash( *publicKey ); |
|
2682 |
|
2683 HBufC8 *elem( hasher->Final().AllocLC() ); |
|
2684 aIdArray.AppendL( elem ); |
|
2685 CleanupStack::Pop( elem ); |
|
2686 |
|
2687 CleanupStack::PopAndDestroy( publicKey ); |
|
2688 CleanupStack::PopAndDestroy( cert ); |
|
2689 |
|
2690 CleanupStack::PopAndDestroy( hasher ); |
|
2691 CleanupStack::PopAndDestroy( &certChain ); |
|
2692 return err; |
|
2693 } |
|
2694 |
|
2695 // End of file |