• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
drm_parseUintVar(uint8_t * buffer,uint8_t * len)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 */
drm_dcfParser(uint8_t * buffer,int32_t bufferLen,T_DRM_DCF_Info * pDcfInfo,uint8_t ** ppEncryptedData)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