Home | History | Annotate | Download | only in parser
      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