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 if (fseek(m_pFP, 0, SEEK_END) != 0) {
150 DRM_TAPPS_EXCEPTION("operation fail. fseek");
151 return TADC_FILE_OPEN_ERROR;
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;
159 m_plaintextSize = m_OriginEndOffset - m_PlaintextStartOffset;
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;
167 m_DrmEndOffset = m_plaintextSize;
169 if (fseek(m_pFP, m_PlaintextStartOffset, SEEK_SET) != 0) {
170 DRM_TAPPS_EXCEPTION("operation fail. fseek");
171 return TADC_FILE_OPEN_ERROR;
173 m_OriginCurOffset = ftell(m_pFP);
176 m_blockCnt = (m_plaintextSize / 512) + ((m_plaintextSize % 512) ? 1 : 0);
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);
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);
189 DRM_TAPPS_LOG("m_PlaintextStartOffset = %ld", m_PlaintextStartOffset);
190 DRM_TAPPS_LOG("m_OriginEndOffset = %ld", m_OriginEndOffset);
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);
196 DRM_TAPPS_LOG("m_blockCnt = %ld", m_blockCnt);
197 DRM_TAPPS_LOG("m_curBlockIndex = %ld", m_curBlockIndex);
204 int DrmFileHandler::DrmSeek(long long offset, int origin)
206 int nRet = TADC_SUCCESS;
207 long long OriginOffset = 0;
208 long long DrmOffset = 0;
213 if (origin == SEEK_SET) {
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;
222 OriginOffset = m_PlaintextStartOffset + DrmOffset;
224 if (fseek(m_pFP, OriginOffset, SEEK_SET) != 0) {
225 DRM_TAPPS_EXCEPTION("fseek failed.");
226 return TADC_FILE_READ_ERROR;
229 m_OriginCurOffset = OriginOffset;
230 m_DrmCurOffset = DrmOffset;
231 } else if (origin == SEEK_CUR) {
232 temp = m_OriginCurOffset;
235 DRM_TAPPS_EXCEPTION("GetOriginCurOffset() failed.");
236 return TADC_FILE_READ_ERROR;
239 OriginOffset = temp + offset;
240 DrmOffset = OriginOffset - m_PlaintextStartOffset;
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;
248 if (fseek(m_pFP, OriginOffset, SEEK_SET) != 0) {
249 DRM_TAPPS_EXCEPTION("fseek failed.");
250 return TADC_FILE_READ_ERROR;
253 m_OriginCurOffset = OriginOffset;
254 m_DrmCurOffset = DrmOffset;
255 } else if (origin == SEEK_END) {
256 OriginOffset = m_OriginEndOffset + offset;
258 if (fseek(m_pFP, OriginOffset, SEEK_SET) != 0) {
259 DRM_TAPPS_EXCEPTION("fseek failed.");
260 return TADC_FILE_READ_ERROR;
263 DrmOffset = OriginOffset - m_PlaintextStartOffset;
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;
271 m_OriginCurOffset = OriginOffset;
272 m_DrmCurOffset = DrmOffset;
274 DRM_TAPPS_EXCEPTION("Parameter Wrong!");
275 return TADC_PARAMETER_ERROR;
281 long long DrmFileHandler::DrmTell(void)
283 return m_DrmCurOffset;
284 // return GetDrmCurOffset();
287 int DrmFileHandler::DrmDecryptBlocks(void)
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;
295 DrmTdcFileHeader fileHeader;
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));
303 bool bRet = DrmTdcGetFileHeader(packagePath, &fileHeader);
306 DRM_TAPPS_EXCEPTION("DrmDecryptBlocks Error : DrmTdcGetFileHeader()");
307 return TADC_GET_FILEHEADER_ERROR;
310 bRet = DTappsGetCEK(fileHeader.cid, &t_RO);
313 DRM_TAPPS_SECURE_EXCEPTION("DrmDecryptBlocks Error : DTappsGetCEK() packagePath=%s, fileHeader.cid=%s",
314 packagePath, fileHeader.cid);
315 return TADC_GET_CEK_ERROR;
318 auto roPtr = createRoPtr(&t_RO);
320 DRM_TAPPS_SECURE_LOG("fileHeader.cid=%s, t_RO.t_Content.CEK=%s", fileHeader.cid,
323 if ((ret = TADC_SetDeviceInfo(&t_DeviceInfo)) == TADC_GETDUID_ERROR) {
324 DRM_TAPPS_EXCEPTION("DrmDecryptBlocks Error : TADC_SetDeviceInfo(), TADC Error Code - %d",
326 return TADC_FILE_READ_ERROR;
329 ret = TADC_GetDRMHeaderFromFile(packagePath, &t_FileHeader, &t_DRMHeader);
332 DRM_TAPPS_EXCEPTION("DrmDecryptBlocks Error : TADC_GetDRMHeaderFromFile() - %s, TADC Error Code - %d",
334 return TADC_NOTTADCFILE_ERROR;
337 /* resource to be scoped-free */
338 auto fileHeaderPtr = createFileHeaderPtr(&t_FileHeader);
341 if ((ret = TADC_GetCEK(&t_DeviceInfo, &t_RO, &t_DRMHeader)) < 0) {
342 DRM_TAPPS_EXCEPTION("DrmDecryptBlocks Error: TADC_GetCEK, TADC Error Code - %d",
344 return TADC_GET_CEK_ERROR;
347 /* resource to be scoped-free */
348 auto drmHeaderPtr = createDrmHeaderPtr(&t_DRMHeader);
350 if (fseek(m_pFP, m_PlaintextStartOffset, SEEK_SET) != 0) {
351 DRM_TAPPS_EXCEPTION("DrmDecryptBlocks Error :fseek failed.");
352 return TADC_FILE_READ_ERROR;
355 auto EncBlockCnt = m_blockCnt;
357 if (m_encryptionRange != -1)
358 EncBlockCnt = m_encryptionRange;
360 m_pDecBuf = new(std::nothrow) unsigned char[(EncBlockCnt *
361 TDC_DECRYPT_BLOCKSIZE) + 1];
363 if (m_pDecBuf == nullptr) {
364 DRM_TAPPS_EXCEPTION("DrmRead Error : m_pDecBuf Memory allocation failed");
365 return TADC_MEMAlOC_ERROR;
368 auto ReadLen = fread(m_pDecBuf, 1, EncBlockCnt * TDC_DECRYPT_BLOCKSIZE, m_pFP);
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;
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",
381 return TADC_DECRYPT_PACKAGE_ERROR;
391 int DrmFileHandler::DrmRead(void *pBuf, long long buflen, long long *pReadLen)
393 auto EncBlockCnt = m_blockCnt;
395 if (m_encryptionRange != -1)
396 EncBlockCnt = m_encryptionRange;
398 if (m_DrmCurOffset > EncBlockCnt * TDC_DECRYPT_BLOCKSIZE) {
399 auto pNewReadBuf = BufPtr(new(std::nothrow) TADC_U8[buflen + 1]);
402 DRM_TAPPS_EXCEPTION("DrmRead Error : pNewReadBuf Malloc Fail");
403 return TADC_MEMAlOC_ERROR;
406 auto ReadLen = fread(pNewReadBuf.get(), 1, buflen, m_pFP);
408 TADC_IF_MemCpy(pBuf, pNewReadBuf.get(), ReadLen);
412 if (buflen > EncBlockCnt * TDC_DECRYPT_BLOCKSIZE - m_DrmCurOffset) {
413 auto pTempReadBuf = createBufPtr(new(std::nothrow) TADC_U8[buflen + 1]);
416 DRM_TAPPS_EXCEPTION("DrmRead Error : pTempReadBuf Malloc Fail");
417 return TADC_MEMAlOC_ERROR;
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);
424 m_extraReadlen = buflen - m_decReadlen;
426 if (fseek(m_pFP, m_decReadlen, SEEK_CUR) != 0) {
427 DRM_TAPPS_EXCEPTION("DrmRead Error: fseek failed.");
428 return TADC_FILE_READ_ERROR;
431 auto pNewReadBuf = BufPtr(new(std::nothrow) TADC_U8[m_extraReadlen + 1]);
434 DRM_TAPPS_EXCEPTION("DrmRead Error : pNewReadBuf Malloc Fail");
435 return TADC_MEMAlOC_ERROR;
438 auto ReadLen = fread(pNewReadBuf.get(), 1, m_extraReadlen, m_pFP);
440 TADC_IF_MemCpy((char *)pTempReadBuf.get() + m_decReadlen, pNewReadBuf.get(),
442 TADC_IF_MemCpy(pBuf, pTempReadBuf.get(), buflen);
444 if (m_DrmCurOffset == 0)
445 TADC_IF_MemCpy(pBuf, reinterpret_cast<char *>(m_pDecBuf) + m_decReadlen,
448 TADC_IF_MemCpy(pBuf, reinterpret_cast<char *>(m_pDecBuf) + m_DrmCurOffset +
449 m_decReadlen, buflen);
451 m_decReadlen = m_decReadlen + buflen;
460 long long DrmFileHandler::GetCurBlockIndex(void)
462 m_curBlockIndex = (m_DrmCurOffset / 512) + ((m_DrmCurOffset % 512) ? 1 : 0);
464 return m_curBlockIndex;