Files
android/libwvdrmengine/cdm/core/include/cdm_session.h
Rahul Frias 39558526f6 Wrapped OKP info into several classes.
[ Merge of http://go/wvgerrit/133744 ]

This changes adds several small classes which contain and manage
system and engine information related to OTA keybox provisioning.
These classes closely map to the OKP device file messages.

Bug: 189232882
Test: Linux unit tests
Change-Id: Ia9334c38f9d7ea89b30d9ad05f0595570bb38658

Storing and loading OKP info.

[ Merge of http://go/wvgerrit/133763 and http://go/ag/15645333 ]

This change extends the DeviceFiles module to be able to store and
load OKP info.  Mild data validation is performed when storing and
loading the information.

Bug: 189232882
Test: Android unit tests
Change-Id: I077de3234157252f2255a4389bf82a8d5344a355

System OKP fallback policy.

[ Merge of http://go/wvgerrit/133783 and http://go/ag/15645334 ]

SystemFallbackPolicy provides a thread-safe interface for accessing
and modifying OKP info.

Bug: 189232882
Test: Android unit tests
Change-Id: I4e43e3bc047ed5fb6cb517b53e4094e812b70e1e

Engine OKP provisioner.

[ Merge of http://go/wvgerrit/133803 and http://go/ag/15645335 ]

The OtaKeyboxProvisioner provides a CdmEngine-specific context for
performing OTA keybox provisioning.  Utilizes the system-wide
SystemFallbackPolicy to relay provisioning status between engines.
The provisioner will handle message wrapping and unwrapping of the
raw OTA keybox request / response into the SignedProvisioningMessage
which is sent to/received from the provisioning server.

[ Partial merge of http://go/wvgerrit/125844 ]

Note: Includes partial CryptoSession changes from various CLs.
CryptoSession functionality has been stripped to reduce impact of
this CL.

Bug: 189232882
Test: Android unit tests
Change-Id: I282bf7d1887daefb2250af1bd595c4dc3dfcfb29

Integrated OKP into CDM Engine

[ Merge of http://go/wvgerrit/133804 and http://go/ag/15646376 ]

Extended the functionality of the CdmEngine to check if the device
requires OKP and to initialize OKP resources if required.  The
functionality of OpenSession() and GetProvisioningRequest() have been
the most affected.  If OKP is required, these methods will signal to
the app that provisioning is required and will return an OKP request.

Once a device is provisioned, the OKP data is cleared away and the
CdmEngine will resume normal operation.  Engines created after a
device is provisioned will immediately enter normal operations.
The exception is for CdmEngines which failed to perform OKP for some
reason and are still running.  Those apps will need to restart before
gaining access to L1 operations.

Bug: 187646550
Test: Android integration tests
Merged-In: Ia572a66a7b73479355758aa3d0c682691eaca0fc
Change-Id: Ia572a66a7b73479355758aa3d0c682691eaca0fc
2021-10-20 17:50:08 -07:00

334 lines
13 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_CDM_SESSION_H_
#define WVCDM_CORE_CDM_SESSION_H_
#include <memory>
#include <set>
#include <string>
#include <vector>
#include "crypto_session.h"
#include "device_files.h"
#include "disallow_copy_and_assign.h"
#include "file_store.h"
#include "initialization_data.h"
#include "license.h"
#include "metrics_collections.h"
#include "oemcrypto_adapter.h"
#include "policy_engine.h"
#include "timer_metric.h"
#include "wv_cdm_types.h"
namespace wvcdm {
class CdmClientPropertySet;
class ServiceCertificate;
class WvCdmEventListener;
class UsageTableHeader;
class CdmSession {
public:
// Creates a new instance of the CdmSession with the given |file_system|
// and |metrics| parameters. Both parameters are owned by the caller and
// must remain in scope througout the scope of the new instance. |metrics|
// must not be null.
CdmSession(FileSystem* file_system,
std::shared_ptr<metrics::SessionMetrics> metrics);
virtual ~CdmSession();
void Close() { closed_ = true; }
bool IsClosed() { return closed_; }
// Initializes this instance of CdmSession with the given property set.
//
// |cdm_client_property_set| is caller owned, may be null, but must be in
// scope as long as the session is in scope. The service certificate field is
// cached at the time Init() is called.
virtual CdmResponseType Init(CdmClientPropertySet* cdm_client_property_set);
// Initializes this instance of CdmSession with the given parmeters.
// All parameters are owned by the caller.
//
// |cdm_client_property_set| is caller owned, may be null, but must be in
// scope as long as the session is in scope. The service certificate field is
// cached at the time Init() is called.
//
// |forced_session_id| is caller owned and may be null.
//
// |event_listener| is caller owned, may be null, but must be in scope as long
// as the session is in scope.
//
// |forced_level3|_is used to specify whether the "default" security level
// should always use L3 even if L1 is available.
virtual CdmResponseType Init(CdmClientPropertySet* cdm_client_property_set,
const CdmSessionId* forced_session_id,
WvCdmEventListener* event_listener,
bool forced_level3);
// Restores an offline session identified by the |key_set_id| and
// |license_type|. The |error_detail| will be filled with an internal error
// code. The |error_detail| may be a CdmResponseType or other error code type.
// It is only suitable for additional logging or debugging.
virtual CdmResponseType RestoreOfflineSession(const CdmKeySetId& key_set_id,
CdmLicenseType license_type,
int* error_detail);
// Restores an usage session from the provided |usage_data|.
// The |error_detail| will be filled with an internal error code. The
// |error_detail| may be a CdmResponseType or other error code type. It is
// only suitable for additional logging or debugging.
virtual CdmResponseType RestoreUsageSession(
const DeviceFiles::CdmUsageData& usage_data, int* error_detail);
virtual const CdmSessionId& session_id() { return session_id_; }
virtual const CdmKeySetId& key_set_id() { return key_set_id_; }
virtual CdmResponseType GenerateKeyRequest(
const InitializationData& init_data, CdmLicenseType license_type,
const CdmAppParameterMap& app_parameters, CdmKeyRequest* key_request);
// AddKey() - Accept license response and extract key info.
virtual CdmResponseType AddKey(const CdmKeyResponse& key_response);
// Override the currently-installed service certificate with a new service
// certificate.
virtual CdmResponseType SetServiceCertificate(
const std::string& service_certificate);
// Query session status
virtual CdmResponseType QueryStatus(CdmQueryMap* query_response);
// Query license information
virtual CdmResponseType QueryKeyStatus(CdmQueryMap* query_response);
// Query allowed usages for key
virtual CdmResponseType QueryKeyAllowedUsage(const std::string& key_id,
CdmKeyAllowedUsage* key_usage);
// Query OEMCrypto session ID
virtual CdmResponseType QueryOemCryptoSessionId(CdmQueryMap* query_response);
// Decrypt() - Accept encrypted buffer and return decrypted data.
virtual CdmResponseType Decrypt(const CdmDecryptionParametersV16& parameters);
// License renewal
// GenerateRenewalRequest() - Construct valid renewal request for the current
// session keys.
virtual CdmResponseType GenerateRenewalRequest(CdmKeyRequest* key_request);
// RenewKey() - Accept renewal response and update key info.
virtual CdmResponseType RenewKey(const CdmKeyResponse& key_response);
// License release
// GenerateReleaseRequest() - Construct valid release request for the current
// session keys.
virtual CdmResponseType GenerateReleaseRequest(CdmKeyRequest* key_request);
// ReleaseKey() - Accept response and release key.
virtual CdmResponseType ReleaseKey(const CdmKeyResponse& key_response);
virtual CdmResponseType DeleteUsageEntry(uint32_t usage_entry_number);
virtual bool IsKeyLoaded(const KeyId& key_id);
virtual int64_t GetDurationRemaining();
// Used for notifying the Policy Engine of resolution changes
virtual void NotifyResolution(uint32_t width, uint32_t height);
virtual void OnTimerEvent(bool update_usage);
virtual void OnKeyReleaseEvent(const CdmKeySetId& key_set_id);
virtual void GetApplicationId(std::string* app_id);
virtual SecurityLevel GetRequestedSecurityLevel() {
return requested_security_level_;
}
virtual CdmSecurityLevel GetSecurityLevel() { return security_level_; }
virtual CdmResponseType UpdateUsageEntryInformation();
virtual bool is_initial_usage_update() { return is_initial_usage_update_; }
virtual bool is_usage_update_needed() { return is_usage_update_needed_; }
virtual void reset_usage_flags() {
is_initial_usage_update_ = false;
is_usage_update_needed_ = false;
}
virtual bool is_release() { return is_release_; }
virtual bool is_offline() { return is_offline_; }
virtual bool is_temporary() { return is_temporary_; }
virtual bool license_received() { return license_received_; }
virtual bool has_provider_session_token() {
return (license_parser_ &&
license_parser_->provider_session_token().size() > 0);
}
virtual bool supports_usage_info() const {
return usage_table_header_ != nullptr;
}
// This method will remove keys by resetting crypto resources and
// policy information. This renders the session mostly useless and it is
// preferable to simply delete this object rather than call this method.
virtual CdmResponseType RemoveKeys();
// Remove the current offline license and/or matching usage record, if any
// exist.
CdmResponseType RemoveLicense();
// Delete this session's associated license or usage record file. Note that,
// unlike RemoveLicense(), this method ONLY affects the file system and does
// not touch the usage table headers.
bool DeleteLicenseFile();
// Generate unique ID for each new session.
CdmSessionId GenerateSessionId();
// Generic crypto operations - provides basic crypto operations that an
// application can use outside of content stream processing
// Encrypts a buffer of app-level data.
virtual CdmResponseType GenericEncrypt(const std::string& in_buffer,
const std::string& key_id,
const std::string& iv,
CdmEncryptionAlgorithm algorithm,
std::string* out_buffer);
// Decrypts a buffer of app-level data.
virtual CdmResponseType GenericDecrypt(const std::string& in_buffer,
const std::string& key_id,
const std::string& iv,
CdmEncryptionAlgorithm algorithm,
std::string* out_buffer);
// Computes the signature for a message.
virtual CdmResponseType GenericSign(const std::string& message,
const std::string& key_id,
CdmSigningAlgorithm algorithm,
std::string* signature);
// Verifies the signature on a buffer of app-level data.
virtual CdmResponseType GenericVerify(const std::string& message,
const std::string& key_id,
CdmSigningAlgorithm algorithm,
const std::string& signature);
virtual CdmResponseType SetDecryptHash(uint32_t frame_number,
const std::string& hash);
virtual CdmResponseType GetDecryptHashError(std::string* hash_error_string);
virtual metrics::SessionMetrics* GetMetrics() { return metrics_.get(); }
private:
friend class CdmSessionTest;
// Both these methods will attempt to load wrapped key material and
// cache values in |drm_certificate_| and |wrapped_private_key_|
// if successful.
// This methods will load the key from persistent storage.
CdmResponseType LoadPrivateKey();
// This method will load the specified key if valid or otherwise load
// the information from the legacy certificate.
CdmResponseType LoadPrivateOrLegacyKey(
const std::string& certificate,
const CryptoWrappedKey& wrapped_private_key);
CdmResponseType LoadPrivateKey(const std::string& certificate,
const CryptoWrappedKey& wrapped_private_key);
bool GenerateKeySetId(bool atsc_mode_enabled, CdmKeySetId* key_set_id);
CdmResponseType StoreLicense();
bool StoreLicense(CdmOfflineLicenseState state, int* error_detail);
bool UpdateUsageInfo();
CdmResponseType GenerateKeyRequestInternal(
const InitializationData& init_data, CdmLicenseType license_type,
const CdmAppParameterMap& app_parameters, CdmKeyRequest* key_request);
virtual CdmResponseType AddKeyInternal(const CdmKeyResponse& key_response);
void UpdateRequestLatencyTiming(CdmResponseType sts);
// Checks that the usage entry in the usage table header matches the
// information of the currently loaded license for this session.
// Returns false if there is any unexpected mismatch of information,
// true otherwise.
bool VerifyOfflineUsageEntry();
// These setters are for testing only. Takes ownership of the pointers.
void set_license_parser(CdmLicense* license_parser);
void set_crypto_session(CryptoSession* crypto_session);
void set_policy_engine(PolicyEngine* policy_engine);
void set_file_handle(DeviceFiles* file_handle);
// instance variables
std::shared_ptr<metrics::SessionMetrics> metrics_;
metrics::CryptoMetrics* crypto_metrics_;
metrics::TimerMetric life_span_;
metrics::TimerMetric license_request_latency_;
CdmKeyRequestType key_request_type_;
bool initialized_;
bool closed_; // Session closed, but final shared_ptr has not been released.
CdmSessionId session_id_;
FileSystem* file_system_;
std::unique_ptr<CdmLicense> license_parser_;
std::unique_ptr<CryptoSession> crypto_session_;
std::unique_ptr<PolicyEngine> policy_engine_;
std::unique_ptr<DeviceFiles> file_handle_;
bool license_received_;
bool is_offline_;
bool is_release_;
bool is_temporary_;
CdmSecurityLevel security_level_;
SecurityLevel requested_security_level_;
// If |forced_level3_|, |security_level_| and |requested_security_level_|
// MUST be set to kSecurityLevelL3 and kLevel3, respectively.
bool forced_level3_ = false;
CdmAppParameterMap app_parameters_;
bool atsc_mode_enabled_ = false;
std::string drm_certificate_;
CryptoWrappedKey wrapped_private_key_;
// decryption flags
bool is_initial_decryption_;
bool has_decrypted_since_last_report_; // ... last report to policy engine.
// Usage related flags and data
bool is_initial_usage_update_;
bool is_usage_update_needed_;
// Only assign |usage_table_header_| if capable of supporting usage
// information.
UsageTableHeader* usage_table_header_ = nullptr;
uint32_t usage_entry_number_;
CdmUsageEntry usage_entry_;
std::string usage_provider_session_token_;
// information useful for offline and usage scenarios
CdmKeyMessage key_request_;
CdmKeyResponse key_response_;
// license type offline related information
CdmInitData offline_init_data_;
CdmKeyMessage offline_key_renewal_request_;
CdmKeyResponse offline_key_renewal_response_;
std::string offline_release_server_url_;
// license type release and offline related information
CdmKeySetId key_set_id_;
bool has_license_been_loaded_ = false;
bool has_license_been_restored_ = false;
bool mock_license_parser_in_use_;
bool mock_policy_engine_in_use_;
CORE_DISALLOW_COPY_AND_ASSIGN(CdmSession);
};
} // namespace wvcdm
#endif // WVCDM_CORE_CDM_SESSION_H_