/* * 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; }