diff --git a/example/wvpl_cas_proxy_environment_example b/example/wvpl_cas_proxy_environment_example index d75f24b..fb7149d 100644 Binary files a/example/wvpl_cas_proxy_environment_example and b/example/wvpl_cas_proxy_environment_example differ diff --git a/example/wvpl_cas_proxy_session_example b/example/wvpl_cas_proxy_session_example index 2d68df6..ee2a968 100644 Binary files a/example/wvpl_cas_proxy_session_example and b/example/wvpl_cas_proxy_session_example differ diff --git a/libwvpl_cas_proxy.so b/libwvpl_cas_proxy.so index cb48965..66e0ff6 100755 Binary files a/libwvpl_cas_proxy.so and b/libwvpl_cas_proxy.so differ diff --git a/media_cas_proxy_sdk/external/common/wvpl/wvpl_cas_proxy_environment.h b/media_cas_proxy_sdk/external/common/wvpl/wvpl_cas_proxy_environment.h index 982cdc7..e5a3437 100644 --- a/media_cas_proxy_sdk/external/common/wvpl/wvpl_cas_proxy_environment.h +++ b/media_cas_proxy_sdk/external/common/wvpl/wvpl_cas_proxy_environment.h @@ -76,6 +76,13 @@ class WvPLCASProxyEnvironment : public WvPLSDKEnvironment { virtual WvPLStatus CreateSession(const std::string& cas_license_request, WvPLCASProxySession** cas_proxy_session); + /** + * Deletes the session + * + * @param session + */ + virtual void DestroySession(WvPLCASProxySession* cas_proxy_session) const; + /** * Set the certificate status list system-wide. * |cert_list| specifies the device certificate status diff --git a/media_cas_proxy_sdk/external/common/wvpl/wvpl_cas_proxy_session.h b/media_cas_proxy_sdk/external/common/wvpl/wvpl_cas_proxy_session.h index 6043777..9fadd05 100644 --- a/media_cas_proxy_sdk/external/common/wvpl/wvpl_cas_proxy_session.h +++ b/media_cas_proxy_sdk/external/common/wvpl/wvpl_cas_proxy_session.h @@ -10,14 +10,17 @@ #define MEDIA_CAS_PROXY_SDK_EXTERNAL_COMMON_WVPL_WVPL_CAS_PROXY_SESSION_H_ #include +#include +#include "absl/synchronization/mutex.h" #include "sdk/external/common/wvpl/wvpl_sdk_session.h" +#include "protos/public/media_cas_license.pb.h" namespace widevine_server { namespace wv_pl_sdk { constexpr uint32_t kMajorVersion = 1; -constexpr uint32_t kMinorVersion = 0; -constexpr uint32_t kRelease = 1; +constexpr uint32_t kMinorVersion = 1; +constexpr uint32_t kRelease = 2; /** * Models a session for Widevine CAS Proxy functionality for @@ -68,6 +71,18 @@ class WvPLCASProxySession : public WvPLSDKSession { */ PlatformVerificationStatus VerifyPlatform() override; + /** + * Returns license request as a JSON string. This std::string is placed in + * |license_request|, if successful. Returns OK status upon success, else an + * error status. + */ + WvPLStatus GenerateLicenseRequestAsJSON(std::string* license_request); + + /** + * Adds a key to the WvPLCasKey collection. + */ + WvPLStatus AddCasKey(const WvPLCasKey& key); + private: friend class WvPLCASProxyEnvironment; friend class WvPLCASProxyEnvironmentTest; @@ -76,6 +91,20 @@ class WvPLCASProxySession : public WvPLSDKSession { WvPLCASProxySession( const widevine::DrmRootCertificate* drm_root_certificate, const std::string& cas_license_request_from_cdm); + + WvPLStatus BuildCasDrmLicenseRequest( + widevine::CasDrmLicenseRequest* cas_drm_license_request); + + void set_provider(const std::string& provider) { provider_ = provider; } + + // name of the provider hosting this service. + std::string provider_; + + // holds all the WvPLCasKey objects. Used when generating a CAS License. + std::vector cas_keys_ GUARDED_BY(cas_keys_mutex_); + + // Mutex to protect the keys owned by this session. + mutable absl::Mutex cas_keys_mutex_; }; } // namespace wv_pl_sdk diff --git a/protos/public/BUILD b/protos/public/BUILD index 2e4cd6f..f40aad1 100644 --- a/protos/public/BUILD +++ b/protos/public/BUILD @@ -33,6 +33,8 @@ proto_library( "verified_media_pipeline.proto", "widevine_pssh.proto", "license_services.proto", + "media_cas_encryption.proto", + "media_cas_license.proto", ], ) @@ -241,3 +243,29 @@ java_proto_library( name = "widevine_pssh_java_proto", deps = [":widevine_pssh_proto_base"], ) + +proto_library( + name = "media_cas_license_proto_base", + srcs = ["media_cas_license.proto"], + deps = [ + ":license_protocol_proto_base", + ":license_server_sdk_proto_base", + ":errors_proto_base", + ":media_cas_encryption_proto_base", + ], +) + +cc_proto_library( + name = "media_cas_license_proto", + deps = [":media_cas_license_proto_base"], +) + +proto_library( + name = "media_cas_encryption_proto_base", + srcs = ["media_cas_encryption.proto"], +) + +cc_proto_library( + name = "media_cas_encryption_proto", + deps = [":media_cas_encryption_proto_base"], +) diff --git a/protos/public/errors.proto b/protos/public/errors.proto index cb3c10b..ef7c511 100644 --- a/protos/public/errors.proto +++ b/protos/public/errors.proto @@ -239,4 +239,10 @@ enum Errors { // Invalid method parameter. INVALID_PARAMETER = 170; + // Even KeyID not specified, CasEncryptionResponse.KeyInfo.KeySlot + MISSING_EVEN_KEY_ID = 171; + + // Even Key not specified, CasEncryptionResponse.KeyInfo.KeySlot + MISSING_EVEN_KEY = 172; + } diff --git a/protos/public/media_cas_encryption.proto b/protos/public/media_cas_encryption.proto new file mode 100644 index 0000000..81d0195 --- /dev/null +++ b/protos/public/media_cas_encryption.proto @@ -0,0 +1,74 @@ +//////////////////////////////////////////////////////////////////////////////// +// 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. +//////////////////////////////////////////////////////////////////////////////// + +// Protocol buffer definitions for Widevine CAS. + +syntax = "proto2"; + +option java_package = "com.google.video.widevine.mediacasencryption"; + +package widevine; + +message CasEncryptionRequest { + optional bytes content_id = 1; + optional string provider = 2; + // Optional track types such as "AUDIO", SD" or "HD". + repeated string track_types = 3; + // Indicates if the client is using key rotation. If true, the server will + // return one key for EVEN and one key for ODD, otherwise only a single key is + // returned. + optional bool key_rotation = 4; +} + +message CasEncryptionResponse { + enum Status { + STATUS_UNSPECIFIED = 0; + OK = 1; + SIGNATURE_FAILED = 2; + ACCESS_DENIED = 3; + INTERNAL_ERROR = 4; + INVALID_ARGUMENT = 5; + PROVIDER_ID_MISSING = 6; + CONTENT_ID_MISSING = 7; + TRACK_TYPE_MISSING = 8; + } + message KeyInfo { + enum KeySlot { + KEY_SLOT_UNSPECIFIED = 0; + SINGLE = 1; + EVEN = 2; + ODD = 3; + }; + optional bytes key_id = 1; + optional bytes key = 2; + // Optional label used for the key. + optional string track_type = 3; + optional KeySlot key_slot = 4; + } + optional Status status = 1; + optional string status_message = 2; + optional bytes content_id = 3; + repeated KeyInfo entitlement_keys = 4; +} + +message SignedCasEncryptionRequest { + optional bytes request = 1; + optional bytes signature = 2; + // Identifies the entity sending / signing the request. + optional string signer = 3; +} + +message SignedCasEncryptionResponse { + // Serialized CasEncryptionResponse message. + optional bytes response = 1; + optional bytes signature = 2; +} + +message HttpResponse { + optional bytes response = 1; +} diff --git a/protos/public/media_cas_license.proto b/protos/public/media_cas_license.proto new file mode 100644 index 0000000..42f2c91 --- /dev/null +++ b/protos/public/media_cas_license.proto @@ -0,0 +1,110 @@ +//////////////////////////////////////////////////////////////////////////////// +// 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. +//////////////////////////////////////////////////////////////////////////////// +// +// Description: +// Definitions of the protocol buffer messages used in the Widevine license +// exchange protocol for Media CAS. + +syntax = "proto2"; + +option java_package = "com.google.video.widevine.mediacaslicense"; + +import "protos/public/license_protocol.proto"; +import "protos/public/license_server_sdk.proto"; +import "protos/public/media_cas_encryption.proto"; + +package widevine; + +message CasDrmLicenseRequest { + // The request payload. This is usually the HTTP Post body of a request. + // Required. + optional bytes payload = 1; + // The content provider whose proxy is sending this license request onto the + // Widevine license service. Required. + optional string provider_id = 2; + // An identifier supplied by a content provider, used to identify a piece of + // content and derive key IDs and content keys. + optional bytes content_id = 3; + // A ContentKeySpec identifies a content key by track type name. It also + // specifies the policy that should be used for this key. + // TODO(user): Consolidate this ContentKeySpec with + // ModularDrmLicenseRequest_ContentKeySpec. Both should include a common + // ContentKeySpec. + message ContentKeySpec { + optional License.KeyContainer.SecurityLevel security_level = 1; + optional License.KeyContainer.OutputProtection required_output_protection = + 2; + optional License.KeyContainer.OutputProtection requested_output_protection = + 3; + // Optionally specify even, odd or single slot for key rotation. + repeated CasEncryptionResponse.KeyInfo entitlement_keys = 4; + optional License.KeyContainer.KeyType key_type = 5; + } + repeated ContentKeySpec content_key_specs = 4; + // Policy for the entire license such as playback duration. + optional License.Policy policy = 5; +} + +message CasDrmLicenseResponse { + enum Status { + UNKNOWN = 0; + OK = 1; + SIGNATURE_FAILED = 2; + INVALID_LICENSE_CHALLENGE = 3; + PROVIDER_ID_MISSING = 4; + INVALID_CONTENT_INFO = 5; + EMPTY_CONTENT_INFO = 6; + CONTENT_ID_MISMATCH = 7; + MISSING_CONTENT_ID = 8; + MALFORMED_REQUEST = 9; + INTERNAL_ERROR = 10; + } + optional Status status = 1; + optional string status_message = 2; + // Serialzed bytes for a CAS license. + // TODO(user): Until a CAS license protocol is defined, this field is a + // serialized License message defined in license_protocol.proto. + optional bytes license = 3; + // Actual SDK license status as defined in widevine/server/sdk/error.proto. + optional uint32 internal_status = 4; + // Indicates the type of message in the license response. + optional SignedMessage.MessageType message_type = 5; + // A subset of data from the Widevine PSSH. + message PsshData { + repeated bytes key_id = 1; + optional bytes content_id = 2; + } + message LicenseMetadata { + optional bytes content_id = 1; + repeated bytes key_id = 2; + } + optional PsshData pssh_data = 6; + optional SessionState session_state = 7; + optional string content_owner = 8; + optional string content_provider = 9; + optional LicenseMetadata license_metadata = 10; +} + +message SignedCasDrmRequest { + optional bytes request = 1; + optional bytes signature = 2; + // Identifies the entity sending / signing the request. Required if signature + // is present. + optional string signer = 3; + // The IP Address of the portal that is forwarding the request from the + // original sender. + optional string client_ip_address = 4; + // The client software identifier, as used by HTTP. + optional string user_agent = 5; + optional string provider = 6; +} + +message SignedCasDrmResponse { + optional bytes response = 1; + optional bytes signature = 2; +} diff --git a/sdk/external/common/wvpl/wvpl_sdk_session.h b/sdk/external/common/wvpl/wvpl_sdk_session.h index 9d6c54b..9efe421 100644 --- a/sdk/external/common/wvpl/wvpl_sdk_session.h +++ b/sdk/external/common/wvpl/wvpl_sdk_session.h @@ -99,12 +99,14 @@ class WvPLSDKSession { * Returns the type of the message handled by this session. * * @return MessageType enumeration. + * @deprecated use request_type instead. + * @since end of Q1, 2019 */ virtual MessageType message_type() const; virtual PlatformVerificationStatus VerifyPlatform() = 0; - virtual LicenseRequestType request_type() const { return request_type_; } + virtual WvPLRequestType request_type() const { return type_; } /** * Returns true if the license type is offline, otherwise return false. @@ -164,7 +166,7 @@ class WvPLSDKSession { std::string license_request_from_cdm_; std::string remote_attestation_cert_serial_number_; std::unique_ptr sdk_license_request_; - LicenseRequestType request_type_; + WvPLRequestType type_; bool has_session_state_ = false; bool has_encrypted_client_id_ = false; @@ -244,6 +246,8 @@ class WvPLSDKSession { uint32_t system_id, widevine::ProvisionedDeviceInfo* provisioned_device_info) const; + virtual const std::string TrackTypeToString(TrackType track_type) const; + private: std::unique_ptr system_id_; }; diff --git a/sdk/external/common/wvpl/wvpl_types.h b/sdk/external/common/wvpl/wvpl_types.h index 5b0369a..084afbb 100644 --- a/sdk/external/common/wvpl/wvpl_types.h +++ b/sdk/external/common/wvpl/wvpl_types.h @@ -1015,12 +1015,13 @@ struct WvPLCasKey { TrackType track_type() const { return track_type_; } - void set_output_protection(const WvPLOutputProtection& out_prot) { - output_protection_ = out_prot; + void set_output_protection(const WvPLOutputProtection& output_protection) { + output_protection_ = output_protection; } - void set_requested_output_protection(const WvPLOutputProtection& out_prot) { - requested_output_protection_ = out_prot; + void set_requested_output_protection( + const WvPLOutputProtection& output_protection) { + requested_output_protection_ = output_protection; } const WvPLOutputProtection& output_protection() const {