Remove hidl support.
Merged from http://go/wvgerrit/161857 Test: streaming(Netflix, Play Movies & TV) Test: ./build_and_run_all_unit_tests.sh Test: adb shell ps | grep drm Test: metrics_dump Test: hardware/interfaces/drm/aidl/vts$ atest VtsAidlHalDrmTargetTest Bug: 259299992 Change-Id: I76bcc82bbfb3fc60987b66265a580946a16c341d
This commit is contained in:
@@ -4,56 +4,7 @@ LOCAL_PATH := $(call my-dir)
|
||||
#
|
||||
include $(CLEAR_VARS)
|
||||
|
||||
WV_UNITTESTS_BUILD_TARGET?=
|
||||
ifeq ($(WV_UNITTESTS_BUILD_TARGET), hidl)
|
||||
|
||||
LOCAL_SRC_FILES := \
|
||||
hidl/WVCryptoPlugin_test.cpp \
|
||||
|
||||
LOCAL_C_INCLUDES := \
|
||||
frameworks/av/include \
|
||||
frameworks/native/include \
|
||||
vendor/widevine/libwvdrmengine/cdm/core/include \
|
||||
vendor/widevine/libwvdrmengine/cdm/include \
|
||||
vendor/widevine/libwvdrmengine/cdm/metrics/include \
|
||||
vendor/widevine/libwvdrmengine/cdm/util/include \
|
||||
vendor/widevine/libwvdrmengine/include_hidl \
|
||||
vendor/widevine/libwvdrmengine/mediacrypto/include_hidl \
|
||||
vendor/widevine/libwvdrmengine/oemcrypto/include \
|
||||
|
||||
LOCAL_STATIC_LIBRARIES := \
|
||||
libcdm \
|
||||
libcdm_protos \
|
||||
libcdm_utils_hidl \
|
||||
libjsmn \
|
||||
libgmock \
|
||||
libgmock_main \
|
||||
libgtest \
|
||||
libwvlevel3 \
|
||||
libwvdrmcryptoplugin_hidl \
|
||||
libwv_odk \
|
||||
|
||||
LOCAL_SHARED_LIBRARIES := \
|
||||
android.hardware.drm@1.0 \
|
||||
android.hardware.drm@1.1 \
|
||||
android.hardware.drm@1.2 \
|
||||
android.hardware.drm@1.3 \
|
||||
android.hardware.drm@1.4 \
|
||||
android.hidl.memory@1.0 \
|
||||
libbase \
|
||||
libbinder \
|
||||
libcrypto \
|
||||
libcutils \
|
||||
libdl \
|
||||
libhidlbase \
|
||||
libhidlmemory \
|
||||
liblog \
|
||||
libprotobuf-cpp-lite \
|
||||
libutils \
|
||||
|
||||
# build unit tests for Aidl
|
||||
else
|
||||
|
||||
LOCAL_SRC_FILES := \
|
||||
WVCryptoPlugin_hal_test.cpp \
|
||||
|
||||
@@ -92,9 +43,6 @@ LOCAL_SHARED_LIBRARIES := \
|
||||
libprotobuf-cpp-lite \
|
||||
libutils \
|
||||
|
||||
# endif $(WV_UNITTESTS_BUILD_TARGET)
|
||||
endif
|
||||
|
||||
LOCAL_HEADER_LIBRARIES := \
|
||||
libstagefright_headers \
|
||||
|
||||
|
||||
@@ -1,643 +0,0 @@
|
||||
//
|
||||
// Copyright 2018 Google LLC. All Rights Reserved. This file and proprietary
|
||||
// source code may only be used and distributed under the Widevine License
|
||||
// Agreement.
|
||||
//
|
||||
|
||||
//#define LOG_NDEBUG 0
|
||||
#define LOG_TAG "WVCryptoPluginTest"
|
||||
#include <utils/Log.h>
|
||||
|
||||
#include <map>
|
||||
#include <stdio.h>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <binder/MemoryDealer.h>
|
||||
#include <hidl/Status.h>
|
||||
#include <hidlmemory/mapping.h>
|
||||
|
||||
#include "gmock/gmock.h"
|
||||
#include "gtest/gtest.h"
|
||||
#include "wv_cdm_constants.h"
|
||||
#include "wv_cdm_types.h"
|
||||
#include "wv_content_decryption_module.h"
|
||||
#include "HidlTypes.h"
|
||||
#include "OEMCryptoCENC.h"
|
||||
#include "TypeConvert.h"
|
||||
#include "WVCryptoPlugin.h"
|
||||
|
||||
namespace wvdrm {
|
||||
namespace hardware {
|
||||
namespace drm {
|
||||
namespace V1_4 {
|
||||
namespace widevine {
|
||||
|
||||
using ::android::MemoryDealer;
|
||||
|
||||
using ::testing::_;
|
||||
using ::testing::DefaultValue;
|
||||
using ::testing::DoAll;
|
||||
using ::testing::ElementsAreArray;
|
||||
using ::testing::Field;
|
||||
using ::testing::InSequence;
|
||||
using ::testing::Matcher;
|
||||
using ::testing::SetArgPointee;
|
||||
using ::testing::StrictMock;
|
||||
using ::testing::Test;
|
||||
using ::testing::Truly;
|
||||
using ::testing::Value;
|
||||
using ::testing::internal::ElementsAreArrayMatcher;
|
||||
|
||||
using wvcdm::kCipherModeCtr;
|
||||
using wvcdm::kCipherModeCbc;
|
||||
using wvcdm::CdmCipherMode;
|
||||
using wvcdm::CdmDecryptionParametersV16;
|
||||
using wvcdm::CdmDecryptionSample;
|
||||
using wvcdm::CdmDecryptionSubsample;
|
||||
using wvcdm::CdmQueryMap;
|
||||
using wvcdm::CdmResponseType;
|
||||
using wvcdm::CdmSessionId;
|
||||
using wvcdm::KeyId;
|
||||
using wvcdm::KEY_ID_SIZE;
|
||||
using wvcdm::KEY_IV_SIZE;
|
||||
using wvcdm::QUERY_KEY_SECURITY_LEVEL;
|
||||
using wvcdm::QUERY_VALUE_SECURITY_LEVEL_L1;
|
||||
using wvcdm::QUERY_VALUE_SECURITY_LEVEL_L3;
|
||||
|
||||
class MockCDM : public wvcdm::WvContentDecryptionModule {
|
||||
public:
|
||||
MOCK_METHOD(bool, IsOpenSession, (const CdmSessionId&), (override));
|
||||
|
||||
MOCK_METHOD(CdmResponseType, DecryptV16, (const CdmSessionId&, bool,
|
||||
const CdmDecryptionParametersV16&), (override));
|
||||
|
||||
MOCK_METHOD(CdmResponseType, QuerySessionStatus, (const CdmSessionId&,
|
||||
CdmQueryMap*), (override));
|
||||
};
|
||||
|
||||
class WVCryptoPluginTest : public Test {
|
||||
protected:
|
||||
static const uint32_t kSessionIdSize = 16;
|
||||
uint8_t* pDest = nullptr;
|
||||
uint8_t* pSrc = nullptr;
|
||||
uint8_t sessionId[kSessionIdSize];
|
||||
uint32_t nextBufferId = 0;
|
||||
std::map<void *, uint32_t> heapBases;
|
||||
|
||||
virtual void SetUp() {
|
||||
FILE* fp = fopen("/dev/urandom", "r");
|
||||
fread(sessionId, sizeof(uint8_t), kSessionIdSize, fp);
|
||||
fclose(fp);
|
||||
|
||||
// Set default CdmResponseType value for gMock
|
||||
DefaultValue<CdmResponseType>::Set(wvcdm::NO_ERROR);
|
||||
heapBases.clear();
|
||||
}
|
||||
|
||||
void setHeapBase(WVCryptoPlugin& plugin,
|
||||
const sp<android::IMemoryHeap>& heap) {
|
||||
ASSERT_NE(heap, nullptr);
|
||||
|
||||
void* heapBase = heap->getBase();
|
||||
ASSERT_NE(heapBase, nullptr);
|
||||
|
||||
native_handle_t* nativeHandle = native_handle_create(1, 0);
|
||||
ASSERT_NE(nativeHandle, nullptr);
|
||||
|
||||
nativeHandle->data[0] = heap->getHeapID();
|
||||
|
||||
auto hidlHandle = hidl_handle(nativeHandle);
|
||||
auto hidlMemory = hidl_memory("ashmem", hidlHandle, heap->getSize());
|
||||
heapBases.insert(
|
||||
std::pair<void*, uint32_t>(heapBase, nextBufferId));
|
||||
Return<void> hResult =
|
||||
plugin.setSharedBufferBase(hidlMemory, nextBufferId++);
|
||||
|
||||
ALOGE_IF(!hResult.isOk(), "setHeapBase failed setSharedBufferBase");
|
||||
}
|
||||
|
||||
void toSharedBuffer(WVCryptoPlugin& plugin,
|
||||
const sp<android::IMemory>& memory,
|
||||
SharedBuffer* buffer) {
|
||||
ssize_t offset;
|
||||
size_t size;
|
||||
|
||||
ASSERT_NE(memory, nullptr);
|
||||
ASSERT_NE(buffer, nullptr);
|
||||
|
||||
sp<android::IMemoryHeap> heap = memory->getMemory(&offset, &size);
|
||||
ASSERT_NE(heap, nullptr);
|
||||
|
||||
setHeapBase(plugin, heap);
|
||||
buffer->bufferId = heapBases[heap->getBase()];
|
||||
buffer->offset = offset >= 0 ? offset : 0;
|
||||
buffer->size = size;
|
||||
}
|
||||
};
|
||||
|
||||
TEST_F(WVCryptoPluginTest, CorrectlyReportsSecureBuffers) {
|
||||
android::sp<StrictMock<MockCDM>> cdm = new StrictMock<MockCDM>();
|
||||
|
||||
CdmQueryMap l1Map;
|
||||
l1Map[QUERY_KEY_SECURITY_LEVEL] = QUERY_VALUE_SECURITY_LEVEL_L1;
|
||||
CdmQueryMap l3Map;
|
||||
l3Map[QUERY_KEY_SECURITY_LEVEL] = QUERY_VALUE_SECURITY_LEVEL_L3;
|
||||
|
||||
// Provide the expected behavior for IsOpenSession
|
||||
EXPECT_CALL(*cdm, IsOpenSession(_))
|
||||
.WillRepeatedly(testing::Return(true));
|
||||
|
||||
// Specify the expected calls to QuerySessionStatus
|
||||
EXPECT_CALL(*cdm, QuerySessionStatus(_, _))
|
||||
.WillOnce(DoAll(SetArgPointee<1>(l1Map),
|
||||
testing::Return(wvcdm::NO_ERROR)))
|
||||
.WillOnce(DoAll(SetArgPointee<1>(l3Map),
|
||||
testing::Return(wvcdm::NO_ERROR)));
|
||||
|
||||
WVCryptoPlugin plugin(sessionId, kSessionIdSize, cdm.get());
|
||||
|
||||
EXPECT_TRUE(plugin.requiresSecureDecoderComponent("video/mp4")) <<
|
||||
"WVCryptoPlugin incorrectly allows an insecure video decoder on L1";
|
||||
EXPECT_FALSE(plugin.requiresSecureDecoderComponent("video/mp4")) <<
|
||||
"WVCryptoPlugin incorrectly expects a secure video decoder on L3";
|
||||
EXPECT_FALSE(plugin.requiresSecureDecoderComponent("audio/aac")) <<
|
||||
"WVCryptoPlugin incorrectly expects a secure audio decoder";
|
||||
}
|
||||
|
||||
// TODO(b/28295739):
|
||||
// Add New MediaCrypto Unit Tests for CBC & Pattern Mode in cdmPatternDesc.
|
||||
|
||||
// Predicate that validates that the fields of a passed-in
|
||||
// CdmDecryptionParametersV16 match the values it was given at construction
|
||||
// time.
|
||||
//
|
||||
// This could be done with a huge pile of gMock matchers, but it is ugly and
|
||||
// unmaintainable, particularly once you get into validating the subsamples. The
|
||||
// logic here is complex enough to warrant a custom matcher for this one test.
|
||||
class CDPMatcher {
|
||||
public:
|
||||
// TODO(b/35259313): Uncomment the removed parameters once the matcher can
|
||||
// convert them from HIDL accesses to physical addresses.
|
||||
CDPMatcher(const uint8_t* keyId, bool isSecure, Mode cipherMode,
|
||||
const Pattern& pattern,
|
||||
const uint8_t* /* input */, size_t inputLength,
|
||||
const uint8_t* /* output */, size_t outputLength, const uint8_t* iv,
|
||||
const SubSample* subsamples, size_t subsamplesLength)
|
||||
: mKeyId(keyId, keyId + KEY_ID_SIZE), mIsSecure(isSecure),
|
||||
mCipherMode(cipherMode), mPattern(pattern), /* mInput(input), */
|
||||
mInputLength(inputLength), /* mOutput(output), */
|
||||
mOutputLength(outputLength), mIv(iv, iv + KEY_IV_SIZE),
|
||||
mSubsamples(subsamples, subsamples + subsamplesLength) {}
|
||||
|
||||
bool operator()(const CdmDecryptionParametersV16& params) const {
|
||||
if (mCipherMode == Mode::AES_CTR &&
|
||||
params.cipher_mode != kCipherModeCtr) {
|
||||
return false;
|
||||
} else if (mCipherMode == Mode::AES_CBC &&
|
||||
params.cipher_mode != kCipherModeCbc) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (params.key_id != mKeyId ||
|
||||
params.is_secure != mIsSecure ||
|
||||
params.pattern.encrypt_blocks != mPattern.encryptBlocks ||
|
||||
params.pattern.skip_blocks != mPattern.skipBlocks ||
|
||||
params.samples.size() != 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const CdmDecryptionSample& sample = params.samples[0];
|
||||
if (// TODO(b/35259313): Convert from a HIDL access to a physical address.
|
||||
// sample.encrypt_buffer != mInput ||
|
||||
sample.encrypt_buffer_length != mInputLength ||
|
||||
// TODO(b/35259313): Convert from a HIDL access to a physical address.
|
||||
// sample.decrypt_buffer != mOutput ||
|
||||
sample.decrypt_buffer_size != mOutputLength ||
|
||||
sample.decrypt_buffer_offset != 0 ||
|
||||
sample.iv != mIv ||
|
||||
sample.subsamples.size() != mSubsamples.size()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < mSubsamples.size(); ++i) {
|
||||
const SubSample& androidSubsample = mSubsamples[i];
|
||||
const CdmDecryptionSubsample& cdmSubsample = sample.subsamples[i];
|
||||
|
||||
if (cdmSubsample.clear_bytes != androidSubsample.numBytesOfClearData ||
|
||||
cdmSubsample.protected_bytes != androidSubsample.numBytesOfEncryptedData) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
const KeyId mKeyId;
|
||||
const bool mIsSecure;
|
||||
const Mode mCipherMode;
|
||||
const Pattern mPattern;
|
||||
// TODO(b/35259313): Uncomment this field once the matcher can convert this
|
||||
// from a HIDL access to a physical address.
|
||||
// const uint8_t* const mInput;
|
||||
const size_t mInputLength;
|
||||
// TODO(b/35259313): Uncomment this field once the matcher can convert this
|
||||
// from a HIDL access to a physical address.
|
||||
// const uint8_t* const mOutput;
|
||||
const size_t mOutputLength;
|
||||
const std::vector<uint8_t> mIv;
|
||||
const std::vector<SubSample> mSubsamples;
|
||||
};
|
||||
|
||||
TEST_F(WVCryptoPluginTest, AttemptsToDecrypt) {
|
||||
android::sp<StrictMock<MockCDM>> cdm = new StrictMock<MockCDM>();
|
||||
|
||||
constexpr size_t kSubSampleCount = 6;
|
||||
SubSample subSamples[kSubSampleCount];
|
||||
memset(subSamples, 0, sizeof(subSamples));
|
||||
subSamples[0].numBytesOfEncryptedData = 16;
|
||||
subSamples[1].numBytesOfClearData = 16;
|
||||
subSamples[1].numBytesOfEncryptedData = 16;
|
||||
subSamples[2].numBytesOfEncryptedData = 8;
|
||||
subSamples[3].numBytesOfClearData = 29;
|
||||
subSamples[3].numBytesOfEncryptedData = 24;
|
||||
subSamples[4].numBytesOfEncryptedData = 60;
|
||||
subSamples[5].numBytesOfEncryptedData = 16;
|
||||
|
||||
std::vector<SubSample> subSamplesVector(
|
||||
subSamples, subSamples + sizeof(subSamples) / sizeof(subSamples[0]));
|
||||
auto hSubSamples = hidl_vec<SubSample>(subSamplesVector);
|
||||
|
||||
uint8_t keyId[KEY_ID_SIZE];
|
||||
uint8_t iv[KEY_IV_SIZE];
|
||||
|
||||
static const size_t kDataSize = 185;
|
||||
uint8_t inputData[kDataSize];
|
||||
|
||||
FILE* fp = fopen("/dev/urandom", "r");
|
||||
fread(keyId, sizeof(uint8_t), KEY_ID_SIZE, fp);
|
||||
fread(iv, sizeof(uint8_t), KEY_IV_SIZE, fp);
|
||||
fread(inputData, sizeof(uint8_t), kDataSize, fp);
|
||||
fclose(fp);
|
||||
|
||||
sp<MemoryDealer> memDealer = new MemoryDealer(
|
||||
kDataSize * 2, "WVCryptoPlugin_test");
|
||||
sp<android::IMemory> source = memDealer->allocate(kDataSize);
|
||||
ASSERT_NE(source, nullptr);
|
||||
pSrc = static_cast<uint8_t*>(
|
||||
static_cast<void*>(source->unsecurePointer()));
|
||||
ASSERT_NE(pSrc, nullptr);
|
||||
memcpy(pSrc, inputData, source->size());
|
||||
|
||||
sp<android::IMemory> destination = memDealer->allocate(kDataSize);
|
||||
ASSERT_NE(destination, nullptr);
|
||||
pDest = static_cast<uint8_t*>(
|
||||
static_cast<void*>(destination->unsecurePointer()));
|
||||
ASSERT_NE(pDest, nullptr);
|
||||
|
||||
Pattern noPattern = { 0, 0 };
|
||||
|
||||
// Provide the expected behavior for IsOpenSession
|
||||
EXPECT_CALL(*cdm, IsOpenSession(_))
|
||||
.WillRepeatedly(testing::Return(true));
|
||||
|
||||
// Specify the expected calls to Decrypt
|
||||
CDPMatcher paramsMatcher(keyId, false, Mode::AES_CTR, noPattern, pSrc,
|
||||
kDataSize, pDest, kDataSize, iv, subSamples,
|
||||
kSubSampleCount);
|
||||
|
||||
EXPECT_CALL(*cdm, DecryptV16(ElementsAreArray(sessionId, kSessionIdSize),
|
||||
true,
|
||||
Truly(paramsMatcher)))
|
||||
.Times(1);
|
||||
|
||||
WVCryptoPlugin plugin(sessionId, kSessionIdSize, cdm.get());
|
||||
|
||||
uint32_t bytesWritten = 0;
|
||||
std::string errorDetailMessage;
|
||||
DestinationBuffer hDestination;
|
||||
hDestination.type = BufferType::SHARED_MEMORY;
|
||||
toSharedBuffer(plugin, destination, &hDestination.nonsecureMemory);
|
||||
|
||||
SharedBuffer sourceBuffer;
|
||||
toSharedBuffer(plugin, source, &sourceBuffer);
|
||||
|
||||
plugin.decrypt(
|
||||
false, hidl_array<uint8_t, 16>(keyId), hidl_array<uint8_t, 16>(iv),
|
||||
Mode::AES_CTR, noPattern, hSubSamples, sourceBuffer, 0, hDestination,
|
||||
[&](Status status, uint32_t hBytesWritten, hidl_string hDetailedError) {
|
||||
EXPECT_EQ(status, Status::OK);
|
||||
|
||||
bytesWritten = hBytesWritten;
|
||||
errorDetailMessage.assign(hDetailedError.c_str());
|
||||
});
|
||||
|
||||
EXPECT_EQ(kDataSize, bytesWritten) <<
|
||||
"WVCryptoPlugin decrypted the wrong number of bytes";
|
||||
EXPECT_EQ(0u, errorDetailMessage.size()) <<
|
||||
"WVCryptoPlugin reported a detailed error message.";
|
||||
}
|
||||
|
||||
TEST_F(WVCryptoPluginTest, RejectsCens) {
|
||||
android::sp<StrictMock<MockCDM>> cdm = new StrictMock<MockCDM>();
|
||||
|
||||
constexpr size_t kSubSampleCount = 2;
|
||||
SubSample subSamples[kSubSampleCount];
|
||||
memset(subSamples, 0, sizeof(subSamples));
|
||||
subSamples[0].numBytesOfEncryptedData = 16;
|
||||
subSamples[1].numBytesOfClearData = 16;
|
||||
subSamples[1].numBytesOfEncryptedData = 16;
|
||||
|
||||
std::vector<SubSample> subSamplesVector(
|
||||
subSamples, subSamples + sizeof(subSamples) / sizeof(subSamples[0]));
|
||||
auto hSubSamples = hidl_vec<SubSample>(subSamplesVector);
|
||||
|
||||
uint8_t keyId[KEY_ID_SIZE];
|
||||
uint8_t iv[KEY_IV_SIZE];
|
||||
|
||||
static const size_t kDataSize = 48;
|
||||
uint8_t inputData[kDataSize];
|
||||
|
||||
FILE* fp = fopen("/dev/urandom", "r");
|
||||
fread(keyId, sizeof(uint8_t), KEY_ID_SIZE, fp);
|
||||
fread(iv, sizeof(uint8_t), KEY_IV_SIZE, fp);
|
||||
fread(inputData, sizeof(uint8_t), kDataSize, fp);
|
||||
fclose(fp);
|
||||
|
||||
sp<MemoryDealer> memDealer = new MemoryDealer(
|
||||
kDataSize * 2, "WVCryptoPlugin_test");
|
||||
sp<android::IMemory> source = memDealer->allocate(kDataSize);
|
||||
ASSERT_NE(source, nullptr);
|
||||
pSrc = static_cast<uint8_t*>(
|
||||
static_cast<void*>(source->unsecurePointer()));
|
||||
ASSERT_NE(pSrc, nullptr);
|
||||
memcpy(pSrc, inputData, source->size());
|
||||
|
||||
sp<android::IMemory> destination = memDealer->allocate(kDataSize);
|
||||
ASSERT_NE(destination, nullptr);
|
||||
pDest = static_cast<uint8_t*>(
|
||||
static_cast<void*>(destination->unsecurePointer()));
|
||||
ASSERT_NE(pDest, nullptr);
|
||||
|
||||
Pattern recommendedPattern = { 1, 9 };
|
||||
|
||||
// Provide the expected behavior for IsOpenSession
|
||||
EXPECT_CALL(*cdm, IsOpenSession(_))
|
||||
.WillRepeatedly(testing::Return(true));
|
||||
|
||||
// Refuse calls to Decrypt
|
||||
EXPECT_CALL(*cdm, DecryptV16(_, _, _))
|
||||
.Times(0);
|
||||
|
||||
WVCryptoPlugin plugin(sessionId, kSessionIdSize, cdm.get());
|
||||
|
||||
DestinationBuffer hDestination;
|
||||
hDestination.type = BufferType::SHARED_MEMORY;
|
||||
toSharedBuffer(plugin, destination, &hDestination.nonsecureMemory);
|
||||
|
||||
SharedBuffer sourceBuffer;
|
||||
toSharedBuffer(plugin, source, &sourceBuffer);
|
||||
|
||||
plugin.decrypt(
|
||||
false, hidl_array<uint8_t, 16>(keyId), hidl_array<uint8_t, 16>(iv),
|
||||
Mode::AES_CTR, recommendedPattern, hSubSamples, sourceBuffer, 0,
|
||||
hDestination,
|
||||
[&](Status status, uint32_t bytesWritten,
|
||||
hidl_string /* errorDetailMessage */) {
|
||||
EXPECT_EQ(status, Status::BAD_VALUE);
|
||||
EXPECT_EQ(bytesWritten, 0);
|
||||
});
|
||||
}
|
||||
|
||||
TEST_F(WVCryptoPluginTest, CommunicatesSecureBufferRequest) {
|
||||
android::sp<StrictMock<MockCDM>> cdm = new StrictMock<MockCDM>();
|
||||
|
||||
uint8_t keyId[KEY_ID_SIZE];
|
||||
uint8_t iv[KEY_IV_SIZE];
|
||||
|
||||
static const size_t kDataSize = 32;
|
||||
uint8_t in[kDataSize];
|
||||
|
||||
FILE* fp = fopen("/dev/urandom", "r");
|
||||
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);
|
||||
|
||||
SubSample subSample;
|
||||
subSample.numBytesOfClearData = 16;
|
||||
subSample.numBytesOfEncryptedData = 16;
|
||||
std::vector<SubSample> subSampleVector;
|
||||
subSampleVector.push_back(subSample);
|
||||
auto hSubSamples = hidl_vec<SubSample>(subSampleVector);
|
||||
|
||||
// Provide the expected behavior for IsOpenSession
|
||||
EXPECT_CALL(*cdm, IsOpenSession(_))
|
||||
.WillRepeatedly(testing::Return(true));
|
||||
|
||||
// Specify the expected calls to Decrypt
|
||||
{
|
||||
InSequence calls;
|
||||
|
||||
typedef CdmDecryptionParametersV16 CDP;
|
||||
|
||||
EXPECT_CALL(*cdm, DecryptV16(_, _, Field(&CDP::is_secure, false)))
|
||||
.Times(1);
|
||||
|
||||
EXPECT_CALL(*cdm, DecryptV16(_, _, Field(&CDP::is_secure, true)))
|
||||
.Times(1);
|
||||
}
|
||||
|
||||
sp<MemoryDealer> memDealer = new MemoryDealer(
|
||||
kDataSize * 2, "WVCryptoPlugin_test");
|
||||
sp<android::IMemory> source = memDealer->allocate(kDataSize);
|
||||
ASSERT_NE(source, nullptr);
|
||||
pSrc = static_cast<uint8_t*>(
|
||||
static_cast<void*>(source->unsecurePointer()));
|
||||
ASSERT_NE(pSrc, nullptr);
|
||||
memcpy(pSrc, in, source->size());
|
||||
|
||||
sp<android::IMemory> destination = memDealer->allocate(kDataSize);
|
||||
ASSERT_NE(destination, nullptr);
|
||||
pDest = static_cast<uint8_t*>(
|
||||
static_cast<void*>(destination->unsecurePointer()));
|
||||
ASSERT_NE(pDest, nullptr);
|
||||
|
||||
WVCryptoPlugin plugin(sessionId, kSessionIdSize, cdm.get());
|
||||
|
||||
uint32_t bytesWritten = 0;
|
||||
std::string errorDetailMessage;
|
||||
DestinationBuffer hDestination;
|
||||
hDestination.type = BufferType::SHARED_MEMORY;
|
||||
toSharedBuffer(plugin, destination, &hDestination.nonsecureMemory);
|
||||
Pattern noPattern = { 0, 0 };
|
||||
|
||||
SharedBuffer sourceBuffer;
|
||||
toSharedBuffer(plugin, source, &sourceBuffer);
|
||||
|
||||
plugin.decrypt(
|
||||
false, hidl_array<uint8_t, 16>(keyId), hidl_array<uint8_t, 16>(iv),
|
||||
Mode::AES_CTR, noPattern, hSubSamples, sourceBuffer, 0, hDestination,
|
||||
[&](Status status, uint32_t hBytesWritten, hidl_string hDetailedError) {
|
||||
EXPECT_EQ(status, Status::OK);
|
||||
|
||||
bytesWritten = hBytesWritten;
|
||||
errorDetailMessage.assign(hDetailedError.c_str());
|
||||
});
|
||||
|
||||
EXPECT_EQ(0u, errorDetailMessage.size()) <<
|
||||
"WVCryptoPlugin reported a detailed error message.";
|
||||
|
||||
plugin.decrypt(
|
||||
true, hidl_array<uint8_t, 16>(keyId), hidl_array<uint8_t, 16>(iv),
|
||||
Mode::AES_CTR, noPattern, hSubSamples, sourceBuffer, 0, hDestination,
|
||||
[&](Status status, uint32_t hBytesWritten, hidl_string hDetailedError) {
|
||||
EXPECT_EQ(status, Status::OK);
|
||||
|
||||
bytesWritten = hBytesWritten;
|
||||
errorDetailMessage.assign(hDetailedError.c_str());
|
||||
});
|
||||
|
||||
EXPECT_EQ(0u, errorDetailMessage.size()) <<
|
||||
"WVCryptoPlugin reported a detailed error message.";
|
||||
}
|
||||
|
||||
TEST_F(WVCryptoPluginTest, AllowsSessionIdChanges) {
|
||||
android::sp<StrictMock<MockCDM>> cdm = new StrictMock<MockCDM>();
|
||||
|
||||
uint8_t keyId[KEY_ID_SIZE];
|
||||
uint8_t iv[KEY_IV_SIZE];
|
||||
uint8_t sessionId2[kSessionIdSize];
|
||||
|
||||
static const size_t kDataSize = 32;
|
||||
uint8_t in[kDataSize];
|
||||
|
||||
FILE* fp = fopen("/dev/urandom", "r");
|
||||
fread(keyId, sizeof(uint8_t), KEY_ID_SIZE, fp);
|
||||
fread(iv, sizeof(uint8_t), KEY_IV_SIZE, fp);
|
||||
fread(sessionId2, sizeof(uint8_t), kSessionIdSize, fp);
|
||||
fread(in, sizeof(uint8_t), kDataSize, fp);
|
||||
fclose(fp);
|
||||
|
||||
SubSample subSample;
|
||||
subSample.numBytesOfClearData = 16;
|
||||
subSample.numBytesOfEncryptedData = 16;
|
||||
std::vector<SubSample> subSampleVector;
|
||||
subSampleVector.push_back(subSample);
|
||||
auto hSubSamples = hidl_vec<SubSample>(subSampleVector);
|
||||
|
||||
std::vector<uint8_t> sessionIdVector(sessionId, sessionId + kSessionIdSize);
|
||||
std::vector<uint8_t> sessionId2Vector(sessionId2,
|
||||
sessionId2 + kSessionIdSize);
|
||||
|
||||
// Provide the expected behavior for IsOpenSession
|
||||
EXPECT_CALL(*cdm, IsOpenSession(_))
|
||||
.WillRepeatedly(testing::Return(true));
|
||||
|
||||
// Specify the expected calls to Decrypt
|
||||
{
|
||||
InSequence calls;
|
||||
|
||||
EXPECT_CALL(*cdm,
|
||||
DecryptV16(ElementsAreArray(sessionId, kSessionIdSize), _, _))
|
||||
.Times(1);
|
||||
|
||||
EXPECT_CALL(*cdm,
|
||||
DecryptV16(ElementsAreArray(sessionId2, kSessionIdSize), _, _))
|
||||
.Times(1);
|
||||
}
|
||||
|
||||
sp<MemoryDealer> memDealer = new MemoryDealer(
|
||||
kDataSize * 2, "WVCryptoPlugin_test");
|
||||
sp<android::IMemory> source = memDealer->allocate(kDataSize);
|
||||
ASSERT_NE(source, nullptr);
|
||||
pSrc = static_cast<uint8_t*>(
|
||||
static_cast<void*>(source->unsecurePointer()));
|
||||
ASSERT_NE(pSrc, nullptr);
|
||||
memcpy(pSrc, in, source->size());
|
||||
|
||||
sp<android::IMemory> destination = memDealer->allocate(kDataSize);
|
||||
ASSERT_NE(destination, nullptr);
|
||||
pDest = static_cast<uint8_t*>(
|
||||
static_cast<void*>(destination->unsecurePointer()));
|
||||
ASSERT_NE(pDest, nullptr);
|
||||
|
||||
uint8_t blank[1]; // Some compilers will not accept 0.
|
||||
WVCryptoPlugin plugin(blank, 0, cdm.get());
|
||||
|
||||
uint32_t bytesWritten = 0;
|
||||
std::string errorDetailMessage;
|
||||
DestinationBuffer hDestination;
|
||||
hDestination.type = BufferType::SHARED_MEMORY;
|
||||
toSharedBuffer(plugin, destination, &hDestination.nonsecureMemory);
|
||||
Pattern noPattern = { 0, 0 };
|
||||
|
||||
SharedBuffer sourceBuffer;
|
||||
toSharedBuffer(plugin, source, &sourceBuffer);
|
||||
|
||||
Status status = plugin.setMediaDrmSession(sessionIdVector);
|
||||
EXPECT_EQ(status, Status::OK);
|
||||
|
||||
plugin.decrypt(
|
||||
false, hidl_array<uint8_t, 16>(keyId), hidl_array<uint8_t, 16>(iv),
|
||||
Mode::AES_CTR, noPattern, hSubSamples, sourceBuffer, 0, hDestination,
|
||||
[&](Status status, uint32_t hBytesWritten, hidl_string hDetailedError) {
|
||||
EXPECT_EQ(status, Status::OK);
|
||||
|
||||
bytesWritten = hBytesWritten;
|
||||
errorDetailMessage.assign(hDetailedError.c_str());
|
||||
});
|
||||
|
||||
EXPECT_EQ(0u, errorDetailMessage.size()) <<
|
||||
"WVCryptoPlugin reported a detailed error message.";
|
||||
|
||||
status = plugin.setMediaDrmSession(sessionId2Vector);
|
||||
EXPECT_EQ(status, Status::OK);
|
||||
|
||||
plugin.decrypt(
|
||||
false, hidl_array<uint8_t, 16>(keyId), hidl_array<uint8_t, 16>(iv),
|
||||
Mode::AES_CTR, noPattern, hSubSamples, sourceBuffer, 0, hDestination,
|
||||
[&](Status status, uint32_t hBytesWritten, hidl_string hDetailedError) {
|
||||
EXPECT_EQ(status, Status::OK);
|
||||
|
||||
bytesWritten = hBytesWritten;
|
||||
errorDetailMessage.assign(hDetailedError.c_str());
|
||||
});
|
||||
|
||||
EXPECT_EQ(0u, errorDetailMessage.size()) <<
|
||||
"WVCryptoPlugin reported a detailed error message.";
|
||||
}
|
||||
|
||||
TEST_F(WVCryptoPluginTest, DisallowsUnopenedSessionIdChanges) {
|
||||
android::sp<StrictMock<MockCDM>> cdm = new StrictMock<MockCDM>();
|
||||
|
||||
uint8_t blank[1]; // Some compilers will not accept 0.
|
||||
std::vector<uint8_t> sessionIdVector(sessionId, sessionId + kSessionIdSize);
|
||||
|
||||
// Specify the expected calls to IsOpenSession
|
||||
{
|
||||
InSequence calls;
|
||||
|
||||
EXPECT_CALL(*cdm, IsOpenSession(ElementsAreArray(blank, 0)))
|
||||
.WillOnce(testing::Return(false));
|
||||
|
||||
EXPECT_CALL(*cdm, IsOpenSession(ElementsAreArray(sessionId, kSessionIdSize)))
|
||||
.WillOnce(testing::Return(false))
|
||||
.WillOnce(testing::Return(true));
|
||||
}
|
||||
|
||||
WVCryptoPlugin plugin(blank, 0, cdm.get());
|
||||
|
||||
Status status = plugin.setMediaDrmSession(sessionIdVector);
|
||||
EXPECT_EQ(status, Status::ERROR_DRM_SESSION_NOT_OPENED);
|
||||
|
||||
status = plugin.setMediaDrmSession(sessionIdVector);
|
||||
EXPECT_EQ(status, Status::OK);
|
||||
}
|
||||
|
||||
} // namespace widevine
|
||||
} // namespace V1_4
|
||||
} // namespace drm
|
||||
} // namespace hardware
|
||||
} // namespace wvdrm
|
||||
Reference in New Issue
Block a user