Initial import of Widevine Common Encryption DRM engine

Builds libwvmdrmengine.so, which is loaded by the new
MediaDrm APIs to support playback of Widevine/CENC
protected content.

Change-Id: I6f57dd37083dfd96c402cb9dd137c7d74edc8f1c
This commit is contained in:
Jeff Tinker
2013-03-21 17:39:02 -07:00
parent 38334efbe7
commit 1a8aa0dd05
211 changed files with 51913 additions and 144 deletions

View File

@@ -0,0 +1,54 @@
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_SRC_FILES := \
WVCryptoPlugin_test.cpp \
LOCAL_C_INCLUDES := \
bionic \
external/gtest/include \
external/stlport/stlport \
frameworks/av/include \
frameworks/native/include \
vendor/widevine/libwvdrmengine/cdm/core/include \
vendor/widevine/libwvdrmengine/cdm/include \
vendor/widevine/libwvdrmengine/mediacrypto/include \
vendor/widevine/libwvdrmengine/mediacrypto/test \
vendor/widevine/libwvdrmengine/test/gmock/include \
LOCAL_STATIC_LIBRARIES := \
libcdm \
libgmock \
libgmock_main \
libgtest \
libprotobuf-cpp-2.3.0-lite \
libwvdrmcryptoplugin \
LOCAL_SHARED_LIBRARIES := \
liblog \
liboemcrypto \
libstlport \
libutils \
# CDM's protobuffers are not part of the library
PROTO_SRC_DIR := $(proto_generated_cc_sources_dir)/$(LOCAL_PATH)/core/src
LOCAL_SRC_FILES += \
$(PROTO_SRC_DIR)/license_protocol.pb.cc \
LOCAL_C_INCLUDES += \
$(proto_generated_cc_sources_dir)/$(LOCAL_PATH)/core/src \
external/protobuf/src \
LOCAL_ADDITIONAL_DEPENDENCIES += $(proto_generated_headers)
LOCAL_WHOLE_STATIC_LIBRARIES := \
license_protocol_protos \
# End protobuf section
LOCAL_MODULE := libwvdrmmediacrypto_test
LOCAL_MODULE_TAGS := tests
include $(BUILD_EXECUTABLE)

View File

@@ -0,0 +1,28 @@
//
// Copyright 2013 Google Inc. All Rights Reserved.
//
#ifndef WV_CRYPTO_PLUGIN_MOCK_CDM_H_
#define WV_CRYPTO_PLUGIN_MOCK_CDM_H_
#include <string>
#include <vector>
#include "gmock/gmock.h"
#include "wv_cdm_types.h"
#include "wv_content_decryption_module.h"
namespace wvcdm {
class MockCDM : public WvContentDecryptionModule {
public:
MOCK_METHOD8(Decrypt, CdmResponseType(const CdmSessionId&, bool, const KeyId&,
const uint8_t*, size_t,
const std::vector<uint8_t>&, size_t,
void*));
};
} // namespace wvcdm
#endif // WV_CRYPTO_PLUGIN_MOCK_CDM_H_

View File

