Merge "Initial OMA DRM forward lock contribution"
This commit is contained in:
16
drm/libdrmframework/plugins/common/Android.mk
Normal file
16
drm/libdrmframework/plugins/common/Android.mk
Normal file
@@ -0,0 +1,16 @@
|
||||
#
|
||||
# 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)
|
||||
52
drm/libdrmframework/plugins/common/util/Android.mk
Normal file
52
drm/libdrmframework/plugins/common/util/Android.mk
Normal file
@@ -0,0 +1,52 @@
|
||||
#
|
||||
# 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 := \
|
||||
src/MimeTypeUtil.cpp
|
||||
|
||||
LOCAL_MODULE := libdrmutility
|
||||
|
||||
LOCAL_SHARED_LIBRARIES := \
|
||||
libutils \
|
||||
libdl \
|
||||
libdvm \
|
||||
libandroid_runtime \
|
||||
libnativehelper \
|
||||
liblog
|
||||
|
||||
|
||||
base := frameworks/base
|
||||
|
||||
LOCAL_C_INCLUDES += \
|
||||
$(JNI_H_INCLUDE) \
|
||||
$(base)/include \
|
||||
$(base)/include/drm \
|
||||
$(base)/include/drm/plugins \
|
||||
$(LOCAL_PATH)/include
|
||||
|
||||
|
||||
ifneq ($(TARGET_BUILD_VARIANT),user)
|
||||
LOCAL_C_INCLUDES += \
|
||||
$(LOCAL_PATH)/tools
|
||||
|
||||
endif
|
||||
|
||||
LOCAL_MODULE_TAGS := optional
|
||||
|
||||
include $(BUILD_STATIC_LIBRARY)
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* 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 __MIMETYPEUTIL_H__
|
||||
#define __MIMETYPEUTIL_H__
|
||||
|
||||
#include <utils/String8.h>
|
||||
|
||||
namespace android {
|
||||
|
||||
class MimeTypeUtil {
|
||||
|
||||
public:
|
||||
|
||||
MimeTypeUtil() {}
|
||||
|
||||
virtual ~MimeTypeUtil() {}
|
||||
|
||||
/**
|
||||
* May convert the mimetype if there is a well known
|
||||
* replacement mimetype otherwise the original mimetype
|
||||
* is returned.
|
||||
*
|
||||
* @param mimeType - mimetype in lower case to convert.
|
||||
*
|
||||
* @return mimetype or null.
|
||||
*/
|
||||
static String8 convertMimeType(String8& mimeType);
|
||||
|
||||
};
|
||||
};
|
||||
|
||||
#endif /* __MIMETYPEUTIL_H__ */
|
||||
155
drm/libdrmframework/plugins/common/util/include/SessionMap.h
Normal file
155
drm/libdrmframework/plugins/common/util/include/SessionMap.h
Normal file
@@ -0,0 +1,155 @@
|
||||
/*
|
||||
* 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 __SESSIONMAP_H__
|
||||
#define __SESSIONMAP_H__
|
||||
|
||||
#include <utils/KeyedVector.h>
|
||||
|
||||
namespace android {
|
||||
|
||||
/**
|
||||
* A wrapper template class for handling DRM Engine sessions.
|
||||
*/
|
||||
template <typename NODE>
|
||||
class SessionMap {
|
||||
|
||||
public:
|
||||
KeyedVector<int, NODE> map;
|
||||
|
||||
SessionMap() {}
|
||||
|
||||
virtual ~SessionMap() {
|
||||
destroyMap();
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a new value in the session map table. It expects memory to be allocated already
|
||||
* for the session object
|
||||
*
|
||||
* @param key - key or Session ID
|
||||
* @param value - session object to add
|
||||
*
|
||||
* @return boolean result of adding value. returns false if key is already exist.
|
||||
*/
|
||||
bool addValue(int key, NODE value) {
|
||||
bool result = false;
|
||||
|
||||
if (!isCreated(key)) {
|
||||
map.add(key, value);
|
||||
result = true;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* returns the session object by the key
|
||||
*
|
||||
* @param key - key or Session ID
|
||||
*
|
||||
* @return session object as per the key
|
||||
*/
|
||||
NODE getValue(int key) {
|
||||
NODE value = NULL;
|
||||
|
||||
if (isCreated(key)) {
|
||||
value = (NODE) map.valueFor(key);
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* returns the number of objects in the session map table
|
||||
*
|
||||
* @return count of number of session objects.
|
||||
*/
|
||||
int getSize() {
|
||||
return map.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* returns the session object by the index in the session map table
|
||||
*
|
||||
* @param index - index of the value required
|
||||
*
|
||||
* @return session object as per the index
|
||||
*/
|
||||
NODE getValueAt(unsigned int index) {
|
||||
NODE value = NULL;
|
||||
|
||||
if (map.size() > index) {
|
||||
value = map.valueAt(index);
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* deletes the object from session map. It also frees up memory for the session object.
|
||||
*
|
||||
* @param key - key of the value to be deleted
|
||||
*
|
||||
*/
|
||||
void removeValue(int key) {
|
||||
deleteValue(getValue(key));
|
||||
map.removeItem(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* decides if session is already created.
|
||||
*
|
||||
* @param key - key of the value for the session
|
||||
*
|
||||
* @return boolean result of whether session is created
|
||||
*/
|
||||
bool isCreated(int key) {
|
||||
return (0 <= map.indexOfKey(key));
|
||||
}
|
||||
|
||||
/**
|
||||
* empty the entire session table. It releases all the memory for session objects.
|
||||
*/
|
||||
void destroyMap() {
|
||||
int size = map.size();
|
||||
int i = 0;
|
||||
|
||||
for (i = 0; i < size; i++) {
|
||||
deleteValue(map.valueAt(i));
|
||||
}
|
||||
|
||||
map.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* free up the memory for the session object.
|
||||
* Make sure if any reference to the session object anywhere, otherwise it will be a
|
||||
* dangle pointer after this call.
|
||||
*
|
||||
* @param value - session object to free
|
||||
*
|
||||
*/
|
||||
void deleteValue(NODE value) {
|
||||
delete value;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
#endif /* __SESSIONMAP_H__ */
|
||||
154
drm/libdrmframework/plugins/common/util/src/MimeTypeUtil.cpp
Normal file
154
drm/libdrmframework/plugins/common/util/src/MimeTypeUtil.cpp
Normal file
@@ -0,0 +1,154 @@
|
||||
/*
|
||||
* 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 <MimeTypeUtil.h>
|
||||
#include <utils/Log.h>
|
||||
|
||||
namespace android {
|
||||
|
||||
#undef LOG_TAG
|
||||
#define LOG_TAG "MimeTypeUtil"
|
||||
|
||||
enum {
|
||||
MIMETYPE_AUDIO = 0,
|
||||
MIMETYPE_APPLICATION = 1,
|
||||
MIMETYPE_IMAGE = 2,
|
||||
MIMETYPE_VIDEO = 3,
|
||||
MIMETYPE_LAST = -1,
|
||||
};
|
||||
|
||||
struct MimeGroup{
|
||||
int type; // Audio, video,.. use the enum values
|
||||
const char* pGroup; // "audio/", "video/",.. should contain the last "/"
|
||||
int size; // Number of bytes. e.g. "audio/" = 6 bytes
|
||||
};
|
||||
|
||||
struct MimeTypeList{
|
||||
int type;
|
||||
const char* pMimeExt; // Everything after the '/' e.g. audio/x-mpeg -> "x-mpeg"
|
||||
int size; // Number of bytes. e.g. "x-mpeg" = 6 bytes
|
||||
const char* pMimeType; // Mimetype that should be returned
|
||||
};
|
||||
|
||||
|
||||
// Known mimetypes by android
|
||||
static const char mime_type_audio_mpeg[] = "audio/mpeg";
|
||||
static const char mime_type_audio_3gpp[] = "audio/3gpp";
|
||||
static const char mime_type_audio_amr[] = "audio/amr-wb";
|
||||
static const char mime_type_audio_aac[] = "audio/mp4a-latm";
|
||||
static const char mime_type_audio_wav[] = "audio/wav";
|
||||
|
||||
static const char mime_type_video_mpeg4[] = "video/mpeg4";
|
||||
static const char mime_type_video_3gpp[] = "video/3gpp";
|
||||
|
||||
// Known mimetype groups
|
||||
static const char mime_group_audio[] = "audio/";
|
||||
static const char mime_group_application[] = "application/";
|
||||
static const char mime_group_image[] = "image/";
|
||||
static const char mime_group_video[] = "video/";
|
||||
|
||||
static struct MimeGroup mimeGroup[] = {
|
||||
{MIMETYPE_AUDIO, mime_group_audio, sizeof(mime_group_audio)-1},
|
||||
{MIMETYPE_APPLICATION, mime_group_application, sizeof(mime_group_application)-1},
|
||||
{MIMETYPE_IMAGE, mime_group_image, sizeof(mime_group_image)-1},
|
||||
{MIMETYPE_VIDEO, mime_group_video, sizeof(mime_group_video)-1},
|
||||
{MIMETYPE_LAST, NULL, 0} // Must be last entry
|
||||
};
|
||||
|
||||
// List of all mimetypes that should be converted.
|
||||
static struct MimeTypeList mimeTypeList[] = {
|
||||
// Mp3 mime types
|
||||
{MIMETYPE_AUDIO, "mp3", sizeof("mp3")-1, mime_type_audio_mpeg},
|
||||
{MIMETYPE_AUDIO, "x-mpeg", sizeof("x-mpeg")-1, mime_type_audio_mpeg},
|
||||
{MIMETYPE_AUDIO, "x-mp3", sizeof("x-mp3")-1, mime_type_audio_mpeg},
|
||||
{MIMETYPE_AUDIO, "mpg", sizeof("mpg")-1, mime_type_audio_mpeg},
|
||||
{MIMETYPE_AUDIO, "mpg3", sizeof("mpg")-1, mime_type_audio_mpeg},
|
||||
{MIMETYPE_AUDIO, "x-mpg", sizeof("x-mpg")-1, mime_type_audio_mpeg},
|
||||
{MIMETYPE_AUDIO, "x-mpegaudio", sizeof("x-mpegaudio")-1, mime_type_audio_mpeg},
|
||||
|
||||
// 3gpp audio mime types
|
||||
{MIMETYPE_AUDIO, "3gp", sizeof("3gp")-1, mime_type_audio_3gpp},
|
||||
|
||||
// Amr audio mime types
|
||||
{MIMETYPE_AUDIO, "amr", sizeof("amr")-1, mime_type_audio_amr},
|
||||
|
||||
// Aac audio mime types
|
||||
{MIMETYPE_AUDIO, "aac", sizeof("aac")-1, mime_type_audio_aac},
|
||||
|
||||
// Wav audio mime types
|
||||
{MIMETYPE_AUDIO, "x-wav", sizeof("x-wav")-1, mime_type_audio_wav},
|
||||
|
||||
// Mpeg4 video mime types
|
||||
{MIMETYPE_VIDEO, "mpg4", sizeof("mpg4")-1, mime_type_video_mpeg4},
|
||||
{MIMETYPE_VIDEO, "mp4v-es", sizeof("mp4v-es")-1, mime_type_video_mpeg4},
|
||||
|
||||
// 3gpp video mime types
|
||||
{MIMETYPE_VIDEO, "3gp", sizeof("3gp")-1, mime_type_video_3gpp},
|
||||
|
||||
// Must be last entry
|
||||
{MIMETYPE_LAST, NULL, 0, NULL}
|
||||
};
|
||||
|
||||
/**
|
||||
* May convert the mimetype if there is a well known
|
||||
* replacement mimetype otherwise the original mimetype
|
||||
* is returned.
|
||||
*
|
||||
* @param mimeType - mimetype in lower case to convert.
|
||||
*
|
||||
* @return mimetype or null.
|
||||
*/
|
||||
String8 MimeTypeUtil::convertMimeType(String8& mimeType) {
|
||||
String8 result = mimeType;
|
||||
const char* pTmp;
|
||||
const char* pMimeType;
|
||||
struct MimeGroup* pGroup;
|
||||
struct MimeTypeList* pMimeItem;
|
||||
int len;
|
||||
|
||||
pMimeType = mimeType.string();
|
||||
if (NULL != pMimeType) {
|
||||
/* Check which group the mimetype is */
|
||||
pGroup = mimeGroup;
|
||||
|
||||
while (MIMETYPE_LAST != pGroup->type) {
|
||||
if (0 == strncmp(pMimeType, pGroup->pGroup, pGroup->size)) {
|
||||
break;
|
||||
}
|
||||
pGroup++;
|
||||
}
|
||||
|
||||
/* Go through the mimetype list. Only check items of the correct group */
|
||||
if (MIMETYPE_LAST != pGroup->type) {
|
||||
pMimeItem = mimeTypeList;
|
||||
len = strlen (pMimeType+pGroup->size);
|
||||
|
||||
while (MIMETYPE_LAST != pMimeItem->type) {
|
||||
if ((len == pMimeItem->size) &&
|
||||
(0 == strcmp(pMimeType+pGroup->size, pMimeItem->pMimeExt))) {
|
||||
result = String8(pMimeItem->pMimeType);
|
||||
break;
|
||||
}
|
||||
pMimeItem++;
|
||||
}
|
||||
}
|
||||
LOGI("convertMimeType got mimetype %s, converted into mimetype %s",
|
||||
pMimeType, result.string());
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
};
|
||||
16
drm/libdrmframework/plugins/forward-lock/Android.mk
Normal file
16
drm/libdrmframework/plugins/forward-lock/Android.mk
Normal file
@@ -0,0 +1,16 @@
|
||||
#
|
||||
# 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)
|
||||
@@ -0,0 +1,67 @@
|
||||
#
|
||||
# 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)
|
||||
|
||||
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_PRELINK_MODULE := false
|
||||
|
||||
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/plugins/native
|
||||
|
||||
LOCAL_MODULE_TAGS := optional
|
||||
|
||||
include $(BUILD_SHARED_LIBRARY)
|
||||
@@ -0,0 +1,559 @@
|
||||
/*
|
||||
* 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:
|
||||
|
||||
/**
|
||||
* 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__ */
|
||||
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* 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 __FWDLOCKENGINECONST_H__
|
||||
#define __FWDLOCKENGINECONST_H__
|
||||
|
||||
namespace android {
|
||||
|
||||
/**
|
||||
* Constants for forward Lock Engine used for exposing engine's capabilities.
|
||||
*/
|
||||
#define FWDLOCK_EXTENSION_FL ("FL")
|
||||
#define FWDLOCK_DOTEXTENSION_FL (".fl")
|
||||
#define FWDLOCK_MIMETYPE_FL ("application/x-android-drm-fl")
|
||||
|
||||
#define FWDLOCK_EXTENSION_DM ("DM")
|
||||
#define FWDLOCK_DOTEXTENSION_DM (".dm")
|
||||
#define FWDLOCK_MIMETYPE_DM ("application/vnd.oma.drm.message")
|
||||
|
||||
#define FWDLOCK_DESCRIPTION ("OMA V1 Forward Lock")
|
||||
|
||||
};
|
||||
|
||||
#endif /* __FWDLOCKENGINECONST_H__ */
|
||||
@@ -0,0 +1,628 @@
|
||||
/*
|
||||
* 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 "FwdLockEngineConst.h"
|
||||
#include "MimeTypeUtil.h"
|
||||
|
||||
#undef LOG_TAG
|
||||
#define LOG_TAG "FwdLockEngine"
|
||||
|
||||
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() {
|
||||
LOGD("FwdLockEngine Construction");
|
||||
}
|
||||
|
||||
FwdLockEngine::~FwdLockEngine() {
|
||||
LOGD("FwdLockEngine Destruction");
|
||||
|
||||
convertSessionMap.destroyMap();
|
||||
decodeSessionMap.destroyMap();
|
||||
}
|
||||
|
||||
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:
|
||||
LOGD("FwdLockEngine getConvertedStatus: file conversion Error %d. " \
|
||||
"Returning STATUS_INPUTDATA_ERROR", status);
|
||||
retStatus = DrmConvertedStatus::STATUS_INPUTDATA_ERROR;
|
||||
break;
|
||||
default:
|
||||
LOGD("FwdLockEngine getConvertedStatus: file conversion Error %d. " \
|
||||
"Returning STATUS_ERROR", status);
|
||||
retStatus = DrmConvertedStatus::STATUS_ERROR;
|
||||
break;
|
||||
}
|
||||
|
||||
return retStatus;
|
||||
}
|
||||
|
||||
DrmConstraints* FwdLockEngine::onGetConstraints(int uniqueId, const String8* path, int action) {
|
||||
DrmConstraints* drmConstraints = NULL;
|
||||
|
||||
LOGD("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;
|
||||
|
||||
LOGD("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) {
|
||||
LOGD("FwdLockEngine::onInitialize");
|
||||
|
||||
|
||||
if (FwdLockGlue_InitializeKeyEncryption()) {
|
||||
LOGD("FwdLockEngine::onInitialize -- FwdLockGlue_InitializeKeyEncryption succeeded");
|
||||
} else {
|
||||
LOGD("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
|
||||
LOGD("FwdLockEngine::onSetOnInfoListener");
|
||||
|
||||
return DRM_NO_ERROR;
|
||||
}
|
||||
|
||||
android::status_t FwdLockEngine::onTerminate(int uniqueId) {
|
||||
LOGD("FwdLockEngine::onTerminate");
|
||||
|
||||
return DRM_NO_ERROR;
|
||||
}
|
||||
|
||||
DrmSupportInfo* FwdLockEngine::onGetSupportInfo(int uniqueId) {
|
||||
DrmSupportInfo* pSupportInfo = new DrmSupportInfo();
|
||||
|
||||
LOGD("FwdLockEngine::onGetSupportInfo");
|
||||
|
||||
// fill all Forward Lock mimetypes and extensions
|
||||
if (NULL != pSupportInfo) {
|
||||
pSupportInfo->addMimeType(String8(FWDLOCK_MIMETYPE_FL));
|
||||
pSupportInfo->addFileSuffix(String8(FWDLOCK_DOTEXTENSION_FL));
|
||||
pSupportInfo->addMimeType(String8(FWDLOCK_MIMETYPE_DM));
|
||||
pSupportInfo->addFileSuffix(String8(FWDLOCK_DOTEXTENSION_DM));
|
||||
|
||||
pSupportInfo->setDescription(String8(FWDLOCK_DESCRIPTION));
|
||||
}
|
||||
|
||||
return pSupportInfo;
|
||||
}
|
||||
|
||||
bool FwdLockEngine::onCanHandle(int uniqueId, const String8& path) {
|
||||
bool result = false;
|
||||
|
||||
String8 extString = path.getPathExtension();
|
||||
|
||||
extString.toLower();
|
||||
|
||||
if ((extString == String8(FWDLOCK_DOTEXTENSION_FL)) ||
|
||||
(extString == String8(FWDLOCK_DOTEXTENSION_DM))) {
|
||||
result = true;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
DrmInfoStatus* FwdLockEngine::onProcessDrmInfo(int uniqueId, const DrmInfo* drmInfo) {
|
||||
DrmInfoStatus *drmInfoStatus = NULL;
|
||||
|
||||
// Nothing to process
|
||||
|
||||
drmInfoStatus = new DrmInfoStatus((int)DrmInfoStatus::STATUS_OK, 0, NULL, String8(""));
|
||||
|
||||
LOGD("FwdLockEngine::onProcessDrmInfo");
|
||||
|
||||
return drmInfoStatus;
|
||||
}
|
||||
|
||||
status_t FwdLockEngine::onSaveRights(
|
||||
int uniqueId,
|
||||
const DrmRights& drmRights,
|
||||
const String8& rightsPath,
|
||||
const String8& contentPath) {
|
||||
// No rights to save. Return
|
||||
LOGD("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
|
||||
LOGD("FwdLockEngine::onAcquireDrmInfo");
|
||||
|
||||
return drmInfo;
|
||||
}
|
||||
|
||||
int FwdLockEngine::onCheckRightsStatus(int uniqueId,
|
||||
const String8& path,
|
||||
int action) {
|
||||
int result = RightsStatus::RIGHTS_INVALID;
|
||||
|
||||
LOGD("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
|
||||
LOGD("FwdLockEngine::onConsumeRights");
|
||||
return DRM_NO_ERROR;
|
||||
}
|
||||
|
||||
bool FwdLockEngine::onValidateAction(int uniqueId,
|
||||
const String8& path,
|
||||
int action,
|
||||
const ActionDescription& description) {
|
||||
LOGD("FwdLockEngine::onValidateAction");
|
||||
|
||||
// For the forwardlock engine checkRights and ValidateAction are the same.
|
||||
return (onCheckRightsStatus(uniqueId, path, action) == RightsStatus::RIGHTS_VALID);
|
||||
}
|
||||
|
||||
String8 FwdLockEngine::onGetOriginalMimeType(int uniqueId, const String8& path) {
|
||||
LOGD("FwdLockEngine::onGetOriginalMimeType");
|
||||
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);
|
||||
|
||||
LOGD("FwdLockEngine::onGetDrmObjectType");
|
||||
|
||||
mimeStr.toLower();
|
||||
|
||||
/* 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()) || ((mimeStr == String8(FWDLOCK_MIMETYPE_FL)) ||
|
||||
(mimeStr == String8(FWDLOCK_MIMETYPE_DM)))) && (mimeType != path) ) {
|
||||
return DrmObjectType::CONTENT;
|
||||
}
|
||||
|
||||
return DrmObjectType::UNKNOWN;
|
||||
}
|
||||
|
||||
status_t FwdLockEngine::onRemoveRights(int uniqueId, const String8& path) {
|
||||
// No Rights to remove
|
||||
LOGD("FwdLockEngine::onRemoveRights");
|
||||
return DRM_NO_ERROR;
|
||||
}
|
||||
|
||||
status_t FwdLockEngine::onRemoveAllRights(int uniqueId) {
|
||||
// No rights to remove
|
||||
LOGD("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
|
||||
LOGD("FwdLockEngine::onSetPlaybackStatus");
|
||||
return DRM_NO_ERROR;
|
||||
}
|
||||
|
||||
status_t FwdLockEngine::onOpenConvertSession(int uniqueId,
|
||||
int convertId) {
|
||||
status_t result = DRM_ERROR_UNKNOWN;
|
||||
LOGD("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 {
|
||||
LOGD("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;
|
||||
|
||||
LOGD("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;
|
||||
|
||||
LOGD("FwdLockEngine::onOpenDecryptSession");
|
||||
|
||||
if ((-1 < fd) &&
|
||||
(NULL != decryptHandle) &&
|
||||
(!decodeSessionMap.isCreated(decryptHandle->decryptId))) {
|
||||
fileDesc = dup(fd);
|
||||
} else {
|
||||
LOGD("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 {
|
||||
LOGD("FwdLockEngine::onOpenDecryptSession Integrity Check failed for the fd");
|
||||
FwdLockFile_detach(fileDesc);
|
||||
::close(fileDesc);
|
||||
delete decodeSession;
|
||||
}
|
||||
}
|
||||
|
||||
LOGD("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;
|
||||
LOGD("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;
|
||||
}
|
||||
}
|
||||
|
||||
LOGD("FwdLockEngine::onCloseDecryptSession Exit");
|
||||
return result;
|
||||
}
|
||||
|
||||
status_t FwdLockEngine::onInitializeDecryptUnit(int uniqueId,
|
||||
DecryptHandle* decryptHandle,
|
||||
int decryptUnitId,
|
||||
const DrmBuffer* headerInfo) {
|
||||
LOGD("FwdLockEngine::onInitializeDecryptUnit");
|
||||
return DRM_ERROR_UNKNOWN;
|
||||
}
|
||||
|
||||
status_t FwdLockEngine::onDecrypt(int uniqueId, DecryptHandle* decryptHandle, int decryptUnitId,
|
||||
const DrmBuffer* encBuffer, DrmBuffer** decBuffer, DrmBuffer* IV) {
|
||||
LOGD("FwdLockEngine::onDecrypt");
|
||||
return DRM_ERROR_UNKNOWN;
|
||||
}
|
||||
|
||||
status_t FwdLockEngine::onDecrypt(int uniqueId,
|
||||
DecryptHandle* decryptHandle,
|
||||
int decryptUnitId,
|
||||
const DrmBuffer* encBuffer,
|
||||
DrmBuffer** decBuffer) {
|
||||
LOGD("FwdLockEngine::onDecrypt");
|
||||
return DRM_ERROR_UNKNOWN;
|
||||
}
|
||||
|
||||
status_t FwdLockEngine::onFinalizeDecryptUnit(int uniqueId,
|
||||
DecryptHandle* decryptHandle,
|
||||
int decryptUnitId) {
|
||||
LOGD("FwdLockEngine::onFinalizeDecryptUnit");
|
||||
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) {
|
||||
LOGD("FwdLockEngine::onPread error reading");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
LOGD("FwdLockEngine::onPread decryptId not found");
|
||||
}
|
||||
|
||||
return bytesRead;
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
#
|
||||
# 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)
|
||||
@@ -0,0 +1,32 @@
|
||||
#
|
||||
# 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)
|
||||
@@ -0,0 +1,191 @@
|
||||
/*
|
||||
* 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;
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
/*
|
||||
* 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__
|
||||
@@ -0,0 +1,37 @@
|
||||
#
|
||||
# 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)
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,282 @@
|
||||
/*
|
||||
* 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__
|
||||
@@ -0,0 +1,37 @@
|
||||
#
|
||||
# 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)
|
||||
@@ -0,0 +1,447 @@
|
||||
/*
|
||||
* 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 <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) {
|
||||
errno = ENFILE;
|
||||
}
|
||||
}
|
||||
return sessionId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds the file session associated to 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 && 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;
|
||||
size_t 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, signatureSize) == 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];
|
||||
size_t signatureSize = SHA1_HASH_SIZE;
|
||||
HMAC_Update(&pSession->signingContext, pSession->topHeader, TOP_HEADER_SIZE);
|
||||
HMAC_Update(&pSession->signingContext, (unsigned char *)pSession->pContentType,
|
||||
pSession->contentTypeLength);
|
||||
HMAC_Update(&pSession->signingContext, pSession->pEncryptedSessionKey,
|
||||
pSession->encryptedSessionKeyLength);
|
||||
HMAC_Update(&pSession->signingContext, pSession->dataSignature, signatureSize);
|
||||
HMAC_Final(&pSession->signingContext, signature, &signatureSize);
|
||||
assert(signatureSize == SHA1_HASH_SIZE);
|
||||
result = memcmp(signature, pSession->headerSignature, signatureSize) == 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;
|
||||
}
|
||||
@@ -0,0 +1,135 @@
|
||||
/*
|
||||
* 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__
|
||||
1039
drm/libdrmframework/plugins/forward-lock/internal-format/doc/FwdLock.html
Executable file
1039
drm/libdrmframework/plugins/forward-lock/internal-format/doc/FwdLock.html
Executable file
File diff suppressed because it is too large
Load Diff
Binary file not shown.
|
After Width: | Height: | Size: 5.4 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 11 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 14 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 10 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 9.1 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 8.8 KiB |
Reference in New Issue
Block a user