223 lines
7.1 KiB
C++
223 lines
7.1 KiB
C++
// Copyright 2018 Google LLC. All Rights Reserved. This file and proprietary
|
|
// source code may only be used and distributed under the Widevine License
|
|
// Agreement.
|
|
#ifndef WVCDM_CORE_LICENSE_H_
|
|
#define WVCDM_CORE_LICENSE_H_
|
|
|
|
#include <memory>
|
|
#include <set>
|
|
|
|
#include "initialization_data.h"
|
|
#include "license_protocol.pb.h"
|
|
#include "service_certificate.h"
|
|
#include "wv_cdm_types.h"
|
|
#include "wv_class_utils.h"
|
|
|
|
namespace wvutil {
|
|
class Clock;
|
|
} // namespace wvutil
|
|
|
|
namespace wvcdm {
|
|
class CdmSession;
|
|
class CryptoKey;
|
|
class CryptoSession;
|
|
class InitializationData;
|
|
class PolicyEngine;
|
|
|
|
class CdmLicense {
|
|
public:
|
|
using PsshEntitledKey = video_widevine::WidevinePsshData::EntitledKey;
|
|
|
|
CdmLicense() = delete;
|
|
WVCDM_DISALLOW_COPY_AND_MOVE(CdmLicense);
|
|
explicit CdmLicense(const CdmSessionId& session_id);
|
|
virtual ~CdmLicense();
|
|
|
|
virtual bool Init(bool use_privacy_mode,
|
|
const std::string& signed_service_certificate,
|
|
CryptoSession* session, PolicyEngine* policy_engine);
|
|
|
|
// == Accessors ==
|
|
|
|
virtual bool is_offline() const { return is_offline_; }
|
|
|
|
virtual std::string provider_session_token() {
|
|
return provider_session_token_;
|
|
}
|
|
|
|
virtual bool HasInitData() { return static_cast<bool>(stored_init_data_); }
|
|
|
|
virtual const video_widevine::VersionInfo& GetServiceVersion() {
|
|
return latest_service_version_;
|
|
}
|
|
|
|
virtual bool IsKeyLoaded(const KeyId& key_id);
|
|
|
|
// == Service Certificate API ==
|
|
|
|
// Override the currently-installed service certificate with a new service
|
|
// certificate.
|
|
virtual CdmResponseType SetServiceCertificate(
|
|
const std::string& signed_service_certificate);
|
|
|
|
// == License Restoring API ==
|
|
|
|
virtual CdmResponseType RestoreOfflineLicense(
|
|
const std::string& client_token, const CdmKeyMessage& license_request,
|
|
const CdmKeyResponse& license_response,
|
|
const CdmKeyResponse& license_renewal_response,
|
|
int64_t playback_start_time, int64_t last_playback_time,
|
|
int64_t grace_period_end_time, CdmSession* cdm_session);
|
|
virtual CdmResponseType RestoreLicenseForRelease(
|
|
const std::string& client_token, const CdmKeyMessage& license_request,
|
|
const CdmKeyResponse& license_response);
|
|
|
|
// == Request/Response API ==
|
|
|
|
virtual CdmResponseType PrepareKeyRequest(
|
|
const InitializationData& init_data, const std::string& client_token,
|
|
CdmLicenseType license_type, const CdmAppParameterMap& app_parameters,
|
|
CdmKeyMessage* signed_request, std::string* server_url);
|
|
|
|
virtual CdmResponseType PrepareKeyUpdateRequest(
|
|
bool is_renewal, const CdmAppParameterMap& app_parameters,
|
|
CdmSession* cdm_session, CdmKeyMessage* signed_request,
|
|
std::string* server_url);
|
|
|
|
virtual CdmResponseType HandleKeyResponse(
|
|
bool is_restore, const CdmKeyResponse& license_response);
|
|
|
|
virtual CdmResponseType HandleKeyUpdateResponse(
|
|
bool is_renewal, bool is_restore, const CdmKeyResponse& license_response);
|
|
|
|
virtual CdmResponseType HandleEmbeddedKeyData(
|
|
const InitializationData& init_data);
|
|
|
|
// == Utilities ==
|
|
|
|
static bool ExtractProviderSessionToken(
|
|
const CdmKeyResponse& license_response,
|
|
std::string* provider_session_token);
|
|
|
|
// == Test Accessors ==
|
|
|
|
// Testing only. Caller retains ownership of pointers.
|
|
void set_crypto_session(CryptoSession* crypto_session) {
|
|
crypto_session_ = crypto_session;
|
|
}
|
|
|
|
void set_policy_engine(PolicyEngine* policy_engine) {
|
|
policy_engine_ = policy_engine;
|
|
}
|
|
|
|
private:
|
|
// Test Constructor.
|
|
// CdmLicense takes ownership of the clock.
|
|
CdmLicense(const CdmSessionId& session_id, wvutil::Clock* clock);
|
|
|
|
// == Internal Request/Response API ==
|
|
|
|
// Prepare to reload a key update message. Some special code is needed to work
|
|
// around b/166010609.
|
|
// TODO(b/166007195): Remove this.
|
|
CdmResponseType PrepareKeyUpdateReload(CdmSession* cdm_session);
|
|
|
|
CdmResponseType HandleKeyErrorResponse(
|
|
const video_widevine::SignedMessage& signed_message);
|
|
|
|
CdmResponseType HandleContentKeyResponse(
|
|
bool is_restore, const std::string& session_key, const std::string& msg,
|
|
const std::string& core_message, const std::string& signature,
|
|
const std::vector<CryptoKey>& license_keys,
|
|
const video_widevine::License& license);
|
|
|
|
// Loads the entitlement keys in |license_keys| into
|
|
// the crypto session.
|
|
//
|
|
// In addition, it also extracts content keys from
|
|
// |request_entitled_keys_| and loads them for use.
|
|
CdmResponseType HandleEntitlementKeyResponse(
|
|
bool is_restore, const std::string& session_key, const std::string& msg,
|
|
const std::string& core_message, const std::string& signature,
|
|
const std::vector<CryptoKey>& license_keys,
|
|
const video_widevine::License& license);
|
|
|
|
CdmResponseType HandleNewEntitledKeys(
|
|
const std::vector<PsshEntitledKey>& packaged_entitled_keys);
|
|
|
|
// == Internal Utilities ==
|
|
|
|
CdmResponseType PrepareClientId(
|
|
const CdmAppParameterMap& app_parameters,
|
|
const std::string& provider_client_token,
|
|
video_widevine::LicenseRequest* license_request);
|
|
|
|
CdmResponseType PrepareContentId(
|
|
const InitializationData& init_data, CdmLicenseType license_type,
|
|
const std::string& request_id,
|
|
video_widevine::LicenseRequest* license_request);
|
|
|
|
template <typename T>
|
|
bool SetTypeAndId(CdmLicenseType license_type, const std::string& request_id,
|
|
T* content_id);
|
|
|
|
// == Creation-time Variables ==
|
|
|
|
const CdmSessionId session_id_;
|
|
std::unique_ptr<wvutil::Clock> clock_;
|
|
|
|
// == Initialization-time Variables ==
|
|
|
|
bool initialized_ = false;
|
|
CryptoSession* crypto_session_ = nullptr;
|
|
PolicyEngine* policy_engine_ = nullptr;
|
|
|
|
// Associated with ClientIdentification encryption
|
|
bool use_privacy_mode_ = false;
|
|
ServiceCertificate service_certificate_;
|
|
|
|
video_widevine::ProtocolVersion protocol_version_ =
|
|
video_widevine::VERSION_2_2;
|
|
|
|
// == License Request/Response variables ==
|
|
|
|
std::string client_token_;
|
|
std::unique_ptr<InitializationData> stored_init_data_;
|
|
|
|
// The nonce used in the original license request.
|
|
uint32_t license_nonce_ = 0;
|
|
|
|
CdmKeyMessage license_request_;
|
|
|
|
// For entitlement key licensing. This holds the keys from the init_data.
|
|
// These keys are extracted from the PSSH when we generate a license request.
|
|
// It is used to load content keys after we have received a license and
|
|
// entitlement keys. It is also used in updating the key status info.
|
|
std::vector<PsshEntitledKey> request_entitled_keys_;
|
|
|
|
std::string provider_client_token_;
|
|
std::string provider_session_token_;
|
|
|
|
bool renew_with_client_id_ = false;
|
|
|
|
std::string renewal_server_url_;
|
|
|
|
// This is the latest version info extracted from the SignedMessage in
|
|
// HandleKeyResponse
|
|
video_widevine::VersionInfo latest_service_version_;
|
|
|
|
// == License Life-Time Variables ==
|
|
|
|
CdmLicenseKeyType license_key_type_ = kLicenseKeyTypeContent;
|
|
bool is_offline_ = false;
|
|
|
|
std::set<KeyId> content_key_ids_;
|
|
std::set<KeyId> entitlement_key_ids_;
|
|
|
|
#if defined(UNIT_TEST)
|
|
friend class CdmLicenseTestPeer;
|
|
#endif
|
|
}; // class CdmLicense
|
|
} // namespace wvcdm
|
|
#endif // WVCDM_CORE_LICENSE_H_
|