diff options
Diffstat (limited to 'drm/libdrmframework/plugins/forward-lock')
21 files changed, 0 insertions, 5003 deletions
diff --git a/drm/libdrmframework/plugins/forward-lock/Android.mk b/drm/libdrmframework/plugins/forward-lock/Android.mk deleted file mode 100644 index 9ee7961..0000000 --- a/drm/libdrmframework/plugins/forward-lock/Android.mk +++ /dev/null @@ -1,16 +0,0 @@ -# -# Copyright (C) 2010 The Android Open Source Project -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# -include $(call all-subdir-makefiles) diff --git a/drm/libdrmframework/plugins/forward-lock/FwdLockEngine/Android.mk b/drm/libdrmframework/plugins/forward-lock/FwdLockEngine/Android.mk deleted file mode 100644 index e359dbd..0000000 --- a/drm/libdrmframework/plugins/forward-lock/FwdLockEngine/Android.mk +++ /dev/null @@ -1,70 +0,0 @@ -# -# Copyright (C) 2010 The Android Open Source Project -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# -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. -ifneq ($(shell grep -c 'off64_t offset' $(base)/drm/libdrmframework/plugins/common/include/IDrmEngine.h), 0) -LOCAL_CFLAGS += -DUSE_64BIT_DRM_API -endif - -LOCAL_SRC_FILES:= \ - src/FwdLockEngine.cpp - -LOCAL_MODULE := libfwdlockengine - -LOCAL_SHARED_LIBRARIES := \ - libicui18n \ - libicuuc \ - libutils \ - libdl \ - libandroid_runtime \ - libnativehelper \ - libcrypto \ - libssl \ - libdrmframework - -LOCAL_STATIC_LIBRARIES := \ - libdrmutility \ - libdrmframeworkcommon \ - libfwdlock-common \ - libfwdlock-converter \ - libfwdlock-decoder - - - -LOCAL_C_INCLUDES += \ - $(JNI_H_INCLUDE) \ - $(base)/include/drm \ - $(base)/drm/libdrmframework/plugins/common/include \ - $(base)/drm/libdrmframework/plugins/common/util/include \ - $(base)/drm/libdrmframework/plugins/forward-lock/internal-format/common \ - $(base)/drm/libdrmframework/plugins/forward-lock/internal-format/converter \ - $(base)/drm/libdrmframework/plugins/forward-lock/internal-format/decoder \ - $(LOCAL_PATH)/include \ - external/openssl/include - -LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/drm - -LOCAL_MODULE_TAGS := optional - -include $(BUILD_SHARED_LIBRARY) diff --git a/drm/libdrmframework/plugins/forward-lock/FwdLockEngine/include/FwdLockEngine.h b/drm/libdrmframework/plugins/forward-lock/FwdLockEngine/include/FwdLockEngine.h deleted file mode 100644 index c0e408e..0000000 --- a/drm/libdrmframework/plugins/forward-lock/FwdLockEngine/include/FwdLockEngine.h +++ /dev/null @@ -1,567 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef __FWDLOCKENGINE_H__ -#define __FWDLOCKENGINE_H__ - -#include <DrmEngineBase.h> -#include <DrmConstraints.h> -#include <DrmRights.h> -#include <DrmInfo.h> -#include <DrmInfoStatus.h> -#include <DrmConvertedStatus.h> -#include <DrmInfoRequest.h> -#include <DrmSupportInfo.h> -#include <DrmInfoEvent.h> - -#include "SessionMap.h" -#include "FwdLockConv.h" - -namespace android { - -/** - * Forward Lock Engine class. - */ -class FwdLockEngine : public android::DrmEngineBase { - -public: - FwdLockEngine(); - virtual ~FwdLockEngine(); - -protected: -/** - * Get constraint information associated with input content. - * - * @param uniqueId Unique identifier for a session - * @param path Path of the protected content - * @param action Actions defined such as, - * Action::DEFAULT, Action::PLAY, etc - * @return DrmConstraints - * key-value pairs of constraint are embedded in it - * @note - * In case of error, return NULL - */ -DrmConstraints* onGetConstraints(int uniqueId, const String8* path, int action); - -/** - * Get metadata information associated with input content. - * - * @param uniqueId Unique identifier for a session - * @param path Path of the protected content - * @return DrmMetadata - * For Forward Lock engine, it returns an empty object - * @note - * In case of error, returns NULL - */ -DrmMetadata* onGetMetadata(int uniqueId, const String8* path); - -/** - * Initialize plug-in. - * - * @param uniqueId Unique identifier for a session - * @return status_t - * Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure - */ -status_t onInitialize(int uniqueId); - -/** - * Register a callback to be invoked when the caller required to - * receive necessary information. - * - * @param uniqueId Unique identifier for a session - * @param infoListener Listener - * @return status_t - * Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure - */ -status_t onSetOnInfoListener(int uniqueId, const IDrmEngine::OnInfoListener* infoListener); - -/** - * Terminate the plug-in and release resources bound to it. - * - * @param uniqueId Unique identifier for a session - * @return status_t - * Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure - */ -status_t onTerminate(int uniqueId); - -/** - * Get whether the given content can be handled by this plugin or not. - * - * @param uniqueId Unique identifier for a session - * @param path Path to the protected object - * @return bool - * Returns true if this plugin can handle , false in case of not able to handle - */ -bool onCanHandle(int uniqueId, const String8& path); - -/** - * Processes the given DRM information as appropriate for its type. - * Not used for Forward Lock Engine. - * - * @param uniqueId Unique identifier for a session - * @param drmInfo Information that needs to be processed - * @return DrmInfoStatus - * instance as a result of processing given input - */ -DrmInfoStatus* onProcessDrmInfo(int uniqueId, const DrmInfo* drmInfo); - -/** - * Save DRM rights to specified rights path - * and make association with content path. - * - * @param uniqueId Unique identifier for a session - * @param drmRights DrmRights to be saved - * @param rightsPath File path where rights to be saved - * @param contentPath File path where content was saved - * @return status_t - * Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure - */ -status_t onSaveRights(int uniqueId, - const DrmRights& drmRights, - const String8& rightsPath, - const String8& contentPath); - -/** - * Retrieves necessary information for registration, unregistration or rights - * acquisition information. - * - * @param uniqueId Unique identifier for a session - * @param drmInfoRequest Request information to retrieve drmInfo - * @return DrmInfo - * instance as a result of processing given input - */ -DrmInfo* onAcquireDrmInfo(int uniqueId, - const DrmInfoRequest* drmInfoRequest); - -/** - * Retrieves the mime type embedded inside the original content. - * - * @param uniqueId Unique identifier for a session - * @param path Path of the protected content - * @return String8 - * Returns mime-type of the original content, such as "video/mpeg" - */ -String8 onGetOriginalMimeType(int uniqueId, const String8& path); - -/** - * Retrieves the type of the protected object (content, rights, etc..) - * using specified path or mimetype. At least one parameter should be non null - * to retrieve DRM object type. - * - * @param uniqueId Unique identifier for a session - * @param path Path of the content or null. - * @param mimeType Mime type of the content or null. - * @return type of the DRM content, - * such as DrmObjectType::CONTENT, DrmObjectType::RIGHTS_OBJECT - */ -int onGetDrmObjectType(int uniqueId, - const String8& path, - const String8& mimeType); - -/** - * Check whether the given content has valid rights or not. - * - * @param uniqueId Unique identifier for a session - * @param path Path of the protected content - * @param action Action to perform (Action::DEFAULT, Action::PLAY, etc) - * @return the status of the rights for the protected content, - * such as RightsStatus::RIGHTS_VALID, RightsStatus::RIGHTS_EXPIRED, etc. - */ -int onCheckRightsStatus(int uniqueId, - const String8& path, - int action); - -/** - * Consumes the rights for a content. - * If the reserve parameter is true the rights are reserved until the same - * application calls this api again with the reserve parameter set to false. - * - * @param uniqueId Unique identifier for a session - * @param decryptHandle Handle for the decryption session - * @param action Action to perform. (Action::DEFAULT, Action::PLAY, etc) - * @param reserve True if the rights should be reserved. - * @return status_t - * Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure - */ -status_t onConsumeRights(int uniqueId, - DecryptHandle* decryptHandle, - int action, - bool reserve); - -/** - * Informs the DRM Engine about the playback actions performed on the DRM files. - * - * @param uniqueId Unique identifier for a session - * @param decryptHandle Handle for the decryption session - * @param playbackStatus Playback action (Playback::START, Playback::STOP, Playback::PAUSE) - * @param position Position in the file (in milliseconds) where the start occurs. - * Only valid together with Playback::START. - * @return status_t - * Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure - */ -#ifdef USE_64BIT_DRM_API -status_t onSetPlaybackStatus(int uniqueId, - DecryptHandle* decryptHandle, - int playbackStatus, - int64_t position); -#else -status_t onSetPlaybackStatus(int uniqueId, - DecryptHandle* decryptHandle, - int playbackStatus, - int position); -#endif - -/** - * Validates whether an action on the DRM content is allowed or not. - * - * @param uniqueId Unique identifier for a session - * @param path Path of the protected content - * @param action Action to validate (Action::PLAY, Action::TRANSFER, etc) - * @param description Detailed description of the action - * @return true if the action is allowed. - */ -bool onValidateAction(int uniqueId, - const String8& path, - int action, - const ActionDescription& description); - -/** - * Removes the rights associated with the given protected content. - * Not used for Forward Lock Engine. - * - * @param uniqueId Unique identifier for a session - * @param path Path of the protected content - * @return status_t - * Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure - */ -status_t onRemoveRights(int uniqueId, const String8& path); - -/** - * Removes all the rights information of each plug-in associated with - * DRM framework. Will be used in master reset but does nothing for - * Forward Lock Engine. - * - * @param uniqueId Unique identifier for a session - * @return status_t - * Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure - */ -status_t onRemoveAllRights(int uniqueId); - -/** - * Starts the Forward Lock file conversion session. - * Each time the application tries to download a new DRM file - * which needs to be converted, then the application has to - * begin with calling this API. The convertId is used as the conversion session key - * and must not be the same for different convert sessions. - * - * @param uniqueId Unique identifier for a session - * @param convertId Handle for the convert session - * @return status_t - * Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure - */ -status_t onOpenConvertSession(int uniqueId, int convertId); - -/** - * Accepts and converts the input data which is part of DRM file. - * The resultant converted data and the status is returned in the DrmConvertedInfo - * object. This method will be called each time there is a new block - * of data received by the application. - * - * @param uniqueId Unique identifier for a session - * @param convertId Handle for the convert session - * @param inputData Input Data which need to be converted - * @return Return object contains the status of the data conversion, - * the output converted data and offset. In this case the - * application will ignore the offset information. - */ -DrmConvertedStatus* onConvertData(int uniqueId, - int convertId, - const DrmBuffer* inputData); - -/** - * Closes the convert session in case of data supply completed or error occurred. - * Upon successful conversion of the complete data, it returns signature calculated over - * the entire data used over a conversion session. This signature must be copied to the offset - * mentioned in the DrmConvertedStatus. Signature is used for data integrity protection. - * - * @param uniqueId Unique identifier for a session - * @param convertId Handle for the convert session - * @return Return object contains the status of the data conversion, - * the header and body signature data. It also informs - * the application about the file offset at which this - * signature data should be written. - */ -DrmConvertedStatus* onCloseConvertSession(int uniqueId, int convertId); - -/** - * Returns the information about the Drm Engine capabilities which includes - * supported MimeTypes and file suffixes. - * - * @param uniqueId Unique identifier for a session - * @return DrmSupportInfo - * instance which holds the capabilities of a plug-in - */ -DrmSupportInfo* onGetSupportInfo(int uniqueId); - -/** - * Open the decrypt session to decrypt the given protected content. - * - * @param uniqueId Unique identifier for a session - * @param decryptHandle Handle for the current decryption session - * @param fd File descriptor of the protected content to be decrypted - * @param offset Start position of the content - * @param length The length of the protected content - * @return - * DRM_ERROR_CANNOT_HANDLE for failure and DRM_NO_ERROR for success - */ -#ifdef USE_64BIT_DRM_API -status_t onOpenDecryptSession(int uniqueId, - DecryptHandle* decryptHandle, - int fd, off64_t offset, off64_t length); -#else -status_t onOpenDecryptSession(int uniqueId, - DecryptHandle* decryptHandle, - int fd, int offset, int length); -#endif - -/** - * Open the decrypt session to decrypt the given protected content. - * - * @param uniqueId Unique identifier for a session - * @param decryptHandle Handle for the current decryption session - * @param uri Path of the protected content to be decrypted - * @return - * DRM_ERROR_CANNOT_HANDLE for failure and DRM_NO_ERROR for success - */ -status_t onOpenDecryptSession(int uniqueId, - DecryptHandle* decryptHandle, - const char* uri); - -/** - * Close the decrypt session for the given handle. - * - * @param uniqueId Unique identifier for a session - * @param decryptHandle Handle for the decryption session - * @return status_t - * Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure - */ -status_t onCloseDecryptSession(int uniqueId, - DecryptHandle* decryptHandle); - -/** - * Initialize decryption for the given unit of the protected content. - * - * @param uniqueId Unique identifier for a session - * @param decryptHandle Handle for the decryption session - * @param decryptUnitId ID which specifies decryption unit, such as track ID - * @param headerInfo Information for initializing decryption of this decrypUnit - * @return - * DRM_ERROR_CANNOT_HANDLE for failure and DRM_NO_ERROR for success - */ -status_t onInitializeDecryptUnit(int uniqueId, - DecryptHandle* decryptHandle, - int decryptUnitId, - const DrmBuffer* headerInfo); - -/** - * Decrypt the protected content buffers for the given unit. - * This method will be called any number of times, based on number of - * encrypted streams received from application. - * - * @param uniqueId Unique identifier for a session - * @param decryptHandle Handle for the decryption session - * @param decryptUnitId ID which specifies decryption unit, such as track ID - * @param encBuffer Encrypted data block - * @param decBuffer Decrypted data block - * @return status_t - * Returns the error code for this API - * DRM_NO_ERROR for success, and one of DRM_ERROR_UNKNOWN, DRM_ERROR_LICENSE_EXPIRED - * DRM_ERROR_SESSION_NOT_OPENED, DRM_ERROR_DECRYPT_UNIT_NOT_INITIALIZED, - * DRM_ERROR_DECRYPT for failure. - */ -status_t onDecrypt(int uniqueId, - DecryptHandle* decryptHandle, - int decryptUnitId, - const DrmBuffer* encBuffer, - DrmBuffer** decBuffer); - -/** - * Decrypt the protected content buffers for the given unit. - * This method will be called any number of times, based on number of - * encrypted streams received from application. - * - * @param uniqueId Unique identifier for a session - * @param decryptId Handle for the decryption session - * @param decryptUnitId ID Specifies decryption unit, such as track ID - * @param encBuffer Encrypted data block - * @param decBuffer Decrypted data block - * @param IV Optional buffer - * @return status_t - * Returns the error code for this API - * DRM_NO_ERROR for success, and one of DRM_ERROR_UNKNOWN, DRM_ERROR_LICENSE_EXPIRED - * DRM_ERROR_SESSION_NOT_OPENED, DRM_ERROR_DECRYPT_UNIT_NOT_INITIALIZED, - * DRM_ERROR_DECRYPT for failure. - */ -status_t onDecrypt(int uniqueId, DecryptHandle* decryptHandle, - int decryptUnitId, const DrmBuffer* encBuffer, - DrmBuffer** decBuffer, DrmBuffer* IV); - -/** - * Finalize decryption for the given unit of the protected content. - * - * @param uniqueId Unique identifier for a session - * @param decryptHandle Handle for the decryption session - * @param decryptUnitId ID Specifies decryption unit, such as track ID - * @return - * DRM_ERROR_CANNOT_HANDLE for failure and DRM_NO_ERROR for success - */ -status_t onFinalizeDecryptUnit(int uniqueId, - DecryptHandle* decryptHandle, - int decryptUnitId); - -/** - * Reads the specified number of bytes from an open DRM file. - * - * @param uniqueId Unique identifier for a session - * @param decryptHandle Handle for the decryption session - * @param buffer Reference to the buffer that should receive the read data. - * @param numBytes Number of bytes to read. - * - * @return Number of bytes read. - * @retval -1 Failure. - */ -ssize_t onRead(int uniqueId, - DecryptHandle* decryptHandle, - void* pBuffer, - int numBytes); - -/** - * Updates the file position within an open DRM file. - * - * @param uniqueId Unique identifier for a session - * @param decryptHandle Handle for the decryption session - * @param offset Offset with which to update the file position. - * @param whence One of SEEK_SET, SEEK_CUR, and SEEK_END. - * These constants are defined in unistd.h. - * - * @return New file position. - * @retval ((off_t)-1) Failure. - */ -#ifdef USE_64BIT_DRM_API -off64_t onLseek(int uniqueId, - DecryptHandle* decryptHandle, - off64_t offset, - int whence); -#else -off_t onLseek(int uniqueId, - DecryptHandle* decryptHandle, - off_t offset, - int whence); -#endif - -/** - * Reads the specified number of bytes from an open DRM file. - * - * @param uniqueId Unique identifier for a session - * @param decryptHandle Handle for the decryption session - * @param buffer Reference to the buffer that should receive the read data. - * @param numBytes Number of bytes to read. - * @param offset Offset with which to update the file position. - * - * @return Number of bytes read. Returns -1 for Failure. - */ -#ifdef USE_64BIT_DRM_API -ssize_t onPread(int uniqueId, - DecryptHandle* decryptHandle, - void* buffer, - ssize_t numBytes, - off64_t offset); -#else -ssize_t onPread(int uniqueId, - DecryptHandle* decryptHandle, - void* buffer, - ssize_t numBytes, - off_t offset); -#endif - -private: - - static const String8 Description; - static const String8 FileSuffixes[]; - static const String8 MimeTypes[]; - static bool IsFileSuffixSupported(const String8& suffix); - static bool IsMimeTypeSupported(const String8& mime); - static void AddSupportedMimeTypes(DrmSupportInfo *info); - static void AddSupportedFileSuffixes(DrmSupportInfo *info); - -/** - * Session Class for Forward Lock Conversion. An object of this class is created - * for every conversion. - */ -class ConvertSession { - public : - int uniqueId; - FwdLockConv_Output_t output; - - ConvertSession() { - uniqueId = 0; - memset(&output, 0, sizeof(FwdLockConv_Output_t)); - } - - virtual ~ConvertSession() {} -}; - -/** - * Session Class for Forward Lock decoder. An object of this class is created - * for every decoding session. - */ -class DecodeSession { - public : - int fileDesc; - off_t offset; - - DecodeSession() { - fileDesc = -1; - offset = 0; - } - - DecodeSession(int fd) { - fileDesc = fd; - offset = 0; - } - - virtual ~DecodeSession() {} -}; - -/** - * Session Map Tables for Conversion and Decoding of forward lock files. - */ -SessionMap<ConvertSession*> convertSessionMap; -SessionMap<DecodeSession*> decodeSessionMap; - -/** - * Converts the error code from Forward Lock Converter to DrmConvertStatus error code. - * - * @param Forward Lock Converter error code - * - * @return Status code from DrmConvertStatus. - */ -static int getConvertedStatus(FwdLockConv_Status_t status); -}; - -}; - -#endif /* __FWDLOCKENGINE_H__ */ diff --git a/drm/libdrmframework/plugins/forward-lock/FwdLockEngine/src/FwdLockEngine.cpp b/drm/libdrmframework/plugins/forward-lock/FwdLockEngine/src/FwdLockEngine.cpp deleted file mode 100644 index 4b1b40e..0000000 --- a/drm/libdrmframework/plugins/forward-lock/FwdLockEngine/src/FwdLockEngine.cpp +++ /dev/null @@ -1,695 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "SessionMap.h" -#include "FwdLockEngine.h" -#include <utils/Log.h> -#include <errno.h> -#include <stdio.h> -#include <unistd.h> -#include "drm_framework_common.h" -#include <fcntl.h> -#include <limits.h> -#include <DrmRights.h> -#include <DrmConstraints.h> -#include <DrmMetadata.h> -#include <DrmInfo.h> -#include <DrmInfoStatus.h> -#include <DrmInfoRequest.h> -#include <DrmSupportInfo.h> -#include <DrmConvertedStatus.h> -#include <utils/String8.h> -#include "FwdLockConv.h" -#include "FwdLockFile.h" -#include "FwdLockGlue.h" -#include "MimeTypeUtil.h" - -#undef LOG_TAG -#define LOG_TAG "FwdLockEngine" - -#ifdef DRM_OMA_FL_ENGINE_DEBUG -#define LOG_NDEBUG 0 -#define LOG_VERBOSE(...) ALOGV(__VA_ARGS__) -#else -#define LOG_VERBOSE(...) -#endif - -using namespace android; -// This extern "C" is mandatory to be managed by TPlugInManager -extern "C" IDrmEngine* create() { - return new FwdLockEngine(); -} - -// This extern "C" is mandatory to be managed by TPlugInManager -extern "C" void destroy(IDrmEngine* plugIn) { - delete plugIn; -} - -FwdLockEngine::FwdLockEngine() { - LOG_VERBOSE("FwdLockEngine Construction"); -} - -FwdLockEngine::~FwdLockEngine() { - 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); - } - - 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) { - int retStatus = DrmConvertedStatus::STATUS_ERROR; - - switch(status) { - case FwdLockConv_Status_OK: - retStatus = DrmConvertedStatus::STATUS_OK; - break; - case FwdLockConv_Status_SyntaxError: - case FwdLockConv_Status_InvalidArgument: - case FwdLockConv_Status_UnsupportedFileFormat: - case FwdLockConv_Status_UnsupportedContentTransferEncoding: - ALOGE("FwdLockEngine getConvertedStatus: file conversion Error %d. " - "Returning STATUS_INPUTDATA_ERROR", status); - retStatus = DrmConvertedStatus::STATUS_INPUTDATA_ERROR; - break; - default: - ALOGE("FwdLockEngine getConvertedStatus: file conversion Error %d. " - "Returning STATUS_ERROR", status); - retStatus = DrmConvertedStatus::STATUS_ERROR; - break; - } - - return retStatus; -} - -DrmConstraints* FwdLockEngine::onGetConstraints(int uniqueId, const String8* path, int action) { - DrmConstraints* drmConstraints = NULL; - - LOG_VERBOSE("FwdLockEngine::onGetConstraints"); - - if (NULL != path && - (RightsStatus::RIGHTS_VALID == onCheckRightsStatus(uniqueId, *path, action))) { - // Return the empty constraints to show no error condition. - drmConstraints = new DrmConstraints(); - } - - return drmConstraints; -} - -DrmMetadata* FwdLockEngine::onGetMetadata(int uniqueId, const String8* path) { - DrmMetadata* drmMetadata = NULL; - - LOG_VERBOSE("FwdLockEngine::onGetMetadata"); - - if (NULL != path) { - // Returns empty metadata to show no error condition. - drmMetadata = new DrmMetadata(); - } - - return drmMetadata; -} - -android::status_t FwdLockEngine::onInitialize(int uniqueId) { - LOG_VERBOSE("FwdLockEngine::onInitialize"); - - if (FwdLockGlue_InitializeKeyEncryption()) { - LOG_VERBOSE("FwdLockEngine::onInitialize -- FwdLockGlue_InitializeKeyEncryption succeeded"); - } else { - ALOGE("FwdLockEngine::onInitialize -- FwdLockGlue_InitializeKeyEncryption failed:" - "errno = %d", errno); - } - - return DRM_NO_ERROR; -} - -android::status_t -FwdLockEngine::onSetOnInfoListener(int uniqueId, const IDrmEngine::OnInfoListener* infoListener) { - // Not used - LOG_VERBOSE("FwdLockEngine::onSetOnInfoListener"); - - return DRM_NO_ERROR; -} - -android::status_t FwdLockEngine::onTerminate(int uniqueId) { - LOG_VERBOSE("FwdLockEngine::onTerminate"); - - return DRM_NO_ERROR; -} - -// make sure that lower-case letters are used. -const String8 FwdLockEngine::FileSuffixes[] = { - String8(".fl"), - String8(".dm"), -}; - -// make sure that lower-case letters are used. -const String8 FwdLockEngine::MimeTypes[] = { - String8("application/x-android-drm-fl"), - String8("application/vnd.oma.drm.message"), -}; - -const String8 FwdLockEngine::Description("OMA V1 Forward Lock"); - -void FwdLockEngine::AddSupportedMimeTypes(DrmSupportInfo *info) { - for (size_t i = 0, n = sizeof(MimeTypes)/sizeof(MimeTypes[0]); i < n; ++i) { - info->addMimeType(MimeTypes[i]); - } -} - -void FwdLockEngine::AddSupportedFileSuffixes(DrmSupportInfo *info) { - for (size_t i = 0, n = sizeof(FileSuffixes)/sizeof(FileSuffixes[0]); i < n; ++i) { - info->addFileSuffix(FileSuffixes[i]); - } -} - -bool FwdLockEngine::IsMimeTypeSupported(const String8& mime) { - String8 tmp(mime); - tmp.toLower(); - for (size_t i = 0, n = sizeof(MimeTypes)/sizeof(MimeTypes[0]); i < n; ++i) { - if (tmp == MimeTypes[i]) { - return true; - } - } - return false; -} - -bool FwdLockEngine::IsFileSuffixSupported(const String8& suffix) { - String8 tmp(suffix); - tmp.toLower(); - for (size_t i = 0, n = sizeof(FileSuffixes)/sizeof(FileSuffixes[0]); i < n; ++i) { - if (tmp == FileSuffixes[i]) { - return true; - } - } - return false; -} - -DrmSupportInfo* FwdLockEngine::onGetSupportInfo(int uniqueId) { - DrmSupportInfo* pSupportInfo = new DrmSupportInfo(); - - LOG_VERBOSE("FwdLockEngine::onGetSupportInfo"); - - // fill all Forward Lock mimetypes and extensions - if (NULL != pSupportInfo) { - AddSupportedMimeTypes(pSupportInfo); - AddSupportedFileSuffixes(pSupportInfo); - pSupportInfo->setDescription(Description); - } - - return pSupportInfo; -} - -bool FwdLockEngine::onCanHandle(int uniqueId, const String8& path) { - bool result = false; - - String8 extString = path.getPathExtension(); - return IsFileSuffixSupported(extString); -} - -DrmInfoStatus* FwdLockEngine::onProcessDrmInfo(int uniqueId, const DrmInfo* drmInfo) { - DrmInfoStatus *drmInfoStatus = NULL; - - // Nothing to process - - drmInfoStatus = new DrmInfoStatus((int)DrmInfoStatus::STATUS_OK, 0, NULL, String8("")); - - LOG_VERBOSE("FwdLockEngine::onProcessDrmInfo"); - - return drmInfoStatus; -} - -status_t FwdLockEngine::onSaveRights( - int uniqueId, - const DrmRights& drmRights, - const String8& rightsPath, - const String8& contentPath) { - // No rights to save. Return - LOG_VERBOSE("FwdLockEngine::onSaveRights"); - return DRM_ERROR_UNKNOWN; -} - -DrmInfo* FwdLockEngine::onAcquireDrmInfo(int uniqueId, const DrmInfoRequest* drmInfoRequest) { - DrmInfo* drmInfo = NULL; - - // Nothing to be done for Forward Lock file - LOG_VERBOSE("FwdLockEngine::onAcquireDrmInfo"); - - return drmInfo; -} - -int FwdLockEngine::onCheckRightsStatus(int uniqueId, - const String8& path, - int action) { - int result = RightsStatus::RIGHTS_INVALID; - - LOG_VERBOSE("FwdLockEngine::onCheckRightsStatus"); - - // Only Transfer action is not allowed for forward Lock files. - if (onCanHandle(uniqueId, path)) { - switch(action) { - case Action::DEFAULT: - case Action::PLAY: - case Action::RINGTONE: - case Action::OUTPUT: - case Action::PREVIEW: - case Action::EXECUTE: - case Action::DISPLAY: - result = RightsStatus::RIGHTS_VALID; - break; - - case Action::TRANSFER: - default: - result = RightsStatus::RIGHTS_INVALID; - break; - } - } - - return result; -} - -status_t FwdLockEngine::onConsumeRights(int uniqueId, - DecryptHandle* decryptHandle, - int action, - bool reserve) { - // No rights consumption - LOG_VERBOSE("FwdLockEngine::onConsumeRights"); - return DRM_NO_ERROR; -} - -bool FwdLockEngine::onValidateAction(int uniqueId, - const String8& path, - int action, - const ActionDescription& description) { - 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) { - LOG_VERBOSE("FwdLockEngine::onGetOriginalMimeType"); - String8 mimeString = String8(""); - int fileDesc = FwdLockFile_open(path.string()); - - if (-1 < fileDesc) { - const char* pMimeType = FwdLockFile_GetContentType(fileDesc); - - if (NULL != pMimeType) { - String8 contentType = String8(pMimeType); - contentType.toLower(); - mimeString = MimeTypeUtil::convertMimeType(contentType); - } - - FwdLockFile_close(fileDesc); - } - - return mimeString; -} - -int FwdLockEngine::onGetDrmObjectType(int uniqueId, - const String8& path, - const String8& mimeType) { - String8 mimeStr = String8(mimeType); - - LOG_VERBOSE("FwdLockEngine::onGetDrmObjectType"); - - /* Checks whether - * 1. path and mime type both are not empty strings (meaning unavailable) else content is unknown - * 2. if one of them is empty string and if other is known then its a DRM Content Object. - * 3. if both of them are available, then both may be of known type - * (regardless of the relation between them to make it compatible with other DRM Engines) - */ - if (((0 == path.length()) || onCanHandle(uniqueId, path)) && - ((0 == mimeType.length()) || IsMimeTypeSupported(mimeType)) && (mimeType != path) ) { - return DrmObjectType::CONTENT; - } - - return DrmObjectType::UNKNOWN; -} - -status_t FwdLockEngine::onRemoveRights(int uniqueId, const String8& path) { - // No Rights to remove - LOG_VERBOSE("FwdLockEngine::onRemoveRights"); - return DRM_NO_ERROR; -} - -status_t FwdLockEngine::onRemoveAllRights(int uniqueId) { - // No rights to remove - LOG_VERBOSE("FwdLockEngine::onRemoveAllRights"); - return DRM_NO_ERROR; -} - -#ifdef USE_64BIT_DRM_API -status_t FwdLockEngine::onSetPlaybackStatus(int uniqueId, DecryptHandle* decryptHandle, - int playbackStatus, int64_t position) { -#else -status_t FwdLockEngine::onSetPlaybackStatus(int uniqueId, DecryptHandle* decryptHandle, - int playbackStatus, int position) { -#endif - // Not used - LOG_VERBOSE("FwdLockEngine::onSetPlaybackStatus"); - return DRM_NO_ERROR; -} - -status_t FwdLockEngine::onOpenConvertSession(int uniqueId, - int convertId) { - status_t result = DRM_ERROR_UNKNOWN; - LOG_VERBOSE("FwdLockEngine::onOpenConvertSession"); - if (!convertSessionMap.isCreated(convertId)) { - ConvertSession *newSession = new ConvertSession(); - if (FwdLockConv_Status_OK == - FwdLockConv_OpenSession(&(newSession->uniqueId), &(newSession->output))) { - convertSessionMap.addValue(convertId, newSession); - result = DRM_NO_ERROR; - } else { - ALOGE("FwdLockEngine::onOpenConvertSession -- FwdLockConv_OpenSession failed."); - delete newSession; - } - } - return result; -} - -DrmConvertedStatus* FwdLockEngine::onConvertData(int uniqueId, - int convertId, - const DrmBuffer* inputData) { - FwdLockConv_Status_t retStatus = FwdLockConv_Status_InvalidArgument; - DrmBuffer *convResult = new DrmBuffer(NULL, 0); - int offset = -1; - - if (NULL != inputData && convertSessionMap.isCreated(convertId)) { - ConvertSession *convSession = convertSessionMap.getValue(convertId); - - if (NULL != convSession) { - retStatus = FwdLockConv_ConvertData(convSession->uniqueId, - inputData->data, - inputData->length, - &(convSession->output)); - - if (FwdLockConv_Status_OK == retStatus) { - // return bytes from conversion if available - if (convSession->output.fromConvertData.numBytes > 0) { - convResult->data = new char[convSession->output.fromConvertData.numBytes]; - - if (NULL != convResult->data) { - convResult->length = convSession->output.fromConvertData.numBytes; - memcpy(convResult->data, - (char *)convSession->output.fromConvertData.pBuffer, - convResult->length); - } - } - } else { - offset = convSession->output.fromConvertData.errorPos; - } - } - } - return new DrmConvertedStatus(getConvertedStatus(retStatus), convResult, offset); -} - -DrmConvertedStatus* FwdLockEngine::onCloseConvertSession(int uniqueId, - int convertId) { - FwdLockConv_Status_t retStatus = FwdLockConv_Status_InvalidArgument; - DrmBuffer *convResult = new DrmBuffer(NULL, 0); - int offset = -1; - - LOG_VERBOSE("FwdLockEngine::onCloseConvertSession"); - - if (convertSessionMap.isCreated(convertId)) { - ConvertSession *convSession = convertSessionMap.getValue(convertId); - - if (NULL != convSession) { - retStatus = FwdLockConv_CloseSession(convSession->uniqueId, &(convSession->output)); - - if (FwdLockConv_Status_OK == retStatus) { - offset = convSession->output.fromCloseSession.fileOffset; - convResult->data = new char[FWD_LOCK_SIGNATURES_SIZE]; - - if (NULL != convResult->data) { - convResult->length = FWD_LOCK_SIGNATURES_SIZE; - memcpy(convResult->data, - (char *)convSession->output.fromCloseSession.signatures, - convResult->length); - } - } - } - convertSessionMap.removeValue(convertId); - } - return new DrmConvertedStatus(getConvertedStatus(retStatus), convResult, offset); -} - -#ifdef USE_64BIT_DRM_API -status_t FwdLockEngine::onOpenDecryptSession(int uniqueId, - DecryptHandle* decryptHandle, - int fd, - off64_t offset, - off64_t length) { -#else -status_t FwdLockEngine::onOpenDecryptSession(int uniqueId, - DecryptHandle* decryptHandle, - int fd, - int offset, - int length) { -#endif - status_t result = DRM_ERROR_CANNOT_HANDLE; - int fileDesc = -1; - - LOG_VERBOSE("FwdLockEngine::onOpenDecryptSession"); - - if ((-1 < fd) && - (NULL != decryptHandle) && - (!decodeSessionMap.isCreated(decryptHandle->decryptId))) { - fileDesc = dup(fd); - } else { - ALOGE("FwdLockEngine::onOpenDecryptSession parameter error"); - return result; - } - - if (-1 < fileDesc && - -1 < ::lseek(fileDesc, offset, SEEK_SET) && - -1 < FwdLockFile_attach(fileDesc)) { - // check for file integrity. This must be done to protect the content mangling. - int retVal = FwdLockFile_CheckHeaderIntegrity(fileDesc); - DecodeSession* decodeSession = new DecodeSession(fileDesc); - - if (retVal && NULL != decodeSession) { - decodeSessionMap.addValue(decryptHandle->decryptId, decodeSession); - const char *pmime= FwdLockFile_GetContentType(fileDesc); - String8 contentType = String8(pmime == NULL ? "" : pmime); - contentType.toLower(); - decryptHandle->mimeType = MimeTypeUtil::convertMimeType(contentType); - decryptHandle->decryptApiType = DecryptApiType::CONTAINER_BASED; - decryptHandle->status = RightsStatus::RIGHTS_VALID; - decryptHandle->decryptInfo = NULL; - result = DRM_NO_ERROR; - } else { - LOG_VERBOSE("FwdLockEngine::onOpenDecryptSession Integrity Check failed for the fd"); - FwdLockFile_detach(fileDesc); - delete decodeSession; - } - } - - if (DRM_NO_ERROR != result && -1 < fileDesc) { - ::close(fileDesc); - } - - LOG_VERBOSE("FwdLockEngine::onOpenDecryptSession Exit. result = %d", result); - - return result; -} - -status_t FwdLockEngine::onOpenDecryptSession(int uniqueId, - DecryptHandle* decryptHandle, - const char* uri) { - status_t result = DRM_ERROR_CANNOT_HANDLE; - const char fileTag [] = "file://"; - - if (NULL != decryptHandle && NULL != uri && strlen(uri) > sizeof(fileTag)) { - String8 uriTag = String8(uri); - uriTag.toLower(); - - if (0 == strncmp(uriTag.string(), fileTag, sizeof(fileTag) - 1)) { - const char *filePath = strchr(uri + sizeof(fileTag) - 1, '/'); - if (NULL != filePath && onCanHandle(uniqueId, String8(filePath))) { - int fd = open(filePath, O_RDONLY); - - if (-1 < fd) { - // offset is always 0 and length is not used. so any positive size. - result = onOpenDecryptSession(uniqueId, decryptHandle, fd, 0, 1); - - // fd is duplicated already if success. closing the file - close(fd); - } - } - } - } - - return result; -} - -status_t FwdLockEngine::onCloseDecryptSession(int uniqueId, - DecryptHandle* decryptHandle) { - status_t result = DRM_ERROR_UNKNOWN; - LOG_VERBOSE("FwdLockEngine::onCloseDecryptSession"); - - if (NULL != decryptHandle && decodeSessionMap.isCreated(decryptHandle->decryptId)) { - DecodeSession* session = decodeSessionMap.getValue(decryptHandle->decryptId); - if (NULL != session && session->fileDesc > -1) { - FwdLockFile_detach(session->fileDesc); - ::close(session->fileDesc); - decodeSessionMap.removeValue(decryptHandle->decryptId); - result = DRM_NO_ERROR; - } - } - - if (NULL != decryptHandle) { - if (NULL != decryptHandle->decryptInfo) { - delete decryptHandle->decryptInfo; - decryptHandle->decryptInfo = NULL; - } - - decryptHandle->copyControlVector.clear(); - decryptHandle->extendedData.clear(); - - delete decryptHandle; - decryptHandle = NULL; - } - - LOG_VERBOSE("FwdLockEngine::onCloseDecryptSession Exit"); - return result; -} - -status_t FwdLockEngine::onInitializeDecryptUnit(int uniqueId, - DecryptHandle* decryptHandle, - int decryptUnitId, - const DrmBuffer* headerInfo) { - ALOGE("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) { - ALOGE("FwdLockEngine::onDecrypt 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) { - ALOGE("FwdLockEngine::onDecrypt is not supported for this DRM scheme"); - return DRM_ERROR_UNKNOWN; -} - -status_t FwdLockEngine::onFinalizeDecryptUnit(int uniqueId, - DecryptHandle* decryptHandle, - int decryptUnitId) { - ALOGE("FwdLockEngine::onFinalizeDecryptUnit is not supported for this DRM scheme"); - return DRM_ERROR_UNKNOWN; -} - -ssize_t FwdLockEngine::onRead(int uniqueId, - DecryptHandle* decryptHandle, - void* buffer, - int numBytes) { - ssize_t size = -1; - - if (NULL != decryptHandle && - decodeSessionMap.isCreated(decryptHandle->decryptId) && - NULL != buffer && - numBytes > -1) { - DecodeSession* session = decodeSessionMap.getValue(decryptHandle->decryptId); - if (NULL != session && session->fileDesc > -1) { - size = FwdLockFile_read(session->fileDesc, buffer, numBytes); - - if (0 > size) { - session->offset = ((off_t)-1); - } else { - session->offset += size; - } - } - } - - return size; -} - -#ifdef USE_64BIT_DRM_API -off64_t FwdLockEngine::onLseek(int uniqueId, DecryptHandle* decryptHandle, - off64_t offset, int whence) { -#else -off_t FwdLockEngine::onLseek(int uniqueId, DecryptHandle* decryptHandle, - off_t offset, int whence) { -#endif - off_t offval = -1; - - if (NULL != decryptHandle && decodeSessionMap.isCreated(decryptHandle->decryptId)) { - DecodeSession* session = decodeSessionMap.getValue(decryptHandle->decryptId); - if (NULL != session && session->fileDesc > -1) { - offval = FwdLockFile_lseek(session->fileDesc, offset, whence); - session->offset = offval; - } - } - - return offval; -} - -#ifdef USE_64BIT_DRM_API -ssize_t FwdLockEngine::onPread(int uniqueId, - DecryptHandle* decryptHandle, - void* buffer, - ssize_t numBytes, - off64_t offset) { -#else -ssize_t FwdLockEngine::onPread(int uniqueId, - DecryptHandle* decryptHandle, - void* buffer, - ssize_t numBytes, - off_t offset) { -#endif - ssize_t bytesRead = -1; - - DecodeSession* decoderSession = NULL; - - if ((NULL != decryptHandle) && - (NULL != (decoderSession = decodeSessionMap.getValue(decryptHandle->decryptId))) && - (NULL != buffer) && - (numBytes > -1) && - (offset > -1)) { - if (offset != decoderSession->offset) { - decoderSession->offset = onLseek(uniqueId, decryptHandle, offset, SEEK_SET); - } - - if (((off_t)-1) != decoderSession->offset) { - bytesRead = onRead(uniqueId, decryptHandle, buffer, numBytes); - if (bytesRead < 0) { - ALOGE("FwdLockEngine::onPread error reading"); - } - } - } else { - ALOGE("FwdLockEngine::onPread decryptId not found"); - } - - return bytesRead; -} diff --git a/drm/libdrmframework/plugins/forward-lock/internal-format/Android.mk b/drm/libdrmframework/plugins/forward-lock/internal-format/Android.mk deleted file mode 100644 index 9ee7961..0000000 --- a/drm/libdrmframework/plugins/forward-lock/internal-format/Android.mk +++ /dev/null @@ -1,16 +0,0 @@ -# -# Copyright (C) 2010 The Android Open Source Project -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# -include $(call all-subdir-makefiles) diff --git a/drm/libdrmframework/plugins/forward-lock/internal-format/common/Android.mk b/drm/libdrmframework/plugins/forward-lock/internal-format/common/Android.mk deleted file mode 100644 index 6c5d3cf..0000000 --- a/drm/libdrmframework/plugins/forward-lock/internal-format/common/Android.mk +++ /dev/null @@ -1,32 +0,0 @@ -# -# Copyright (C) 2010 The Android Open Source Project -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# -LOCAL_PATH := $(call my-dir) - -include $(CLEAR_VARS) - -LOCAL_SRC_FILES := \ - FwdLockGlue.c - -LOCAL_C_INCLUDES := \ - external/openssl/include - -LOCAL_SHARED_LIBRARIES := libcrypto - -LOCAL_MODULE := libfwdlock-common - -LOCAL_MODULE_TAGS := optional - -include $(BUILD_STATIC_LIBRARY) diff --git a/drm/libdrmframework/plugins/forward-lock/internal-format/common/FwdLockGlue.c b/drm/libdrmframework/plugins/forward-lock/internal-format/common/FwdLockGlue.c deleted file mode 100644 index 92bda8f..0000000 --- a/drm/libdrmframework/plugins/forward-lock/internal-format/common/FwdLockGlue.c +++ /dev/null @@ -1,191 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include <assert.h> -#include <errno.h> -#include <fcntl.h> -#include <pthread.h> -#include <stdlib.h> -#include <string.h> -#include <sys/stat.h> -#include <unistd.h> -#include <openssl/aes.h> - -#include "FwdLockGlue.h" - -#define TRUE 1 -#define FALSE 0 - -#define KEY_SIZE 16 -#define KEY_SIZE_IN_BITS (KEY_SIZE * 8) - -static int isInitialized = FALSE; - -static const char strKeyFilename[] = "/data/drm/fwdlock/kek.dat"; - -static AES_KEY encryptionRoundKeys; -static AES_KEY decryptionRoundKeys; - -/** - * Creates all directories along the fully qualified path of the given file. - * - * @param[in] path A reference to the fully qualified path of a file. - * @param[in] mode The access mode to use for the directories being created. - * - * @return A Boolean value indicating whether the operation was successful. - */ -static int FwdLockGlue_CreateDirectories(const char *path, mode_t mode) { - int result = TRUE; - size_t partialPathLength = strlen(path); - char *partialPath = malloc(partialPathLength + 1); - if (partialPath == NULL) { - result = FALSE; - } else { - size_t i; - for (i = 0; i < partialPathLength; ++i) { - if (path[i] == '/' && i > 0) { - partialPath[i] = '\0'; - if (mkdir(partialPath, mode) != 0 && errno != EEXIST) { - result = FALSE; - break; - } - } - partialPath[i] = path[i]; - } - free(partialPath); - } - return result; -} - -/** - * Initializes the round keys used for encryption and decryption of session keys. First creates a - * device-unique key-encryption key if none exists yet. - */ -static void FwdLockGlue_InitializeRoundKeys() { - unsigned char keyEncryptionKey[KEY_SIZE]; - int fileDesc = open(strKeyFilename, O_RDONLY); - if (fileDesc >= 0) { - if (read(fileDesc, keyEncryptionKey, KEY_SIZE) == KEY_SIZE) { - isInitialized = TRUE; - } - (void)close(fileDesc); - } else if (errno == ENOENT && - FwdLockGlue_GetRandomNumber(keyEncryptionKey, KEY_SIZE) && - FwdLockGlue_CreateDirectories(strKeyFilename, S_IRWXU)) { - fileDesc = open(strKeyFilename, O_CREAT | O_TRUNC | O_WRONLY, S_IRUSR); - if (fileDesc >= 0) { - if (write(fileDesc, keyEncryptionKey, KEY_SIZE) == KEY_SIZE) { - isInitialized = TRUE; - } - (void)close(fileDesc); - } - } - if (isInitialized) { - if (AES_set_encrypt_key(keyEncryptionKey, KEY_SIZE_IN_BITS, &encryptionRoundKeys) != 0 || - AES_set_decrypt_key(keyEncryptionKey, KEY_SIZE_IN_BITS, &decryptionRoundKeys) != 0) { - isInitialized = FALSE; - } - } - memset(keyEncryptionKey, 0, KEY_SIZE); // Zero out key data. -} - -/** - * Validates the padding of a decrypted key. - * - * @param[in] pData A reference to the buffer containing the decrypted key and padding. - * @param[in] decryptedKeyLength The length in bytes of the decrypted key. - * - * @return A Boolean value indicating whether the padding was valid. - */ -static int FwdLockGlue_ValidatePadding(const unsigned char *pData, size_t decryptedKeyLength) { - size_t i; - size_t padding = AES_BLOCK_SIZE - (decryptedKeyLength % AES_BLOCK_SIZE); - pData += decryptedKeyLength; - for (i = 0; i < padding; ++i) { - if ((size_t)*pData != padding) { - return FALSE; - } - ++pData; - } - return TRUE; -} - -int FwdLockGlue_GetRandomNumber(void *pBuffer, size_t numBytes) { - // Generate 'cryptographically secure' random bytes by reading them from "/dev/urandom" (the - // non-blocking version of "/dev/random"). - ssize_t numBytesRead = 0; - int fileDesc = open("/dev/urandom", O_RDONLY); - if (fileDesc >= 0) { - numBytesRead = read(fileDesc, pBuffer, numBytes); - (void)close(fileDesc); - } - return numBytesRead >= 0 && (size_t)numBytesRead == numBytes; -} - -int FwdLockGlue_InitializeKeyEncryption() { - static pthread_once_t once = PTHREAD_ONCE_INIT; - pthread_once(&once, FwdLockGlue_InitializeRoundKeys); - return isInitialized; -} - -size_t FwdLockGlue_GetEncryptedKeyLength(size_t plaintextKeyLength) { - return ((plaintextKeyLength / AES_BLOCK_SIZE) + 2) * AES_BLOCK_SIZE; -} - -int FwdLockGlue_EncryptKey(const void *pPlaintextKey, - size_t plaintextKeyLength, - void *pEncryptedKey, - size_t encryptedKeyLength) { - int result = FALSE; - assert(encryptedKeyLength == FwdLockGlue_GetEncryptedKeyLength(plaintextKeyLength)); - if (FwdLockGlue_InitializeKeyEncryption()) { - unsigned char initVector[AES_BLOCK_SIZE]; - if (FwdLockGlue_GetRandomNumber(initVector, AES_BLOCK_SIZE)) { - size_t padding = AES_BLOCK_SIZE - (plaintextKeyLength % AES_BLOCK_SIZE); - size_t dataLength = encryptedKeyLength - AES_BLOCK_SIZE; - memcpy(pEncryptedKey, pPlaintextKey, plaintextKeyLength); - memset((unsigned char *)pEncryptedKey + plaintextKeyLength, (int)padding, padding); - memcpy((unsigned char *)pEncryptedKey + dataLength, initVector, AES_BLOCK_SIZE); - AES_cbc_encrypt(pEncryptedKey, pEncryptedKey, dataLength, &encryptionRoundKeys, - initVector, AES_ENCRYPT); - result = TRUE; - } - } - return result; -} - -int FwdLockGlue_DecryptKey(const void *pEncryptedKey, - size_t encryptedKeyLength, - void *pDecryptedKey, - size_t decryptedKeyLength) { - int result = FALSE; - assert(encryptedKeyLength == FwdLockGlue_GetEncryptedKeyLength(decryptedKeyLength)); - if (FwdLockGlue_InitializeKeyEncryption()) { - size_t dataLength = encryptedKeyLength - AES_BLOCK_SIZE; - unsigned char *pData = malloc(dataLength); - if (pData != NULL) { - unsigned char initVector[AES_BLOCK_SIZE]; - memcpy(pData, pEncryptedKey, dataLength); - memcpy(initVector, (const unsigned char *)pEncryptedKey + dataLength, AES_BLOCK_SIZE); - AES_cbc_encrypt(pData, pData, dataLength, &decryptionRoundKeys, initVector, - AES_DECRYPT); - memcpy(pDecryptedKey, pData, decryptedKeyLength); - result = FwdLockGlue_ValidatePadding(pData, decryptedKeyLength); - free(pData); - } - } - return result; -} diff --git a/drm/libdrmframework/plugins/forward-lock/internal-format/common/FwdLockGlue.h b/drm/libdrmframework/plugins/forward-lock/internal-format/common/FwdLockGlue.h deleted file mode 100644 index f36f6ea..0000000 --- a/drm/libdrmframework/plugins/forward-lock/internal-format/common/FwdLockGlue.h +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef __FWDLOCKGLUE_H__ -#define __FWDLOCKGLUE_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * Generates the specified number of cryptographically secure random bytes. - * - * @param[out] pBuffer A reference to the buffer that should receive the random data. - * @param[in] numBytes The number of random bytes to generate. - * - * @return A Boolean value indicating whether the operation was successful. - */ -int FwdLockGlue_GetRandomNumber(void *pBuffer, size_t numBytes); - -/** - * Performs initialization of the key-encryption key. Should be called once during startup to - * facilitate encryption and decryption of session keys. - * - * @return A Boolean value indicating whether the operation was successful. - */ -int FwdLockGlue_InitializeKeyEncryption(); - -/** - * Returns the length of the encrypted key, given the length of the plaintext key. - * - * @param[in] plaintextKeyLength The length in bytes of the plaintext key. - * - * @return The length in bytes of the encrypted key. - */ -size_t FwdLockGlue_GetEncryptedKeyLength(size_t plaintextKeyLength); - -/** - * Encrypts the given session key using a key-encryption key unique to this device. - * - * @param[in] pPlaintextKey A reference to the buffer containing the plaintext key. - * @param[in] plaintextKeyLength The length in bytes of the plaintext key. - * @param[out] pEncryptedKey A reference to the buffer containing the encrypted key. - * @param[in] encryptedKeyLength The length in bytes of the encrypted key. - * - * @return A Boolean value indicating whether the operation was successful. - */ -int FwdLockGlue_EncryptKey(const void *pPlaintextKey, - size_t plaintextKeyLength, - void *pEncryptedKey, - size_t encryptedKeyLength); - -/** - * Decrypts the given session key using a key-encryption key unique to this device. - * - * @param[in] pEncryptedKey A reference to the buffer containing the encrypted key. - * @param[in] encryptedKeyLength The length in bytes of the encrypted key. - * @param[out] pDecryptedKey A reference to the buffer containing the decrypted key. - * @param[in] decryptedKeyLength The length in bytes of the decrypted key. - * - * @return A Boolean value indicating whether the operation was successful. - */ -int FwdLockGlue_DecryptKey(const void *pEncryptedKey, - size_t encryptedKeyLength, - void *pDecryptedKey, - size_t decryptedKeyLength); - -#ifdef __cplusplus -} -#endif - -#endif // __FWDLOCKGLUE_H__ diff --git a/drm/libdrmframework/plugins/forward-lock/internal-format/converter/Android.mk b/drm/libdrmframework/plugins/forward-lock/internal-format/converter/Android.mk deleted file mode 100644 index 00bb788..0000000 --- a/drm/libdrmframework/plugins/forward-lock/internal-format/converter/Android.mk +++ /dev/null @@ -1,37 +0,0 @@ -# -# Copyright (C) 2010 The Android Open Source Project -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# -LOCAL_PATH := $(call my-dir) - -include $(CLEAR_VARS) - -LOCAL_SRC_FILES := \ - FwdLockConv.c - -LOCAL_C_INCLUDES := \ - frameworks/base/drm/libdrmframework/plugins/forward-lock/internal-format/common \ - external/openssl/include - -LOCAL_SHARED_LIBRARIES := libcrypto - -LOCAL_WHOLE_STATIC_LIBRARIES := libfwdlock-common - -LOCAL_STATIC_LIBRARIES := libfwdlock-common - -LOCAL_MODULE := libfwdlock-converter - -LOCAL_MODULE_TAGS := optional - -include $(BUILD_STATIC_LIBRARY) diff --git a/drm/libdrmframework/plugins/forward-lock/internal-format/converter/FwdLockConv.c b/drm/libdrmframework/plugins/forward-lock/internal-format/converter/FwdLockConv.c deleted file mode 100644 index 299116d..0000000 --- a/drm/libdrmframework/plugins/forward-lock/internal-format/converter/FwdLockConv.c +++ /dev/null @@ -1,1347 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include <assert.h> -#include <ctype.h> -#include <fcntl.h> -#include <limits.h> -#include <pthread.h> -#include <string.h> -#include <sys/stat.h> -#include <unistd.h> -#include <openssl/aes.h> -#include <openssl/hmac.h> - -#include "FwdLockConv.h" -#include "FwdLockGlue.h" - -#define TRUE 1 -#define FALSE 0 - -#define INVALID_OFFSET ((off64_t)-1) - -#define MAX_NUM_SESSIONS 32 - -#define OUTPUT_BUFFER_SIZE_INCREMENT 1024 -#define READ_BUFFER_SIZE 1024 - -#define MAX_BOUNDARY_LENGTH 70 -#define MAX_DELIMITER_LENGTH (MAX_BOUNDARY_LENGTH + 4) - -#define STRING_LENGTH_INCREMENT 25 - -#define KEY_SIZE AES_BLOCK_SIZE -#define KEY_SIZE_IN_BITS (KEY_SIZE * 8) - -#define SHA1_HASH_SIZE 20 - -#define FWD_LOCK_VERSION 0 -#define FWD_LOCK_SUBFORMAT 0 -#define USAGE_RESTRICTION_FLAGS 0 -#define CONTENT_TYPE_LENGTH_POS 7 -#define TOP_HEADER_SIZE 8 - -/** - * Data type for the parser states of the converter. - */ -typedef enum FwdLockConv_ParserState { - FwdLockConv_ParserState_WantsOpenDelimiter, - FwdLockConv_ParserState_WantsMimeHeaders, - FwdLockConv_ParserState_WantsBinaryEncodedData, - FwdLockConv_ParserState_WantsBase64EncodedData, - FwdLockConv_ParserState_Done -} FwdLockConv_ParserState_t; - -/** - * Data type for the scanner states of the converter. - */ -typedef enum FwdLockConv_ScannerState { - FwdLockConv_ScannerState_WantsFirstDash, - FwdLockConv_ScannerState_WantsSecondDash, - FwdLockConv_ScannerState_WantsCR, - FwdLockConv_ScannerState_WantsLF, - FwdLockConv_ScannerState_WantsBoundary, - FwdLockConv_ScannerState_WantsBoundaryEnd, - FwdLockConv_ScannerState_WantsMimeHeaderNameStart, - FwdLockConv_ScannerState_WantsMimeHeaderName, - FwdLockConv_ScannerState_WantsMimeHeaderNameEnd, - FwdLockConv_ScannerState_WantsContentTypeStart, - FwdLockConv_ScannerState_WantsContentType, - FwdLockConv_ScannerState_WantsContentTransferEncodingStart, - FwdLockConv_ScannerState_Wants_A_OR_I, - FwdLockConv_ScannerState_Wants_N, - FwdLockConv_ScannerState_Wants_A, - FwdLockConv_ScannerState_Wants_R, - FwdLockConv_ScannerState_Wants_Y, - FwdLockConv_ScannerState_Wants_S, - FwdLockConv_ScannerState_Wants_E, - FwdLockConv_ScannerState_Wants_6, - FwdLockConv_ScannerState_Wants_4, - FwdLockConv_ScannerState_Wants_B, - FwdLockConv_ScannerState_Wants_I, - FwdLockConv_ScannerState_Wants_T, - FwdLockConv_ScannerState_WantsContentTransferEncodingEnd, - FwdLockConv_ScannerState_WantsMimeHeaderValueEnd, - FwdLockConv_ScannerState_WantsMimeHeadersEnd, - FwdLockConv_ScannerState_WantsByte1, - FwdLockConv_ScannerState_WantsByte1_AfterCRLF, - FwdLockConv_ScannerState_WantsByte2, - FwdLockConv_ScannerState_WantsByte3, - FwdLockConv_ScannerState_WantsByte4, - FwdLockConv_ScannerState_WantsPadding, - FwdLockConv_ScannerState_WantsWhitespace, - FwdLockConv_ScannerState_WantsWhitespace_AfterCRLF, - FwdLockConv_ScannerState_WantsDelimiter -} FwdLockConv_ScannerState_t; - -/** - * Data type for the content transfer encoding. - */ -typedef enum FwdLockConv_ContentTransferEncoding { - FwdLockConv_ContentTransferEncoding_Undefined, - FwdLockConv_ContentTransferEncoding_Binary, - FwdLockConv_ContentTransferEncoding_Base64 -} FwdLockConv_ContentTransferEncoding_t; - -/** - * Data type for a dynamically growing string. - */ -typedef struct FwdLockConv_String { - char *ptr; - size_t length; - size_t maxLength; - size_t lengthIncrement; -} FwdLockConv_String_t; - -/** - * Data type for the per-file state information needed by the converter. - */ -typedef struct FwdLockConv_Session { - FwdLockConv_ParserState_t parserState; - FwdLockConv_ScannerState_t scannerState; - FwdLockConv_ScannerState_t savedScannerState; - off64_t numCharsConsumed; - char delimiter[MAX_DELIMITER_LENGTH]; - size_t delimiterLength; - size_t delimiterMatchPos; - FwdLockConv_String_t mimeHeaderName; - FwdLockConv_String_t contentType; - FwdLockConv_ContentTransferEncoding_t contentTransferEncoding; - unsigned char sessionKey[KEY_SIZE]; - void *pEncryptedSessionKey; - size_t encryptedSessionKeyLength; - AES_KEY encryptionRoundKeys; - HMAC_CTX signingContext; - unsigned char topHeader[TOP_HEADER_SIZE]; - unsigned char counter[AES_BLOCK_SIZE]; - unsigned char keyStream[AES_BLOCK_SIZE]; - int keyStreamIndex; - unsigned char ch; - size_t outputBufferSize; - size_t dataOffset; - size_t numDataBytes; -} FwdLockConv_Session_t; - -static FwdLockConv_Session_t *sessionPtrs[MAX_NUM_SESSIONS] = { NULL }; - -static pthread_mutex_t sessionAcquisitionMutex = PTHREAD_MUTEX_INITIALIZER; - -static const FwdLockConv_String_t nullString = { NULL, 0, 0, STRING_LENGTH_INCREMENT }; - -static const unsigned char topHeaderTemplate[] = - { 'F', 'W', 'L', 'K', FWD_LOCK_VERSION, FWD_LOCK_SUBFORMAT, USAGE_RESTRICTION_FLAGS }; - -static const char strContent[] = "content-"; -static const char strType[] = "type"; -static const char strTransferEncoding[] = "transfer-encoding"; -static const char strTextPlain[] = "text/plain"; -static const char strApplicationVndOmaDrmRightsXml[] = "application/vnd.oma.drm.rights+xml"; -static const char strApplicationVndOmaDrmContent[] = "application/vnd.oma.drm.content"; - -static const size_t strlenContent = sizeof strContent - 1; -static const size_t strlenTextPlain = sizeof strTextPlain - 1; - -static const signed char base64Values[] = { - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63, - 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -2, -1, -1, - -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, - 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, - -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, - 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51 -}; - -/** - * Acquires an unused converter session. - * - * @return A session ID. - */ -static int FwdLockConv_AcquireSession() { - int sessionId = -1; - int i; - pthread_mutex_lock(&sessionAcquisitionMutex); - for (i = 0; i < MAX_NUM_SESSIONS; ++i) { - if (sessionPtrs[i] == NULL) { - sessionPtrs[i] = malloc(sizeof *sessionPtrs[i]); - if (sessionPtrs[i] != NULL) { - sessionId = i; - } - break; - } - } - pthread_mutex_unlock(&sessionAcquisitionMutex); - return sessionId; -} - -/** - * Checks whether a session ID is in range and currently in use. - * - * @param[in] sessionID A session ID. - * - * @return A Boolean value indicating whether the session ID is in range and currently in use. - */ -static int FwdLockConv_IsValidSession(int sessionId) { - return 0 <= sessionId && sessionId < MAX_NUM_SESSIONS && sessionPtrs[sessionId] != NULL; -} - -/** - * Releases a converter session. - * - * @param[in] sessionID A session ID. - */ -static void FwdLockConv_ReleaseSession(int sessionId) { - pthread_mutex_lock(&sessionAcquisitionMutex); - assert(FwdLockConv_IsValidSession(sessionId)); - memset(sessionPtrs[sessionId], 0, sizeof *sessionPtrs[sessionId]); // Zero out key data. - free(sessionPtrs[sessionId]); - sessionPtrs[sessionId] = NULL; - pthread_mutex_unlock(&sessionAcquisitionMutex); -} - -/** - * Derives cryptographically independent keys for encryption and signing from the session key. - * - * @param[in,out] pSession A reference to a converter session. - * - * @return A status code. - */ -static int FwdLockConv_DeriveKeys(FwdLockConv_Session_t *pSession) { - FwdLockConv_Status_t status; - struct FwdLockConv_DeriveKeys_Data { - AES_KEY sessionRoundKeys; - unsigned char value[KEY_SIZE]; - unsigned char key[KEY_SIZE]; - } *pData = malloc(sizeof *pData); - if (pData == NULL) { - status = FwdLockConv_Status_OutOfMemory; - } else { - if (AES_set_encrypt_key(pSession->sessionKey, KEY_SIZE_IN_BITS, - &pData->sessionRoundKeys) != 0) { - status = FwdLockConv_Status_ProgramError; - } else { - // Encrypt the 16-byte value {0, 0, ..., 0} to produce the encryption key. - memset(pData->value, 0, KEY_SIZE); - AES_encrypt(pData->value, pData->key, &pData->sessionRoundKeys); - if (AES_set_encrypt_key(pData->key, KEY_SIZE_IN_BITS, - &pSession->encryptionRoundKeys) != 0) { - status = FwdLockConv_Status_ProgramError; - } else { - // Encrypt the 16-byte value {1, 0, ..., 0} to produce the signing key. - ++pData->value[0]; - AES_encrypt(pData->value, pData->key, &pData->sessionRoundKeys); - HMAC_CTX_init(&pSession->signingContext); - HMAC_Init_ex(&pSession->signingContext, pData->key, KEY_SIZE, EVP_sha1(), NULL); - status = FwdLockConv_Status_OK; - } - } - memset(pData, 0, sizeof pData); // Zero out key data. - free(pData); - } - return status; -} - -/** - * 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 == ' ' || ch == '%' || ch == '[' || ch == '&' || ch == '*' || ch == '^'; -} - -/** - * Checks whether a given character should be considered whitespace, using a narrower definition - * than the standard-library isspace() function. - * - * @param[in] ch The character to check. - * - * @return A Boolean value indicating whether the given character should be considered whitespace. - */ -static int FwdLockConv_IsWhitespace(int ch) { - return ch == ' ' || ch == '\t'; -} - -/** - * Removes trailing spaces from the delimiter. - * - * @param[in,out] pSession A reference to a converter session. - * - * @return A status code. - */ -static FwdLockConv_Status_t FwdLockConv_RightTrimDelimiter(FwdLockConv_Session_t *pSession) { - while (pSession->delimiterLength > 4 && - pSession->delimiter[pSession->delimiterLength - 1] == ' ') { - --pSession->delimiterLength; - } - if (pSession->delimiterLength > 4) { - return FwdLockConv_Status_OK; - } - return FwdLockConv_Status_SyntaxError; -} - -/** - * Matches the open delimiter. - * - * @param[in,out] pSession A reference to a converter session. - * @param[in] ch A character. - * - * @return A status code. - */ -static FwdLockConv_Status_t FwdLockConv_MatchOpenDelimiter(FwdLockConv_Session_t *pSession, - int ch) { - FwdLockConv_Status_t status = FwdLockConv_Status_OK; - switch (pSession->scannerState) { - case FwdLockConv_ScannerState_WantsFirstDash: - if (ch == '-') { - pSession->scannerState = FwdLockConv_ScannerState_WantsSecondDash; - } else if (ch == '\r') { - pSession->scannerState = FwdLockConv_ScannerState_WantsLF; - } else { - pSession->scannerState = FwdLockConv_ScannerState_WantsCR; - } - break; - case FwdLockConv_ScannerState_WantsSecondDash: - if (ch == '-') { - // The delimiter starts with "\r\n--" (the open delimiter may omit the initial "\r\n"). - // The rest is the user-defined boundary that should come next. - pSession->delimiter[0] = '\r'; - pSession->delimiter[1] = '\n'; - pSession->delimiter[2] = '-'; - pSession->delimiter[3] = '-'; - pSession->delimiterLength = 4; - pSession->scannerState = FwdLockConv_ScannerState_WantsBoundary; - } else if (ch == '\r') { - pSession->scannerState = FwdLockConv_ScannerState_WantsLF; - } else { - pSession->scannerState = FwdLockConv_ScannerState_WantsCR; - } - break; - case FwdLockConv_ScannerState_WantsCR: - if (ch == '\r') { - pSession->scannerState = FwdLockConv_ScannerState_WantsLF; - } - break; - case FwdLockConv_ScannerState_WantsLF: - if (ch == '\n') { - pSession->scannerState = FwdLockConv_ScannerState_WantsFirstDash; - } else if (ch != '\r') { - pSession->scannerState = FwdLockConv_ScannerState_WantsCR; - } - break; - case FwdLockConv_ScannerState_WantsBoundary: - if (FwdLockConv_IsBoundaryChar(ch)) { - // The boundary may contain leading and internal spaces, so trailing spaces will also be - // matched here. These will be removed later. - if (pSession->delimiterLength < MAX_DELIMITER_LENGTH) { - pSession->delimiter[pSession->delimiterLength++] = ch; - } else if (ch != ' ') { - status = FwdLockConv_Status_SyntaxError; - } - } else if (ch == '\r') { - status = FwdLockConv_RightTrimDelimiter(pSession); - if (status == FwdLockConv_Status_OK) { - pSession->scannerState = FwdLockConv_ScannerState_WantsBoundaryEnd; - } - } else if (ch == '\t') { - status = FwdLockConv_RightTrimDelimiter(pSession); - if (status == FwdLockConv_Status_OK) { - pSession->scannerState = FwdLockConv_ScannerState_WantsWhitespace; - } - } else { - status = FwdLockConv_Status_SyntaxError; - } - break; - case FwdLockConv_ScannerState_WantsWhitespace: - if (ch == '\r') { - pSession->scannerState = FwdLockConv_ScannerState_WantsBoundaryEnd; - } else if (!FwdLockConv_IsWhitespace(ch)) { - status = FwdLockConv_Status_SyntaxError; - } - break; - case FwdLockConv_ScannerState_WantsBoundaryEnd: - if (ch == '\n') { - pSession->parserState = FwdLockConv_ParserState_WantsMimeHeaders; - pSession->scannerState = FwdLockConv_ScannerState_WantsMimeHeaderNameStart; - } else { - status = FwdLockConv_Status_SyntaxError; - } - break; - default: - status = FwdLockConv_Status_ProgramError; - break; - } - return status; -} - -/** - * Checks whether a given character is valid in a MIME header name. - * - * @param[in] ch The character to check. - * - * @return A Boolean value indicating whether the given character is valid in a MIME header name. - */ -static int FwdLockConv_IsMimeHeaderNameChar(int ch) { - return isgraph(ch) && ch != ':'; -} - -/** - * Checks whether a given character is valid in a MIME header value. - * - * @param[in] ch The character to check. - * - * @return A Boolean value indicating whether the given character is valid in a MIME header value. - */ -static int FwdLockConv_IsMimeHeaderValueChar(int ch) { - return isgraph(ch) && ch != ';'; -} - -/** - * Appends a character to the specified dynamically growing string. - * - * @param[in,out] pString A reference to a dynamically growing string. - * @param[in] ch The character to append. - * - * @return A status code. - */ -static FwdLockConv_Status_t FwdLockConv_StringAppend(FwdLockConv_String_t *pString, int ch) { - if (pString->length == pString->maxLength) { - size_t newMaxLength = pString->maxLength + pString->lengthIncrement; - char *newPtr = realloc(pString->ptr, newMaxLength + 1); - if (newPtr == NULL) { - return FwdLockConv_Status_OutOfMemory; - } - pString->ptr = newPtr; - pString->maxLength = newMaxLength; - } - pString->ptr[pString->length++] = ch; - pString->ptr[pString->length] = '\0'; - return FwdLockConv_Status_OK; -} - -/** - * Attempts to recognize the MIME header name and changes the scanner state accordingly. - * - * @param[in,out] pSession A reference to a converter session. - * - * @return A status code. - */ -static FwdLockConv_Status_t FwdLockConv_RecognizeMimeHeaderName(FwdLockConv_Session_t *pSession) { - FwdLockConv_Status_t status = FwdLockConv_Status_OK; - if (strncmp(pSession->mimeHeaderName.ptr, strContent, strlenContent) == 0) { - if (strcmp(pSession->mimeHeaderName.ptr + strlenContent, strType) == 0) { - if (pSession->contentType.ptr == NULL) { - pSession->scannerState = FwdLockConv_ScannerState_WantsContentTypeStart; - } else { - status = FwdLockConv_Status_SyntaxError; - } - } else if (strcmp(pSession->mimeHeaderName.ptr + strlenContent, strTransferEncoding) == 0) { - if (pSession->contentTransferEncoding == - FwdLockConv_ContentTransferEncoding_Undefined) { - pSession->scannerState = FwdLockConv_ScannerState_WantsContentTransferEncodingStart; - } else { - status = FwdLockConv_Status_SyntaxError; - } - } else { - pSession->scannerState = FwdLockConv_ScannerState_WantsCR; - } - } else { - pSession->scannerState = FwdLockConv_ScannerState_WantsCR; - } - return status; -} - -/** - * Applies defaults to missing MIME header values. - * - * @param[in,out] pSession A reference to a converter session. - * - * @return A status code. - */ -static FwdLockConv_Status_t FwdLockConv_ApplyDefaults(FwdLockConv_Session_t *pSession) { - if (pSession->contentType.ptr == NULL) { - // Content type is missing: default to "text/plain". - pSession->contentType.ptr = malloc(sizeof strTextPlain); - if (pSession->contentType.ptr == NULL) { - return FwdLockConv_Status_OutOfMemory; - } - memcpy(pSession->contentType.ptr, strTextPlain, sizeof strTextPlain); - pSession->contentType.length = strlenTextPlain; - pSession->contentType.maxLength = strlenTextPlain; - } - if (pSession->contentTransferEncoding == FwdLockConv_ContentTransferEncoding_Undefined) { - // Content transfer encoding is missing: default to binary. - pSession->contentTransferEncoding = FwdLockConv_ContentTransferEncoding_Binary; - } - return FwdLockConv_Status_OK; -} - -/** - * Verifies that the content type is supported. - * - * @param[in,out] pSession A reference to a converter session. - * - * @return A status code. - */ -static FwdLockConv_Status_t FwdLockConv_VerifyContentType(FwdLockConv_Session_t *pSession) { - FwdLockConv_Status_t status; - if (pSession->contentType.ptr == NULL) { - status = FwdLockConv_Status_ProgramError; - } else if (strcmp(pSession->contentType.ptr, strApplicationVndOmaDrmRightsXml) == 0 || - strcmp(pSession->contentType.ptr, strApplicationVndOmaDrmContent) == 0) { - status = FwdLockConv_Status_UnsupportedFileFormat; - } else { - status = FwdLockConv_Status_OK; - } - return status; -} - -/** - * Writes the header of the output file. - * - * @param[in,out] pSession A reference to a converter session. - * @param[out] pOutput The output from the conversion process. - * - * @return A status code. - */ -static FwdLockConv_Status_t FwdLockConv_WriteHeader(FwdLockConv_Session_t *pSession, - FwdLockConv_Output_t *pOutput) { - FwdLockConv_Status_t status; - if (pSession->contentType.length > UCHAR_MAX) { - status = FwdLockConv_Status_SyntaxError; - } else { - pSession->outputBufferSize = OUTPUT_BUFFER_SIZE_INCREMENT; - pOutput->fromConvertData.pBuffer = malloc(pSession->outputBufferSize); - if (pOutput->fromConvertData.pBuffer == NULL) { - status = FwdLockConv_Status_OutOfMemory; - } else { - size_t encryptedSessionKeyPos = TOP_HEADER_SIZE + pSession->contentType.length; - size_t dataSignaturePos = encryptedSessionKeyPos + pSession->encryptedSessionKeyLength; - size_t headerSignaturePos = dataSignaturePos + SHA1_HASH_SIZE; - pSession->dataOffset = headerSignaturePos + SHA1_HASH_SIZE; - memcpy(pSession->topHeader, topHeaderTemplate, sizeof topHeaderTemplate); - pSession->topHeader[CONTENT_TYPE_LENGTH_POS] = - (unsigned char)pSession->contentType.length; - memcpy(pOutput->fromConvertData.pBuffer, pSession->topHeader, TOP_HEADER_SIZE); - memcpy((char *)pOutput->fromConvertData.pBuffer + TOP_HEADER_SIZE, - pSession->contentType.ptr, pSession->contentType.length); - memcpy((char *)pOutput->fromConvertData.pBuffer + encryptedSessionKeyPos, - pSession->pEncryptedSessionKey, pSession->encryptedSessionKeyLength); - - // Set the signatures to all zeros for now; they will have to be updated later. - memset((char *)pOutput->fromConvertData.pBuffer + dataSignaturePos, 0, - SHA1_HASH_SIZE); - memset((char *)pOutput->fromConvertData.pBuffer + headerSignaturePos, 0, - SHA1_HASH_SIZE); - - pOutput->fromConvertData.numBytes = pSession->dataOffset; - status = FwdLockConv_Status_OK; - } - } - return status; -} - -/** - * Matches the MIME headers. - * - * @param[in,out] pSession A reference to a converter session. - * @param[in] ch A character. - * @param[out] pOutput The output from the conversion process. - * - * @return A status code. - */ -static FwdLockConv_Status_t FwdLockConv_MatchMimeHeaders(FwdLockConv_Session_t *pSession, - int ch, - FwdLockConv_Output_t *pOutput) { - FwdLockConv_Status_t status = FwdLockConv_Status_OK; - switch (pSession->scannerState) { - case FwdLockConv_ScannerState_WantsMimeHeaderNameStart: - if (FwdLockConv_IsMimeHeaderNameChar(ch)) { - pSession->mimeHeaderName.length = 0; - status = FwdLockConv_StringAppend(&pSession->mimeHeaderName, tolower(ch)); - if (status == FwdLockConv_Status_OK) { - pSession->scannerState = FwdLockConv_ScannerState_WantsMimeHeaderName; - } - } else if (ch == '\r') { - pSession->scannerState = FwdLockConv_ScannerState_WantsMimeHeadersEnd; - } else if (!FwdLockConv_IsWhitespace(ch)) { - status = FwdLockConv_Status_SyntaxError; - } - break; - case FwdLockConv_ScannerState_WantsMimeHeaderName: - if (FwdLockConv_IsMimeHeaderNameChar(ch)) { - status = FwdLockConv_StringAppend(&pSession->mimeHeaderName, tolower(ch)); - } else if (ch == ':') { - status = FwdLockConv_RecognizeMimeHeaderName(pSession); - } else if (FwdLockConv_IsWhitespace(ch)) { - pSession->scannerState = FwdLockConv_ScannerState_WantsMimeHeaderNameEnd; - } else { - status = FwdLockConv_Status_SyntaxError; - } - break; - case FwdLockConv_ScannerState_WantsMimeHeaderNameEnd: - if (ch == ':') { - status = FwdLockConv_RecognizeMimeHeaderName(pSession); - } else if (!FwdLockConv_IsWhitespace(ch)) { - status = FwdLockConv_Status_SyntaxError; - } - break; - case FwdLockConv_ScannerState_WantsContentTypeStart: - if (FwdLockConv_IsMimeHeaderValueChar(ch)) { - status = FwdLockConv_StringAppend(&pSession->contentType, tolower(ch)); - if (status == FwdLockConv_Status_OK) { - pSession->scannerState = FwdLockConv_ScannerState_WantsContentType; - } - } else if (!FwdLockConv_IsWhitespace(ch)) { - status = FwdLockConv_Status_SyntaxError; - } - break; - case FwdLockConv_ScannerState_WantsContentType: - if (FwdLockConv_IsMimeHeaderValueChar(ch)) { - status = FwdLockConv_StringAppend(&pSession->contentType, tolower(ch)); - } else if (ch == ';') { - pSession->scannerState = FwdLockConv_ScannerState_WantsCR; - } else if (ch == '\r') { - pSession->scannerState = FwdLockConv_ScannerState_WantsLF; - } else if (FwdLockConv_IsWhitespace(ch)) { - pSession->scannerState = FwdLockConv_ScannerState_WantsMimeHeaderValueEnd; - } else { - status = FwdLockConv_Status_SyntaxError; - } - break; - case FwdLockConv_ScannerState_WantsContentTransferEncodingStart: - if (ch == 'b' || ch == 'B') { - pSession->scannerState = FwdLockConv_ScannerState_Wants_A_OR_I; - } else if (ch == '7' || ch == '8') { - pSession->scannerState = FwdLockConv_ScannerState_Wants_B; - } else if (!FwdLockConv_IsWhitespace(ch)) { - status = FwdLockConv_Status_UnsupportedContentTransferEncoding; - } - break; - case FwdLockConv_ScannerState_Wants_A_OR_I: - if (ch == 'i' || ch == 'I') { - pSession->scannerState = FwdLockConv_ScannerState_Wants_N; - } else if (ch == 'a' || ch == 'A') { - pSession->scannerState = FwdLockConv_ScannerState_Wants_S; - } else { - status = FwdLockConv_Status_UnsupportedContentTransferEncoding; - } - break; - case FwdLockConv_ScannerState_Wants_N: - if (ch == 'n' || ch == 'N') { - pSession->scannerState = FwdLockConv_ScannerState_Wants_A; - } else { - status = FwdLockConv_Status_UnsupportedContentTransferEncoding; - } - break; - case FwdLockConv_ScannerState_Wants_A: - if (ch == 'a' || ch == 'A') { - pSession->scannerState = FwdLockConv_ScannerState_Wants_R; - } else { - status = FwdLockConv_Status_UnsupportedContentTransferEncoding; - } - break; - case FwdLockConv_ScannerState_Wants_R: - if (ch == 'r' || ch == 'R') { - pSession->scannerState = FwdLockConv_ScannerState_Wants_Y; - } else { - status = FwdLockConv_Status_UnsupportedContentTransferEncoding; - } - break; - case FwdLockConv_ScannerState_Wants_Y: - if (ch == 'y' || ch == 'Y') { - pSession->contentTransferEncoding = FwdLockConv_ContentTransferEncoding_Binary; - pSession->scannerState = FwdLockConv_ScannerState_WantsContentTransferEncodingEnd; - } else { - status = FwdLockConv_Status_UnsupportedContentTransferEncoding; - } - break; - case FwdLockConv_ScannerState_Wants_S: - if (ch == 's' || ch == 'S') { - pSession->scannerState = FwdLockConv_ScannerState_Wants_E; - } else { - status = FwdLockConv_Status_UnsupportedContentTransferEncoding; - } - break; - case FwdLockConv_ScannerState_Wants_E: - if (ch == 'e' || ch == 'E') { - pSession->scannerState = FwdLockConv_ScannerState_Wants_6; - } else { - status = FwdLockConv_Status_UnsupportedContentTransferEncoding; - } - break; - case FwdLockConv_ScannerState_Wants_6: - if (ch == '6') { - pSession->scannerState = FwdLockConv_ScannerState_Wants_4; - } else { - status = FwdLockConv_Status_UnsupportedContentTransferEncoding; - } - break; - case FwdLockConv_ScannerState_Wants_4: - if (ch == '4') { - pSession->contentTransferEncoding = FwdLockConv_ContentTransferEncoding_Base64; - pSession->scannerState = FwdLockConv_ScannerState_WantsContentTransferEncodingEnd; - } else { - status = FwdLockConv_Status_UnsupportedContentTransferEncoding; - } - break; - case FwdLockConv_ScannerState_Wants_B: - if (ch == 'b' || ch == 'B') { - pSession->scannerState = FwdLockConv_ScannerState_Wants_I; - } else { - status = FwdLockConv_Status_UnsupportedContentTransferEncoding; - } - break; - case FwdLockConv_ScannerState_Wants_I: - if (ch == 'i' || ch == 'I') { - pSession->scannerState = FwdLockConv_ScannerState_Wants_T; - } else { - status = FwdLockConv_Status_UnsupportedContentTransferEncoding; - } - break; - case FwdLockConv_ScannerState_Wants_T: - if (ch == 't' || ch == 'T') { - pSession->contentTransferEncoding = FwdLockConv_ContentTransferEncoding_Binary; - pSession->scannerState = FwdLockConv_ScannerState_WantsContentTransferEncodingEnd; - } else { - status = FwdLockConv_Status_UnsupportedContentTransferEncoding; - } - break; - case FwdLockConv_ScannerState_WantsContentTransferEncodingEnd: - if (ch == ';') { - pSession->scannerState = FwdLockConv_ScannerState_WantsCR; - } else if (ch == '\r') { - pSession->scannerState = FwdLockConv_ScannerState_WantsLF; - } else if (FwdLockConv_IsWhitespace(ch)) { - pSession->scannerState = FwdLockConv_ScannerState_WantsMimeHeaderValueEnd; - } else { - status = FwdLockConv_Status_UnsupportedContentTransferEncoding; - } - break; - case FwdLockConv_ScannerState_WantsMimeHeaderValueEnd: - if (ch == ';') { - pSession->scannerState = FwdLockConv_ScannerState_WantsCR; - } else if (ch == '\r') { - pSession->scannerState = FwdLockConv_ScannerState_WantsLF; - } else if (!FwdLockConv_IsWhitespace(ch)) { - status = FwdLockConv_Status_SyntaxError; - } - break; - case FwdLockConv_ScannerState_WantsCR: - if (ch == '\r') { - pSession->scannerState = FwdLockConv_ScannerState_WantsLF; - } - break; - case FwdLockConv_ScannerState_WantsLF: - if (ch == '\n') { - pSession->scannerState = FwdLockConv_ScannerState_WantsMimeHeaderNameStart; - } else { - status = FwdLockConv_Status_SyntaxError; - } - break; - case FwdLockConv_ScannerState_WantsMimeHeadersEnd: - if (ch == '\n') { - status = FwdLockConv_ApplyDefaults(pSession); - if (status == FwdLockConv_Status_OK) { - status = FwdLockConv_VerifyContentType(pSession); - } - if (status == FwdLockConv_Status_OK) { - status = FwdLockConv_WriteHeader(pSession, pOutput); - } - if (status == FwdLockConv_Status_OK) { - if (pSession->contentTransferEncoding == - FwdLockConv_ContentTransferEncoding_Binary) { - pSession->parserState = FwdLockConv_ParserState_WantsBinaryEncodedData; - } else { - pSession->parserState = FwdLockConv_ParserState_WantsBase64EncodedData; - } - pSession->scannerState = FwdLockConv_ScannerState_WantsByte1; - } - } else { - status = FwdLockConv_Status_SyntaxError; - } - break; - default: - status = FwdLockConv_Status_ProgramError; - break; - } - return status; -} - -/** - * Increments the counter, treated as a 16-byte little-endian number, by one. - * - * @param[in,out] pSession A reference to a converter session. - */ -static void FwdLockConv_IncrementCounter(FwdLockConv_Session_t *pSession) { - size_t i = 0; - while ((++pSession->counter[i] == 0) && (++i < AES_BLOCK_SIZE)) - ; -} - -/** - * Encrypts the given character and writes it to the output buffer. - * - * @param[in,out] pSession A reference to a converter session. - * @param[in] ch The character to encrypt and write. - * @param[in,out] pOutput The output from the conversion process. - * - * @return A status code. - */ -static FwdLockConv_Status_t FwdLockConv_WriteEncryptedChar(FwdLockConv_Session_t *pSession, - unsigned char ch, - FwdLockConv_Output_t *pOutput) { - if (pOutput->fromConvertData.numBytes == pSession->outputBufferSize) { - void *pBuffer; - pSession->outputBufferSize += OUTPUT_BUFFER_SIZE_INCREMENT; - pBuffer = realloc(pOutput->fromConvertData.pBuffer, pSession->outputBufferSize); - if (pBuffer == NULL) { - return FwdLockConv_Status_OutOfMemory; - } - pOutput->fromConvertData.pBuffer = pBuffer; - } - if (++pSession->keyStreamIndex == AES_BLOCK_SIZE) { - FwdLockConv_IncrementCounter(pSession); - pSession->keyStreamIndex = 0; - } - if (pSession->keyStreamIndex == 0) { - AES_encrypt(pSession->counter, pSession->keyStream, &pSession->encryptionRoundKeys); - } - ch ^= pSession->keyStream[pSession->keyStreamIndex]; - ((unsigned char *)pOutput->fromConvertData.pBuffer)[pOutput->fromConvertData.numBytes++] = ch; - ++pSession->numDataBytes; - return FwdLockConv_Status_OK; -} - -/** - * Matches binary-encoded content data and encrypts it, while looking out for the close delimiter. - * - * @param[in,out] pSession A reference to a converter session. - * @param[in] ch A character. - * @param[in,out] pOutput The output from the conversion process. - * - * @return A status code. - */ -static FwdLockConv_Status_t FwdLockConv_MatchBinaryEncodedData(FwdLockConv_Session_t *pSession, - int ch, - FwdLockConv_Output_t *pOutput) { - FwdLockConv_Status_t status = FwdLockConv_Status_OK; - switch (pSession->scannerState) { - case FwdLockConv_ScannerState_WantsByte1: - if (ch != pSession->delimiter[pSession->delimiterMatchPos]) { - // The partial match of the delimiter turned out to be spurious. Flush the matched bytes - // to the output buffer and start over. - size_t i; - for (i = 0; i < pSession->delimiterMatchPos; ++i) { - status = FwdLockConv_WriteEncryptedChar(pSession, pSession->delimiter[i], pOutput); - if (status != FwdLockConv_Status_OK) { - return status; - } - } - pSession->delimiterMatchPos = 0; - } - if (ch != pSession->delimiter[pSession->delimiterMatchPos]) { - // The current character isn't part of the delimiter. Write it to the output buffer. - status = FwdLockConv_WriteEncryptedChar(pSession, ch, pOutput); - } else if (++pSession->delimiterMatchPos == pSession->delimiterLength) { - // The entire delimiter has been matched. The only valid characters now are the "--" - // that complete the close delimiter (no more message parts are expected). - pSession->scannerState = FwdLockConv_ScannerState_WantsFirstDash; - } - break; - case FwdLockConv_ScannerState_WantsFirstDash: - if (ch == '-') { - pSession->scannerState = FwdLockConv_ScannerState_WantsSecondDash; - } else { - status = FwdLockConv_Status_SyntaxError; - } - break; - case FwdLockConv_ScannerState_WantsSecondDash: - if (ch == '-') { - pSession->parserState = FwdLockConv_ParserState_Done; - } else { - status = FwdLockConv_Status_SyntaxError; - } - break; - default: - status = FwdLockConv_Status_ProgramError; - break; - } - return status; -} - -/** - * Checks whether a given character is valid in base64-encoded data. - * - * @param[in] ch The character to check. - * - * @return A Boolean value indicating whether the given character is valid in base64-encoded data. - */ -static int FwdLockConv_IsBase64Char(int ch) { - return 0 <= ch && ch <= 'z' && base64Values[ch] >= 0; -} - -/** - * Matches base64-encoded content data and encrypts it, while looking out for the close delimiter. - * - * @param[in,out] pSession A reference to a converter session. - * @param[in] ch A character. - * @param[in,out] pOutput The output from the conversion process. - * - * @return A status code. - */ -static FwdLockConv_Status_t FwdLockConv_MatchBase64EncodedData(FwdLockConv_Session_t *pSession, - int ch, - FwdLockConv_Output_t *pOutput) { - FwdLockConv_Status_t status = FwdLockConv_Status_OK; - switch (pSession->scannerState) { - case FwdLockConv_ScannerState_WantsByte1: - case FwdLockConv_ScannerState_WantsByte1_AfterCRLF: - if (FwdLockConv_IsBase64Char(ch)) { - pSession->ch = base64Values[ch] << 2; - pSession->scannerState = FwdLockConv_ScannerState_WantsByte2; - } else if (ch == '\r') { - pSession->savedScannerState = FwdLockConv_ScannerState_WantsByte1_AfterCRLF; - pSession->scannerState = FwdLockConv_ScannerState_WantsLF; - } else if (ch == '-') { - if (pSession->scannerState == FwdLockConv_ScannerState_WantsByte1_AfterCRLF) { - pSession->delimiterMatchPos = 3; - pSession->scannerState = FwdLockConv_ScannerState_WantsDelimiter; - } else { - status = FwdLockConv_Status_SyntaxError; - } - } else if (!FwdLockConv_IsWhitespace(ch)) { - status = FwdLockConv_Status_SyntaxError; - } - break; - case FwdLockConv_ScannerState_WantsByte2: - if (FwdLockConv_IsBase64Char(ch)) { - pSession->ch |= base64Values[ch] >> 4; - status = FwdLockConv_WriteEncryptedChar(pSession, pSession->ch, pOutput); - if (status == FwdLockConv_Status_OK) { - pSession->ch = base64Values[ch] << 4; - pSession->scannerState = FwdLockConv_ScannerState_WantsByte3; - } - } else if (ch == '\r') { - pSession->savedScannerState = pSession->scannerState; - pSession->scannerState = FwdLockConv_ScannerState_WantsLF; - } else if (!FwdLockConv_IsWhitespace(ch)) { - status = FwdLockConv_Status_SyntaxError; - } - break; - case FwdLockConv_ScannerState_WantsByte3: - if (FwdLockConv_IsBase64Char(ch)) { - pSession->ch |= base64Values[ch] >> 2; - status = FwdLockConv_WriteEncryptedChar(pSession, pSession->ch, pOutput); - if (status == FwdLockConv_Status_OK) { - pSession->ch = base64Values[ch] << 6; - pSession->scannerState = FwdLockConv_ScannerState_WantsByte4; - } - } else if (ch == '\r') { - pSession->savedScannerState = pSession->scannerState; - pSession->scannerState = FwdLockConv_ScannerState_WantsLF; - } else if (ch == '=') { - pSession->scannerState = FwdLockConv_ScannerState_WantsPadding; - } else if (!FwdLockConv_IsWhitespace(ch)) { - status = FwdLockConv_Status_SyntaxError; - } - break; - case FwdLockConv_ScannerState_WantsByte4: - if (FwdLockConv_IsBase64Char(ch)) { - pSession->ch |= base64Values[ch]; - status = FwdLockConv_WriteEncryptedChar(pSession, pSession->ch, pOutput); - if (status == FwdLockConv_Status_OK) { - pSession->scannerState = FwdLockConv_ScannerState_WantsByte1; - } - } else if (ch == '\r') { - pSession->savedScannerState = pSession->scannerState; - pSession->scannerState = FwdLockConv_ScannerState_WantsLF; - } else if (ch == '=') { - pSession->scannerState = FwdLockConv_ScannerState_WantsWhitespace; - } else if (!FwdLockConv_IsWhitespace(ch)) { - status = FwdLockConv_Status_SyntaxError; - } - break; - case FwdLockConv_ScannerState_WantsLF: - if (ch == '\n') { - pSession->scannerState = pSession->savedScannerState; - } else { - status = FwdLockConv_Status_SyntaxError; - } - break; - case FwdLockConv_ScannerState_WantsPadding: - if (ch == '=') { - pSession->scannerState = FwdLockConv_ScannerState_WantsWhitespace; - } else { - status = FwdLockConv_Status_SyntaxError; - } - break; - case FwdLockConv_ScannerState_WantsWhitespace: - case FwdLockConv_ScannerState_WantsWhitespace_AfterCRLF: - if (ch == '\r') { - pSession->savedScannerState = FwdLockConv_ScannerState_WantsWhitespace_AfterCRLF; - pSession->scannerState = FwdLockConv_ScannerState_WantsLF; - } else if (ch == '-') { - if (pSession->scannerState == FwdLockConv_ScannerState_WantsWhitespace_AfterCRLF) { - pSession->delimiterMatchPos = 3; - pSession->scannerState = FwdLockConv_ScannerState_WantsDelimiter; - } else { - status = FwdLockConv_Status_SyntaxError; - } - } else if (FwdLockConv_IsWhitespace(ch)) { - pSession->scannerState = FwdLockConv_ScannerState_WantsWhitespace; - } else { - status = FwdLockConv_Status_SyntaxError; - } - break; - case FwdLockConv_ScannerState_WantsDelimiter: - if (ch != pSession->delimiter[pSession->delimiterMatchPos]) { - status = FwdLockConv_Status_SyntaxError; - } else if (++pSession->delimiterMatchPos == pSession->delimiterLength) { - pSession->scannerState = FwdLockConv_ScannerState_WantsFirstDash; - } - break; - case FwdLockConv_ScannerState_WantsFirstDash: - if (ch == '-') { - pSession->scannerState = FwdLockConv_ScannerState_WantsSecondDash; - } else { - status = FwdLockConv_Status_SyntaxError; - } - break; - case FwdLockConv_ScannerState_WantsSecondDash: - if (ch == '-') { - pSession->parserState = FwdLockConv_ParserState_Done; - } else { - status = FwdLockConv_Status_SyntaxError; - } - break; - default: - status = FwdLockConv_Status_ProgramError; - break; - } - return status; -} - -/** - * Pushes a single character into the converter's state machine. - * - * @param[in,out] pSession A reference to a converter session. - * @param[in] ch A character. - * @param[in,out] pOutput The output from the conversion process. - * - * @return A status code. - */ -static FwdLockConv_Status_t FwdLockConv_PushChar(FwdLockConv_Session_t *pSession, - int ch, - FwdLockConv_Output_t *pOutput) { - FwdLockConv_Status_t status; - ++pSession->numCharsConsumed; - switch (pSession->parserState) { - case FwdLockConv_ParserState_WantsOpenDelimiter: - status = FwdLockConv_MatchOpenDelimiter(pSession, ch); - break; - case FwdLockConv_ParserState_WantsMimeHeaders: - status = FwdLockConv_MatchMimeHeaders(pSession, ch, pOutput); - break; - case FwdLockConv_ParserState_WantsBinaryEncodedData: - 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: - status = FwdLockConv_Status_OK; - break; - default: - status = FwdLockConv_Status_ProgramError; - break; - } - return status; -} - -FwdLockConv_Status_t FwdLockConv_OpenSession(int *pSessionId, FwdLockConv_Output_t *pOutput) { - FwdLockConv_Status_t status; - if (pSessionId == NULL || pOutput == NULL) { - status = FwdLockConv_Status_InvalidArgument; - } else { - *pSessionId = FwdLockConv_AcquireSession(); - if (*pSessionId < 0) { - status = FwdLockConv_Status_TooManySessions; - } else { - FwdLockConv_Session_t *pSession = sessionPtrs[*pSessionId]; - pSession->encryptedSessionKeyLength = FwdLockGlue_GetEncryptedKeyLength(KEY_SIZE); - if (pSession->encryptedSessionKeyLength < AES_BLOCK_SIZE) { - // The encrypted session key is used as the CTR-mode nonce, so it must be at least - // the size of a single AES block. - status = FwdLockConv_Status_ProgramError; - } else { - pSession->pEncryptedSessionKey = malloc(pSession->encryptedSessionKeyLength); - if (pSession->pEncryptedSessionKey == NULL) { - status = FwdLockConv_Status_OutOfMemory; - } else { - if (!FwdLockGlue_GetRandomNumber(pSession->sessionKey, KEY_SIZE)) { - status = FwdLockConv_Status_RandomNumberGenerationFailed; - } else if (!FwdLockGlue_EncryptKey(pSession->sessionKey, KEY_SIZE, - pSession->pEncryptedSessionKey, - pSession->encryptedSessionKeyLength)) { - status = FwdLockConv_Status_KeyEncryptionFailed; - } else { - status = FwdLockConv_DeriveKeys(pSession); - } - if (status == FwdLockConv_Status_OK) { - memset(pSession->sessionKey, 0, KEY_SIZE); // Zero out key data. - memcpy(pSession->counter, pSession->pEncryptedSessionKey, AES_BLOCK_SIZE); - pSession->parserState = FwdLockConv_ParserState_WantsOpenDelimiter; - pSession->scannerState = FwdLockConv_ScannerState_WantsFirstDash; - pSession->numCharsConsumed = 0; - pSession->delimiterMatchPos = 0; - pSession->mimeHeaderName = nullString; - pSession->contentType = nullString; - pSession->contentTransferEncoding = - FwdLockConv_ContentTransferEncoding_Undefined; - pSession->keyStreamIndex = -1; - pOutput->fromConvertData.pBuffer = NULL; - pOutput->fromConvertData.errorPos = INVALID_OFFSET; - } else { - free(pSession->pEncryptedSessionKey); - } - } - } - if (status != FwdLockConv_Status_OK) { - FwdLockConv_ReleaseSession(*pSessionId); - *pSessionId = -1; - } - } - } - return status; -} - -FwdLockConv_Status_t FwdLockConv_ConvertData(int sessionId, - const void *pBuffer, - size_t numBytes, - FwdLockConv_Output_t *pOutput) { - FwdLockConv_Status_t status; - if (!FwdLockConv_IsValidSession(sessionId) || pBuffer == NULL || pOutput == NULL) { - status = FwdLockConv_Status_InvalidArgument; - } else { - size_t i; - FwdLockConv_Session_t *pSession = sessionPtrs[sessionId]; - pSession->dataOffset = 0; - pSession->numDataBytes = 0; - pOutput->fromConvertData.numBytes = 0; - status = FwdLockConv_Status_OK; - - for (i = 0; i < numBytes; ++i) { - status = FwdLockConv_PushChar(pSession, ((char *)pBuffer)[i], pOutput); - if (status != FwdLockConv_Status_OK) { - break; - } - } - if (status == FwdLockConv_Status_OK) { - // Update the data signature. - HMAC_Update(&pSession->signingContext, - &((unsigned char *)pOutput->fromConvertData.pBuffer)[pSession->dataOffset], - pSession->numDataBytes); - } else if (status == FwdLockConv_Status_SyntaxError) { - pOutput->fromConvertData.errorPos = pSession->numCharsConsumed; - } - } - return status; -} - -FwdLockConv_Status_t FwdLockConv_CloseSession(int sessionId, FwdLockConv_Output_t *pOutput) { - FwdLockConv_Status_t status; - if (!FwdLockConv_IsValidSession(sessionId) || pOutput == NULL) { - status = FwdLockConv_Status_InvalidArgument; - } else { - FwdLockConv_Session_t *pSession = sessionPtrs[sessionId]; - free(pOutput->fromConvertData.pBuffer); - if (pSession->parserState != FwdLockConv_ParserState_Done) { - pOutput->fromCloseSession.errorPos = pSession->numCharsConsumed; - status = FwdLockConv_Status_SyntaxError; - } else { - // Finalize the data signature. - unsigned int signatureSize = SHA1_HASH_SIZE; - HMAC_Final(&pSession->signingContext, pOutput->fromCloseSession.signatures, - &signatureSize); - if (signatureSize != SHA1_HASH_SIZE) { - status = FwdLockConv_Status_ProgramError; - } else { - // Calculate the header signature, which is a signature of the rest of the header - // including the data signature. - HMAC_Init_ex(&pSession->signingContext, NULL, KEY_SIZE, NULL, NULL); - HMAC_Update(&pSession->signingContext, pSession->topHeader, TOP_HEADER_SIZE); - HMAC_Update(&pSession->signingContext, (unsigned char *)pSession->contentType.ptr, - pSession->contentType.length); - HMAC_Update(&pSession->signingContext, pSession->pEncryptedSessionKey, - pSession->encryptedSessionKeyLength); - HMAC_Update(&pSession->signingContext, pOutput->fromCloseSession.signatures, - SHA1_HASH_SIZE); - HMAC_Final(&pSession->signingContext, - &pOutput->fromCloseSession.signatures[SHA1_HASH_SIZE], &signatureSize); - if (signatureSize != SHA1_HASH_SIZE) { - status = FwdLockConv_Status_ProgramError; - } else { - pOutput->fromCloseSession.fileOffset = TOP_HEADER_SIZE + - pSession->contentType.length + pSession->encryptedSessionKeyLength; - status = FwdLockConv_Status_OK; - } - } - pOutput->fromCloseSession.errorPos = INVALID_OFFSET; - } - free(pSession->mimeHeaderName.ptr); - free(pSession->contentType.ptr); - free(pSession->pEncryptedSessionKey); - HMAC_CTX_cleanup(&pSession->signingContext); - FwdLockConv_ReleaseSession(sessionId); - } - return status; -} - -FwdLockConv_Status_t FwdLockConv_ConvertOpenFile(int inputFileDesc, - FwdLockConv_ReadFunc_t *fpReadFunc, - int outputFileDesc, - FwdLockConv_WriteFunc_t *fpWriteFunc, - FwdLockConv_LSeekFunc_t *fpLSeekFunc, - off64_t *pErrorPos) { - FwdLockConv_Status_t status; - if (pErrorPos != NULL) { - *pErrorPos = INVALID_OFFSET; - } - if (fpReadFunc == NULL || fpWriteFunc == NULL || fpLSeekFunc == NULL || inputFileDesc < 0 || - outputFileDesc < 0) { - status = FwdLockConv_Status_InvalidArgument; - } else { - char *pReadBuffer = malloc(READ_BUFFER_SIZE); - if (pReadBuffer == NULL) { - status = FwdLockConv_Status_OutOfMemory; - } else { - int sessionId; - FwdLockConv_Output_t output; - status = FwdLockConv_OpenSession(&sessionId, &output); - if (status == FwdLockConv_Status_OK) { - ssize_t numBytesRead; - FwdLockConv_Status_t closeStatus; - while ((numBytesRead = - fpReadFunc(inputFileDesc, pReadBuffer, READ_BUFFER_SIZE)) > 0) { - status = FwdLockConv_ConvertData(sessionId, pReadBuffer, (size_t)numBytesRead, - &output); - if (status == FwdLockConv_Status_OK) { - if (output.fromConvertData.pBuffer != NULL && - output.fromConvertData.numBytes > 0) { - ssize_t numBytesWritten = fpWriteFunc(outputFileDesc, - output.fromConvertData.pBuffer, - output.fromConvertData.numBytes); - if (numBytesWritten != (ssize_t)output.fromConvertData.numBytes) { - status = FwdLockConv_Status_FileWriteError; - break; - } - } - } else { - if (status == FwdLockConv_Status_SyntaxError && pErrorPos != NULL) { - *pErrorPos = output.fromConvertData.errorPos; - } - break; - } - } // end while - if (numBytesRead < 0) { - status = FwdLockConv_Status_FileReadError; - } - closeStatus = FwdLockConv_CloseSession(sessionId, &output); - if (status == FwdLockConv_Status_OK) { - if (closeStatus != FwdLockConv_Status_OK) { - if (closeStatus == FwdLockConv_Status_SyntaxError && pErrorPos != NULL) { - *pErrorPos = output.fromCloseSession.errorPos; - } - status = closeStatus; - } else if (fpLSeekFunc(outputFileDesc, output.fromCloseSession.fileOffset, - SEEK_SET) < 0) { - status = FwdLockConv_Status_FileSeekError; - } else if (fpWriteFunc(outputFileDesc, output.fromCloseSession.signatures, - FWD_LOCK_SIGNATURES_SIZE) != FWD_LOCK_SIGNATURES_SIZE) { - status = FwdLockConv_Status_FileWriteError; - } - } - } - free(pReadBuffer); - } - } - return status; -} - -FwdLockConv_Status_t FwdLockConv_ConvertFile(const char *pInputFilename, - const char *pOutputFilename, - off64_t *pErrorPos) { - FwdLockConv_Status_t status; - if (pErrorPos != NULL) { - *pErrorPos = INVALID_OFFSET; - } - if (pInputFilename == NULL || pOutputFilename == NULL) { - status = FwdLockConv_Status_InvalidArgument; - } else { - int inputFileDesc = open(pInputFilename, O_RDONLY); - if (inputFileDesc < 0) { - status = FwdLockConv_Status_FileNotFound; - } else { - int outputFileDesc = open(pOutputFilename, O_CREAT | O_TRUNC | O_WRONLY, - S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); - if (outputFileDesc < 0) { - status = FwdLockConv_Status_FileCreationFailed; - } else { - status = FwdLockConv_ConvertOpenFile(inputFileDesc, read, outputFileDesc, write, - lseek64, pErrorPos); - if (close(outputFileDesc) == 0 && status != FwdLockConv_Status_OK) { - remove(pOutputFilename); - } - } - (void)close(inputFileDesc); - } - } - return status; -} diff --git a/drm/libdrmframework/plugins/forward-lock/internal-format/converter/FwdLockConv.h b/drm/libdrmframework/plugins/forward-lock/internal-format/converter/FwdLockConv.h deleted file mode 100644 index e20c0c3..0000000 --- a/drm/libdrmframework/plugins/forward-lock/internal-format/converter/FwdLockConv.h +++ /dev/null @@ -1,282 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef __FWDLOCKCONV_H__ -#define __FWDLOCKCONV_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -#include <sys/types.h> - -/** - * The size of the data and header signatures combined. The signatures are adjacent to each other in - * the produced output file. - */ -#define FWD_LOCK_SIGNATURES_SIZE (2 * 20) - -/** - * Data type for the output from FwdLockConv_ConvertData. - */ -typedef struct FwdLockConv_ConvertData_Output { - /// The converted data. - void *pBuffer; - - /// The size of the converted data. - size_t numBytes; - - /// The file position where the error occurred, in the case of a syntax error. - off64_t errorPos; -} FwdLockConv_ConvertData_Output_t; - -/** - * Data type for the output from FwdLockConv_CloseSession. - */ -typedef struct FwdLockConv_CloseSession_Output { - /// The final set of signatures. - unsigned char signatures[FWD_LOCK_SIGNATURES_SIZE]; - - /// The offset in the produced output file where the signatures are located. - off64_t fileOffset; - - /// The file position where the error occurred, in the case of a syntax error. - off64_t errorPos; -} FwdLockConv_CloseSession_Output_t; - -/** - * Data type for the output from the conversion process. - */ -typedef union FwdLockConv_Output { - FwdLockConv_ConvertData_Output_t fromConvertData; - FwdLockConv_CloseSession_Output_t fromCloseSession; -} FwdLockConv_Output_t; - -/** - * Data type for the Posix-style read function used by the converter in pull mode. - * - * @param[in] fileDesc The file descriptor of a file opened for reading. - * @param[out] pBuffer A reference to the buffer that should receive the read data. - * @param[in] numBytes The number of bytes to read. - * - * @return The number of bytes read. - * @retval -1 Failure. - */ -typedef ssize_t FwdLockConv_ReadFunc_t(int fileDesc, void *pBuffer, size_t numBytes); - -/** - * Data type for the Posix-style write function used by the converter in pull mode. - * - * @param[in] fileDesc The file descriptor of a file opened for writing. - * @param[in] pBuffer A reference to the buffer containing the data to be written. - * @param[in] numBytes The number of bytes to write. - * - * @return The number of bytes written. - * @retval -1 Failure. - */ -typedef ssize_t FwdLockConv_WriteFunc_t(int fileDesc, const void *pBuffer, size_t numBytes); - -/** - * Data type for the Posix-style lseek function used by the converter in pull mode. - * - * @param[in] fileDesc The file descriptor of a file opened for writing. - * @param[in] offset The offset with which to update the file position. - * @param[in] whence One of SEEK_SET, SEEK_CUR, and SEEK_END. - * - * @return The new file position. - * @retval ((off64_t)-1) Failure. - */ -typedef off64_t FwdLockConv_LSeekFunc_t(int fileDesc, off64_t offset, int whence); - -/** - * The status codes returned by the converter functions. - */ -typedef enum FwdLockConv_Status { - /// The operation was successful. - FwdLockConv_Status_OK = 0, - - /// An actual argument to the function is invalid (a program error on the caller's part). - FwdLockConv_Status_InvalidArgument = 1, - - /// There is not enough free dynamic memory to complete the operation. - FwdLockConv_Status_OutOfMemory = 2, - - /// An error occurred while opening the input file. - FwdLockConv_Status_FileNotFound = 3, - - /// An error occurred while creating the output file. - FwdLockConv_Status_FileCreationFailed = 4, - - /// An error occurred while reading from the input file. - FwdLockConv_Status_FileReadError = 5, - - /// An error occurred while writing to the output file. - FwdLockConv_Status_FileWriteError = 6, - - /// An error occurred while seeking to a new file position within the output file. - FwdLockConv_Status_FileSeekError = 7, - - /// The input file is not a syntactically correct OMA DRM v1 Forward Lock file. - FwdLockConv_Status_SyntaxError = 8, - - /// Support for this DRM file format has been disabled in the current product configuration. - FwdLockConv_Status_UnsupportedFileFormat = 9, - - /// The content transfer encoding is not one of "binary", "base64", "7bit", or "8bit" - /// (case-insensitive). - FwdLockConv_Status_UnsupportedContentTransferEncoding = 10, - - /// The generation of a random number failed. - FwdLockConv_Status_RandomNumberGenerationFailed = 11, - - /// Key encryption failed. - FwdLockConv_Status_KeyEncryptionFailed = 12, - - /// The calculation of a keyed hash for integrity protection failed. - FwdLockConv_Status_IntegrityProtectionFailed = 13, - - /// There are too many ongoing sessions for another one to be opened. - FwdLockConv_Status_TooManySessions = 14, - - /// An unexpected error occurred. - FwdLockConv_Status_ProgramError = 15 -} FwdLockConv_Status_t; - -/** - * Opens a session for converting an OMA DRM v1 Forward Lock file to the internal Forward Lock file - * format. - * - * @param[out] pSessionId The session ID. - * @param[out] pOutput The output from the conversion process (initialized). - * - * @return A status code. - * @retval FwdLockConv_Status_OK - * @retval FwdLockConv_Status_InvalidArgument - * @retval FwdLockConv_Status_TooManySessions - */ -FwdLockConv_Status_t FwdLockConv_OpenSession(int *pSessionId, FwdLockConv_Output_t *pOutput); - -/** - * Supplies the converter with data to convert. The caller is expected to write the converted data - * to file. Can be called an arbitrary number of times. - * - * @param[in] sessionId The session ID. - * @param[in] pBuffer A reference to a buffer containing the data to convert. - * @param[in] numBytes The number of bytes to convert. - * @param[in,out] pOutput The output from the conversion process (allocated/reallocated). - * - * @return A status code. - * @retval FwdLockConv_Status_OK - * @retval FwdLockConv_Status_InvalidArgument - * @retval FwdLockConv_Status_OutOfMemory - * @retval FwdLockConv_Status_SyntaxError - * @retval FwdLockConv_Status_UnsupportedFileFormat - * @retval FwdLockConv_Status_UnsupportedContentTransferEncoding - * @retval FwdLockConv_Status_RandomNumberGenerationFailed - * @retval FwdLockConv_Status_KeyEncryptionFailed - * @retval FwdLockConv_Status_DataEncryptionFailed - */ -FwdLockConv_Status_t FwdLockConv_ConvertData(int sessionId, - const void *pBuffer, - size_t numBytes, - FwdLockConv_Output_t *pOutput); - -/** - * Closes a session for converting an OMA DRM v1 Forward Lock file to the internal Forward Lock - * file format. The caller must update the produced output file at the indicated file offset with - * the final set of signatures. - * - * @param[in] sessionId The session ID. - * @param[in,out] pOutput The output from the conversion process (deallocated and overwritten). - * - * @return A status code. - * @retval FwdLockConv_Status_OK - * @retval FwdLockConv_Status_InvalidArgument - * @retval FwdLockConv_Status_OutOfMemory - * @retval FwdLockConv_Status_IntegrityProtectionFailed - */ -FwdLockConv_Status_t FwdLockConv_CloseSession(int sessionId, FwdLockConv_Output_t *pOutput); - -/** - * Converts an open OMA DRM v1 Forward Lock file to the internal Forward Lock file format in pull - * mode. - * - * @param[in] inputFileDesc The file descriptor of the open input file. - * @param[in] fpReadFunc A reference to a read function that can operate on the open input file. - * @param[in] outputFileDesc The file descriptor of the open output file. - * @param[in] fpWriteFunc A reference to a write function that can operate on the open output file. - * @param[in] fpLSeekFunc A reference to an lseek function that can operate on the open output file. - * @param[out] pErrorPos - * The file position where the error occurred, in the case of a syntax error. May be NULL. - * - * @return A status code. - * @retval FwdLockConv_Status_OK - * @retval FwdLockConv_Status_InvalidArgument - * @retval FwdLockConv_Status_OutOfMemory - * @retval FwdLockConv_Status_FileReadError - * @retval FwdLockConv_Status_FileWriteError - * @retval FwdLockConv_Status_FileSeekError - * @retval FwdLockConv_Status_SyntaxError - * @retval FwdLockConv_Status_UnsupportedFileFormat - * @retval FwdLockConv_Status_UnsupportedContentTransferEncoding - * @retval FwdLockConv_Status_RandomNumberGenerationFailed - * @retval FwdLockConv_Status_KeyEncryptionFailed - * @retval FwdLockConv_Status_DataEncryptionFailed - * @retval FwdLockConv_Status_IntegrityProtectionFailed - * @retval FwdLockConv_Status_TooManySessions - */ -FwdLockConv_Status_t FwdLockConv_ConvertOpenFile(int inputFileDesc, - FwdLockConv_ReadFunc_t *fpReadFunc, - int outputFileDesc, - FwdLockConv_WriteFunc_t *fpWriteFunc, - FwdLockConv_LSeekFunc_t *fpLSeekFunc, - off64_t *pErrorPos); - -/** - * Converts an OMA DRM v1 Forward Lock file to the internal Forward Lock file format in pull mode. - * - * @param[in] pInputFilename A reference to the input filename. - * @param[in] pOutputFilename A reference to the output filename. - * @param[out] pErrorPos - * The file position where the error occurred, in the case of a syntax error. May be NULL. - * - * @return A status code. - * @retval FwdLockConv_Status_OK - * @retval FwdLockConv_Status_InvalidArgument - * @retval FwdLockConv_Status_OutOfMemory - * @retval FwdLockConv_Status_FileNotFound - * @retval FwdLockConv_Status_FileCreationFailed - * @retval FwdLockConv_Status_FileReadError - * @retval FwdLockConv_Status_FileWriteError - * @retval FwdLockConv_Status_FileSeekError - * @retval FwdLockConv_Status_SyntaxError - * @retval FwdLockConv_Status_UnsupportedFileFormat - * @retval FwdLockConv_Status_UnsupportedContentTransferEncoding - * @retval FwdLockConv_Status_RandomNumberGenerationFailed - * @retval FwdLockConv_Status_KeyEncryptionFailed - * @retval FwdLockConv_Status_DataEncryptionFailed - * @retval FwdLockConv_Status_IntegrityProtectionFailed - * @retval FwdLockConv_Status_TooManySessions - */ -FwdLockConv_Status_t FwdLockConv_ConvertFile(const char *pInputFilename, - const char *pOutputFilename, - off64_t *pErrorPos); - -#ifdef __cplusplus -} -#endif - -#endif // __FWDLOCKCONV_H__ diff --git a/drm/libdrmframework/plugins/forward-lock/internal-format/decoder/Android.mk b/drm/libdrmframework/plugins/forward-lock/internal-format/decoder/Android.mk deleted file mode 100644 index b625edf..0000000 --- a/drm/libdrmframework/plugins/forward-lock/internal-format/decoder/Android.mk +++ /dev/null @@ -1,37 +0,0 @@ -# -# Copyright (C) 2010 The Android Open Source Project -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# -LOCAL_PATH := $(call my-dir) - -include $(CLEAR_VARS) - -LOCAL_SRC_FILES := \ - FwdLockFile.c - -LOCAL_C_INCLUDES := \ - frameworks/base/drm/libdrmframework/plugins/forward-lock/internal-format/common \ - external/openssl/include - -LOCAL_SHARED_LIBRARIES := libcrypto - -LOCAL_WHOLE_STATIC_LIBRARIES := libfwdlock-common - -LOCAL_STATIC_LIBRARIES := libfwdlock-common - -LOCAL_MODULE := libfwdlock-decoder - -LOCAL_MODULE_TAGS := optional - -include $(BUILD_STATIC_LIBRARY) diff --git a/drm/libdrmframework/plugins/forward-lock/internal-format/decoder/FwdLockFile.c b/drm/libdrmframework/plugins/forward-lock/internal-format/decoder/FwdLockFile.c deleted file mode 100644 index 365bdec..0000000 --- a/drm/libdrmframework/plugins/forward-lock/internal-format/decoder/FwdLockFile.c +++ /dev/null @@ -1,454 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include <utils/Log.h> -#include <assert.h> -#include <errno.h> -#include <fcntl.h> -#include <limits.h> -#include <pthread.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> -#include <openssl/aes.h> -#include <openssl/hmac.h> - -#include "FwdLockFile.h" -#include "FwdLockGlue.h" - -#define TRUE 1 -#define FALSE 0 - -#define INVALID_OFFSET ((off64_t)-1) - -#define INVALID_BLOCK_INDEX ((uint64_t)-1) - -#define MAX_NUM_SESSIONS 128 - -#define KEY_SIZE AES_BLOCK_SIZE -#define KEY_SIZE_IN_BITS (KEY_SIZE * 8) - -#define SHA1_HASH_SIZE 20 -#define SHA1_BLOCK_SIZE 64 - -#define FWD_LOCK_VERSION 0 -#define FWD_LOCK_SUBFORMAT 0 -#define USAGE_RESTRICTION_FLAGS 0 -#define CONTENT_TYPE_LENGTH_POS 7 -#define TOP_HEADER_SIZE 8 - -#define SIG_CALC_BUFFER_SIZE (16 * SHA1_BLOCK_SIZE) - -/** - * Data type for the per-file state information needed by the decoder. - */ -typedef struct FwdLockFile_Session { - int fileDesc; - unsigned char topHeader[TOP_HEADER_SIZE]; - char *pContentType; - size_t contentTypeLength; - void *pEncryptedSessionKey; - size_t encryptedSessionKeyLength; - unsigned char dataSignature[SHA1_HASH_SIZE]; - unsigned char headerSignature[SHA1_HASH_SIZE]; - off64_t dataOffset; - off64_t filePos; - AES_KEY encryptionRoundKeys; - HMAC_CTX signingContext; - unsigned char keyStream[AES_BLOCK_SIZE]; - uint64_t blockIndex; -} FwdLockFile_Session_t; - -static FwdLockFile_Session_t *sessionPtrs[MAX_NUM_SESSIONS] = { NULL }; - -static pthread_mutex_t sessionAcquisitionMutex = PTHREAD_MUTEX_INITIALIZER; - -static const unsigned char topHeaderTemplate[] = - { 'F', 'W', 'L', 'K', FWD_LOCK_VERSION, FWD_LOCK_SUBFORMAT, USAGE_RESTRICTION_FLAGS }; - -/** - * Acquires an unused file session for the given file descriptor. - * - * @param[in] fileDesc A file descriptor. - * - * @return A session ID. - */ -static int FwdLockFile_AcquireSession(int fileDesc) { - int sessionId = -1; - if (fileDesc < 0) { - errno = EBADF; - } else { - int i; - pthread_mutex_lock(&sessionAcquisitionMutex); - for (i = 0; i < MAX_NUM_SESSIONS; ++i) { - int candidateSessionId = (fileDesc + i) % MAX_NUM_SESSIONS; - if (sessionPtrs[candidateSessionId] == NULL) { - sessionPtrs[candidateSessionId] = malloc(sizeof **sessionPtrs); - if (sessionPtrs[candidateSessionId] != NULL) { - sessionPtrs[candidateSessionId]->fileDesc = fileDesc; - sessionPtrs[candidateSessionId]->pContentType = NULL; - sessionPtrs[candidateSessionId]->pEncryptedSessionKey = NULL; - sessionId = candidateSessionId; - } - break; - } - } - pthread_mutex_unlock(&sessionAcquisitionMutex); - if (i == MAX_NUM_SESSIONS) { - ALOGE("Too many sessions opened at the same time"); - errno = ENFILE; - } - } - return sessionId; -} - -/** - * Finds the file session associated with the given file descriptor. - * - * @param[in] fileDesc A file descriptor. - * - * @return A session ID. - */ -static int FwdLockFile_FindSession(int fileDesc) { - int sessionId = -1; - if (fileDesc < 0) { - errno = EBADF; - } else { - int i; - pthread_mutex_lock(&sessionAcquisitionMutex); - for (i = 0; i < MAX_NUM_SESSIONS; ++i) { - int candidateSessionId = (fileDesc + i) % MAX_NUM_SESSIONS; - if (sessionPtrs[candidateSessionId] != NULL && - sessionPtrs[candidateSessionId]->fileDesc == fileDesc) { - sessionId = candidateSessionId; - break; - } - } - pthread_mutex_unlock(&sessionAcquisitionMutex); - if (i == MAX_NUM_SESSIONS) { - errno = EBADF; - } - } - return sessionId; -} - -/** - * Releases a file session. - * - * @param[in] sessionID A session ID. - */ -static void FwdLockFile_ReleaseSession(int sessionId) { - pthread_mutex_lock(&sessionAcquisitionMutex); - assert(0 <= sessionId && sessionId < MAX_NUM_SESSIONS && sessionPtrs[sessionId] != NULL); - free(sessionPtrs[sessionId]->pContentType); - free(sessionPtrs[sessionId]->pEncryptedSessionKey); - memset(sessionPtrs[sessionId], 0, sizeof *sessionPtrs[sessionId]); // Zero out key data. - free(sessionPtrs[sessionId]); - sessionPtrs[sessionId] = NULL; - pthread_mutex_unlock(&sessionAcquisitionMutex); -} - -/** - * Derives keys for encryption and signing from the encrypted session key. - * - * @param[in,out] pSession A reference to a file session. - * - * @return A Boolean value indicating whether key derivation was successful. - */ -static int FwdLockFile_DeriveKeys(FwdLockFile_Session_t * pSession) { - int result; - struct FwdLockFile_DeriveKeys_Data { - AES_KEY sessionRoundKeys; - unsigned char value[KEY_SIZE]; - unsigned char key[KEY_SIZE]; - } *pData = malloc(sizeof *pData); - if (pData == NULL) { - result = FALSE; - } else { - result = FwdLockGlue_DecryptKey(pSession->pEncryptedSessionKey, - pSession->encryptedSessionKeyLength, pData->key, KEY_SIZE); - if (result) { - if (AES_set_encrypt_key(pData->key, KEY_SIZE_IN_BITS, &pData->sessionRoundKeys) != 0) { - result = FALSE; - } else { - // Encrypt the 16-byte value {0, 0, ..., 0} to produce the encryption key. - memset(pData->value, 0, KEY_SIZE); - AES_encrypt(pData->value, pData->key, &pData->sessionRoundKeys); - if (AES_set_encrypt_key(pData->key, KEY_SIZE_IN_BITS, - &pSession->encryptionRoundKeys) != 0) { - result = FALSE; - } else { - // Encrypt the 16-byte value {1, 0, ..., 0} to produce the signing key. - ++pData->value[0]; - AES_encrypt(pData->value, pData->key, &pData->sessionRoundKeys); - HMAC_CTX_init(&pSession->signingContext); - HMAC_Init_ex(&pSession->signingContext, pData->key, KEY_SIZE, EVP_sha1(), NULL); - } - } - } - if (!result) { - errno = ENOSYS; - } - memset(pData, 0, sizeof pData); // Zero out key data. - free(pData); - } - return result; -} - -/** - * Calculates the counter, treated as a 16-byte little-endian number, used to generate the keystream - * for the given block. - * - * @param[in] pNonce A reference to the nonce. - * @param[in] blockIndex The index number of the block. - * @param[out] pCounter A reference to the counter. - */ -static void FwdLockFile_CalculateCounter(const unsigned char *pNonce, - uint64_t blockIndex, - unsigned char *pCounter) { - unsigned char carry = 0; - size_t i = 0; - for (; i < sizeof blockIndex; ++i) { - unsigned char part = pNonce[i] + (unsigned char)(blockIndex >> (i * CHAR_BIT)); - pCounter[i] = part + carry; - carry = (part < pNonce[i] || pCounter[i] < part) ? 1 : 0; - } - for (; i < AES_BLOCK_SIZE; ++i) { - pCounter[i] = pNonce[i] + carry; - carry = (pCounter[i] < pNonce[i]) ? 1 : 0; - } -} - -/** - * Decrypts the byte at the current file position using AES-128-CTR. In CTR (or "counter") mode, - * encryption and decryption are performed using the same algorithm. - * - * @param[in,out] pSession A reference to a file session. - * @param[in] pByte The byte to decrypt. - */ -void FwdLockFile_DecryptByte(FwdLockFile_Session_t * pSession, unsigned char *pByte) { - uint64_t blockIndex = pSession->filePos / AES_BLOCK_SIZE; - uint64_t blockOffset = pSession->filePos % AES_BLOCK_SIZE; - if (blockIndex != pSession->blockIndex) { - // The first 16 bytes of the encrypted session key is used as the nonce. - unsigned char counter[AES_BLOCK_SIZE]; - FwdLockFile_CalculateCounter(pSession->pEncryptedSessionKey, blockIndex, counter); - AES_encrypt(counter, pSession->keyStream, &pSession->encryptionRoundKeys); - pSession->blockIndex = blockIndex; - } - *pByte ^= pSession->keyStream[blockOffset]; -} - -int FwdLockFile_attach(int fileDesc) { - int sessionId = FwdLockFile_AcquireSession(fileDesc); - if (sessionId >= 0) { - FwdLockFile_Session_t *pSession = sessionPtrs[sessionId]; - int isSuccess = FALSE; - if (read(fileDesc, pSession->topHeader, TOP_HEADER_SIZE) == TOP_HEADER_SIZE && - memcmp(pSession->topHeader, topHeaderTemplate, sizeof topHeaderTemplate) == 0) { - pSession->contentTypeLength = pSession->topHeader[CONTENT_TYPE_LENGTH_POS]; - assert(pSession->contentTypeLength <= UCHAR_MAX); // Untaint scalar for code checkers. - pSession->pContentType = malloc(pSession->contentTypeLength + 1); - if (pSession->pContentType != NULL && - read(fileDesc, pSession->pContentType, pSession->contentTypeLength) == - (ssize_t)pSession->contentTypeLength) { - pSession->pContentType[pSession->contentTypeLength] = '\0'; - pSession->encryptedSessionKeyLength = FwdLockGlue_GetEncryptedKeyLength(KEY_SIZE); - pSession->pEncryptedSessionKey = malloc(pSession->encryptedSessionKeyLength); - if (pSession->pEncryptedSessionKey != NULL && - read(fileDesc, pSession->pEncryptedSessionKey, - pSession->encryptedSessionKeyLength) == - (ssize_t)pSession->encryptedSessionKeyLength && - read(fileDesc, pSession->dataSignature, SHA1_HASH_SIZE) == - SHA1_HASH_SIZE && - read(fileDesc, pSession->headerSignature, SHA1_HASH_SIZE) == - SHA1_HASH_SIZE) { - isSuccess = FwdLockFile_DeriveKeys(pSession); - } - } - } - if (isSuccess) { - pSession->dataOffset = pSession->contentTypeLength + - pSession->encryptedSessionKeyLength + TOP_HEADER_SIZE + 2 * SHA1_HASH_SIZE; - pSession->filePos = 0; - pSession->blockIndex = INVALID_BLOCK_INDEX; - } else { - FwdLockFile_ReleaseSession(sessionId); - sessionId = -1; - } - } - return (sessionId >= 0) ? 0 : -1; -} - -int FwdLockFile_open(const char *pFilename) { - int fileDesc = open(pFilename, O_RDONLY); - if (fileDesc < 0) { - ALOGE("failed to open file '%s': %s", pFilename, strerror(errno)); - return fileDesc; - } - - if (FwdLockFile_attach(fileDesc) < 0) { - (void)close(fileDesc); - fileDesc = -1; - } - return fileDesc; -} - -ssize_t FwdLockFile_read(int fileDesc, void *pBuffer, size_t numBytes) { - ssize_t numBytesRead; - int sessionId = FwdLockFile_FindSession(fileDesc); - if (sessionId < 0) { - numBytesRead = -1; - } else { - FwdLockFile_Session_t *pSession = sessionPtrs[sessionId]; - ssize_t i; - numBytesRead = read(pSession->fileDesc, pBuffer, numBytes); - for (i = 0; i < numBytesRead; ++i) { - FwdLockFile_DecryptByte(pSession, &((unsigned char *)pBuffer)[i]); - ++pSession->filePos; - } - } - return numBytesRead; -} - -off64_t FwdLockFile_lseek(int fileDesc, off64_t offset, int whence) { - off64_t newFilePos; - int sessionId = FwdLockFile_FindSession(fileDesc); - if (sessionId < 0) { - newFilePos = INVALID_OFFSET; - } else { - FwdLockFile_Session_t *pSession = sessionPtrs[sessionId]; - switch (whence) { - case SEEK_SET: - newFilePos = lseek64(pSession->fileDesc, pSession->dataOffset + offset, whence); - break; - case SEEK_CUR: - case SEEK_END: - newFilePos = lseek64(pSession->fileDesc, offset, whence); - break; - default: - errno = EINVAL; - newFilePos = INVALID_OFFSET; - break; - } - if (newFilePos != INVALID_OFFSET) { - if (newFilePos < pSession->dataOffset) { - // The new file position is illegal for an internal Forward Lock file. Restore the - // original file position. - (void)lseek64(pSession->fileDesc, pSession->dataOffset + pSession->filePos, - SEEK_SET); - errno = EINVAL; - newFilePos = INVALID_OFFSET; - } else { - // The return value should be the file position that lseek64() would have returned - // for the embedded content file. - pSession->filePos = newFilePos - pSession->dataOffset; - newFilePos = pSession->filePos; - } - } - } - return newFilePos; -} - -int FwdLockFile_detach(int fileDesc) { - int sessionId = FwdLockFile_FindSession(fileDesc); - if (sessionId < 0) { - return -1; - } - HMAC_CTX_cleanup(&sessionPtrs[sessionId]->signingContext); - FwdLockFile_ReleaseSession(sessionId); - return 0; -} - -int FwdLockFile_close(int fileDesc) { - return (FwdLockFile_detach(fileDesc) == 0) ? close(fileDesc) : -1; -} - -int FwdLockFile_CheckDataIntegrity(int fileDesc) { - int result; - int sessionId = FwdLockFile_FindSession(fileDesc); - if (sessionId < 0) { - result = FALSE; - } else { - struct FwdLockFile_CheckDataIntegrity_Data { - unsigned char signature[SHA1_HASH_SIZE]; - unsigned char buffer[SIG_CALC_BUFFER_SIZE]; - } *pData = malloc(sizeof *pData); - if (pData == NULL) { - result = FALSE; - } else { - FwdLockFile_Session_t *pSession = sessionPtrs[sessionId]; - if (lseek64(pSession->fileDesc, pSession->dataOffset, SEEK_SET) != - pSession->dataOffset) { - result = FALSE; - } else { - ssize_t numBytesRead; - 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); - } - if (numBytesRead < 0) { - result = FALSE; - } else { - HMAC_Final(&pSession->signingContext, pData->signature, &signatureSize); - assert(signatureSize == SHA1_HASH_SIZE); - 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, - SEEK_SET); - } - free(pData); - } - } - return result; -} - -int FwdLockFile_CheckHeaderIntegrity(int fileDesc) { - int result; - int sessionId = FwdLockFile_FindSession(fileDesc); - if (sessionId < 0) { - result = FALSE; - } else { - FwdLockFile_Session_t *pSession = sessionPtrs[sessionId]; - unsigned char signature[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, SHA1_HASH_SIZE); - HMAC_Final(&pSession->signingContext, signature, &signatureSize); - assert(signatureSize == SHA1_HASH_SIZE); - result = memcmp(signature, pSession->headerSignature, SHA1_HASH_SIZE) == 0; - HMAC_Init_ex(&pSession->signingContext, NULL, KEY_SIZE, NULL, NULL); - } - return result; -} - -int FwdLockFile_CheckIntegrity(int fileDesc) { - return FwdLockFile_CheckHeaderIntegrity(fileDesc) && FwdLockFile_CheckDataIntegrity(fileDesc); -} - -const char *FwdLockFile_GetContentType(int fileDesc) { - int sessionId = FwdLockFile_FindSession(fileDesc); - if (sessionId < 0) { - return NULL; - } - return sessionPtrs[sessionId]->pContentType; -} diff --git a/drm/libdrmframework/plugins/forward-lock/internal-format/decoder/FwdLockFile.h b/drm/libdrmframework/plugins/forward-lock/internal-format/decoder/FwdLockFile.h deleted file mode 100644 index fc64050..0000000 --- a/drm/libdrmframework/plugins/forward-lock/internal-format/decoder/FwdLockFile.h +++ /dev/null @@ -1,135 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef __FWDLOCKFILE_H__ -#define __FWDLOCKFILE_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -#include <sys/types.h> - -/** - * Attaches to an open Forward Lock file. The file position is assumed to be at the beginning of the - * file. - * - * @param[in] fileDesc The file descriptor of an open Forward Lock file. - * - * @return A status code. - * @retval 0 Success. - * @retval -1 Failure. - */ -int FwdLockFile_attach(int fileDesc); - -/** - * Opens a Forward Lock file for reading. - * - * @param[in] pFilename A reference to a filename. - * - * @return A file descriptor. - * @retval -1 Failure. - */ -int FwdLockFile_open(const char *pFilename); - -/** - * Reads the specified number of bytes from an open Forward Lock file. - * - * @param[in] fileDesc The file descriptor of an open Forward Lock file. - * @param[out] pBuffer A reference to the buffer that should receive the read data. - * @param[in] numBytes The number of bytes to read. - * - * @return The number of bytes read. - * @retval -1 Failure. - */ -ssize_t FwdLockFile_read(int fileDesc, void *pBuffer, size_t numBytes); - -/** - * Updates the file position within an open Forward Lock file. - * - * @param[in] fileDesc The file descriptor of an open Forward Lock file. - * @param[in] offset The offset with which to update the file position. - * @param[in] whence One of SEEK_SET, SEEK_CUR, and SEEK_END. - * - * @return The new file position. - * @retval ((off64_t)-1) Failure. - */ -off64_t FwdLockFile_lseek(int fileDesc, off64_t offset, int whence); - -/** - * Detaches from an open Forward Lock file. - * - * @param[in] fileDesc The file descriptor of an open Forward Lock file. - * - * @return A status code. - * @retval 0 Success. - * @retval -1 Failure. - */ -int FwdLockFile_detach(int fileDesc); - -/** - * Closes an open Forward Lock file. - * - * @param[in] fileDesc The file descriptor of an open Forward Lock file. - * - * @return A status code. - * @retval 0 Success. - * @retval -1 Failure. - */ -int FwdLockFile_close(int fileDesc); - -/** - * Checks the data integrity of an open Forward Lock file. - * - * @param[in] fileDesc The file descriptor of an open Forward Lock file. - * - * @return A Boolean value indicating whether the integrity check was successful. - */ -int FwdLockFile_CheckDataIntegrity(int fileDesc); - -/** - * Checks the header integrity of an open Forward Lock file. - * - * @param[in] fileDesc The file descriptor of an open Forward Lock file. - * - * @return A Boolean value indicating whether the integrity check was successful. - */ -int FwdLockFile_CheckHeaderIntegrity(int fileDesc); - -/** - * Checks both the data and header integrity of an open Forward Lock file. - * - * @param[in] fileDesc The file descriptor of an open Forward Lock file. - * - * @return A Boolean value indicating whether the integrity check was successful. - */ -int FwdLockFile_CheckIntegrity(int fileDesc); - -/** - * Returns the content type of an open Forward Lock file. - * - * @param[in] fileDesc The file descriptor of an open Forward Lock file. - * - * @return - * A reference to the content type. The reference remains valid as long as the file is kept open. - */ -const char *FwdLockFile_GetContentType(int fileDesc); - -#ifdef __cplusplus -} -#endif - -#endif // __FWDLOCKFILE_H__ diff --git a/drm/libdrmframework/plugins/forward-lock/internal-format/doc/FwdLock.html b/drm/libdrmframework/plugins/forward-lock/internal-format/doc/FwdLock.html deleted file mode 100755 index 8f95cd2..0000000 --- a/drm/libdrmframework/plugins/forward-lock/internal-format/doc/FwdLock.html +++ /dev/null @@ -1,1039 +0,0 @@ -<html> - -<head> -<meta http-equiv=Content-Type content="text/html; charset=windows-1252"> -<meta name=Generator content="Microsoft Word 12 (filtered)"> -<title>Forward Lock Converter and Decoder</title> -<style> -<!-- - /* Font Definitions */ - @font-face - {font-family:SimSun; - panose-1:2 1 6 0 3 1 1 1 1 1;} -@font-face - {font-family:"Cambria Math"; - panose-1:2 4 5 3 5 4 6 3 2 4;} -@font-face - {font-family:Tahoma; - panose-1:2 11 6 4 3 5 4 4 2 4;} -@font-face - {font-family:"Lucida Console","DejaVu Sans Mono"; - panose-1:2 11 6 9 4 5 4 2 2 4;} -@font-face - {font-family:"\@SimSun"; - panose-1:2 1 6 0 3 1 1 1 1 1;} - /* Style Definitions */ - p.MsoNormal, li.MsoNormal, div.MsoNormal - {margin:0cm; - margin-bottom:.0001pt; - font-size:12.0pt; - font-family:"Times New Roman","serif";} -h1 - {margin-right:0cm; - margin-left:21.6pt; - text-indent:-21.6pt; - page-break-after:avoid; - font-size:16.0pt; - font-family:"Arial","sans-serif";} -h2 - {margin-top:12.0pt; - margin-right:0cm; - margin-bottom:3.0pt; - margin-left:28.8pt; - text-indent:-28.8pt; - page-break-after:avoid; - font-size:14.0pt; - font-family:"Arial","sans-serif"; - font-style:italic;} -h3 - {margin-top:12.0pt; - margin-right:0cm; - margin-bottom:3.0pt; - margin-left:36.0pt; - text-indent:-36.0pt; - page-break-after:avoid; - font-size:13.0pt; - font-family:"Arial","sans-serif";} -h4 - {margin-top:12.0pt; - margin-right:0cm; - margin-bottom:3.0pt; - margin-left:43.2pt; - text-indent:-43.2pt; - page-break-after:avoid; - font-size:14.0pt; - font-family:"Times New Roman","serif";} -h5 - {margin-top:12.0pt; - margin-right:0cm; - margin-bottom:3.0pt; - margin-left:50.4pt; - text-indent:-50.4pt; - font-size:13.0pt; - font-family:"Times New Roman","serif"; - font-style:italic;} -h6 - {margin-top:12.0pt; - margin-right:0cm; - margin-bottom:3.0pt; - margin-left:57.6pt; - text-indent:-57.6pt; - font-size:11.0pt; - font-family:"Times New Roman","serif";} -p.MsoHeading7, li.MsoHeading7, div.MsoHeading7 - {margin-top:12.0pt; - margin-right:0cm; - margin-bottom:3.0pt; - margin-left:64.8pt; - text-indent:-64.8pt; - font-size:12.0pt; - font-family:"Times New Roman","serif";} -p.MsoHeading8, li.MsoHeading8, div.MsoHeading8 - {margin-top:12.0pt; - margin-right:0cm; - margin-bottom:3.0pt; - margin-left:72.0pt; - text-indent:-72.0pt; - font-size:12.0pt; - font-family:"Times New Roman","serif"; - font-style:italic;} -p.MsoHeading9, li.MsoHeading9, div.MsoHeading9 - {margin-top:12.0pt; - margin-right:0cm; - margin-bottom:3.0pt; - margin-left:79.2pt; - text-indent:-79.2pt; - font-size:11.0pt; - font-family:"Arial","sans-serif";} -p.MsoToc1, li.MsoToc1, div.MsoToc1 - {margin-top:6.0pt; - margin-right:0cm; - margin-bottom:6.0pt; - margin-left:0cm; - line-height:150%; - font-size:10.5pt; - font-family:"Times New Roman","serif"; - text-transform:uppercase; - font-weight:bold;} -p.MsoToc2, li.MsoToc2, div.MsoToc2 - {margin-top:0cm; - margin-right:0cm; - margin-bottom:0cm; - margin-left:12.0pt; - margin-bottom:.0001pt; - line-height:150%; - font-size:10.5pt; - font-family:"Times New Roman","serif"; - font-variant:small-caps;} -p.MsoToc3, li.MsoToc3, div.MsoToc3 - {margin-top:0cm; - margin-right:0cm; - margin-bottom:0cm; - margin-left:24.0pt; - margin-bottom:.0001pt; - line-height:150%; - font-size:10.5pt; - font-family:"Times New Roman","serif"; - font-style:italic;} -p.MsoToc4, li.MsoToc4, div.MsoToc4 - {margin-top:0cm; - margin-right:0cm; - margin-bottom:0cm; - margin-left:36.0pt; - margin-bottom:.0001pt; - font-size:9.0pt; - font-family:"Times New Roman","serif";} -p.MsoToc5, li.MsoToc5, div.MsoToc5 - {margin-top:0cm; - margin-right:0cm; - margin-bottom:0cm; - margin-left:48.0pt; - margin-bottom:.0001pt; - font-size:9.0pt; - font-family:"Times New Roman","serif";} -p.MsoToc6, li.MsoToc6, div.MsoToc6 - {margin-top:0cm; - margin-right:0cm; - margin-bottom:0cm; - margin-left:60.0pt; - margin-bottom:.0001pt; - font-size:9.0pt; - font-family:"Times New Roman","serif";} -p.MsoToc7, li.MsoToc7, div.MsoToc7 - {margin-top:0cm; - margin-right:0cm; - margin-bottom:0cm; - margin-left:72.0pt; - margin-bottom:.0001pt; - font-size:9.0pt; - font-family:"Times New Roman","serif";} -p.MsoToc8, li.MsoToc8, div.MsoToc8 - {margin-top:0cm; - margin-right:0cm; - margin-bottom:0cm; - margin-left:84.0pt; - margin-bottom:.0001pt; - font-size:9.0pt; - font-family:"Times New Roman","serif";} -p.MsoToc9, li.MsoToc9, div.MsoToc9 - {margin-top:0cm; - margin-right:0cm; - margin-bottom:0cm; - margin-left:96.0pt; - margin-bottom:.0001pt; - font-size:9.0pt; - font-family:"Times New Roman","serif";} -p.MsoFootnoteText, li.MsoFootnoteText, div.MsoFootnoteText - {margin:0cm; - margin-bottom:.0001pt; - font-size:10.0pt; - font-family:"Times New Roman","serif";} -p.MsoHeader, li.MsoHeader, div.MsoHeader - {margin:0cm; - margin-bottom:.0001pt; - font-size:12.0pt; - font-family:"Times New Roman","serif";} -p.MsoFooter, li.MsoFooter, div.MsoFooter - {margin:0cm; - margin-bottom:.0001pt; - font-size:12.0pt; - font-family:"Times New Roman","serif";} -p.MsoCaption, li.MsoCaption, div.MsoCaption - {margin:0cm; - margin-bottom:.0001pt; - font-size:11.0pt; - font-family:"Times New Roman","serif"; - font-weight:bold;} -span.MsoFootnoteReference - {vertical-align:super;} -p.MsoTitle, li.MsoTitle, div.MsoTitle - {margin-top:12.0pt; - margin-right:0cm; - margin-bottom:120.0pt; - margin-left:0cm; - text-align:center; - font-size:16.0pt; - font-family:"Arial","sans-serif"; - font-weight:bold;} -p.MsoBodyText, li.MsoBodyText, div.MsoBodyText - {mso-style-link:"Body Text Char"; - margin-top:0cm; - margin-right:0cm; - margin-bottom:6.0pt; - margin-left:0cm; - font-size:12.0pt; - font-family:"Times New Roman","serif";} -a:link, span.MsoHyperlink - {color:blue; - text-decoration:underline;} -a:visited, span.MsoHyperlinkFollowed - {color:purple; - text-decoration:underline;} -p.MsoAcetate, li.MsoAcetate, div.MsoAcetate - {margin:0cm; - margin-bottom:.0001pt; - font-size:8.0pt; - font-family:"Tahoma","sans-serif";} -span.BodyTextChar - {mso-style-name:"Body Text Char"; - mso-style-link:"Body Text";} - /* Page Definitions */ - @page WordSection1 - {size:595.45pt 841.7pt; - margin:72.0pt 90.0pt 72.0pt 90.0pt;} -div.WordSection1 - {page:WordSection1;} -@page WordSection2 - {size:595.45pt 841.7pt; - margin:72.0pt 90.0pt 72.0pt 90.0pt;} -div.WordSection2 - {page:WordSection2;} - /* List Definitions */ - ol - {margin-bottom:0cm;} -ul - {margin-bottom:0cm;} ---> -</style> - -</head> - -<body lang=EN-US link=blue vlink=purple> - -<div class=WordSection1> - -<p class=MsoTitle>Forward Lock Converter And Decoder</p> - -<p class=MsoToc1><span -class=MsoHyperlink><a href="#_Toc276471422">1<span style='font-size:12.0pt; -line-height:150%;color:windowtext;text-transform:none;font-weight:normal; -text-decoration:none'> </span>Introduction<span style='color:windowtext; -display:none;text-decoration:none'>. </span><span -style='color:windowtext;display:none;text-decoration:none'>3</span></a></span></p> - -<p class=MsoToc1><span class=MsoHyperlink><a href="#_Toc276471423">2<span -style='font-size:12.0pt;line-height:150%;color:windowtext;text-transform:none; -font-weight:normal;text-decoration:none'> </span>Overview<span -style='color:windowtext;display:none;text-decoration:none'>... </span><span -style='color:windowtext;display:none;text-decoration:none'>3</span></a></span></p> - -<p class=MsoToc1><span class=MsoHyperlink><a href="#_Toc276471424">3<span -style='font-size:12.0pt;line-height:150%;color:windowtext;text-transform:none; -font-weight:normal;text-decoration:none'> </span>Use Cases<span -style='color:windowtext;display:none;text-decoration:none'>. </span><span -style='color:windowtext;display:none;text-decoration:none'>4</span></a></span></p> - -<p class=MsoToc2><span class=MsoHyperlink><span style='font-variant:normal !important; -text-transform:uppercase'><a href="#_Toc276471425">3.1<span style='font-size: -12.0pt;line-height:150%;color:windowtext;text-transform:none;text-decoration: -none'> </span>Converter<span style='color:windowtext;display:none; -text-decoration:none'>. </span><span -style='color:windowtext;display:none;text-decoration:none'>4</span></a></span></span></p> - -<p class=MsoToc3><span class=MsoHyperlink><a href="#_Toc276471426">3.1.1<span -style='font-size:12.0pt;line-height:150%;color:windowtext;font-style:normal; -text-decoration:none'> </span>Convert Data (Push-Mode Conversion)<span -style='color:windowtext;display:none;text-decoration:none'> </span><span -style='color:windowtext;display:none;text-decoration:none'>4</span></a></span></p> - -<p class=MsoToc3><span class=MsoHyperlink><a href="#_Toc276471427">3.1.2<span -style='font-size:12.0pt;line-height:150%;color:windowtext;font-style:normal; -text-decoration:none'> </span>Convert File (Pull-Mode Conversion)<span -style='color:windowtext;display:none;text-decoration:none'> </span><span -style='color:windowtext;display:none;text-decoration:none'>6</span></a></span></p> - -<p class=MsoToc2><span class=MsoHyperlink><span style='font-variant:normal !important; -text-transform:uppercase'><a href="#_Toc276471428">3.2<span style='font-size: -12.0pt;line-height:150%;color:windowtext;text-transform:none;text-decoration: -none'> </span>Decoder<span style='color:windowtext;display:none; -text-decoration:none'>. </span><span -style='color:windowtext;display:none;text-decoration:none'>7</span></a></span></span></p> - -<p class=MsoToc3><span class=MsoHyperlink><a href="#_Toc276471429">3.2.1<span -style='font-size:12.0pt;line-height:150%;color:windowtext;font-style:normal; -text-decoration:none'> </span>Check Integrity<span style='color:windowtext; -display:none;text-decoration:none'>. </span><span -style='color:windowtext;display:none;text-decoration:none'>8</span></a></span></p> - -<p class=MsoToc3><span class=MsoHyperlink><a href="#_Toc276471430">3.2.2<span -style='font-size:12.0pt;line-height:150%;color:windowtext;font-style:normal; -text-decoration:none'> </span>Get Content Type<span style='color:windowtext; -display:none;text-decoration:none'>. </span><span -style='color:windowtext;display:none;text-decoration:none'>9</span></a></span></p> - -<p class=MsoToc3><span class=MsoHyperlink><a href="#_Toc276471431">3.2.3<span -style='font-size:12.0pt;line-height:150%;color:windowtext;font-style:normal; -text-decoration:none'> </span>Decode File<span style='color:windowtext; -display:none;text-decoration:none'>. </span><span -style='color:windowtext;display:none;text-decoration:none'>10</span></a></span></p> - -<p class=MsoToc1><span class=MsoHyperlink><a href="#_Toc276471432">4<span -style='font-size:12.0pt;line-height:150%;color:windowtext;text-transform:none; -font-weight:normal;text-decoration:none'> </span>Definition of the -Internal Forward Lock File Format<span style='color:windowtext;display:none; -text-decoration:none'>. </span><span -style='color:windowtext;display:none;text-decoration:none'>11</span></a></span></p> - -<p class=MsoToc2><span class=MsoHyperlink><span style='font-variant:normal !important; -text-transform:uppercase'><a href="#_Toc276471433">4.1<span style='font-size: -12.0pt;line-height:150%;color:windowtext;text-transform:none;text-decoration: -none'> </span>Key Derivation<span style='color:windowtext;display:none; -text-decoration:none'>.. </span><span -style='color:windowtext;display:none;text-decoration:none'>11</span></a></span></span></p> - -<p class=MsoToc2><span class=MsoHyperlink><span style='font-variant:normal !important; -text-transform:uppercase'><a href="#_Toc276471434">4.2<span style='font-size: -12.0pt;line-height:150%;color:windowtext;text-transform:none;text-decoration: -none'> </span>Calculation of the Counters<span style='color:windowtext; -display:none;text-decoration:none'>. </span><span -style='color:windowtext;display:none;text-decoration:none'>12</span></a></span></span></p> - -<p class=MsoToc1><span class=MsoHyperlink><a href="#_Toc276471435">5<span -style='font-size:12.0pt;line-height:150%;color:windowtext;text-transform:none; -font-weight:normal;text-decoration:none'> </span>Unit Test Cases<span -style='color:windowtext;display:none;text-decoration:none'>. </span><span -style='color:windowtext;display:none;text-decoration:none'>12</span></a></span></p> - -<p class=MsoToc1><span class=MsoHyperlink><a href="#_Toc276471436">6<span -style='font-size:12.0pt;line-height:150%;color:windowtext;text-transform:none; -font-weight:normal;text-decoration:none'> </span>References<span -style='color:windowtext;display:none;text-decoration:none'>. </span><span -style='color:windowtext;display:none;text-decoration:none'>12</span></a></span></p> - -<p class=MsoBodyText></p> - -</div> - -<span style='font-size:12.0pt;font-family:"Times New Roman","serif"'><br -clear=all style='page-break-before:right'> -</span> - -<div class=WordSection2> - -<h1><a name="_Toc276471422"></a><a name="_Ref263085474">1<span -style='font:7.0pt "Times New Roman"'> </span>Introduction</a></h1> - -<p class=MsoBodyText>The internal Forward Lock file format is used for encrypting -inherently unencrypted OMA DRM version 1 Forward Lock and Combined Delivery -files so they can be securely stored on externally accessible file system partitions -such as memory stick.</p> - -<p class=MsoBodyText>Our general strategy is to convert such <i>OMA DRM Message</i> -(‘.dm’) files to internal Forward Lock (‘.fl’) files as soon as they are -downloaded or otherwise transferred to the phone, and not actually provide any -decoders for ‘.dm’ files.</p> - -<h1><a name="_Toc276471423">2<span style='font:7.0pt "Times New Roman"'> -</span>Overview</a></h1> - -<p class=MsoBodyText>The <i>Forward Lock Converter</i> converts OMA DRM Message -files to the internal file format. The <i>Forward Lock Decoder</i> provides a -POSIX-level API for transparent reading and seeking through such a converted -file as if it were unencrypted. The API also includes functions for checking a -file’s integrity and getting the MIME type of its embedded content.</p> - -<p class=MsoBodyText style='margin-bottom:24.0pt'>The converter and decoder are -built into two separate libraries, which share common code for random number -generation and key encryption in a third library. For test purposes there is -also a unit test application. See Figure 1.</p> - -<p class=MsoBodyText style='page-break-after:avoid'><img width=288 height=364 -src="images/image001.gif"></p> - -<p class=MsoCaption style='margin-top:12.0pt;margin-right:0cm;margin-bottom: -12.0pt;margin-left:0cm'><a name="_Ref262730885">Figure </a>1. Block diagram illustrating the dependencies between the executable modules.</p> - -<b><span style='font-size:16.0pt;font-family:"Arial","sans-serif"'><br -clear=all style='page-break-before:always'> -</span></b> - -<h1><a name="_Toc276471424">3<span style='font:7.0pt "Times New Roman"'> -</span>Use Cases</a></h1> - -<p class=MsoBodyText>This section describes all the use cases for the converter -and decoder. It shows the sequence of API calls that should be used to solve -these use cases.</p> - -<h2><a name="_Toc276471425">3.1<span style='font:7.0pt "Times New Roman"'> -</span>Converter</a></h2> - -<p class=MsoBodyText>Through the converter API, conversion can be performed in one -of two ways:</p> - -<p class=MsoBodyText style='margin-left:36.0pt;text-indent:-18.0pt'>1.<span -style='font:7.0pt "Times New Roman"'> </span><i>Push-mode -conversion</i> is when the client progressively feeds data to the converter as -it arrives. This is appropriate when data arrives gradually in chunks, with -idle time in between. Consequently, push mode is used for converting files -being downloaded through HTTP. See section 3.1.1.</p> - -<p class=MsoBodyText style='margin-left:36.0pt;text-indent:-18.0pt'>2.<span -style='font:7.0pt "Times New Roman"'> </span><i>Pull-mode -conversion</i> is when the converter drives the process and consumes data from -the client as it needs it. This is appropriate when the entire file to be -converted is readily available. Hence, pull mode is used by the unit test application. -See section 3.1.2.</p> - -<p class=MsoBodyText>Internally, pull-mode conversion is implemented in terms -of the API for push-mode conversion.</p> - -<h3><a name="_Toc276471426"></a><a name="_Ref263085478">3.1.1<span -style='font:7.0pt "Times New Roman"'> </span>Convert Data -(Push-Mode Conversion)</a></h3> - -<p class=MsoBodyText>Push-mode conversion is performed as follows (see also Figure 2):</p> - -<p class=MsoBodyText style='margin-left:36.0pt;text-indent:-18.0pt'>1.<span -style='font:7.0pt "Times New Roman"'> </span><span -style='font-size:10.0pt;font-family:"Lucida Console","DejaVu Sans Mono"'>FwdLockConv_OpenSession</span> -initializes the output parameter and returns a <i>session ID</i> to be used in -subsequent calls to the API. The output parameter is a union of return values -whose correct use at any given moment is determined by the API function last -called.</p> - -<p class=MsoBodyText style='margin-left:36.0pt;text-indent:-18.0pt'>2.<span -style='font:7.0pt "Times New Roman"'> </span><span -style='font-size:10.0pt;font-family:"Lucida Console","DejaVu Sans Mono"'>FwdLockConv_ConvertData</span> -is called repeatedly until no more input data remains. Each call converts the -maximum amount of data possible and writes it to the output buffer. The client then -writes this data to file.</p> - -<p class=MsoBodyText style='margin-left:36.0pt;text-indent:-18.0pt'>3.<span -style='font:7.0pt "Times New Roman"'> </span><span -style='font-size:10.0pt;font-family:"Lucida Console","DejaVu Sans Mono"'>FwdLockConv_CloseSession</span> -cleans up the session and deallocates the output buffer. If all has gone well, a -two-part cryptographic signature of the output file is calculated. The client -must go back and rewrite part of the file header with this updated signature -information.</p> - -<p class=MsoBodyText>Every time a file is being converted, the converter calls <span -style='font-size:10.0pt;font-family:"Lucida Console","DejaVu Sans Mono"'>FwdLockGlue_GetRandomNumber</span> -to generate a new, unique session key. No two converted files look alike, even -if the original files are the same.</p> - -<p class=MsoBodyText><b>Note:</b> The random bytes cannot come from any bare-minimum -implementation of the C-library <span style='font-size:10.0pt;font-family:"Lucida Console","DejaVu Sans Mono"'>rand</span> -function—they must be cryptographically secure. Otherwise, security will be -compromised.</p> - -<p class=MsoBodyText>The session key is encrypted and stored within the -converted file. Key encryption is performed using <span style='font-size:10.0pt; -font-family:"Lucida Console","DejaVu Sans Mono"'>FwdLockGlue_GetEncryptedKeyLength</span> and <span -style='font-size:10.0pt;font-family:"Lucida Console","DejaVu Sans Mono"'>FwdLockGlue_EncryptKey</span>. -These two functions, together with the corresponding decryption function (<span -style='font-size:10.0pt;font-family:"Lucida Console","DejaVu Sans Mono"'>FwdLockGlue_DecryptKey</span>), -are the integration points where an OEM manufacturer may implement their own -key-encryption scheme.</p> - -<p class=MsoBodyText><b>Note:</b> The key-encryption key must be unique to each -device; this is what makes the files forward lock–protected. Ideally, it should -be derived from secret hardware parameters, but at the very least it should be -persistent from one master reset to the next.</p> - -<div style='margin-bottom:24.0pt;border:solid windowtext 1.0pt;padding:1.0pt 4.0pt 1.0pt 4.0pt; -background:#F2F2F2'> - -<p class=MsoBodyText style='background:#F2F2F2;border: -none;padding:0cm'><b>Note:</b> In the open-source implementation of the <span -style='font-size:10.0pt;font-family:"Lucida Console","DejaVu Sans Mono"'>libfwdlock-common</span> -library, a random key-encryption key is generated and stored in plaintext in -the file system, without being obfuscated in any way (doing so would be futile -since the source code is openly available). This key must be kept secret from -the user, and shouldn’t be possible to extract through backup-and-restore -functionality or the like. OEM manufacturers will probably want to implement a -truly hardware-based device-unique key.</p> - -</div> - -<p class=MsoBodyText style='page-break-after:avoid'><img width=531 height=563 -src="images/image002.gif"></p> - -<p class=MsoCaption style='margin-top:6.0pt;margin-right:0cm;margin-bottom: -12.0pt;margin-left:0cm'><a name="_Ref263085187">Figure </a>2. Converter UC: Convert Data.</p> - -<b><span style='font-size:13.0pt;font-family:"Arial","sans-serif"'><br -clear=all style='page-break-before:always'> -</span></b> - -<h3><a name="_Toc276471427"></a><a name="_Ref263163082">3.1.2<span -style='font:7.0pt "Times New Roman"'> </span>Convert File -(Pull-Mode Conversion)</a></h3> - -<p class=MsoBodyText>Pull-mode conversion is performed by calling <span -style='font-size:10.0pt;font-family:"Lucida Console","DejaVu Sans Mono"'>FwdLockFile_ConvertFile</span> -with the filename, unless there is need for a specialized <span -style='font-size:10.0pt;font-family:"Lucida Console","DejaVu Sans Mono"'>read</span> function, in -which case <span style='font-size:10.0pt;font-family:"Lucida Console","DejaVu Sans Mono"'>FwdLockFile_ConvertOpenFile</span> -should be used directly instead. See Figure 3.</p> - -<p class=MsoBodyText style='margin-bottom:24.0pt'>Internally, <span -style='font-size:10.0pt;font-family:"Lucida Console","DejaVu Sans Mono"'>FwdLockFile_ConvertFile</span> -calls <span style='font-size:10.0pt;font-family:"Lucida Console","DejaVu Sans Mono"'>FwdLockFile_ConvertOpenFile</span>. -The latter then proceeds with the conversion using the push-mode API, acting as -the client in the previous use case; see section 3.1.1.</p> - -<p class=MsoBodyText style='page-break-after:avoid'><img width=531 height=731 -src="images/image003.gif"></p> - -<p class=MsoCaption style='margin-top:6.0pt;margin-right:0cm;margin-bottom: -12.0pt;margin-left:0cm'><a name="_Ref263085208">Figure </a>3. Converter UC: Convert File.</p> - -<b><i><span style='font-size:14.0pt;font-family:"Arial","sans-serif"'><br -clear=all style='page-break-before:always'> -</span></i></b> - -<h2><a name="_Toc276471428">3.2<span style='font:7.0pt "Times New Roman"'> -</span>Decoder</a></h2> - -<p class=MsoBodyText>The decoder API allows the client to do the following:</p> - -<p class=MsoBodyText style='margin-left:36.0pt;text-indent:-18.0pt'>1.<span -style='font:7.0pt "Times New Roman"'> </span>Check -the integrity of an internal Forward Lock file, i.e., detect whether it has -been manipulated in any way; see section 3.2.1.</p> - -<p class=MsoBodyText style='margin-left:36.0pt;text-indent:-18.0pt'>2.<span -style='font:7.0pt "Times New Roman"'> </span>Get -the MIME type of the embedded content (the “original” MIME type before DRM protection -was applied); see section 3.2.2.</p> - -<p class=MsoBodyText style='margin-left:36.0pt;text-indent:-18.0pt'>3.<span -style='font:7.0pt "Times New Roman"'> </span>Decode -the file by random access, i.e., read and seek through it in an arbitrary -manner; see section 3.2.3.</p> - -<p class=MsoBodyText>All subsequent operations on a file first require it to be -opened. Opening a file returns a <i>file descriptor</i>—a handle to be used in -these subsequent operations.</p> - -<p class=MsoBodyText>If the filename is known, an internal Forward Lock file -can be opened using <span style='font-size:10.0pt;font-family:"Lucida Console","DejaVu Sans Mono"'>FwdLockFile_open</span>. -If only the file descriptor of an already open file is available, a decoding -session can instead be initialized using <span style='font-size:10.0pt; -font-family:"Lucida Console","DejaVu Sans Mono"'>FwdLockFile_attach</span>.</p> - -<p class=MsoBodyText>Internally, <span style='font-size:10.0pt;font-family: -"Lucida Console","DejaVu Sans Mono"'>FwdLockFile_open</span> calls <span style='font-size:10.0pt; -font-family:"Lucida Console","DejaVu Sans Mono"'>FwdLockFile_attach</span>. For efficiency -reasons, <span style='font-size:10.0pt;font-family:"Lucida Console","DejaVu Sans Mono"'>FwdLockFile_attach</span> -therefore assumes that the file position is at the beginning of the file when -the function gets called. A client who calls it directly must make sure that -this assumption holds.</p> - -<p class=MsoBodyText>When a file is being attached, the session key stored in -the file during conversion is decrypted using <span style='font-size:10.0pt; -font-family:"Lucida Console","DejaVu Sans Mono"'>FwdLockGlue_GetEncryptedKeyLength</span> and <span -style='font-size:10.0pt;font-family:"Lucida Console","DejaVu Sans Mono"'>FwdLockGlue_DecryptKey</span>, -in order to set up for decoding and integrity checking.</p> - -<p class=MsoBodyText>For just getting the content type, however, retrieving the -session key would strictly speaking not be necessary, so there is an -opportunity here to optimize for that if it proves necessary later.</p> - -<p class=MsoBodyText>Symmetrical to <span style='font-size:10.0pt;font-family: -"Lucida Console","DejaVu Sans Mono"'>FwdLockFile_open</span> and <span style='font-size:10.0pt; -font-family:"Lucida Console","DejaVu Sans Mono"'>FwdLockFile_attach</span>, there are also functions -for closing a file or detaching from it:</p> - -<p class=MsoBodyText style='margin-left:36.0pt;text-indent:-18.0pt'>1.<span -style='font:7.0pt "Times New Roman"'> </span>If -it was opened with <span style='font-size:10.0pt;font-family:"Lucida Console","DejaVu Sans Mono"'>FwdLockFile_open</span> -it should be closed with <span style='font-size:10.0pt;font-family:"Lucida Console","DejaVu Sans Mono"'>FwdLockFile_close</span>.</p> - -<p class=MsoBodyText style='margin-left:36.0pt;text-indent:-18.0pt'>2.<span -style='font:7.0pt "Times New Roman"'> </span>If -it was attached with <span style='font-size:10.0pt;font-family:"Lucida Console","DejaVu Sans Mono"'>FwdLockFile_attach</span> -it should be detached with <span style='font-size:10.0pt;font-family:"Lucida Console","DejaVu Sans Mono"'>FwdLockFile_detach</span>.</p> - -<b><span style='font-size:13.0pt;font-family:"Arial","sans-serif"'><br -clear=all style='page-break-before:always'> -</span></b> - -<h3><a name="_Ref263163099"></a><a name="_Toc276471429">3.2.1<span -style='font:7.0pt "Times New Roman"'> </span>Check Integrity</a></h3> - -<p class=MsoBodyText>There are three methods for checking the integrity of an -internal Forward Lock file, in whole or in part (see also Figure 4):</p> - -<p class=MsoBodyText style='margin-left:36.0pt;text-indent:-18.0pt'>1.<span -style='font:7.0pt "Times New Roman"'> </span><span -style='font-size:10.0pt;font-family:"Lucida Console","DejaVu Sans Mono"'>FwdLockFile_CheckDataIntegrity</span>, -which checks the integrity of the encrypted content data.</p> - -<p class=MsoBodyText style='margin-left:36.0pt;text-indent:-18.0pt'>2.<span -style='font:7.0pt "Times New Roman"'> </span><span -style='font-size:10.0pt;font-family:"Lucida Console","DejaVu Sans Mono"'>FwdLockFile_CheckHeaderIntegrity</span>, -which checks the integrity of the file header, including the content type and -other fields not currently supported but reserved for future use.</p> - -<p class=MsoBodyText style='margin-left:36.0pt;text-indent:-18.0pt'>3.<span -style='font:7.0pt "Times New Roman"'> </span><span -style='font-size:10.0pt;font-family:"Lucida Console","DejaVu Sans Mono"'>FwdLockFile_CheckIntegrity</span>, -which internally calls first <span style='font-size:10.0pt;font-family:"Lucida Console","DejaVu Sans Mono"'>FwdLockFile_CheckHeaderIntegrity</span> -and then <span style='font-size:10.0pt;font-family:"Lucida Console","DejaVu Sans Mono"'>FwdLockFile_CheckDataIntegrity</span>.</p> - -<p class=MsoBodyText style='margin-bottom:24.0pt'><span style='font-size:10.0pt; -font-family:"Lucida Console","DejaVu Sans Mono"'>FwdLockFile_CheckHeaderIntegrity</span> is -generally much faster than <span style='font-size:10.0pt;font-family:"Lucida Console","DejaVu Sans Mono"'>FwdLockFile_CheckDataIntegrity</span>, -whose running time is directly proportional to the size of the file.</p> - -<p class=MsoBodyText style='page-break-after:avoid'><img width=543 height=575 -src="images/image004.gif"></p> - -<p class=MsoCaption style='margin-top:6.0pt;margin-right:0cm;margin-bottom: -12.0pt;margin-left:0cm'><a name="_Ref263163308">Figure </a>4. Decoder UC: Check Integrity.</p> - -<b><span style='font-size:13.0pt;font-family:"Arial","sans-serif"'><br -clear=all style='page-break-before:always'> -</span></b> - -<h3><a name="_Toc276471430"></a><a name="_Ref263163117">3.2.2<span -style='font:7.0pt "Times New Roman"'> </span>Get Content Type</a></h3> - -<p class=MsoBodyText style='margin-bottom:24.0pt'><span style='font-size:10.0pt; -font-family:"Lucida Console","DejaVu Sans Mono"'>FwdLockFile_GetContentType</span> returns a -read-only reference to an ASCII string containing the MIME type of the -embedded content. This reference is valid as long as the file is kept open. -Clients who need access to the content type after closing the file should make -a copy of the string. See Figure 5 below.</p> - -<p class=MsoBodyText style='page-break-after:avoid'><img width=543 height=488 -src="images/image005.gif"></p> - -<p class=MsoCaption style='margin-top:6.0pt;margin-right:0cm;margin-bottom: -12.0pt;margin-left:0cm'><a name="_Ref263163392">Figure </a>5. Decoder UC: Get Content Type.</p> - -<b><span style='font-size:13.0pt;font-family:"Arial","sans-serif"'><br -clear=all style='page-break-before:always'> -</span></b> - -<h3><a name="_Toc276471431"></a><a name="_Ref263163137">3.2.3<span -style='font:7.0pt "Times New Roman"'> </span>Decode File</a></h3> - -<p class=MsoBodyText>After opening an internal Forward Lock file (or attaching -to an already open one), it can be transparently read from as if it were -unencrypted. Any number of calls to read data from the current file position or -set it to a new one (which is what <span style='font-size:10.0pt;font-family: -"Lucida Console","DejaVu Sans Mono"'>lseek</span> does) can be made in any order; this is what we -call <i>random access</i>. See Figure 6.</p> - -<p class=MsoBodyText>The Forward Lock Decoder versions of the <span -style='font-size:10.0pt;font-family:"Lucida Console","DejaVu Sans Mono"'>read</span>, <span -style='font-size:10.0pt;font-family:"Lucida Console","DejaVu Sans Mono"'>lseek</span>, and <span -style='font-size:10.0pt;font-family:"Lucida Console","DejaVu Sans Mono"'>close</span> functions -have the exact same signatures as their POSIX counterparts. So, for example, -the call <span style='font-size:10.0pt;font-family:"Lucida Console","DejaVu Sans Mono"'>FwdLockFile_lseek(fd, -0, SEEK_END)</span> returns the size of the embedded content data, i.e., the -size of the original file before DRM protection.</p> - -<p class=MsoBodyText style='margin-bottom:24.0pt'>Moreover, <span -style='font-size:10.0pt;font-family:"Lucida Console","DejaVu Sans Mono"'>FwdLockFile_open</span> -is like regular POSIX <span style='font-size:10.0pt;font-family:"Lucida Console","DejaVu Sans Mono"'>open</span> -except it takes only the filename as a parameter—access is always read-only.</p> - -<p class=MsoBodyText style='page-break-after:avoid'><img width=543 height=522 -src="images/image006.gif"></p> - -<p class=MsoCaption style='margin-top:6.0pt;margin-right:0cm;margin-bottom: -12.0pt;margin-left:0cm'><a name="_Ref263166303">Figure </a>6. Decoder UC: Decode File.</p> - -<b><span style='font-size:16.0pt;font-family:"Arial","sans-serif"'><br -clear=all style='page-break-before:always'> -</span></b> - -<h1><a name="_Toc276471432">4<span style='font:7.0pt "Times New Roman"'> -</span>Definition of the Internal Forward Lock File Format</a></h1> - -<p class=MsoBodyText style='margin-bottom:12.0pt'>The inner structure of an internal -Forward Lock file is defined in Table 1 below.</p> - -<table class=MsoNormalTable border=1 cellspacing=0 cellpadding=0 - style='border-collapse:collapse;border:none'> - <tr> - <td width=111 valign=top style='width:83.4pt;border:solid windowtext 1.0pt; - padding:0cm 5.4pt 0cm 5.4pt'> - <p class=MsoNormal style='page-break-after:avoid'><b>Offset [bytes]</b></p> - </td> - <td width=96 valign=top style='width:72.0pt;border:solid windowtext 1.0pt; - border-left:none;padding:0cm 5.4pt 0cm 5.4pt'> - <p class=MsoNormal style='page-break-after:avoid'><b>Size [bytes]</b></p> - </td> - <td width=361 valign=top style='width:270.85pt;border:solid windowtext 1.0pt; - border-left:none;padding:0cm 5.4pt 0cm 5.4pt'> - <p class=MsoNormal style='page-break-after:avoid'><b>Description</b></p> - </td> - </tr> - <tr> - <td width=111 valign=top style='width:83.4pt;border:solid windowtext 1.0pt; - border-top:none;padding:0cm 5.4pt 0cm 5.4pt'> - <p class=MsoNormal style='page-break-after:avoid'>0</p> - </td> - <td width=96 valign=top style='width:72.0pt;border-top:none;border-left:none; - border-bottom:solid windowtext 1.0pt;border-right:solid windowtext 1.0pt; - padding:0cm 5.4pt 0cm 5.4pt'> - <p class=MsoNormal style='page-break-after:avoid'>4</p> - </td> - <td width=361 valign=top style='width:270.85pt;border-top:none;border-left: - none;border-bottom:solid windowtext 1.0pt;border-right:solid windowtext 1.0pt; - padding:0cm 5.4pt 0cm 5.4pt'> - <p class=MsoNormal style='page-break-after:avoid'>The file signature (so-called - <i>magic number</i>): a four-character code consisting of the letters - F-W-L-K.</p> - </td> - </tr> - <tr> - <td width=111 valign=top style='width:83.4pt;border:solid windowtext 1.0pt; - border-top:none;padding:0cm 5.4pt 0cm 5.4pt'> - <p class=MsoNormal style='page-break-after:avoid'>4</p> - </td> - <td width=96 valign=top style='width:72.0pt;border-top:none;border-left:none; - border-bottom:solid windowtext 1.0pt;border-right:solid windowtext 1.0pt; - padding:0cm 5.4pt 0cm 5.4pt'> - <p class=MsoNormal style='page-break-after:avoid'>1</p> - </td> - <td width=361 valign=top style='width:270.85pt;border-top:none;border-left: - none;border-bottom:solid windowtext 1.0pt;border-right:solid windowtext 1.0pt; - padding:0cm 5.4pt 0cm 5.4pt'> - <p class=MsoNormal style='page-break-after:avoid'>Version number (0 for the - first version).</p> - </td> - </tr> - <tr> - <td width=111 valign=top style='width:83.4pt;border:solid windowtext 1.0pt; - border-top:none;padding:0cm 5.4pt 0cm 5.4pt'> - <p class=MsoNormal style='page-break-after:avoid'>5</p> - </td> - <td width=96 valign=top style='width:72.0pt;border-top:none;border-left:none; - border-bottom:solid windowtext 1.0pt;border-right:solid windowtext 1.0pt; - padding:0cm 5.4pt 0cm 5.4pt'> - <p class=MsoNormal style='page-break-after:avoid'>1</p> - </td> - <td width=361 valign=top style='width:270.85pt;border-top:none;border-left: - none;border-bottom:solid windowtext 1.0pt;border-right:solid windowtext 1.0pt; - padding:0cm 5.4pt 0cm 5.4pt'> - <p class=MsoNormal style='page-break-after:avoid'>Indicates the subformat:</p> - <p class=MsoNormal style='page-break-after:avoid'><i>0x00 Forward Lock</i></p> - <p class=MsoNormal style='page-break-after:avoid'><i>0x01 Combined Delivery</i></p> - </td> - </tr> - <tr> - <td width=111 valign=top style='width:83.4pt;border:solid windowtext 1.0pt; - border-top:none;padding:0cm 5.4pt 0cm 5.4pt'> - <p class=MsoNormal style='page-break-after:avoid'>6</p> - </td> - <td width=96 valign=top style='width:72.0pt;border-top:none;border-left:none; - border-bottom:solid windowtext 1.0pt;border-right:solid windowtext 1.0pt; - padding:0cm 5.4pt 0cm 5.4pt'> - <p class=MsoNormal style='page-break-after:avoid'>1</p> - </td> - <td width=361 valign=top style='width:270.85pt;border-top:none;border-left: - none;border-bottom:solid windowtext 1.0pt;border-right:solid windowtext 1.0pt; - padding:0cm 5.4pt 0cm 5.4pt'> - <p class=MsoNormal style='page-break-after:avoid'>Usage restriction flags (prohibitions - against usage as ringtone or as wallpaper and screen saver). Also indicates - if the file is bound to a specific SIM card.</p> - <p class=MsoNormal style='page-break-after:avoid'><i>0x00 No usage - restrictions</i></p> - <p class=MsoNormal style='page-break-after:avoid'><i>0x01 Ringtone usage - prohibited</i></p> - <p class=MsoNormal style='page-break-after:avoid'><i>0x02 Screen usage - prohibited</i></p> - <p class=MsoNormal style='page-break-after:avoid'><i>0x80 Bound to SIM</i></p> - <p class=MsoNormal style='page-break-after:avoid'>(Any number of these may be - OR-ed together.)</p> - </td> - </tr> - <tr> - <td width=111 valign=top style='width:83.4pt;border:solid windowtext 1.0pt; - border-top:none;padding:0cm 5.4pt 0cm 5.4pt'> - <p class=MsoNormal style='page-break-after:avoid'>7</p> - </td> - <td width=96 valign=top style='width:72.0pt;border-top:none;border-left:none; - border-bottom:solid windowtext 1.0pt;border-right:solid windowtext 1.0pt; - padding:0cm 5.4pt 0cm 5.4pt'> - <p class=MsoNormal style='page-break-after:avoid'>1</p> - </td> - <td width=361 valign=top style='width:270.85pt;border-top:none;border-left: - none;border-bottom:solid windowtext 1.0pt;border-right:solid windowtext 1.0pt; - padding:0cm 5.4pt 0cm 5.4pt'> - <p class=MsoNormal style='page-break-after:avoid'>Length of the MIME content - type (<i>k</i>).</p> - </td> - </tr> - <tr> - <td width=111 valign=top style='width:83.4pt;border:solid windowtext 1.0pt; - border-top:none;padding:0cm 5.4pt 0cm 5.4pt'> - <p class=MsoNormal style='page-break-after:avoid'>8</p> - </td> - <td width=96 valign=top style='width:72.0pt;border-top:none;border-left:none; - border-bottom:solid windowtext 1.0pt;border-right:solid windowtext 1.0pt; - padding:0cm 5.4pt 0cm 5.4pt'> - <p class=MsoNormal style='page-break-after:avoid'><i>k</i></p> - </td> - <td width=361 valign=top style='width:270.85pt;border-top:none;border-left: - none;border-bottom:solid windowtext 1.0pt;border-right:solid windowtext 1.0pt; - padding:0cm 5.4pt 0cm 5.4pt'> - <p class=MsoNormal style='page-break-after:avoid'>The MIME content type - (ASCII-encoded without null-character termination).</p> - </td> - </tr> - <tr> - <td width=111 valign=top style='width:83.4pt;border:solid windowtext 1.0pt; - border-top:none;padding:0cm 5.4pt 0cm 5.4pt'> - <p class=MsoNormal style='page-break-after:avoid'>8+<i>k</i></p> - </td> - <td width=96 valign=top style='width:72.0pt;border-top:none;border-left:none; - border-bottom:solid windowtext 1.0pt;border-right:solid windowtext 1.0pt; - padding:0cm 5.4pt 0cm 5.4pt'> - <p class=MsoNormal style='page-break-after:avoid'><i>l </i>= 0 or 16</p> - </td> - <td width=361 valign=top style='width:270.85pt;border-top:none;border-left: - none;border-bottom:solid windowtext 1.0pt;border-right:solid windowtext 1.0pt; - padding:0cm 5.4pt 0cm 5.4pt'> - <p class=MsoNormal style='page-break-after:avoid'>If the subformat is - Combined Delivery, this field contains the auto-generated content ID (16 bytes). - If not, this field is zero-size.</p> - </td> - </tr> - <tr> - <td width=111 valign=top style='width:83.4pt;border:solid windowtext 1.0pt; - border-top:none;padding:0cm 5.4pt 0cm 5.4pt'> - <p class=MsoNormal style='page-break-after:avoid'>8+<i>k</i>+<i>l</i></p> - </td> - <td width=96 valign=top style='width:72.0pt;border-top:none;border-left:none; - border-bottom:solid windowtext 1.0pt;border-right:solid windowtext 1.0pt; - padding:0cm 5.4pt 0cm 5.4pt'> - <p class=MsoNormal style='page-break-after:avoid'><i>m </i>= 0 or 9</p> - </td> - <td width=361 valign=top style='width:270.85pt;border-top:none;border-left: - none;border-bottom:solid windowtext 1.0pt;border-right:solid windowtext 1.0pt; - padding:0cm 5.4pt 0cm 5.4pt'> - <p class=MsoNormal style='page-break-after:avoid'>If the file is bound to a - specific SIM card, this field contains the 9-byte packed IMSI number. If not, - this field is zero-size.</p> - </td> - </tr> - <tr> - <td width=111 valign=top style='width:83.4pt;border:solid windowtext 1.0pt; - border-top:none;padding:0cm 5.4pt 0cm 5.4pt'> - <p class=MsoNormal style='page-break-after:avoid'>8+<i>k</i>+<i>l</i>+<i>m</i></p> - </td> - <td width=96 valign=top style='width:72.0pt;border-top:none;border-left:none; - border-bottom:solid windowtext 1.0pt;border-right:solid windowtext 1.0pt; - padding:0cm 5.4pt 0cm 5.4pt'> - <p class=MsoNormal style='page-break-after:avoid'><i>n</i> ≥ 16</p> - </td> - <td width=361 valign=top style='width:270.85pt;border-top:none;border-left: - none;border-bottom:solid windowtext 1.0pt;border-right:solid windowtext 1.0pt; - padding:0cm 5.4pt 0cm 5.4pt'> - <p class=MsoNormal style='page-break-after:avoid'>The encrypted session key, the - first sixteen bytes of which are also used as the CTR-mode <i>nonce</i> (similar - to the CBC-mode <i>initialization vector</i>).</p> - </td> - </tr> - <tr> - <td width=111 valign=top style='width:83.4pt;border:solid windowtext 1.0pt; - border-top:none;padding:0cm 5.4pt 0cm 5.4pt'> - <p class=MsoNormal style='page-break-after:avoid'>8+<i>k</i>+<i>l</i>+<i>m</i>+<i>n</i></p> - </td> - <td width=96 valign=top style='width:72.0pt;border-top:none;border-left:none; - border-bottom:solid windowtext 1.0pt;border-right:solid windowtext 1.0pt; - padding:0cm 5.4pt 0cm 5.4pt'> - <p class=MsoNormal style='page-break-after:avoid'>20</p> - </td> - <td width=361 valign=top style='width:270.85pt;border-top:none;border-left: - none;border-bottom:solid windowtext 1.0pt;border-right:solid windowtext 1.0pt; - padding:0cm 5.4pt 0cm 5.4pt'> - <p class=MsoNormal style='page-break-after:avoid'>Data signature—the SHA-1 - HMAC of the encrypted content data.</p> - </td> - </tr> - <tr> - <td width=111 valign=top style='width:83.4pt;border:solid windowtext 1.0pt; - border-top:none;padding:0cm 5.4pt 0cm 5.4pt'> - <p class=MsoNormal style='page-break-after:avoid'>28+<i>k</i>+<i>l</i>+<i>m</i>+<i>n</i></p> - </td> - <td width=96 valign=top style='width:72.0pt;border-top:none;border-left:none; - border-bottom:solid windowtext 1.0pt;border-right:solid windowtext 1.0pt; - padding:0cm 5.4pt 0cm 5.4pt'> - <p class=MsoNormal style='page-break-after:avoid'>20</p> - </td> - <td width=361 valign=top style='width:270.85pt;border-top:none;border-left: - none;border-bottom:solid windowtext 1.0pt;border-right:solid windowtext 1.0pt; - padding:0cm 5.4pt 0cm 5.4pt'> - <p class=MsoNormal style='page-break-after:avoid'>Header signature—the SHA-1 - HMAC of all the fields above, including the encrypted session key and data - signature.</p> - </td> - </tr> - <tr> - <td width=111 valign=top style='width:83.4pt;border:solid windowtext 1.0pt; - border-top:none;padding:0cm 5.4pt 0cm 5.4pt'> - <p class=MsoNormal style='page-break-after:avoid'>48+<i>k</i>+<i>l</i>+<i>m</i>+<i>n</i></p> - </td> - <td width=96 valign=top style='width:72.0pt;border-top:none;border-left:none; - border-bottom:solid windowtext 1.0pt;border-right:solid windowtext 1.0pt; - padding:0cm 5.4pt 0cm 5.4pt'> - <p class=MsoNormal style='page-break-after:avoid'><i><to the end of the - file></i></p> - </td> - <td width=361 valign=top style='width:270.85pt;border-top:none;border-left: - none;border-bottom:solid windowtext 1.0pt;border-right:solid windowtext 1.0pt; - padding:0cm 5.4pt 0cm 5.4pt'> - <p class=MsoNormal style='page-break-after:avoid'>The content data encrypted - using 128-bit AES in CTR mode.</p> - </td> - </tr> -</table> - -<p class=MsoCaption style='margin-top:6.0pt;margin-right:0cm;margin-bottom: -12.0pt;margin-left:0cm;page-break-after:avoid'><a name="_Ref151269206">Table </a>1. Definition of the fields of an internal Forward Lock file.</p> - -<p class=MsoBodyText>As of now, neither Combined Delivery nor usage -restrictions (including SIM binding) are supported. These fields are reserved -for future use.</p> - -<h2><a name="_Toc276471433">4.1<span style='font:7.0pt "Times New Roman"'> -</span>Key Derivation</a></h2> - -<p class=MsoBodyText>The session key consists of sixteen bytes fetched from a -cryptographically secure random number generator. From the session key, two -separate keys are derived: one used for encryption, the other for signing.</p> - -<p class=MsoBodyText>The encryption key is the output from encrypting the -16-byte all-zero input block {0, 0, …, 0} using 128-bit AES with the random session -key as the key. The signing key is the output from encrypting the 16-byte input -block {1, 0, …, 0} the same way. The keys so derived will be cryptographically -independent from each other.</p> - -<p class=MsoBodyText>The session key is encrypted using a hardware-dependent -key-encryption key unique to each device. The encrypted session key is stored -inside the file, and its first sixteen bytes are also used as the <i>nonce</i> -for the CTR-mode encryption of the content data.</p> - -<h2><a name="_Toc276471434">4.2<span style='font:7.0pt "Times New Roman"'> -</span>Calculation of the Counters</a></h2> - -<p class=MsoBodyText>Using CTR (“counter”) mode, a block cipher such as AES can -be turned into a stream cipher. The process of encryption and decryption is -well defined in [1], except for the specifics of the calculation of the -counters. For the internal Forward Lock file format, the counters are -calculated as follows:</p> - -<p class=MsoBodyText style='margin-left:36.0pt;text-indent:-18.0pt'>1.<span -style='font:7.0pt "Times New Roman"'> </span>The -nonce is interpreted as a 128-bit unsigned integer in little-endian format.</p> - -<p class=MsoBodyText style='margin-left:36.0pt;text-indent:-18.0pt'>2.<span -style='font:7.0pt "Times New Roman"'> </span>The -zero-based block sequence number (also a little-endian unsigned integer) is -added modulo 2<sup>128</sup> to the nonce to produce the counter for a given -block.</p> - -<h1><a name="_Toc276471435">5<span style='font:7.0pt "Times New Roman"'> -</span>Unit Test Cases</a></h1> - -<p class=MsoBodyText>Unit test cases for the converter and decoder come in two -varieties:</p> - -<p class=MsoBodyText style='margin-left:36.0pt;text-indent:-18.0pt'>1.<span -style='font:7.0pt "Times New Roman"'> </span><i>Black-box</i> -test cases aim to verify that you get sensible results from malformed or -“tricky” input data.</p> - -<p class=MsoBodyText style='margin-left:36.0pt;text-indent:-18.0pt'>2.<span -style='font:7.0pt "Times New Roman"'> </span><i>White-box</i> -test cases aim to maximize code coverage using knowledge of code internals.</p> - -<p class=MsoBodyText>The black-box test cases are dependent on a specifically -designed set of input files found in the <span style='font-size:10.0pt; -font-family:"Lucida Console","DejaVu Sans Mono"'>forward-lock/internal-format/test/res</span> -directory in the repository. For ‘tests’ variants of the software, these input -files will be automatically installed in the file system image during build.</p> - -<p class=MsoBodyText>Run the test cases from the ADB shell command line as -follows:</p> - -<p class=MsoNormal style='margin-top:0cm;margin-right:0cm;margin-bottom:6.0pt; -margin-left:21.55pt'><span style='font-size:10.0pt;font-family:"Lucida Console","DejaVu Sans Mono"'># -gtest_fwdlock</span></p> - -<p class=MsoBodyText>If all black-box but no white-box test cases fail, the -input files probably can’t be found in the working directory.</p> - -<h1><a name="_Toc276471436">6<span style='font:7.0pt "Times New Roman"'> -</span>References</a></h1> - -<p class=MsoBodyText style='margin-left:28.9pt;text-indent:-28.9pt'>[1]<span -style='font:7.0pt "Times New Roman"'> -</span><a -href="http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf">Dworkin, -Morris: “Recommendation for Block Cipher Modes of Operation—Methods and -Techniques,” NIST Special Publication 800-38A, December 2001.</a><a -name="_Ref151269073"></a></p> - -</div> - -</body> - -</html> diff --git a/drm/libdrmframework/plugins/forward-lock/internal-format/doc/images/image001.gif b/drm/libdrmframework/plugins/forward-lock/internal-format/doc/images/image001.gif Binary files differdeleted file mode 100644 index ee94513..0000000 --- a/drm/libdrmframework/plugins/forward-lock/internal-format/doc/images/image001.gif +++ /dev/null diff --git a/drm/libdrmframework/plugins/forward-lock/internal-format/doc/images/image002.gif b/drm/libdrmframework/plugins/forward-lock/internal-format/doc/images/image002.gif Binary files differdeleted file mode 100644 index 8c12f46..0000000 --- a/drm/libdrmframework/plugins/forward-lock/internal-format/doc/images/image002.gif +++ /dev/null diff --git a/drm/libdrmframework/plugins/forward-lock/internal-format/doc/images/image003.gif b/drm/libdrmframework/plugins/forward-lock/internal-format/doc/images/image003.gif Binary files differdeleted file mode 100644 index 9e019ca..0000000 --- a/drm/libdrmframework/plugins/forward-lock/internal-format/doc/images/image003.gif +++ /dev/null diff --git a/drm/libdrmframework/plugins/forward-lock/internal-format/doc/images/image004.gif b/drm/libdrmframework/plugins/forward-lock/internal-format/doc/images/image004.gif Binary files differdeleted file mode 100644 index cae1d01..0000000 --- a/drm/libdrmframework/plugins/forward-lock/internal-format/doc/images/image004.gif +++ /dev/null diff --git a/drm/libdrmframework/plugins/forward-lock/internal-format/doc/images/image005.gif b/drm/libdrmframework/plugins/forward-lock/internal-format/doc/images/image005.gif Binary files differdeleted file mode 100644 index 0d87be9..0000000 --- a/drm/libdrmframework/plugins/forward-lock/internal-format/doc/images/image005.gif +++ /dev/null diff --git a/drm/libdrmframework/plugins/forward-lock/internal-format/doc/images/image006.gif b/drm/libdrmframework/plugins/forward-lock/internal-format/doc/images/image006.gif Binary files differdeleted file mode 100644 index 9445b6b..0000000 --- a/drm/libdrmframework/plugins/forward-lock/internal-format/doc/images/image006.gif +++ /dev/null |