blob: 3eac1203a90d6a64f69de462075f9c0d58bed7ba [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/*
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
20static 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 */
45int32_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;
Nick Kralevich25619b22013-04-29 10:49:47 -070061
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080062 pDcfInfo->ContentTypeLen = *(tmpBuf++);
Nick Kralevich25619b22013-04-29 10:49:47 -070063 if (pDcfInfo->ContentTypeLen >= MAX_CONTENT_TYPE_LEN)
64 return FALSE;
65
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080066 pDcfInfo->ContentURILen = *(tmpBuf++);
Nick Kralevich25619b22013-04-29 10:49:47 -070067 if (pDcfInfo->ContentURILen >= MAX_CONTENT_URI_LEN)
68 return FALSE;
69
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080070 strncpy((char *)pDcfInfo->ContentType, (char *)tmpBuf, pDcfInfo->ContentTypeLen);
Nick Kralevich25619b22013-04-29 10:49:47 -070071 pDcfInfo->ContentType[MAX_CONTENT_TYPE_LEN - 1] = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080072 tmpBuf += pDcfInfo->ContentTypeLen;
73 strncpy((char *)pDcfInfo->ContentURI, (char *)tmpBuf, pDcfInfo->ContentURILen);
Nick Kralevich25619b22013-04-29 10:49:47 -070074 pDcfInfo->ContentURI[MAX_CONTENT_URI_LEN - 1] = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080075 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
Nick Kralevich25619b22013-04-29 10:49:47 -070098 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;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800101 strncpy((char *)pDcfInfo->Encryption_Method,
102 (char *)(pStart + HEADER_ENCRYPTION_METHOD_LEN),
103 pEnd - pStart - HEADER_ENCRYPTION_METHOD_LEN);
Nick Kralevich25619b22013-04-29 10:49:47 -0700104 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;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800108 strncpy((char *)pDcfInfo->Rights_Issuer,
109 (char *)(pStart + HEADER_RIGHTS_ISSUER_LEN),
110 pEnd - pStart - HEADER_RIGHTS_ISSUER_LEN);
Nick Kralevich25619b22013-04-29 10:49:47 -0700111 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;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800115 strncpy((char *)pDcfInfo->Content_Name,
116 (char *)(pStart + HEADER_CONTENT_NAME_LEN),
117 pEnd - pStart - HEADER_CONTENT_NAME_LEN);
Nick Kralevich25619b22013-04-29 10:49:47 -0700118 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;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800122 strncpy((char *)pDcfInfo->ContentDescription,
123 (char *)(pStart + HEADER_CONTENT_DESCRIPTION_LEN),
124 pEnd - pStart - HEADER_CONTENT_DESCRIPTION_LEN);
Nick Kralevich25619b22013-04-29 10:49:47 -0700125 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;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800129 strncpy((char *)pDcfInfo->ContentVendor,
130 (char *)(pStart + HEADER_CONTENT_VENDOR_LEN),
131 pEnd - pStart - HEADER_CONTENT_VENDOR_LEN);
Nick Kralevich25619b22013-04-29 10:49:47 -0700132 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;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800136 strncpy((char *)pDcfInfo->Icon_URI,
137 (char *)(pStart + HEADER_ICON_URI_LEN),
138 pEnd - pStart - HEADER_ICON_URI_LEN);
Nick Kralevich25619b22013-04-29 10:49:47 -0700139 pDcfInfo->Icon_URI[MAX_ICON_URI_LEN - 1] = 0;
140 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800141
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}