|
1 /* |
|
2 * Copyright (c) 2007 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 #include <random.h> |
|
24 |
|
25 #include "wmdrmkeystorage.h" |
|
26 #include "slotdata.h" |
|
27 #include "wmdrmserver.h" |
|
28 #include "slotdatacache.h" |
|
29 #include "slotenumeratorcache.h" |
|
30 #include "wmdrmdb.h" |
|
31 |
|
32 #define _LOGGING_FILE L"wmdrmserver.txt" |
|
33 |
|
34 #include "flogger.h" |
|
35 #include "logfn.h" |
|
36 |
|
37 #ifdef __WINSCW__ |
|
38 _LIT8( KDummyKey, "0123456789012345" ); |
|
39 #endif |
|
40 |
|
41 CSlotData* CSlotData::NewL( |
|
42 CWmDrmServer* aServer, |
|
43 const TDesC8& aStore, |
|
44 const TDesC8& aNamespace, |
|
45 const TDesC8& aHashKey, |
|
46 const TDesC8& aUniqueKey ) |
|
47 { |
|
48 LOGFN( "CSlotData::NewL" ); |
|
49 CSlotData* self = new (ELeave) CSlotData( aServer, |
|
50 aStore, |
|
51 aNamespace, |
|
52 aHashKey, |
|
53 aUniqueKey ); |
|
54 return self; |
|
55 } |
|
56 |
|
57 CSlotData::CSlotData( |
|
58 CWmDrmServer* aServer, |
|
59 const TDesC8& aStore, |
|
60 const TDesC8& aNamespace, |
|
61 const TDesC8& aHashKey, |
|
62 const TDesC8& aUniqueKey ) : iServer( aServer ), |
|
63 iDirty( EFalse ), |
|
64 iExists( ETrue ), |
|
65 iReferences( 0 ) |
|
66 { |
|
67 LOGFN( "CSlotData::CSlotData" ); |
|
68 iStore.Copy( aStore ); |
|
69 iNamespace.Copy( aNamespace ); |
|
70 LOG( iNamespace ); |
|
71 iHashKey.Copy( aHashKey ); |
|
72 LOG( iHashKey ); |
|
73 iUniqueKey.Copy( aUniqueKey ); |
|
74 LOG( iUniqueKey ); |
|
75 } |
|
76 |
|
77 CSlotData::~CSlotData() |
|
78 { |
|
79 LOGFN( "CSlotData::~CSlotData" ); |
|
80 //FlushL(); |
|
81 iData.Close(); |
|
82 } |
|
83 |
|
84 void CSlotData::CreateL( TInt& aInitialSize ) |
|
85 { |
|
86 LOGFN( "CSlotData::CreateL" ); |
|
87 LOG2( "Size: %d", aInitialSize ); |
|
88 LOG1( "*** Create record" ); |
|
89 if ( aInitialSize > KMaxSlotSize ) |
|
90 { |
|
91 User::Leave( KErrArgument ); |
|
92 } |
|
93 iServer->Db()->CreateRecordL( iStore, iNamespace, iHashKey, iUniqueKey, aInitialSize ); |
|
94 iData.Close(); |
|
95 iData.CreateL( aInitialSize ); |
|
96 iData.SetLength( iData.MaxLength() ); |
|
97 iData.FillZ(); |
|
98 iDirty = ETrue; |
|
99 iExists = ETrue; |
|
100 iOpen = ETrue; |
|
101 iServer->EnumeratorCache()->AddEntryL( iStore, iNamespace, iHashKey, iUniqueKey ); |
|
102 //FlushL(); |
|
103 } |
|
104 |
|
105 TInt CSlotData::OpenL( TInt& aCurrentSize ) |
|
106 { |
|
107 TInt r = KErrNone; |
|
108 RBuf8 compressedData; |
|
109 TUint32 uncompressedSize; |
|
110 TPckg<TUint32> pckg( uncompressedSize ); |
|
111 RBuf8 encryptedData; |
|
112 CBufferedDecryptor* decryptor = NULL; |
|
113 CModeCBCDecryptor* cbcDecryptor = NULL; |
|
114 CAESDecryptor* aesDecryptor = NULL; |
|
115 CPaddingPKCS7* padding = NULL; |
|
116 TInt size; |
|
117 |
|
118 LOGFN( "CSlotData::OpenL" ); |
|
119 LOG3( "Size: %d, data size: %d", aCurrentSize, iData.Length() ); |
|
120 if ( !IsOpen() ) |
|
121 { |
|
122 if ( iExists ) |
|
123 { |
|
124 LOG1( "*** Opening record" ); |
|
125 TRAP( r, iServer->Db()->ReadRecordL( iStore, iNamespace, iHashKey, iUniqueKey ) ); |
|
126 if ( !r ) |
|
127 { |
|
128 TBuf8<KAESKeyLength> key; |
|
129 TBuf8<KAESKeyLength> iv; |
|
130 RBuf8 buffer; |
|
131 |
|
132 iServer->Db()->GetDataSizeL( size ); |
|
133 LOG2( "Record size: %d", size ); |
|
134 if( size <= 0 ) |
|
135 { |
|
136 iServer->Db()->DeleteData(); |
|
137 iServer->Db()->DeleteRecordL( iStore, iNamespace, iHashKey, iUniqueKey ); |
|
138 User::Leave( KErrArgument ); |
|
139 } |
|
140 |
|
141 encryptedData.CreateL( size - sizeof( TUint32 ) - KAESKeyLength ); |
|
142 encryptedData.CleanupClosePushL(); |
|
143 |
|
144 compressedData.CreateL( size - sizeof( TUint32 ) - KAESKeyLength ); |
|
145 compressedData.CleanupClosePushL(); |
|
146 |
|
147 |
|
148 buffer.CreateL( size ); |
|
149 buffer.CleanupClosePushL(); |
|
150 iServer->Db()->ReadDataL( buffer ); |
|
151 //LOGHEX( buffer.Ptr(), buffer.Size() ); |
|
152 pckg.Copy( buffer.Left( sizeof( TUint32 ) ) ); |
|
153 LOG2( "Uncompressed size: %d", uncompressedSize ); |
|
154 iv.Copy( buffer.Mid ( sizeof( TUint32 ), KAESKeyLength ) ); |
|
155 //LOGHEX( iv.Ptr(), iv.Size () ); |
|
156 encryptedData.Copy( buffer.Right( size - sizeof( TUint32 ) - KAESKeyLength ) ); |
|
157 //LOGHEX( encryptedData.Ptr(), encryptedData.Size() ); |
|
158 #ifdef __WINSCW__ |
|
159 key.Copy( KDummyKey ); |
|
160 #else |
|
161 iServer->Cache()->iKeyStorage->GetDeviceSpecificKeyL( key ); |
|
162 #endif |
|
163 aesDecryptor = CAESDecryptor::NewL( key ); |
|
164 CleanupStack::PushL( aesDecryptor ); |
|
165 |
|
166 cbcDecryptor = CModeCBCDecryptor::NewL( aesDecryptor, iv ); |
|
167 CleanupStack::Pop( aesDecryptor ); |
|
168 CleanupStack::PushL( cbcDecryptor ); |
|
169 |
|
170 padding = CPaddingPKCS7::NewL( KAESKeyLength ); |
|
171 CleanupStack::PushL( padding ); |
|
172 |
|
173 decryptor = CBufferedDecryptor::NewL( cbcDecryptor, padding ); |
|
174 CleanupStack::Pop( 2, cbcDecryptor ); //padding, cbcDecryptor |
|
175 CleanupStack::PushL( decryptor ); |
|
176 |
|
177 decryptor->ProcessFinalL( encryptedData, compressedData ); |
|
178 |
|
179 iData.Close(); |
|
180 iData.CreateMaxL( uncompressedSize ); |
|
181 User::LeaveIfError( uncompress( const_cast<TUint8*>( iData.Ptr() ), &uncompressedSize, |
|
182 compressedData.Ptr(), compressedData.Size() ) ); |
|
183 CleanupStack::PopAndDestroy( 4, &encryptedData ); //decryptor, buffer, compressedData, encryptedData |
|
184 TRandom::RandomL( key ); |
|
185 iOpen = ETrue; |
|
186 } |
|
187 else |
|
188 { |
|
189 iExists = EFalse; |
|
190 if ( r == KErrPathNotFound ) |
|
191 { |
|
192 r = KErrNotFound; |
|
193 } |
|
194 } |
|
195 } |
|
196 else |
|
197 { |
|
198 r = KErrNotFound; |
|
199 } |
|
200 } |
|
201 else |
|
202 { |
|
203 LOG1( "Record already open" ); |
|
204 } |
|
205 aCurrentSize = iData.Length(); |
|
206 |
|
207 return r; |
|
208 } |
|
209 |
|
210 TInt CSlotData::Read( TInt aPosition, TDes8& aBuffer ) |
|
211 { |
|
212 TInt r = KErrNone; |
|
213 TInt length; |
|
214 |
|
215 LOGFNR( "CSlotData::Read", r ); |
|
216 if ( IsOpen() ) |
|
217 { |
|
218 length = Min( aBuffer.MaxLength(), iData.Length() - aPosition ); |
|
219 LOG4( "Read %d bytes from %d, buffer size: %d", length, aPosition, aBuffer.MaxLength() ); |
|
220 aBuffer.Copy( iData.Mid( aPosition, length ) ); |
|
221 // LOGHEX( aBuffer.Ptr(), aBuffer.Size() ); |
|
222 } |
|
223 else |
|
224 { |
|
225 r = KErrNotReady; |
|
226 iServer->Cache()->Release( this ); |
|
227 } |
|
228 return r; |
|
229 } |
|
230 |
|
231 TInt CSlotData::WriteL( TInt aPosition, const TDesC8& aBuffer ) |
|
232 { |
|
233 TInt r = KErrNone; |
|
234 |
|
235 LOGFNR( "CSlotData::Write", r ); |
|
236 if ( IsOpen() ) |
|
237 { |
|
238 LOG3( "Write %d bytes at %d", aBuffer.Length(), aPosition ); |
|
239 // LOGHEX( aBuffer.Ptr(), aBuffer.Size() ); |
|
240 if ( aBuffer.Length() + aPosition > iData.Length() ) |
|
241 { |
|
242 iData.ReAllocL( aBuffer.Length() + aPosition ); |
|
243 iData.SetLength( iData.MaxLength() ); |
|
244 } |
|
245 iData.Replace( aPosition, aBuffer.Length(), aBuffer ); |
|
246 iDirty = ETrue; |
|
247 FlushL(); |
|
248 } |
|
249 else |
|
250 { |
|
251 r = KErrNotReady; |
|
252 iServer->Cache()->Release( this ); |
|
253 } |
|
254 return r; |
|
255 } |
|
256 |
|
257 TInt CSlotData::ResizeL( TInt aNewSize ) |
|
258 { |
|
259 TInt r = KErrNone; |
|
260 |
|
261 LOGFNR( "CSlotData::Resize", r ); |
|
262 if ( IsOpen() ) |
|
263 { |
|
264 LOG2( "New size: %d", aNewSize ); |
|
265 if ( aNewSize > iData.Size() ) |
|
266 { |
|
267 iData.ReAllocL( aNewSize ); |
|
268 } |
|
269 iData.SetLength( aNewSize ); |
|
270 } |
|
271 else |
|
272 { |
|
273 r = KErrNotReady; |
|
274 iServer->Cache()->Release( this ); |
|
275 } |
|
276 return r; |
|
277 } |
|
278 |
|
279 TInt CSlotData::DeleteL() |
|
280 { |
|
281 TInt r = KErrNone; |
|
282 |
|
283 LOGFNR( "CSlotData::Delete", r ); |
|
284 iServer->EnumeratorCache()->DeleteEntryL( iStore, iNamespace, iHashKey, iUniqueKey ); |
|
285 r = iServer->Cache()->Delete( this ); |
|
286 return r; |
|
287 } |
|
288 |
|
289 TInt CSlotData::Size() |
|
290 { |
|
291 TInt r; |
|
292 |
|
293 LOGFNR( "CSlotData::Size", r ); |
|
294 if ( IsOpen() ) |
|
295 { |
|
296 r = iData.Length(); |
|
297 } |
|
298 else |
|
299 { |
|
300 r = KErrNotReady; |
|
301 iServer->Cache()->Release( this ); |
|
302 } |
|
303 return r; |
|
304 } |
|
305 |
|
306 void CSlotData::Close() |
|
307 { |
|
308 LOGFN( "CSlotData::Close" ); |
|
309 iServer->Cache()->Release( this ); |
|
310 } |
|
311 |
|
312 void CSlotData::CloseFile() |
|
313 { |
|
314 LOGFN( "CSlotData::CloseFile" ); |
|
315 iOpen = EFalse; |
|
316 } |
|
317 |
|
318 void CSlotData::FlushL() |
|
319 { |
|
320 LOGFN( "CSlotData::FlushL" ); |
|
321 __UHEAP_MARK; |
|
322 if ( IsOpen() && iDirty ) |
|
323 { |
|
324 TBuf8<KAESKeyLength> iv; |
|
325 TBuf8<KAESKeyLength> key; |
|
326 TInt size = iData.Size(); |
|
327 RBuf8 compressedData; |
|
328 TUint32 compressedDataLen = size + size / 10 + 12; |
|
329 TUint8* compressedDataPtr; |
|
330 RBuf8 encryptedData; |
|
331 CBufferedEncryptor* encryptor = NULL; |
|
332 CModeCBCEncryptor* cbcEncryptor = NULL; |
|
333 CAESEncryptor* aesEncryptor = NULL; |
|
334 CPaddingPKCS7* padding = NULL; |
|
335 RBuf8 buffer; |
|
336 |
|
337 compressedData.CreateL( compressedDataLen ); |
|
338 compressedData.CleanupClosePushL(); |
|
339 compressedDataPtr = const_cast<TUint8*>( compressedData.Ptr() ); |
|
340 User::LeaveIfError( compress( compressedDataPtr, &compressedDataLen, iData.Ptr(), size ) ); |
|
341 compressedData.SetLength( compressedDataLen ); |
|
342 |
|
343 encryptedData.CreateL( compressedData.Size() + 2 * KAESKeyLength ); |
|
344 encryptedData.CleanupClosePushL(); |
|
345 |
|
346 iv.SetLength( KAESKeyLength ); |
|
347 TRandom::RandomL( iv ); |
|
348 #ifdef __WINSCW__ |
|
349 key.Copy( KDummyKey ); |
|
350 #else |
|
351 iServer->Cache()->iKeyStorage->GetDeviceSpecificKeyL( key ); |
|
352 #endif |
|
353 aesEncryptor = CAESEncryptor::NewL( key ); |
|
354 CleanupStack::PushL( aesEncryptor ); |
|
355 |
|
356 cbcEncryptor = CModeCBCEncryptor::NewL( aesEncryptor, iv ); |
|
357 CleanupStack::Pop( aesEncryptor ); |
|
358 CleanupStack::PushL( cbcEncryptor ); |
|
359 |
|
360 padding = CPaddingPKCS7::NewL( KAESKeyLength ); |
|
361 CleanupStack::PushL( padding ); |
|
362 |
|
363 encryptor = CBufferedEncryptor::NewL( cbcEncryptor, padding ); |
|
364 CleanupStack::Pop( 2, cbcEncryptor ); //padding, cbcEncryptor |
|
365 CleanupStack::PushL( encryptor ); |
|
366 |
|
367 encryptor->ProcessFinalL( compressedData, encryptedData ); |
|
368 |
|
369 LOG1( "*** Write record" ); |
|
370 LOG3( "Uncompressed size: %d, compresseded size: %d", size, encryptedData.Size() ); |
|
371 buffer.CreateL( sizeof( TUint32 ) + iv.Size() + encryptedData.Size() ); |
|
372 buffer.CleanupClosePushL(); |
|
373 buffer.Append( TPckgC<TUint32>( size ) ); |
|
374 buffer.Append( iv ); |
|
375 buffer.Append( encryptedData ); |
|
376 //LOGHEX( buffer.Ptr(), buffer.Size() ); |
|
377 |
|
378 iServer->Db()->WriteDataL( iStore, iNamespace, iHashKey, iUniqueKey, buffer ); |
|
379 iDirty = EFalse; |
|
380 TRandom::RandomL( key ); |
|
381 CleanupStack::PopAndDestroy( 4, &compressedData ); //buffer, encryptor, encryptedData, compressedData |
|
382 } |
|
383 __UHEAP_MARKEND; |
|
384 } |
|
385 |
|
386 TBool CSlotData::IsOpen() |
|
387 { |
|
388 return iOpen; |
|
389 } |
|
390 |