@@ -0,0 +1,118 @@
//
// Copyright 2013 Google Inc. All Rights Reserved.
//
#include <stdio.h>
#include <string>
#include "gtest/gtest.h"
#include "media/stagefright/foundation/ABase.h"
#include "media/stagefright/foundation/AString.h"
#include "MockCDM.h"
#include "wv_cdm_constants.h"
#include "WVCryptoPlugin.h"
using namespace android;
using namespace std;
using namespace testing;
using namespace wvcdm;
using namespace wvdrm;
class WVCryptoPluginTest : public Test {
protected:
static const uint32_t kSessionIdSize = 16;
uint8_t sessionId[kSessionIdSize];
uint8_t keyId[KEY_ID_SIZE];
uint8_t iv[KEY_IV_SIZE];
static const uint32_t kDataSize = 64;
uint8_t in[kDataSize];
uint8_t out[kDataSize];
static const uint32_t kSubSampleCount = 3;
CryptoPlugin::SubSample subSamples[kSubSampleCount];
virtual void SetUp() {
FILE* fp = fopen("/dev/urandom", "r");
fread(sessionId, sizeof(uint8_t), kSessionIdSize, fp);
fread(keyId, sizeof(uint8_t), KEY_ID_SIZE, fp);
fread(iv, sizeof(uint8_t), KEY_IV_SIZE, fp);
fread(in, sizeof(uint8_t), kDataSize, fp);
fclose(fp);
memset(out, 0, sizeof(out));
memset(subSamples, 0, sizeof(subSamples));
subSamples[0].mNumBytesOfEncryptedData = 16;
subSamples[1].mNumBytesOfClearData = 16;
subSamples[1].mNumBytesOfEncryptedData = 24;
subSamples[2].mNumBytesOfEncryptedData = 8;
// Set default CdmResponseType value for gMock
DefaultValue<CdmResponseType>::Set(wvcdm::NO_ERROR);
}
};
TEST_F(WVCryptoPluginTest, CorrectlyReportsSecureBuffers) {
MockCDM cdm;
WVCryptoPlugin plugin(sessionId, kSessionIdSize, &cdm);
EXPECT_FALSE(plugin.requiresSecureDecoderComponent("video/mp4")) <<
"WVCryptoPlugin incorrectly expects a secure video decoder";
EXPECT_FALSE(plugin.requiresSecureDecoderComponent("audio/aac")) <<
"WVCryptoPlugin incorrectly expects a secure audio decoder";
}
TEST_F(WVCryptoPluginTest, RejectsSecureDecode) {
MockCDM cdm;
WVCryptoPlugin plugin(sessionId, kSessionIdSize, &cdm);
// Decrypt should not be called because we specified an unsupported
// security level
EXPECT_CALL(cdm, Decrypt(_, _, _, _, _, _, _, _))
.Times(0);
ssize_t res = plugin.decrypt(true, keyId, iv, CryptoPlugin::kMode_AES_CTR,
in, subSamples, kSubSampleCount, out, NULL);
EXPECT_EQ(static_cast<ssize_t>(-EPERM), res) <<
"WVCryptoPlugin allowed decryption to proceed despite being asked for an "
"unsupported security level";
}
TEST_F(WVCryptoPluginTest, AttemptsToDecrypt) {
MockCDM cdm;
WVCryptoPlugin plugin(sessionId, kSessionIdSize, &cdm);
// Specify the expected calls to Decrypt
{
InSequence calls;
EXPECT_CALL(cdm, Decrypt(ElementsAreArray(sessionId, kSessionIdSize), true,
ElementsAreArray(keyId, KEY_ID_SIZE), in, 16,
ElementsAreArray(iv, KEY_IV_SIZE), 0, out))
.WillOnce(Return(wvcdm::NO_ERROR));
EXPECT_CALL(cdm, Decrypt(ElementsAreArray(sessionId, kSessionIdSize), false,
ElementsAreArray(keyId, KEY_ID_SIZE), in + 16, 16,
ElementsAreArray(iv, KEY_IV_SIZE), 0, out + 16))
.WillOnce(Return(wvcdm::NO_ERROR));
EXPECT_CALL(cdm, Decrypt(ElementsAreArray(sessionId, kSessionIdSize), true,
ElementsAreArray(keyId, KEY_ID_SIZE), in + 32, 24,
ElementsAreArray(iv, KEY_IV_SIZE), 0, out + 32))
.WillOnce(Return(wvcdm::NO_ERROR));
EXPECT_CALL(cdm, Decrypt(ElementsAreArray(sessionId, kSessionIdSize), true,
ElementsAreArray(keyId, KEY_ID_SIZE), in + 56, 8,
ElementsAreArray(iv, KEY_IV_SIZE), 8, out + 56))
.WillOnce(Return(wvcdm::NO_ERROR));
}
ssize_t res = plugin.decrypt(false, keyId, iv, CryptoPlugin::kMode_AES_CTR,
in, subSamples, kSubSampleCount, out, NULL);
EXPECT_EQ(static_cast<ssize_t>(kDataSize), res) <<
"WVCryptoPlugin decrypted the wrong number of bytes";
}