Source release v3.1.0

This commit is contained in:
Gene Morgan
2016-07-19 18:43:15 -07:00
parent 7a7f78d654
commit 643b91b616
108 changed files with 16537 additions and 7174 deletions

View File

@@ -7,6 +7,7 @@
#include "certificate_provisioning.h"
#include "crypto_session.h"
#include "file_store.h"
#include "initialization_data.h"
#include "lock.h"
#include "oemcrypto_adapter.h"
@@ -26,22 +27,24 @@ typedef std::map<CdmKeySetId, CdmSessionId> CdmReleaseKeySetMap;
class CdmEngine {
public:
CdmEngine();
CdmEngine(FileSystem* file_system);
virtual ~CdmEngine();
// Session related methods
virtual CdmResponseType OpenSession(const CdmKeySystem& key_system,
CdmClientPropertySet* property_set,
const std::string& origin,
const CdmSessionId& forced_session_id,
WvCdmEventListener* event_listener);
virtual CdmResponseType OpenSession(const CdmKeySystem& key_system,
CdmClientPropertySet* property_set,
WvCdmEventListener* event_listener,
const CdmSessionId* forced_session_id,
CdmSessionId* session_id);
virtual CdmResponseType CloseSession(const CdmSessionId& session_id);
virtual bool IsOpenSession(const CdmSessionId& session_id);
virtual CdmResponseType OpenKeySetSession(
const CdmKeySetId& key_set_id, CdmClientPropertySet* property_set,
const std::string& origin, WvCdmEventListener* event_listener);
virtual CdmResponseType OpenKeySetSession(const CdmKeySetId& key_set_id,
CdmClientPropertySet* property_set,
WvCdmEventListener* event_listener);
virtual CdmResponseType CloseKeySetSession(const CdmKeySetId& key_set_id);
// License related methods
@@ -58,27 +61,17 @@ class CdmEngine {
// app_parameters: Additional, application-specific parameters that factor
// into the request generation. This is ignored for release
// and renewal requests.
// key_request: This must be non-null and point to a CdmKeyMessage. The buffer
// will have its contents replaced with the key request.
// key_request_type: May be null. If it is non-null, it will be filled with
// key request type, whether it is an initial request,
// renewal request or release request etc.
// server_url: This must be non-null and point to a string. The string will
// have its contents replaced with the default URL (if one is
// known) to send this key request to.
// key_set_id_out: May be null. If it is non-null, the CdmKeySetId pointed to
// will have its contents replaced with the key set ID of the
// session. Note that for non-offline license requests, the
// key set ID is empty, so the CdmKeySetId will be cleared.
// TODO(kqyang): Consider refactor GenerateKeyRequest to reduce the number of
// parameters.
// key_request: This must be non-null and point to a CdmKeyRequest. The
// message field will be filled with the key request, the
// type field will be filled with the key request type,
// whether it is an initial request, renewal request,
// release request, etc. The url field will be filled with
// the default URL (if one is known) to send this key
// request to.
virtual CdmResponseType GenerateKeyRequest(
const CdmSessionId& session_id, const CdmKeySetId& key_set_id,
const InitializationData& init_data, const CdmLicenseType license_type,
CdmAppParameterMap& app_parameters, CdmKeyMessage* key_request,
CdmKeyRequestType* key_request_type, std::string* server_url,
CdmKeySetId* key_set_id_out);
CdmAppParameterMap& app_parameters, CdmKeyRequest* key_request);
// Accept license response and extract key info.
virtual CdmResponseType AddKey(const CdmSessionId& session_id,
const CdmKeyResponse& key_data,
@@ -90,9 +83,8 @@ class CdmEngine {
virtual CdmResponseType RemoveKeys(const CdmSessionId& session_id);
// Construct valid renewal request for the current session keys.
virtual CdmResponseType GenerateRenewalRequest(const CdmSessionId& session_id,
CdmKeyMessage* key_request,
std::string* server_url);
virtual CdmResponseType GenerateRenewalRequest(
const CdmSessionId& session_id, CdmKeyRequest* key_request);
// Accept renewal response and update key info.
virtual CdmResponseType RenewKey(const CdmSessionId& session_id,
@@ -100,38 +92,48 @@ class CdmEngine {
// Query system information
virtual CdmResponseType QueryStatus(SecurityLevel security_level,
const std::string& key,
std::string* value);
const std::string& query_token,
std::string* query_response);
// Query session information
virtual CdmResponseType QuerySessionStatus(const CdmSessionId& session_id,
CdmQueryMap* key_info);
CdmQueryMap* query_response);
virtual bool IsReleaseSession(const CdmSessionId& session_id);
virtual bool IsOfflineSession(const CdmSessionId& session_id);
// Query license information
virtual CdmResponseType QueryKeyStatus(const CdmSessionId& session_id,
CdmQueryMap* key_info);
CdmQueryMap* query_response);
// Query session control information
virtual CdmResponseType QueryKeyControlInfo(const CdmSessionId& session_id,
CdmQueryMap* key_info);
// Query the types of usage permitted for the specified key.
virtual CdmResponseType QueryKeyAllowedUsage(const CdmSessionId& session_id,
const std::string& key_id,
CdmKeyAllowedUsage* key_usage);
// Query the types of usage permitted for the specified key.
// Apply the query across all sessions. If the key is found in more than
// one session, return the allowed usage settings only if the usage settings
// are identical for each instance of the key. Otherwise, clear the settings
// and return KEY_CONFLICT_1.
virtual CdmResponseType QueryKeyAllowedUsage(const std::string& key_id,
CdmKeyAllowedUsage* key_usage);
// Query OEMCrypto session ID
virtual CdmResponseType QueryOemCryptoSessionId(
const CdmSessionId& session_id, CdmQueryMap* query_response);
// Provisioning related methods
virtual CdmResponseType GetProvisioningRequest(
CdmCertificateType cert_type, const std::string& cert_authority,
const std::string& origin, CdmProvisioningRequest* request,
std::string* default_url);
CdmProvisioningRequest* request, std::string* default_url);
virtual CdmResponseType HandleProvisioningResponse(
const std::string& origin, const CdmProvisioningResponse& response,
std::string* cert, std::string* wrapped_key);
const CdmProvisioningResponse& response, std::string* cert,
std::string* wrapped_key);
virtual bool IsProvisioned(CdmSecurityLevel security_level,
const std::string& origin);
virtual bool IsProvisioned(CdmSecurityLevel security_level);
virtual CdmResponseType Unprovision(CdmSecurityLevel security_level,
const std::string& origin);
virtual CdmResponseType Unprovision(CdmSecurityLevel security_level);
// Usage related methods for streaming licenses
// Retrieve a random usage info from the list of all usage infos for this app
@@ -154,6 +156,35 @@ class CdmEngine {
virtual CdmResponseType Decrypt(const CdmSessionId& session_id,
const CdmDecryptionParameters& parameters);
// 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& session_id, 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& session_id, 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& session_id,
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& session_id,
const std::string& message,
const std::string& key_id,
CdmSigningAlgorithm algorithm,
const std::string& signature);
virtual size_t SessionSize() const { return sessions_.size(); }
// Is the key known to any session?
@@ -175,6 +206,12 @@ class CdmEngine {
private:
// private methods
CdmResponseType OpenSession(const CdmKeySystem& key_system,
CdmClientPropertySet* property_set,
WvCdmEventListener* event_listener,
const CdmSessionId* forced_session_id,
CdmSessionId* session_id);
void DeleteAllUsageReportsUponFactoryReset();
bool ValidateKeySystem(const CdmKeySystem& key_system);
CdmResponseType GetUsageInfo(const std::string& app_id,
@@ -190,6 +227,7 @@ class CdmEngine {
CdmReleaseKeySetMap release_key_sets_;
scoped_ptr<CertificateProvisioning> cert_provisioning_;
SecurityLevel cert_provisioning_requested_security_level_;
FileSystem* file_system_;
static bool seeded_;

View File

@@ -8,6 +8,7 @@
#include "crypto_session.h"
#include "device_files.h"
#include "file_store.h"
#include "initialization_data.h"
#include "license.h"
#include "oemcrypto_adapter.h"
@@ -22,12 +23,13 @@ class WvCdmEventListener;
class CdmSession {
public:
CdmSession(CdmClientPropertySet* cdm_client_property_set,
const std::string& origin, WvCdmEventListener* event_listener,
const CdmSessionId* forced_session_id);
CdmSession(FileSystem* file_system);
virtual ~CdmSession();
virtual CdmResponseType Init();
virtual CdmResponseType Init(CdmClientPropertySet* cdm_client_property_set);
virtual CdmResponseType Init(CdmClientPropertySet* cdm_client_property_set,
const CdmSessionId* forced_session_id,
WvCdmEventListener* event_listener);
virtual CdmResponseType RestoreOfflineSession(
const CdmKeySetId& key_set_id, const CdmLicenseType license_type);
@@ -35,25 +37,27 @@ class CdmSession {
const CdmKeyMessage& key_request, const CdmKeyResponse& key_response);
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, CdmKeyMessage* key_request,
CdmKeyRequestType* key_request_type, std::string* server_url,
CdmKeySetId* key_set_id);
const CdmAppParameterMap& app_parameters, CdmKeyRequest* key_request);
// AddKey() - Accept license response and extract key info.
virtual CdmResponseType AddKey(const CdmKeyResponse& key_response,
CdmKeySetId* key_set_id);
virtual CdmResponseType AddKey(const CdmKeyResponse& key_response);
// Query session status
virtual CdmResponseType QueryStatus(CdmQueryMap* key_info);
virtual CdmResponseType QueryStatus(CdmQueryMap* query_response);
// Query license information
virtual CdmResponseType QueryKeyStatus(CdmQueryMap* key_info);
virtual CdmResponseType QueryKeyStatus(CdmQueryMap* query_response);
// Query session control info
virtual CdmResponseType QueryKeyControlInfo(CdmQueryMap* key_info);
// 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 CdmDecryptionParameters& parameters);
@@ -61,8 +65,7 @@ class CdmSession {
// License renewal
// GenerateRenewalRequest() - Construct valid renewal request for the current
// session keys.
virtual CdmResponseType GenerateRenewalRequest(CdmKeyMessage* key_request,
std::string* server_url);
virtual CdmResponseType GenerateRenewalRequest(CdmKeyRequest* key_request);
// RenewKey() - Accept renewal response and update key info.
virtual CdmResponseType RenewKey(const CdmKeyResponse& key_response);
@@ -70,13 +73,13 @@ class CdmSession {
// License release
// GenerateReleaseRequest() - Construct valid release request for the current
// session keys.
virtual CdmResponseType GenerateReleaseRequest(CdmKeyMessage* key_request,
std::string* server_url);
virtual CdmResponseType GenerateReleaseRequest(CdmKeyRequest* key_request);
// ReleaseKey() - Accept response and release key.
virtual CdmResponseType ReleaseKey(const CdmKeyResponse& key_response);
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);
@@ -116,11 +119,41 @@ class CdmSession {
bool DeleteLicense();
// 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);
private:
friend class CdmSessionTest;
// Generate unique ID for each new session.
CdmSessionId GenerateSessionId();
bool GenerateKeySetId(CdmKeySetId* key_set_id);
CdmResponseType StoreLicense();
@@ -135,7 +168,6 @@ class CdmSession {
// instance variables
bool initialized_;
CdmSessionId session_id_;
const std::string origin_;
scoped_ptr<CdmLicense> license_parser_;
scoped_ptr<CryptoSession> crypto_session_;
scoped_ptr<PolicyEngine> policy_engine_;
@@ -167,6 +199,9 @@ class CdmSession {
// license type release and offline related information
CdmKeySetId key_set_id_;
bool mock_license_parser_in_use_;
bool mock_policy_engine_in_use_;
CORE_DISALLOW_COPY_AND_ASSIGN(CdmSession);
};

View File

@@ -12,6 +12,7 @@
namespace wvcdm {
class CdmSession;
class FileSystem;
class CertificateProvisioning {
public:
@@ -26,7 +27,7 @@ class CertificateProvisioning {
CdmProvisioningRequest* request,
std::string* default_url);
CdmResponseType HandleProvisioningResponse(
const std::string& origin,
FileSystem* file_system,
const CdmProvisioningResponse& response,
std::string* cert,
std::string* wrapped_key);

View File

@@ -17,6 +17,7 @@ class CryptoKey {
const std::string& key_data_iv() const { return key_data_iv_; }
const std::string& key_control() const { return key_control_; }
const std::string& key_control_iv() const { return key_control_iv_; }
CdmCipherMode cipher_mode() const { return cipher_mode_; }
void set_key_id(const std::string& key_id) { key_id_ = key_id; }
void set_key_data(const std::string& key_data) { key_data_ = key_data; }
void set_key_data_iv(const std::string& iv) { key_data_iv_ = iv; }
@@ -24,6 +25,9 @@ class CryptoKey {
void set_key_control_iv(const std::string& ctl_iv) {
key_control_iv_ = ctl_iv;
}
void set_cipher_mode(CdmCipherMode cipher_mode) {
cipher_mode_ = cipher_mode;
}
bool HasKeyControl() const { return key_control_.size() >= 16; }
@@ -33,6 +37,7 @@ class CryptoKey {
std::string key_data_;
std::string key_control_;
std::string key_control_iv_;
CdmCipherMode cipher_mode_;
};
} // namespace wvcdm

View File

@@ -35,6 +35,7 @@ class CryptoSession {
virtual bool GetApiVersion(uint32_t* version);
virtual bool GetSystemId(uint32_t* system_id);
virtual bool GetProvisioningId(std::string* provisioning_id);
virtual uint8_t GetSecurityPatchLevel();
virtual CdmResponseType Open() { return Open(kLevelDefault); }
virtual CdmResponseType Open(SecurityLevel requested_security_level);
@@ -102,6 +103,25 @@ class CryptoSession {
virtual bool GetNumberOfOpenSessions(size_t* count);
virtual bool GetMaxNumberOfSessions(size_t* max);
virtual CdmResponseType GenericEncrypt(const std::string& in_buffer,
const std::string& key_id,
const std::string& iv,
CdmEncryptionAlgorithm algorithm,
std::string* out_buffer);
virtual CdmResponseType GenericDecrypt(const std::string& in_buffer,
const std::string& key_id,
const std::string& iv,
CdmEncryptionAlgorithm algorithm,
std::string* out_buffer);
virtual CdmResponseType GenericSign(const std::string& message,
const std::string& key_id,
CdmSigningAlgorithm algorithm,
std::string* signature);
virtual CdmResponseType GenericVerify(const std::string& message,
const std::string& key_id,
CdmSigningAlgorithm algorithm,
const std::string& signature);
private:
void Init();
void Terminate();
@@ -113,9 +133,17 @@ class CryptoSession {
bool GenerateRsaSignature(const std::string& message, std::string* signature);
size_t GetOffset(std::string message, std::string field);
bool SetDestinationBufferType();
bool SelectKey(const std::string& key_id);
static const OEMCrypto_Algorithm kInvalidAlgorithm =
static_cast<OEMCrypto_Algorithm>(-1);
OEMCrypto_Algorithm GenericSigningAlgorithm(CdmSigningAlgorithm algorithm);
OEMCrypto_Algorithm GenericEncryptionAlgorithm(
CdmEncryptionAlgorithm algorithm);
size_t GenericEncryptionBlockSize(CdmEncryptionAlgorithm algorithm);
static const size_t kAes128BlockSize = 16; // Block size for AES_CBC_128
static const size_t kSignatureSize = 32; // size for HMAC-SHA256 signature
static Lock crypto_lock_;
static bool initialized_;
@@ -129,11 +157,13 @@ class CryptoSession {
bool is_destination_buffer_type_valid_;
SecurityLevel requested_security_level_;
KeyId key_id_;
KeyId cached_key_id_;
uint64_t request_id_base_;
static uint64_t request_id_index_;
CdmCipherMode cipher_mode_;
CORE_DISALLOW_COPY_AND_ASSIGN(CryptoSession);
};

View File

@@ -18,7 +18,7 @@
namespace wvcdm {
class File;
class FileSystem;
class DeviceFiles {
public:
@@ -28,7 +28,7 @@ class DeviceFiles {
kLicenseStateUnknown,
} LicenseState;
DeviceFiles();
DeviceFiles(FileSystem*);
virtual ~DeviceFiles();
virtual bool Init(CdmSecurityLevel security_level);
@@ -36,14 +36,12 @@ class DeviceFiles {
return Init(security_level);
}
virtual bool StoreCertificate(const std::string& origin,
const std::string& certificate,
virtual bool StoreCertificate(const std::string& certificate,
const std::string& wrapped_private_key);
virtual bool RetrieveCertificate(const std::string& origin,
std::string* certificate,
virtual bool RetrieveCertificate(std::string* certificate,
std::string* wrapped_private_key);
virtual bool HasCertificate(const std::string& origin);
virtual bool RemoveCertificate(const std::string& origin);
virtual bool HasCertificate();
virtual bool RemoveCertificate();
virtual bool StoreLicense(const std::string& key_set_id,
const LicenseState state,
@@ -100,6 +98,13 @@ class DeviceFiles {
CdmKeyMessage* license_request,
CdmKeyResponse* license_response);
virtual bool StoreHlsAttributes(const std::string& key_set_id,
const CdmHlsMethod method,
const std::vector<uint8_t>& media_segment_iv);
virtual bool RetrieveHlsAttributes(const std::string& key_set_id,
CdmHlsMethod* method,
std::vector<uint8_t>* media_segment_iv);
virtual bool DeleteHlsAttributes(const std::string& key_set_id);
private:
// Helpers that wrap the File interface and automatically handle hashing, as
// well as adding the device files base path to to the file name.
@@ -113,29 +118,25 @@ class DeviceFiles {
bool RemoveFile(const std::string& name);
ssize_t GetFileSize(const std::string& name);
// Certificate and offline licenses are now stored in security
// level specific directories. In an earlier version they were
// stored in a common directory and need to be copied over.
virtual void SecurityLevelPathBackwardCompatibility();
static std::string GetCertificateFileName(const std::string& origin);
static std::string GetCertificateFileName();
static std::string GetHlsAttributesFileNameExtension();
static std::string GetLicenseFileNameExtension();
static std::string GetUsageInfoFileName(const std::string& app_id);
static std::string GetFileNameSafeHash(const std::string& input);
// For testing only:
void SetTestFile(File* file);
#if defined(UNIT_TEST)
FRIEND_TEST(DeviceFilesSecurityLevelTest, SecurityLevel);
FRIEND_TEST(DeviceCertificateStoreTest, StoreCertificate);
FRIEND_TEST(DeviceCertificateTest, ReadCertificate);
FRIEND_TEST(DeviceCertificateTest, HasCertificate);
FRIEND_TEST(DeviceFilesStoreTest, StoreLicense);
FRIEND_TEST(DeviceFilesHlsAttributesTest, Delete);
FRIEND_TEST(DeviceFilesHlsAttributesTest, Read);
FRIEND_TEST(DeviceFilesHlsAttributesTest, Store);
FRIEND_TEST(DeviceFilesTest, DeleteLicense);
FRIEND_TEST(DeviceFilesTest, ReserveLicenseIdsDoesNotUseFileSystem);
FRIEND_TEST(DeviceFilesTest, RetrieveLicenses);
FRIEND_TEST(DeviceFilesTest, AppParametersBackwardCompatibility);
FRIEND_TEST(DeviceFilesTest, SecurityLevelPathBackwardCompatibility);
FRIEND_TEST(DeviceFilesTest, StoreLicenses);
FRIEND_TEST(DeviceFilesTest, UpdateLicenseState);
FRIEND_TEST(DeviceFilesUsageInfoTest, Delete);
@@ -153,12 +154,10 @@ class DeviceFiles {
static std::set<std::string> reserved_license_ids_;
scoped_ptr<File> file_;
FileSystem* file_system_;
CdmSecurityLevel security_level_;
bool initialized_;
bool test_file_;
CORE_DISALLOW_COPY_AND_ASSIGN(DeviceFiles);
};

View File

@@ -15,39 +15,54 @@ namespace wvcdm {
// File class. The implementation is platform dependent.
class File {
public:
virtual ssize_t Read(char* buffer, size_t bytes);
virtual ssize_t Write(const char* buffer, size_t bytes);
virtual void Close();
protected:
class Impl;
File(Impl*);
virtual ~File();
private:
Impl* impl_;
friend class FileSystem;
CORE_DISALLOW_COPY_AND_ASSIGN(File);
};
class FileSystem {
public:
class Impl;
// defines as bit flag
enum OpenFlags {
kNoFlags = 0,
kBinary = 1,
kCreate = 2,
kReadOnly = 4, // defaults to read and write access
kTruncate = 8
kCreate = 1,
kReadOnly = 2, // defaults to read and write access
kTruncate = 4
};
File();
virtual ~File();
FileSystem();
FileSystem(const std::string& origin, void* extra_data);
virtual ~FileSystem();
virtual bool Open(const std::string& file_path, int flags);
virtual ssize_t Read(char* buffer, size_t bytes);
virtual ssize_t Write(const char* buffer, size_t bytes);
virtual void Close();
virtual File* Open(const std::string& file_path, int flags);
virtual bool Exists(const std::string& file_path);
virtual bool Remove(const std::string& file_path);
virtual bool Copy(const std::string& old_path, const std::string& new_path);
virtual bool List(const std::string& path, std::vector<std::string>* files);
virtual bool CreateDirectory(const std::string dir_path);
virtual bool IsDirectory(const std::string& dir_path);
virtual bool IsRegularFile(const std::string& file_path);
virtual ssize_t FileSize(const std::string& file_path);
const std::string& origin() const { return origin_; }
void SetOrigin(const std::string& origin);
private:
Impl* impl_;
std::string origin_;
CORE_DISALLOW_COPY_AND_ASSIGN(File);
CORE_DISALLOW_COPY_AND_ASSIGN(FileSystem);
};
} // namespace wvcdm

View File

@@ -16,24 +16,62 @@ class InitializationData {
InitializationData(const std::string& type = std::string(),
const CdmInitData& data = CdmInitData());
bool is_supported() const { return is_cenc_ || is_webm_; }
bool is_supported() const { return is_cenc_ || is_webm_ || is_hls_; }
bool is_cenc() const { return is_cenc_; }
bool is_hls() const { return is_hls_; }
bool is_webm() const { return is_webm_; }
bool IsEmpty() const { return data_.empty(); }
const std::string& type() const { return type_; }
const CdmInitData& data() const { return data_; }
std::vector<uint8_t> hls_iv() const { return hls_iv_; }
CdmHlsMethod hls_method() const { return hls_method_; }
private:
// Parse a blob of multiple concatenated PSSH atoms to extract the first
// Widevine PSSH.
bool ExtractWidevinePssh(const CdmInitData& init_data, CdmInitData* output);
bool ExtractHlsAttributes(const std::string& attribute_list,
CdmHlsMethod* method, std::vector<uint8_t>* iv,
std::string* uri);
static bool ConstructWidevineInitData(CdmHlsMethod method,
const std::string& uri,
CdmInitData* output);
static bool ExtractQuotedAttribute(const std::string& attribute_list,
const std::string& key,
std::string* value);
static bool ExtractHexAttribute(const std::string& attribute_list,
const std::string& key,
std::vector<uint8_t>* value);
static bool ExtractAttribute(const std::string& attribute_list,
const std::string& key, std::string* value);
static std::vector<std::string> ExtractKeyFormatVersions(
const std::string& key_format_versions);
// For testing only:
#if defined(UNIT_TEST)
FRIEND_TEST(HlsAttributeExtractionTest, ExtractAttribute);
FRIEND_TEST(HlsConstructionTest, InitData);
FRIEND_TEST(HlsInitDataConstructionTest, InvalidUriDataFormat);
FRIEND_TEST(HlsInitDataConstructionTest, InvalidUriBase64Encode);
FRIEND_TEST(HlsHexAttributeExtractionTest, ExtractHexAttribute);
FRIEND_TEST(HlsKeyFormatVersionsExtractionTest, ExtractKeyFormatVersions);
FRIEND_TEST(HlsParseTest, Parse);
FRIEND_TEST(HlsQuotedAttributeExtractionTest, ExtractQuotedAttribute);
FRIEND_TEST(HlsTest, ExtractHlsAttributes);
#endif
std::string type_;
CdmInitData data_;
bool is_cenc_;
bool is_hls_;
bool is_webm_;
std::vector<uint8_t> hls_iv_;
CdmHlsMethod hls_method_;
};
} // namespace wvcdm

View File

@@ -0,0 +1,139 @@
// Copyright 2016 Google Inc. All Rights Reserved.
#ifndef WVCDM_CORE_LICENSE_KEY_STATUS_H_
#define WVCDM_CORE_LICENSE_KEY_STATUS_H_
#include <map>
#include "crypto_session.h"
#include "license_protocol.pb.h"
#include "wv_cdm_types.h"
namespace wvcdm {
class LicenseKeyStatus;
// Holds all content and operator session keys for a session.
class LicenseKeys {
public:
LicenseKeys() {}
virtual ~LicenseKeys() { Clear(); }
virtual bool Empty() { return keys_.empty(); }
// Returns true if the key is a content key (not an operator session key)
virtual bool IsContentKey(const KeyId& key_id);
// Returns true if the key is currently usable for content decryption.
virtual bool CanDecryptContent(const KeyId& key_id);
// Returns the allowed usages for a key.
virtual bool GetAllowedUsage(const KeyId& key_id,
CdmKeyAllowedUsage* allowed_usage);
// Applies a new status to each content key.
// Returns true if any statuses changed, and sets new_usable_keys to
// true if the status changes resulted in keys becoming usable.
virtual bool ApplyStatusChange(CdmKeyStatus new_status,
bool* new_usable_keys);
// Populates the CdmKeyStatusMap with the current content keys.
virtual void ExtractKeyStatuses(CdmKeyStatusMap* content_keys);
// Determines whether the specified key can be used under the current
// resolution and/or hdcp constraints. If no constraints have been applied
// to the key, returns true.
virtual bool MeetsConstraints(const KeyId& key_id);
// Applies a resolution and/or hdcp change to each key, updating their
// useability under their constraints.
virtual void ApplyConstraints(uint32_t new_resolution,
CryptoSession::HdcpCapability new_hdcp_level);
// Extracts the keys from a license and makes them available for
// querying usage and constraint settings.
virtual void SetFromLicense(
const video_widevine_server::sdk::License& license);
private:
typedef ::video_widevine_server::sdk::License::KeyContainer KeyContainer;
typedef std::map<wvcdm::KeyId, LicenseKeyStatus*>::const_iterator
LicenseKeyStatusIterator;
void Clear();
bool is_initialized_;
std::map<KeyId, LicenseKeyStatus*> keys_;
CORE_DISALLOW_COPY_AND_ASSIGN(LicenseKeys);
};
// Holds the current license status of a key.
class LicenseKeyStatus {
friend class LicenseKeys;
public:
// Returns true if the key is a content key (not an operator session key)
virtual bool IsContentKey() { return is_content_key_; }
// Returns true if the key is currently usable for content decryption
virtual bool CanDecryptContent();
// Returns the usages allowed for this key.
virtual bool GetAllowedUsage(CdmKeyAllowedUsage* allowed_usage);
// Returns the current status of the key.
virtual CdmKeyStatus GetKeyStatus() const { return key_status_; }
// Applies a new status to this key.
// Returns true if the status changed, and sets new_usable_keys to
// true if the status changes resulted in the key becoming usable.
virtual bool ApplyStatusChange(CdmKeyStatus new_status,
bool* new_usable_keys);
// Returns the current constraint status of this key. The result
// may change due to calls to ApplyConstraints().
// Note: this will return true until the first call to ApplyConstraints().
virtual bool MeetsConstraints() const { return meets_constraints_; }
// Applies the given changes in resolution or HDCP settings.
virtual void ApplyConstraints(
uint32_t new_resolution, CryptoSession::HdcpCapability new_hdcp_level);
protected:
typedef ::video_widevine_server::sdk::License::KeyContainer KeyContainer;
typedef KeyContainer::OperatorSessionKeyPermissions
OperatorSessionKeyPermissions;
typedef KeyContainer::OutputProtection OutputProtection;
typedef KeyContainer::VideoResolutionConstraint VideoResolutionConstraint;
typedef ::google::protobuf::RepeatedPtrField<VideoResolutionConstraint>
ConstraintList;
LicenseKeyStatus(const KeyContainer& key);
virtual ~LicenseKeyStatus() {}
private:
void ParseContentKey(const KeyContainer& key);
void ParseOperatorSessionKey(const KeyContainer& key);
bool HasConstraints() {
return is_content_key_ && constraints_.size() != 0;
}
void SetConstraints(const ConstraintList& constraints);
bool is_content_key_;
CdmKeyStatus key_status_;
bool meets_constraints_;
CdmKeyAllowedUsage allowed_usage_;
CryptoSession::HdcpCapability default_hdcp_level_;
ConstraintList constraints_;
CORE_DISALLOW_COPY_AND_ASSIGN(LicenseKeyStatus);
};
} // namespace wvcdm
#endif // WVCDM_CORE_LICENSE_KEY_STATUS_H_

View File

@@ -1,105 +0,0 @@
// Copyright 2014 Google Inc. All Rights Reserved.
#ifndef WVCDM_CORE_MAX_RES_ENGINE_H_
#define WVCDM_CORE_MAX_RES_ENGINE_H_
#include <map>
#include "crypto_session.h"
#include "license_protocol.pb.h"
#include "lock.h"
#include "scoped_ptr.h"
#include "wv_cdm_types.h"
namespace wvcdm {
class Clock;
class MaxResEngineTest;
// Similar to the Policy Engine, this acts as an oracle that basically says
// "Yes(true) you may still decrypt or no(false) you may not decrypt this data
// anymore."
class MaxResEngine {
public:
explicit MaxResEngine(CryptoSession* crypto_session);
virtual ~MaxResEngine();
// The value returned is computed during the last call to SetLicense/
// SetResolution/OnTimerEvent and may be out of sync depending on the amount
// of time elapsed. The current decryption status is not calculated when this
// function is called to avoid overhead in the decryption path.
virtual bool CanDecrypt(const KeyId& key_id);
// SetLicense is used in handling the initial license response. It stores
// an exact copy of the key constraints from the license.
virtual void SetLicense(const video_widevine_server::sdk::License& license);
// SetResolution is called when the current output resolution is updated by
// the decoder. The max-res engine will recalculate the current resolution
// constraints, (if any) which may affect the results for CanDecrypt().
virtual void SetResolution(uint32_t width, uint32_t height);
// OnTimerEvent is called when a timer fires. The max-res engine may check the
// current HDCP level using the crypto session, which may affect the results
// for CanDecrypt().
virtual void OnTimerEvent();
private:
typedef ::video_widevine_server::sdk::License::KeyContainer KeyContainer;
typedef ::video_widevine_server::sdk::License::KeyContainer::OutputProtection
OutputProtection;
typedef ::video_widevine_server::sdk::License::KeyContainer::
VideoResolutionConstraint VideoResolutionConstraint;
typedef ::google::protobuf::RepeatedPtrField<VideoResolutionConstraint>
ConstraintList;
class KeyStatus {
public:
explicit KeyStatus(const ConstraintList& constraints);
KeyStatus(const ConstraintList& constraints,
const OutputProtection::HDCP& default_hdcp_level);
bool can_decrypt() const { return can_decrypt_; }
void Update(uint32_t res,
CryptoSession::HdcpCapability current_hdcp_level);
private:
void Init(const ConstraintList& constraints);
VideoResolutionConstraint* GetConstraintForRes(uint32_t res);
static CryptoSession::HdcpCapability ProtobufHdcpToOemCryptoHdcp(
const OutputProtection::HDCP& input);
bool can_decrypt_;
CryptoSession::HdcpCapability default_hdcp_level_;
ConstraintList constraints_;
};
typedef std::map<wvcdm::KeyId,
wvcdm::MaxResEngine::KeyStatus*>::const_iterator KeyIterator;
void Init(CryptoSession* crypto_session, Clock* clock);
void DeleteAllKeys();
Lock status_lock_;
std::map<KeyId, KeyStatus*> keys_;
uint32_t current_resolution_;
int64_t next_check_time_;
scoped_ptr<Clock> clock_;
CryptoSession* crypto_session_;
// For testing
friend class MaxResEngineTest;
MaxResEngine(CryptoSession* crypto_session, Clock* clock);
CORE_DISALLOW_COPY_AND_ASSIGN(MaxResEngine);
};
} // wvcdm
#endif // WVCDM_CORE_MAX_RES_ENGINE_H_

View File

@@ -34,6 +34,7 @@ OEMCryptoResult OEMCrypto_GetNumberOfOpenSessions(SecurityLevel level,
size_t* count);
OEMCryptoResult OEMCrypto_GetMaxNumberOfSessions(SecurityLevel level,
size_t* maximum);
uint8_t OEMCrypto_Security_Patch_Level(SecurityLevel level);
} // namespace wvcdm
#endif // WVCDM_CORE_OEMCRYPTO_ADAPTER_H_

View File

@@ -6,8 +6,8 @@
#include <map>
#include <string>
#include "license_key_status.h"
#include "license_protocol.pb.h"
#include "max_res_engine.h"
#include "scoped_ptr.h"
#include "wv_cdm_types.h"
@@ -67,7 +67,10 @@ class PolicyEngine {
virtual void NotifySessionExpiration();
virtual CdmResponseType Query(CdmQueryMap* key_info);
virtual CdmResponseType Query(CdmQueryMap* query_response);
virtual CdmResponseType QueryKeyAllowedUsage(const KeyId& key_id,
CdmKeyAllowedUsage* key_usage);
virtual const LicenseIdentification& license_id() { return license_id_; }
@@ -84,11 +87,20 @@ class PolicyEngine {
bool IsPlaybackStarted() { return playback_start_time_ > 0; }
bool IsLicenseOrPlaybackDurationExpired(int64_t current_time);
int64_t GetLicenseOrPlaybackDurationRemaining();
bool CanRenew() { return policy_.can_renew(); }
private:
friend class PolicyEngineTest;
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;
}
typedef enum {
kLicenseStateInitial,
@@ -119,9 +131,9 @@ class PolicyEngine {
// expiry time changes.
void NotifyExpirationUpdate();
// These setters are for testing only. Takes ownership of the pointers.
// set_clock() is for testing only. It alters ownership of the
// passed-in pointer.
void set_clock(Clock* clock);
void set_max_res_engine(MaxResEngine* max_res_engine);
LicenseState license_state_;
@@ -153,9 +165,14 @@ class PolicyEngine {
CdmSessionId session_id_;
WvCdmEventListener* event_listener_;
scoped_ptr<MaxResEngine> max_res_engine_;
// Keys associated with license - holds allowed usage, usage constraints,
// and current status (CdmKeyStatus)
scoped_ptr<LicenseKeys> license_keys_;
std::map<KeyId, CdmKeyStatus> keys_status_;
// Device checks
int64_t next_device_check_;
uint32_t current_resolution_;
CryptoSession* crypto_session_;
scoped_ptr<Clock> clock_;

View File

@@ -15,12 +15,13 @@ std::vector<uint8_t> a2b_hex(const std::string& label, const std::string& b);
std::string a2bs_hex(const std::string& b);
std::string b2a_hex(const std::vector<uint8_t>& b);
std::string b2a_hex(const std::string& b);
std::string Base64Encode(const std::vector<uint8_t>& bin_input);
std::vector<uint8_t> Base64Decode(const std::string& bin_input);
std::string Base64SafeEncode(const std::vector<uint8_t>& bin_input);
std::string Base64SafeEncodeNoPad(const std::vector<uint8_t>& bin_input);
std::vector<uint8_t> Base64SafeDecode(const std::string& bin_input);
std::string HexEncode(const uint8_t* bytes, unsigned size);
std::string IntToString(int value);
std::string UintToString(unsigned int value);
int64_t htonll64(int64_t x);
inline int64_t ntohll64(int64_t x) { return htonll64(x); }

View File

@@ -80,8 +80,19 @@ static const std::string ISO_BMFF_AUDIO_MIME_TYPE = "audio/mp4";
static const std::string WEBM_VIDEO_MIME_TYPE = "video/webm";
static const std::string WEBM_AUDIO_MIME_TYPE = "audio/webm";
static const std::string CENC_INIT_DATA_FORMAT = "cenc";
static const std::string HLS_INIT_DATA_FORMAT = "hls";
static const std::string WEBM_INIT_DATA_FORMAT = "webm";
static const std::string HLS_KEYFORMAT_ATTRIBUTE = "KEYFORMAT";
static const std::string HLS_KEYFORMAT_VERSIONS_ATTRIBUTE = "KEYFORMATVERSIONS";
static const std::string HLS_KEYFORMAT_VERSION_VALUE_1 = "1";
static const std::string HLS_METHOD_ATTRIBUTE = "METHOD";
static const std::string HLS_METHOD_AES_128 = "AES-128";
static const std::string HLS_METHOD_NONE = "NONE";
static const std::string HLS_METHOD_SAMPLE_AES = "SAMPLE-AES";
static const std::string HLS_IV_ATTRIBUTE = "IV";
static const std::string HLS_URI_ATTRIBUTE = "URI";
static const char EMPTY_ORIGIN[] = "";
} // namespace wvcdm

View File

@@ -149,9 +149,9 @@ enum CdmResponseType {
RENEW_KEY_ERROR_1,
RENEW_KEY_ERROR_2,
LICENSE_RENEWAL_SIGNING_ERROR,
RESTORE_OFFLINE_LICENSE_ERROR_1,
UNUSED_4, /* previously RESTORE_OFFLINE_LICENSE_ERROR_1 */
RESTORE_OFFLINE_LICENSE_ERROR_2,
SESSION_INIT_ERROR_1,
UNUSED_5, /* SESSION_INIT_ERROR_1 */
SESSION_INIT_ERROR_2,
SESSION_INIT_GET_KEYBOX_ERROR,
SESSION_NOT_FOUND_1,
@@ -169,7 +169,7 @@ enum CdmResponseType {
SIGNATURE_NOT_FOUND,
STORE_LICENSE_ERROR_1,
STORE_LICENSE_ERROR_2,
STORE_LICENSE_ERROR_3,
UNUSED_6, /* previously STORE_LICENSE_ERROR_3 */
STORE_USAGE_INFO_ERROR,
UNPROVISION_ERROR_1,
UNPROVISION_ERROR_2,
@@ -213,6 +213,38 @@ enum CdmResponseType {
SESSION_NOT_FOUND_11,
LOAD_USAGE_INFO_FILE_ERROR,
LOAD_USAGE_INFO_MISSING,
SESSION_FILE_HANDLE_INIT_ERROR,
INCORRECT_CRYPTO_MODE,
INVALID_PARAMETERS_ENG_5,
DECRYPT_ERROR,
INSUFFICIENT_OUTPUT_PROTECTION,
SESSION_NOT_FOUND_12,
KEY_NOT_FOUND_1,
KEY_NOT_FOUND_2,
KEY_CONFLICT_1,
INVALID_PARAMETERS_ENG_6,
INVALID_PARAMETERS_ENG_7,
INVALID_PARAMETERS_ENG_8,
INVALID_PARAMETERS_ENG_9,
INVALID_PARAMETERS_ENG_10,
INVALID_PARAMETERS_ENG_11,
INVALID_PARAMETERS_ENG_12,
SESSION_NOT_FOUND_13,
SESSION_NOT_FOUND_14,
SESSION_NOT_FOUND_15,
SESSION_NOT_FOUND_16,
KEY_NOT_FOUND_3,
KEY_NOT_FOUND_4,
KEY_NOT_FOUND_5,
KEY_NOT_FOUND_6,
KEY_ERROR_1,
KEY_ERROR_2,
KEY_ERROR_3,
KEY_ERROR_4,
INVALID_PARAMETERS_ENG_13,
INVALID_PARAMETERS_ENG_14,
INVALID_PARAMETERS_ENG_15,
INVALID_PARAMETERS_ENG_16,
};
enum CdmKeyStatus {
@@ -258,9 +290,89 @@ enum CdmCertificateType {
kCertificateX509,
};
enum CdmHlsMethod {
kHlsMethodNone,
kHlsMethodAes128,
kHlsMethodSampleAes,
};
enum CdmCipherMode {
kCipherModeCtr,
kCipherModeCbc,
};
enum CdmEncryptionAlgorithm {
kEncryptionAlgorithmUnknown,
kEncryptionAlgorithmAesCbc128
};
enum CdmSigningAlgorithm {
kSigningAlgorithmUnknown,
kSigningAlgorithmHmacSha256
};
class CdmKeyAllowedUsage {
public:
CdmKeyAllowedUsage() {
Clear();
}
bool Valid() const { return valid_; }
void SetValid() { valid_ = true; }
void Clear() {
decrypt_to_clear_buffer = false;
decrypt_to_secure_buffer = false;
generic_encrypt = false;
generic_decrypt = false;
generic_sign = false;
generic_verify = false;
valid_ = false;
}
bool Equals(const CdmKeyAllowedUsage& other) {
if (!valid_ || !other.Valid() ||
decrypt_to_clear_buffer != other.decrypt_to_clear_buffer ||
decrypt_to_secure_buffer != other.decrypt_to_secure_buffer ||
generic_encrypt != other.generic_encrypt ||
generic_decrypt != other.generic_decrypt ||
generic_sign != other.generic_sign ||
generic_verify != other.generic_verify) {
return false;
}
return true;
}
bool decrypt_to_clear_buffer;
bool decrypt_to_secure_buffer;
bool generic_encrypt;
bool generic_decrypt;
bool generic_sign;
bool generic_verify;
private:
bool valid_;
};
// For schemes that do not use pattern encryption (cenc and cbc1), encrypt
// and skip should be set to 0. For those that do (cens and cbcs), it is
// recommended that encrypt+skip bytes sum to 10 and for cbcs that a 1:9
// encrypt:skip ratio be used. See ISO/IEC DIS 23001-7, section 10.4.2 for
// more information.
struct CdmCencPatternEncryptionDescriptor {
size_t encrypt_blocks; // number of 16 byte blocks to decrypt
size_t skip_blocks; // number of 16 byte blocks to leave in clear
size_t offset_blocks; // offset into the pattern for this call, in blocks
CdmCencPatternEncryptionDescriptor()
: encrypt_blocks(0),
skip_blocks(0),
offset_blocks(0) {}
};
struct CdmDecryptionParameters {
bool is_encrypted;
bool is_secure;
CdmCipherMode cipher_mode;
const KeyId* key_id;
const uint8_t* encrypt_buffer;
size_t encrypt_length;
@@ -271,9 +383,11 @@ struct CdmDecryptionParameters {
size_t decrypt_buffer_offset;
uint8_t subsample_flags;
bool is_video;
CdmCencPatternEncryptionDescriptor pattern_descriptor;
CdmDecryptionParameters()
: is_encrypted(true),
is_secure(true),
cipher_mode(kCipherModeCtr),
key_id(NULL),
encrypt_buffer(NULL),
encrypt_length(0),
@@ -290,6 +404,7 @@ struct CdmDecryptionParameters {
size_t offset, void* decrypted_buffer)
: is_encrypted(true),
is_secure(true),
cipher_mode(kCipherModeCtr),
key_id(key),
encrypt_buffer(encrypted_buffer),
encrypt_length(encrypted_length),
@@ -302,6 +417,12 @@ struct CdmDecryptionParameters {
is_video(true) {}
};
struct CdmKeyRequest {
CdmKeyMessage message;
CdmKeyRequestType type;
std::string url;
};
// forward class references
class KeyMessage;
class Request;