From 5249221e3a26edd224f7b241180482cd5a05b846 Mon Sep 17 00:00:00 2001 From: "John W. Bruce" Date: Tue, 24 Jan 2017 16:54:43 -0800 Subject: [PATCH] Report 3072-bit Certificate Capability (This is a merge of go/wvgerrit/23154) This patch updates the ClientCapabilities protobuf to match the latest on the server side and adds plumbing to the provisioning request process so that devices can report whether they like big certs. Their capacity to lie remains untested. Bug: 34076937 Test: license_unittest Change-Id: I3bcc9f1741146953d8bc0ff3d7d2305e7ac2c118 --- .../cdm/core/include/crypto_session.h | 9 ++++++++- libwvdrmengine/cdm/core/src/crypto_session.cpp | 18 ++++++++++++++++++ libwvdrmengine/cdm/core/src/license.cpp | 18 +++++++++++++++++- .../cdm/core/src/license_protocol.proto | 6 ++++++ .../cdm/core/test/license_unittest.cpp | 17 +++++++++++++++++ 5 files changed, 66 insertions(+), 2 deletions(-) diff --git a/libwvdrmengine/cdm/core/include/crypto_session.h b/libwvdrmengine/cdm/core/include/crypto_session.h index 8e7385e4..dd6dd139 100644 --- a/libwvdrmengine/cdm/core/include/crypto_session.h +++ b/libwvdrmengine/cdm/core/include/crypto_session.h @@ -26,6 +26,12 @@ class CryptoSession { kUsageDurationsValid = 2, } UsageDurationStatus; + struct SupportedCertificateTypes { + bool rsa_2048_bit; + bool rsa_3072_bit; + bool rsa_cast; + }; + CryptoSession(); virtual ~CryptoSession(); @@ -97,13 +103,14 @@ class CryptoSession { const std::string& provider_session_token); // Delete usage information for a list of tokens. This does not require // a signed message from the server. - virtual CdmResponseType DeleteMultipleUsageInformation( + virtual CdmResponseType DeleteMultipleUsageInformation( const std::vector& provider_session_tokens); virtual CdmResponseType DeleteAllUsageReports(); virtual bool IsAntiRollbackHwPresent(); virtual bool GetHdcpCapabilities(HdcpCapability* current, HdcpCapability* max); + virtual bool GetSupportedCertificateTypes(SupportedCertificateTypes* support); virtual bool GetRandom(size_t data_length, uint8_t* random_data); virtual bool GetNumberOfOpenSessions(size_t* count); virtual bool GetMaxNumberOfSessions(size_t* max); diff --git a/libwvdrmengine/cdm/core/src/crypto_session.cpp b/libwvdrmengine/cdm/core/src/crypto_session.cpp index 96b4d886..000a8cac 100644 --- a/libwvdrmengine/cdm/core/src/crypto_session.cpp +++ b/libwvdrmengine/cdm/core/src/crypto_session.cpp @@ -1185,6 +1185,24 @@ bool CryptoSession::GetHdcpCapabilities(HdcpCapability* current, return true; } +bool CryptoSession::GetSupportedCertificateTypes( + SupportedCertificateTypes* support) { + LOGV("GetSupportedCertificateTypes: id=%ld", (uint32_t)oec_session_id_); + if (!initialized_) return false; + if (support == NULL) { + LOGE("CryptoSession::GetSupportedCertificateTypes: |support| cannot be " + "NULL"); + return false; + } + + uint32_t oec_support = + OEMCrypto_SupportedCertificates(requested_security_level_); + support->rsa_2048_bit = oec_support & OEMCrypto_Supports_RSA_2048bit; + support->rsa_3072_bit = oec_support & OEMCrypto_Supports_RSA_3072bit; + support->rsa_cast = oec_support & OEMCrypto_Supports_RSA_CAST; + return true; +} + bool CryptoSession::GetRandom(size_t data_length, uint8_t* random_data) { if (random_data == NULL) { LOGE("CryptoSession::GetRandom: random data destination not provided"); diff --git a/libwvdrmengine/cdm/core/src/license.cpp b/libwvdrmengine/cdm/core/src/license.cpp index b95b86de..8131d2c0 100644 --- a/libwvdrmengine/cdm/core/src/license.cpp +++ b/libwvdrmengine/cdm/core/src/license.cpp @@ -41,6 +41,8 @@ namespace wvcdm { // Protobuf generated classes. using video_widevine::ClientIdentification; using video_widevine::ClientIdentification_ClientCapabilities; +using video_widevine:: + ClientIdentification_ClientCapabilities_CertificateKeyType; using video_widevine::ClientIdentification_NameValue; using video_widevine::DrmDeviceCertificate; using video_widevine::EncryptedClientIdentification; @@ -95,7 +97,7 @@ static std::vector ExtractContentKeys(const License& license) { case kFourCcLittleEndianCbcs: key.set_cipher_mode(kCipherModeCbc); break; - default: + default: key.set_cipher_mode(kCipherModeCtr); break; } @@ -951,6 +953,20 @@ CdmResponseType CdmLicense::PrepareClientId( } } + CryptoSession::SupportedCertificateTypes supported_certs; + if (crypto_session_->GetSupportedCertificateTypes(&supported_certs)) { + if (supported_certs.rsa_2048_bit) { + client_capabilities->add_supported_certificate_key_type( + video_widevine:: + ClientIdentification_ClientCapabilities_CertificateKeyType_RSA_2048); + } + if (supported_certs.rsa_3072_bit) { + client_capabilities->add_supported_certificate_key_type( + video_widevine:: + ClientIdentification_ClientCapabilities_CertificateKeyType_RSA_3072); + } + } + client_capabilities->set_can_update_srm( crypto_session_->IsSrmUpdateSupported()); uint16_t srm_version; diff --git a/libwvdrmengine/cdm/core/src/license_protocol.proto b/libwvdrmengine/cdm/core/src/license_protocol.proto index 7525b1f7..cebe09ff 100644 --- a/libwvdrmengine/cdm/core/src/license_protocol.proto +++ b/libwvdrmengine/cdm/core/src/license_protocol.proto @@ -510,6 +510,11 @@ message ClientIdentification { HDCP_NO_DIGITAL_OUTPUT = 0xff; } + enum CertificateKeyType { + RSA_2048 = 0; + RSA_3072 = 1; + } + optional bool client_token = 1 [default = false]; optional bool session_token = 2 [default = false]; optional bool video_resolution_constraints = 3 [default = false]; @@ -524,6 +529,7 @@ message ClientIdentification { // A device may have SRM data, and report a version, but may not be capable // of updating SRM data. optional bool can_update_srm = 8 [default = false]; + repeated CertificateKeyType supported_certificate_key_type = 9; } // Type of factory-provisioned device root of trust. Optional. diff --git a/libwvdrmengine/cdm/core/test/license_unittest.cpp b/libwvdrmengine/cdm/core/test/license_unittest.cpp index 7b7ae043..c3790c25 100644 --- a/libwvdrmengine/cdm/core/test/license_unittest.cpp +++ b/libwvdrmengine/cdm/core/test/license_unittest.cpp @@ -83,6 +83,7 @@ class MockCryptoSession : public CryptoSession { MOCK_METHOD1(GenerateRequestId, bool(std::string*)); MOCK_METHOD1(UsageInformationSupport, bool(bool*)); MOCK_METHOD2(GetHdcpCapabilities, bool(HdcpCapability*, HdcpCapability*)); + MOCK_METHOD1(GetSupportedCertificateTypes, bool(SupportedCertificateTypes*)); MOCK_METHOD1(GetApiVersion, bool(uint32_t*)); MOCK_METHOD1(GenerateNonce, bool(uint32_t*)); MOCK_METHOD3(PrepareRequest, bool(const std::string&, bool, std::string*)); @@ -121,6 +122,7 @@ using ::testing::Eq; using ::testing::NotNull; using ::testing::Return; using ::testing::SetArgPointee; +using ::testing::UnorderedElementsAre; class CdmLicenseTest : public ::testing::Test { protected: @@ -184,6 +186,11 @@ TEST_F(CdmLicenseTest, PrepareKeyRequestValidation) { bool usage_information_support = true; CryptoSession::HdcpCapability current_hdcp_version = HDCP_NO_DIGITAL_OUTPUT; CryptoSession::HdcpCapability max_hdcp_version = HDCP_V2_1; + CryptoSession::SupportedCertificateTypes device_supported_certs = { + true, + true, + true + }; uint32_t crypto_session_api_version = 9; EXPECT_CALL(*crypto_session_, IsOpen()) @@ -196,6 +203,8 @@ TEST_F(CdmLicenseTest, PrepareKeyRequestValidation) { EXPECT_CALL(*crypto_session_, GetHdcpCapabilities(NotNull(), NotNull())) .WillOnce(DoAll(SetArgPointee<0>(current_hdcp_version), SetArgPointee<1>(max_hdcp_version), Return(true))); + EXPECT_CALL(*crypto_session_, GetSupportedCertificateTypes(NotNull())) + .WillOnce(DoAll(SetArgPointee<0>(device_supported_certs), Return(true))); EXPECT_CALL(*crypto_session_, GetApiVersion(NotNull())) .WillOnce( DoAll(SetArgPointee<0>(crypto_session_api_version), Return(true))); @@ -264,6 +273,14 @@ TEST_F(CdmLicenseTest, PrepareKeyRequestValidation) { EXPECT_EQ(crypto_session_api_version, client_capabilities.oem_crypto_api_version()); + EXPECT_THAT( + client_capabilities.supported_certificate_key_type(), + UnorderedElementsAre( + video_widevine:: + ClientIdentification_ClientCapabilities_CertificateKeyType_RSA_2048, + video_widevine:: + ClientIdentification_ClientCapabilities_CertificateKeyType_RSA_3072)); + // Verify Content Identification const LicenseRequest_ContentIdentification& content_id = license_request.content_id();