diff --git a/example/wv_cas_ecm_example b/example/wv_cas_ecm_example index 4dc6517..279d8c6 100644 Binary files a/example/wv_cas_ecm_example and b/example/wv_cas_ecm_example differ diff --git a/libmedia_cas_packager_sdk.so b/libmedia_cas_packager_sdk.so index bd00d2f..f8e4cb8 100755 Binary files a/libmedia_cas_packager_sdk.so and b/libmedia_cas_packager_sdk.so differ diff --git a/media_cas_packager_sdk/public/wv_cas_ecm.h b/media_cas_packager_sdk/public/wv_cas_ecm.h index 14bce9d..d85623c 100644 --- a/media_cas_packager_sdk/public/wv_cas_ecm.h +++ b/media_cas_packager_sdk/public/wv_cas_ecm.h @@ -9,7 +9,7 @@ #ifndef MEDIA_CAS_PACKAGER_SDK_PUBLIC_WV_CAS_ECM_H_ #define MEDIA_CAS_PACKAGER_SDK_PUBLIC_WV_CAS_ECM_H_ -#include +#include #include #include #include @@ -111,6 +111,29 @@ class WvCasEcm { const char* const even_entitlement_key_id, const char* const even_entitlement_key, std::string* ecm) const; + // Generate a TS packet with the given |ecm| as payload. + // + // Args (all pointer parameters must be not nullptr): + // - |ecm| serialized ECM, e.g., generated by GenerateEcm() method above + // - |pid| program ID for the ECM stream + // - |table_id| is the table ID byte put in the section header, it should be + // either 0x80 or 0x81. Changing table ID from 0x80 or 0x81 or + // 0x81 to 0x80 is used to singal to the client that the key contained + // in the ECM has changed. In other words, if you are building an ECM + // with a new key that was not in any previous ECM, you should flip the + // table ID so the client knows this is an important ECM it should process. + // - |continuity_counter| continuity_counter for the ECM packet, + // it will be incremented, only last 4 bits are used + // - |packet| a buffer of size at least 188 bytes to be used to return + // the generated TS packet + // + // Returns: + // - A status indicating whether there was any error during processing + virtual WvCasStatus GenerateTsPacket(const std::string& ecm, uint16_t pid, + uint8_t table_id, + uint8_t* continuity_counter, + uint8_t* packet); + private: bool initialized_ = false; int content_iv_size_; diff --git a/media_cas_packager_sdk/public/wv_cas_key_fetcher.h b/media_cas_packager_sdk/public/wv_cas_key_fetcher.h new file mode 100644 index 0000000..03eddec --- /dev/null +++ b/media_cas_packager_sdk/public/wv_cas_key_fetcher.h @@ -0,0 +1,58 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright 2018 Google LLC. +// +// This software is licensed under the terms defined in the Widevine Master +// License Agreement. For a copy of this agreement, please contact +// widevine-licensing@google.com. +//////////////////////////////////////////////////////////////////////////////// + +#ifndef MEDIA_CAS_PACKAGER_SDK_PUBLIC_WV_CAS_KEY_FETCHER_H_ +#define MEDIA_CAS_PACKAGER_SDK_PUBLIC_WV_CAS_KEY_FETCHER_H_ + +#include + +#include "gflags/gflags.h" +#include "common/status.h" +#include "media_cas_packager_sdk/internal/key_fetcher.h" + +DECLARE_string(license_server); +DECLARE_string(signing_provider); +DECLARE_string(signing_key); +DECLARE_string(signing_iv); + +namespace widevine { +namespace cas { + +// WV CAS KeyFetcher. Performs the communication with the Widevine License +// Server to get entitlement keys on behalf of a WvCasEcm object. +class WvCasKeyFetcher : public KeyFetcher { + public: + WvCasKeyFetcher() = default; + WvCasKeyFetcher(const WvCasKeyFetcher&) = delete; + WvCasKeyFetcher& operator=(const WvCasKeyFetcher&) = delete; + virtual ~WvCasKeyFetcher() = default; + + // Get entitlement keys from the license server. Send a + // SignedCasEncryptionRequest message to the license server, receive a + // SignedCasEncryptionResponse and return it to the caller. + // Args: + // |request_string| a serialized CasEncryptionRequest message, produced + // by WvCasEcm::Initialize(). + // |signed_response_string| a serialized SignedCasEncryptionResponse + // message. It should be passed into + // widevine::cas::Ecm::ProcessCasEncryptionResponse(). + virtual util::Status RequestEntitlementKey(const std::string& request_string, + std::string* signed_response_string); + + protected: + // Makes a HTTP request to License Server for entitlement key(s). + // Returns the HTTP response in Json format in |http_response_json|. + // Protected visibility to support unit testing. + virtual util::Status MakeHttpRequest(const std::string& signed_request_json, + std::string* http_response_json) const; +}; + +} // namespace cas +} // namespace widevine + +#endif // MEDIA_CAS_PACKAGER_SDK_PUBLIC_WV_CAS_KEY_FETCHER_H_ diff --git a/media_cas_packager_sdk/public/wv_cas_types.h b/media_cas_packager_sdk/public/wv_cas_types.h index 64024e2..3acd30e 100644 --- a/media_cas_packager_sdk/public/wv_cas_types.h +++ b/media_cas_packager_sdk/public/wv_cas_types.h @@ -50,17 +50,19 @@ enum WvCasStatus { // Returns the message std::string for the given WvCasStatus. std::string GetWvCasStatusMessage(WvCasStatus status); -// Crypto mode for encryption / decryption. +// Crypto mode for encryption / decryption. ENUM value should be consistent with +// https://docs.google.com/document/d/1A5vflf8tbKyUheV-xsvfxFqB6YyNLNdsGXYx8ZnhjfY/edit#heading=h.ej4ts3lifoio enum class CryptoMode : int { - kCryptoModeUnspecified = 0, + kAesCbc = 0, kAesCtr = 1, - kAesCbc = 2, - kDvbCsa2 = 3 + kDvbCsa2 = 2, }; -std::string CryptoModeToString(CryptoMode mode); +// Returns false if mode is not a valid CryptoMode. +bool CryptoModeToString(CryptoMode mode, std::string* str); -CryptoMode StringToCryptoMode(std::string str); +// Returns false if str is not a valid CryptoMode. +bool StringToCryptoMode(const std::string& str, CryptoMode* mode); } // namespace cas } // namespace widevine diff --git a/util/error_space.h b/util/error_space.h index 68c093a..2e66a39 100644 --- a/util/error_space.h +++ b/util/error_space.h @@ -49,11 +49,11 @@ class ErrorSpaceImpl : public ErrorSpace { // pointer to stateless static methods, so that clients of ErrorSpaceImpl are // safe to have constexpr global instances. static std::string SpaceNameImpl(const ErrorSpace* /*space*/) { - return T::SpaceName(); + return T::space_name(); } static std::string CodeToStringImpl(const ErrorSpace* /*space*/, int code) { - return T::CodeToString(code); + return T::code_to_string(code); } }; diff --git a/util/status.h b/util/status.h deleted file mode 100644 index 5e3b15b..0000000 --- a/util/status.h +++ /dev/null @@ -1,119 +0,0 @@ -//////////////////////////////////////////////////////////////////////////////// -// Copyright 2017 Google LLC. -// -// This software is licensed under the terms defined in the Widevine Master -// License Agreement. For a copy of this agreement, please contact -// widevine-licensing@google.com. -//////////////////////////////////////////////////////////////////////////////// - -#ifndef UTIL_STATUS_H_ -#define UTIL_STATUS_H_ - -#include - -#include "util/error_space.h" - -namespace widevine { -namespace util { -namespace error { - -enum StatusCode { - // Success. - OK = 0, - - // Client specified an invalid argument. - INVALID_ARGUMENT = 3, - - // Some requested entity (e.g., file or directory) was not found. - NOT_FOUND = 5, - - // Some entity that we attempted to create (e.g., file or directory) - // already exists. - ALREADY_EXISTS = 6, - - // The caller does not have permission to execute the specified - // operation. PERMISSION_DENIED must not be used for rejections - // caused by exhausting some resource (use RESOURCE_EXHAUSTED - // instead for those errors). - PERMISSION_DENIED = 7, - - // Operation is not implemented or not supported/enabled in this service. - UNIMPLEMENTED = 12, - - // Internal errors. Means some invariants expected by underlying - // system has been broken. If you see one of these errors, - // something is very broken. - INTERNAL = 13, - - // Operation is not implemented or not supported/enabled in this service. - UNAVAILABLE = 14, - - // Number of generic (non license related) errors. - NUM_ERRORS, -}; - -} // namespace error - -class GenericErrorSpace : public ErrorSpaceImpl { - public: - static std::string SpaceName(); - static std::string CodeToString(int code); -}; - -class Status { - public: - Status() : status_code_(error::OK) {} - ~Status() {} - explicit Status(error::StatusCode c) : status_code_(c) {} - Status(error::StatusCode c, const std::string& error_message) - : status_code_(c), error_message_(error_message) {} - Status(const ErrorSpace* e, error::StatusCode c, - const std::string& error_message) { - SetError(e, c, error_message); - } - Status(const ErrorSpace* e, int error, const std::string& error_message) { - SetError(e, error, error_message); - } - void SetError(const ErrorSpace* e, int c, const std::string& error_message) { - error_space_ = e; - status_code_ = c; - error_message_ = error_message; - } - - bool ok() const { return status_code_ == error::OK; } - const ErrorSpace* error_space() const { return error_space_; } - static const ErrorSpace* canonical_space() { - return GenericErrorSpace::Get(); - } - std::string ToString() const; - std::string error_message() const { return error_message_; } - int error_code() const { return status_code_; } - - private: - const ErrorSpace* error_space_ = GenericErrorSpace::Get(); - int status_code_; - std::string error_message_; -}; // class Status - -inline Status OkStatus() { return Status(); } - -// Here error_message_ is ignored during comparison. -inline bool operator==(const Status& s1, const Status& s2) { - return s1.error_space() == s2.error_space() && - s1.error_code() == s2.error_code(); -} -inline bool operator!=(const Status& s1, const Status& s2) { - return s1.error_space() != s2.error_space() || - s1.error_code() != s2.error_code(); -} - -// Prints a human-readable representation of 'x' to 'os'. -std::ostream& operator<<(std::ostream& os, const Status& x); - -#define CHECK_OK(expression) CHECK_EQ(util::error::OK, expression.error_code()) - - -} // namespace util -} // namespace widevine - -#endif // UTIL_STATUS_H_