e1a5a5709e819ed8bcd666130bd0a4e2f7d3f8c6
[platform/core/security/drm-service-core-tizen.git] / tadcore / DrmFileHandleMgr / DrmFileHandler.cpp
1 /*
2  * Copyright (c) 2000-2015 Samsung Electronics Co., Ltd.
3  *
4  * Licensed under the Flora License, Version 1.1 (the License);
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://floralicense.org/license/
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an AS IS BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #include "TADC_Core.h"
18 #include "TADC_ErrorCode.h"
19 #include "DTapps2Rights.h"
20 #include "DrmFileHandler.h"
21 #include "TADC_IF.h"
22
23
24
25
26 #define TDC_DECRYPT_BLOCKSIZE   512
27
28 DrmFileHandler::DrmFileHandler(void)
29         : m_pFilePath(NULL)
30         , m_pCID(NULL)
31         , m_pCEK(NULL)
32         , m_pFP(NULL)
33 {
34 }
35
36 DrmFileHandler::~DrmFileHandler(void)
37 {
38         if (m_pFilePath != NULL)
39         {
40                 delete[] m_pFilePath;
41         }
42
43         if (m_pCID != NULL)
44         {
45                 delete[] m_pCID;
46         }
47
48         if (m_pCEK != NULL)
49         {
50                 delete[] m_pCEK;
51         }
52
53         if (m_pDecBuf != NULL)
54         {
55                 delete[] m_pDecBuf;
56         }
57
58         if (m_pFP != NULL)
59         {
60                 fclose(m_pFP);
61         }
62 }
63
64 int DrmFileHandler::Construct(const char* szDrmFilePath)
65 {
66         T_FILE_HEADER    t_FileHeader;
67         T_DRM_HEADER     t_DRMHeader;
68         T_RO                     t_RO;
69
70         int ret = TADC_SUCCESS;
71         bool bRet = true;
72
73         // 1. Check the file is TADC DRM file.
74         memset(&t_FileHeader, 0x00, sizeof(t_FileHeader));
75         memset(&t_DRMHeader, 0x00, sizeof(T_DRM_HEADER));
76         memset(&t_RO, 0x00, sizeof(T_RO));
77
78         DRM_TAPPS_LOG("%s starts", __func__);
79
80         if (szDrmFilePath == NULL)
81         {
82                 DRM_TAPPS_EXCEPTION("Parameters NULL!");
83                 ret = TADC_PARAMETER_ERROR;
84
85                 goto finish;
86         }
87
88         ret = TADC_GetDRMHeaderFromFile(szDrmFilePath, &t_FileHeader, &t_DRMHeader);
89
90         if (ret < 0)
91         {
92                 DRM_TAPPS_EXCEPTION("Error : TADC_GetDRMHeaderFromFile() - %s TADC Error Code - %d", szDrmFilePath, ret);
93                 ret = TADC_NOTTADCFILE_ERROR;
94
95                 goto finish;
96         }
97
98         // 2. Validate license and get the CEK for the DRM file
99         bRet = DTappsGetCEK((char*)t_DRMHeader.CID, &t_RO);
100         if (bRet == false)
101         {
102                 DRM_TAPPS_EXCEPTION("Error : DTappsGetCEK() - %s", t_DRMHeader.CID);
103                 ret = TADC_GET_CEK_ERROR;
104
105                 goto finish;
106         }
107
108         // 3. Setting the member variable
109         m_pFilePath = new unsigned char[strlen(szDrmFilePath) + 1];
110         memset(m_pFilePath, 0x00, strlen(szDrmFilePath) + 1);
111         memcpy(m_pFilePath, szDrmFilePath, strlen(szDrmFilePath));
112
113         m_pCID = new unsigned char[strlen((char*)t_DRMHeader.CID) + 1];
114         memset(m_pCID, 0x00, strlen((char*)t_DRMHeader.CID) + 1);
115         memcpy(m_pCID, t_DRMHeader.CID, strlen((char*)t_DRMHeader.CID));
116
117         m_pCEK = new unsigned char[CEK_SIZE + 1];
118         memset(m_pCEK, 0x00, CEK_SIZE + 1);
119         memcpy(m_pCEK, t_RO.t_Content.CEK, CEK_SIZE);
120
121         m_encryptionLevel = t_DRMHeader.EncryptionLevel;
122         m_encryptionRange = t_DRMHeader.EncryptionRange;
123         m_plaintextSize = t_DRMHeader.PlaintextSize;
124
125         // 4. Open the DRM file and set the filepointer to member variable
126         m_pFP = fopen(szDrmFilePath, "rb");
127         if (m_pFP == NULL)
128         {
129                 DRM_TAPPS_EXCEPTION("Error : fopen() - %s", szDrmFilePath);
130                 ret = TADC_FILE_OPEN_ERROR;
131
132                 goto finish;
133         }
134
135         m_PlaintextStartOffset = t_FileHeader.Offset1 + 35 + t_DRMHeader.XmlSize;
136
137         fseek(m_pFP, 0, SEEK_END);
138         m_OriginEndOffset = ftell(m_pFP);
139
140         m_plaintextSize = m_OriginEndOffset - m_PlaintextStartOffset;
141         if (m_plaintextSize != t_DRMHeader.PlaintextSize)
142         {
143                 DRM_TAPPS_EXCEPTION("Error : plaintext file size incorrect. real = %ld, header = %ld", m_plaintextSize, t_DRMHeader.PlaintextSize);
144                 ret = TADC_FILE_OPEN_ERROR;
145
146                 goto finish;
147         }
148
149         m_DrmEndOffset = m_plaintextSize;
150
151         fseek(m_pFP, m_PlaintextStartOffset, SEEK_SET);
152         m_OriginCurOffset = ftell(m_pFP);
153         m_DrmCurOffset = 0;
154
155         m_blockCnt = (m_plaintextSize / 512) + ((m_plaintextSize % 512) ? 1 : 0);
156
157         m_curBlockIndex = 0;
158         m_decReadlen = 0;
159
160         DRM_TAPPS_LOG("m_pCEK = %s", m_pCEK);
161         DRM_TAPPS_LOG("m_pCID = %s", m_pCID);
162         DRM_TAPPS_LOG("m_pFilePath = %s", m_pFilePath);
163
164         DRM_TAPPS_LOG("m_encryptionLevel = %ld", m_encryptionLevel);
165         DRM_TAPPS_LOG("m_encryptionRange = %ld", m_encryptionRange);
166         DRM_TAPPS_LOG("m_plaintextSize = %ld", m_plaintextSize);
167
168         DRM_TAPPS_LOG("m_PlaintextStartOffset = %ld", m_PlaintextStartOffset);
169         DRM_TAPPS_LOG("m_OriginEndOffset = %ld", m_OriginEndOffset);
170
171         DRM_TAPPS_LOG("m_OriginCurOffset = %ld", m_OriginCurOffset);
172         DRM_TAPPS_LOG("m_DrmCurOffset = %ld", m_DrmCurOffset);
173         DRM_TAPPS_LOG("m_DrmEndOffset = %ld", m_DrmEndOffset);
174
175         DRM_TAPPS_LOG("m_blockCnt = %ld", m_blockCnt);
176         DRM_TAPPS_LOG("m_curBlockIndex = %ld", m_curBlockIndex);
177
178         DrmDecryptBlocks();
179
180         return TADC_SUCCESS;
181
182 finish:
183         TADC_MEMFree_FileHeader(&t_FileHeader);
184         TADC_MEMFree_DRMHeader(&t_DRMHeader);
185         TADC_MEMFree_RO(&t_RO);
186
187         return ret;
188 }
189
190 int DrmFileHandler::DrmSeek(long long offset, int origin)
191 {
192         int nRet = TADC_SUCCESS;
193         long long OriginOffset = 0;
194         long long DrmOffset = 0;
195         long long temp = 0;
196
197         m_decReadlen = 0;
198
199         if (origin == SEEK_SET)
200         {
201                 DrmOffset = offset;
202                 if (DrmOffset < 0 || DrmOffset > m_plaintextSize)
203                 {
204                         DRM_TAPPS_EXCEPTION("Parameter Wrong! Offset can not be minus. offset=%lld, m_OriginCurOffset=%lld, m_plaintextSize=%lld", offset, m_OriginCurOffset, m_plaintextSize);
205                         return TADC_PARAMETER_ERROR;
206                 }
207
208                 OriginOffset = m_PlaintextStartOffset + DrmOffset;
209                 if (fseek(m_pFP, OriginOffset, SEEK_SET) != 0)
210                 {
211                         DRM_TAPPS_EXCEPTION("fseek failed.");
212                         return TADC_FILE_READ_ERROR;
213                 }
214
215                 m_OriginCurOffset = OriginOffset;
216                 m_DrmCurOffset = DrmOffset;
217         }
218         else if (origin == SEEK_CUR)
219         {
220                 temp = m_OriginCurOffset;
221
222                 if (temp == -1)
223                 {
224                         DRM_TAPPS_EXCEPTION("GetOriginCurOffset() failed.");
225                         return TADC_FILE_READ_ERROR;
226                 }
227
228                 OriginOffset = temp + offset;
229                 DrmOffset = OriginOffset - m_PlaintextStartOffset;
230
231                 if (DrmOffset < 0 || DrmOffset > m_plaintextSize)
232                 {
233                         DRM_TAPPS_EXCEPTION("Parameter Wrong! Offset can not be minus. offset=%lld, m_OriginCurOffset=%lld, OriginOffset=%lld, DrmOffset=%lld, m_plaintextSize=%lld", offset, temp, OriginOffset, DrmOffset, m_plaintextSize);
234                         return TADC_PARAMETER_ERROR;
235                 }
236
237                 if (fseek(m_pFP, OriginOffset, SEEK_SET) != 0)
238                 {
239                         DRM_TAPPS_EXCEPTION("fseek failed.");
240                         return TADC_FILE_READ_ERROR;
241                 }
242
243                 m_OriginCurOffset = OriginOffset;
244                 m_DrmCurOffset = DrmOffset;
245         }
246         else if (origin == SEEK_END)
247         {
248                 OriginOffset = m_OriginEndOffset + offset;
249                 if (fseek(m_pFP, OriginOffset, SEEK_SET) != 0)
250                 {
251                         DRM_TAPPS_EXCEPTION("fseek failed.");
252                         return TADC_FILE_READ_ERROR;
253                 }
254
255                 DrmOffset = OriginOffset - m_PlaintextStartOffset;
256                 if (DrmOffset < 0 || DrmOffset > m_plaintextSize)
257                 {
258                         DRM_TAPPS_EXCEPTION("Parameter Wrong! Offset can not be minus. offset=%lld, m_OriginCurOffset=%lld, OriginOffset=%lld, DrmOffset=%lld, m_plaintextSize=%lld", offset, temp, OriginOffset, DrmOffset, m_plaintextSize);
259                         return TADC_PARAMETER_ERROR;
260                 }
261
262                 m_OriginCurOffset = OriginOffset;
263                 m_DrmCurOffset = DrmOffset;
264         }
265         else
266         {
267                 DRM_TAPPS_EXCEPTION("Parameter Wrong!");
268                 return TADC_PARAMETER_ERROR;
269         }
270
271         return nRet;
272 }
273
274 long long DrmFileHandler::DrmTell(void)
275 {
276         return m_DrmCurOffset;
277 //      return GetDrmCurOffset();
278 }
279
280 int DrmFileHandler::DrmDecryptBlocks(void)
281 {
282
283         bool bRet = true;
284         int ret = TADC_SUCCESS;
285         const char* packagePath = (const char*)m_pFilePath;
286         long long EncBlockCnt = 0;
287         T_FILE_HEADER    t_FileHeader;
288         T_DRM_HEADER     t_DRMHeader;
289         T_DEVICE_INFO    t_DeviceInfo;
290         T_RO    t_RO;
291         DrmTdcFileHeader fileHeader;
292
293         ULONG DecLen = 0;
294         ULONG ReadLen = 0;
295         ULONG k = 0, l= 0;
296
297         // 1. Check the file is TADC DRM file.
298         memset(&t_FileHeader, 0x00, sizeof(t_FileHeader));
299         memset(&t_DRMHeader, 0x00, sizeof(T_DRM_HEADER));
300         memset(&t_DeviceInfo, 0x00, sizeof(T_DEVICE_INFO));
301         memset(&t_RO, 0x00, sizeof(T_RO));
302
303         bRet = DrmTdcGetFileHeader(packagePath, &fileHeader);
304         if (bRet == FALSE)
305         {
306                 DRM_TAPPS_EXCEPTION("DrmDecryptBlocks Error : DrmTdcGetFileHeader()");
307                 ret = TADC_GET_FILEHEADER_ERROR;
308
309                 goto finish;
310         }
311
312         bRet = DTappsGetCEK(fileHeader.cid, &t_RO);
313         if(bRet == FALSE)
314         {
315                 DRM_TAPPS_SECURE_EXCEPTION("DrmDecryptBlocks Error : DTappsGetCEK() packagePath=%s, fileHeader.cid=%s", packagePath, fileHeader.cid);
316                 ret = TADC_GET_CEK_ERROR;
317
318                 goto finish;
319         }
320         DRM_TAPPS_SECURE_LOG("fileHeader.cid=%s, t_RO.t_Content.CEK=%s", fileHeader.cid, t_RO.t_Content.CEK);
321
322         if ((ret = TADC_SetDeviceInfo(&t_DeviceInfo) ) == TADC_GETDUID_ERROR)
323         {
324                 DRM_TAPPS_EXCEPTION("DrmDecryptBlocks Error : TADC_SetDeviceInfo(), TADC Error Code - %d", ret);
325                 ret = TADC_FILE_READ_ERROR;
326
327                 goto finish;
328         }
329
330         ret = TADC_GetDRMHeaderFromFile(packagePath, &t_FileHeader, &t_DRMHeader);
331         if (ret < 0)
332         {
333                 DRM_TAPPS_EXCEPTION("DrmDecryptBlocks Error : TADC_GetDRMHeaderFromFile() - %s,  TADC Error Code - %d", packagePath, ret);
334                 ret = TADC_NOTTADCFILE_ERROR;
335
336                 goto finish;
337         }
338
339         //Get CEK
340         if ((ret = TADC_GetCEK(&t_DeviceInfo, &t_RO, &t_DRMHeader )) < 0)
341         {
342                 DRM_TAPPS_EXCEPTION("DrmDecryptBlocks Error: TADC_GetCEK, TADC Error Code - %d", ret);
343                 ret = TADC_GET_CEK_ERROR;
344
345                 goto finish;
346         }
347
348         if (fseek(m_pFP, m_PlaintextStartOffset, SEEK_SET ) != 0)
349         {
350                 DRM_TAPPS_EXCEPTION("DrmDecryptBlocks Error :fseek failed.");
351                 ret = TADC_FILE_READ_ERROR;
352
353                 goto finish;
354         }
355
356         if (m_encryptionRange == -1)
357         {
358                 EncBlockCnt = m_blockCnt;
359         }
360         else
361         {
362                 EncBlockCnt = m_encryptionRange;
363         }
364
365         m_pDecBuf = new unsigned char[(EncBlockCnt * TDC_DECRYPT_BLOCKSIZE) + 1];
366         if (m_pDecBuf == NULL)
367         {
368                 DRM_TAPPS_EXCEPTION("DrmRead Error : m_pDecBuf Memory allocation failed");
369                 return TADC_MEMAlOC_ERROR;
370         }
371
372         ReadLen = fread(m_pDecBuf, 1, EncBlockCnt * TDC_DECRYPT_BLOCKSIZE, m_pFP);
373
374         for (k = 0 ; k < ReadLen ; k += 512)
375         {
376                 if (l < EncBlockCnt)
377                 {
378                         DecLen = ReadLen - k;
379                         DecLen = ( DecLen > 512) ? 512 : DecLen;
380
381                         if ((ret = TADC_DecryptBlock((char*)m_pDecBuf + k, DecLen, &t_DRMHeader)) < 0)
382                         {
383                                 DRM_TAPPS_EXCEPTION("DrmDecryptBlocks Error : TADC_DecryptBlock, TADC Error Code - %d", ret);
384                                 ret = TADC_DECRYPT_PACKAGE_ERROR;
385                                 goto finish;
386                         }
387                 }
388                 l += 1;
389         }
390
391 finish:
392         TADC_MEMFree_FileHeader(&t_FileHeader);
393         TADC_MEMFree_DRMHeader(&t_DRMHeader);
394         TADC_MEMFree_RO(&t_RO);
395         return ret;
396 }
397
398 int DrmFileHandler::DrmRead(void* pBuf, long long buflen, long long* pReadLen)
399 {
400         unsigned char *pNewReadBuf = NULL;
401         unsigned char *pTempReadBuf = NULL;
402         int ret = TADC_SUCCESS;
403
404         ULONG ReadLen = 0;
405         long long EncBlockCnt = 0;
406
407         if (m_encryptionRange == -1)
408         {
409                 EncBlockCnt = m_blockCnt;
410         }
411         else
412         {
413                 EncBlockCnt = m_encryptionRange;
414         }
415
416         if (m_DrmCurOffset > EncBlockCnt * TDC_DECRYPT_BLOCKSIZE)
417         {
418                 pNewReadBuf = (TADC_U8*)TADC_IF_Malloc(buflen + 1);
419                 if (pNewReadBuf == NULL)
420                 {
421                         DRM_TAPPS_EXCEPTION("DrmRead Error : pNewReadBuf Malloc Fail");
422                         return TADC_MEMAlOC_ERROR;
423                 }
424
425                 ReadLen = fread(pNewReadBuf, 1, buflen, m_pFP);
426
427                 TADC_IF_MemCpy(pBuf , pNewReadBuf , ReadLen);
428                 TADC_IF_Free(pNewReadBuf);
429
430                 *pReadLen = ReadLen;
431         }
432         else
433         {
434                 if (buflen > EncBlockCnt * TDC_DECRYPT_BLOCKSIZE - m_DrmCurOffset)
435                 {
436                         pTempReadBuf = (TADC_U8*)TADC_IF_Malloc((buflen) + 1);
437                         if (pTempReadBuf == NULL)
438                         {
439                                 DRM_TAPPS_EXCEPTION("DrmRead Error : pTempReadBuf Malloc Fail");
440                                 ret = TADC_MEMAlOC_ERROR;
441
442                                 goto finish;
443                         }
444
445                         m_decReadlen = (EncBlockCnt * TDC_DECRYPT_BLOCKSIZE) - m_DrmCurOffset;
446                         TADC_IF_MemCpy(pTempReadBuf , (char*)m_pDecBuf + m_DrmCurOffset , m_decReadlen);
447
448                         m_extraReadlen = buflen - m_decReadlen;
449
450                         if (fseek(m_pFP, m_decReadlen, SEEK_CUR) != 0)
451                         {
452                                 DRM_TAPPS_EXCEPTION("DrmRead Error: fseek failed.");
453                                 ret = TADC_FILE_READ_ERROR;
454
455                                 goto finish;
456                         }
457
458                         pNewReadBuf = (TADC_U8*)TADC_IF_Malloc(m_extraReadlen + 1);
459                         if (pNewReadBuf == NULL)
460                         {
461                                 DRM_TAPPS_EXCEPTION("DrmRead Error : pNewReadBuf Malloc Fail");
462                                 ret = TADC_MEMAlOC_ERROR;
463                                 goto finish;
464                         }
465
466                         ReadLen = fread(pNewReadBuf, 1, m_extraReadlen, m_pFP);
467
468                         TADC_IF_MemCpy((char*)pTempReadBuf + m_decReadlen, pNewReadBuf , ReadLen);
469                         TADC_IF_MemCpy(pBuf , pTempReadBuf , buflen);
470
471                         TADC_IF_Free(pNewReadBuf);
472                         TADC_IF_Free(pTempReadBuf);
473                 }
474                 else
475                 {
476                         if (m_DrmCurOffset == 0)
477                         {
478                                 TADC_IF_MemCpy(pBuf, (char*)m_pDecBuf + m_decReadlen , buflen);
479                         }
480                         else
481                         {
482                                 TADC_IF_MemCpy(pBuf, (char*)m_pDecBuf + m_DrmCurOffset + m_decReadlen, buflen);
483                         }
484                         m_decReadlen = m_decReadlen + buflen;
485                 }
486
487                 *pReadLen = buflen;
488         }
489
490         return TADC_SUCCESS;
491
492 finish:
493         TADC_IF_Free(pNewReadBuf);
494         TADC_IF_Free(pTempReadBuf);
495         return ret;
496 }
497
498 long long DrmFileHandler::GetCurBlockIndex(void)
499 {
500         m_curBlockIndex = (m_DrmCurOffset / 512) + ((m_DrmCurOffset % 512) ? 1 : 0);
501
502         return m_curBlockIndex;
503 }