From 90855078eb989944bca1824058d7231cd68e5021 Mon Sep 17 00:00:00 2001 From: Henrik B Andersson Date: Mon, 21 Feb 2011 14:22:08 +0100 Subject: Bug fixes in OMA DRM v1 Forward Lock Agent A couple of fixes in the Forward Lock Agent. The DRM Framework isn't thread safe so the Forward Lock Agent needs to protect the private structures. Base64-encoded content with LF-only instead of CRLF line breaks is now accepted. A fix for non-standard boundary characters. The debug prints are also turned off as default. Change-Id: I8ab417231380fbe1c371d18a147773ceabc6f69f --- .../plugins/common/util/include/SessionMap.h | 238 ++++++++++++--------- .../plugins/common/util/src/MimeTypeUtil.cpp | 62 +++--- .../plugins/forward-lock/FwdLockEngine/Android.mk | 3 + .../FwdLockEngine/src/FwdLockEngine.cpp | 99 +++++---- .../internal-format/converter/FwdLockConv.c | 26 ++- .../internal-format/decoder/FwdLockFile.c | 12 +- 6 files changed, 257 insertions(+), 183 deletions(-) (limited to 'drm/libdrmframework') diff --git a/drm/libdrmframework/plugins/common/util/include/SessionMap.h b/drm/libdrmframework/plugins/common/util/include/SessionMap.h index 3dff58c..e563894 100644 --- a/drm/libdrmframework/plugins/common/util/include/SessionMap.h +++ b/drm/libdrmframework/plugins/common/util/include/SessionMap.h @@ -13,141 +13,175 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - #ifndef __SESSIONMAP_H__ #define __SESSIONMAP_H__ #include +#include 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 +template class SessionMap { public: - KeyedVector map; - SessionMap() {} virtual ~SessionMap() { + Mutex::Autolock lock(mLock); destroyMap(); } -/** - * Adds a new value in the session map table. It expects memory to be allocated already - * for the session object - * - * @param key - key or Session ID - * @param value - session object to add - * - * @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)) { - map.add(key, value); - result = true; + /** + * Adds a new value in the session map table. It expects memory to be allocated already + * for the session object + * + * @param key - key or Session ID + * @param value - session object to add + * + * @return boolean result of adding value. returns false if key is already exist. + */ + bool addValue(int key, TValue value) { + Mutex::Autolock lock(mLock); + if (!isCreatedInternal(key)) { + map.add(key, value); + return true; + } + return false; } - return result; -} - - -/** - * returns the session object by the key - * - * @param key - key or Session ID - * - * @return session object as per the key - */ -NODE getValue(int key) { - NODE value = NULL; - - if (isCreated(key)) { - value = (NODE) map.valueFor(key); + /** + * returns the session object by the key + * + * @param key - key or Session ID + * + * @return session object as per the key + */ + TValue getValue(int key) { + Mutex::Autolock lock(mLock); + return getValueInternal(key); } - return value; -} - -/** - * returns the number of objects in the session map table - * - * @return count of number of session objects. - */ -int getSize() { - return map.size(); -} - -/** - * returns the session object by the index in the session map table - * - * @param index - index of the value required - * - * @return session object as per the index - */ -NODE getValueAt(unsigned int index) { - NODE value = NULL; + /** + * returns the number of objects in the session map table + * + * @return count of number of session objects. + */ + int getSize() { + Mutex::Autolock lock(mLock); + return map.size(); + } - if (map.size() > index) { - value = map.valueAt(index); + /** + * returns the session object by the index in the session map table + * + * @param index - index of the value required + * + * @return session object as per the index + */ + TValue getValueAt(unsigned int index) { + TValue value = NULL; + Mutex::Autolock lock(mLock); + + if (map.size() > index) { + value = map.valueAt(index); + } + return value; } - return value; -} + /** + * deletes the object from session map. It also frees up memory for the session object. + * + * @param key - key of the value to be deleted + * + */ + void removeValue(int key) { + Mutex::Autolock lock(mLock); + deleteValue(getValueInternal(key)); + map.removeItem(key); + } -/** - * deletes the object from session map. It also frees up memory for the session object. - * - * @param key - key of the value to be deleted - * - */ -void removeValue(int key) { - deleteValue(getValue(key)); - map.removeItem(key); -} + /** + * decides if session is already created. + * + * @param key - key of the value for the session + * + * @return boolean result of whether session is created + */ + bool isCreated(int key) { + Mutex::Autolock lock(mLock); + return isCreatedInternal(key); + } -/** - * decides if session is already created. - * - * @param key - key of the value for the session - * - * @return boolean result of whether session is created - */ -bool isCreated(int key) { - return (0 <= map.indexOfKey(key)); -} + SessionMap & operator=(const SessionMap & objectCopy) { + Mutex::Autolock lock(mLock); -/** - * empty the entire session table. It releases all the memory for session objects. - */ -void destroyMap() { - int size = map.size(); - int i = 0; + destroyMap(); + map = objectCopy.map; + return *this; + } - for (i = 0; i < size; i++) { - deleteValue(map.valueAt(i)); +private: + KeyedVector 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; } - map.clear(); -} + /** + * 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(); + + 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. - * - * @param value - session object to free - * - */ -void deleteValue(NODE value) { - delete value; -} + /** + * decides if session is already created. + * + * @param key - key of the value for the session + * + * @return boolean result of whether session is created + */ + 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; + } }; }; diff --git a/drm/libdrmframework/plugins/common/util/src/MimeTypeUtil.cpp b/drm/libdrmframework/plugins/common/util/src/MimeTypeUtil.cpp index 4ee903e..57ef799 100644 --- a/drm/libdrmframework/plugins/common/util/src/MimeTypeUtil.cpp +++ b/drm/libdrmframework/plugins/common/util/src/MimeTypeUtil.cpp @@ -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,48 +115,52 @@ 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) { - /* Check which group the mimetype is */ - pGroup = mimeGroup; - - while (MIMETYPE_LAST != pGroup->type) { - if (0 == strncmp(pMimeType, pGroup->pGroup, pGroup->size)) { - break; + 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; + } + pGroup++; } - pGroup++; - } - - /* Go through the mimetype list. Only check items of the correct group */ - if (MIMETYPE_LAST != pGroup->type) { - pMimeItem = mimeTypeList; - len = strlen (pMimeType+pGroup->size); - while (MIMETYPE_LAST != pMimeItem->type) { - if ((len == pMimeItem->size) && - (0 == strcmp(pMimeType+pGroup->size, pMimeItem->pMimeExt))) { - result = String8(pMimeItem->pMimeType); - break; + /* Go through the mimetype list. Only check items of the correct group */ + if (MIMETYPE_LAST != pGroup->type) { + pMimeItem = mimeTypeList; + len = strlen (pMimeType+pGroup->size); + while (MIMETYPE_LAST != pMimeItem->type) { + if ((pGroup->type == pMimeItem->type) && + (len == pMimeItem->size) && + (0 == strcmp(pMimeType+pGroup->size, pMimeItem->pMimeExt))) { + result = String8(pMimeItem->pMimeType); + break; + } + pMimeItem++; } - pMimeItem++; } + } else { + result = String8(mime_type_unsupported); } - LOGI("convertMimeType got mimetype %s, converted into mimetype %s", - pMimeType, result.string()); + LOG_DEBUG("convertMimeType got mimetype %s, converted into mimetype %s", + pMimeType, result.string()); } - return result; } }; diff --git a/drm/libdrmframework/plugins/forward-lock/FwdLockEngine/Android.mk b/drm/libdrmframework/plugins/forward-lock/FwdLockEngine/Android.mk index d4a6f18..21de4ea 100644 --- a/drm/libdrmframework/plugins/forward-lock/FwdLockEngine/Android.mk +++ b/drm/libdrmframework/plugins/forward-lock/FwdLockEngine/Android.mk @@ -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. diff --git a/drm/libdrmframework/plugins/forward-lock/FwdLockEngine/src/FwdLockEngine.cpp b/drm/libdrmframework/plugins/forward-lock/FwdLockEngine/src/FwdLockEngine.cpp index d430f72..9453a20 100644 --- a/drm/libdrmframework/plugins/forward-lock/FwdLockEngine/src/FwdLockEngine.cpp +++ b/drm/libdrmframework/plugins/forward-lock/FwdLockEngine/src/FwdLockEngine.cpp @@ -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(); - convertSessionMap.destroyMap(); - decodeSessionMap.destroyMap(); + for (int i = 0; i < size; i++) { + DecodeSession *session = (DecodeSession*) decodeSessionMap.getValueAt(i); + FwdLockFile_detach(session->fileDesc); + ::close(session->fileDesc); + } + + 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; diff --git a/drm/libdrmframework/plugins/forward-lock/internal-format/converter/FwdLockConv.c b/drm/libdrmframework/plugins/forward-lock/internal-format/converter/FwdLockConv.c index 14ea9e9..299116d 100644 --- a/drm/libdrmframework/plugins/forward-lock/internal-format/converter/FwdLockConv.c +++ b/drm/libdrmframework/plugins/forward-lock/internal-format/converter/FwdLockConv.c @@ -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 { diff --git a/drm/libdrmframework/plugins/forward-lock/internal-format/decoder/FwdLockFile.c b/drm/libdrmframework/plugins/forward-lock/internal-format/decoder/FwdLockFile.c index 98284e7..dacf00e 100644 --- a/drm/libdrmframework/plugins/forward-lock/internal-format/decoder/FwdLockFile.c +++ b/drm/libdrmframework/plugins/forward-lock/internal-format/decoder/FwdLockFile.c @@ -114,7 +114,7 @@ static int FwdLockFile_AcquireSession(int fileDesc) { } /** - * Finds the file session associated to the given file descriptor. + * Finds the file session associated with the given file descriptor. * * @param[in] fileDesc A file descriptor. * @@ -389,7 +389,7 @@ int FwdLockFile_CheckDataIntegrity(int fileDesc) { result = FALSE; } else { ssize_t numBytesRead; - size_t signatureSize = SHA1_HASH_SIZE; + unsigned int signatureSize = SHA1_HASH_SIZE; while ((numBytesRead = read(pSession->fileDesc, pData->buffer, SIG_CALC_BUFFER_SIZE)) > 0) { HMAC_Update(&pSession->signingContext, pData->buffer, (size_t)numBytesRead); @@ -399,7 +399,7 @@ int FwdLockFile_CheckDataIntegrity(int fileDesc) { } else { HMAC_Final(&pSession->signingContext, pData->signature, &signatureSize); assert(signatureSize == SHA1_HASH_SIZE); - result = memcmp(pData->signature, pSession->dataSignature, signatureSize) == 0; + result = memcmp(pData->signature, pSession->dataSignature, SHA1_HASH_SIZE) == 0; } HMAC_Init_ex(&pSession->signingContext, NULL, KEY_SIZE, NULL, NULL); (void)lseek64(pSession->fileDesc, pSession->dataOffset + pSession->filePos, @@ -419,16 +419,16 @@ int FwdLockFile_CheckHeaderIntegrity(int fileDesc) { } else { FwdLockFile_Session_t *pSession = sessionPtrs[sessionId]; unsigned char signature[SHA1_HASH_SIZE]; - size_t signatureSize = SHA1_HASH_SIZE; + unsigned int signatureSize = SHA1_HASH_SIZE; HMAC_Update(&pSession->signingContext, pSession->topHeader, TOP_HEADER_SIZE); HMAC_Update(&pSession->signingContext, (unsigned char *)pSession->pContentType, pSession->contentTypeLength); HMAC_Update(&pSession->signingContext, pSession->pEncryptedSessionKey, pSession->encryptedSessionKeyLength); - HMAC_Update(&pSession->signingContext, pSession->dataSignature, signatureSize); + HMAC_Update(&pSession->signingContext, pSession->dataSignature, SHA1_HASH_SIZE); HMAC_Final(&pSession->signingContext, signature, &signatureSize); assert(signatureSize == SHA1_HASH_SIZE); - result = memcmp(signature, pSession->headerSignature, signatureSize) == 0; + result = memcmp(signature, pSession->headerSignature, SHA1_HASH_SIZE) == 0; HMAC_Init_ex(&pSession->signingContext, NULL, KEY_SIZE, NULL, NULL); } return result; -- cgit v1.1