From 95cc5af781a0b92f8acc3aae6ba58e5bb0a91c63 Mon Sep 17 00:00:00 2001 From: Chong Zhang Date: Wed, 25 Oct 2017 13:40:28 -0700 Subject: [PATCH] cas: add vts test to catch oob in descrambling requests bug: 67962232 test: cts MediaCasTest vts VtsHalCasV1_0Target Change-Id: I825e8cefb0d6f8e183e96ee2ebfbe0be1572dca8 --- .../functional/VtsHalCasV1_0TargetTest.cpp | 233 +++++++++++++++++- 1 file changed, 230 insertions(+), 3 deletions(-) diff --git a/cas/1.0/vts/functional/VtsHalCasV1_0TargetTest.cpp b/cas/1.0/vts/functional/VtsHalCasV1_0TargetTest.cpp index d3b0f1da3b..193253ac7f 100644 --- a/cas/1.0/vts/functional/VtsHalCasV1_0TargetTest.cpp +++ b/cas/1.0/vts/functional/VtsHalCasV1_0TargetTest.cpp @@ -223,12 +223,26 @@ class MediaCasHidlTest : public ::testing::VtsHalHidlTargetTestBase { sp mMediaCas; sp mDescramblerBase; sp mCasListener; + typedef struct _OobInputTestParams { + const SubSample* subSamples; + uint32_t numSubSamples; + size_t imemSizeActual; + uint64_t imemOffset; + uint64_t imemSize; + uint64_t srcOffset; + uint64_t dstOffset; + } OobInputTestParams; ::testing::AssertionResult createCasPlugin(int32_t caSystemId); ::testing::AssertionResult openCasSession(std::vector* sessionId); - ::testing::AssertionResult descrambleTestInputBuffer(const sp& descrambler, - Status* descrambleStatus, - sp* hidlInMemory); + ::testing::AssertionResult descrambleTestInputBuffer( + const sp& descrambler, + Status* descrambleStatus, + sp* hidlInMemory); + ::testing::AssertionResult descrambleTestOobInput( + const sp& descrambler, + Status* descrambleStatus, + const OobInputTestParams& params); }; ::testing::AssertionResult MediaCasHidlTest::createCasPlugin(int32_t caSystemId) { @@ -332,6 +346,72 @@ class MediaCasHidlTest : public ::testing::VtsHalHidlTargetTestBase { return ::testing::AssertionResult(returnVoid.isOk()); } +::testing::AssertionResult MediaCasHidlTest::descrambleTestOobInput( + const sp& descrambler, + Status* descrambleStatus, + const OobInputTestParams& params) { + hidl_vec hidlSubSamples; + hidlSubSamples.setToExternal( + const_cast(params.subSamples), params.numSubSamples, false /*own*/); + + sp dealer = new MemoryDealer(params.imemSizeActual, "vts-cas"); + if (nullptr == dealer.get()) { + ALOGE("couldn't get MemoryDealer!"); + return ::testing::AssertionFailure(); + } + + sp mem = dealer->allocate(params.imemSizeActual); + if (nullptr == mem.get()) { + ALOGE("couldn't allocate IMemory!"); + return ::testing::AssertionFailure(); + } + + // build hidl_memory from memory heap + ssize_t offset; + size_t size; + sp heap = mem->getMemory(&offset, &size); + if (nullptr == heap.get()) { + ALOGE("couldn't get memory heap!"); + return ::testing::AssertionFailure(); + } + + native_handle_t* nativeHandle = native_handle_create(1, 0); + if (!nativeHandle) { + ALOGE("failed to create native handle!"); + return ::testing::AssertionFailure(); + } + nativeHandle->data[0] = heap->getHeapID(); + + SharedBuffer srcBuffer = { + .heapBase = hidl_memory("ashmem", hidl_handle(nativeHandle), heap->getSize()), + .offset = (uint64_t) offset + params.imemOffset, + .size = (uint64_t) params.imemSize, + }; + + DestinationBuffer dstBuffer; + dstBuffer.type = BufferType::SHARED_MEMORY; + dstBuffer.nonsecureMemory = srcBuffer; + + uint32_t outBytes; + hidl_string detailedError; + auto returnVoid = descrambler->descramble( + ScramblingControl::EVENKEY /*2*/, hidlSubSamples, + srcBuffer, + params.srcOffset, + dstBuffer, + params.dstOffset, + [&](Status status, uint32_t bytesWritten, const hidl_string& detailedErr) { + *descrambleStatus = status; + outBytes = bytesWritten; + detailedError = detailedErr; + }); + if (!returnVoid.isOk() || *descrambleStatus != Status::OK) { + ALOGI("descramble failed, trans=%s, status=%d, outBytes=%u, error=%s", + returnVoid.description().c_str(), *descrambleStatus, outBytes, detailedError.c_str()); + } + return ::testing::AssertionResult(returnVoid.isOk()); +} + TEST_F(MediaCasHidlTest, EnumeratePlugins) { description("Test enumerate plugins"); hidl_vec descriptors; @@ -613,6 +693,153 @@ TEST_F(MediaCasHidlTest, TestClearKeyErrors) { EXPECT_FALSE(mDescramblerBase->requiresSecureDecoderComponent("bad")); } +TEST_F(MediaCasHidlTest, TestClearKeyOobFails) { + description("Test that oob descramble request fails with expected error"); + + ASSERT_TRUE(createCasPlugin(CLEAR_KEY_SYSTEM_ID)); + + auto returnStatus = mMediaCas->provision(hidl_string(PROVISION_STR)); + EXPECT_TRUE(returnStatus.isOk()); + EXPECT_EQ(Status::OK, returnStatus); + + std::vector sessionId; + ASSERT_TRUE(openCasSession(&sessionId)); + + returnStatus = mDescramblerBase->setMediaCasSession(sessionId); + EXPECT_TRUE(returnStatus.isOk()); + EXPECT_EQ(Status::OK, returnStatus); + + hidl_vec hidlEcm; + hidlEcm.setToExternal(const_cast(kEcmBinaryBuffer), sizeof(kEcmBinaryBuffer)); + returnStatus = mMediaCas->processEcm(sessionId, hidlEcm); + EXPECT_TRUE(returnStatus.isOk()); + EXPECT_EQ(Status::OK, returnStatus); + + sp descrambler = IDescrambler::castFrom(mDescramblerBase); + ASSERT_NE(nullptr, descrambler.get()); + + Status descrambleStatus = Status::OK; + + // test invalid src buffer offset + ASSERT_TRUE(descrambleTestOobInput( + descrambler, + &descrambleStatus, + { + .subSamples = kSubSamples, + .numSubSamples = sizeof(kSubSamples)/sizeof(SubSample), + .imemSizeActual = sizeof(kInBinaryBuffer), + .imemOffset = 0xcccccc, + .imemSize = sizeof(kInBinaryBuffer), + .srcOffset = 0, + .dstOffset = 0 + })); + EXPECT_EQ(Status::BAD_VALUE, descrambleStatus); + + // test invalid src buffer size + ASSERT_TRUE(descrambleTestOobInput( + descrambler, + &descrambleStatus, + { + .subSamples = kSubSamples, + .numSubSamples = sizeof(kSubSamples)/sizeof(SubSample), + .imemSizeActual = sizeof(kInBinaryBuffer), + .imemOffset = 0, + .imemSize = 0xcccccc, + .srcOffset = 0, + .dstOffset = 0 + })); + EXPECT_EQ(Status::BAD_VALUE, descrambleStatus); + + // test invalid src buffer size + ASSERT_TRUE(descrambleTestOobInput( + descrambler, + &descrambleStatus, + { + .subSamples = kSubSamples, + .numSubSamples = sizeof(kSubSamples)/sizeof(SubSample), + .imemSizeActual = sizeof(kInBinaryBuffer), + .imemOffset = 1, + .imemSize = (uint64_t)-1, + .srcOffset = 0, + .dstOffset = 0 + })); + EXPECT_EQ(Status::BAD_VALUE, descrambleStatus); + + // test invalid srcOffset + ASSERT_TRUE(descrambleTestOobInput( + descrambler, + &descrambleStatus, + { + .subSamples = kSubSamples, + .numSubSamples = sizeof(kSubSamples)/sizeof(SubSample), + .imemSizeActual = sizeof(kInBinaryBuffer), + .imemOffset = 0, + .imemSize = sizeof(kInBinaryBuffer), + .srcOffset = 0xcccccc, + .dstOffset = 0 + })); + EXPECT_EQ(Status::BAD_VALUE, descrambleStatus); + + // test invalid dstOffset + ASSERT_TRUE(descrambleTestOobInput( + descrambler, + &descrambleStatus, + { + .subSamples = kSubSamples, + .numSubSamples = sizeof(kSubSamples)/sizeof(SubSample), + .imemSizeActual = sizeof(kInBinaryBuffer), + .imemOffset = 0, + .imemSize = sizeof(kInBinaryBuffer), + .srcOffset = 0, + .dstOffset = 0xcccccc + })); + EXPECT_EQ(Status::BAD_VALUE, descrambleStatus); + + // test detection of oob subsample sizes + const SubSample invalidSubSamples1[] = + {{162, 0}, {0, 184}, {0, 0xdddddd}}; + + ASSERT_TRUE(descrambleTestOobInput( + descrambler, + &descrambleStatus, + { + .subSamples = invalidSubSamples1, + .numSubSamples = sizeof(invalidSubSamples1)/sizeof(SubSample), + .imemSizeActual = sizeof(kInBinaryBuffer), + .imemOffset = 0, + .imemSize = sizeof(kInBinaryBuffer), + .srcOffset = 0, + .dstOffset = 0 + })); + EXPECT_EQ(Status::BAD_VALUE, descrambleStatus); + + // test detection of overflowing subsample sizes + const SubSample invalidSubSamples2[] = + {{162, 0}, {0, 184}, {2, (uint32_t)-1}}; + + ASSERT_TRUE(descrambleTestOobInput( + descrambler, + &descrambleStatus, + { + .subSamples = invalidSubSamples2, + .numSubSamples = sizeof(invalidSubSamples2)/sizeof(SubSample), + .imemSizeActual = sizeof(kInBinaryBuffer), + .imemOffset = 0, + .imemSize = sizeof(kInBinaryBuffer), + .srcOffset = 0, + .dstOffset = 0 + })); + EXPECT_EQ(Status::BAD_VALUE, descrambleStatus); + + returnStatus = mDescramblerBase->release(); + EXPECT_TRUE(returnStatus.isOk()); + EXPECT_EQ(Status::OK, returnStatus); + + returnStatus = mMediaCas->release(); + EXPECT_TRUE(returnStatus.isOk()); + EXPECT_EQ(Status::OK, returnStatus); +} + } // anonymous namespace int main(int argc, char** argv) {