diff --git a/whitebox-impl/WORKSPACE b/whitebox-impl/WORKSPACE index 285db15..adc1469 100644 --- a/whitebox-impl/WORKSPACE +++ b/whitebox-impl/WORKSPACE @@ -57,9 +57,9 @@ git_repository( http_archive( name = "zlib", build_file = "@com_google_protobuf//:third_party/zlib.BUILD", - sha256 = "b3a24de97a8fdbc835b9833169501030b8977031bcb54b3b3ac13740f846ab30", - strip_prefix = "zlib-1.2.13", - urls = ["https://zlib.net/zlib-1.2.13.tar.gz"], + sha256 = "ff0ba4c292013dbc27530b3a81e1f9a813cd39de01ca5e0f8bf355702efa593e", + strip_prefix = "zlib-1.3", + urls = ["https://zlib.net/zlib-1.3.tar.gz"], ) # ODK diff --git a/whitebox/WORKSPACE b/whitebox/WORKSPACE index 07957e9..eb69323 100644 --- a/whitebox/WORKSPACE +++ b/whitebox/WORKSPACE @@ -56,9 +56,9 @@ git_repository( http_archive( name = "zlib", build_file = "@com_google_protobuf//:third_party/zlib.BUILD", - sha256 = "b3a24de97a8fdbc835b9833169501030b8977031bcb54b3b3ac13740f846ab30", - strip_prefix = "zlib-1.2.13", - urls = ["https://zlib.net/zlib-1.2.13.tar.gz"], + sha256 = "ff0ba4c292013dbc27530b3a81e1f9a813cd39de01ca5e0f8bf355702efa593e", + strip_prefix = "zlib-1.3", + urls = ["https://zlib.net/zlib-1.3.tar.gz"], ) # ODK diff --git a/whitebox/api/license_whitebox_entitlement_content_key_test.cc b/whitebox/api/license_whitebox_entitlement_content_key_test.cc index 0f8a810..bf8e108 100644 --- a/whitebox/api/license_whitebox_entitlement_content_key_test.cc +++ b/whitebox/api/license_whitebox_entitlement_content_key_test.cc @@ -14,13 +14,16 @@ namespace widevine { class LicenseWhiteboxEntitlementContentKeyTest - : public LicenseWhiteboxTestBase { + : public LicenseWhiteboxTestBase, + public ::testing::WithParamInterface { protected: void SetUp() { LicenseWhiteboxTestBase::SetUp(); server_ = TestServer::CreateDualKey(); TestLicenseBuilder builder; + // provider keys do not apply to entitlement keys, so the license + // does not need to be built with provider key id set. builder.GetSettings().odk_version = TestLicenseBuilder::OdkVersion::k16_5; builder.AddSigningKey(TestLicenseBuilder::DefaultSigningKey()); builder.AddEntitlementKey( @@ -32,13 +35,13 @@ class LicenseWhiteboxEntitlementContentKeyTest License license_; }; -TEST_F(LicenseWhiteboxEntitlementContentKeyTest, Decrypt) { +TEST_P(LicenseWhiteboxEntitlementContentKeyTest, Decrypt) { auto result = WB_License_ProcessLicenseResponse( whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY, license_.core_message.data(), license_.core_message.size(), license_.message.data(), license_.message.size(), license_.signature.data(), license_.signature.size(), license_.session_key.data(), - license_.session_key.size(), kNoProviderKeyId, license_.request.data(), + license_.session_key.size(), GetParam(), license_.request.data(), license_.request.size()); #ifndef HAS_ENTITLEMENT if (result == WB_RESULT_NOT_IMPLEMENTED) @@ -104,7 +107,7 @@ TEST_F(LicenseWhiteboxEntitlementContentKeyTest, Remove) { #endif ASSERT_EQ(result, WB_RESULT_OK); - ASSERT_EQ(WB_License_RemoveEntitledContentKey(whitebox_,key_id.data(), + ASSERT_EQ(WB_License_RemoveEntitledContentKey(whitebox_, key_id.data(), key_id.size()), WB_RESULT_OK); @@ -124,4 +127,8 @@ TEST_F(LicenseWhiteboxEntitlementContentKeyTest, Remove) { WB_RESULT_KEY_UNAVAILABLE); } +INSTANTIATE_TEST_SUITE_P( + WithAndWithoutProviderKeyId, + LicenseWhiteboxEntitlementContentKeyTest, + ::testing::Values(kNoProviderKeyId, kProviderKeyId)); } // namespace widevine diff --git a/whitebox/api/test_license_builder.h b/whitebox/api/test_license_builder.h index 14dd144..69c8696 100644 --- a/whitebox/api/test_license_builder.h +++ b/whitebox/api/test_license_builder.h @@ -15,6 +15,7 @@ namespace widevine { constexpr size_t kNoProviderKeyId = 0; +constexpr size_t kProviderKeyId = 1; struct License { std::vector request; diff --git a/whitebox/crypto_utils/rsa_util.h b/whitebox/crypto_utils/rsa_util.h index c0bf1f7..972926f 100644 --- a/whitebox/crypto_utils/rsa_util.h +++ b/whitebox/crypto_utils/rsa_util.h @@ -18,6 +18,21 @@ #include "third_party/boringssl/src/include/openssl/rsa.h" +#if BORINGSSL_API_VERSION <= 9 +inline const BIGNUM* RSA_get0_p(const RSA* r) { + return r->p; +} +inline const BIGNUM* RSA_get0_q(const RSA* r) { + return r->q; +} +inline const BIGNUM* RSA_get0_e(const RSA* r) { + return r->e; +} +inline const BIGNUM* RSA_get0_n(const RSA* r) { + return r->n; +} +#endif + namespace widevine { namespace rsa_util { diff --git a/whitebox/reference/impl/license_parser.cc b/whitebox/reference/impl/license_parser.cc index 9189239..ab1772d 100644 --- a/whitebox/reference/impl/license_parser.cc +++ b/whitebox/reference/impl/license_parser.cc @@ -31,14 +31,17 @@ bool LicenseParser::Decrypt(const std::string& key, } bool LicenseParser::UnwrapKey( + KeyType key_type, const std::string& wrapped_key, const std::vector& provider_keys, size_t provider_key_id, const std::string& key_decryption_key, const std::string& key_decryption_key_iv, std::string* unwrapped_key) { + // provider keys are only applied on content keys. const bool provider_key_id_valid = - (provider_key_id >= 1 && provider_key_id <= provider_keys.size()); + (provider_key_id >= 1 && provider_key_id <= provider_keys.size() && + key_type == KeyType::kContentKey); // If |provider_key_id| is used and valid, then start by unmasking it. std::string key = wrapped_key; @@ -109,13 +112,17 @@ InternalKey LicenseParser::CreateInternalKey( InternalKey internal_key; internal_key.type = key_type; - internal_key.status = GetKeyStatus(level, is_hw_verified); + if (key_type == KeyType::kGenericCryptoKey) + internal_key.status = WB_KEY_STATUS_CONTENT_KEY_VALID; + else + internal_key.status = GetKeyStatus(level, is_hw_verified); internal_key.kcb_flags = kcb_flags; // Unless we are going to use the key, we don't want to save this key as it // will only risk exposing it. We only have an entry for it so we can handle // errors correctly. - if (internal_key.can_decrypt() || internal_key.can_masked_decrypt()) { + if (key_type == KeyType::kGenericCryptoKey || internal_key.can_decrypt() || + internal_key.can_masked_decrypt()) { CHECK_LE(key.size(), internal_key.key.size()); std::copy(key.begin(), key.end(), internal_key.key.begin()); } diff --git a/whitebox/reference/impl/license_parser.h b/whitebox/reference/impl/license_parser.h index 0d281f3..4dd6065 100644 --- a/whitebox/reference/impl/license_parser.h +++ b/whitebox/reference/impl/license_parser.h @@ -50,10 +50,11 @@ class LicenseParser { const std::string& encrypted, std::string* decrypted); - // Unwrap key |wrapped_key| using |provider_key_id| and + // Unwrap key |wrapped_key| using |key_type|, |provider_key_id| and // |key_decryption_key|, as necessary. Returns true and // |unwrapped_content_key| is updated on success, false otherwise. - static bool UnwrapKey(const std::string& wrapped_key, + static bool UnwrapKey(KeyType key_type, + const std::string& wrapped_key, const std::vector& provider_keys, size_t provider_key_id, const std::string& key_decryption_key, diff --git a/whitebox/reference/impl/odk.cc b/whitebox/reference/impl/odk.cc index 20ffea8..1f8a6a6 100644 --- a/whitebox/reference/impl/odk.cc +++ b/whitebox/reference/impl/odk.cc @@ -28,7 +28,7 @@ WB_Result GetODKContext(const std::string& combined_message, // By using initial_license_load==false, ODK won't validate the nonce. #if ODK_MAJOR_VERSION == 16 uint8_t request_hash[16]; -#elif ODK_MAJOR_VERSION == 18 +#elif ODK_MAJOR_VERSION >= 18 uint64_t clock_value = 0; #endif for (bool usage_entry_present : {false, true}) { @@ -42,17 +42,18 @@ WB_Result GetODKContext(const std::string& combined_message, /* initial_license_load= */ false, usage_entry_present, #if ODK_MAJOR_VERSION == 16 request_hash, -#elif ODK_MAJOR_VERSION == 18 +#elif ODK_MAJOR_VERSION >= 18 clock_value, #endif &timer, &clock, &nonce, &context->license -#if ODK_MAJOR_VERSION == 18 +#if ODK_MAJOR_VERSION >= 18 , &clock_value #endif ); if (result != ODK_ERROR_CORE_MESSAGE) break; } - if (result != OEMCrypto_SUCCESS) { + if (result != OEMCrypto_SUCCESS && result != ODK_SET_TIMER && + result != ODK_DISABLE_TIMER) { DVLOG(1) << "Error parsing license response: " << result; return WB_RESULT_INVALID_PARAMETER; } diff --git a/whitebox/reference/impl/odk_license_parser.cc b/whitebox/reference/impl/odk_license_parser.cc index 56204a4..2e503e8 100644 --- a/whitebox/reference/impl/odk_license_parser.cc +++ b/whitebox/reference/impl/odk_license_parser.cc @@ -257,8 +257,8 @@ InternalKey OdkLicenseParser::ParseInternalKey( } std::string unwrapped_key; - if (!UnwrapKey(wrapped_key, provider_keys, provider_key_id, decryption_key, - iv, &unwrapped_key)) { + if (!UnwrapKey(key_type, wrapped_key, provider_keys, provider_key_id, + decryption_key, iv, &unwrapped_key)) { VLOG(3) << "Failed to decrypt key."; return InternalKey(); } diff --git a/whitebox/reference/impl/protobuf_license_parser.cc b/whitebox/reference/impl/protobuf_license_parser.cc index 7d15635..e30168c 100644 --- a/whitebox/reference/impl/protobuf_license_parser.cc +++ b/whitebox/reference/impl/protobuf_license_parser.cc @@ -225,8 +225,8 @@ InternalKey ProtobufLicenseParser::ParseInternalKey( std::string wrapped_key = key.key().substr(0, key_size_without_padding); std::string unwrapped_key; - if (!UnwrapKey(wrapped_key, provider_keys, provider_key_id, decryption_key, - key.iv(), &unwrapped_key)) { + if (!UnwrapKey(key_type, wrapped_key, provider_keys, provider_key_id, + decryption_key, key.iv(), &unwrapped_key)) { VLOG(3) << "Failed to decrypt content key."; return InternalKey(); }