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 62 pDcfInfo->ContentTypeLen = *(tmpBuf++); 63 if (pDcfInfo->ContentTypeLen >= MAX_CONTENT_TYPE_LEN) 64 return FALSE; 65 66 pDcfInfo->ContentURILen = *(tmpBuf++); 67 if (pDcfInfo->ContentURILen >= MAX_CONTENT_URI_LEN) 68 return FALSE; 69 70 strncpy((char *)pDcfInfo->ContentType, (char *)tmpBuf, pDcfInfo->ContentTypeLen); 71 pDcfInfo->ContentType[MAX_CONTENT_TYPE_LEN - 1] = 0; 72 tmpBuf += pDcfInfo->ContentTypeLen; 73 strncpy((char *)pDcfInfo->ContentURI, (char *)tmpBuf, pDcfInfo->ContentURILen); 74 pDcfInfo->ContentURI[MAX_CONTENT_URI_LEN - 1] = 0; 75 tmpBuf += pDcfInfo->ContentURILen; 76 77 /* 2. Get the headers length and data length */ 78 pDcfInfo->HeadersLen = drm_parseUintVar(tmpBuf, &varLen); 79 if (DRM_UINT_VAR_ERR == pDcfInfo->HeadersLen) 80 return FALSE; 81 tmpBuf += varLen; 82 pDcfInfo->DecryptedDataLen = DRM_UNKNOWN_DATA_LEN; 83 pDcfInfo->EncryptedDataLen = drm_parseUintVar(tmpBuf, &varLen); 84 if (DRM_UINT_VAR_ERR == pDcfInfo->EncryptedDataLen) 85 return FALSE; 86 tmpBuf += varLen; 87 pHeader = tmpBuf; 88 tmpBuf += pDcfInfo->HeadersLen; 89 pData = tmpBuf; 90 91 /* 3. Parse the headers */ 92 pStart = pHeader; 93 while (pStart < pData) { 94 pEnd = pStart; 95 while ('\r' != *pEnd && pEnd < pData) 96 pEnd++; 97 98 if (0 == strncmp((char *)pStart, HEADER_ENCRYPTION_METHOD, HEADER_ENCRYPTION_METHOD_LEN)) { 99 if ((pEnd - pStart - HEADER_ENCRYPTION_METHOD_LEN) >= MAX_ENCRYPTION_METHOD_LEN) 100 return FALSE; 101 strncpy((char *)pDcfInfo->Encryption_Method, 102 (char *)(pStart + HEADER_ENCRYPTION_METHOD_LEN), 103 pEnd - pStart - HEADER_ENCRYPTION_METHOD_LEN); 104 pDcfInfo->Encryption_Method[MAX_ENCRYPTION_METHOD_LEN - 1] = 0; 105 } else if (0 == strncmp((char *)pStart, HEADER_RIGHTS_ISSUER, HEADER_RIGHTS_ISSUER_LEN)) { 106 if ((pEnd - pStart - HEADER_RIGHTS_ISSUER_LEN) >= MAX_RIGHTS_ISSUER_LEN) 107 return FALSE; 108 strncpy((char *)pDcfInfo->Rights_Issuer, 109 (char *)(pStart + HEADER_RIGHTS_ISSUER_LEN), 110 pEnd - pStart - HEADER_RIGHTS_ISSUER_LEN); 111 pDcfInfo->Rights_Issuer[MAX_RIGHTS_ISSUER_LEN - 1] = 0; 112 } else if (0 == strncmp((char *)pStart, HEADER_CONTENT_NAME, HEADER_CONTENT_NAME_LEN)) { 113 if ((pEnd - pStart - HEADER_CONTENT_NAME_LEN) >= MAX_CONTENT_NAME_LEN) 114 return FALSE; 115 strncpy((char *)pDcfInfo->Content_Name, 116 (char *)(pStart + HEADER_CONTENT_NAME_LEN), 117 pEnd - pStart - HEADER_CONTENT_NAME_LEN); 118 pDcfInfo->Content_Name[MAX_CONTENT_NAME_LEN - 1] = 0; 119 } else if (0 == strncmp((char *)pStart, HEADER_CONTENT_DESCRIPTION, HEADER_CONTENT_DESCRIPTION_LEN)) { 120 if ((pEnd - pStart - HEADER_CONTENT_DESCRIPTION_LEN) >= MAX_CONTENT_DESCRIPTION_LEN) 121 return FALSE; 122 strncpy((char *)pDcfInfo->ContentDescription, 123 (char *)(pStart + HEADER_CONTENT_DESCRIPTION_LEN), 124 pEnd - pStart - HEADER_CONTENT_DESCRIPTION_LEN); 125 pDcfInfo->ContentDescription[MAX_CONTENT_DESCRIPTION_LEN - 1] = 0; 126 } else if (0 == strncmp((char *)pStart, HEADER_CONTENT_VENDOR, HEADER_CONTENT_VENDOR_LEN)) { 127 if ((pEnd - pStart - HEADER_CONTENT_VENDOR_LEN) >= MAX_CONTENT_VENDOR_LEN) 128 return FALSE; 129 strncpy((char *)pDcfInfo->ContentVendor, 130 (char *)(pStart + HEADER_CONTENT_VENDOR_LEN), 131 pEnd - pStart - HEADER_CONTENT_VENDOR_LEN); 132 pDcfInfo->ContentVendor[MAX_CONTENT_VENDOR_LEN - 1] = 0; 133 } else if (0 == strncmp((char *)pStart, HEADER_ICON_URI, HEADER_ICON_URI_LEN)) { 134 if ((pEnd - pStart - HEADER_ICON_URI_LEN) >= MAX_ICON_URI_LEN) 135 return FALSE; 136 strncpy((char *)pDcfInfo->Icon_URI, 137 (char *)(pStart + HEADER_ICON_URI_LEN), 138 pEnd - pStart - HEADER_ICON_URI_LEN); 139 pDcfInfo->Icon_URI[MAX_ICON_URI_LEN - 1] = 0; 140 } 141 142 if ('\n' == *(pEnd + 1)) 143 pStart = pEnd + 2; /* Two bytes: a '\r' and a '\n' */ 144 else 145 pStart = pEnd + 1; 146 } 147 148 /* 4. Give out the location of encrypted data */ 149 if (NULL != ppEncryptedData) 150 *ppEncryptedData = pData; 151 152 return TRUE; 153 } 154