07b373504ba984e086ee1f7407e2cd478df0a535
[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 <memory>
18
19 #include "TADC_Core.h"
20 #include "TADC_ErrorCode.h"
21 #include "DTapps2Rights.h"
22 #include "DrmFileHandler.h"
23 #include "TADC_IF.h"
24
25 #define TDC_DECRYPT_BLOCKSIZE 512
26
27 namespace {
28
29 using FileHeaderPtr = std::unique_ptr<T_FILE_HEADER, int(*)(T_FILE_HEADER *)>;
30 using DrmHeaderPtr = std::unique_ptr<T_DRM_HEADER, int(*)(T_DRM_HEADER *)>;
31 using RoPtr = std::unique_ptr<T_RO, int(*)(T_RO *)>;
32
33 using BufPtr = std::unique_ptr<unsigned char[]>;
34
35 inline FileHeaderPtr createFileHeaderPtr(T_FILE_HEADER *ptr)
36 {
37         return FileHeaderPtr(ptr, TADC_MEMFree_FileHeader);
38 }
39
40 inline DrmHeaderPtr createDrmHeaderPtr(T_DRM_HEADER *ptr)
41 {
42         return DrmHeaderPtr(ptr, TADC_MEMFree_DRMHeader);
43 }
44
45 inline RoPtr createRoPtr(T_RO *ptr)
46 {
47         return RoPtr(ptr, TADC_MEMFree_RO);
48 }
49
50 inline BufPtr createBufPtr(unsigned char *ptr)
51 {
52         return BufPtr(ptr);
53 }
54
55 }
56
57 DrmFileHandler::DrmFileHandler(void)
58         : m_pFilePath(nullptr)
59         , m_pCID(nullptr)
60         , m_pCEK(nullptr)
61         , m_pFP(nullptr)
62 {
63 }
64
65 DrmFileHandler::~DrmFileHandler(void)
66 {
67         if (m_pFilePath != NULL)
68                 delete[] m_pFilePath;
69
70         if (m_pCID != NULL)
71                 delete[] m_pCID;
72
73         if (m_pCEK != NULL)
74                 delete[] m_pCEK;
75
76         if (m_pDecBuf != NULL)
77                 delete[] m_pDecBuf;
78
79         if (m_pFP != NULL)
80                 fclose(m_pFP);
81 }
82
83 int DrmFileHandler::Construct(const char *szDrmFilePath)
84 {
85         T_FILE_HEADER t_FileHeader;
86         T_DRM_HEADER t_DRMHeader;
87         T_RO t_RO;
88
89         // 1. Check the file is TADC DRM file.
90         memset(&t_FileHeader, 0x00, sizeof(t_FileHeader));
91         memset(&t_DRMHeader, 0x00, sizeof(T_DRM_HEADER));
92         memset(&t_RO, 0x00, sizeof(T_RO));
93
94         DRM_TAPPS_LOG("%s starts", __func__);
95
96         if (szDrmFilePath == nullptr) {
97                 DRM_TAPPS_EXCEPTION("Parameters NULL!");
98                 return TADC_PARAMETER_ERROR;
99         }
100
101         int ret = TADC_GetDRMHeaderFromFile(szDrmFilePath, &t_FileHeader, &t_DRMHeader);
102
103         if (ret < 0) {
104                 DRM_TAPPS_EXCEPTION("Error : TADC_GetDRMHeaderFromFile() - %s TADC Error Code - %d",
105                                                         szDrmFilePath, ret);
106                 return TADC_NOTTADCFILE_ERROR;
107         }
108
109         auto fileHeaderPtr = createFileHeaderPtr(&t_FileHeader);
110         auto drmHeaderPtr = createDrmHeaderPtr(&t_DRMHeader);
111
112         // 2. Validate license and get the CEK for the DRM file
113         bool bRet = DTappsGetCEK((char *)t_DRMHeader.CID, &t_RO);
114
115         if (!bRet) {
116                 DRM_TAPPS_EXCEPTION("Error : DTappsGetCEK() - %s", t_DRMHeader.CID);
117                 return TADC_GET_CEK_ERROR;
118         }
119
120         auto roPtr = createRoPtr(&t_RO);
121
122         // 3. Setting the member variable
123         m_pFilePath = new unsigned char[strlen(szDrmFilePath) + 1];
124         memset(m_pFilePath, 0x00, strlen(szDrmFilePath) + 1);
125         memcpy(m_pFilePath, szDrmFilePath, strlen(szDrmFilePath));
126
127         m_pCID = new unsigned char[strlen((char *)t_DRMHeader.CID) + 1];
128         memset(m_pCID, 0x00, strlen((char *)t_DRMHeader.CID) + 1);
129         memcpy(m_pCID, t_DRMHeader.CID, strlen((char *)t_DRMHeader.CID));
130
131         m_pCEK = new unsigned char[CEK_SIZE + 1];
132         memset(m_pCEK, 0x00, CEK_SIZE + 1);
133         memcpy(m_pCEK, t_RO.t_Content.CEK, CEK_SIZE);
134
135         m_encryptionLevel = t_DRMHeader.EncryptionLevel;
136         m_encryptionRange = t_DRMHeader.EncryptionRange;
137         m_plaintextSize = t_DRMHeader.PlaintextSize;
138
139         // 4. Open the DRM file and set the filepointer to member variable
140         m_pFP = fopen(szDrmFilePath, "rb");
141
142         if (m_pFP == nullptr) {
143                 DRM_TAPPS_EXCEPTION("Error : fopen() - %s", szDrmFilePath);
144                 return TADC_FILE_OPEN_ERROR;
145         }
146
147         m_PlaintextStartOffset = t_FileHeader.Offset1 + 35 + t_DRMHeader.XmlSize;
148
149         if (fseek(m_pFP, 0, SEEK_END) != 0) {
150                 DRM_TAPPS_EXCEPTION("operation fail. fseek");
151                 return TADC_FILE_OPEN_ERROR;
152         }
153         m_OriginEndOffset = ftell(m_pFP);
154         if (m_OriginEndOffset < m_PlaintextStartOffset) {
155                 DRM_TAPPS_EXCEPTION("Invalid file offset... offset is bigger than file size");
156                 return TADC_FILE_OPEN_ERROR;
157         }
158
159         m_plaintextSize = m_OriginEndOffset - m_PlaintextStartOffset;
160
161         if (m_plaintextSize != t_DRMHeader.PlaintextSize) {
162                 DRM_TAPPS_EXCEPTION("Error : plaintext file size incorrect. real = %ld, header = %ld",
163                                                         m_plaintextSize, t_DRMHeader.PlaintextSize);
164                 return TADC_FILE_OPEN_ERROR;
165         }
166
167         m_DrmEndOffset = m_plaintextSize;
168
169         if (fseek(m_pFP, m_PlaintextStartOffset, SEEK_SET) != 0) {
170                 DRM_TAPPS_EXCEPTION("operation fail. fseek");
171                 return TADC_FILE_OPEN_ERROR;
172         }
173         m_OriginCurOffset = ftell(m_pFP);
174         m_DrmCurOffset = 0;
175
176         m_blockCnt = (m_plaintextSize / 512) + ((m_plaintextSize % 512) ? 1 : 0);
177
178         m_curBlockIndex = 0;
179         m_decReadlen = 0;
180
181         DRM_TAPPS_LOG("m_pCEK = %s", m_pCEK);
182         DRM_TAPPS_LOG("m_pCID = %s", m_pCID);
183         DRM_TAPPS_LOG("m_pFilePath = %s", m_pFilePath);
184
185         DRM_TAPPS_LOG("m_encryptionLevel = %ld", m_encryptionLevel);
186         DRM_TAPPS_LOG("m_encryptionRange = %ld", m_encryptionRange);
187         DRM_TAPPS_LOG("m_plaintextSize = %ld", m_plaintextSize);
188
189         DRM_TAPPS_LOG("m_PlaintextStartOffset = %ld", m_PlaintextStartOffset);
190         DRM_TAPPS_LOG("m_OriginEndOffset = %ld", m_OriginEndOffset);
191
192         DRM_TAPPS_LOG("m_OriginCurOffset = %ld", m_OriginCurOffset);
193         DRM_TAPPS_LOG("m_DrmCurOffset = %ld", m_DrmCurOffset);
194         DRM_TAPPS_LOG("m_DrmEndOffset = %ld", m_DrmEndOffset);
195
196         DRM_TAPPS_LOG("m_blockCnt = %ld", m_blockCnt);
197         DRM_TAPPS_LOG("m_curBlockIndex = %ld", m_curBlockIndex);
198
199         DrmDecryptBlocks();
200
201         return TADC_SUCCESS;
202 }
203
204 int DrmFileHandler::DrmSeek(long long offset, int origin)
205 {
206         int nRet = TADC_SUCCESS;
207         long long OriginOffset = 0;
208         long long DrmOffset = 0;
209         long long temp = 0;
210
211         m_decReadlen = 0;
212
213         if (origin == SEEK_SET) {
214                 DrmOffset = offset;
215
216                 if (DrmOffset < 0 || DrmOffset > m_plaintextSize) {
217                         DRM_TAPPS_EXCEPTION("Parameter Wrong! Offset can not be minus. offset=%lld, m_OriginCurOffset=%lld, m_plaintextSize=%lld",
218                                                                 offset, m_OriginCurOffset, m_plaintextSize);
219                         return TADC_PARAMETER_ERROR;
220                 }
221
222                 OriginOffset = m_PlaintextStartOffset + DrmOffset;
223
224                 if (fseek(m_pFP, OriginOffset, SEEK_SET) != 0) {
225                         DRM_TAPPS_EXCEPTION("fseek failed.");
226                         return TADC_FILE_READ_ERROR;
227                 }
228
229                 m_OriginCurOffset = OriginOffset;
230                 m_DrmCurOffset = DrmOffset;
231         } else if (origin == SEEK_CUR) {
232                 temp = m_OriginCurOffset;
233
234                 if (temp == -1) {
235                         DRM_TAPPS_EXCEPTION("GetOriginCurOffset() failed.");
236                         return TADC_FILE_READ_ERROR;
237                 }
238
239                 OriginOffset = temp + offset;
240                 DrmOffset = OriginOffset - m_PlaintextStartOffset;
241
242                 if (DrmOffset < 0 || DrmOffset > m_plaintextSize) {
243                         DRM_TAPPS_EXCEPTION("Parameter Wrong! Offset can not be minus. offset=%lld, m_OriginCurOffset=%lld, OriginOffset=%lld, DrmOffset=%lld, m_plaintextSize=%lld",
244                                                                 offset, temp, OriginOffset, DrmOffset, m_plaintextSize);
245                         return TADC_PARAMETER_ERROR;
246                 }
247
248                 if (fseek(m_pFP, OriginOffset, SEEK_SET) != 0) {
249                         DRM_TAPPS_EXCEPTION("fseek failed.");
250                         return TADC_FILE_READ_ERROR;
251                 }
252
253                 m_OriginCurOffset = OriginOffset;
254                 m_DrmCurOffset = DrmOffset;
255         } else if (origin == SEEK_END) {
256                 OriginOffset = m_OriginEndOffset + offset;
257
258                 if (fseek(m_pFP, OriginOffset, SEEK_SET) != 0) {
259                         DRM_TAPPS_EXCEPTION("fseek failed.");
260                         return TADC_FILE_READ_ERROR;
261                 }
262
263                 DrmOffset = OriginOffset - m_PlaintextStartOffset;
264
265                 if (DrmOffset < 0 || DrmOffset > m_plaintextSize) {
266                         DRM_TAPPS_EXCEPTION("Parameter Wrong! Offset can not be minus. offset=%lld, m_OriginCurOffset=%lld, OriginOffset=%lld, DrmOffset=%lld, m_plaintextSize=%lld",
267                                                                 offset, temp, OriginOffset, DrmOffset, m_plaintextSize);
268                         return TADC_PARAMETER_ERROR;
269                 }
270
271                 m_OriginCurOffset = OriginOffset;
272                 m_DrmCurOffset = DrmOffset;
273         } else {
274                 DRM_TAPPS_EXCEPTION("Parameter Wrong!");
275                 return TADC_PARAMETER_ERROR;
276         }
277
278         return nRet;
279 }
280
281 long long DrmFileHandler::DrmTell(void)
282 {
283         return m_DrmCurOffset;
284         //  return GetDrmCurOffset();
285 }
286
287 int DrmFileHandler::DrmDecryptBlocks(void)
288 {
289         int ret = TADC_SUCCESS;
290         const char *packagePath = (const char *)m_pFilePath;
291         T_FILE_HEADER t_FileHeader;
292         T_DRM_HEADER t_DRMHeader;
293         T_DEVICE_INFO t_DeviceInfo;
294         T_RO t_RO;
295         DrmTdcFileHeader fileHeader;
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         bool bRet = DrmTdcGetFileHeader(packagePath, &fileHeader);
304
305         if (bRet == FALSE) {
306                 DRM_TAPPS_EXCEPTION("DrmDecryptBlocks Error : DrmTdcGetFileHeader()");
307                 return TADC_GET_FILEHEADER_ERROR;
308         }
309
310         bRet = DTappsGetCEK(fileHeader.cid, &t_RO);
311
312         if (bRet == FALSE) {
313                 DRM_TAPPS_SECURE_EXCEPTION("DrmDecryptBlocks Error : DTappsGetCEK() packagePath=%s, fileHeader.cid=%s",
314                                                                    packagePath, fileHeader.cid);
315                 return TADC_GET_CEK_ERROR;
316         }
317
318         auto roPtr = createRoPtr(&t_RO);
319
320         DRM_TAPPS_SECURE_LOG("fileHeader.cid=%s, t_RO.t_Content.CEK=%s", fileHeader.cid,
321                                                  t_RO.t_Content.CEK);
322
323         if ((ret = TADC_SetDeviceInfo(&t_DeviceInfo)) == TADC_GETDUID_ERROR) {
324                 DRM_TAPPS_EXCEPTION("DrmDecryptBlocks Error : TADC_SetDeviceInfo(), TADC Error Code - %d",
325                                                         ret);
326                 return TADC_FILE_READ_ERROR;
327         }
328
329         ret = TADC_GetDRMHeaderFromFile(packagePath, &t_FileHeader, &t_DRMHeader);
330
331         if (ret < 0) {
332                 DRM_TAPPS_EXCEPTION("DrmDecryptBlocks Error : TADC_GetDRMHeaderFromFile() - %s,  TADC Error Code - %d",
333                                                         packagePath, ret);
334                 return TADC_NOTTADCFILE_ERROR;
335         }
336
337         /* resource to be scoped-free */
338         auto fileHeaderPtr = createFileHeaderPtr(&t_FileHeader);
339
340         //Get CEK
341         if ((ret = TADC_GetCEK(&t_DeviceInfo, &t_RO, &t_DRMHeader)) < 0) {
342                 DRM_TAPPS_EXCEPTION("DrmDecryptBlocks Error: TADC_GetCEK, TADC Error Code - %d",
343                                                         ret);
344                 return TADC_GET_CEK_ERROR;
345         }
346
347         /* resource to be scoped-free */
348         auto drmHeaderPtr = createDrmHeaderPtr(&t_DRMHeader);
349
350         if (fseek(m_pFP, m_PlaintextStartOffset, SEEK_SET) != 0) {
351                 DRM_TAPPS_EXCEPTION("DrmDecryptBlocks Error :fseek failed.");
352                 return TADC_FILE_READ_ERROR;
353         }
354
355         auto EncBlockCnt = m_blockCnt;
356
357         if (m_encryptionRange != -1)
358                 EncBlockCnt = m_encryptionRange;
359
360         m_pDecBuf = new(std::nothrow) unsigned char[(EncBlockCnt *
361                         TDC_DECRYPT_BLOCKSIZE) + 1];
362
363         if (m_pDecBuf == nullptr) {
364                 DRM_TAPPS_EXCEPTION("DrmRead Error : m_pDecBuf Memory allocation failed");
365                 return TADC_MEMAlOC_ERROR;
366         }
367
368         auto ReadLen = fread(m_pDecBuf, 1, EncBlockCnt * TDC_DECRYPT_BLOCKSIZE, m_pFP);
369
370         long long l = 0;
371
372         for (size_t k = 0; k < ReadLen; k += 512) {
373                 if (l < EncBlockCnt) {
374                         auto DecLen = ReadLen - k;
375                         DecLen = (DecLen > 512) ? 512 : DecLen;
376
377                         if ((ret = TADC_DecryptBlock((char *)m_pDecBuf + k, DecLen,
378                                                                                  &t_DRMHeader)) < 0) {
379                                 DRM_TAPPS_EXCEPTION("DrmDecryptBlocks Error : TADC_DecryptBlock, TADC Error Code - %d",
380                                                                         ret);
381                                 return TADC_DECRYPT_PACKAGE_ERROR;
382                         }
383                 }
384
385                 l += 1;
386         }
387
388         return ret;
389 }
390
391 int DrmFileHandler::DrmRead(void *pBuf, long long buflen, long long *pReadLen)
392 {
393         auto EncBlockCnt = m_blockCnt;
394
395         if (m_encryptionRange != -1)
396                 EncBlockCnt = m_encryptionRange;
397
398         if (m_DrmCurOffset > EncBlockCnt * TDC_DECRYPT_BLOCKSIZE) {
399                 auto pNewReadBuf = BufPtr(new(std::nothrow) TADC_U8[buflen + 1]);
400
401                 if (!pNewReadBuf) {
402                         DRM_TAPPS_EXCEPTION("DrmRead Error : pNewReadBuf Malloc Fail");
403                         return TADC_MEMAlOC_ERROR;
404                 }
405
406                 auto ReadLen = fread(pNewReadBuf.get(), 1, buflen, m_pFP);
407
408                 TADC_IF_MemCpy(pBuf, pNewReadBuf.get(), ReadLen);
409
410                 *pReadLen = ReadLen;
411         } else {
412                 if (buflen > EncBlockCnt * TDC_DECRYPT_BLOCKSIZE - m_DrmCurOffset) {
413                         auto pTempReadBuf = createBufPtr(new(std::nothrow) TADC_U8[buflen + 1]);
414
415                         if (!pTempReadBuf) {
416                                 DRM_TAPPS_EXCEPTION("DrmRead Error : pTempReadBuf Malloc Fail");
417                                 return TADC_MEMAlOC_ERROR;
418                         }
419
420                         m_decReadlen = (EncBlockCnt * TDC_DECRYPT_BLOCKSIZE) - m_DrmCurOffset;
421                         TADC_IF_MemCpy(pTempReadBuf.get(),
422                                                    reinterpret_cast<char *>(m_pDecBuf) + m_DrmCurOffset, m_decReadlen);
423
424                         m_extraReadlen = buflen - m_decReadlen;
425
426                         if (fseek(m_pFP, m_decReadlen, SEEK_CUR) != 0) {
427                                 DRM_TAPPS_EXCEPTION("DrmRead Error: fseek failed.");
428                                 return TADC_FILE_READ_ERROR;
429                         }
430
431                         auto pNewReadBuf = BufPtr(new(std::nothrow) TADC_U8[m_extraReadlen + 1]);
432
433                         if (!pNewReadBuf) {
434                                 DRM_TAPPS_EXCEPTION("DrmRead Error : pNewReadBuf Malloc Fail");
435                                 return TADC_MEMAlOC_ERROR;
436                         }
437
438                         auto ReadLen = fread(pNewReadBuf.get(), 1, m_extraReadlen, m_pFP);
439
440                         TADC_IF_MemCpy((char *)pTempReadBuf.get() + m_decReadlen, pNewReadBuf.get(),
441                                                    ReadLen);
442                         TADC_IF_MemCpy(pBuf, pTempReadBuf.get(), buflen);
443                 } else {
444                         if (m_DrmCurOffset == 0)
445                                 TADC_IF_MemCpy(pBuf, reinterpret_cast<char *>(m_pDecBuf) + m_decReadlen,
446                                                            buflen);
447                         else
448                                 TADC_IF_MemCpy(pBuf, reinterpret_cast<char *>(m_pDecBuf) + m_DrmCurOffset +
449                                                            m_decReadlen, buflen);
450
451                         m_decReadlen = m_decReadlen + buflen;
452                 }
453
454                 *pReadLen = buflen;
455         }
456
457         return TADC_SUCCESS;
458 }
459
460 long long DrmFileHandler::GetCurBlockIndex(void)
461 {
462         m_curBlockIndex = (m_DrmCurOffset / 512) + ((m_DrmCurOffset % 512) ? 1 : 0);
463
464         return m_curBlockIndex;
465 }