Commit caebb755 authored by Rintaro Kuroiwa's avatar Rintaro Kuroiwa Committed by Commit Bot

Check crypto session key exchange methods in D3D11CdmProxy

- Crypto session key exchange method should be HW key exchange.

Cq-Include-Trybots: luci.chromium.try:android_optional_gpu_tests_rel;luci.chromium.try:linux_optional_gpu_tests_rel;luci.chromium.try:mac_optional_gpu_tests_rel;luci.chromium.try:win_optional_gpu_tests_rel
Change-Id: Iad92618778da0b83860cd6a4de19e829b03a667a
Reviewed-on: https://chromium-review.googlesource.com/1087318
Commit-Queue: Rintaro Kuroiwa <rkuroiwa@chromium.org>
Reviewed-by: default avatarXiaohan Wang <xhwang@chromium.org>
Cr-Commit-Position: refs/heads/master@{#568665}
parent e9883cd1
......@@ -18,6 +18,39 @@ namespace media {
namespace {
// Checks whether there is a hardware protected key exhange method.
// https://msdn.microsoft.com/en-us/library/windows/desktop/dn894125(v=vs.85).aspx
// The key exhange capabilities are checked using these.
// https://msdn.microsoft.com/en-us/library/windows/desktop/hh447640%28v=vs.85%29.aspx?f=255&MSPPError=-2147217396
// https://msdn.microsoft.com/en-us/library/windows/desktop/hh447782(v=vs.85).aspx
bool CanDoHardwareProtectedKeyExchange(
Microsoft::WRL::ComPtr<ID3D11VideoDevice> video_device,
const GUID& crypto_type) {
D3D11_VIDEO_CONTENT_PROTECTION_CAPS caps = {};
HRESULT hresult = video_device->GetContentProtectionCaps(
&crypto_type, &D3D11_DECODER_PROFILE_H264_VLD_NOFGT, &caps);
if (FAILED(hresult)) {
DVLOG(1) << "Failed to get content protection caps.";
return false;
}
for (uint32_t i = 0; i < caps.KeyExchangeTypeCount; ++i) {
GUID kex_guid = {};
hresult = video_device->CheckCryptoKeyExchange(
&crypto_type, &D3D11_DECODER_PROFILE_H264_VLD_NOFGT, i, &kex_guid);
if (FAILED(hresult)) {
DVLOG(1) << "Failed to get key exchange GUID";
return false;
}
if (kex_guid == D3D11_KEY_EXCHANGE_HW_PROTECTION)
return true;
}
DVLOG(1) << "Hardware key exchange is not supported.";
return false;
}
class D3D11CdmProxyContext : public CdmProxyContext {
public:
explicit D3D11CdmProxyContext(const GUID& key_info_guid)
......@@ -183,6 +216,12 @@ void D3D11CdmProxy::Initialize(Client* client, InitializeCB init_cb) {
return;
}
if (!CanDoHardwareProtectedKeyExchange(video_device_, crypto_type_)) {
DLOG(ERROR) << "Cannot do hardware proteted key exhange.";
failed();
return;
}
hresult = device_context_.CopyTo(video_context_.GetAddressOf());
if (FAILED(hresult)) {
DLOG(ERROR) << "Failed to get ID3D11VideoContext: " << hresult;
......
......@@ -18,6 +18,7 @@ using ::testing::AllOf;
using ::testing::AtLeast;
using ::testing::DoAll;
using ::testing::Invoke;
using ::testing::Lt;
using ::testing::Ne;
using ::testing::Pointee;
using ::testing::Return;
......@@ -76,12 +77,86 @@ class D3D11CdmProxyTest : public ::testing::Test {
video_context_mock_ = CreateD3D11Mock<D3D11VideoContextMock>();
video_context1_mock_ = CreateD3D11Mock<D3D11VideoContext1Mock>();
// These flags are a reasonable subset of flags to get HARDWARE protected
// playback.
content_protection_caps_.Caps =
D3D11_CONTENT_PROTECTION_CAPS_HARDWARE |
D3D11_CONTENT_PROTECTION_CAPS_HARDWARE_PROTECT_UNCOMPRESSED |
D3D11_CONTENT_PROTECTION_CAPS_HARDWARE_PROTECTED_MEMORY_PAGEABLE |
D3D11_CONTENT_PROTECTION_CAPS_HARDWARE_TEARDOWN |
D3D11_CONTENT_PROTECTION_CAPS_HARDWARE_DRM_COMMUNICATION;
// 1 for the mock behavior below for CheckCryptoKeyExchange().
content_protection_caps_.KeyExchangeTypeCount = 1;
// This is arbitrary but 1 is reasonable, meaning doesn't need to be
// aligned.
content_protection_caps_.BlockAlignmentSize = 1;
// This value is arbitrary.
content_protection_caps_.ProtectedMemorySize = 10000000;
OnCallsForInitialize();
proxy_->SetCreateDeviceCallbackForTesting(
base::BindRepeating(&D3D11CreateDeviceMock::Create,
base::Unretained(&create_device_mock_)));
}
// Helper method to do Initialize(). Only useful if the test doesn't require
// access to the mocks later.
// Sets up ON_CALLs for the mock objects. These can be overriden with
// EXPECT_CALLs.
// |content_protection_caps_| should be set.
void OnCallsForInitialize() {
ON_CALL(create_device_mock_,
Create(_, D3D_DRIVER_TYPE_HARDWARE, _, _, _, _, _, _, _, _))
.WillByDefault(
DoAll(AddRefAndSetArgPointee<7>(device_mock_.Get()),
AddRefAndSetArgPointee<9>(device_context_mock_.Get()),
Return(S_OK)));
ON_CALL(*device_mock_.Get(), QueryInterface(IID_ID3D11VideoDevice, _))
.WillByDefault(DoAll(
AddRefAndSetArgPointee<1>(video_device_mock_.Get()), Return(S_OK)));
ON_CALL(*device_mock_.Get(), QueryInterface(IID_ID3D11VideoDevice1, _))
.WillByDefault(
DoAll(AddRefAndSetArgPointee<1>(video_device1_mock_.Get()),
Return(S_OK)));
ON_CALL(*device_context_mock_.Get(),
QueryInterface(IID_ID3D11VideoContext, _))
.WillByDefault(
DoAll(AddRefAndSetArgPointee<1>(video_context_mock_.Get()),
Return(S_OK)));
ON_CALL(*device_context_mock_.Get(),
QueryInterface(IID_ID3D11VideoContext1, _))
.WillByDefault(
DoAll(AddRefAndSetArgPointee<1>(video_context1_mock_.Get()),
Return(S_OK)));
ON_CALL(*video_device_mock_.Get(),
CreateCryptoSession(Pointee(CRYPTO_TYPE_GUID), _,
Pointee(D3D11_KEY_EXCHANGE_HW_PROTECTION), _))
.WillByDefault(
DoAll(AddRefAndSetArgPointee<3>(crypto_session_mock_.Get()),
Return(S_OK)));
ON_CALL(
*video_device1_mock_.Get(),
GetCryptoSessionPrivateDataSize(Pointee(CRYPTO_TYPE_GUID), _, _, _, _))
.WillByDefault(DoAll(SetArgPointee<3>(kPrivateInputSize),
SetArgPointee<4>(kPrivateOutputSize),
Return(S_OK)));
ON_CALL(*video_device_mock_.Get(), GetContentProtectionCaps(_, _, _))
.WillByDefault(
DoAll(SetArgPointee<2>(content_protection_caps_), Return(S_OK)));
ON_CALL(*video_device_mock_.Get(), CheckCryptoKeyExchange(_, _, Lt(1u), _))
.WillByDefault(DoAll(SetArgPointee<3>(D3D11_KEY_EXCHANGE_HW_PROTECTION),
Return(S_OK)));
}
// Helper method to do Initialize(), sets up EXPECT_CALLs for a successful
// initialization.
void Initialize(CdmProxy::InitializeCB callback) {
EXPECT_CALL(create_device_mock_,
Create(_, D3D_DRIVER_TYPE_HARDWARE, _, _, _, _, _, _, _, _))
......@@ -148,6 +223,7 @@ class D3D11CdmProxyTest : public ::testing::Test {
Microsoft::WRL::ComPtr<D3D11DeviceContextMock> device_context_mock_;
Microsoft::WRL::ComPtr<D3D11VideoContextMock> video_context_mock_;
Microsoft::WRL::ComPtr<D3D11VideoContext1Mock> video_context1_mock_;
D3D11_VIDEO_CONTENT_PROTECTION_CAPS content_protection_caps_ = {};
// These size values are arbitrary. Used for mocking
// GetCryptoSessionPrivateDataSize().
......@@ -173,6 +249,22 @@ TEST_F(D3D11CdmProxyTest, Initialize) {
&CallbackMock::InitializeCallback, base::Unretained(&callback_mock_))));
}
// Initialization failure because HW key exchange is not available.
TEST_F(D3D11CdmProxyTest, NoHwKeyExchange) {
EXPECT_CALL(callback_mock_,
InitializeCallback(CdmProxy::Status::kFail, _, _));
// GUID is set to non-D3D11_KEY_EXCHANGE_HW_PROTECTION, which means no HW key
// exchange.
EXPECT_CALL(*video_device_mock_.Get(),
CheckCryptoKeyExchange(_, _, Lt(1u), _))
.WillOnce(
DoAll(SetArgPointee<3>(D3D11_CRYPTO_TYPE_AES128_CTR), Return(S_OK)));
proxy_->Initialize(nullptr,
base::BindOnce(&CallbackMock::InitializeCallback,
base::Unretained(&callback_mock_)));
}
// Verifies that Process() won't work if not initialized.
TEST_F(D3D11CdmProxyTest, ProcessUninitialized) {
// The size nor value here matter, so making non empty non zero vector.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment