From 7f347cd59faee6a0fb08fe58f3c92d754153d61a Mon Sep 17 00:00:00 2001 From: Fred Gylys-Colwell Date: Mon, 13 Jul 2020 10:12:37 -0700 Subject: [PATCH 1/2] Adjust nonce for v15 servers Merge from Widevine repo of http://go/wvgerrit/102783 When OEMCrypto is v16, but the license server is v15, we should not create a new nonce for a license renewal. However, the request does need a nonce or the license server will not generate a valid key control block. So we should use the nonce that came from the original license. Bug: 160676790 Test: tested playback using netflix Test: GTS tests. http://go/forrest-run/L55100000642199761 Change-Id: Ie1644b5abe0662387edf01f6110d82f70a64df6c --- libwvdrmengine/cdm/core/include/license.h | 3 +++ libwvdrmengine/cdm/core/src/license.cpp | 19 +++++++++++++------ 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/libwvdrmengine/cdm/core/include/license.h b/libwvdrmengine/cdm/core/include/license.h index 95c307e4..9d566803 100644 --- a/libwvdrmengine/cdm/core/include/license.h +++ b/libwvdrmengine/cdm/core/include/license.h @@ -176,6 +176,9 @@ class CdmLicense { // HandleKeyResponse VersionInfo latest_service_version_; + // The nonce used in the original license request. + uint32_t license_nonce_; + #if defined(UNIT_TEST) friend class CdmLicenseTestPeer; #endif diff --git a/libwvdrmengine/cdm/core/src/license.cpp b/libwvdrmengine/cdm/core/src/license.cpp index a6585d34..a934571c 100644 --- a/libwvdrmengine/cdm/core/src/license.cpp +++ b/libwvdrmengine/cdm/core/src/license.cpp @@ -237,6 +237,7 @@ bool CdmLicense::Init(const std::string& client_token, crypto_session_ = session; policy_engine_ = policy_engine; use_privacy_mode_ = use_privacy_mode; + license_nonce_ = 0; initialized_ = true; return true; } @@ -313,8 +314,7 @@ CdmResponseType CdmLicense::PrepareKeyRequest( // Get/set the nonce. This value will be reflected in the Key Control Block // of the license response. - uint32_t nonce; - status = crypto_session_->GenerateNonce(&nonce); + status = crypto_session_->GenerateNonce(&license_nonce_); switch (status) { case NO_ERROR: @@ -325,7 +325,7 @@ CdmResponseType CdmLicense::PrepareKeyRequest( default: return LICENSE_REQUEST_NONCE_GENERATION_ERROR; } - license_request.set_key_control_nonce(nonce); + license_request.set_key_control_nonce(license_nonce_); license_request.set_protocol_version(video_widevine::VERSION_2_1); // License request is complete. Serialize it. @@ -460,11 +460,11 @@ CdmResponseType CdmLicense::PrepareKeyUpdateRequest( LOGW("Unknown API Version"); api_version = 15; } - uint32_t nonce = 0; if (api_version < 16) { // For a pre-v16 license, get/set the nonce. This value will be reflected // in the Key Control Block of the license response. - const CdmResponseType status = crypto_session_->GenerateNonce(&nonce); + const CdmResponseType status = + crypto_session_->GenerateNonce(&license_nonce_); switch (status) { case NO_ERROR: break; @@ -475,7 +475,7 @@ CdmResponseType CdmLicense::PrepareKeyUpdateRequest( return LICENSE_RENEWAL_NONCE_GENERATION_ERROR; } } - license_request.set_key_control_nonce(nonce); + license_request.set_key_control_nonce(license_nonce_); license_request.set_protocol_version(video_widevine::VERSION_2_1); // License request is complete. Serialize it. @@ -810,6 +810,13 @@ CdmResponseType CdmLicense::RestoreOfflineLicense( } key_request_ = signed_request.msg(); + LicenseRequest original_license_request; + if (!original_license_request.ParseFromString(key_request_)) { + LOGW("Could not parse original request."); + } else { + license_nonce_ = original_license_request.key_control_nonce(); + } + CdmResponseType sts = HandleKeyResponse(license_response); if (sts != KEY_ADDED) return sts; From b90f88072f25ed14095444f45382f52e38f953ad Mon Sep 17 00:00:00 2001 From: Fred Gylys-Colwell Date: Fri, 17 Jul 2020 23:45:54 -0700 Subject: [PATCH 2/2] Start rental clock when nonce-free offline license loaded Merge from Widevine repo of http://go/wvgerrit/103107 When an offline license is reloaded, if it does not have a usage entry to indicate when the rental clock was started, the start time defaults to 0 in the ODK library (in OEMCrypto). This CL changes the code to start the rental clock in this case. It does this by signing a dummy message, which triggers the ODK library to start the rental clock. Bug: 161585265 Bug: 161023174 Test: GTS tests. http://go/forrest-run/L55100000642199761 Change-Id: I4cf555b2fb43009ffb62e7b2c1a37265c3f70bfe --- libwvdrmengine/cdm/core/src/cdm_session.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/libwvdrmengine/cdm/core/src/cdm_session.cpp b/libwvdrmengine/cdm/core/src/cdm_session.cpp index 9dd23530..8e1ccf34 100644 --- a/libwvdrmengine/cdm/core/src/cdm_session.cpp +++ b/libwvdrmengine/cdm/core/src/cdm_session.cpp @@ -286,6 +286,15 @@ CdmResponseType CdmSession::RestoreOfflineSession(const CdmKeySetId& key_set_id, key_response_, &provider_session_token) || usage_table_header_ == nullptr) { provider_session_token.clear(); + // TODO(b/161023174): remove this code in v17. + std::string fake_message("empty message"); + std::string core_message; + std::string license_request_signature; + // Sign a fake message so that OEMCrypto will start the rental clock. The + // signature and generated core message are ignored. + CdmResponseType status = crypto_session_->PrepareAndSignLicenseRequest( + fake_message, &core_message, &license_request_signature); + if (status != NO_ERROR) return status; } else if (!VerifyOfflineUsageEntry()) { LOGE("License usage entry is invalid, cannot restore"); return LICENSE_USAGE_ENTRY_MISSING;