| /* |
| * 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 <parser_dcf.h> |
| #include <svc_drm.h> |
| |
| static int32_t drm_parseUintVar(uint8_t * buffer, uint8_t * len) |
| { |
| int32_t i; |
| int32_t byteLen; |
| int32_t sum; |
| |
| if (NULL == buffer) |
| return DRM_UINT_VAR_ERR; |
| |
| byteLen = 0; |
| while ((buffer[byteLen] & UINT_VAR_FLAG) > 0 && byteLen < MAX_UINT_VAR_BYTE) /* UINT_VAR_FLAG == 0x80 */ |
| byteLen++; |
| |
| if (byteLen >= MAX_UINT_VAR_BYTE) /* MAX_UINT_VAR_BYTE == 5 */ |
| return DRM_UINT_VAR_ERR; /* The var int is too large, and that is impossible */ |
| |
| *len = (uint8_t)(byteLen + 1); |
| sum = buffer[byteLen]; |
| for (i = byteLen - 1; i >= 0; i--) |
| sum += ((buffer[i] & UINT_VAR_DATA) << 7 * (byteLen - i)); /* UINT_VAR_DATA == 0x7F */ |
| |
| return sum; |
| } |
| |
| /* See parser_dcf.h */ |
| int32_t drm_dcfParser(uint8_t *buffer, int32_t bufferLen, T_DRM_DCF_Info *pDcfInfo, |
| uint8_t **ppEncryptedData) |
| { |
| uint8_t *tmpBuf; |
| uint8_t *pStart, *pEnd; |
| uint8_t *pHeader, *pData; |
| uint8_t varLen; |
| |
| if (NULL == buffer || bufferLen <= 0 || NULL == pDcfInfo) |
| return FALSE; |
| |
| tmpBuf = buffer; |
| /* 1. Parse the version, content-type and content-url */ |
| pDcfInfo->Version = *(tmpBuf++); |
| if (0x01 != pDcfInfo->Version) /* Because it is OMA DRM v1.0, the vension must be 1 */ |
| return FALSE; |
| pDcfInfo->ContentTypeLen = *(tmpBuf++); |
| pDcfInfo->ContentURILen = *(tmpBuf++); |
| strncpy((char *)pDcfInfo->ContentType, (char *)tmpBuf, pDcfInfo->ContentTypeLen); |
| tmpBuf += pDcfInfo->ContentTypeLen; |
| strncpy((char *)pDcfInfo->ContentURI, (char *)tmpBuf, pDcfInfo->ContentURILen); |
| tmpBuf += pDcfInfo->ContentURILen; |
| |
| /* 2. Get the headers length and data length */ |
| pDcfInfo->HeadersLen = drm_parseUintVar(tmpBuf, &varLen); |
| if (DRM_UINT_VAR_ERR == pDcfInfo->HeadersLen) |
| return FALSE; |
| tmpBuf += varLen; |
| pDcfInfo->DecryptedDataLen = DRM_UNKNOWN_DATA_LEN; |
| pDcfInfo->EncryptedDataLen = drm_parseUintVar(tmpBuf, &varLen); |
| if (DRM_UINT_VAR_ERR == pDcfInfo->EncryptedDataLen) |
| return FALSE; |
| tmpBuf += varLen; |
| pHeader = tmpBuf; |
| tmpBuf += pDcfInfo->HeadersLen; |
| pData = tmpBuf; |
| |
| /* 3. Parse the headers */ |
| pStart = pHeader; |
| while (pStart < pData) { |
| pEnd = pStart; |
| while ('\r' != *pEnd && pEnd < pData) |
| pEnd++; |
| |
| if (0 == strncmp((char *)pStart, HEADER_ENCRYPTION_METHOD, HEADER_ENCRYPTION_METHOD_LEN)) |
| strncpy((char *)pDcfInfo->Encryption_Method, |
| (char *)(pStart + HEADER_ENCRYPTION_METHOD_LEN), |
| pEnd - pStart - HEADER_ENCRYPTION_METHOD_LEN); |
| else if (0 == strncmp((char *)pStart, HEADER_RIGHTS_ISSUER, HEADER_RIGHTS_ISSUER_LEN)) |
| strncpy((char *)pDcfInfo->Rights_Issuer, |
| (char *)(pStart + HEADER_RIGHTS_ISSUER_LEN), |
| pEnd - pStart - HEADER_RIGHTS_ISSUER_LEN); |
| else if (0 == strncmp((char *)pStart, HEADER_CONTENT_NAME, HEADER_CONTENT_NAME_LEN)) |
| strncpy((char *)pDcfInfo->Content_Name, |
| (char *)(pStart + HEADER_CONTENT_NAME_LEN), |
| pEnd - pStart - HEADER_CONTENT_NAME_LEN); |
| else if (0 == strncmp((char *)pStart, HEADER_CONTENT_DESCRIPTION, HEADER_CONTENT_DESCRIPTION_LEN)) |
| strncpy((char *)pDcfInfo->ContentDescription, |
| (char *)(pStart + HEADER_CONTENT_DESCRIPTION_LEN), |
| pEnd - pStart - HEADER_CONTENT_DESCRIPTION_LEN); |
| else if (0 == strncmp((char *)pStart, HEADER_CONTENT_VENDOR, HEADER_CONTENT_VENDOR_LEN)) |
| strncpy((char *)pDcfInfo->ContentVendor, |
| (char *)(pStart + HEADER_CONTENT_VENDOR_LEN), |
| pEnd - pStart - HEADER_CONTENT_VENDOR_LEN); |
| else if (0 == strncmp((char *)pStart, HEADER_ICON_URI, HEADER_ICON_URI_LEN)) |
| strncpy((char *)pDcfInfo->Icon_URI, |
| (char *)(pStart + HEADER_ICON_URI_LEN), |
| pEnd - pStart - HEADER_ICON_URI_LEN); |
| |
| if ('\n' == *(pEnd + 1)) |
| pStart = pEnd + 2; /* Two bytes: a '\r' and a '\n' */ |
| else |
| pStart = pEnd + 1; |
| } |
| |
| /* 4. Give out the location of encrypted data */ |
| if (NULL != ppEncryptedData) |
| *ppEncryptedData = pData; |
| |
| return TRUE; |
| } |