Allow Setting of Session ID
Implements the optional setMediaDrmSession() method. To enble this, support was added to the core to report if a session ID is valid. As a consequence of this, in the tests for the CryptoPlugin, construction of the plugin must be deferred until all gMock expectations are set, as construction now calls into the CDM core. This is a merge of two changes from the Widevine CDM repo: http://go/wvgerrit/14083 Allow Setting of Session ID http://go/wvgerrit/14085 Check If Session ID Is Valid When Changing CryptoPlugin IDs Bug: 19570317 Change-Id: I7dbd777ce6efebd71fdb5e602663a0e35a48a9c4
This commit is contained in:
@@ -10,6 +10,8 @@
|
||||
#include "gtest/gtest.h"
|
||||
#include "media/stagefright/foundation/ABase.h"
|
||||
#include "media/stagefright/foundation/AString.h"
|
||||
#include "media/stagefright/MediaErrors.h"
|
||||
|
||||
#include "OEMCryptoCENC.h"
|
||||
#include "wv_cdm_constants.h"
|
||||
#include "wv_cdm_types.h"
|
||||
@@ -24,6 +26,8 @@ using namespace wvdrm;
|
||||
|
||||
class MockCDM : public WvContentDecryptionModule {
|
||||
public:
|
||||
MOCK_METHOD1(IsOpenSession, bool(const CdmSessionId&));
|
||||
|
||||
MOCK_METHOD3(Decrypt, CdmResponseType(const CdmSessionId&, bool,
|
||||
const CdmDecryptionParameters&));
|
||||
|
||||
@@ -48,20 +52,25 @@ class WVCryptoPluginTest : public Test {
|
||||
|
||||
TEST_F(WVCryptoPluginTest, CorrectlyReportsSecureBuffers) {
|
||||
StrictMock<MockCDM> cdm;
|
||||
WVCryptoPlugin plugin(sessionId, kSessionIdSize, &cdm);
|
||||
|
||||
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(Return(true));
|
||||
|
||||
// Specify the expected calls to QuerySessionStatus
|
||||
EXPECT_CALL(cdm, QuerySessionStatus(_, _))
|
||||
.WillOnce(DoAll(SetArgPointee<1>(l1Map),
|
||||
Return(wvcdm::NO_ERROR)))
|
||||
.WillOnce(DoAll(SetArgPointee<1>(l3Map),
|
||||
Return(wvcdm::NO_ERROR)));
|
||||
|
||||
WVCryptoPlugin plugin(sessionId, kSessionIdSize, &cdm);
|
||||
|
||||
EXPECT_TRUE(plugin.requiresSecureDecoderComponent("video/mp4")) <<
|
||||
"WVCryptoPlugin incorrectly allows an insecure video decoder on L1";
|
||||
EXPECT_FALSE(plugin.requiresSecureDecoderComponent("video/mp4")) <<
|
||||
@@ -140,7 +149,6 @@ class CDPMatcherFactory {
|
||||
|
||||
TEST_F(WVCryptoPluginTest, AttemptsToDecrypt) {
|
||||
StrictMock<MockCDM> cdm;
|
||||
WVCryptoPlugin plugin(sessionId, kSessionIdSize, &cdm);
|
||||
|
||||
uint8_t keyId[KEY_ID_SIZE];
|
||||
uint8_t baseIv[KEY_IV_SIZE];
|
||||
@@ -181,6 +189,11 @@ TEST_F(WVCryptoPluginTest, AttemptsToDecrypt) {
|
||||
|
||||
CDPMatcherFactory ParamsAre = CDPMatcherFactory(false, keyId, out, kDataSize);
|
||||
|
||||
// Provide the expected behavior for IsOpenSession
|
||||
EXPECT_CALL(cdm, IsOpenSession(_))
|
||||
.WillRepeatedly(Return(true));
|
||||
|
||||
// Specify the expected calls to Decrypt
|
||||
{
|
||||
InSequence calls;
|
||||
|
||||
@@ -233,6 +246,7 @@ TEST_F(WVCryptoPluginTest, AttemptsToDecrypt) {
|
||||
.Times(1);
|
||||
}
|
||||
|
||||
WVCryptoPlugin plugin(sessionId, kSessionIdSize, &cdm);
|
||||
AString errorDetailMessage;
|
||||
|
||||
ssize_t res = plugin.decrypt(false, keyId, iv[0], CryptoPlugin::kMode_AES_CTR,
|
||||
@@ -247,7 +261,6 @@ TEST_F(WVCryptoPluginTest, AttemptsToDecrypt) {
|
||||
|
||||
TEST_F(WVCryptoPluginTest, CommunicatesSecureBufferRequest) {
|
||||
StrictMock<MockCDM> cdm;
|
||||
WVCryptoPlugin plugin(sessionId, kSessionIdSize, &cdm);
|
||||
|
||||
uint8_t keyId[KEY_ID_SIZE];
|
||||
uint8_t iv[KEY_IV_SIZE];
|
||||
@@ -268,6 +281,10 @@ TEST_F(WVCryptoPluginTest, CommunicatesSecureBufferRequest) {
|
||||
subSamples[0].mNumBytesOfClearData = 16;
|
||||
subSamples[0].mNumBytesOfEncryptedData = 16;
|
||||
|
||||
// Provide the expected behavior for IsOpenSession
|
||||
EXPECT_CALL(cdm, IsOpenSession(_))
|
||||
.WillRepeatedly(Return(true));
|
||||
|
||||
// Specify the expected calls to Decrypt
|
||||
{
|
||||
InSequence calls;
|
||||
@@ -281,6 +298,7 @@ TEST_F(WVCryptoPluginTest, CommunicatesSecureBufferRequest) {
|
||||
.Times(2);
|
||||
}
|
||||
|
||||
WVCryptoPlugin plugin(sessionId, kSessionIdSize, &cdm);
|
||||
AString errorDetailMessage;
|
||||
|
||||
ssize_t res = plugin.decrypt(false, keyId, iv, CryptoPlugin::kMode_AES_CTR,
|
||||
@@ -301,7 +319,6 @@ TEST_F(WVCryptoPluginTest, CommunicatesSecureBufferRequest) {
|
||||
|
||||
TEST_F(WVCryptoPluginTest, SetsFlagsForMinimumSubsampleRuns) {
|
||||
MockCDM cdm;
|
||||
WVCryptoPlugin plugin(sessionId, kSessionIdSize, &cdm);
|
||||
|
||||
uint8_t keyId[KEY_ID_SIZE];
|
||||
uint8_t iv[KEY_IV_SIZE];
|
||||
@@ -330,6 +347,10 @@ TEST_F(WVCryptoPluginTest, SetsFlagsForMinimumSubsampleRuns) {
|
||||
mixedSubSamples[0].mNumBytesOfClearData = 8;
|
||||
mixedSubSamples[0].mNumBytesOfEncryptedData = 8;
|
||||
|
||||
// Provide the expected behavior for IsOpenSession
|
||||
EXPECT_CALL(cdm, IsOpenSession(_))
|
||||
.WillRepeatedly(Return(true));
|
||||
|
||||
// Specify the expected calls to Decrypt
|
||||
{
|
||||
InSequence calls;
|
||||
@@ -350,6 +371,7 @@ TEST_F(WVCryptoPluginTest, SetsFlagsForMinimumSubsampleRuns) {
|
||||
.Times(1);
|
||||
}
|
||||
|
||||
WVCryptoPlugin plugin(sessionId, kSessionIdSize, &cdm);
|
||||
AString errorDetailMessage;
|
||||
|
||||
ssize_t res = plugin.decrypt(false, keyId, iv, CryptoPlugin::kMode_AES_CTR,
|
||||
@@ -376,3 +398,101 @@ TEST_F(WVCryptoPluginTest, SetsFlagsForMinimumSubsampleRuns) {
|
||||
EXPECT_EQ(0u, errorDetailMessage.size()) <<
|
||||
"WVCryptoPlugin reported a detailed error message.";
|
||||
}
|
||||
|
||||
TEST_F(WVCryptoPluginTest, AllowsSessionIdChanges) {
|
||||
StrictMock<MockCDM> cdm;
|
||||
|
||||
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];
|
||||
uint8_t out[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);
|
||||
|
||||
static const uint32_t kSubSampleCount = 1;
|
||||
CryptoPlugin::SubSample subSamples[kSubSampleCount];
|
||||
memset(subSamples, 0, sizeof(subSamples));
|
||||
subSamples[0].mNumBytesOfClearData = 16;
|
||||
subSamples[0].mNumBytesOfEncryptedData = 16;
|
||||
|
||||
Vector<uint8_t> sessionIdVector;
|
||||
sessionIdVector.appendArray(sessionId, kSessionIdSize);
|
||||
Vector<uint8_t> sessionId2Vector;
|
||||
sessionId2Vector.appendArray(sessionId2, kSessionIdSize);
|
||||
|
||||
// Provide the expected behavior for IsOpenSession
|
||||
EXPECT_CALL(cdm, IsOpenSession(_))
|
||||
.WillRepeatedly(Return(true));
|
||||
|
||||
// Specify the expected calls to Decrypt
|
||||
{
|
||||
InSequence calls;
|
||||
|
||||
EXPECT_CALL(cdm,
|
||||
Decrypt(ElementsAreArray(sessionId, kSessionIdSize), _, _))
|
||||
.Times(2);
|
||||
|
||||
EXPECT_CALL(cdm,
|
||||
Decrypt(ElementsAreArray(sessionId2, kSessionIdSize), _, _))
|
||||
.Times(2);
|
||||
}
|
||||
|
||||
uint8_t blank[1]; // Some compilers will not accept 0.
|
||||
WVCryptoPlugin plugin(blank, 0, &cdm);
|
||||
AString errorDetailMessage;
|
||||
ssize_t res;
|
||||
|
||||
res = plugin.setMediaDrmSession(sessionIdVector);
|
||||
EXPECT_EQ(android::NO_ERROR, res);
|
||||
res = plugin.decrypt(false, keyId, iv, CryptoPlugin::kMode_AES_CTR, in,
|
||||
subSamples, kSubSampleCount, out, &errorDetailMessage);
|
||||
EXPECT_GE(res, 0) <<
|
||||
"WVCryptoPlugin returned an error";
|
||||
EXPECT_EQ(0u, errorDetailMessage.size()) <<
|
||||
"WVCryptoPlugin reported a detailed error message.";
|
||||
|
||||
res = plugin.setMediaDrmSession(sessionId2Vector);
|
||||
EXPECT_EQ(android::NO_ERROR, res);
|
||||
res = plugin.decrypt(false, keyId, iv, CryptoPlugin::kMode_AES_CTR, in,
|
||||
subSamples, kSubSampleCount, out, &errorDetailMessage);
|
||||
EXPECT_GE(res, 0) <<
|
||||
"WVCryptoPlugin returned an error";
|
||||
EXPECT_EQ(0u, errorDetailMessage.size()) <<
|
||||
"WVCryptoPlugin reported a detailed error message.";
|
||||
}
|
||||
|
||||
TEST_F(WVCryptoPluginTest, DisallowsUnopenedSessionIdChanges) {
|
||||
StrictMock<MockCDM> cdm;
|
||||
|
||||
uint8_t blank[1]; // Some compilers will not accept 0.
|
||||
Vector<uint8_t> sessionIdVector;
|
||||
sessionIdVector.appendArray(sessionId, kSessionIdSize);
|
||||
|
||||
// Specify the expected calls to IsOpenSession
|
||||
{
|
||||
InSequence calls;
|
||||
|
||||
EXPECT_CALL(cdm, IsOpenSession(ElementsAreArray(blank, 0)))
|
||||
.WillOnce(Return(false));
|
||||
|
||||
EXPECT_CALL(cdm, IsOpenSession(ElementsAreArray(sessionId, kSessionIdSize)))
|
||||
.WillOnce(Return(false))
|
||||
.WillOnce(Return(true));
|
||||
}
|
||||
|
||||
WVCryptoPlugin plugin(blank, 0, &cdm);
|
||||
|
||||
ssize_t res;
|
||||
res = plugin.setMediaDrmSession(sessionIdVector);
|
||||
EXPECT_EQ(android::ERROR_DRM_SESSION_NOT_OPENED, res);
|
||||
res = plugin.setMediaDrmSession(sessionIdVector);
|
||||
EXPECT_EQ(android::NO_ERROR, res);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user