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();