Source release v3.3.0

This commit is contained in:
Gene Morgan
2017-05-04 14:01:27 -07:00
parent baa7b133d3
commit 8082775924
678 changed files with 51264 additions and 14200 deletions

View File

@@ -3,9 +3,11 @@
#ifndef WVCDM_CORE_CDM_ENGINE_H_
#define WVCDM_CORE_CDM_ENGINE_H_
#include <memory>
#include <string>
#include <vector>
#include "cdm_session_map.h"
#include "certificate_provisioning.h"
#include "clock.h"
#include "crypto_session.h"
@@ -26,11 +28,9 @@ class CryptoEngine;
class UsagePropertySet;
class WvCdmEventListener;
typedef std::map<CdmSessionId, CdmSession*> CdmSessionMap;
typedef std::map<
CdmKeySetId,
std::pair<CdmSessionId, int64_t /* expiration time in seconds */> >
CdmReleaseKeySetMap;
// Keep expiration time for each key set
typedef std::map<CdmKeySetId,
std::pair<CdmSessionId, int64_t> > CdmReleaseKeySetMap;
class CdmEngine {
public:
@@ -44,6 +44,20 @@ class CdmEngine {
virtual CdmResponseType SetServiceCertificate(
const std::string& certificate);
// Report whether the service certificate has been set.
virtual bool HasServiceCertificate();
// Generate and return a Service Certificate Request message.
// This message can be sent to the License Server to get a service
// certificate.
virtual bool GetServiceCertificateRequest(CdmKeyMessage* request);
// Parse the message returned by the License Server in response to a
// Service Certificate Request message. Return the service certificate
// from the parsed response.
virtual CdmResponseType ParseServiceCertificateResponse(
const std::string& response, std::string* certificate);
// Session related methods
virtual CdmResponseType OpenSession(
const CdmKeySystem& key_system, CdmClientPropertySet* property_set,
@@ -158,24 +172,45 @@ class CdmEngine {
virtual CdmResponseType Unprovision(CdmSecurityLevel security_level);
// Delete OEMCrypto usage tables. Used by Unprovision().
CdmResponseType DeleteUsageTable(CdmSecurityLevel security_level);
virtual CdmResponseType DeleteUsageTable(CdmSecurityLevel security_level);
// Return the list of key_set_ids stored on the current (origin-specific)
// file system.
virtual CdmResponseType ListStoredLicenses(
CdmSecurityLevel security_level, std::vector<std::string>* key_set_ids);
// Return the list of key_set_ids stored as usage records on the
// current (origin-specific) file system.
virtual CdmResponseType ListUsageRecords(
const std::string& app_id, CdmSecurityLevel security_level,
std::vector<std::string>* ksids);
// Delete the usage record for the given key_set_id. This removes the
// usage record in the file system and the OEMCrypto usage record.
virtual CdmResponseType DeleteUsageRecord(const std::string& app_id,
CdmSecurityLevel security_level,
const std::string& key_set_id);
// Usage related methods for streaming licenses
// Retrieve a random usage info from the list of all usage infos for this app
// id.
virtual CdmResponseType GetUsageInfo(const std::string& app_id,
CdmUsageInfo* usage_info);
// Retrieve the usage info for the specified pst.
// Returns UNKNOWN_ERROR if no usage info was found.
virtual CdmResponseType GetUsageInfo(const std::string& app_id,
const CdmSecureStopId& ssid,
CdmUsageInfo* usage_info);
// Release all usage records for the current origin.
virtual CdmResponseType ReleaseAllUsageInfo(const std::string& app_id,
CdmSecurityLevel security_level);
// Release all usage records for the current origin. Span all
// security levels.
virtual CdmResponseType ReleaseAllUsageInfo(const std::string& app_id);
virtual CdmResponseType ReleaseUsageInfo(
const CdmUsageInfoReleaseMessage& message);
virtual CdmResponseType LoadUsageSession(const CdmKeySetId& key_set_id,
@@ -215,7 +250,7 @@ class CdmEngine {
CdmSigningAlgorithm algorithm,
const std::string& signature);
virtual size_t SessionSize() const { return sessions_.size(); }
virtual size_t SessionSize() const { return session_map_.Size(); }
// Is the key known to any session?
virtual bool IsKeyLoaded(const KeyId& key_id);
@@ -255,7 +290,7 @@ class CdmEngine {
void CloseExpiredReleaseSessions();
// instance variables
CdmSessionMap sessions_;
CdmSessionMap session_map_;
CdmReleaseKeySetMap release_key_sets_;
scoped_ptr<CertificateProvisioning> cert_provisioning_;
SecurityLevel cert_provisioning_requested_security_level_;
@@ -276,14 +311,7 @@ class CdmEngine {
scoped_ptr<UsagePropertySet> usage_property_set_;
int64_t last_usage_information_update_time_;
// Locks the list of sessions, |sessions_|, for the event timer. It will be
// locked in OpenSession, CloseSession. It is also locked in OnTimerEvent and
// OnKeyReleaseEvent while the list of event listeners is being generated.
// The layer above the CDM implementation is expected to handle thread
// synchronization to make sure other functions that access sessions do not
// occur simultaneously with OpenSession or CloseSession.
Lock session_list_lock_;
// Protect release_key_sets_ from non-thread-safe operations.
Lock release_key_sets_lock_;
CORE_DISALLOW_COPY_AND_ASSIGN(CdmEngine);

View File

@@ -28,6 +28,9 @@ class CdmSession {
CdmSession(FileSystem* file_system);
virtual ~CdmSession();
void Close() { closed_ = true; }
bool IsClosed() { return closed_; }
virtual CdmResponseType Init(CdmClientPropertySet* cdm_client_property_set);
virtual CdmResponseType Init(ServiceCertificate* service_certificate,
CdmClientPropertySet* cdm_client_property_set,
@@ -171,6 +174,7 @@ class CdmSession {
// instance variables
bool initialized_;
bool closed_; // Session closed, but final shared_ptr has not been released.
CdmSessionId session_id_;
scoped_ptr<CdmLicense> license_parser_;
scoped_ptr<CryptoSession> crypto_session_;

View File

@@ -0,0 +1,52 @@
// Copyright 2017 Google Inc. All Rights Reserved.
#ifndef WVCDM_CORE_CDM_SESSION_MAP_H_
#define WVCDM_CORE_CDM_SESSION_MAP_H_
#include <list>
#include <memory>
#include <string>
#include "lock.h"
#include "wv_cdm_types.h"
namespace wvcdm {
class CdmSession;
typedef std::list<std::shared_ptr<CdmSession> > CdmSessionList;
class CdmSessionMap {
public:
CdmSessionMap() {}
virtual ~CdmSessionMap();
void Add(const std::string& id, CdmSession* session);
bool CloseSession(const std::string& id);
bool Exists(const std::string& id);
size_t Size() const { return sessions_.size(); }
bool FindSession(const CdmSessionId& id,
std::shared_ptr<CdmSession>& session);
void GetSessionList(CdmSessionList& sessions);
private:
typedef std::map<CdmSessionId, std::shared_ptr<CdmSession> >
CdmIdToSessionMap;
bool FindSessionNoLock(const CdmSessionId& session_id,
std::shared_ptr<CdmSession>& session);
Lock lock_;
CdmIdToSessionMap sessions_;
CORE_DISALLOW_COPY_AND_ASSIGN(CdmSessionMap);
};
} // namespace wvcdm
#endif // WVCDM_CORE_CDM_SESSION_MAP_H_

View File

@@ -49,12 +49,6 @@ class CertificateProvisioning {
video_widevine::SignedProvisioningMessage::ProtocolVersion
GetProtocolVersion();
void ComposeJsonRequestAsQueryString(const std::string& message,
CdmProvisioningRequest* request);
bool ParseJsonResponse(const CdmProvisioningResponse& json_str,
const std::string& start_substr,
const std::string& end_substr, std::string* result);
CryptoSession crypto_session_;
CdmCertificateType cert_type_;
ServiceCertificate* service_certificate_;

View File

@@ -68,12 +68,15 @@ class CryptoSession {
virtual bool GenerateDerivedKeys(const std::string& message);
virtual bool GenerateDerivedKeys(const std::string& message,
const std::string& session_key);
virtual bool RewrapDeviceRSAKey(const std::string& message,
const std::string& signature,
const std::string& nonce,
const std::string& enc_rsa_key,
const std::string& rsa_key_iv,
std::string* wrapped_rsa_key);
virtual bool RewrapCertificate(const std::string& signed_message,
const std::string& signature,
const std::string& nonce,
const std::string& private_key,
const std::string& iv,
const std::string& wrapping_key,
std::string* wrapped_private_key);
// Media data path
virtual CdmResponseType Decrypt(const CdmDecryptionParameters& parameters);
@@ -127,7 +130,7 @@ class CryptoSession {
const std::string& signature);
private:
bool GetProvisioningMethod(CdmClientTokenType* token_type);
bool GetProvisioningMethod(CdmClientTokenType& token_type);
void Init();
void Terminate();
bool GetTokenFromKeybox(std::string* token);
@@ -140,6 +143,17 @@ class CryptoSession {
bool GenerateRsaSignature(const std::string& message, std::string* signature);
size_t GetOffset(std::string message, std::string field);
bool SetDestinationBufferType();
bool RewrapDeviceRSAKey(
const std::string& message, const std::string& signature,
const std::string& nonce, const std::string& enc_rsa_key,
const std::string& rsa_key_iv, std::string* wrapped_rsa_key);
bool RewrapDeviceRSAKey30(
const std::string& message, const std::string& nonce,
const std::string& private_key, const std::string& iv,
const std::string& wrapping_key, std::string* wrapped_private_key);
bool SelectKey(const std::string& key_id);
static const OEMCrypto_Algorithm kInvalidAlgorithm =
@@ -170,6 +184,7 @@ class CryptoSession {
bool open_;
CdmClientTokenType pre_provision_token_type_;
std::string oem_token_; // Cached OEMCrypto Public Key
bool update_usage_table_after_close_session_;
CryptoSessionId oec_session_id_;

View File

@@ -73,29 +73,45 @@ class DeviceFiles {
virtual bool ReserveLicenseId(const std::string& key_set_id);
virtual bool UnreserveLicenseId(const std::string& key_set_id);
// Store a usage record to the set of usage information on the file system.
virtual bool StoreUsageInfo(const std::string& provider_session_token,
const CdmKeyMessage& key_request,
const CdmKeyResponse& key_response,
const std::string& app_id,
const std::string& key_set_id);
// Extract KSIDs from usage information on the file system.
virtual bool ListUsageRecords(const std::string& app_id,
std::vector<std::string>* ksids);
// Get the provider token for the given key_set_id.
virtual bool GetProviderToken(const std::string& app_id,
const std::string& key_set_id,
std::string* provider_session_token);
// Delete the usage record for the given PST.
virtual bool DeleteUsageInfo(const std::string& app_id,
const std::string& provider_session_token);
// Delete usage information from the file system. Puts a list of all the
// psts that were deleted from the file into |provider_session_tokens|.
virtual bool DeleteAllUsageInfoForApp(
const std::string& app_id,
std::vector<std::string>* provider_session_tokens);
// Retrieve one usage info from the file. Subsequent calls will retrieve
// subsequent entries in the table for this app_id.
virtual bool RetrieveUsageInfo(
const std::string& app_id,
std::vector<std::pair<CdmKeyMessage, CdmKeyResponse> >* usage_info);
// Retrieve the usage info entry specified by |provider_session_token|.
// Returns false if the entry could not be found.
virtual bool RetrieveUsageInfo(const std::string& app_id,
const std::string& provider_session_token,
CdmKeyMessage* license_request,
CdmKeyResponse* license_response);
// Retrieve the usage info entry specified by |key_set_id|.
// Returns false if the entry could not be found.
virtual bool RetrieveUsageInfoByKeySetId(const std::string& app_id,
@@ -110,6 +126,7 @@ class DeviceFiles {
CdmHlsMethod* method,
std::vector<uint8_t>* media_segment_iv);
virtual bool DeleteHlsAttributes(const std::string& key_set_id);
private:
// Extract serial number and system ID from DRM Device certificate
bool ExtractDeviceInfo(const std::string& device_certificate,
@@ -138,7 +155,7 @@ class DeviceFiles {
#if defined(UNIT_TEST)
FRIEND_TEST(DeviceFilesSecurityLevelTest, SecurityLevel);
FRIEND_TEST(DeviceCertificateStoreTest, StoreCertificate);
FRIEND_TEST(DeviceCertificateTest, ReadCertificate);
FRIEND_TEST(DeviceCertificateTest, DISABLED_ReadCertificate);
FRIEND_TEST(DeviceCertificateTest, HasCertificate);
FRIEND_TEST(DeviceFilesStoreTest, StoreLicense);
FRIEND_TEST(DeviceFilesHlsAttributesTest, Delete);

View File

@@ -29,7 +29,7 @@ class CdmLicense {
virtual bool Init(
ServiceCertificate* service_certificate, const std::string& client_token,
CdmClientTokenType client_token_type, const std::string& serial_number,
CdmClientTokenType client_token_type, const std::string& device_id,
CryptoSession* session, PolicyEngine* policy_engine);
virtual CdmResponseType PrepareKeyRequest(
@@ -52,7 +52,6 @@ class CdmLicense {
int64_t grace_period_end_time);
virtual bool RestoreLicenseForRelease(const CdmKeyMessage& license_request,
const CdmKeyResponse& license_response);
virtual bool HasInitData() { return stored_init_data_.get(); }
virtual bool IsKeyLoaded(const KeyId& key_id);
virtual std::string provider_session_token() {
@@ -89,9 +88,8 @@ class CdmLicense {
std::string server_url_;
std::string client_token_;
CdmClientTokenType client_token_type_;
std::string serial_number_;
std::string device_id_;
const CdmSessionId session_id_;
scoped_ptr<InitializationData> stored_init_data_;
bool initialized_;
std::set<KeyId> loaded_keys_;
std::string provider_session_token_;

View File

@@ -37,7 +37,11 @@ class LicenseKeys {
virtual bool ApplyStatusChange(CdmKeyStatus new_status,
bool* new_usable_keys);
// Populates the CdmKeyStatusMap with the current content keys.
// Returns current CdmKeyStatus for the given key.
// Returns kKeyStatusKeyUnknown if key_id not found.
virtual CdmKeyStatus GetKeyStatus(const KeyId& key_id);
// Populates a CdmKeyStatusMap with the current content keys.
virtual void ExtractKeyStatuses(CdmKeyStatusMap* content_keys);
// Determines whether the specified key can be used under the current

View File

@@ -34,6 +34,11 @@ class PolicyEngine {
// status is not calculated to avoid overhead in the decryption path.
virtual bool CanDecryptContent(const KeyId& key_id);
// Returns the current CdmKeyStatus for the given key, or
// kKeyStatusKeyUnknown if the key is not found. This is useful for finding
// out why a key is not usable.
virtual CdmKeyStatus GetKeyStatus(const KeyId& key_id);
// OnTimerEvent is called when a timer fires. It notifies the Policy Engine
// that the timer has fired and dispatches the relevant events through
// |event_listener_|.
@@ -104,11 +109,9 @@ class PolicyEngine {
friend class PolicyEngineConstraintsTest;
void InitDevice(CryptoSession* crypto_session);
void CheckDevice(int64_t current_time);
void SetDeviceResolution(uint32_t width, uint32_t height) {
current_resolution_ = width * height;
}
void SetDeviceResolution(uint32_t width, uint32_t height);
void CheckDeviceHdcpStatusOnTimer(int64_t current_time);
void CheckDeviceHdcpStatus();
typedef enum {
kLicenseStateInitial,

View File

@@ -40,6 +40,9 @@ class Properties {
static inline bool use_certificates_as_identification() {
return use_certificates_as_identification_;
}
static inline bool provisioning_messages_are_binary() {
return provisioning_messages_are_binary_;
}
static inline bool security_level_path_backward_compatibility_support() {
return security_level_path_backward_compatibility_support_;
}
@@ -90,6 +93,9 @@ class Properties {
static void set_use_certificates_as_identification(bool flag) {
use_certificates_as_identification_ = flag;
}
static void set_provisioning_messages_are_binary(bool flag) {
provisioning_messages_are_binary_ = flag;
}
static void set_security_level_path_backward_compatibility_support(
bool flag) {
security_level_path_backward_compatibility_support_ = flag;
@@ -111,6 +117,7 @@ class Properties {
static bool oem_crypto_use_userspace_buffers_;
static bool use_certificates_as_identification_;
static bool security_level_path_backward_compatibility_support_;
static bool provisioning_messages_are_binary_;
static scoped_ptr<CdmClientPropertySetMap> session_property_set_;
CORE_DISALLOW_COPY_AND_ASSIGN(Properties);

View File

@@ -11,13 +11,11 @@
// Certificate Request to the target server to get one. Once the Service
// Certificate is established for the session, it should not change.
#include "license_protocol.pb.h"
#include "wv_cdm_types.h"
#include <memory>
namespace video_widevine {
class SignedMessage;
class LicenseRequest;
} // namespace video_widevine
#include "license_protocol.pb.h"
#include "privacy_crypto.h"
#include "wv_cdm_types.h"
namespace wvcdm {
@@ -25,23 +23,20 @@ class CryptoSession;
class ServiceCertificate {
public:
ServiceCertificate() {}
ServiceCertificate() : has_certificate_(false) {}
virtual ~ServiceCertificate() {}
// Set up a new service certificate.
// Accept a serialized video_widevine::SignedDrmDeviceCertificate message.
virtual CdmResponseType Init(const std::string& signed_certificate);
// Initialize the service certificate.
// Set the certificate with no certificate and provider ID.
virtual void Clear();
bool has_certificate() const { return has_certificate_; }
const std::string certificate() const { return certificate_; }
const std::string& provider_id() const { return provider_id_; }
// Current state of certificate.
// If !HasCertificate() and privacy mode is enabled, then should call
// PrepareRequest() and pass the request to the license server.
virtual bool HasCertificate() { return !certificate_.empty(); }
virtual bool HasProviderId() { return !provider_id_.empty(); }
virtual const std::string& provider_id() { return provider_id_; }
// Verify the signature for a message.
virtual CdmResponseType VerifySignedMessage(const std::string& message,
const std::string& signature);
// Encrypt the ClientIdentification message for a provisioning or
// licensing request. Encryption is performed using the current
@@ -54,29 +49,23 @@ class ServiceCertificate {
const video_widevine::ClientIdentification* clear_client_id,
video_widevine::EncryptedClientIdentification* encrypted_client_id);
// Construct service certificate request.
virtual bool PrepareRequest(CdmKeyMessage* signed_request);
// Parse service certificate response and make it usable.
virtual CdmResponseType HandleResponse(
const std::string& signed_respnse);
private:
// Verify the signature on the signed service certificate.
// Extract and save the certificate and provider_id.
// Expected format: serialized video_widevine::SignedDrmDeviceCertificate.
virtual CdmResponseType VerifyAndExtract(
const std::string& raw_certificate);
// True while waiting for response to service certificate request.
bool fetch_in_progress_;
// Track whether object holds valid certificate
bool has_certificate_;
// Certificate, verified and extracted from signed message.
std::string certificate_;
// Certificate serial number.
std::string serial_number_;
// Provider ID, extracted from certificate message.
std::string provider_id_;
// Public key.
std::unique_ptr<RsaPublicKey> public_key_;
CORE_DISALLOW_COPY_AND_ASSIGN(ServiceCertificate);
};

View File

@@ -99,6 +99,10 @@ static const std::string HLS_URI_ATTRIBUTE = "URI";
static const char EMPTY_ORIGIN[] = "";
static const char EMPTY_SPOID[] = "";
//Policy engine HDCP enforcement
static const uint32_t HDCP_UNSPECIFIED_VIDEO_RESOLUTION = 0;
static const int64_t HDCP_DEVICE_CHECK_INTERVAL = 10;
} // namespace wvcdm
#endif // WVCDM_CORE_WV_CDM_CONSTANTS_H_

View File

@@ -177,9 +177,10 @@ enum CdmResponseType {
UNPROVISION_ERROR_4,
UNSUPPORTED_INIT_DATA,
USAGE_INFO_NOT_FOUND,
LICENSE_RENEWAL_SERVICE_CERTIFICATE_GENERATION_ERROR, /* 140 */
UNUSED_8, /* 140 */
/* UNUSED_8 previously LICENSE_RENEWAL_SERVICE_CERTIFICATE_GENERATION_ERROR */
PARSE_SERVICE_CERTIFICATE_ERROR,
SERVICE_CERTIFICATE_TYPE_ERROR,
UNUSED_10, /* previously SERVICE_CERTIFICATE_TYPE_ERROR */
CLIENT_ID_GENERATE_RANDOM_ERROR,
CLIENT_ID_AES_INIT_ERROR,
CLIENT_ID_AES_ENCRYPT_ERROR, /* 145 */
@@ -194,7 +195,8 @@ enum CdmResponseType {
UNUSED_2, /* previously INVALID_PARAMETERS_LIC_5 */
INVALID_PARAMETERS_LIC_6,
INVALID_PARAMETERS_LIC_7, /* 155 */
LICENSE_REQUEST_SERVICE_CERTIFICATE_GENERATION_ERROR,
UNUSED_9,
/* UNUSED_9 previously LICENSE_REQUEST_SERVICE_CERTIFICATE_GENERATION_ERROR */
CENC_INIT_DATA_UNAVAILABLE,
PREPARE_CENC_CONTENT_ID_FAILED,
WEBM_INIT_DATA_UNAVAILABLE,
@@ -250,10 +252,29 @@ enum CdmResponseType {
CERT_PROVISIONING_CLIENT_TOKEN_ERROR_2, /* 210 */
LICENSING_CLIENT_TOKEN_ERROR_1,
INVALID_PARAMETERS_ENG_17,
STORE_LICENSE_ERROR_3,
INVALID_PARAMETERS_ENG_18,
LIST_LICENSE_ERROR_1,
LIST_LICENSE_ERROR_2, /* 215 */
LIST_USAGE_ERROR_1,
LIST_USAGE_ERROR_2,
DELETE_USAGE_ERROR_1,
DELETE_USAGE_ERROR_2,
DELETE_USAGE_ERROR_3, /* 220 */
RELEASE_ALL_USAGE_INFO_ERROR_3,
RELEASE_ALL_USAGE_INFO_ERROR_4,
PRIVACY_MODE_ERROR_1,
PRIVACY_MODE_ERROR_2,
PRIVACY_MODE_ERROR_3, /* 225 */
EMPTY_RESPONSE_ERROR_1,
INVALID_PARAMETERS_ENG_19,
PARSE_RESPONSE_ERROR_1,
PARSE_RESPONSE_ERROR_2,
PARSE_RESPONSE_ERROR_3, /* 230 */
PARSE_RESPONSE_ERROR_4,
};
enum CdmKeyStatus {
kKeyStatusKeyUnknown,
kKeyStatusUsable,
kKeyStatusExpired,
kKeyStatusOutputNotAllowed,
@@ -270,9 +291,6 @@ enum CdmLicenseType {
kLicenseTypeOffline,
kLicenseTypeStreaming,
kLicenseTypeRelease,
// If the original request was saved to make a service certificate request,
// use Deferred for the license type in the subsequent request.
kLicenseTypeDeferred,
// Like Streaming, but stricter. Does not permit storage of any kind.
// Named after the 'temporary' session type in EME, which has this behavior.
kLicenseTypeTemporary,