Combined Decrypt Calls

(This is a merge of http://go/wvgerrit/93829,
http://go/wvgerrit/93830, http://go/wvgerrit/93832,
http://go/wvgerrit/93833, and http://go/wvgerrit/93834 from the
Widevine repo.)

This implements the CDM code changes necessary to take advantage of
Combined Decrypt Calls on OEMCrypto v16. The result of this is that
WVCryptoPlugin is much lighter now because it can pass the full sample
down to the core in one call, but CryptoSession is heavier, as it now
has to handle more complex fallback logic when devices can't handle
multiple subsamples at once.

This patch also removes support for the 'cens' and 'cbc1' schema, which
are being dropped in OEMCrypto v16. This fixes an overflow in the code
for handling those schemas by removing it entirely.

This patch also fixes the "in chunks" legacy decrypt path to use larger
chunk sizes on devices with higher resource rating tiers.

Bug: 135285640
Bug: 123435824
Bug: 138584971
Bug: 139257871
Bug: 78289910
Bug: 149361893
Test: no new CE CDM Unit Test failures
Test: Google Play plays
Test: Netflix plays
Test: no new GTS failures
Change-Id: Ic4952c9fa3bc7fd5ed08698e88254380a7a18514
This commit is contained in:
John W. Bruce
2020-02-18 14:46:31 -08:00
parent 3708c4d53f
commit a62886b925
28 changed files with 1253 additions and 1260 deletions

View File

