Fix coding style according to tizen rule
[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         fseek(m_pFP, 0, SEEK_END);
150         m_OriginEndOffset = ftell(m_pFP);
151
152         m_plaintextSize = m_OriginEndOffset - m_PlaintextStartOffset;
153
154         if (m_plaintextSize != t_DRMHeader.PlaintextSize) {
155                 DRM_TAPPS_EXCEPTION("Error : plaintext file size incorrect. real = %ld, header = %ld",
156                                                         m_plaintextSize, t_DRMHeader.PlaintextSize);
157                 return TADC_FILE_OPEN_ERROR;
158         }
159
160         m_DrmEndOffset = m_plaintextSize;
161
162         fseek(m_pFP, m_PlaintextStartOffset, SEEK_SET);
163         m_OriginCurOffset = ftell(m_pFP);
164         m_DrmCurOffset = 0;
165
166         m_blockCnt = (m_plaintextSize / 512) + ((m_plaintextSize % 512) ? 1 : 0);
167
168         m_curBlockIndex = 0;
169         m_decReadlen = 0;
170
171         DRM_TAPPS_LOG("m_pCEK = %s", m_pCEK);
172         DRM_TAPPS_LOG("m_pCID = %s", m_pCID);
173         DRM_TAPPS_LOG("m_pFilePath = %s", m_pFilePath);
174
175         DRM_TAPPS_LOG("m_encryptionLevel = %ld", m_encryptionLevel);
176         DRM_TAPPS_LOG("m_encryptionRange = %ld", m_encryptionRange);
177         DRM_TAPPS_LOG("m_plaintextSize = %ld", m_plaintextSize);
178
179         DRM_TAPPS_LOG("m_PlaintextStartOffset = %ld", m_PlaintextStartOffset);
180         DRM_TAPPS_LOG("m_OriginEndOffset = %ld", m_OriginEndOffset);
181
182         DRM_TAPPS_LOG("m_OriginCurOffset = %ld", m_OriginCurOffset);
183         DRM_TAPPS_LOG("m_DrmCurOffset = %ld", m_DrmCurOffset);
184         DRM_TAPPS_LOG("m_DrmEndOffset = %ld", m_DrmEndOffset);
185
186         DRM_TAPPS_LOG("m_blockCnt = %ld", m_blockCnt);
187         DRM_TAPPS_LOG("m_curBlockIndex = %ld", m_curBlockIndex);
188
189         DrmDecryptBlocks();
190
191         return TADC_SUCCESS;
192 }
193
194 int DrmFileHandler::DrmSeek(long long offset, int origin)
195 {
196         int nRet = TADC_SUCCESS;
197         long long OriginOffset = 0;
198         long long DrmOffset = 0;
199         long long temp = 0;
200
201         m_decReadlen = 0;
202
203         if (origin == SEEK_SET) {
204                 DrmOffset = offset;
205
206                 if (DrmOffset < 0 || DrmOffset > m_plaintextSize) {
207                         DRM_TAPPS_EXCEPTION("Parameter Wrong! Offset can not be minus. offset=%lld, m_OriginCurOffset=%lld, m_plaintextSize=%lld",
208                                                                 offset, m_OriginCurOffset, m_plaintextSize);
209                         return TADC_PARAMETER_ERROR;
210                 }
211
212                 OriginOffset = m_PlaintextStartOffset + DrmOffset;
213
214                 if (fseek(m_pFP, OriginOffset, SEEK_SET) != 0) {
215                         DRM_TAPPS_EXCEPTION("fseek failed.");
216                         return TADC_FILE_READ_ERROR;
217                 }
218
219                 m_OriginCurOffset = OriginOffset;
220                 m_DrmCurOffset = DrmOffset;
221         } else if (origin == SEEK_CUR) {
222                 temp = m_OriginCurOffset;
223
224                 if (temp == -1) {
225                         DRM_TAPPS_EXCEPTION("GetOriginCurOffset() failed.");
226                         return TADC_FILE_READ_ERROR;
227                 }
228
229                 OriginOffset = temp + offset;
230                 DrmOffset = OriginOffset - m_PlaintextStartOffset;
231
232                 if (DrmOffset < 0 || DrmOffset > m_plaintextSize) {
233                         DRM_TAPPS_EXCEPTION("Parameter Wrong! Offset can not be minus. offset=%lld, m_OriginCurOffset=%lld, OriginOffset=%lld, DrmOffset=%lld, m_plaintextSize=%lld",
234                                                                 offset, temp, OriginOffset, DrmOffset, m_plaintextSize);
235                         return TADC_PARAMETER_ERROR;
236                 }
237
238                 if (fseek(m_pFP, OriginOffset, SEEK_SET) != 0) {
239                         DRM_TAPPS_EXCEPTION("fseek failed.");
240                         return TADC_FILE_READ_ERROR;
241                 }
242
243                 m_OriginCurOffset = OriginOffset;
244                 m_DrmCurOffset = DrmOffset;
245         } else if (origin == SEEK_END) {
246                 OriginOffset = m_OriginEndOffset + offset;
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                 DrmOffset = OriginOffset - m_PlaintextStartOffset;
254
255                 if (DrmOffset < 0 || DrmOffset > m_plaintextSize) {
256                         DRM_TAPPS_EXCEPTION("Parameter Wrong! Offset can not be minus. offset=%lld, m_OriginCurOffset=%lld, OriginOffset=%lld, DrmOffset=%lld, m_plaintextSize=%lld",
257                                                                 offset, temp, OriginOffset, DrmOffset, m_plaintextSize);
258                         return TADC_PARAMETER_ERROR;
259                 }
260
261                 m_OriginCurOffset = OriginOffset;
262                 m_DrmCurOffset = DrmOffset;
263         } else {
264                 DRM_TAPPS_EXCEPTION("Parameter Wrong!");
265                 return TADC_PARAMETER_ERROR;
266         }
267
268         return nRet;
269 }
270
271 long long DrmFileHandler::DrmTell(void)
272 {
273         return m_DrmCurOffset;
274         //  return GetDrmCurOffset();
275 }
276
277 int DrmFileHandler::DrmDecryptBlocks(void)
278 {
279         int ret = TADC_SUCCESS;
280         const char *packagePath = (const char *)m_pFilePath;
281         T_FILE_HEADER t_FileHeader;
282         T_DRM_HEADER t_DRMHeader;
283         T_DEVICE_INFO t_DeviceInfo;
284         T_RO t_RO;
285         DrmTdcFileHeader fileHeader;
286
287         // 1. Check the file is TADC DRM file.
288         memset(&t_FileHeader, 0x00, sizeof(t_FileHeader));
289         memset(&t_DRMHeader, 0x00, sizeof(T_DRM_HEADER));
290         memset(&t_DeviceInfo, 0x00, sizeof(T_DEVICE_INFO));
291         memset(&t_RO, 0x00, sizeof(T_RO));
292
293         bool bRet = DrmTdcGetFileHeader(packagePath, &fileHeader);
294
295         if (bRet == FALSE) {
296                 DRM_TAPPS_EXCEPTION("DrmDecryptBlocks Error : DrmTdcGetFileHeader()");
297                 return TADC_GET_FILEHEADER_ERROR;
298         }
299
300         bRet = DTappsGetCEK(fileHeader.cid, &t_RO);
301
302         if (bRet == FALSE) {
303                 DRM_TAPPS_SECURE_EXCEPTION("DrmDecryptBlocks Error : DTappsGetCEK() packagePath=%s, fileHeader.cid=%s",
304                                                                    packagePath, fileHeader.cid);
305                 return TADC_GET_CEK_ERROR;
306         }
307
308         auto roPtr = createRoPtr(&t_RO);
309
310         DRM_TAPPS_SECURE_LOG("fileHeader.cid=%s, t_RO.t_Content.CEK=%s", fileHeader.cid,
311                                                  t_RO.t_Content.CEK);
312
313         if ((ret = TADC_SetDeviceInfo(&t_DeviceInfo)) == TADC_GETDUID_ERROR) {
314                 DRM_TAPPS_EXCEPTION("DrmDecryptBlocks Error : TADC_SetDeviceInfo(), TADC Error Code - %d",
315                                                         ret);
316                 return TADC_FILE_READ_ERROR;
317         }
318
319         ret = TADC_GetDRMHeaderFromFile(packagePath, &t_FileHeader, &t_DRMHeader);
320
321         if (ret < 0) {
322                 DRM_TAPPS_EXCEPTION("DrmDecryptBlocks Error : TADC_GetDRMHeaderFromFile() - %s,  TADC Error Code - %d",
323                                                         packagePath, ret);
324                 return TADC_NOTTADCFILE_ERROR;
325         }
326
327         /* resource to be scoped-free */
328         auto fileHeaderPtr = createFileHeaderPtr(&t_FileHeader);
329
330         //Get CEK
331         if ((ret = TADC_GetCEK(&t_DeviceInfo, &t_RO, &t_DRMHeader)) < 0) {
332                 DRM_TAPPS_EXCEPTION("DrmDecryptBlocks Error: TADC_GetCEK, TADC Error Code - %d",
333                                                         ret);
334                 return TADC_GET_CEK_ERROR;
335         }
336
337         /* resource to be scoped-free */
338         auto drmHeaderPtr = createDrmHeaderPtr(&t_DRMHeader);
339
340         if (fseek(m_pFP, m_PlaintextStartOffset, SEEK_SET) != 0) {
341                 DRM_TAPPS_EXCEPTION("DrmDecryptBlocks Error :fseek failed.");
342                 return TADC_FILE_READ_ERROR;
343         }
344
345         auto EncBlockCnt = m_blockCnt;
346
347         if (m_encryptionRange != -1)
348                 EncBlockCnt = m_encryptionRange;
349
350         m_pDecBuf = new(std::nothrow) unsigned char[(EncBlockCnt *
351                         TDC_DECRYPT_BLOCKSIZE) + 1];
352
353         if (m_pDecBuf == nullptr) {
354                 DRM_TAPPS_EXCEPTION("DrmRead Error : m_pDecBuf Memory allocation failed");
355                 return TADC_MEMAlOC_ERROR;
356         }
357
358         auto ReadLen = fread(m_pDecBuf, 1, EncBlockCnt * TDC_DECRYPT_BLOCKSIZE, m_pFP);
359
360         long long l = 0;
361
362         for (size_t k = 0; k < ReadLen; k += 512) {
363                 if (l < EncBlockCnt) {
364                         auto DecLen = ReadLen - k;
365                         DecLen = (DecLen > 512) ? 512 : DecLen;
366
367                         if ((ret = TADC_DecryptBlock((char *)m_pDecBuf + k, DecLen,
368                                                                                  &t_DRMHeader)) < 0) {
369                                 DRM_TAPPS_EXCEPTION("DrmDecryptBlocks Error : TADC_DecryptBlock, TADC Error Code - %d",
370                                                                         ret);
371                                 return TADC_DECRYPT_PACKAGE_ERROR;
372                         }
373                 }
374
375                 l += 1;
376         }
377
378         return ret;
379 }
380
381 int DrmFileHandler::DrmRead(void *pBuf, long long buflen, long long *pReadLen)
382 {
383         auto EncBlockCnt = m_blockCnt;
384
385         if (m_encryptionRange != -1)
386                 EncBlockCnt = m_encryptionRange;
387
388         if (m_DrmCurOffset > EncBlockCnt * TDC_DECRYPT_BLOCKSIZE) {
389                 auto pNewReadBuf = BufPtr(new(std::nothrow) TADC_U8[buflen + 1]);
390
391                 if (!pNewReadBuf) {
392                         DRM_TAPPS_EXCEPTION("DrmRead Error : pNewReadBuf Malloc Fail");
393                         return TADC_MEMAlOC_ERROR;
394                 }
395
396                 auto ReadLen = fread(pNewReadBuf.get(), 1, buflen, m_pFP);
397
398                 TADC_IF_MemCpy(pBuf, pNewReadBuf.get(), ReadLen);
399
400                 *pReadLen = ReadLen;
401         } else {
402                 if (buflen > EncBlockCnt * TDC_DECRYPT_BLOCKSIZE - m_DrmCurOffset) {
403                         auto pTempReadBuf = createBufPtr(new(std::nothrow) TADC_U8[buflen + 1]);
404
405                         if (!pTempReadBuf) {
406                                 DRM_TAPPS_EXCEPTION("DrmRead Error : pTempReadBuf Malloc Fail");
407                                 return TADC_MEMAlOC_ERROR;
408                         }
409
410                         m_decReadlen = (EncBlockCnt * TDC_DECRYPT_BLOCKSIZE) - m_DrmCurOffset;
411                         TADC_IF_MemCpy(pTempReadBuf.get(),
412                                                    reinterpret_cast<char *>(m_pDecBuf) + m_DrmCurOffset, m_decReadlen);
413
414                         m_extraReadlen = buflen - m_decReadlen;
415
416                         if (fseek(m_pFP, m_decReadlen, SEEK_CUR) != 0) {
417                                 DRM_TAPPS_EXCEPTION("DrmRead Error: fseek failed.");
418                                 return TADC_FILE_READ_ERROR;
419                         }
420
421                         auto pNewReadBuf = BufPtr(new(std::nothrow) TADC_U8[m_extraReadlen + 1]);
422
423                         if (!pNewReadBuf) {
424                                 DRM_TAPPS_EXCEPTION("DrmRead Error : pNewReadBuf Malloc Fail");
425                                 return TADC_MEMAlOC_ERROR;
426                         }
427
428                         auto ReadLen = fread(pNewReadBuf.get(), 1, m_extraReadlen, m_pFP);
429
430                         TADC_IF_MemCpy((char *)pTempReadBuf.get() + m_decReadlen, pNewReadBuf.get(),
431                                                    ReadLen);
432                         TADC_IF_MemCpy(pBuf, pTempReadBuf.get(), buflen);
433                 } else {
434                         if (m_DrmCurOffset == 0)
435                                 TADC_IF_MemCpy(pBuf, reinterpret_cast<char *>(m_pDecBuf) + m_decReadlen,
436                                                            buflen);
437                         else
438                                 TADC_IF_MemCpy(pBuf, reinterpret_cast<char *>(m_pDecBuf) + m_DrmCurOffset +
439                                                            m_decReadlen, buflen);
440
441                         m_decReadlen = m_decReadlen + buflen;
442                 }
443
444                 *pReadLen = buflen;
445         }
446
447         return TADC_SUCCESS;
448 }
449
450 long long DrmFileHandler::GetCurBlockIndex(void)
451 {
452         m_curBlockIndex = (m_DrmCurOffset / 512) + ((m_DrmCurOffset % 512) ? 1 : 0);
453
454         return m_curBlockIndex;
455 }