| /* |
| * Copyright (C) 2007 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| #include <svc_drm.h> |
| #include <drm_inner.h> |
| #include <parser_dm.h> |
| #include <parser_dcf.h> |
| #include <parser_rel.h> |
| #include <drm_rights_manager.h> |
| #include <drm_time.h> |
| #include <drm_decoder.h> |
| #include "log.h" |
| |
| /** |
| * Current id. |
| */ |
| static int32_t curID = 0; |
| |
| /** |
| * The header pointer for the session list. |
| */ |
| static T_DRM_Session_Node* sessionTable = NULL; |
| |
| /** |
| * New a session. |
| */ |
| static T_DRM_Session_Node* newSession(T_DRM_Input_Data data) |
| { |
| T_DRM_Session_Node* s = (T_DRM_Session_Node *)malloc(sizeof(T_DRM_Session_Node)); |
| |
| if (NULL != s) { |
| memset(s, 0, sizeof(T_DRM_Session_Node)); |
| |
| s->sessionId = curID++; |
| s->inputHandle = data.inputHandle; |
| s->mimeType = data.mimeType; |
| s->getInputDataLengthFunc = data.getInputDataLength; |
| s->readInputDataFunc = data.readInputData; |
| s->seekInputDataFunc = data.seekInputData; |
| } |
| |
| return s; |
| } |
| |
| /** |
| * Free a session. |
| */ |
| static void freeSession(T_DRM_Session_Node* s) |
| { |
| if (NULL == s) |
| return; |
| |
| if (NULL != s->rawContent) |
| free(s->rawContent); |
| |
| if (NULL != s->readBuf) |
| free(s->readBuf); |
| |
| if (NULL != s->infoStruct) |
| free(s->infoStruct); |
| |
| free(s); |
| } |
| |
| /** |
| * Add a session to list. |
| */ |
| static int32_t addSession(T_DRM_Session_Node* s) |
| { |
| if (NULL == s) |
| return -1; |
| |
| s->next = sessionTable; |
| sessionTable = s; |
| |
| return s->sessionId; |
| } |
| |
| /** |
| * Get a session from the list. |
| */ |
| static T_DRM_Session_Node* getSession(int32_t sessionId) |
| { |
| T_DRM_Session_Node* s; |
| |
| if (sessionId < 0 || NULL == sessionTable) |
| return NULL; |
| |
| for (s = sessionTable; s != NULL; s = s->next) { |
| if (sessionId == s->sessionId) |
| return s; |
| } |
| |
| return NULL; |
| } |
| |
| /** |
| * Remove a session from the list. |
| */ |
| static void removeSession(int32_t sessionId) |
| { |
| T_DRM_Session_Node *curS, *preS; |
| |
| if (sessionId < 0 || NULL == sessionTable) |
| return; |
| |
| if (sessionId == sessionTable->sessionId) { |
| curS = sessionTable; |
| sessionTable = curS->next; |
| freeSession(curS); |
| return; |
| } |
| |
| for (preS = sessionTable; preS->next != NULL; preS = preS->next) { |
| if (preS->next->sessionId == sessionId) |
| curS = preS->next; |
| } |
| |
| if (NULL == preS->next) |
| return; |
| |
| preS->next = curS->next; |
| freeSession(curS); |
| } |
| |
| /** |
| * Try to identify the mimetype according the input DRM data. |
| */ |
| static int32_t getMimeType(const uint8_t *buf, int32_t bufLen) |
| { |
| const uint8_t *p; |
| |
| if (NULL == buf || bufLen <= 0) |
| return TYPE_DRM_UNKNOWN; |
| |
| p = buf; |
| |
| /* check if it is DRM Content Format, only check the first field of Version, it must be "0x01" */ |
| if (0x01 == *p) |
| return TYPE_DRM_CONTENT; |
| |
| /* check if it is DRM Message, only check the first two bytes, it must be the start flag of boundary: "--" */ |
| if (bufLen >= 2 && '-' == *p && '-' == *(p + 1)) |
| return TYPE_DRM_MESSAGE; |
| |
| /* check if it is DRM Rights XML format, only check the first several bytes, it must be: "<o-ex:rights" */ |
| if (bufLen >= 12 && 0 == strncmp("<o-ex:rights", (char *)p, 12)) |
| return TYPE_DRM_RIGHTS_XML; |
| |
| /* check if it is DRM Rights WBXML format, only check the first two bytes, it must be: 0x03, 0x0e */ |
| if (bufLen >= 2 && 0x03 == *p && 0x0e == *(p + 1)) |
| return TYPE_DRM_RIGHTS_WBXML; |
| |
| return TYPE_DRM_UNKNOWN; |
| } |
| |
| static int32_t drm_skipCRLFinB64(const uint8_t* b64Data, int32_t len) |
| { |
| const uint8_t* p; |
| int32_t skipLen = 0; |
| |
| if (NULL == b64Data || len <= 0) |
| return -1; |
| |
| p = b64Data; |
| while (p - b64Data < len) { |
| if ('\r' == *p || '\n'== *p) |
| skipLen++; |
| p++; |
| } |
| |
| return skipLen; |
| } |
| |
| static int32_t drm_scanEndBoundary(const uint8_t* pBuf, int32_t len, uint8_t* const boundary) |
| { |
| const uint8_t* p; |
| int32_t leftLen; |
| int32_t boundaryLen; |
| |
| if (NULL == pBuf || len <=0 || NULL == boundary) |
| return -1; |
| |
| p = pBuf; |
| boundaryLen = strlen((char *)boundary) + 2; /* 2 means: '\r' and '\n' */ |
| leftLen = len - (p - pBuf); |
| while (leftLen > 0) { |
| if (NULL == (p = memchr(p, '\r', leftLen))) |
| break; |
| |
| leftLen = len - (p - pBuf); |
| if (leftLen < boundaryLen) |
| return -2; /* here means may be the boundary has been split */ |
| |
| if (('\n' == *(p + 1)) && (0 == memcmp(p + 2, boundary, strlen((char *)boundary)))) |
| return p - pBuf; /* find the boundary here */ |
| |
| p++; |
| leftLen--; |
| } |
| |
| return len; /* no boundary found */ |
| } |
| |
| static int32_t drm_getLicenseInfo(T_DRM_Rights* pRights, T_DRM_Rights_Info* licenseInfo) |
| { |
| if (NULL != licenseInfo && NULL != pRights) { |
| strcpy((char *)licenseInfo->roId, (char *)pRights->uid); |
| |
| if (1 == pRights->bIsDisplayable) { |
| licenseInfo->displayRights.indicator = pRights->DisplayConstraint.Indicator; |
| licenseInfo->displayRights.count = |
| pRights->DisplayConstraint.Count; |
| licenseInfo->displayRights.startDate = |
| pRights->DisplayConstraint.StartTime.date; |
| licenseInfo->displayRights.startTime = |
| pRights->DisplayConstraint.StartTime.time; |
| licenseInfo->displayRights.endDate = |
| pRights->DisplayConstraint.EndTime.date; |
| licenseInfo->displayRights.endTime = |
| pRights->DisplayConstraint.EndTime.time; |
| licenseInfo->displayRights.intervalDate = |
| pRights->DisplayConstraint.Interval.date; |
| licenseInfo->displayRights.intervalTime = |
| pRights->DisplayConstraint.Interval.time; |
| } |
| if (1 == pRights->bIsPlayable) { |
| licenseInfo->playRights.indicator = pRights->PlayConstraint.Indicator; |
| licenseInfo->playRights.count = pRights->PlayConstraint.Count; |
| licenseInfo->playRights.startDate = |
| pRights->PlayConstraint.StartTime.date; |
| licenseInfo->playRights.startTime = |
| pRights->PlayConstraint.StartTime.time; |
| licenseInfo->playRights.endDate = |
| pRights->PlayConstraint.EndTime.date; |
| licenseInfo->playRights.endTime = |
| pRights->PlayConstraint.EndTime.time; |
| licenseInfo->playRights.intervalDate = |
| pRights->PlayConstraint.Interval.date; |
| licenseInfo->playRights.intervalTime = |
| pRights->PlayConstraint.Interval.time; |
| } |
| if (1 == pRights->bIsExecuteable) { |
| licenseInfo->executeRights.indicator = pRights->ExecuteConstraint.Indicator; |
| licenseInfo->executeRights.count = |
| pRights->ExecuteConstraint.Count; |
| licenseInfo->executeRights.startDate = |
| pRights->ExecuteConstraint.StartTime.date; |
| licenseInfo->executeRights.startTime = |
| pRights->ExecuteConstraint.StartTime.time; |
| licenseInfo->executeRights.endDate = |
| pRights->ExecuteConstraint.EndTime.date; |
| licenseInfo->executeRights.endTime = |
| pRights->ExecuteConstraint.EndTime.time; |
| licenseInfo->executeRights.intervalDate = |
| pRights->ExecuteConstraint.Interval.date; |
| licenseInfo->executeRights.intervalTime = |
| pRights->ExecuteConstraint.Interval.time; |
| } |
| if (1 == pRights->bIsPrintable) { |
| licenseInfo->printRights.indicator = pRights->PrintConstraint.Indicator; |
| licenseInfo->printRights.count = |
| pRights->PrintConstraint.Count; |
| licenseInfo->printRights.startDate = |
| pRights->PrintConstraint.StartTime.date; |
| licenseInfo->printRights.startTime = |
| pRights->PrintConstraint.StartTime.time; |
| licenseInfo->printRights.endDate = |
| pRights->PrintConstraint.EndTime.date; |
| licenseInfo->printRights.endTime = |
| pRights->PrintConstraint.EndTime.time; |
| licenseInfo->printRights.intervalDate = |
| pRights->PrintConstraint.Interval.date; |
| licenseInfo->printRights.intervalTime = |
| pRights->PrintConstraint.Interval.time; |
| } |
| return TRUE; |
| } |
| return FALSE; |
| } |
| |
| static int32_t drm_addRightsNodeToList(T_DRM_Rights_Info_Node **ppRightsHeader, |
| T_DRM_Rights_Info_Node *pInputRightsNode) |
| { |
| T_DRM_Rights_Info_Node *pRightsNode; |
| |
| if (NULL == ppRightsHeader || NULL == pInputRightsNode) |
| return FALSE; |
| |
| pRightsNode = (T_DRM_Rights_Info_Node *)malloc(sizeof(T_DRM_Rights_Info_Node)); |
| if (NULL == pRightsNode) |
| return FALSE; |
| |
| memcpy(pRightsNode, pInputRightsNode, sizeof(T_DRM_Rights_Info_Node)); |
| pRightsNode->next = NULL; |
| |
| /* this means it is the first node */ |
| if (NULL == *ppRightsHeader) |
| *ppRightsHeader = pRightsNode; |
| else { |
| T_DRM_Rights_Info_Node *pTmp; |
| |
| pTmp = *ppRightsHeader; |
| while (NULL != pTmp->next) |
| pTmp = pTmp->next; |
| |
| pTmp->next = pRightsNode; |
| } |
| return TRUE; |
| } |
| |
| static int32_t drm_startConsumeRights(int32_t * bIsXXable, |
| T_DRM_Rights_Constraint * XXConstraint, |
| int32_t * writeFlag) |
| { |
| T_DB_TIME_SysTime curDateTime; |
| T_DRM_DATETIME CurrentTime; |
| uint8_t countFlag = 0; |
| |
| memset(&CurrentTime, 0, sizeof(T_DRM_DATETIME)); |
| |
| if (NULL == bIsXXable || 0 == *bIsXXable || NULL == XXConstraint || NULL == writeFlag) |
| return DRM_FAILURE; |
| |
| if (0 != (uint8_t)(XXConstraint->Indicator & DRM_NO_CONSTRAINT)) /* Have utter right? */ |
| return DRM_SUCCESS; |
| |
| *bIsXXable = 0; /* Assume have invalid rights at first */ |
| *writeFlag = 0; |
| |
| if (0 != (XXConstraint->Indicator & (DRM_START_TIME_CONSTRAINT | DRM_END_TIME_CONSTRAINT | DRM_INTERVAL_CONSTRAINT))) { |
| DRM_time_getSysTime(&curDateTime); |
| |
| if (-1 == drm_checkDate(curDateTime.year, curDateTime.month, curDateTime.day, |
| curDateTime.hour, curDateTime.min, curDateTime.sec)) |
| return DRM_FAILURE; |
| |
| YMD_HMS_2_INT(curDateTime.year, curDateTime.month, curDateTime.day, |
| CurrentTime.date, curDateTime.hour, curDateTime.min, |
| curDateTime.sec, CurrentTime.time); |
| } |
| |
| if (0 != (uint8_t)(XXConstraint->Indicator & DRM_COUNT_CONSTRAINT)) { /* Have count restrict? */ |
| *writeFlag = 1; |
| /* If it has only one time for use, after use this function, we will delete this rights */ |
| if (XXConstraint->Count <= 0) { |
| XXConstraint->Indicator &= ~DRM_COUNT_CONSTRAINT; |
| return DRM_RIGHTS_EXPIRED; |
| } |
| |
| if (XXConstraint->Count-- <= 1) { |
| XXConstraint->Indicator &= ~DRM_COUNT_CONSTRAINT; |
| countFlag = 1; |
| } |
| } |
| |
| if (0 != (uint8_t)(XXConstraint->Indicator & DRM_START_TIME_CONSTRAINT)) { |
| if (XXConstraint->StartTime.date > CurrentTime.date || |
| (XXConstraint->StartTime.date == CurrentTime.date && |
| XXConstraint->StartTime.time >= CurrentTime.time)) { |
| *bIsXXable = 1; |
| return DRM_RIGHTS_PENDING; |
| } |
| } |
| |
| if (0 != (uint8_t)(XXConstraint->Indicator & DRM_END_TIME_CONSTRAINT)) { /* Have end time restrict? */ |
| if (XXConstraint->EndTime.date < CurrentTime.date || |
| (XXConstraint->EndTime.date == CurrentTime.date && |
| XXConstraint->EndTime.time <= CurrentTime.time)) { |
| *writeFlag = 1; |
| XXConstraint->Indicator &= ~DRM_END_TIME_CONSTRAINT; |
| return DRM_RIGHTS_EXPIRED; |
| } |
| } |
| |
| if (0 != (uint8_t)(XXConstraint->Indicator & DRM_INTERVAL_CONSTRAINT)) { /* Have interval time restrict? */ |
| int32_t year, mon, day, hour, min, sec, date, time; |
| int32_t ret; |
| |
| XXConstraint->Indicator |= DRM_END_TIME_CONSTRAINT; |
| XXConstraint->Indicator &= ~DRM_INTERVAL_CONSTRAINT; /* Write off interval right */ |
| *writeFlag = 1; |
| |
| if (XXConstraint->Interval.date == 0 |
| && XXConstraint->Interval.time == 0) { |
| return DRM_RIGHTS_EXPIRED; |
| } |
| date = CurrentTime.date + XXConstraint->Interval.date; |
| time = CurrentTime.time + XXConstraint->Interval.time; |
| INT_2_YMD_HMS(year, mon, day, date, hour, min, sec, time); |
| |
| if (sec > 59) { |
| min += sec / 60; |
| sec %= 60; |
| } |
| if (min > 59) { |
| hour += min / 60; |
| min %= 60; |
| } |
| if (hour > 23) { |
| day += hour / 24; |
| hour %= 24; |
| } |
| if (day > 31) { |
| mon += day / 31; |
| day %= 31; |
| } |
| if (mon > 12) { |
| year += mon / 12; |
| mon %= 12; |
| } |
| if (day > (ret = drm_monthDays(year, mon))) { |
| day -= ret; |
| mon++; |
| if (mon > 12) { |
| mon -= 12; |
| year++; |
| } |
| } |
| YMD_HMS_2_INT(year, mon, day, XXConstraint->EndTime.date, hour, |
| min, sec, XXConstraint->EndTime.time); |
| } |
| |
| if (1 != countFlag) |
| *bIsXXable = 1; /* Can go here ,so right must be valid */ |
| return DRM_SUCCESS; |
| } |
| |
| static int32_t drm_startCheckRights(int32_t * bIsXXable, |
| T_DRM_Rights_Constraint * XXConstraint) |
| { |
| T_DB_TIME_SysTime curDateTime; |
| T_DRM_DATETIME CurrentTime; |
| |
| memset(&CurrentTime, 0, sizeof(T_DRM_DATETIME)); |
| |
| if (NULL == bIsXXable || 0 == *bIsXXable || NULL == XXConstraint) |
| return DRM_FAILURE; |
| |
| if (0 != (uint8_t)(XXConstraint->Indicator & DRM_NO_CONSTRAINT)) /* Have utter right? */ |
| return DRM_SUCCESS; |
| |
| *bIsXXable = 0; /* Assume have invalid rights at first */ |
| |
| if (0 != (XXConstraint->Indicator & (DRM_START_TIME_CONSTRAINT | DRM_END_TIME_CONSTRAINT))) { |
| DRM_time_getSysTime(&curDateTime); |
| |
| if (-1 == drm_checkDate(curDateTime.year, curDateTime.month, curDateTime.day, |
| curDateTime.hour, curDateTime.min, curDateTime.sec)) |
| return DRM_FAILURE; |
| |
| YMD_HMS_2_INT(curDateTime.year, curDateTime.month, curDateTime.day, |
| CurrentTime.date, curDateTime.hour, curDateTime.min, |
| curDateTime.sec, CurrentTime.time); |
| } |
| |
| if (0 != (uint8_t)(XXConstraint->Indicator & DRM_COUNT_CONSTRAINT)) { /* Have count restrict? */ |
| if (XXConstraint->Count <= 0) { |
| XXConstraint->Indicator &= ~DRM_COUNT_CONSTRAINT; |
| return DRM_RIGHTS_EXPIRED; |
| } |
| } |
| |
| if (0 != (uint8_t)(XXConstraint->Indicator & DRM_START_TIME_CONSTRAINT)) { |
| if (XXConstraint->StartTime.date > CurrentTime.date || |
| (XXConstraint->StartTime.date == CurrentTime.date && |
| XXConstraint->StartTime.time >= CurrentTime.time)) { |
| *bIsXXable = 1; |
| return DRM_RIGHTS_PENDING; |
| } |
| } |
| |
| if (0 != (uint8_t)(XXConstraint->Indicator & DRM_END_TIME_CONSTRAINT)) { /* Have end time restrict? */ |
| if (XXConstraint->EndTime.date < CurrentTime.date || |
| (XXConstraint->EndTime.date == CurrentTime.date && |
| XXConstraint->EndTime.time <= CurrentTime.time)) { |
| XXConstraint->Indicator &= ~DRM_END_TIME_CONSTRAINT; |
| return DRM_RIGHTS_EXPIRED; |
| } |
| } |
| |
| if (0 != (uint8_t)(XXConstraint->Indicator & DRM_INTERVAL_CONSTRAINT)) { /* Have interval time restrict? */ |
| if (XXConstraint->Interval.date == 0 && XXConstraint->Interval.time == 0) { |
| XXConstraint->Indicator &= ~DRM_INTERVAL_CONSTRAINT; |
| return DRM_RIGHTS_EXPIRED; |
| } |
| } |
| |
| *bIsXXable = 1; |
| return DRM_SUCCESS; |
| } |
| |
| int32_t drm_checkRoAndUpdate(int32_t id, int32_t permission) |
| { |
| int32_t writeFlag = 0; |
| int32_t roAmount; |
| int32_t validRoAmount = 0; |
| int32_t flag = DRM_FAILURE; |
| int32_t i, j; |
| T_DRM_Rights *pRo; |
| T_DRM_Rights *pCurRo; |
| int32_t * pNumOfPriority; |
| int32_t iNum; |
| T_DRM_Rights_Constraint * pCurConstraint; |
| T_DRM_Rights_Constraint * pCompareConstraint; |
| int priority[8] = {1, 2, 4, 3, 8, 6, 7, 5}; |
| |
| if (FALSE == drm_writeOrReadInfo(id, NULL, &roAmount, GET_ROAMOUNT)) |
| return DRM_FAILURE; |
| |
| validRoAmount = roAmount; |
| if (roAmount < 1) |
| return DRM_NO_RIGHTS; |
| |
| pRo = malloc(roAmount * sizeof(T_DRM_Rights)); |
| pCurRo = pRo; |
| if (NULL == pRo) |
| return DRM_FAILURE; |
| |
| if (FALSE == drm_writeOrReadInfo(id, pRo, &roAmount, GET_ALL_RO)) { |
| free(pRo); |
| return DRM_FAILURE; |
| } |
| |
| /** check the right priority */ |
| pNumOfPriority = malloc(sizeof(int32_t) * roAmount); |
| for(i = 0; i < roAmount; i++) { |
| iNum = roAmount - 1; |
| for(j = 0; j < roAmount; j++) { |
| if(i == j) |
| continue; |
| switch(permission) { |
| case DRM_PERMISSION_PLAY: |
| pCurConstraint = &pRo[i].PlayConstraint; |
| pCompareConstraint = &pRo[j].PlayConstraint; |
| break; |
| case DRM_PERMISSION_DISPLAY: |
| pCurConstraint = &pRo[i].DisplayConstraint; |
| pCompareConstraint = &pRo[j].DisplayConstraint; |
| break; |
| case DRM_PERMISSION_EXECUTE: |
| pCurConstraint = &pRo[i].ExecuteConstraint; |
| pCompareConstraint = &pRo[j].ExecuteConstraint; |
| break; |
| case DRM_PERMISSION_PRINT: |
| pCurConstraint = &pRo[i].PrintConstraint; |
| pCompareConstraint = &pRo[j].PrintConstraint; |
| break; |
| default: |
| free(pRo); |
| free(pNumOfPriority); |
| return DRM_FAILURE; |
| } |
| |
| /**get priority by Indicator*/ |
| if(0 == (pCurConstraint->Indicator & DRM_NO_CONSTRAINT) && |
| 0 == (pCompareConstraint->Indicator & DRM_NO_CONSTRAINT)) { |
| int num1, num2; |
| num1 = (pCurConstraint->Indicator & 0x0e) >> 1; |
| num2 = (pCompareConstraint->Indicator & 0x0e) >> 1; |
| if(priority[num1] > priority[num2]) { |
| iNum--; |
| continue; |
| } else if(priority[pCurConstraint->Indicator] < priority[pCompareConstraint->Indicator]) |
| continue; |
| } else if(pCurConstraint->Indicator > pCompareConstraint->Indicator) { |
| iNum--; |
| continue; |
| } else if(pCurConstraint->Indicator < pCompareConstraint->Indicator) |
| continue; |
| |
| if(0 != (pCurConstraint->Indicator & DRM_END_TIME_CONSTRAINT)) { |
| if(pCurConstraint->EndTime.date < pCompareConstraint->EndTime.date) { |
| iNum--; |
| continue; |
| } else if(pCurConstraint->EndTime.date > pCompareConstraint->EndTime.date) |
| continue; |
| |
| if(pCurConstraint->EndTime.time < pCompareConstraint->EndTime.time) { |
| iNum--; |
| continue; |
| } else if(pCurConstraint->EndTime.date > pCompareConstraint->EndTime.date) |
| continue; |
| } |
| |
| if(0 != (pCurConstraint->Indicator & DRM_INTERVAL_CONSTRAINT)) { |
| if(pCurConstraint->Interval.date < pCompareConstraint->Interval.date) { |
| iNum--; |
| continue; |
| } else if(pCurConstraint->Interval.date > pCompareConstraint->Interval.date) |
| continue; |
| |
| if(pCurConstraint->Interval.time < pCompareConstraint->Interval.time) { |
| iNum--; |
| continue; |
| } else if(pCurConstraint->Interval.time > pCompareConstraint->Interval.time) |
| continue; |
| } |
| |
| if(0 != (pCurConstraint->Indicator & DRM_COUNT_CONSTRAINT)) { |
| if(pCurConstraint->Count < pCompareConstraint->Count) { |
| iNum--; |
| continue; |
| } else if(pCurConstraint->Count > pCompareConstraint->Count) |
| continue; |
| } |
| |
| if(i < j) |
| iNum--; |
| } |
| pNumOfPriority[iNum] = i; |
| } |
| |
| for (i = 0; i < validRoAmount; i++) { |
| /** check the right priority */ |
| if (pNumOfPriority[i] >= validRoAmount) |
| break; |
| |
| pCurRo = pRo + pNumOfPriority[i]; |
| |
| switch (permission) { |
| case DRM_PERMISSION_PLAY: |
| flag = |
| drm_startConsumeRights(&pCurRo->bIsPlayable, |
| &pCurRo->PlayConstraint, &writeFlag); |
| break; |
| case DRM_PERMISSION_DISPLAY: |
| flag = |
| drm_startConsumeRights(&pCurRo->bIsDisplayable, |
| &pCurRo->DisplayConstraint, |
| &writeFlag); |
| break; |
| case DRM_PERMISSION_EXECUTE: |
| flag = |
| drm_startConsumeRights(&pCurRo->bIsExecuteable, |
| &pCurRo->ExecuteConstraint, |
| &writeFlag); |
| break; |
| case DRM_PERMISSION_PRINT: |
| flag = |
| drm_startConsumeRights(&pCurRo->bIsPrintable, |
| &pCurRo->PrintConstraint, &writeFlag); |
| break; |
| default: |
| free(pNumOfPriority); |
| free(pRo); |
| return DRM_FAILURE; |
| } |
| |
| /* Here confirm the valid RO amount and set the writeFlag */ |
| if (0 == pCurRo->bIsPlayable && 0 == pCurRo->bIsDisplayable && |
| 0 == pCurRo->bIsExecuteable && 0 == pCurRo->bIsPrintable) { |
| int32_t iCurPri; |
| |
| /** refresh the right priority */ |
| iCurPri = pNumOfPriority[i]; |
| for(j = i; j < validRoAmount - 1; j++) |
| pNumOfPriority[j] = pNumOfPriority[j + 1]; |
| |
| if(iCurPri != validRoAmount - 1) { |
| memcpy(pCurRo, pRo + validRoAmount - 1, |
| sizeof(T_DRM_Rights)); |
| for(j = 0; j < validRoAmount -1; j++) { |
| if(validRoAmount - 1 == pNumOfPriority[j]) |
| pNumOfPriority[j] = iCurPri; |
| } |
| } |
| |
| /* Here means it is not the last one RO, so the invalid RO should be deleted */ |
| writeFlag = 1; |
| validRoAmount--; /* If current right is invalid */ |
| i--; |
| } |
| |
| /* If the flag is TRUE, this means: we have found a valid RO, so break, no need to check other RO */ |
| if (DRM_SUCCESS == flag) |
| break; |
| } |
| |
| if (1 == writeFlag) { |
| /* Delete the *.info first */ |
| //drm_removeIdInfoFile(id); |
| |
| if (FALSE == drm_writeOrReadInfo(id, pRo, &validRoAmount, SAVE_ALL_RO)) |
| flag = DRM_FAILURE; |
| } |
| |
| free(pNumOfPriority); |
| free(pRo); |
| return flag; |
| } |
| |
| |
| /* see svc_drm.h */ |
| int32_t SVC_drm_installRights(T_DRM_Input_Data data, T_DRM_Rights_Info* pRightsInfo) |
| { |
| uint8_t *buf; |
| int32_t dataLen, bufLen; |
| T_DRM_Rights rights; |
| |
| if (0 == data.inputHandle) |
| return DRM_RIGHTS_DATA_INVALID; |
| |
| /* Get input rights data length */ |
| dataLen = data.getInputDataLength(data.inputHandle); |
| if (dataLen <= 0) |
| return DRM_RIGHTS_DATA_INVALID; |
| |
| /* Check if the length is larger than DRM max malloc length */ |
| if (dataLen > DRM_MAX_MALLOC_LEN) |
| bufLen = DRM_MAX_MALLOC_LEN; |
| else |
| bufLen = dataLen; |
| |
| buf = (uint8_t *)malloc(bufLen); |
| if (NULL == buf) |
| return DRM_FAILURE; |
| |
| /* Read input data to buffer */ |
| if (0 >= data.readInputData(data.inputHandle, buf, bufLen)) { |
| free(buf); |
| return DRM_RIGHTS_DATA_INVALID; |
| } |
| |
| /* if the input mime type is unknown, DRM engine will try to recognize it. */ |
| if (TYPE_DRM_UNKNOWN == data.mimeType) |
| data.mimeType = getMimeType(buf, bufLen); |
| |
| switch(data.mimeType) { |
| case TYPE_DRM_MESSAGE: /* in case of Combined Delivery, extract the rights part to install */ |
| { |
| T_DRM_DM_Info dmInfo; |
| |
| memset(&dmInfo, 0, sizeof(T_DRM_DM_Info)); |
| if (FALSE == drm_parseDM(buf, bufLen, &dmInfo)) { |
| free(buf); |
| return DRM_RIGHTS_DATA_INVALID; |
| } |
| |
| /* if it is not Combined Delivery, it can not use to "SVC_drm_installRights" */ |
| if (COMBINED_DELIVERY != dmInfo.deliveryType || dmInfo.rightsOffset <= 0 || dmInfo.rightsLen <= 0) { |
| free(buf); |
| return DRM_RIGHTS_DATA_INVALID; |
| } |
| |
| memset(&rights, 0, sizeof(T_DRM_Rights)); |
| if (FALSE == drm_relParser(buf + dmInfo.rightsOffset, dmInfo.rightsLen, TYPE_DRM_RIGHTS_XML, &rights)) { |
| free(buf); |
| return DRM_RIGHTS_DATA_INVALID; |
| } |
| } |
| break; |
| case TYPE_DRM_RIGHTS_XML: |
| case TYPE_DRM_RIGHTS_WBXML: |
| memset(&rights, 0, sizeof(T_DRM_Rights)); |
| if (FALSE == drm_relParser(buf, bufLen, data.mimeType, &rights)) { |
| free(buf); |
| return DRM_RIGHTS_DATA_INVALID; |
| } |
| break; |
| case TYPE_DRM_CONTENT: /* DCF should not using "SVC_drm_installRights", it should be used to open a session. */ |
| case TYPE_DRM_UNKNOWN: |
| default: |
| free(buf); |
| return DRM_MEDIA_DATA_INVALID; |
| } |
| |
| free(buf); |
| |
| /* append the rights information to DRM engine storage */ |
| if (FALSE == drm_appendRightsInfo(&rights)) |
| return DRM_FAILURE; |
| |
| memset(pRightsInfo, 0, sizeof(T_DRM_Rights_Info)); |
| drm_getLicenseInfo(&rights, pRightsInfo); |
| |
| return DRM_SUCCESS; |
| } |
| |
| /* see svc_drm.h */ |
| int32_t SVC_drm_openSession(T_DRM_Input_Data data) |
| { |
| int32_t session; |
| int32_t dataLen; |
| T_DRM_Session_Node* s; |
| |
| if (0 == data.inputHandle) |
| return DRM_MEDIA_DATA_INVALID; |
| |
| /* Get input data length */ |
| dataLen = data.getInputDataLength(data.inputHandle); |
| if (dataLen <= 0) |
| return DRM_MEDIA_DATA_INVALID; |
| |
| s = newSession(data); |
| if (NULL == s) |
| return DRM_FAILURE; |
| |
| /* Check if the length is larger than DRM max malloc length */ |
| if (dataLen > DRM_MAX_MALLOC_LEN) |
| s->rawContentLen = DRM_MAX_MALLOC_LEN; |
| else |
| s->rawContentLen = dataLen; |
| |
| s->rawContent = (uint8_t *)malloc(s->rawContentLen); |
| if (NULL == s->rawContent) |
| return DRM_FAILURE; |
| |
| /* Read input data to buffer */ |
| if (0 >= data.readInputData(data.inputHandle, s->rawContent, s->rawContentLen)) { |
| freeSession(s); |
| return DRM_MEDIA_DATA_INVALID; |
| } |
| |
| /* if the input mime type is unknown, DRM engine will try to recognize it. */ |
| if (TYPE_DRM_UNKNOWN == data.mimeType) |
| data.mimeType = getMimeType(s->rawContent, s->rawContentLen); |
| |
| switch(data.mimeType) { |
| case TYPE_DRM_MESSAGE: |
| { |
| T_DRM_DM_Info dmInfo; |
| |
| memset(&dmInfo, 0, sizeof(T_DRM_DM_Info)); |
| if (FALSE == drm_parseDM(s->rawContent, s->rawContentLen, &dmInfo)) { |
| freeSession(s); |
| return DRM_MEDIA_DATA_INVALID; |
| } |
| |
| s->deliveryMethod = dmInfo.deliveryType; |
| |
| if (SEPARATE_DELIVERY_FL == s->deliveryMethod) |
| s->contentLength = DRM_UNKNOWN_DATA_LEN; |
| else |
| s->contentLength = dmInfo.contentLen; |
| |
| s->transferEncoding = dmInfo.transferEncoding; |
| s->contentOffset = dmInfo.contentOffset; |
| s->bEndData = FALSE; |
| strcpy((char *)s->contentType, (char *)dmInfo.contentType); |
| strcpy((char *)s->contentID, (char *)dmInfo.contentID); |
| |
| if (SEPARATE_DELIVERY_FL == s->deliveryMethod) { |
| s->infoStruct = (T_DRM_Dcf_Node *)malloc(sizeof(T_DRM_Dcf_Node)); |
| if (NULL == s->infoStruct) |
| return DRM_FAILURE; |
| memset(s->infoStruct, 0, sizeof(T_DRM_Dcf_Node)); |
| |
| ((T_DRM_Dcf_Node *)(s->infoStruct))->encContentLength = dmInfo.contentLen; |
| strcpy((char *)((T_DRM_Dcf_Node *)(s->infoStruct))->rightsIssuer, (char *)dmInfo.rightsIssuer); |
| break; |
| } |
| |
| if (DRM_MESSAGE_CODING_BASE64 == s->transferEncoding) { |
| s->infoStruct = (T_DRM_DM_Base64_Node *)malloc(sizeof(T_DRM_DM_Base64_Node)); |
| if (NULL == s->infoStruct) |
| return DRM_FAILURE; |
| memset(s->infoStruct, 0, sizeof(T_DRM_DM_Base64_Node)); |
| |
| strcpy((char *)((T_DRM_DM_Base64_Node *)(s->infoStruct))->boundary, (char *)dmInfo.boundary); |
| } else { |
| s->infoStruct = (T_DRM_DM_Binary_Node *)malloc(sizeof(T_DRM_DM_Binary_Node)); |
| if (NULL == s->infoStruct) |
| return DRM_FAILURE; |
| memset(s->infoStruct, 0, sizeof(T_DRM_DM_Binary_Node)); |
| |
| strcpy((char *)((T_DRM_DM_Binary_Node *)(s->infoStruct))->boundary, (char *)dmInfo.boundary); |
| } |
| |
| |
| if (DRM_MESSAGE_CODING_BASE64 == s->transferEncoding) { |
| if (s->contentLength > 0) { |
| int32_t encLen, decLen; |
| |
| encLen = s->contentLength; |
| decLen = encLen / DRM_B64_ENC_BLOCK * DRM_B64_DEC_BLOCK; |
| |
| decLen = drm_decodeBase64(s->rawContent, decLen, s->rawContent + s->contentOffset, &encLen); |
| s->contentLength = decLen; |
| } else { |
| int32_t encLen = DRM_MAX_MALLOC_LEN - s->contentOffset, decLen; |
| int32_t skipLen, needBytes, i; |
| uint8_t *pStart; |
| int32_t res, bFoundBoundary = FALSE; |
| |
| pStart = s->rawContent + s->contentOffset; |
| if (-1 == (skipLen = drm_skipCRLFinB64(pStart, encLen))) { |
| freeSession(s); |
| return DRM_FAILURE; |
| } |
| |
| needBytes = DRM_B64_ENC_BLOCK - ((encLen - skipLen) % DRM_B64_ENC_BLOCK); |
| if (needBytes < DRM_B64_ENC_BLOCK) { |
| s->rawContent = (uint8_t *)realloc(s->rawContent, DRM_MAX_MALLOC_LEN + needBytes); |
| if (NULL == s->rawContent) { |
| freeSession(s); |
| return DRM_FAILURE; |
| } |
| |
| i = 0; |
| while (i < needBytes) { |
| if (-1 != data.readInputData(data.inputHandle, s->rawContent + DRM_MAX_MALLOC_LEN + i, 1)) { |
| if ('\r' == *(s->rawContent + DRM_MAX_MALLOC_LEN + i) || '\n' == *(s->rawContent + DRM_MAX_MALLOC_LEN + i)) |
| continue; |
| i++; |
| } else |
| break; |
| } |
| encLen += i; |
| } |
| |
| res = drm_scanEndBoundary(pStart, encLen, ((T_DRM_DM_Base64_Node *)(s->infoStruct))->boundary); |
| if (-1 == res) { |
| freeSession(s); |
| return DRM_FAILURE; |
| } |
| if (-2 == res) { /* may be there is a boundary */ |
| int32_t boundaryLen, leftLen, readBytes; |
| char* pTmp = memrchr(pStart, '\r', encLen); |
| |
| if (NULL == pTmp) { |
| freeSession(s); |
| return DRM_FAILURE; /* conflict */ |
| } |
| boundaryLen = strlen((char *)((T_DRM_DM_Base64_Node *)(s->infoStruct))->boundary) + 2; /* 2 means: '\r''\n' */ |
| s->readBuf = (uint8_t *)malloc(boundaryLen); |
| if (NULL == s->readBuf) { |
| freeSession(s); |
| return DRM_FAILURE; |
| } |
| s->readBufOff = encLen - ((uint8_t *)pTmp - pStart); |
| s->readBufLen = boundaryLen - s->readBufOff; |
| memcpy(s->readBuf, pTmp, s->readBufOff); |
| readBytes = data.readInputData(data.inputHandle, s->readBuf + s->readBufOff, s->readBufLen); |
| if (-1 == readBytes || readBytes < s->readBufLen) { |
| freeSession(s); |
| return DRM_MEDIA_DATA_INVALID; |
| } |
| |
| if (0 == drm_scanEndBoundary(s->readBuf, boundaryLen, ((T_DRM_DM_Base64_Node *)(s->infoStruct))->boundary)) { |
| encLen = (uint8_t *)pTmp - pStart; /* yes, it is the end boundary */ |
| bFoundBoundary = TRUE; |
| } |
| } else { |
| if (res >= 0 && res < encLen) { |
| encLen = res; |
| bFoundBoundary = TRUE; |
| } |
| } |
| |
| decLen = encLen / DRM_B64_ENC_BLOCK * DRM_B64_DEC_BLOCK; |
| decLen = drm_decodeBase64(s->rawContent, decLen, s->rawContent + s->contentOffset, &encLen); |
| ((T_DRM_DM_Base64_Node *)(s->infoStruct))->b64DecodeDataLen = decLen; |
| if (bFoundBoundary) |
| s->contentLength = decLen; |
| } |
| } else { |
| /* binary data */ |
| if (DRM_UNKNOWN_DATA_LEN == s->contentLength) { |
| /* try to check whether there is boundary may be split */ |
| int32_t res, binContentLen; |
| uint8_t* pStart; |
| int32_t bFoundBoundary = FALSE; |
| |
| pStart = s->rawContent + s->contentOffset; |
| binContentLen = s->rawContentLen - s->contentOffset; |
| res = drm_scanEndBoundary(pStart, binContentLen, ((T_DRM_DM_Binary_Node *)(s->infoStruct))->boundary); |
| |
| if (-1 == res) { |
| freeSession(s); |
| return DRM_FAILURE; |
| } |
| |
| if (-2 == res) { /* may be the boundary is split */ |
| int32_t boundaryLen, leftLen, readBytes; |
| char* pTmp = memrchr(pStart, '\r', binContentLen); |
| |
| if (NULL == pTmp) { |
| freeSession(s); |
| return DRM_FAILURE; /* conflict */ |
| } |
| |
| boundaryLen = strlen((char *)((T_DRM_DM_Binary_Node *)(s->infoStruct))->boundary) + 2; /* 2 means: '\r''\n' */ |
| s->readBuf = (uint8_t *)malloc(boundaryLen); |
| if (NULL == s->readBuf) { |
| freeSession(s); |
| return DRM_FAILURE; |
| } |
| s->readBufOff = binContentLen - ((uint8_t *)pTmp - pStart); |
| s->readBufLen = boundaryLen - s->readBufOff; |
| memcpy(s->readBuf, pTmp, s->readBufOff); |
| readBytes = data.readInputData(data.inputHandle, s->readBuf + s->readBufOff, s->readBufLen); |
| if (-1 == readBytes || readBytes < s->readBufLen) { |
| freeSession(s); |
| return DRM_MEDIA_DATA_INVALID; |
| } |
| |
| if (0 == drm_scanEndBoundary(s->readBuf, boundaryLen, ((T_DRM_DM_Binary_Node *)(s->infoStruct))->boundary)) { |
| binContentLen = (uint8_t *)pTmp - pStart; /* yes, it is the end boundary */ |
| bFoundBoundary = TRUE; |
| } |
| } else { |
| if (res >= 0 && res < binContentLen) { |
| binContentLen = res; |
| bFoundBoundary = TRUE; |
| } |
| } |
| |
| if (bFoundBoundary) |
| s->contentLength = binContentLen; |
| } |
| } |
| } |
| break; |
| case TYPE_DRM_CONTENT: |
| { |
| T_DRM_DCF_Info dcfInfo; |
| uint8_t* pEncData = NULL; |
| |
| memset(&dcfInfo, 0, sizeof(T_DRM_DCF_Info)); |
| if (FALSE == drm_dcfParser(s->rawContent, s->rawContentLen, &dcfInfo, &pEncData)) { |
| freeSession(s); |
| return DRM_MEDIA_DATA_INVALID; |
| } |
| |
| s->infoStruct = (T_DRM_Dcf_Node *)malloc(sizeof(T_DRM_Dcf_Node)); |
| if (NULL == s->infoStruct) |
| return DRM_FAILURE; |
| memset(s->infoStruct, 0, sizeof(T_DRM_Dcf_Node)); |
| |
| s->deliveryMethod = SEPARATE_DELIVERY; |
| s->contentLength = dcfInfo.DecryptedDataLen; |
| ((T_DRM_Dcf_Node *)(s->infoStruct))->encContentLength = dcfInfo.EncryptedDataLen; |
| s->contentOffset = pEncData - s->rawContent; |
| strcpy((char *)s->contentType, (char *)dcfInfo.ContentType); |
| strcpy((char *)s->contentID, (char *)dcfInfo.ContentURI); |
| strcpy((char *)((T_DRM_Dcf_Node *)(s->infoStruct))->rightsIssuer, (char *)dcfInfo.Rights_Issuer); |
| } |
| break; |
| case TYPE_DRM_RIGHTS_XML: /* rights object should using "SVC_drm_installRights", it can not open a session */ |
| case TYPE_DRM_RIGHTS_WBXML: /* rights object should using "SVC_drm_installRights", it can not open a session */ |
| case TYPE_DRM_UNKNOWN: |
| default: |
| freeSession(s); |
| return DRM_MEDIA_DATA_INVALID; |
| } |
| |
| if ((SEPARATE_DELIVERY_FL == s->deliveryMethod || SEPARATE_DELIVERY == s->deliveryMethod) && |
| s->contentOffset + ((T_DRM_Dcf_Node *)(s->infoStruct))->encContentLength <= DRM_MAX_MALLOC_LEN) { |
| uint8_t keyValue[DRM_KEY_LEN]; |
| uint8_t lastDcfBuf[DRM_TWO_AES_BLOCK_LEN]; |
| int32_t seekPos, moreBytes; |
| |
| if (TRUE == drm_getKey(s->contentID, keyValue)) { |
| seekPos = s->contentOffset + ((T_DRM_Dcf_Node *)(s->infoStruct))->encContentLength - DRM_TWO_AES_BLOCK_LEN; |
| memcpy(lastDcfBuf, s->rawContent + seekPos, DRM_TWO_AES_BLOCK_LEN); |
| |
| if (TRUE == drm_updateDcfDataLen(lastDcfBuf, keyValue, &moreBytes)) { |
| s->contentLength = ((T_DRM_Dcf_Node *)(s->infoStruct))->encContentLength; |
| s->contentLength -= moreBytes; |
| } |
| } |
| } |
| |
| session = addSession(s); |
| if (-1 == session) |
| return DRM_FAILURE; |
| |
| return session; |
| } |
| |
| /* see svc_drm.h */ |
| int32_t SVC_drm_getDeliveryMethod(int32_t session) |
| { |
| T_DRM_Session_Node* s; |
| |
| if (session < 0) |
| return DRM_FAILURE; |
| |
| s = getSession(session); |
| if (NULL == s) |
| return DRM_SESSION_NOT_OPENED; |
| |
| return s->deliveryMethod; |
| } |
| |
| /* see svc_drm.h */ |
| int32_t SVC_drm_getContentType(int32_t session, uint8_t* mediaType) |
| { |
| T_DRM_Session_Node* s; |
| |
| if (session < 0 || NULL == mediaType) |
| return DRM_FAILURE; |
| |
| s = getSession(session); |
| if (NULL == s) |
| return DRM_SESSION_NOT_OPENED; |
| |
| strcpy((char *)mediaType, (char *)s->contentType); |
| |
| return DRM_SUCCESS; |
| } |
| |
| /* see svc_drm.h */ |
| int32_t SVC_drm_checkRights(int32_t session, int32_t permission) |
| { |
| T_DRM_Session_Node* s; |
| int32_t id; |
| T_DRM_Rights *pRo, *pCurRo; |
| int32_t roAmount; |
| int32_t i; |
| int32_t res = DRM_FAILURE; |
| |
| if (session < 0) |
| return DRM_FAILURE; |
| |
| s = getSession(session); |
| if (NULL == s) |
| return DRM_SESSION_NOT_OPENED; |
| |
| /* if it is Forward-Lock cases, check it and return directly */ |
| if (FORWARD_LOCK == s->deliveryMethod) { |
| if (DRM_PERMISSION_PLAY == permission || |
| DRM_PERMISSION_DISPLAY == permission || |
| DRM_PERMISSION_EXECUTE == permission || |
| DRM_PERMISSION_PRINT == permission) |
| return DRM_SUCCESS; |
| |
| return DRM_FAILURE; |
| } |
| |
| /* if try to forward, only DCF can be forwarded */ |
| if (DRM_PERMISSION_FORWARD == permission) { |
| if (SEPARATE_DELIVERY == s->deliveryMethod) |
| return DRM_SUCCESS; |
| |
| return DRM_FAILURE; |
| } |
| |
| /* The following will check CD or SD other permissions */ |
| if (FALSE == drm_readFromUidTxt(s->contentID, &id, GET_ID)) |
| return DRM_FAILURE; |
| |
| drm_writeOrReadInfo(id, NULL, &roAmount, GET_ROAMOUNT); |
| if (roAmount <= 0) |
| return DRM_FAILURE; |
| |
| pRo = malloc(roAmount * sizeof(T_DRM_Rights)); |
| if (NULL == pRo) |
| return DRM_FAILURE; |
| |
| drm_writeOrReadInfo(id, pRo, &roAmount, GET_ALL_RO); |
| |
| pCurRo = pRo; |
| for (i = 0; i < roAmount; i++) { |
| switch (permission) { |
| case DRM_PERMISSION_PLAY: |
| res = drm_startCheckRights(&(pCurRo->bIsPlayable), &(pCurRo->PlayConstraint)); |
| break; |
| case DRM_PERMISSION_DISPLAY: |
| res = drm_startCheckRights(&(pCurRo->bIsDisplayable), &(pCurRo->DisplayConstraint)); |
| break; |
| case DRM_PERMISSION_EXECUTE: |
| res = drm_startCheckRights(&(pCurRo->bIsExecuteable), &(pCurRo->ExecuteConstraint)); |
| break; |
| case DRM_PERMISSION_PRINT: |
| res = drm_startCheckRights(&(pCurRo->bIsPrintable), &(pCurRo->PrintConstraint)); |
| break; |
| default: |
| free(pRo); |
| return DRM_FAILURE; |
| } |
| |
| if (DRM_SUCCESS == res) { |
| free(pRo); |
| return DRM_SUCCESS; |
| } |
| pCurRo++; |
| } |
| |
| free(pRo); |
| return res; |
| } |
| |
| /* see svc_drm.h */ |
| int32_t SVC_drm_consumeRights(int32_t session, int32_t permission) |
| { |
| T_DRM_Session_Node* s; |
| int32_t id; |
| |
| if (session < 0) |
| return DRM_FAILURE; |
| |
| s = getSession(session); |
| if (NULL == s) |
| return DRM_SESSION_NOT_OPENED; |
| |
| if (DRM_PERMISSION_FORWARD == permission) { |
| if (SEPARATE_DELIVERY == s->deliveryMethod) |
| return DRM_SUCCESS; |
| |
| return DRM_FAILURE; |
| } |
| |
| if (FORWARD_LOCK == s->deliveryMethod) /* Forwardlock type have utter rights */ |
| return DRM_SUCCESS; |
| |
| if (FALSE == drm_readFromUidTxt(s->contentID, &id, GET_ID)) |
| return DRM_FAILURE; |
| |
| return drm_checkRoAndUpdate(id, permission); |
| } |
| |
| /* see svc_drm.h */ |
| int32_t SVC_drm_getContentLength(int32_t session) |
| { |
| T_DRM_Session_Node* s; |
| |
| if (session < 0) |
| return DRM_FAILURE; |
| |
| s = getSession(session); |
| if (NULL == s) |
| return DRM_SESSION_NOT_OPENED; |
| |
| if (DRM_UNKNOWN_DATA_LEN == s->contentLength && s->contentOffset + ((T_DRM_Dcf_Node *)(s->infoStruct))->encContentLength <= DRM_MAX_MALLOC_LEN && |
| (SEPARATE_DELIVERY == s->deliveryMethod || SEPARATE_DELIVERY_FL == s->deliveryMethod)) { |
| uint8_t keyValue[DRM_KEY_LEN]; |
| uint8_t lastDcfBuf[DRM_TWO_AES_BLOCK_LEN]; |
| int32_t seekPos, moreBytes; |
| |
| if (TRUE == drm_getKey(s->contentID, keyValue)) { |
| seekPos = s->contentOffset + ((T_DRM_Dcf_Node *)(s->infoStruct))->encContentLength - DRM_TWO_AES_BLOCK_LEN; |
| memcpy(lastDcfBuf, s->rawContent + seekPos, DRM_TWO_AES_BLOCK_LEN); |
| |
| if (TRUE == drm_updateDcfDataLen(lastDcfBuf, keyValue, &moreBytes)) { |
| s->contentLength = ((T_DRM_Dcf_Node *)(s->infoStruct))->encContentLength; |
| s->contentLength -= moreBytes; |
| } |
| } |
| } |
| |
| return s->contentLength; |
| } |
| |
| static int32_t drm_readAesData(uint8_t* buf, T_DRM_Session_Node* s, int32_t aesStart, int32_t bufLen) |
| { |
| if (NULL == buf || NULL == s || aesStart < 0 || bufLen < 0) |
| return -1; |
| |
| if (aesStart - s->contentOffset + bufLen > ((T_DRM_Dcf_Node *)(s->infoStruct))->encContentLength) |
| return -2; |
| |
| if (aesStart < DRM_MAX_MALLOC_LEN) { |
| if (aesStart + bufLen <= DRM_MAX_MALLOC_LEN) { /* read from buffer */ |
| memcpy(buf, s->rawContent + aesStart, bufLen); |
| return bufLen; |
| } else { /* first read from buffer and then from InputStream */ |
| int32_t point = DRM_MAX_MALLOC_LEN - aesStart; |
| int32_t res; |
| |
| if (((T_DRM_Dcf_Node *)(s->infoStruct))->bAesBackupBuf) { |
| memcpy(buf, ((T_DRM_Dcf_Node *)(s->infoStruct))->aesBackupBuf, DRM_ONE_AES_BLOCK_LEN); |
| res = s->readInputDataFunc(s->inputHandle, buf + DRM_ONE_AES_BLOCK_LEN, DRM_ONE_AES_BLOCK_LEN); |
| if (0 == res || -1 == res) |
| return -1; |
| |
| res += DRM_ONE_AES_BLOCK_LEN; |
| } else { |
| memcpy(buf, s->rawContent + aesStart, point); |
| res = s->readInputDataFunc(s->inputHandle, buf + point, bufLen - point); |
| if (0 == res || -1 == res) |
| return -1; |
| |
| res += point; |
| } |
| |
| memcpy(((T_DRM_Dcf_Node *)(s->infoStruct))->aesBackupBuf, buf + DRM_ONE_AES_BLOCK_LEN, DRM_ONE_AES_BLOCK_LEN); |
| ((T_DRM_Dcf_Node *)(s->infoStruct))->bAesBackupBuf = TRUE; |
| |
| return res; |
| } |
| } else { /* read from InputStream */ |
| int32_t res; |
| |
| memcpy(buf, ((T_DRM_Dcf_Node *)(s->infoStruct))->aesBackupBuf, DRM_ONE_AES_BLOCK_LEN); |
| res = s->readInputDataFunc(s->inputHandle, buf + DRM_ONE_AES_BLOCK_LEN, DRM_ONE_AES_BLOCK_LEN); |
| |
| if (0 == res || -1 == res) |
| return -1; |
| |
| memcpy(((T_DRM_Dcf_Node *)(s->infoStruct))->aesBackupBuf, buf + DRM_ONE_AES_BLOCK_LEN, DRM_ONE_AES_BLOCK_LEN); |
| |
| return DRM_ONE_AES_BLOCK_LEN + res; |
| } |
| } |
| |
| static int32_t drm_readContentFromBuf(T_DRM_Session_Node* s, int32_t offset, uint8_t* mediaBuf, int32_t mediaBufLen) |
| { |
| int32_t readBytes; |
| |
| if (offset > s->contentLength) |
| return DRM_FAILURE; |
| |
| if (offset == s->contentLength) |
| return DRM_MEDIA_EOF; |
| |
| if (offset + mediaBufLen > s->contentLength) |
| readBytes = s->contentLength - offset; |
| else |
| readBytes = mediaBufLen; |
| |
| if (DRM_MESSAGE_CODING_BASE64 == s->transferEncoding) |
| memcpy(mediaBuf, s->rawContent + offset, readBytes); |
| else |
| memcpy(mediaBuf, s->rawContent + s->contentOffset + offset, readBytes); |
| |
| return readBytes; |
| } |
| |
| static int32_t drm_readB64ContentFromInputStream(T_DRM_Session_Node* s, int32_t offset, uint8_t* mediaBuf, int32_t mediaBufLen) |
| { |
| uint8_t encBuf[DRM_B64_ENC_BLOCK], decBuf[DRM_B64_DEC_BLOCK]; |
| int32_t encLen, decLen; |
| int32_t i, j, piece, leftLen, firstBytes; |
| int32_t readBytes = 0; |
| |
| if (offset < ((T_DRM_DM_Base64_Node *)(s->infoStruct))->b64DecodeDataLen) { |
| readBytes = ((T_DRM_DM_Base64_Node *)(s->infoStruct))->b64DecodeDataLen - offset; |
| memcpy(mediaBuf, s->rawContent + offset, readBytes); |
| } else { |
| if (s->bEndData) |
| return DRM_MEDIA_EOF; |
| |
| firstBytes = offset % DRM_B64_DEC_BLOCK; |
| if (firstBytes > 0) { |
| if (DRM_B64_DEC_BLOCK - firstBytes >= mediaBufLen) { |
| readBytes = mediaBufLen; |
| memcpy(mediaBuf, ((T_DRM_DM_Base64_Node *)(s->infoStruct))->b64DecodeData + firstBytes, readBytes); |
| return readBytes; |
| } |
| |
| readBytes = DRM_B64_DEC_BLOCK - firstBytes; |
| memcpy(mediaBuf, ((T_DRM_DM_Base64_Node *)(s->infoStruct))->b64DecodeData + firstBytes, readBytes); |
| } |
| } |
| |
| leftLen = mediaBufLen - readBytes; |
| encLen = (leftLen - 1) / DRM_B64_DEC_BLOCK * DRM_B64_ENC_BLOCK + DRM_B64_ENC_BLOCK; |
| piece = encLen / DRM_B64_ENC_BLOCK; |
| |
| for (i = 0; i < piece; i++) { |
| j = 0; |
| while (j < DRM_B64_ENC_BLOCK) { |
| if (NULL != s->readBuf && s->readBufLen > 0) { /* read from backup buffer */ |
| *(encBuf + j) = s->readBuf[s->readBufOff]; |
| s->readBufOff++; |
| s->readBufLen--; |
| } else { /* read from InputStream */ |
| if (0 == s->readInputDataFunc(s->inputHandle, encBuf + j, 1)) |
| return DRM_MEDIA_DATA_INVALID; |
| } |
| |
| if ('\r' == *(encBuf + j) || '\n' == *(encBuf + j)) |
| continue; /* skip CRLF */ |
| |
| if ('-' == *(encBuf + j)) { |
| int32_t k, len; |
| |
| /* invalid base64 data, it comes to end boundary */ |
| if (0 != j) |
| return DRM_MEDIA_DATA_INVALID; |
| |
| /* check whether it is really the boundary */ |
| len = strlen((char *)((T_DRM_DM_Base64_Node *)(s->infoStruct))->boundary); |
| if (NULL == s->readBuf) { |
| s->readBuf = (uint8_t *)malloc(len); |
| if (NULL == s->readBuf) |
| return DRM_FAILURE; |
| } |
| |
| s->readBuf[0] = '-'; |
| for (k = 0; k < len - 1; k++) { |
| if (NULL != s->readBuf && s->readBufLen > 0) { /* read from backup buffer */ |
| *(s->readBuf + k + 1) = s->readBuf[s->readBufOff]; |
| s->readBufOff++; |
| s->readBufLen--; |
| } else { /* read from InputStream */ |
| if (-1 == s->readInputDataFunc(s->inputHandle, s->readBuf + k + 1, 1)) |
| return DRM_MEDIA_DATA_INVALID; |
| } |
| } |
| if (0 == memcmp(s->readBuf, ((T_DRM_DM_Base64_Node *)(s->infoStruct))->boundary, len)) |
| s->bEndData = TRUE; |
| else |
| return DRM_MEDIA_DATA_INVALID; |
| |
| break; |
| } |
| j++; |
| } |
| |
| if (TRUE == s->bEndData) { /* it means come to the end of base64 data */ |
| if (0 == readBytes) |
| return DRM_MEDIA_EOF; |
| |
| break; |
| } |
| |
| encLen = DRM_B64_ENC_BLOCK; |
| decLen = DRM_B64_DEC_BLOCK; |
| if (-1 == (decLen = drm_decodeBase64(decBuf, decLen, encBuf, &encLen))) |
| return DRM_MEDIA_DATA_INVALID; |
| |
| if (leftLen >= decLen) { |
| memcpy(mediaBuf + readBytes, decBuf, decLen); |
| readBytes += decLen; |
| leftLen -= decLen; |
| } else { |
| if (leftLen > 0) { |
| memcpy(mediaBuf + readBytes, decBuf, leftLen); |
| readBytes += leftLen; |
| } |
| break; |
| } |
| } |
| memcpy(((T_DRM_DM_Base64_Node *)(s->infoStruct))->b64DecodeData, decBuf, DRM_B64_DEC_BLOCK); |
| |
| return readBytes; |
| } |
| |
| static int32_t drm_readBase64Content(T_DRM_Session_Node* s, int32_t offset, uint8_t* mediaBuf, int32_t mediaBufLen) |
| { |
| int32_t readBytes; |
| |
| /* when the content length has been well-known */ |
| if (s->contentLength >= 0) |
| readBytes = drm_readContentFromBuf(s, offset, mediaBuf, mediaBufLen); |
| else /* else when the content length has not been well-known yet */ |
| if (offset < ((T_DRM_DM_Base64_Node *)(s->infoStruct))->b64DecodeDataLen) |
| if (offset + mediaBufLen <= ((T_DRM_DM_Base64_Node *)(s->infoStruct))->b64DecodeDataLen) { |
| readBytes = mediaBufLen; |
| memcpy(mediaBuf, s->rawContent + offset, readBytes); |
| } else |
| readBytes = drm_readB64ContentFromInputStream(s, offset, mediaBuf, mediaBufLen); |
| else |
| readBytes = drm_readB64ContentFromInputStream(s, offset, mediaBuf, mediaBufLen); |
| |
| return readBytes; |
| } |
| |
| static int32_t drm_readBinaryContentFromInputStream(T_DRM_Session_Node* s, int32_t offset, uint8_t* mediaBuf, int32_t mediaBufLen) |
| { |
| int32_t res = 0, readBytes = 0; |
| int32_t leftLen; |
| |
| if (s->contentOffset + offset < DRM_MAX_MALLOC_LEN) { |
| readBytes = DRM_MAX_MALLOC_LEN - s->contentOffset - offset; |
| memcpy(mediaBuf, s->rawContent + s->contentOffset + offset, readBytes); |
| } else |
| if (s->bEndData) |
| return DRM_MEDIA_EOF; |
| |
| leftLen = mediaBufLen - readBytes; |
| |
| if (NULL != s->readBuf && s->readBufLen > 0) { /* read from backup buffer */ |
| if (leftLen <= s->readBufLen) { |
| memcpy(mediaBuf, s->readBuf + s->readBufOff, leftLen); |
| s->readBufOff += leftLen; |
| s->readBufLen -= leftLen; |
| readBytes += leftLen; |
| leftLen = 0; |
| } else { |
| memcpy(mediaBuf, s->readBuf + s->readBufOff, s->readBufLen); |
| s->readBufOff += s->readBufLen; |
| leftLen -= s->readBufLen; |
| readBytes += s->readBufLen; |
| s->readBufLen = 0; |
| } |
| } |
| |
| if (leftLen > 0) { |
| res = s->readInputDataFunc(s->inputHandle, mediaBuf + readBytes, mediaBufLen - readBytes); |
| if (-1 == res) |
| return DRM_MEDIA_DATA_INVALID; |
| } |
| |
| readBytes += res; |
| res = drm_scanEndBoundary(mediaBuf, readBytes, ((T_DRM_DM_Binary_Node *)(s->infoStruct))->boundary); |
| if (-1 == res) |
| return DRM_MEDIA_DATA_INVALID; |
| if (-2 == res) { /* may be the boundary is split */ |
| int32_t boundaryLen, len, off, k; |
| char* pTmp = memrchr(mediaBuf, '\r', readBytes); |
| |
| if (NULL == pTmp) |
| return DRM_FAILURE; /* conflict */ |
| |
| boundaryLen = strlen((char *)((T_DRM_DM_Binary_Node *)(s->infoStruct))->boundary) + 2; /* 2 means: '\r''\n' */ |
| if (NULL == s->readBuf) { |
| s->readBuf = (uint8_t *)malloc(boundaryLen); |
| if (NULL == s->readBuf) |
| return DRM_FAILURE; |
| } |
| |
| off = readBytes - ((uint8_t *)pTmp - mediaBuf); |
| len = boundaryLen - off; |
| memcpy(s->readBuf, pTmp, off); |
| for (k = 0; k < boundaryLen - off; k++) { |
| if (NULL != s->readBuf && s->readBufLen > 0) { /* read from backup buffer */ |
| *(s->readBuf + k + off) = s->readBuf[s->readBufOff]; |
| s->readBufOff++; |
| s->readBufLen--; |
| } else { /* read from InputStream */ |
| if (-1 == s->readInputDataFunc(s->inputHandle, s->readBuf + k + off, 1)) |
| return DRM_MEDIA_DATA_INVALID; |
| } |
| } |
| s->readBufOff = off; |
| s->readBufLen = len; |
| |
| if (0 == drm_scanEndBoundary(s->readBuf, boundaryLen, ((T_DRM_DM_Binary_Node *)(s->infoStruct))->boundary)) { |
| readBytes = (uint8_t *)pTmp - mediaBuf; /* yes, it is the end boundary */ |
| s->bEndData = TRUE; |
| } |
| } else { |
| if (res >= 0 && res < readBytes) { |
| readBytes = res; |
| s->bEndData = TRUE; |
| } |
| } |
| |
| if (s->bEndData) { |
| if (0 == readBytes) |
| return DRM_MEDIA_EOF; |
| } |
| |
| return readBytes; |
| } |
| |
| static int32_t drm_readBinaryContent(T_DRM_Session_Node* s, int32_t offset, uint8_t* mediaBuf, int32_t mediaBufLen) |
| { |
| int32_t readBytes; |
| |
| if (s->contentLength >= 0) |
| readBytes = drm_readContentFromBuf(s, offset, mediaBuf, mediaBufLen); |
| else /* else when the content length has not been well-known yet */ |
| if (s->contentOffset + offset < DRM_MAX_MALLOC_LEN) |
| if (s->contentOffset + offset + mediaBufLen <= DRM_MAX_MALLOC_LEN) { |
| readBytes = mediaBufLen; |
| memcpy(mediaBuf, s->rawContent + s->contentOffset + offset, readBytes); |
| } else |
| readBytes = drm_readBinaryContentFromInputStream(s, offset, mediaBuf, mediaBufLen); |
| else |
| readBytes = drm_readBinaryContentFromInputStream(s, offset, mediaBuf, mediaBufLen); |
| |
| return readBytes; |
| } |
| |
| static int32_t drm_readAesContent(T_DRM_Session_Node* s, int32_t offset, uint8_t* mediaBuf, int32_t mediaBufLen) |
| { |
| uint8_t keyValue[DRM_KEY_LEN]; |
| uint8_t buf[DRM_TWO_AES_BLOCK_LEN]; |
| int32_t readBytes = 0; |
| int32_t bufLen, piece, i, copyBytes, leftBytes; |
| int32_t aesStart, mediaStart, mediaBufOff; |
| AES_KEY key; |
| |
| if (FALSE == drm_getKey(s->contentID, keyValue)) |
| return DRM_NO_RIGHTS; |
| |
| /* when the content length has been well-known */ |
| if (s->contentLength > 0) { |
| if (offset > s->contentLength) |
| return DRM_FAILURE; |
| |
| if (offset == s->contentLength) |
| return DRM_MEDIA_EOF; |
| |
| if (offset + mediaBufLen > s->contentLength) |
| readBytes = s->contentLength - offset; |
| else |
| readBytes = mediaBufLen; |
| |
| aesStart = s->contentOffset + (offset / DRM_ONE_AES_BLOCK_LEN * DRM_ONE_AES_BLOCK_LEN); |
| piece = (offset + readBytes - 1) / DRM_ONE_AES_BLOCK_LEN - offset / DRM_ONE_AES_BLOCK_LEN + 2; |
| mediaStart = offset % DRM_ONE_AES_BLOCK_LEN; |
| |
| AES_set_decrypt_key(keyValue, DRM_KEY_LEN * 8, &key); |
| mediaBufOff = 0; |
| leftBytes = readBytes; |
| |
| for (i = 0; i < piece - 1; i++) { |
| memcpy(buf, s->rawContent + aesStart + i * DRM_ONE_AES_BLOCK_LEN, DRM_TWO_AES_BLOCK_LEN); |
| bufLen = DRM_TWO_AES_BLOCK_LEN; |
| |
| if (drm_aesDecBuffer(buf, &bufLen, &key) < 0) |
| return DRM_MEDIA_DATA_INVALID; |
| |
| if (0 != i) |
| mediaStart = 0; |
| |
| if (bufLen - mediaStart <= leftBytes) |
| copyBytes = bufLen - mediaStart; |
| else |
| copyBytes = leftBytes; |
| |
| memcpy(mediaBuf + mediaBufOff, buf + mediaStart, copyBytes); |
| leftBytes -= copyBytes; |
| mediaBufOff += copyBytes; |
| } |
| } else { |
| int32_t res; |
| |
| if (s->bEndData) |
| return DRM_MEDIA_EOF; |
| |
| if (((T_DRM_Dcf_Node *)(s->infoStruct))->aesDecDataLen > ((T_DRM_Dcf_Node *)(s->infoStruct))->aesDecDataOff) { |
| if (mediaBufLen < ((T_DRM_Dcf_Node *)(s->infoStruct))->aesDecDataLen - ((T_DRM_Dcf_Node *)(s->infoStruct))->aesDecDataOff) |
| copyBytes = mediaBufLen; |
| else |
| copyBytes = ((T_DRM_Dcf_Node *)(s->infoStruct))->aesDecDataLen - ((T_DRM_Dcf_Node *)(s->infoStruct))->aesDecDataOff; |
| |
| memcpy(mediaBuf, ((T_DRM_Dcf_Node *)(s->infoStruct))->aesDecData + ((T_DRM_Dcf_Node *)(s->infoStruct))->aesDecDataOff, copyBytes); |
| ((T_DRM_Dcf_Node *)(s->infoStruct))->aesDecDataOff += copyBytes; |
| readBytes += copyBytes; |
| } |
| |
| leftBytes = mediaBufLen - readBytes; |
| if (0 == leftBytes) |
| return readBytes; |
| if (leftBytes < 0) |
| return DRM_FAILURE; |
| |
| offset += readBytes; |
| aesStart = s->contentOffset + (offset / DRM_ONE_AES_BLOCK_LEN * DRM_ONE_AES_BLOCK_LEN); |
| piece = (offset + leftBytes - 1) / DRM_ONE_AES_BLOCK_LEN - offset / DRM_ONE_AES_BLOCK_LEN + 2; |
| mediaBufOff = readBytes; |
| |
| AES_set_decrypt_key(keyValue, DRM_KEY_LEN * 8, &key); |
| |
| for (i = 0; i < piece - 1; i++) { |
| if (-1 == (res = drm_readAesData(buf, s, aesStart, DRM_TWO_AES_BLOCK_LEN))) |
| return DRM_MEDIA_DATA_INVALID; |
| |
| if (-2 == res) |
| break; |
| |
| bufLen = DRM_TWO_AES_BLOCK_LEN; |
| aesStart += DRM_ONE_AES_BLOCK_LEN; |
| |
| if (drm_aesDecBuffer(buf, &bufLen, &key) < 0) |
| return DRM_MEDIA_DATA_INVALID; |
| |
| drm_discardPaddingByte(buf, &bufLen); |
| |
| if (bufLen <= leftBytes) |
| copyBytes = bufLen; |
| else |
| copyBytes = leftBytes; |
| |
| memcpy(mediaBuf + mediaBufOff, buf, copyBytes); |
| leftBytes -= copyBytes; |
| mediaBufOff += copyBytes; |
| readBytes += copyBytes; |
| } |
| |
| memcpy(((T_DRM_Dcf_Node *)(s->infoStruct))->aesDecData, buf, DRM_ONE_AES_BLOCK_LEN); |
| ((T_DRM_Dcf_Node *)(s->infoStruct))->aesDecDataLen = bufLen; |
| ((T_DRM_Dcf_Node *)(s->infoStruct))->aesDecDataOff = copyBytes; |
| |
| if (aesStart - s->contentOffset > ((T_DRM_Dcf_Node *)(s->infoStruct))->encContentLength - DRM_TWO_AES_BLOCK_LEN && ((T_DRM_Dcf_Node *)(s->infoStruct))->aesDecDataOff == ((T_DRM_Dcf_Node *)(s->infoStruct))->aesDecDataLen) { |
| s->bEndData = TRUE; |
| if (0 == readBytes) |
| return DRM_MEDIA_EOF; |
| } |
| } |
| |
| return readBytes; |
| } |
| |
| /* see svc_drm.h */ |
| int32_t SVC_drm_getContent(int32_t session, int32_t offset, uint8_t* mediaBuf, int32_t mediaBufLen) |
| { |
| T_DRM_Session_Node* s; |
| int32_t readBytes; |
| |
| if (session < 0 || offset < 0 || NULL == mediaBuf || mediaBufLen <= 0) |
| return DRM_FAILURE; |
| |
| s = getSession(session); |
| if (NULL == s) |
| return DRM_SESSION_NOT_OPENED; |
| |
| if (0 >= s->getInputDataLengthFunc(s->inputHandle)) |
| return DRM_MEDIA_DATA_INVALID; |
| |
| switch(s->deliveryMethod) { |
| case FORWARD_LOCK: |
| case COMBINED_DELIVERY: |
| if (DRM_MESSAGE_CODING_BASE64 == s->transferEncoding) |
| readBytes = drm_readBase64Content(s, offset, mediaBuf, mediaBufLen); |
| else /* binary */ |
| readBytes = drm_readBinaryContent(s, offset, mediaBuf, mediaBufLen); |
| break; |
| case SEPARATE_DELIVERY: |
| case SEPARATE_DELIVERY_FL: |
| readBytes = drm_readAesContent(s, offset, mediaBuf, mediaBufLen); |
| break; |
| default: |
| return DRM_FAILURE; |
| } |
| |
| return readBytes; |
| } |
| |
| /* see svc_drm.h */ |
| int32_t SVC_drm_getRightsIssuer(int32_t session, uint8_t* rightsIssuer) |
| { |
| T_DRM_Session_Node* s; |
| |
| if (session < 0 || NULL == rightsIssuer) |
| return DRM_FAILURE; |
| |
| s = getSession(session); |
| if (NULL == s) |
| return DRM_SESSION_NOT_OPENED; |
| |
| if (SEPARATE_DELIVERY == s->deliveryMethod || SEPARATE_DELIVERY_FL == s->deliveryMethod) { |
| strcpy((char *)rightsIssuer, (char *)((T_DRM_Dcf_Node *)(s->infoStruct))->rightsIssuer); |
| return DRM_SUCCESS; |
| } |
| |
| return DRM_NOT_SD_METHOD; |
| } |
| |
| /* see svc_drm.h */ |
| int32_t SVC_drm_getRightsInfo(int32_t session, T_DRM_Rights_Info* rights) |
| { |
| T_DRM_Session_Node* s; |
| T_DRM_Rights rightsInfo; |
| int32_t roAmount, id; |
| |
| if (session < 0 || NULL == rights) |
| return DRM_FAILURE; |
| |
| s = getSession(session); |
| if (NULL == s) |
| return DRM_SESSION_NOT_OPENED; |
| |
| if (FORWARD_LOCK == s->deliveryMethod) { |
| strcpy((char *)rights->roId, "ForwardLock"); |
| rights->displayRights.indicator = DRM_NO_CONSTRAINT; |
| rights->playRights.indicator = DRM_NO_CONSTRAINT; |
| rights->executeRights.indicator = DRM_NO_CONSTRAINT; |
| rights->printRights.indicator = DRM_NO_CONSTRAINT; |
| return DRM_SUCCESS; |
| } |
| |
| if (FALSE == drm_readFromUidTxt(s->contentID, &id, GET_ID)) |
| return DRM_NO_RIGHTS; |
| |
| if (FALSE == drm_writeOrReadInfo(id, NULL, &roAmount, GET_ROAMOUNT)) |
| return DRM_FAILURE; |
| |
| if (roAmount < 0) |
| return DRM_NO_RIGHTS; |
| |
| /* some rights has been installed, but now there is no valid rights */ |
| if (0 == roAmount) { |
| strcpy((char *)rights->roId, s->contentID); |
| rights->displayRights.indicator = DRM_NO_PERMISSION; |
| rights->playRights.indicator = DRM_NO_PERMISSION; |
| rights->executeRights.indicator = DRM_NO_PERMISSION; |
| rights->printRights.indicator = DRM_NO_PERMISSION; |
| return DRM_SUCCESS; |
| } |
| |
| roAmount = 1; |
| memset(&rightsInfo, 0, sizeof(T_DRM_Rights)); |
| if (FALSE == drm_writeOrReadInfo(id, &rightsInfo, &roAmount, GET_A_RO)) |
| return DRM_FAILURE; |
| |
| memset(rights, 0, sizeof(T_DRM_Rights_Info)); |
| drm_getLicenseInfo(&rightsInfo, rights); |
| return DRM_SUCCESS; |
| } |
| |
| /* see svc_drm.h */ |
| int32_t SVC_drm_closeSession(int32_t session) |
| { |
| if (session < 0) |
| return DRM_FAILURE; |
| |
| if (NULL == getSession(session)) |
| return DRM_SESSION_NOT_OPENED; |
| |
| removeSession(session); |
| |
| return DRM_SUCCESS; |
| } |
| |
| /* see svc_drm.h */ |
| int32_t SVC_drm_updateRights(uint8_t* contentID, int32_t permission) |
| { |
| int32_t id; |
| |
| if (NULL == contentID) |
| return DRM_FAILURE; |
| |
| if (FALSE == drm_readFromUidTxt(contentID, &id, GET_ID)) |
| return DRM_FAILURE; |
| |
| return drm_checkRoAndUpdate(id, permission); |
| } |
| |
| /* see svc_drm.h */ |
| int32_t SVC_drm_viewAllRights(T_DRM_Rights_Info_Node **ppRightsInfo) |
| { |
| T_DRM_Rights_Info_Node rightsNode; |
| int32_t maxId, id, roAmount, j; |
| T_DRM_Rights rights; |
| |
| memset(&rights, 0, sizeof(T_DRM_Rights)); |
| |
| if (NULL == ppRightsInfo) |
| return DRM_FAILURE; |
| |
| *ppRightsInfo = NULL; |
| |
| maxId = drm_getMaxIdFromUidTxt(); |
| if (-1 == maxId) |
| return DRM_FAILURE; |
| |
| for (id = 1; id <= maxId; id++) { |
| drm_writeOrReadInfo(id, NULL, &roAmount, GET_ROAMOUNT); |
| if (roAmount <= 0) /* this means there is not any rights */ |
| continue; |
| |
| for (j = 1; j <= roAmount; j++) { |
| if (FALSE == drm_writeOrReadInfo(id, &rights, &j, GET_A_RO)) |
| continue; |
| |
| memset(&rightsNode, 0, sizeof(T_DRM_Rights_Info_Node)); |
| |
| drm_getLicenseInfo(&rights, &(rightsNode.roInfo)); |
| |
| if (FALSE == drm_addRightsNodeToList(ppRightsInfo, &rightsNode)) |
| continue; |
| } |
| } |
| return DRM_SUCCESS; |
| } |
| |
| /* see svc_drm.h */ |
| int32_t SVC_drm_freeRightsInfoList(T_DRM_Rights_Info_Node *pRightsHeader) |
| { |
| T_DRM_Rights_Info_Node *pNode, *pTmp; |
| |
| if (NULL == pRightsHeader) |
| return DRM_FAILURE; |
| |
| pNode = pRightsHeader; |
| |
| while (NULL != pNode) { |
| pTmp = pNode; |
| pNode = pNode->next; |
| free(pTmp); |
| } |
| return DRM_SUCCESS; |
| } |
| |
| /* see svc_drm.h */ |
| int32_t SVC_drm_deleteRights(uint8_t* roId) |
| { |
| int32_t maxId, id, roAmount, j; |
| T_DRM_Rights rights; |
| |
| memset(&rights, 0, sizeof(T_DRM_Rights)); |
| |
| if (NULL == roId) |
| return DRM_FAILURE; |
| |
| maxId = drm_getMaxIdFromUidTxt(); |
| if (-1 == maxId) |
| return DRM_NO_RIGHTS; |
| |
| for (id = 1; id <= maxId; id++) { |
| drm_writeOrReadInfo(id, NULL, &roAmount, GET_ROAMOUNT); |
| if (roAmount <= 0) /* this means there is not any rights */ |
| continue; |
| |
| for (j = 1; j <= roAmount; j++) { |
| if (FALSE == drm_writeOrReadInfo(id, &rights, &j, GET_A_RO)) |
| continue; |
| |
| /* here find the RO which will be deleted */ |
| if (0 == strcmp((char *)rights.uid, (char *)roId)) { |
| T_DRM_Rights *pAllRights; |
| |
| pAllRights = (T_DRM_Rights *)malloc(roAmount * sizeof(T_DRM_Rights)); |
| if (NULL == pAllRights) |
| return DRM_FAILURE; |
| |
| drm_writeOrReadInfo(id, pAllRights, &roAmount, GET_ALL_RO); |
| roAmount--; |
| if (0 == roAmount) { /* this means it is the last one rights */ |
| drm_removeIdInfoFile(id); /* delete the id.info file first */ |
| drm_updateUidTxtWhenDelete(id); /* update uid.txt file */ |
| free(pAllRights); |
| return DRM_SUCCESS; |
| } else /* using the last one rights instead of the deleted one */ |
| memcpy(pAllRights + (j - 1), pAllRights + roAmount, sizeof(T_DRM_Rights)); |
| |
| /* delete the id.info file first */ |
| // drm_removeIdInfoFile(id); |
| |
| if (FALSE == drm_writeOrReadInfo(id, pAllRights, &roAmount, SAVE_ALL_RO)) { |
| free(pAllRights); |
| return DRM_FAILURE; |
| } |
| |
| free(pAllRights); |
| return DRM_SUCCESS; |
| } |
| } |
| } |
| |
| return DRM_FAILURE; |
| } |