// Copyright 2018 Google LLC. All Rights Reserved. This file and proprietary // source code may only be used and distributed under the Widevine Master // License Agreement. #ifndef WIDEVINE_CAS_LICENSE_KEY_STATUS_H_ #define WIDEVINE_CAS_LICENSE_KEY_STATUS_H_ #include #include "crypto_session.h" #include "license_protocol.pb.h" namespace wvcas { class LicenseKeyStatus; using video_widevine::WidevinePsshData_EntitledKey; // Policy engine HDCP enforcement static constexpr uint32_t HDCP_UNSPECIFIED_VIDEO_RESOLUTION = 0; static constexpr int64_t HDCP_DEVICE_CHECK_INTERVAL = 10; enum KeySecurityLevel { kKeySecurityLevelUnset, kSoftwareSecureCrypto, kSoftwareSecureDecode, kHardwareSecureCrypto, kHardwareSecureDecode, kHardwareSecureAll, kKeySecurityLevelUnknown, }; class KeyAllowedUsage { public: KeyAllowedUsage() { 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; key_security_level_ = kKeySecurityLevelUnset; valid_ = false; } bool Equals(const KeyAllowedUsage& 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 || key_security_level_ != other.key_security_level_) { 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; KeySecurityLevel key_security_level_; private: bool valid_; }; // Holds all content and operator session keys for a session. class LicenseKeys { public: LicenseKeys() {} virtual ~LicenseKeys() { Clear(); } virtual bool Empty() { return key_statuses_.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, KeyAllowedUsage* 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(KeyStatus new_status, bool* new_usable_keys); // Returns current KeyStatus for the given key. // Returns kKeyStatusKeyUnknown if key_id not found. virtual KeyStatus GetKeyStatus(const KeyId& key_id); // Populates a KeyStatusMap with the current content keys. virtual void ExtractKeyStatuses(KeyStatusMap* 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, 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::License& license); // Sets the keys from the input entitled key data. virtual void SetEntitledKeys( const std::vector& keys); LicenseKeys(const LicenseKeys&) = delete; LicenseKeys& operator=(const LicenseKeys&) = delete; private: typedef ::video_widevine::License::KeyContainer KeyContainer; typedef std::map::const_iterator LicenseKeyStatusIterator; void Clear(); bool is_initialized_; // |key_statuses_| can hold either content key statuses, or entitlement key // statuses. std::map key_statuses_; // |content_keyid_to_entitlement_key_id_| maps a content key id to an // entitlement_key_id. The resulting key id can be used to obtain the current // key status from |key_statuses_| when using entitlement key licensing. std::map content_keyid_to_entitlement_key_id_; }; // 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(KeyAllowedUsage* allowed_usage); // Returns the current status of the key. virtual KeyStatus 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(KeyStatus 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, HdcpCapability new_hdcp_level); LicenseKeyStatus(const LicenseKeyStatus&) = delete; LicenseKeyStatus& operator=(const LicenseKeyStatus&) = delete; protected: typedef ::video_widevine::License::KeyContainer KeyContainer; typedef KeyContainer::OperatorSessionKeyPermissions OperatorSessionKeyPermissions; typedef KeyContainer::OutputProtection OutputProtection; typedef KeyContainer::VideoResolutionConstraint VideoResolutionConstraint; typedef ::google::protobuf::RepeatedPtrField 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_; KeyStatus key_status_; bool meets_constraints_; KeyAllowedUsage allowed_usage_; HdcpCapability default_hdcp_level_; ConstraintList constraints_; }; } // namespace wvcas #endif // WIDEVINE_CAS_LICENSE_KEY_STATUS_H_