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

Commit 8a6fb50d authored by Gloria Wang's avatar Gloria Wang Committed by Android Git Automerger
Browse files

am 4e197ea8: am e15a73ee: Merge "Bug fixes in OMA DRM v1 Forward Lock Agent"

* commit '4e197ea8':
  Bug fixes in OMA DRM v1 Forward Lock Agent
parents 320834c9 4e197ea8
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