2 * Copyright (c) 2000-2015 Samsung Electronics Co., Ltd.
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
8 * http://floralicense.org/license/
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.
19 #include "TADC_Core.h"
20 #include "TADC_ErrorCode.h"
21 #include "DTapps2Rights.h"
22 #include "DrmFileHandler.h"
25 #define TDC_DECRYPT_BLOCKSIZE 512
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 *)>;
33 using BufPtr = std::unique_ptr<unsigned char[]>;
35 inline FileHeaderPtr createFileHeaderPtr(T_FILE_HEADER *ptr)
37 return FileHeaderPtr(ptr, TADC_MEMFree_FileHeader);
40 inline DrmHeaderPtr createDrmHeaderPtr(T_DRM_HEADER *ptr)
42 return DrmHeaderPtr(ptr, TADC_MEMFree_DRMHeader);
45 inline RoPtr createRoPtr(T_RO *ptr)
47 return RoPtr(ptr, TADC_MEMFree_RO);
50 inline BufPtr createBufPtr(unsigned char *ptr)
57 DrmFileHandler::DrmFileHandler(void)
58 : m_pFilePath(nullptr)
65 DrmFileHandler::~DrmFileHandler(void)
67 if (m_pFilePath != NULL)
76 if (m_pDecBuf != NULL)
83 int DrmFileHandler::Construct(const char *szDrmFilePath)
85 T_FILE_HEADER t_FileHeader;
86 T_DRM_HEADER t_DRMHeader;
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));
94 DRM_TAPPS_LOG("%s starts", __func__);
96 if (szDrmFilePath == nullptr) {
97 DRM_TAPPS_EXCEPTION("Parameters NULL!");
98 return TADC_PARAMETER_ERROR;
101 int ret = TADC_GetDRMHeaderFromFile(szDrmFilePath, &t_FileHeader, &t_DRMHeader);
104 DRM_TAPPS_EXCEPTION("Error : TADC_GetDRMHeaderFromFile() - %s TADC Error Code - %d",
106 return TADC_NOTTADCFILE_ERROR;
109 auto fileHeaderPtr = createFileHeaderPtr(&t_FileHeader);
110 auto drmHeaderPtr = createDrmHeaderPtr(&t_DRMHeader);
112 // 2. Validate license and get the CEK for the DRM file
113 bool bRet = DTappsGetCEK((char *)t_DRMHeader.CID, &t_RO);
116 DRM_TAPPS_EXCEPTION("Error : DTappsGetCEK() - %s", t_DRMHeader.CID);
117 return TADC_GET_CEK_ERROR;
120 auto roPtr = createRoPtr(&t_RO);
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));
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));
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);
135 m_encryptionLevel = t_DRMHeader.EncryptionLevel;
136 m_encryptionRange = t_DRMHeader.EncryptionRange;
137 m_plaintextSize = t_DRMHeader.PlaintextSize;
139 // 4. Open the DRM file and set the filepointer to member variable
140 m_pFP = fopen(szDrmFilePath, "rb");
142 if (m_pFP == nullptr) {
143 DRM_TAPPS_EXCEPTION("Error : fopen() - %s", szDrmFilePath);
144 return TADC_FILE_OPEN_ERROR;
147 m_PlaintextStartOffset = t_FileHeader.Offset1 + 35 + t_DRMHeader.XmlSize;
149 fseek(m_pFP, 0, SEEK_END);
150 m_OriginEndOffset = ftell(m_pFP);
152 m_plaintextSize = m_OriginEndOffset - m_PlaintextStartOffset;
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;
160 m_DrmEndOffset = m_plaintextSize;
162 fseek(m_pFP, m_PlaintextStartOffset, SEEK_SET);
163 m_OriginCurOffset = ftell(m_pFP);
166 m_blockCnt = (m_plaintextSize / 512) + ((m_plaintextSize % 512) ? 1 : 0);
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);
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);
179 DRM_TAPPS_LOG("m_PlaintextStartOffset = %ld", m_PlaintextStartOffset);
180 DRM_TAPPS_LOG("m_OriginEndOffset = %ld", m_OriginEndOffset);
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);
186 DRM_TAPPS_LOG("m_blockCnt = %ld", m_blockCnt);
187 DRM_TAPPS_LOG("m_curBlockIndex = %ld", m_curBlockIndex);
194 int DrmFileHandler::DrmSeek(long long offset, int origin)
196 int nRet = TADC_SUCCESS;
197 long long OriginOffset = 0;
198 long long DrmOffset = 0;
203 if (origin == SEEK_SET) {
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;
212 OriginOffset = m_PlaintextStartOffset + DrmOffset;
214 if (fseek(m_pFP, OriginOffset, SEEK_SET) != 0) {
215 DRM_TAPPS_EXCEPTION("fseek failed.");
216 return TADC_FILE_READ_ERROR;
219 m_OriginCurOffset = OriginOffset;
220 m_DrmCurOffset = DrmOffset;
221 } else if (origin == SEEK_CUR) {
222 temp = m_OriginCurOffset;
225 DRM_TAPPS_EXCEPTION("GetOriginCurOffset() failed.");
226 return TADC_FILE_READ_ERROR;
229 OriginOffset = temp + offset;
230 DrmOffset = OriginOffset - m_PlaintextStartOffset;
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;
238 if (fseek(m_pFP, OriginOffset, SEEK_SET) != 0) {
239 DRM_TAPPS_EXCEPTION("fseek failed.");
240 return TADC_FILE_READ_ERROR;
243 m_OriginCurOffset = OriginOffset;
244 m_DrmCurOffset = DrmOffset;
245 } else if (origin == SEEK_END) {
246 OriginOffset = m_OriginEndOffset + offset;
248 if (fseek(m_pFP, OriginOffset, SEEK_SET) != 0) {
249 DRM_TAPPS_EXCEPTION("fseek failed.");
250 return TADC_FILE_READ_ERROR;
253 DrmOffset = OriginOffset - m_PlaintextStartOffset;
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;
261 m_OriginCurOffset = OriginOffset;
262 m_DrmCurOffset = DrmOffset;
264 DRM_TAPPS_EXCEPTION("Parameter Wrong!");
265 return TADC_PARAMETER_ERROR;
271 long long DrmFileHandler::DrmTell(void)
273 return m_DrmCurOffset;
274 // return GetDrmCurOffset();
277 int DrmFileHandler::DrmDecryptBlocks(void)
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;
285 DrmTdcFileHeader fileHeader;
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));
293 bool bRet = DrmTdcGetFileHeader(packagePath, &fileHeader);
296 DRM_TAPPS_EXCEPTION("DrmDecryptBlocks Error : DrmTdcGetFileHeader()");
297 return TADC_GET_FILEHEADER_ERROR;
300 bRet = DTappsGetCEK(fileHeader.cid, &t_RO);
303 DRM_TAPPS_SECURE_EXCEPTION("DrmDecryptBlocks Error : DTappsGetCEK() packagePath=%s, fileHeader.cid=%s",
304 packagePath, fileHeader.cid);
305 return TADC_GET_CEK_ERROR;
308 auto roPtr = createRoPtr(&t_RO);
310 DRM_TAPPS_SECURE_LOG("fileHeader.cid=%s, t_RO.t_Content.CEK=%s", fileHeader.cid,
313 if ((ret = TADC_SetDeviceInfo(&t_DeviceInfo)) == TADC_GETDUID_ERROR) {
314 DRM_TAPPS_EXCEPTION("DrmDecryptBlocks Error : TADC_SetDeviceInfo(), TADC Error Code - %d",
316 return TADC_FILE_READ_ERROR;
319 ret = TADC_GetDRMHeaderFromFile(packagePath, &t_FileHeader, &t_DRMHeader);
322 DRM_TAPPS_EXCEPTION("DrmDecryptBlocks Error : TADC_GetDRMHeaderFromFile() - %s, TADC Error Code - %d",
324 return TADC_NOTTADCFILE_ERROR;
327 /* resource to be scoped-free */
328 auto fileHeaderPtr = createFileHeaderPtr(&t_FileHeader);
331 if ((ret = TADC_GetCEK(&t_DeviceInfo, &t_RO, &t_DRMHeader)) < 0) {
332 DRM_TAPPS_EXCEPTION("DrmDecryptBlocks Error: TADC_GetCEK, TADC Error Code - %d",
334 return TADC_GET_CEK_ERROR;
337 /* resource to be scoped-free */
338 auto drmHeaderPtr = createDrmHeaderPtr(&t_DRMHeader);
340 if (fseek(m_pFP, m_PlaintextStartOffset, SEEK_SET) != 0) {
341 DRM_TAPPS_EXCEPTION("DrmDecryptBlocks Error :fseek failed.");
342 return TADC_FILE_READ_ERROR;
345 auto EncBlockCnt = m_blockCnt;
347 if (m_encryptionRange != -1)
348 EncBlockCnt = m_encryptionRange;
350 m_pDecBuf = new(std::nothrow) unsigned char[(EncBlockCnt *
351 TDC_DECRYPT_BLOCKSIZE) + 1];
353 if (m_pDecBuf == nullptr) {
354 DRM_TAPPS_EXCEPTION("DrmRead Error : m_pDecBuf Memory allocation failed");
355 return TADC_MEMAlOC_ERROR;
358 auto ReadLen = fread(m_pDecBuf, 1, EncBlockCnt * TDC_DECRYPT_BLOCKSIZE, m_pFP);
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;
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",
371 return TADC_DECRYPT_PACKAGE_ERROR;
381 int DrmFileHandler::DrmRead(void *pBuf, long long buflen, long long *pReadLen)
383 auto EncBlockCnt = m_blockCnt;
385 if (m_encryptionRange != -1)
386 EncBlockCnt = m_encryptionRange;
388 if (m_DrmCurOffset > EncBlockCnt * TDC_DECRYPT_BLOCKSIZE) {
389 auto pNewReadBuf = BufPtr(new(std::nothrow) TADC_U8[buflen + 1]);
392 DRM_TAPPS_EXCEPTION("DrmRead Error : pNewReadBuf Malloc Fail");
393 return TADC_MEMAlOC_ERROR;
396 auto ReadLen = fread(pNewReadBuf.get(), 1, buflen, m_pFP);
398 TADC_IF_MemCpy(pBuf, pNewReadBuf.get(), ReadLen);
402 if (buflen > EncBlockCnt * TDC_DECRYPT_BLOCKSIZE - m_DrmCurOffset) {
403 auto pTempReadBuf = createBufPtr(new(std::nothrow) TADC_U8[buflen + 1]);
406 DRM_TAPPS_EXCEPTION("DrmRead Error : pTempReadBuf Malloc Fail");
407 return TADC_MEMAlOC_ERROR;
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);
414 m_extraReadlen = buflen - m_decReadlen;
416 if (fseek(m_pFP, m_decReadlen, SEEK_CUR) != 0) {
417 DRM_TAPPS_EXCEPTION("DrmRead Error: fseek failed.");
418 return TADC_FILE_READ_ERROR;
421 auto pNewReadBuf = BufPtr(new(std::nothrow) TADC_U8[m_extraReadlen + 1]);
424 DRM_TAPPS_EXCEPTION("DrmRead Error : pNewReadBuf Malloc Fail");
425 return TADC_MEMAlOC_ERROR;
428 auto ReadLen = fread(pNewReadBuf.get(), 1, m_extraReadlen, m_pFP);
430 TADC_IF_MemCpy((char *)pTempReadBuf.get() + m_decReadlen, pNewReadBuf.get(),
432 TADC_IF_MemCpy(pBuf, pTempReadBuf.get(), buflen);
434 if (m_DrmCurOffset == 0)
435 TADC_IF_MemCpy(pBuf, reinterpret_cast<char *>(m_pDecBuf) + m_decReadlen,
438 TADC_IF_MemCpy(pBuf, reinterpret_cast<char *>(m_pDecBuf) + m_DrmCurOffset +
439 m_decReadlen, buflen);
441 m_decReadlen = m_decReadlen + buflen;
450 long long DrmFileHandler::GetCurBlockIndex(void)
452 m_curBlockIndex = (m_DrmCurOffset / 512) + ((m_DrmCurOffset % 512) ? 1 : 0);
454 return m_curBlockIndex;