|
1 /* |
|
2 * Copyright (c) 2007-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: WMDRM Server implementation |
|
15 * |
|
16 */ |
|
17 |
|
18 |
|
19 #include <ezlib.h> |
|
20 #include <e32math.h> |
|
21 #include <symmetric.h> |
|
22 #include <bacntf.h> |
|
23 |
|
24 #include "wmdrmkeystorage.h" |
|
25 #include "slotdatacache.h" |
|
26 #include "clock.h" |
|
27 #include "wmdrmserver.h" |
|
28 #include "drmserviceapiwrapper.h" |
|
29 #include "drmrightsstoringlocation.h" |
|
30 #include "drmutilityinternaltypes.h" |
|
31 |
|
32 #define _LOGGING_FILE L"wmdrmserver.txt" |
|
33 |
|
34 #include "flogger.h" |
|
35 #include "logfn.h" |
|
36 |
|
37 |
|
38 // Constants |
|
39 |
|
40 #if defined(FF_PLATFORM_SIMULATOR) || defined(__WINSCW__) |
|
41 _LIT8( KDummyKey, "0123456789012345" ); |
|
42 #endif |
|
43 |
|
44 _LIT(KDrmServiceApiWrapperName, "drmserviceapiwrapper.dll"); |
|
45 static const TInt KDrmServiceApiWrapperGateOrdinal = 1; |
|
46 |
|
47 //--------------------------------------------------------------------------- |
|
48 // CClock::NewL |
|
49 // Second phase constructor |
|
50 //--------------------------------------------------------------------------- |
|
51 // |
|
52 CClock* CClock::NewL( CWmDrmServer* aServer ) |
|
53 { |
|
54 LOGFN( "CClock::NewL" ); |
|
55 CClock* self = new (ELeave) CClock( aServer ); |
|
56 CleanupStack::PushL( self ); |
|
57 self->ConstructL(); |
|
58 CleanupStack::Pop( self ); |
|
59 return self; |
|
60 } |
|
61 |
|
62 //--------------------------------------------------------------------------- |
|
63 // CClock::CClock |
|
64 // Constructor |
|
65 //--------------------------------------------------------------------------- |
|
66 // |
|
67 CClock::CClock( CWmDrmServer* aServer ): |
|
68 CTimer( -1 ), |
|
69 iTimeIsGood( EFalse ), |
|
70 iServer( aServer ), |
|
71 iServiceApiLoaded( EFalse ), |
|
72 iServiceApi( NULL ) |
|
73 { |
|
74 CActiveScheduler::Add( this ); |
|
75 } |
|
76 |
|
77 //--------------------------------------------------------------------------- |
|
78 // CClock::~CClock |
|
79 // Destructor |
|
80 //--------------------------------------------------------------------------- |
|
81 // |
|
82 CClock::~CClock() |
|
83 { |
|
84 delete iChangeNotifier; |
|
85 delete iServiceApi; |
|
86 iServiceApiLib.Close(); |
|
87 } |
|
88 |
|
89 //--------------------------------------------------------------------------- |
|
90 // CClock::TimeIsGood |
|
91 //--------------------------------------------------------------------------- |
|
92 // |
|
93 TBool CClock::TimeIsGood() |
|
94 { |
|
95 return iTimeIsGood; |
|
96 } |
|
97 |
|
98 //--------------------------------------------------------------------------- |
|
99 // CClock::SetTimeAsGoodL |
|
100 //--------------------------------------------------------------------------- |
|
101 // |
|
102 void CClock::SetTimeAsGoodL( TBool aGood ) |
|
103 { |
|
104 iTimeIsGood = aGood; |
|
105 if ( iTimeIsGood ) |
|
106 { |
|
107 iTime.UniversalTime(); |
|
108 WriteTimeL(); |
|
109 } |
|
110 } |
|
111 |
|
112 //--------------------------------------------------------------------------- |
|
113 // CClock::ConstructL |
|
114 //--------------------------------------------------------------------------- |
|
115 // |
|
116 void CClock::ConstructL() |
|
117 { |
|
118 TInt r = KErrNone; |
|
119 TInt trap = KErrNone; |
|
120 |
|
121 LOGFN( "CClock::ConstructL" ); |
|
122 CTimer::ConstructL(); |
|
123 iChangeNotifier = CEnvironmentChangeNotifier::NewL( EPriorityNormal, |
|
124 TCallBack( CClock::ChangeCallback, this ) ); |
|
125 TRAP( trap, r = ReadTimeL() ); |
|
126 if ( trap != KErrNone || r != KErrNone ) |
|
127 { |
|
128 // Init Change: init to a date prior to the manufacturing date: |
|
129 // 00:00:00:000000 October 2nd, 2007. |
|
130 // iTime.UniversalTime(); |
|
131 iTime = TDateTime(2007,EOctober,1,0,0,0,0); |
|
132 WriteTimeL(); |
|
133 } |
|
134 } |
|
135 |
|
136 //--------------------------------------------------------------------------- |
|
137 // CClock::Start |
|
138 //--------------------------------------------------------------------------- |
|
139 // |
|
140 void CClock::Start() |
|
141 { |
|
142 LOGFN( "CClock::Start" ); |
|
143 After( KClockInterval ); |
|
144 iChangeNotifier->Start(); |
|
145 } |
|
146 |
|
147 //--------------------------------------------------------------------------- |
|
148 // CClock::ChangeCallback |
|
149 //--------------------------------------------------------------------------- |
|
150 // |
|
151 TInt CClock::ChangeCallback( TAny* aClock ) |
|
152 { |
|
153 LOGFN( "CClock::ChangeCallback" ); |
|
154 reinterpret_cast< CClock*>( aClock )->HandleChange(); |
|
155 return KErrNone; |
|
156 } |
|
157 |
|
158 //--------------------------------------------------------------------------- |
|
159 // CClock::EvaluateCurrentTime |
|
160 //--------------------------------------------------------------------------- |
|
161 // |
|
162 void CClock::EvaluateCurrentTime() |
|
163 { |
|
164 TTime time; |
|
165 TTimeIntervalSeconds delta; |
|
166 TDateTime dateTime; |
|
167 |
|
168 LOGFN( "CClock::EvaluateCurrentTime" ); |
|
169 time.UniversalTime(); |
|
170 dateTime = iTime.DateTime(); |
|
171 |
|
172 if( time.Int64() < iTime.Int64() ) |
|
173 { |
|
174 iTimeIsGood = EFalse; |
|
175 LOG1( "Time invalid" ); |
|
176 } |
|
177 else |
|
178 { |
|
179 iTimeIsGood = ETrue; |
|
180 LOG1( "Time valid" ); |
|
181 } |
|
182 } |
|
183 |
|
184 //--------------------------------------------------------------------------- |
|
185 // CClock::ReadTimeL |
|
186 //--------------------------------------------------------------------------- |
|
187 // |
|
188 TInt CClock::ReadTimeL() |
|
189 { |
|
190 RFile file; |
|
191 TBuf8<sizeof( TTime ) + 2 * KAESKeyLength> encryptedData; |
|
192 TBuf8<sizeof( TTime ) + 2 * KAESKeyLength> decryptedData; |
|
193 TBuf8<KAESKeyLength> key; |
|
194 TBuf8<KAESKeyLength> iv; |
|
195 CBufferedDecryptor* decryptor = NULL; |
|
196 CModeCBCDecryptor* cbcDecryptor = NULL; |
|
197 CAESDecryptor* aesDecryptor = NULL; |
|
198 CPaddingPKCS7* padding = NULL; |
|
199 TInt r = KErrNone; |
|
200 TInt size = 0; |
|
201 TDrmScheme drmScheme( EDrmSchemeWmDrm ); |
|
202 TChar driveLetter; |
|
203 TBool wmDrmRightsConfigFound( EFalse ); |
|
204 TFileName timeSaverFile; |
|
205 |
|
206 LOGFNR( "CClock::ReadTimeL", r ); |
|
207 |
|
208 // Check which drive is configured in the Central Repository Key |
|
209 // for the desired storing location of WM DRM rights. Time saver |
|
210 // file should be read from that location, too. |
|
211 wmDrmRightsConfigFound = DrmRightsStoringLocation::CheckDrmRightsStorageDriveL( |
|
212 iServer->Fs(), drmScheme, driveLetter ); |
|
213 |
|
214 if( wmDrmRightsConfigFound ) |
|
215 { |
|
216 LOG1( "ReadTimeL: Rights Config Found" ); |
|
217 } |
|
218 |
|
219 timeSaverFile.Format( KTimeSaverFile, (TUint)driveLetter ); |
|
220 |
|
221 r = file.Open( iServer->Fs(), timeSaverFile, EFileRead ); |
|
222 if ( r == KErrNone ) |
|
223 { |
|
224 CleanupClosePushL( file ); |
|
225 |
|
226 User::LeaveIfError( file.Size( size ) ); |
|
227 |
|
228 if( size != ( 2 * KAESKeyLength ) ) |
|
229 { |
|
230 User::Leave(KErrCorrupt); |
|
231 } |
|
232 |
|
233 User::LeaveIfError( file.Read( iv ) ); |
|
234 User::LeaveIfError( file.Read( encryptedData ) ); |
|
235 #if defined(FF_PLATFORM_SIMULATOR) || defined(__WINSCW__) |
|
236 key.Copy( KDummyKey ); |
|
237 #else |
|
238 iServer->Cache()->iKeyStorage->GetDeviceSpecificKeyL( key ); |
|
239 #endif |
|
240 |
|
241 aesDecryptor = CAESDecryptor::NewL( key ); |
|
242 CleanupStack::PushL( aesDecryptor ); |
|
243 |
|
244 cbcDecryptor = CModeCBCDecryptor::NewL( aesDecryptor, iv ); |
|
245 CleanupStack::Pop( aesDecryptor ); |
|
246 CleanupStack::PushL( cbcDecryptor ); |
|
247 |
|
248 padding = CPaddingPKCS7::NewL( KAESKeyLength ); |
|
249 CleanupStack::PushL( padding ); |
|
250 |
|
251 decryptor = CBufferedDecryptor::NewL( cbcDecryptor, padding ); |
|
252 CleanupStack::Pop( 2, cbcDecryptor ); //padding, cbcDecryptor |
|
253 CleanupStack::PushL( decryptor ); |
|
254 |
|
255 decryptor->ProcessFinalL( encryptedData, decryptedData ); |
|
256 TPtr8 ptr( reinterpret_cast<TUint8*>( &iTime ), sizeof( iTime ) ); |
|
257 ptr.Copy( decryptedData.Left( sizeof( TTime ) ) ); |
|
258 EvaluateCurrentTime(); |
|
259 CleanupStack::PopAndDestroy( 2, &file ); //decryptor, file |
|
260 } |
|
261 return r; |
|
262 } |
|
263 |
|
264 //--------------------------------------------------------------------------- |
|
265 // CClock::WriteTimeL |
|
266 //--------------------------------------------------------------------------- |
|
267 // |
|
268 TInt CClock::WriteTimeL() |
|
269 { |
|
270 RFile file; |
|
271 TBuf8<sizeof( TTime ) + 2 * KAESKeyLength> encryptedData; |
|
272 TBuf8<sizeof( TTime ) + 2 * KAESKeyLength> decryptedData; |
|
273 TBuf8<KAESKeyLength> key; |
|
274 TBuf8<KAESKeyLength> iv; |
|
275 CBufferedEncryptor* encryptor = NULL; |
|
276 CModeCBCEncryptor* cbcEncryptor = NULL; |
|
277 CAESEncryptor* aesEncryptor = NULL; |
|
278 CPaddingPKCS7* padding = NULL; |
|
279 TInt r = KErrNone; |
|
280 TInt pos = 0; |
|
281 TDrmScheme drmScheme( EDrmSchemeWmDrm ); |
|
282 TChar driveLetter; |
|
283 TBool wmDrmRightsConfigFound( EFalse ); |
|
284 TFileName tempFile; |
|
285 |
|
286 LOGFNR( "CClock::WriteTime", r ); |
|
287 |
|
288 // Check which drive is configured in the Central Repository Key |
|
289 // for the desired storing location of WM DRM rights. Time saver |
|
290 // file should be stored to that location, too. |
|
291 wmDrmRightsConfigFound = DrmRightsStoringLocation::CheckDrmRightsStorageDriveL( |
|
292 iServer->Fs(), drmScheme, driveLetter ); |
|
293 |
|
294 if( wmDrmRightsConfigFound ) |
|
295 { |
|
296 LOG1( "WriteTimeL: Rights Config Found" ); |
|
297 } |
|
298 |
|
299 tempFile.Format( KPrivateDir, (TUint)driveLetter ); |
|
300 iServer->Fs().MkDirAll( tempFile ); |
|
301 |
|
302 tempFile.Format( KTimeSaverFile, (TUint)driveLetter ); |
|
303 User::LeaveIfError( file.Replace( iServer->Fs(), tempFile, EFileRead | EFileWrite ) ); |
|
304 CleanupClosePushL( file ); |
|
305 |
|
306 iv.SetLength( KAESKeyLength ); |
|
307 TRandom::RandomL( iv ); |
|
308 #if defined(FF_PLATFORM_SIMULATOR) || defined(__WINSCW__) |
|
309 key.Copy( KDummyKey ); |
|
310 #else |
|
311 iServer->Cache()->iKeyStorage->GetDeviceSpecificKeyL( key ); |
|
312 #endif |
|
313 aesEncryptor = CAESEncryptor::NewL( key ); |
|
314 CleanupStack::PushL( aesEncryptor ); |
|
315 |
|
316 cbcEncryptor = CModeCBCEncryptor::NewL( aesEncryptor, iv ); |
|
317 CleanupStack::Pop( aesEncryptor ); |
|
318 CleanupStack::PushL( cbcEncryptor ); |
|
319 |
|
320 padding = CPaddingPKCS7::NewL( KAESKeyLength ); |
|
321 CleanupStack::PushL( padding ); |
|
322 |
|
323 encryptor = CBufferedEncryptor::NewL( cbcEncryptor, padding ); |
|
324 CleanupStack::Pop( 2, cbcEncryptor ); //padding, cbcEncryptor |
|
325 CleanupStack::PushL( encryptor ); |
|
326 |
|
327 TPtr8 ptr( reinterpret_cast<TUint8*>( &iTime ), sizeof( iTime ), sizeof( iTime ) ); |
|
328 decryptedData.Copy( ptr.Left( sizeof( TTime ) ) ); |
|
329 encryptor->ProcessFinalL( decryptedData, encryptedData ); |
|
330 User::LeaveIfError( file.Seek( ESeekStart, pos ) ); |
|
331 User::LeaveIfError( file.SetSize( 0 ) ); |
|
332 User::LeaveIfError( file.Write( iv ) ); |
|
333 User::LeaveIfError( file.Write( encryptedData ) ); |
|
334 iTimeIsGood = ETrue; |
|
335 CleanupStack::PopAndDestroy( 2, &file ); //encryptor, file |
|
336 return r; |
|
337 } |
|
338 |
|
339 //--------------------------------------------------------------------------- |
|
340 // CClock::HandleChange |
|
341 //--------------------------------------------------------------------------- |
|
342 // |
|
343 void CClock::HandleChange() |
|
344 { |
|
345 TInt change; |
|
346 |
|
347 LOGFN( "CClock::HandleChange" ); |
|
348 change = iChangeNotifier->Change(); |
|
349 LOG2( "Change: %d", change ); |
|
350 if ( ( change & EChangesSystemTime ) ) |
|
351 { |
|
352 EvaluateCurrentTime(); |
|
353 if ( iTimeIsGood ) |
|
354 { |
|
355 iTime.UniversalTime(); |
|
356 TRAP_IGNORE( WriteTimeL() ); |
|
357 } |
|
358 } |
|
359 } |
|
360 |
|
361 |
|
362 //--------------------------------------------------------------------------- |
|
363 // CClock::LoadServiceApi |
|
364 //--------------------------------------------------------------------------- |
|
365 // |
|
366 TInt CClock::LoadServiceApi() |
|
367 { |
|
368 #ifdef __DRM_CLOCK |
|
369 TInt err = KErrNone; |
|
370 |
|
371 if( !iServiceApiLoaded ) |
|
372 { |
|
373 err = iServiceApiLib.Load( KDrmServiceApiWrapperName ); |
|
374 if( err ) |
|
375 { |
|
376 iServiceApiLoaded = EFalse; |
|
377 return err; |
|
378 } |
|
379 iServiceApiLoaded = ETrue; |
|
380 } |
|
381 |
|
382 if( !iServiceApi ) |
|
383 { |
|
384 TLibraryFunction function = iServiceApiLib.Lookup( KDrmServiceApiWrapperGateOrdinal ); |
|
385 if( function ) |
|
386 { |
|
387 iServiceApi = reinterpret_cast<DRM::CDrmServiceApiWrapper*>( function() ); |
|
388 if( !iServiceApi ) |
|
389 { |
|
390 iServiceApi = NULL; |
|
391 return KErrGeneral; |
|
392 } |
|
393 } |
|
394 else |
|
395 { |
|
396 return KErrNotFound; |
|
397 } |
|
398 } |
|
399 #endif |
|
400 return KErrNone; |
|
401 } |
|
402 |
|
403 //---------------------------------------------------------------------------- |
|
404 // CClock::GetTimeL |
|
405 // This function gets the time from DRM Clock checks the validity and |
|
406 // then returns this information |
|
407 // flagged for use with DRM Clock, if clock is not there, use the old implementation |
|
408 //---------------------------------------------------------------------------- |
|
409 // |
|
410 void CClock::GetTimeL( TTime& aTime, TBool& aValid ) |
|
411 { |
|
412 TInt timeZone = 0; |
|
413 |
|
414 #ifdef __DRM_CLOCK |
|
415 |
|
416 DRMClock::ESecurityLevel secLevel; |
|
417 |
|
418 // If it's already loaded then this just returns KErrNone |
|
419 User::LeaveIfError( LoadServiceApi() ); |
|
420 |
|
421 User::LeaveIfError( iServiceApi->GetSecureTime( aTime, timeZone, secLevel ) ); |
|
422 |
|
423 if( secLevel == DRMClock::KSecure ) |
|
424 { |
|
425 aValid = ETrue; |
|
426 } |
|
427 else |
|
428 { |
|
429 aValid = EFalse; |
|
430 } |
|
431 #else |
|
432 aTime.UniversalTime(); |
|
433 aValid = EFalse; |
|
434 #endif |
|
435 } |
|
436 |
|
437 //---------------------------------------------------------------------------- |
|
438 // CClock::RunL |
|
439 //---------------------------------------------------------------------------- |
|
440 // |
|
441 void CClock::RunL() |
|
442 { |
|
443 LOGFN( "CClock::RunL" ); |
|
444 LOG2( "Status: %d", iStatus.Int() ); |
|
445 EvaluateCurrentTime(); |
|
446 if ( iTimeIsGood ) |
|
447 { |
|
448 iTime.UniversalTime(); |
|
449 TRAP_IGNORE( WriteTimeL() ); |
|
450 } |
|
451 After( KClockInterval ); |
|
452 } |