Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e15a73ee authored by Gloria Wang's avatar Gloria Wang Committed by Android Code Review
Browse files

Merge "Bug fixes in OMA DRM v1 Forward Lock Agent"

parents 6b3a0123 93827fb0
Loading
Loading
Loading
Loading
+136 −102
Original line number Diff line number Diff line
@@ -13,26 +13,28 @@
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef __SESSIONMAP_H__
#define __SESSIONMAP_H__

#include <utils/KeyedVector.h>
#include <utils/threads.h>

namespace android {

/**
 * A wrapper template class for handling DRM Engine sessions.
 * A thread safe wrapper template class for session handlings for Drm Engines. It wraps a
 * pointer type over KeyedVector. It keeps pointer as data in the vector and free up memory
 * allocated pointer can be of any type of structure/class meant for keeping session data.
 * so session object here means pointer to the session data.
 */
template <typename NODE>
template <typename TValue>
class SessionMap {

public:
    KeyedVector<int, NODE> map;

    SessionMap() {}

    virtual ~SessionMap() {
        Mutex::Autolock lock(mLock);
        destroyMap();
    }

@@ -45,18 +47,15 @@ public:
     *
     * @return boolean result of adding value. returns false if key is already exist.
     */
bool addValue(int key, NODE value) {
    bool result = false;

    if (!isCreated(key)) {
    bool addValue(int key, TValue value) {
        Mutex::Autolock lock(mLock);
        if (!isCreatedInternal(key)) {
            map.add(key, value);
        result = true;
            return true;
        }

    return result;
        return false;
    }


    /**
     * returns the session object by the key
     *
@@ -64,14 +63,9 @@ bool addValue(int key, NODE value) {
     *
     * @return session object as per the key
     */
NODE getValue(int key) {
    NODE value = NULL;

    if (isCreated(key)) {
        value = (NODE) map.valueFor(key);
    }

    return value;
    TValue getValue(int key) {
        Mutex::Autolock lock(mLock);
        return getValueInternal(key);
    }

    /**
@@ -80,6 +74,7 @@ NODE getValue(int key) {
     * @return count of number of session objects.
     */
    int getSize() {
        Mutex::Autolock lock(mLock);
        return map.size();
    }

@@ -90,13 +85,13 @@ int getSize() {
     *
     * @return session object as per the index
     */
NODE getValueAt(unsigned int index) {
    NODE value = NULL;
    TValue getValueAt(unsigned int index) {
        TValue value = NULL;
        Mutex::Autolock lock(mLock);

        if (map.size() > index) {
            value = map.valueAt(index);
        }

        return value;
    }

@@ -107,7 +102,8 @@ NODE getValueAt(unsigned int index) {
     *
     */
    void removeValue(int key) {
    deleteValue(getValue(key));
        Mutex::Autolock lock(mLock);
        deleteValue(getValueInternal(key));
        map.removeItem(key);
    }

@@ -119,35 +115,73 @@ void removeValue(int key) {
     * @return boolean result of whether session is created
     */
    bool isCreated(int key) {
    return (0 <= map.indexOfKey(key));
        Mutex::Autolock lock(mLock);
        return isCreatedInternal(key);
    }

    SessionMap<TValue> & operator=(const SessionMap<TValue> & objectCopy) {
        Mutex::Autolock lock(mLock);

        destroyMap();
        map = objectCopy.map;
        return *this;
    }

private:
    KeyedVector<int, TValue> map;
    Mutex mLock;

   /**
    * free up the memory for the session object.
    * Make sure if any reference to the session object anywhere, otherwise it will be a
    * dangle pointer after this call.
    *
    * @param value - session object to free
    *
    */
    void deleteValue(TValue value) {
        delete value;
    }

   /**
 * empty the entire session table. It releases all the memory for session objects.
    * free up the memory for the entire map.
    * free up any resources in the sessions before calling this funtion.
    *
    */
    void destroyMap() {
        int size = map.size();
    int i = 0;

    for (i = 0; i < size; i++) {
        for (int i = 0; i < size; i++) {
            deleteValue(map.valueAt(i));
        }

        map.clear();
    }

   /**
 * free up the memory for the session object.
 * Make sure if any reference to the session object anywhere, otherwise it will be a
 * dangle pointer after this call.
    * decides if session is already created.
    *
 * @param value - session object to free
    * @param key - key of the value for the session
    *
    * @return boolean result of whether session is created
    */
void deleteValue(NODE value) {
    delete value;
    bool isCreatedInternal(int key) {
        return(0 <= map.indexOfKey(key));
    }

   /**
    * returns the session object by the key
    *
    * @param key - key or Session ID
    *
    * @return session object as per the key
    */
    TValue getValueInternal(int key) {
        TValue value = NULL;
        if (isCreatedInternal(key)) {
            value = (TValue) map.valueFor(key);
        }
        return value;
    }
};

};
+37 −25
Original line number Diff line number Diff line
@@ -22,6 +22,13 @@ namespace android {
#undef LOG_TAG
#define LOG_TAG "MimeTypeUtil"

#ifdef DRM_OMA_FL_ENGINE_DEBUG
#define LOG_NDEBUG 0
#define LOG_DEBUG(...) LOGD(__VA_ARGS__)
#else
#define LOG_DEBUG(...)
#endif

enum {
    MIMETYPE_AUDIO       = 0,
    MIMETYPE_APPLICATION = 1,
@@ -59,6 +66,7 @@ static const char mime_group_audio[] = "audio/";
static const char mime_group_application[] = "application/";
static const char mime_group_image[]       = "image/";
static const char mime_group_video[]       = "video/";
static const char mime_type_unsupported[]  = "unsupported/drm.mimetype";

static struct MimeGroup mimeGroup[] = {
    {MIMETYPE_AUDIO,       mime_group_audio,        sizeof(mime_group_audio)-1},
@@ -107,23 +115,25 @@ static struct MimeTypeList mimeTypeList[] = {
 * replacement mimetype otherwise the original mimetype
 * is returned.
 *
 * If the mimetype is of unsupported group i.e. application/*
 * then "unsupported/drm.mimetype" will be returned.
 *
 * @param mimeType - mimetype in lower case to convert.
 *
 * @return mimetype or null.
 * @return mimetype or "unsupported/drm.mimetype".
 */
String8 MimeTypeUtil::convertMimeType(String8& mimeType) {
    String8 result = mimeType;
    const char* pTmp;
    const char* pMimeType;
    struct MimeGroup* pGroup;
    struct MimeTypeList* pMimeItem;
    int len;

    pMimeType = mimeType.string();
    if (NULL != pMimeType) {
        if ((0 == strncmp(pMimeType, mime_group_audio, (sizeof mime_group_audio) - 1)) ||
            (0 == strncmp(pMimeType, mime_group_video, (sizeof mime_group_video) - 1))) {
            /* Check which group the mimetype is */
            pGroup = mimeGroup;

            while (MIMETYPE_LAST != pGroup->type) {
                if (0 == strncmp(pMimeType, pGroup->pGroup, pGroup->size)) {
                    break;
@@ -135,9 +145,9 @@ String8 MimeTypeUtil::convertMimeType(String8& mimeType) {
            if (MIMETYPE_LAST != pGroup->type) {
                pMimeItem = mimeTypeList;
                len = strlen (pMimeType+pGroup->size);

                while (MIMETYPE_LAST != pMimeItem->type) {
                if ((len == pMimeItem->size) &&
                    if ((pGroup->type == pMimeItem->type) &&
                        (len == pMimeItem->size) &&
                        (0 == strcmp(pMimeType+pGroup->size, pMimeItem->pMimeExt))) {
                        result = String8(pMimeItem->pMimeType);
                        break;
@@ -145,10 +155,12 @@ String8 MimeTypeUtil::convertMimeType(String8& mimeType) {
                    pMimeItem++;
                }
            }
        LOGI("convertMimeType got mimetype %s, converted into mimetype %s",
        } else {
            result = String8(mime_type_unsupported);
        }
        LOG_DEBUG("convertMimeType got mimetype %s, converted into mimetype %s",
                pMimeType, result.string());
    }

    return result;
}
};
+3 −0
Original line number Diff line number Diff line
@@ -17,6 +17,9 @@ LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

# The flag below turns on local debug printouts
#LOCAL_CFLAGS += -DDRM_OMA_FL_ENGINE_DEBUG

base := frameworks/base

# Determine whether the DRM framework uses 64-bit data types for file offsets and do the same.
+58 −41
Original line number Diff line number Diff line
@@ -41,6 +41,13 @@
#undef LOG_TAG
#define LOG_TAG "FwdLockEngine"

#ifdef DRM_OMA_FL_ENGINE_DEBUG
#define LOG_NDEBUG 0
#define LOG_VERBOSE(...) LOGV(__VA_ARGS__)
#else
#define LOG_VERBOSE(...)
#endif

using namespace android;
// This extern "C" is mandatory to be managed by TPlugInManager
extern "C" IDrmEngine* create() {
@@ -53,14 +60,25 @@ extern "C" void destroy(IDrmEngine* plugIn) {
}

FwdLockEngine::FwdLockEngine() {
    LOGD("FwdLockEngine Construction");
    LOG_VERBOSE("FwdLockEngine Construction");
}

FwdLockEngine::~FwdLockEngine() {
    LOGD("FwdLockEngine Destruction");
    LOG_VERBOSE("FwdLockEngine Destruction");

    int size = decodeSessionMap.getSize();

    for (int i = 0; i < size; i++) {
        DecodeSession *session = (DecodeSession*) decodeSessionMap.getValueAt(i);
        FwdLockFile_detach(session->fileDesc);
        ::close(session->fileDesc);
    }

    convertSessionMap.destroyMap();
    decodeSessionMap.destroyMap();
    size = convertSessionMap.getSize();
    for (int i = 0; i < size; i++) {
        ConvertSession *convSession = (ConvertSession*) convertSessionMap.getValueAt(i);
        FwdLockConv_CloseSession(convSession->uniqueId, &(convSession->output));
    }
}

int FwdLockEngine::getConvertedStatus(FwdLockConv_Status_t status) {
@@ -74,12 +92,12 @@ int FwdLockEngine::getConvertedStatus(FwdLockConv_Status_t status) {
        case FwdLockConv_Status_InvalidArgument:
        case FwdLockConv_Status_UnsupportedFileFormat:
        case FwdLockConv_Status_UnsupportedContentTransferEncoding:
            LOGD("FwdLockEngine getConvertedStatus: file conversion Error %d. " \
            LOGE("FwdLockEngine getConvertedStatus: file conversion Error %d. "
                  "Returning STATUS_INPUTDATA_ERROR", status);
            retStatus = DrmConvertedStatus::STATUS_INPUTDATA_ERROR;
            break;
        default:
            LOGD("FwdLockEngine getConvertedStatus: file conversion Error %d. " \
            LOGE("FwdLockEngine getConvertedStatus: file conversion Error %d. "
                  "Returning STATUS_ERROR", status);
            retStatus = DrmConvertedStatus::STATUS_ERROR;
            break;
@@ -91,7 +109,7 @@ int FwdLockEngine::getConvertedStatus(FwdLockConv_Status_t status) {
DrmConstraints* FwdLockEngine::onGetConstraints(int uniqueId, const String8* path, int action) {
    DrmConstraints* drmConstraints = NULL;

    LOGD("FwdLockEngine::onGetConstraints");
    LOG_VERBOSE("FwdLockEngine::onGetConstraints");

    if (NULL != path &&
        (RightsStatus::RIGHTS_VALID == onCheckRightsStatus(uniqueId, *path, action))) {
@@ -105,7 +123,7 @@ DrmConstraints* FwdLockEngine::onGetConstraints(int uniqueId, const String8* pat
DrmMetadata* FwdLockEngine::onGetMetadata(int uniqueId, const String8* path) {
    DrmMetadata* drmMetadata = NULL;

    LOGD("FwdLockEngine::onGetMetadata");
    LOG_VERBOSE("FwdLockEngine::onGetMetadata");

    if (NULL != path) {
        // Returns empty metadata to show no error condition.
@@ -116,13 +134,12 @@ DrmMetadata* FwdLockEngine::onGetMetadata(int uniqueId, const String8* path) {
}

android::status_t FwdLockEngine::onInitialize(int uniqueId) {
    LOGD("FwdLockEngine::onInitialize");

    LOG_VERBOSE("FwdLockEngine::onInitialize");

    if (FwdLockGlue_InitializeKeyEncryption()) {
        LOGD("FwdLockEngine::onInitialize -- FwdLockGlue_InitializeKeyEncryption succeeded");
        LOG_VERBOSE("FwdLockEngine::onInitialize -- FwdLockGlue_InitializeKeyEncryption succeeded");
    } else {
        LOGD("FwdLockEngine::onInitialize -- FwdLockGlue_InitializeKeyEncryption failed:"
        LOGE("FwdLockEngine::onInitialize -- FwdLockGlue_InitializeKeyEncryption failed:"
             "errno = %d", errno);
    }

@@ -132,13 +149,13 @@ android::status_t FwdLockEngine::onInitialize(int uniqueId) {
android::status_t
FwdLockEngine::onSetOnInfoListener(int uniqueId, const IDrmEngine::OnInfoListener* infoListener) {
    // Not used
    LOGD("FwdLockEngine::onSetOnInfoListener");
    LOG_VERBOSE("FwdLockEngine::onSetOnInfoListener");

    return DRM_NO_ERROR;
}

android::status_t FwdLockEngine::onTerminate(int uniqueId) {
    LOGD("FwdLockEngine::onTerminate");
    LOG_VERBOSE("FwdLockEngine::onTerminate");

    return DRM_NO_ERROR;
}
@@ -146,7 +163,7 @@ android::status_t FwdLockEngine::onTerminate(int uniqueId) {
DrmSupportInfo* FwdLockEngine::onGetSupportInfo(int uniqueId) {
    DrmSupportInfo* pSupportInfo = new DrmSupportInfo();

    LOGD("FwdLockEngine::onGetSupportInfo");
    LOG_VERBOSE("FwdLockEngine::onGetSupportInfo");

    // fill all Forward Lock mimetypes and extensions
    if (NULL != pSupportInfo) {
@@ -182,7 +199,7 @@ DrmInfoStatus* FwdLockEngine::onProcessDrmInfo(int uniqueId, const DrmInfo* drmI

    drmInfoStatus = new DrmInfoStatus((int)DrmInfoStatus::STATUS_OK, 0, NULL, String8(""));

    LOGD("FwdLockEngine::onProcessDrmInfo");
    LOG_VERBOSE("FwdLockEngine::onProcessDrmInfo");

    return drmInfoStatus;
}
@@ -193,7 +210,7 @@ status_t FwdLockEngine::onSaveRights(
            const String8& rightsPath,
            const String8& contentPath) {
    // No rights to save. Return
    LOGD("FwdLockEngine::onSaveRights");
    LOG_VERBOSE("FwdLockEngine::onSaveRights");
    return DRM_ERROR_UNKNOWN;
}

@@ -201,7 +218,7 @@ DrmInfo* FwdLockEngine::onAcquireDrmInfo(int uniqueId, const DrmInfoRequest* drm
    DrmInfo* drmInfo = NULL;

    // Nothing to be done for Forward Lock file
    LOGD("FwdLockEngine::onAcquireDrmInfo");
    LOG_VERBOSE("FwdLockEngine::onAcquireDrmInfo");

    return drmInfo;
}
@@ -211,7 +228,7 @@ int FwdLockEngine::onCheckRightsStatus(int uniqueId,
                                       int action) {
    int result = RightsStatus::RIGHTS_INVALID;

    LOGD("FwdLockEngine::onCheckRightsStatus");
    LOG_VERBOSE("FwdLockEngine::onCheckRightsStatus");

    // Only Transfer action is not allowed for forward Lock files.
    if (onCanHandle(uniqueId, path)) {
@@ -241,7 +258,7 @@ status_t FwdLockEngine::onConsumeRights(int uniqueId,
                                        int action,
                                        bool reserve) {
    // No rights consumption
    LOGD("FwdLockEngine::onConsumeRights");
    LOG_VERBOSE("FwdLockEngine::onConsumeRights");
    return DRM_NO_ERROR;
}

@@ -249,14 +266,14 @@ bool FwdLockEngine::onValidateAction(int uniqueId,
                                     const String8& path,
                                     int action,
                                     const ActionDescription& description) {
    LOGD("FwdLockEngine::onValidateAction");
    LOG_VERBOSE("FwdLockEngine::onValidateAction");

    // For the forwardlock engine checkRights and ValidateAction are the same.
    return (onCheckRightsStatus(uniqueId, path, action) == RightsStatus::RIGHTS_VALID);
}

String8 FwdLockEngine::onGetOriginalMimeType(int uniqueId, const String8& path) {
    LOGD("FwdLockEngine::onGetOriginalMimeType");
    LOG_VERBOSE("FwdLockEngine::onGetOriginalMimeType");
    String8 mimeString = String8("");
    int fileDesc = FwdLockFile_open(path.string());

@@ -280,7 +297,7 @@ int FwdLockEngine::onGetDrmObjectType(int uniqueId,
                                      const String8& mimeType) {
    String8 mimeStr = String8(mimeType);

    LOGD("FwdLockEngine::onGetDrmObjectType");
    LOG_VERBOSE("FwdLockEngine::onGetDrmObjectType");

    mimeStr.toLower();

@@ -301,13 +318,13 @@ int FwdLockEngine::onGetDrmObjectType(int uniqueId,

status_t FwdLockEngine::onRemoveRights(int uniqueId, const String8& path) {
    // No Rights to remove
    LOGD("FwdLockEngine::onRemoveRights");
    LOG_VERBOSE("FwdLockEngine::onRemoveRights");
    return DRM_NO_ERROR;
}

status_t FwdLockEngine::onRemoveAllRights(int uniqueId) {
    // No rights to remove
    LOGD("FwdLockEngine::onRemoveAllRights");
    LOG_VERBOSE("FwdLockEngine::onRemoveAllRights");
    return DRM_NO_ERROR;
}

@@ -319,14 +336,14 @@ status_t FwdLockEngine::onSetPlaybackStatus(int uniqueId, DecryptHandle* decrypt
                                            int playbackStatus, int position) {
#endif
    // Not used
    LOGD("FwdLockEngine::onSetPlaybackStatus");
    LOG_VERBOSE("FwdLockEngine::onSetPlaybackStatus");
    return DRM_NO_ERROR;
}

status_t FwdLockEngine::onOpenConvertSession(int uniqueId,
                                         int convertId) {
    status_t result = DRM_ERROR_UNKNOWN;
    LOGD("FwdLockEngine::onOpenConvertSession");
    LOG_VERBOSE("FwdLockEngine::onOpenConvertSession");
    if (!convertSessionMap.isCreated(convertId)) {
        ConvertSession *newSession = new ConvertSession();
        if (FwdLockConv_Status_OK ==
@@ -334,7 +351,7 @@ status_t FwdLockEngine::onOpenConvertSession(int uniqueId,
            convertSessionMap.addValue(convertId, newSession);
            result = DRM_NO_ERROR;
        } else {
            LOGD("FwdLockEngine::onOpenConvertSession -- FwdLockConv_OpenSession failed.");
            LOGE("FwdLockEngine::onOpenConvertSession -- FwdLockConv_OpenSession failed.");
            delete newSession;
        }
    }
@@ -383,7 +400,7 @@ DrmConvertedStatus* FwdLockEngine::onCloseConvertSession(int uniqueId,
    DrmBuffer *convResult = new DrmBuffer(NULL, 0);
    int offset = -1;

    LOGD("FwdLockEngine::onCloseConvertSession");
    LOG_VERBOSE("FwdLockEngine::onCloseConvertSession");

    if (convertSessionMap.isCreated(convertId)) {
        ConvertSession *convSession = convertSessionMap.getValue(convertId);
@@ -424,14 +441,14 @@ status_t FwdLockEngine::onOpenDecryptSession(int uniqueId,
    status_t result = DRM_ERROR_CANNOT_HANDLE;
    int fileDesc = -1;

    LOGD("FwdLockEngine::onOpenDecryptSession");
    LOG_VERBOSE("FwdLockEngine::onOpenDecryptSession");

    if ((-1 < fd) &&
        (NULL != decryptHandle) &&
        (!decodeSessionMap.isCreated(decryptHandle->decryptId))) {
        fileDesc = dup(fd);
    } else {
        LOGD("FwdLockEngine::onOpenDecryptSession parameter error");
        LOGE("FwdLockEngine::onOpenDecryptSession parameter error");
        return result;
    }

@@ -453,14 +470,14 @@ status_t FwdLockEngine::onOpenDecryptSession(int uniqueId,
            decryptHandle->decryptInfo = NULL;
            result = DRM_NO_ERROR;
        } else {
            LOGD("FwdLockEngine::onOpenDecryptSession Integrity Check failed for the fd");
            LOG_VERBOSE("FwdLockEngine::onOpenDecryptSession Integrity Check failed for the fd");
            FwdLockFile_detach(fileDesc);
            ::close(fileDesc);
            delete decodeSession;
        }
    }

    LOGD("FwdLockEngine::onOpenDecryptSession Exit. result = %d", result);
    LOG_VERBOSE("FwdLockEngine::onOpenDecryptSession Exit. result = %d", result);

    return result;
}
@@ -497,7 +514,7 @@ status_t FwdLockEngine::onOpenDecryptSession(int uniqueId,
status_t FwdLockEngine::onCloseDecryptSession(int uniqueId,
                                              DecryptHandle* decryptHandle) {
    status_t result = DRM_ERROR_UNKNOWN;
    LOGD("FwdLockEngine::onCloseDecryptSession");
    LOG_VERBOSE("FwdLockEngine::onCloseDecryptSession");

    if (NULL != decryptHandle && decodeSessionMap.isCreated(decryptHandle->decryptId)) {
        DecodeSession* session = decodeSessionMap.getValue(decryptHandle->decryptId);
@@ -509,7 +526,7 @@ status_t FwdLockEngine::onCloseDecryptSession(int uniqueId,
        }
    }

    LOGD("FwdLockEngine::onCloseDecryptSession Exit");
    LOG_VERBOSE("FwdLockEngine::onCloseDecryptSession Exit");
    return result;
}

@@ -517,13 +534,13 @@ status_t FwdLockEngine::onInitializeDecryptUnit(int uniqueId,
                                                DecryptHandle* decryptHandle,
                                                int decryptUnitId,
                                                const DrmBuffer* headerInfo) {
    LOGD("FwdLockEngine::onInitializeDecryptUnit");
    LOGE("FwdLockEngine::onInitializeDecryptUnit is not supported for this DRM scheme");
    return DRM_ERROR_UNKNOWN;
}

status_t FwdLockEngine::onDecrypt(int uniqueId, DecryptHandle* decryptHandle, int decryptUnitId,
            const DrmBuffer* encBuffer, DrmBuffer** decBuffer, DrmBuffer* IV) {
    LOGD("FwdLockEngine::onDecrypt");
    LOGE("FwdLockEngine::onDecrypt is not supported for this DRM scheme");
    return DRM_ERROR_UNKNOWN;
}

@@ -532,14 +549,14 @@ status_t FwdLockEngine::onDecrypt(int uniqueId,
                                  int decryptUnitId,
                                  const DrmBuffer* encBuffer,
                                  DrmBuffer** decBuffer) {
    LOGD("FwdLockEngine::onDecrypt");
    LOGE("FwdLockEngine::onDecrypt is not supported for this DRM scheme");
    return DRM_ERROR_UNKNOWN;
}

status_t FwdLockEngine::onFinalizeDecryptUnit(int uniqueId,
                                              DecryptHandle* decryptHandle,
                                              int decryptUnitId) {
    LOGD("FwdLockEngine::onFinalizeDecryptUnit");
    LOGE("FwdLockEngine::onFinalizeDecryptUnit is not supported for this DRM scheme");
    return DRM_ERROR_UNKNOWN;
}

@@ -617,11 +634,11 @@ ssize_t FwdLockEngine::onPread(int uniqueId,
        if (((off_t)-1) != decoderSession->offset) {
            bytesRead = onRead(uniqueId, decryptHandle, buffer, numBytes);
            if (bytesRead < 0) {
                LOGD("FwdLockEngine::onPread error reading");
                LOGE("FwdLockEngine::onPread error reading");
            }
        }
    } else {
        LOGD("FwdLockEngine::onPread decryptId not found");
        LOGE("FwdLockEngine::onPread decryptId not found");
    }

    return bytesRead;
+17 −9
Original line number Diff line number Diff line
@@ -275,17 +275,18 @@ static int FwdLockConv_DeriveKeys(FwdLockConv_Session_t *pSession) {
}

/**
 * Checks whether a given character is valid in a boundary. Note that the boundary may contain
 * leading and internal spaces.
 * Checks whether a given character is valid in a boundary. Allows some non-standard characters that
 * are invalid according to RFC 2046 but nevertheless used by one vendor's DRM packager. Note that
 * the boundary may contain leading and internal spaces.
 *
 * @param[in] ch The character to check.
 *
 * @return A Boolean value indicating whether the given character is valid in a boundary.
 */
static int FwdLockConv_IsBoundaryChar(int ch) {
    return isalnum(ch) || ch == '\'' ||
            ch == '(' || ch == ')' || ch == '+' || ch == '_' || ch == ',' || ch == '-' ||
            ch == '.' || ch == '/' || ch == ':' || ch == '=' || ch == '?' || ch == ' ';
    return isalnum(ch) || ch == '\'' || ch == '(' || ch == ')' || ch == '+' || ch == '_' ||
            ch == ',' || ch == '-' || ch == '.' || ch == '/' || ch == ':' || ch == '=' ||
            ch == '?' || ch == ' ' || ch == '%' || ch == '[' || ch == '&' || ch == '*' || ch == '^';
}

/**
@@ -1085,6 +1086,13 @@ static FwdLockConv_Status_t FwdLockConv_PushChar(FwdLockConv_Session_t *pSession
        status = FwdLockConv_MatchBinaryEncodedData(pSession, ch, pOutput);
        break;
    case FwdLockConv_ParserState_WantsBase64EncodedData:
        if (ch == '\n' && pSession->scannerState != FwdLockConv_ScannerState_WantsLF) {
            // Repair base64-encoded data that doesn't have carriage returns in its line breaks.
            status = FwdLockConv_MatchBase64EncodedData(pSession, '\r', pOutput);
            if (status != FwdLockConv_Status_OK) {
                break;
            }
        }
        status = FwdLockConv_MatchBase64EncodedData(pSession, ch, pOutput);
        break;
    case FwdLockConv_ParserState_Done:
@@ -1199,7 +1207,7 @@ FwdLockConv_Status_t FwdLockConv_CloseSession(int sessionId, FwdLockConv_Output_
            status = FwdLockConv_Status_SyntaxError;
        } else {
            // Finalize the data signature.
            size_t signatureSize;
            unsigned int signatureSize = SHA1_HASH_SIZE;
            HMAC_Final(&pSession->signingContext, pOutput->fromCloseSession.signatures,
                       &signatureSize);
            if (signatureSize != SHA1_HASH_SIZE) {
@@ -1214,9 +1222,9 @@ FwdLockConv_Status_t FwdLockConv_CloseSession(int sessionId, FwdLockConv_Output_
                HMAC_Update(&pSession->signingContext, pSession->pEncryptedSessionKey,
                            pSession->encryptedSessionKeyLength);
                HMAC_Update(&pSession->signingContext, pOutput->fromCloseSession.signatures,
                            signatureSize);
                HMAC_Final(&pSession->signingContext, &pOutput->fromCloseSession.
                           signatures[signatureSize], &signatureSize);
                            SHA1_HASH_SIZE);
                HMAC_Final(&pSession->signingContext,
                           &pOutput->fromCloseSession.signatures[SHA1_HASH_SIZE], &signatureSize);
                if (signatureSize != SHA1_HASH_SIZE) {
                    status = FwdLockConv_Status_ProgramError;
                } else {
Loading