// Copyright 2025 Google LLC. All Rights Reserved. This file and proprietary // source code may only be used and distributed under the Widevine License // Agreement. #ifndef WVCDM_UTIL_HLS_KEY_H_ #define WVCDM_UTIL_HLS_KEY_H_ #include #include #include #include #include #include "wv_class_utils.h" namespace wvutil { class HlsAttributeList; // Data wrapper types for HLS Key fields. // // Ensures that the values of each attribute of an // HLS key is valid. The class does not enforce contextual // requirements between attributes; however, IsWellFormed() // can optionally be called to ensure some fields are set // appropriately based on the values of other fields. // // This class is based on RFC 8216 section 4.3.2.4. class HlsKey { public: // HLS Tag for key data. static constexpr char kTag[] = "EXT-X-KEY"; // Attribute names for HLS keys. // METHOD is an enumerated string with three known values // of NONE, AES-128, or SAMPLE-AES. // METHOD may be a different value so long as it is a // valid enum string. // METHOD is required, if set to NONE, then the other // fields SHOULD NOT be set. static constexpr char kMethodName[] = "METHOD"; // URI is a quoted string containing be a valid URI which // identifies where to find the key(s) used for content // decryption. // Must be set if METHOD is not NONE. // Should not be set if METHOD is NONE. static constexpr char kUriName[] = "URI"; // IV is a hex sequence for a 128-bit initialization vector // used for decryption of media content. // Must be set if METHOD is not NONE. // Should not be set if METHOD is NONE. static constexpr char kIvName[] = "IV"; // The key format is a quoted string which identifies the // format of the key acquired by the URI. // Optionally set if METHOD is not NONE, if not set, then // it is assumed the URI will directly acquire the key. // Should not be set if METHOD is NONE. static constexpr char kKeyFormatName[] = "KEYFORMAT"; // The key format versions is a quoted string containing one // or more positive integers (of HLS integer format) separated // by a '/', which indicates the vendor-specific versions of the // key acquired via the URI. // Optionally set if METHOD is not NONE, assumed to contain // a value of 1 if not set but a version is required. // Should not be set if METHOD is NONE. static constexpr char kKeyFormatVersionsName[] = "KEYFORMATVERSIONS"; // List of known METHOD values. static constexpr char kMethodNone[] = "NONE"; static constexpr char kMethodAes128[] = "AES-128"; static constexpr char kMethodSampleAes[] = "SAMPLE-AES"; // HLS keys require an IV length of 128-bits / 16 octets. static constexpr size_t kIvLength = 16; // Checks if the provided |method| is one of the known // values for the enumerated string METHOD. static bool IsKnownMethod(const std::string& method); // Checks if the provided |method| is a valid HLS enum // string value. static bool IsValidMethod(const std::string& method); // Simply checks that the provided URI is a valid HLS quoted // string value. Does not valid URI format. static bool IsValidUriValue(const std::string& uri); // Checks that the specified IV length (in octets) is a supported // length. static constexpr bool IsValidIvLength(size_t iv_length) { return iv_length == kIvLength; } static bool IsValidIv(const std::string& iv) { return IsValidIvLength(iv.size()); } static bool IsValidIv(const std::vector& iv) { return IsValidIvLength(iv.size()); } // Checks that the provided key format conforms to the quoted // string value requirements of HLS. static bool IsValidKeyFormat(const std::string& key_format); // Checks if the specified |version| is a valid key format // version (must be positive). static constexpr bool IsValidKeyFormatVersion(uint64_t version) { return version > 0; } // Checks that all the values in the set of |versions| is a valid // versions. // The set of versions cannot be empty, and all versions must be a // positive value. static bool IsValidKeyFormatVersions(const std::set& versions); // Checks that the provided formatted version list is a valid // representation of key format versions. // Note: There is no requirement that the versions are unique. static bool IsValidKeyFormatVersionListRep( const std::string& version_list_rep); HlsKey() = default; WVCDM_DEFAULT_COPY_AND_MOVE(HlsKey); const std::string& method() const { return method_; } bool HasMethod() const { return !method_.empty(); } bool SetMethod(const std::string& method); void ClearMethod() { method_.clear(); } // URIs are only validated that they are valid quoted string // values; not that they are well formed URIs. const std::string& uri() const { return uri_; } bool HasUri() const { return !uri_.empty(); } bool SetUri(const std::string& uri); void ClearUri() { uri_.clear(); } const std::vector& iv() const { return iv_; } bool HasIv() const { return !iv_.empty(); } bool SetIv(const std::vector& iv); bool SetIv(const std::string& iv); bool SetIvHex(const std::string& iv_hex); void ClearIv() { iv_.clear(); } const std::string& key_format() const { return key_format_; } bool HasKeyFormat() const { return !key_format_.empty(); } bool SetKeyFormat(const std::string& key_format); void ClearKeyFormat() { key_format_.clear(); } const std::set& key_format_versions() const { return key_format_versions_; } bool HasKeyFormatVersions() const { return !key_format_versions_.empty(); } bool HasKeyFormatVersion(uint64_t version) const; bool SetKeyFormatVersions(const std::set& versions); bool SetKeyFormatVersions(const std::vector& versions); bool AddKeyFormatVersion(uint64_t version); void ClearKeyFormatVersions() { key_format_versions_.clear(); } void Clear() { ClearMethod(); ClearUri(); ClearIv(); ClearKeyFormat(); ClearKeyFormatVersions(); } // Checks that the HLS key is well-formed based on the requirements // of an HLS key. Relies mainly on the requirements of METHOD. bool IsWellFormed() const; // == Parsing / Serialization == // Initializes the HLS key from a populated instance of // HlsAttributeList. // // Requirements: // - METHOD must be set, must be one of the well-known methods. // - URI is optional, must be quoted string if set. // - IV is optional, must be a 16-byte / 128-bit hex sequence if set. // - KEYFORMAT is optional, must be a quoted string if set, defaults // to "identify" is not set. // - KEYFORMATVERSIONS is optional, must be a quoted string containing // a valid sequence of '/' separated version if set, defaults to // "1" if not set. bool FromAttributeList(const HlsAttributeList& attr_list); // Initializes the HLS key from the HLS serialized HLS Attribute List. // Internally uses FromAttributeList(), and follows the same requirements. bool ParseAttributeList(const std::string& attr_list_rep); // Packages the HLS key into the HlsAttributeList instance. // Clears existing data in |attr_list|. // // Serializing does not enforce any field requirements other than // types. // // Follows the following rules: // - METHOD packaged as enum string if set // - URI packaged as quoted string if set // - IV packaged as hex sequence if set // - KEYFORMAT packaged as quoted string if set // - KEYFORMATVERSIONS packaged as quoted string containing slash // separated version if any version is set. bool ToAttributeList(HlsAttributeList* attr_list) const; // Serializes the HLS key into an HLS attribute string format. // Internally uses ToAttributeList(), and follows the same packaging // rules. std::string Serialize() const; bool SerializeToStream(std::ostream* out) const; private: // Values are either empty or set to valid values. std::string method_; std::string uri_; std::vector iv_; std::string key_format_; std::set key_format_versions_; }; // class HlsKey } // namespace wvutil #endif // WVCDM_UTIL_HLS_KEY_H_