1 /* 2 * Copyright (C) 2007 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (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 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 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. 15 */ 16 17 #include <parser_dcf.h> 18 #include <svc_drm.h> 19 20 static int32_t drm_parseUintVar(uint8_t * buffer, uint8_t * len) 21 { 22 int32_t i; 23 int32_t byteLen; 24 int32_t sum; 25 26 if (NULL == buffer) 27 return DRM_UINT_VAR_ERR; 28 29 byteLen = 0; 30 while ((buffer[byteLen] & UINT_VAR_FLAG) > 0 && byteLen < MAX_UINT_VAR_BYTE) /* UINT_VAR_FLAG == 0x80 */ 31 byteLen++; 32 33 if (byteLen >= MAX_UINT_VAR_BYTE) /* MAX_UINT_VAR_BYTE == 5 */ 34 return DRM_UINT_VAR_ERR; /* The var int is too large, and that is impossible */ 35 36 *len = (uint8_t)(byteLen + 1); 37 sum = buffer[byteLen]; 38 for (i = byteLen - 1; i >= 0; i--) 39 sum += ((buffer[i] & UINT_VAR_DATA) << 7 * (byteLen - i)); /* UINT_VAR_DATA == 0x7F */ 40 41 return sum; 42 } 43 44 /* See parser_dcf.h */ 45 int32_t drm_dcfParser(uint8_t *buffer, int32_t bufferLen, T_DRM_DCF_Info *pDcfInfo, 46 uint8_t **ppEncryptedData) 47 { 48 uint8_t *tmpBuf; 49 uint8_t *pStart, *pEnd; 50 uint8_t *pHeader, *pData; 51 uint8_t varLen; 52 53 if (NULL == buffer || bufferLen <= 0 || NULL == pDcfInfo) 54 return FALSE; 55 56 tmpBuf = buffer; 57 /* 1. Parse the version, content-type and content-url */ 58 pDcfInfo->Version = *(tmpBuf++); 59 if (0x01 != pDcfInfo->Version) /* Because it is OMA DRM v1.0, the vension must be 1 */ 60 return FALSE; 61 pDcfInfo->ContentTypeLen = *(tmpBuf++); 62 pDcfInfo->ContentURILen = *(tmpBuf++); 63 strncpy((char *)pDcfInfo->ContentType, (char *)tmpBuf, pDcfInfo->ContentTypeLen); 64 tmpBuf += pDcfInfo->ContentTypeLen; 65 strncpy((char *)pDcfInfo->ContentURI, (char *)tmpBuf, pDcfInfo->ContentURILen); 66 tmpBuf += pDcfInfo->ContentURILen; 67 68 /* 2. Get the headers length and data length */ 69 pDcfInfo->HeadersLen = drm_parseUintVar(tmpBuf, &varLen); 70 if (DRM_UINT_VAR_ERR == pDcfInfo->HeadersLen) 71 return FALSE; 72 tmpBuf += varLen; 73 pDcfInfo->DecryptedDataLen = DRM_UNKNOWN_DATA_LEN; 74 pDcfInfo->EncryptedDataLen = drm_parseUintVar(tmpBuf, &varLen); 75 if (DRM_UINT_VAR_ERR == pDcfInfo->EncryptedDataLen) 76 return FALSE; 77 tmpBuf += varLen; 78 pHeader = tmpBuf; 79 tmpBuf += pDcfInfo->HeadersLen; 80 pData = tmpBuf; 81 82 /* 3. Parse the headers */ 83 pStart = pHeader; 84 while (pStart < pData) { 85 pEnd = pStart; 86 while ('\r' != *pEnd && pEnd < pData) 87 pEnd++; 88 89 if (0 == strncmp((char *)pStart, HEADER_ENCRYPTION_METHOD, HEADER_ENCRYPTION_METHOD_LEN)) 90 strncpy((char *)pDcfInfo->Encryption_Method, 91 (char *)(pStart + HEADER_ENCRYPTION_METHOD_LEN), 92 pEnd - pStart - HEADER_ENCRYPTION_METHOD_LEN); 93 else if (0 == strncmp((char *)pStart, HEADER_RIGHTS_ISSUER, HEADER_RIGHTS_ISSUER_LEN)) 94 strncpy((char *)pDcfInfo->Rights_Issuer, 95 (char *)(pStart + HEADER_RIGHTS_ISSUER_LEN), 96 pEnd - pStart - HEADER_RIGHTS_ISSUER_LEN); 97 else if (0 == strncmp((char *)pStart, HEADER_CONTENT_NAME, HEADER_CONTENT_NAME_LEN)) 98 strncpy((char *)pDcfInfo->Content_Name, 99 (char *)(pStart + HEADER_CONTENT_NAME_LEN), 100 pEnd - pStart - HEADER_CONTENT_NAME_LEN); 101 else if (0 == strncmp((char *)pStart, HEADER_CONTENT_DESCRIPTION, HEADER_CONTENT_DESCRIPTION_LEN)) 102 strncpy((char *)pDcfInfo->ContentDescription, 103 (char *)(pStart + HEADER_CONTENT_DESCRIPTION_LEN), 104 pEnd - pStart - HEADER_CONTENT_DESCRIPTION_LEN); 105 else if (0 == strncmp((char *)pStart, HEADER_CONTENT_VENDOR, HEADER_CONTENT_VENDOR_LEN)) 106 strncpy((char *)pDcfInfo->ContentVendor, 107 (char *)(pStart + HEADER_CONTENT_VENDOR_LEN), 108 pEnd - pStart - HEADER_CONTENT_VENDOR_LEN); 109 else if (0 == strncmp((char *)pStart, HEADER_ICON_URI, HEADER_ICON_URI_LEN)) 110 strncpy((char *)pDcfInfo->Icon_URI, 111 (char *)(pStart + HEADER_ICON_URI_LEN), 112 pEnd - pStart - HEADER_ICON_URI_LEN); 113 114 if ('\n' == *(pEnd + 1)) 115 pStart = pEnd + 2; /* Two bytes: a '\r' and a '\n' */ 116 else 117 pStart = pEnd + 1; 118 } 119 120 /* 4. Give out the location of encrypted data */ 121 if (NULL != ppEncryptedData) 122 *ppEncryptedData = pData; 123 124 return TRUE; 125 } 126