From a7887f60fc7364f4c61e24e824b4c51c105a077d Mon Sep 17 00:00:00 2001 From: Edwin Wong Date: Tue, 17 Mar 2015 13:51:20 -0700 Subject: [PATCH] Add OEMCrypto_IsAntiRollbackHwPresent API for OEMCrypto v10. Merge from WV CDM repo: https://widevine-internal-review.googlesource.com/#/c/13660/. bug: 18948905 Change-Id: I1ffe72baaac9abf05c06139de790236e763f89a8 --- .../cdm/core/include/crypto_session.h | 1 + .../cdm/core/src/crypto_session.cpp | 4 ++++ libwvdrmengine/cdm/core/src/license.cpp | 13 +++++++---- .../cdm/core/src/license_protocol.proto | 1 + .../oemcrypto_engine_device_properties.cpp | 6 +++++ .../mock/src/oemcrypto_engine_mock.cpp | 7 ++++++ .../mock/src/oemcrypto_engine_mock.h | 1 + .../oemcrypto/mock/src/oemcrypto_key_mock.cpp | 3 ++- .../oemcrypto/mock/src/oemcrypto_key_mock.h | 1 + .../oemcrypto/mock/src/oemcrypto_mock.cpp | 13 ++++++++++- .../oemcrypto/test/oemcrypto_test.cpp | 23 +++++++++++++++++-- 11 files changed, 64 insertions(+), 9 deletions(-) diff --git a/libwvdrmengine/cdm/core/include/crypto_session.h b/libwvdrmengine/cdm/core/include/crypto_session.h index 17a56621..eb3ae485 100644 --- a/libwvdrmengine/cdm/core/include/crypto_session.h +++ b/libwvdrmengine/cdm/core/include/crypto_session.h @@ -97,6 +97,7 @@ class CryptoSession { const std::string& message, const std::string& signature, const std::string& provider_session_token); virtual CdmResponseType DeleteAllUsageReports(); + virtual bool IsAntiRollbackHwPresent(); virtual bool GetHdcpCapabilities(OemCryptoHdcpVersion* current, OemCryptoHdcpVersion* max); diff --git a/libwvdrmengine/cdm/core/src/crypto_session.cpp b/libwvdrmengine/cdm/core/src/crypto_session.cpp index 9c1ba11f..cf1ba6a8 100644 --- a/libwvdrmengine/cdm/core/src/crypto_session.cpp +++ b/libwvdrmengine/cdm/core/src/crypto_session.cpp @@ -864,6 +864,10 @@ CdmResponseType CryptoSession::DeleteAllUsageReports() { return NO_ERROR; } +bool CryptoSession::IsAntiRollbackHwPresent() { + return OEMCrypto_IsAntiRollbackHwPresent(requested_security_level_); +} + bool CryptoSession::GenerateNonce(uint32_t* nonce) { if (!nonce) { LOGE("input parameter is null"); diff --git a/libwvdrmengine/cdm/core/src/license.cpp b/libwvdrmengine/cdm/core/src/license.cpp index ef05b4e7..9dd75687 100644 --- a/libwvdrmengine/cdm/core/src/license.cpp +++ b/libwvdrmengine/cdm/core/src/license.cpp @@ -274,6 +274,14 @@ bool CdmLicense::PrepareKeyRequest(const InitializationData& init_data, client_capabilities->set_session_token(supports_usage_information); } + client_capabilities->set_anti_rollback_hardware_present( + session_->IsAntiRollbackHwPresent()); + + uint32_t api_version = 0; + if (session_->GetApiVersion(&api_version)) { + client_capabilities->set_oem_crypto_api_version(api_version); + } + CryptoSession::OemCryptoHdcpVersion current_version, max_version; if (session_->GetHdcpCapabilities(¤t_version, &max_version)) { switch (max_version) { @@ -315,11 +323,6 @@ bool CdmLicense::PrepareKeyRequest(const InitializationData& init_data, } } - uint32_t version = 0; - if (session_->GetApiVersion(&version)) { - client_capabilities->set_oem_crypto_api_version(version); - } - if (privacy_mode_enabled) { EncryptedClientIdentification* encrypted_client_id = license_request.mutable_encrypted_client_id(); diff --git a/libwvdrmengine/cdm/core/src/license_protocol.proto b/libwvdrmengine/cdm/core/src/license_protocol.proto index 7a32ca02..969d91a3 100644 --- a/libwvdrmengine/cdm/core/src/license_protocol.proto +++ b/libwvdrmengine/cdm/core/src/license_protocol.proto @@ -410,6 +410,7 @@ message ClientIdentification { optional bool video_resolution_constraints = 3 [default = false]; optional HdcpVersion max_hdcp_version = 4 [default = HDCP_NONE]; optional uint32 oem_crypto_api_version = 5; + optional bool anti_rollback_hardware_present = 6 [default = false]; } // Type of factory-provisioned device root of trust. Optional. diff --git a/libwvdrmengine/oemcrypto/mock/src/oemcrypto_engine_device_properties.cpp b/libwvdrmengine/oemcrypto/mock/src/oemcrypto_engine_device_properties.cpp index 6859f936..6c99b997 100644 --- a/libwvdrmengine/oemcrypto/mock/src/oemcrypto_engine_device_properties.cpp +++ b/libwvdrmengine/oemcrypto/mock/src/oemcrypto_engine_device_properties.cpp @@ -33,4 +33,10 @@ bool CryptoEngine::supports_storage() { return true; } +// Returns false for mock library to indicate the client does not support +// anti-rollback hardware. +bool CryptoEngine::is_anti_rollback_hw_present() { + return false; +} + } // namespace wvoec_mock diff --git a/libwvdrmengine/oemcrypto/mock/src/oemcrypto_engine_mock.cpp b/libwvdrmengine/oemcrypto/mock/src/oemcrypto_engine_mock.cpp index 8b30659d..d59a7405 100644 --- a/libwvdrmengine/oemcrypto/mock/src/oemcrypto_engine_mock.cpp +++ b/libwvdrmengine/oemcrypto/mock/src/oemcrypto_engine_mock.cpp @@ -512,6 +512,13 @@ bool SessionContext::InstallKey(const KeyId& key_id, LOGE("Error parsing key control."); return false; } + if ((key_control_block.control_bits() & + kControlRequireAntiRollbackHardware) && + !ce_->is_anti_rollback_hw_present()) { + LOGE("Anti-rollback hardware is required but hardware not present."); + return false; + } + if (!CheckNonceOrEntry(key_control_block, pst)) { LOGE("Failed Nonce/PST check."); return false; diff --git a/libwvdrmengine/oemcrypto/mock/src/oemcrypto_engine_mock.h b/libwvdrmengine/oemcrypto/mock/src/oemcrypto_engine_mock.h index e8248cba..d39cba6f 100644 --- a/libwvdrmengine/oemcrypto/mock/src/oemcrypto_engine_mock.h +++ b/libwvdrmengine/oemcrypto/mock/src/oemcrypto_engine_mock.h @@ -256,6 +256,7 @@ class CryptoEngine { bool local_display(); bool closed_platform(); bool supports_storage(); + bool is_anti_rollback_hw_present(); private: SessionContext* current_session_; diff --git a/libwvdrmengine/oemcrypto/mock/src/oemcrypto_key_mock.cpp b/libwvdrmengine/oemcrypto/mock/src/oemcrypto_key_mock.cpp index cb98c9bc..a7bc356b 100644 --- a/libwvdrmengine/oemcrypto/mock/src/oemcrypto_key_mock.cpp +++ b/libwvdrmengine/oemcrypto/mock/src/oemcrypto_key_mock.cpp @@ -19,7 +19,8 @@ namespace wvoec_mock { bool KeyControlBlock::Validate() { if ((FOURCC('k', 'c', 't', 'l') != verification_) && // original verification - (FOURCC('k', 'c', '0', '9') != verification_)) { // add in version 9 api. + (FOURCC('k', 'c', '0', '9') != verification_) && // add in version 9 api + (FOURCC('k', 'c', '1', '0') != verification_)) { // add in version 10 api LOGE("KCB: BAD verification string: %08X (not %08X or %08X)", verification_, 0x6b63746c, 0x6b633039); return false; diff --git a/libwvdrmengine/oemcrypto/mock/src/oemcrypto_key_mock.h b/libwvdrmengine/oemcrypto/mock/src/oemcrypto_key_mock.h index c6dac749..e7f16d36 100644 --- a/libwvdrmengine/oemcrypto/mock/src/oemcrypto_key_mock.h +++ b/libwvdrmengine/oemcrypto/mock/src/oemcrypto_key_mock.h @@ -14,6 +14,7 @@ namespace wvoec_mock { const uint32_t kControlObserveDataPath = (1<<31); const uint32_t kControlObserveHDCP = (1<<30); const uint32_t kControlObserveCGMS = (1<<29); +const uint32_t kControlRequireAntiRollbackHardware = (1<<28); const uint32_t kControlReplayMask = (0x03<<13); const uint32_t kControlNonceRequired = (0x01<<13); const uint32_t kControlNonceOrEntry = (0x02<<13); diff --git a/libwvdrmengine/oemcrypto/mock/src/oemcrypto_mock.cpp b/libwvdrmengine/oemcrypto/mock/src/oemcrypto_mock.cpp index 96826303..85e1abb8 100644 --- a/libwvdrmengine/oemcrypto/mock/src/oemcrypto_mock.cpp +++ b/libwvdrmengine/oemcrypto/mock/src/oemcrypto_mock.cpp @@ -996,7 +996,7 @@ OEMCryptoResult OEMCrypto_DeriveKeysFromSessionKey( extern "C" uint32_t OEMCrypto_APIVersion() { - return 9; + return 10; } extern "C" @@ -1049,6 +1049,17 @@ OEMCryptoResult OEMCrypto_GetMaxNumberOfSessions(size_t* maximum) { return OEMCrypto_SUCCESS; } +extern "C" +bool OEMCrypto_IsAntiRollbackHwPresent() { + bool anti_rollback_hw_present = crypto_engine->is_anti_rollback_hw_present(); + + if (LogCategoryEnabled(kLoggingTraceOEMCryptoCalls)) { + LOGI("-- bool OEMCrypto_IsAntiRollbackHwPresent(): %d\n", + anti_rollback_hw_present); + } + return anti_rollback_hw_present; +} + extern "C" OEMCryptoResult OEMCrypto_Generic_Encrypt(OEMCrypto_SESSION session, const uint8_t* in_buffer, diff --git a/libwvdrmengine/oemcrypto/test/oemcrypto_test.cpp b/libwvdrmengine/oemcrypto/test/oemcrypto_test.cpp index eecd6036..40f11fe2 100644 --- a/libwvdrmengine/oemcrypto/test/oemcrypto_test.cpp +++ b/libwvdrmengine/oemcrypto/test/oemcrypto_test.cpp @@ -1054,8 +1054,10 @@ class Session { sizeof(license_.keys[i].key_iv)); OEMCrypto_GetRandom(license_.keys[i].control_iv, sizeof(license_.keys[i].control_iv)); - if (control & (wvoec_mock::kControlHDCPVersionMask | - wvoec_mock::kControlReplayMask)) { + if (control & wvoec_mock::kControlRequireAntiRollbackHardware) { + memcpy(license_.keys[i].control.verification, "kc10", 4); + } else if (control & (wvoec_mock::kControlHDCPVersionMask | + wvoec_mock::kControlReplayMask)) { memcpy(license_.keys[i].control.verification, "kc09", 4); } else { memcpy(license_.keys[i].control.verification, "kctl", 4); @@ -1585,6 +1587,23 @@ class OEMCryptoClientTest : public ::testing::Test { } }; +TEST_F(OEMCryptoClientTest, AntiRollbackHardwareRequired) { + Session s; + s.open(); + s.GenerateDerivedKeys(); + s.FillSimpleMessage(0, wvoec_mock::kControlRequireAntiRollbackHardware, 0); + s.EncryptAndSign(); + OEMCryptoResult sts = OEMCrypto_LoadKeys( + s.session_id(), s.message_ptr(), sizeof(MessageData), &s.signature()[0], + s.signature().size(), s.encrypted_license().mac_key_iv, + s.encrypted_license().mac_keys, kNumKeys, s.key_array(), NULL, 0); + if (OEMCrypto_IsAntiRollbackHwPresent()) { + ASSERT_EQ(OEMCrypto_SUCCESS, sts); + } else { + ASSERT_EQ(OEMCrypto_ERROR_UNKNOWN_FAILURE, sts); + } +} + // // Keybox Tests // These two tests are first, becuase it might give an idea why other