Removes the status query from WVCryptoPlugin's decrypt method. It was not providing any additional security since it was not cryptographically secure, and querying status is an expensive operation on some devices. It should not be done on a frequent basis, such as in every decrypt call. Bug: 8667365 Merge of https://widevine-internal-review.googlesource.com/#/c/5121/ from widevine CDM repository to android repository. Change-Id: Id9a877c5655cb8dbee7e97f983d43ec2ab6acc6e
133 lines
4.6 KiB
C++
133 lines
4.6 KiB
C++
//
|
|
// Copyright 2013 Google Inc. All Rights Reserved.
|
|
//
|
|
|
|
#include <stdio.h>
|
|
#include <string>
|
|
#include <vector>
|
|
|
|
#include "gmock/gmock.h"
|
|
#include "gtest/gtest.h"
|
|
#include "media/stagefright/foundation/ABase.h"
|
|
#include "media/stagefright/foundation/AString.h"
|
|
#include "wv_cdm_constants.h"
|
|
#include "wv_cdm_types.h"
|
|
#include "wv_content_decryption_module.h"
|
|
#include "WVCryptoPlugin.h"
|
|
|
|
using namespace android;
|
|
using namespace std;
|
|
using namespace testing;
|
|
using namespace wvcdm;
|
|
using namespace wvdrm;
|
|
|
|
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*));
|
|
|
|
MOCK_METHOD1(QueryStatus, CdmResponseType(CdmQueryMap*));
|
|
};
|
|
|
|
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);
|
|
|
|
CdmQueryMap l1Map;
|
|
l1Map[QUERY_KEY_SECURITY_LEVEL] = QUERY_VALUE_SECURITY_LEVEL_L1;
|
|
|
|
CdmQueryMap l3Map;
|
|
l3Map[QUERY_KEY_SECURITY_LEVEL] = QUERY_VALUE_SECURITY_LEVEL_L3;
|
|
|
|
EXPECT_CALL(cdm, QueryStatus(_))
|
|
.WillOnce(DoAll(SetArgPointee<0>(l1Map),
|
|
Return(wvcdm::NO_ERROR)))
|
|
.WillOnce(DoAll(SetArgPointee<0>(l3Map),
|
|
Return(wvcdm::NO_ERROR)));
|
|
|
|
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";
|
|
}
|
|
|
|
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));
|
|
}
|
|
|
|
AString errorDetailMessage;
|
|
|
|
ssize_t res = plugin.decrypt(false, keyId, iv, CryptoPlugin::kMode_AES_CTR,
|
|
in, subSamples, kSubSampleCount, out,
|
|
&errorDetailMessage);
|
|
|
|
EXPECT_EQ(static_cast<ssize_t>(kDataSize), res) <<
|
|
"WVCryptoPlugin decrypted the wrong number of bytes";
|
|
EXPECT_EQ(0u, errorDetailMessage.size()) <<
|
|
"WVCryptoPlugin reported a detailed error message.";
|
|
} |