@@ -45,16 +45,20 @@ 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::CdmCencPatternEncryptionDescriptor;
using wvcdm::kCipherModeCbc;
using wvcdm::CdmCipherMode;
using wvcdm::CdmDecryptionParameters;
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;
@@ -65,8 +69,8 @@ class MockCDM : public wvcdm::WvContentDecryptionModule {
public:
MOCK_METHOD1(IsOpenSession, bool(const CdmSessionId&));
MOCK_METHOD3(Decrypt, CdmResponseType(const CdmSessionId&, bool,
const CdmDecryptionParameters&));
MOCK_METHOD3(DecryptV16, CdmResponseType(const CdmSessionId&, bool,
const CdmDecryptionParametersV16&));
MOCK_METHOD2(QuerySessionStatus, CdmResponseType(const CdmSessionId&,
CdmQueryMap*));
@@ -161,107 +165,95 @@ TEST_F(WVCryptoPluginTest, CorrectlyReportsSecureBuffers) {
"WVCryptoPlugin incorrectly expects a secure audio decoder";
}
// Factory for matchers that perform deep matching of values against a
// CdmDecryptionParameters struct. For use in the test AttemptsToDecrypt.
class CDPMatcherFactory {
public:
// Some values do not change over the course of the test. To avoid having
// to re-specify them at every call site, we pass them into the factory
// constructor.
CDPMatcherFactory(bool isSecure, CdmCipherMode cipherMode, uint8_t* keyId,
void* out, size_t outLen, bool isVideo)
: mIsSecure(isSecure), mCipherMode(cipherMode), mKeyId(keyId),
mOut(out), mOutLen(outLen), mIsVideo(isVideo) {}
// TODO(b/28295739):
// Add New MediaCrypto Unit Tests for CBC & Pattern Mode in cdmPatternDesc.
testing::Matcher<const CdmDecryptionParameters&> operator()(
bool isEncrypted,
uint8_t* in,
size_t inLen,
uint8_t* iv,
size_t blockOffset,
size_t outOffset,
uint8_t flags,
CdmCencPatternEncryptionDescriptor& cdmPatternDesc) const {
// TODO b/28295739
// Add New MediaCrypto Unit Tests for CBC & Pattern Mode
// in cdmPatternDesc.
return testing::Truly(CDPMatcher(mIsSecure, mCipherMode, mKeyId, mOut,
mOutLen, isEncrypted, in, inLen, iv,
blockOffset, outOffset, flags, mIsVideo,
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;
}
private:
// Predicate that validates that the fields of a passed-in
// CdmDecryptionParameters match the values it was given at construction
// time.
class CDPMatcher {
public:
// TODO b/35259313: Uncomment out parameters when addressed
CDPMatcher(bool isSecure, CdmCipherMode cipherMode, uint8_t* keyId,
void* /* out */, size_t outLen, bool isEncrypted,
uint8_t* /* in */, size_t inLen, uint8_t* iv,
size_t blockOffset, size_t outOffset, uint8_t flags,
bool isVideo,
CdmCencPatternEncryptionDescriptor& cdmPatternDesc)
: mIsSecure(isSecure), mCipherMode(cipherMode), mKeyId(keyId),
/* mOut(out), */ mOutLen(outLen), mIsEncrypted(isEncrypted),
/* mIn(in), */ mInLen(inLen), mIv(iv), mBlockOffset(blockOffset),
mOutOffset(outOffset), mFlags(flags), mIsVideo(isVideo),
mCdmPatternDesc(cdmPatternDesc) {}
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;
}
bool operator()(const CdmDecryptionParameters& params) const {
return params.is_secure == mIsSecure &&
params.cipher_mode == mCipherMode &&
Value(*params.key_id, ElementsAreArray(mKeyId, KEY_ID_SIZE)) &&
// TODO b/35259313
// Converts mOut from hidl address to physical address
// params.decrypt_buffer == mOut &&
params.decrypt_buffer_length == mOutLen &&
params.is_encrypted == mIsEncrypted &&
// TODO b/35259313
// Converts mIn from hidl address to physical address
// params.encrypt_buffer == mIn &&
params.encrypt_length == mInLen &&
Value(*params.iv, ElementsAreArray(mIv, KEY_IV_SIZE)) &&
params.block_offset == mBlockOffset &&
params.decrypt_buffer_offset == mOutOffset &&
params.subsample_flags == mFlags &&
params.is_video == mIsVideo;
}
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;
}
private:
bool mIsSecure;
CdmCipherMode mCipherMode;
uint8_t* mKeyId;
// TODO b/35259313
//void* mOut;
size_t mOutLen;
bool mIsEncrypted;
// TODO b/35259313
//uint8_t* mIn;
size_t mInLen;
uint8_t* mIv;
size_t mBlockOffset;
size_t mOutOffset;
uint8_t mFlags;
bool mIsVideo;
CdmCencPatternEncryptionDescriptor mCdmPatternDesc;
};
for (size_t i = 0; i < mSubsamples.size(); ++i) {
const SubSample& androidSubsample = mSubsamples[i];
const CdmDecryptionSubsample& cdmSubsample = sample.subsamples[i];
bool mIsSecure;
CdmCipherMode mCipherMode;
uint8_t* mKeyId;
void* mOut;
size_t mOutLen;
bool mIsVideo;
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>();
static const size_t kSubSampleCount = 6;
constexpr size_t kSubSampleCount = 6;
SubSample subSamples[kSubSampleCount];
memset(subSamples, 0, sizeof(subSamples));
subSamples[0].numBytesOfEncryptedData = 16;
@@ -277,16 +269,16 @@ TEST_F(WVCryptoPluginTest, AttemptsToDecrypt) {
subSamples, subSamples + sizeof(subSamples) / sizeof(subSamples[0]));
auto hSubSamples = hidl_vec<SubSample>(subSamplesVector);
uint8_t baseIv[KEY_IV_SIZE];
uint8_t keyId[KEY_ID_SIZE];
uint8_t iv[KEY_IV_SIZE];
static const size_t kDataSize = 185;
uint8_t in[kDataSize];
uint8_t inputData[kDataSize];
FILE* fp = fopen("/dev/urandom", "r");
fread(keyId, sizeof(uint8_t), KEY_ID_SIZE, fp);
fread(baseIv, sizeof(uint8_t), KEY_IV_SIZE, fp);
fread(in, sizeof(uint8_t), kDataSize, fp);
fread(iv, sizeof(uint8_t), KEY_IV_SIZE, fp);
fread(inputData, sizeof(uint8_t), kDataSize, fp);
fclose(fp);
sp<MemoryDealer> memDealer = new MemoryDealer(
@@ -296,7 +288,7 @@ TEST_F(WVCryptoPluginTest, AttemptsToDecrypt) {
pSrc = static_cast<uint8_t*>(
static_cast<void*>(source->unsecurePointer()));
ASSERT_NE(pSrc, nullptr);
memcpy(pSrc, in, source->size());
memcpy(pSrc, inputData, source->size());
sp<android::IMemory> destination = memDealer->allocate(kDataSize);
ASSERT_NE(destination, nullptr);
@@ -304,84 +296,21 @@ TEST_F(WVCryptoPluginTest, AttemptsToDecrypt) {
static_cast<void*>(destination->unsecurePointer()));
ASSERT_NE(pDest, nullptr);
uint8_t iv[5][KEY_IV_SIZE];
memcpy(iv[0], baseIv, sizeof(baseIv));
iv[0][15] = 0;
memcpy(iv[1], baseIv, sizeof(baseIv));
iv[1][15] = 1;
memcpy(iv[2], baseIv, sizeof(baseIv));
iv[2][15] = 2;
memcpy(iv[3], baseIv, sizeof(baseIv));
iv[3][15] = 4;
memcpy(iv[4], baseIv, sizeof(baseIv));
iv[4][15] = 7;
CdmCencPatternEncryptionDescriptor cdmPattern;
CDPMatcherFactory ParamsAre =
CDPMatcherFactory(false, kCipherModeCtr, keyId, pDest, kDataSize, true);
Pattern noPattern = { 0, 0 };
// Provide the expected behavior for IsOpenSession
EXPECT_CALL(*cdm, IsOpenSession(_))
.WillRepeatedly(testing::Return(true));
// Specify the expected calls to Decrypt
{
InSequence calls;
CDPMatcher paramsMatcher(keyId, false, Mode::AES_CTR, noPattern, pSrc,
kDataSize, pDest, kDataSize, iv, subSamples,
kSubSampleCount);
// SubSample 0
EXPECT_CALL(*cdm, Decrypt(ElementsAreArray(sessionId, kSessionIdSize),
true,
ParamsAre(true, pSrc, 16, iv[0], 0, 0,
OEMCrypto_FirstSubsample, cdmPattern)))
.Times(1);
// SubSample 1
EXPECT_CALL(*cdm, Decrypt(ElementsAreArray(sessionId, kSessionIdSize),
true,
ParamsAre(false, pSrc + 16, 16, iv[1], 0, 16, 0,
cdmPattern)))
.Times(1);
EXPECT_CALL(*cdm, Decrypt(ElementsAreArray(sessionId, kSessionIdSize),
true,
ParamsAre(true, pSrc + 32, 16, iv[1], 0, 32, 0,
cdmPattern)))
.Times(1);
// SubSample 2
EXPECT_CALL(*cdm, Decrypt(ElementsAreArray(sessionId, kSessionIdSize),
true,
ParamsAre(true, pSrc + 48, 8, iv[2], 0, 48, 0,
cdmPattern)))
.Times(1);
// SubSample 3
EXPECT_CALL(*cdm, Decrypt(ElementsAreArray(sessionId, kSessionIdSize),
true,
ParamsAre(false, pSrc + 56, 29, iv[2], 0, 56, 0,
cdmPattern)))
.Times(1);
EXPECT_CALL(*cdm, Decrypt(ElementsAreArray(sessionId, kSessionIdSize),
true,
ParamsAre(true, pSrc + 85, 24, iv[2], 8, 85, 0,
cdmPattern)))
.Times(1);
// SubSample 4
EXPECT_CALL(*cdm, Decrypt(ElementsAreArray(sessionId, kSessionIdSize),
true,
ParamsAre(true, pSrc + 109, 60, iv[3], 0, 109, 0,
cdmPattern)))
.Times(1);
// SubSample 5
EXPECT_CALL(*cdm, Decrypt(ElementsAreArray(sessionId, kSessionIdSize),
true,
ParamsAre(true, pSrc + 169, 16, iv[4], 12, 169,
OEMCrypto_LastSubsample, cdmPattern)))
.Times(1);
}
EXPECT_CALL(*cdm, DecryptV16(ElementsAreArray(sessionId, kSessionIdSize),
true,
Truly(paramsMatcher)))
.Times(1);
WVCryptoPlugin plugin(sessionId, kSessionIdSize, cdm.get());
@@ -390,13 +319,12 @@ TEST_F(WVCryptoPluginTest, AttemptsToDecrypt) {
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[0]),
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);
@@ -411,6 +339,87 @@ TEST_F(WVCryptoPluginTest, AttemptsToDecrypt) {
"WVCryptoPlugin reported a detailed error message.";
}
TEST_F(WVCryptoPluginTest, RejectsCensAndCbc1) {
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 noPattern = { 0, 0 };
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);
});
plugin.decrypt(
false, hidl_array<uint8_t, 16>(keyId), hidl_array<uint8_t, 16>(iv),
Mode::AES_CBC, noPattern, 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>();
@@ -441,13 +450,13 @@ TEST_F(WVCryptoPluginTest, CommunicatesSecureBufferRequest) {
{
InSequence calls;
typedef CdmDecryptionParameters CDP;
typedef CdmDecryptionParametersV16 CDP;
EXPECT_CALL(*cdm, Decrypt(_, _, Field(&CDP::is_secure, false)))
.Times(2);
EXPECT_CALL(*cdm, DecryptV16(_, _, Field(&CDP::is_secure, false)))
.Times(1);
EXPECT_CALL(*cdm, Decrypt(_, _, Field(&CDP::is_secure, true)))
.Times(2);
EXPECT_CALL(*cdm, DecryptV16(_, _, Field(&CDP::is_secure, true)))
.Times(1);
}
sp<MemoryDealer> memDealer = new MemoryDealer(
@@ -504,134 +513,6 @@ TEST_F(WVCryptoPluginTest, CommunicatesSecureBufferRequest) {
"WVCryptoPlugin reported a detailed error message.";
}
TEST_F(WVCryptoPluginTest, SetsFlagsForMinimumSubsampleRuns) {
android::sp<MockCDM> cdm = new MockCDM();
uint8_t keyId[KEY_ID_SIZE];
uint8_t iv[KEY_IV_SIZE];
static const size_t kDataSize = 16;
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 clearSubSample;
clearSubSample.numBytesOfClearData = 16;
clearSubSample.numBytesOfEncryptedData = 0;
std::vector<SubSample> clearSubSampleVector;
clearSubSampleVector.push_back(clearSubSample);
auto hClearSubSamples = hidl_vec<SubSample>(clearSubSampleVector);
SubSample encryptedSubSample;
encryptedSubSample.numBytesOfClearData = 0;
encryptedSubSample.numBytesOfEncryptedData = 16;
std::vector<SubSample> encryptedSubSampleVector;
encryptedSubSampleVector.push_back(encryptedSubSample);
auto hEncryptedSubSamples = hidl_vec<SubSample>(encryptedSubSampleVector);
SubSample mixedSubSample;
mixedSubSample.numBytesOfClearData = 8;
mixedSubSample.numBytesOfEncryptedData = 8;
std::vector<SubSample> mixedSubSampleVector;
mixedSubSampleVector.push_back(mixedSubSample);
auto hMixedSubSamples = hidl_vec<SubSample>(mixedSubSampleVector);
// Provide the expected behavior for IsOpenSession
EXPECT_CALL(*cdm, IsOpenSession(_))
.WillRepeatedly(testing::Return(true));
// Specify the expected calls to Decrypt
{
InSequence calls;
typedef CdmDecryptionParameters CDP;
EXPECT_CALL(*cdm, Decrypt(_, _, Field(&CDP::subsample_flags,
OEMCrypto_FirstSubsample |
OEMCrypto_LastSubsample)))
.Times(2);
EXPECT_CALL(*cdm, Decrypt(_, _, Field(&CDP::subsample_flags,
OEMCrypto_FirstSubsample)))
.Times(1);
EXPECT_CALL(*cdm, Decrypt(_, _, Field(&CDP::subsample_flags,
OEMCrypto_LastSubsample)))
.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, hClearSubSamples, 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(
false, hidl_array<uint8_t, 16>(keyId), hidl_array<uint8_t, 16>(iv),
Mode::AES_CTR, noPattern, hEncryptedSubSamples, 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(
false, hidl_array<uint8_t, 16>(keyId), hidl_array<uint8_t, 16>(iv),
Mode::AES_CTR, noPattern, hMixedSubSamples, 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>();
@@ -669,12 +550,12 @@ TEST_F(WVCryptoPluginTest, AllowsSessionIdChanges) {
InSequence calls;
EXPECT_CALL(*cdm,
Decrypt(ElementsAreArray(sessionId, kSessionIdSize), _, _))
.Times(2);
DecryptV16(ElementsAreArray(sessionId, kSessionIdSize), _, _))
.Times(1);
EXPECT_CALL(*cdm,
Decrypt(ElementsAreArray(sessionId2, kSessionIdSize), _, _))
.Times(2);
DecryptV16(ElementsAreArray(sessionId2, kSessionIdSize), _, _))
.Times(1);
}
sp<MemoryDealer> memDealer = new MemoryDealer(