Regular update
Plugin: 1. Process ECM v3 and send fingerprinting/service_blocking events 2. Rmove unused function Ctr128Add 3. Add support for ECM v3 OEMCrypto: 1. Update API description of OEMCrypto_LoadCasECMKeys 2. Fix android build files for ODK 3. Load content keys to shared memory 4. Move KCB check to LoadCasKeys call 5. Support even/odd content keys to share entitlement key
This commit is contained in:
@@ -11,6 +11,8 @@
|
||||
#define CAS_QUERY_EVENT_START 4000
|
||||
#define CAS_ERROR_EVENT_START 5000
|
||||
#define CAS_PARENTAL_CONTROL_EVENT_START 6000
|
||||
#define CAS_FINGERPRINTING_EVENT_START 6100
|
||||
#define CAS_SERVICE_BLOCKING_EVENT_START 6200
|
||||
#define CAS_TEST_EVENT_START 10000
|
||||
|
||||
typedef enum {
|
||||
@@ -48,9 +50,41 @@ typedef enum {
|
||||
ACCESS_DENIED_BY_PARENTAL_CONTROL,
|
||||
AGE_RESTRICTION_UPDATED,
|
||||
|
||||
// The content of FINGERPRINTING_INFO events follows TLV (Type (1 byte) -
|
||||
// Length (2 bytes) - Value) format. See FingerprintingFieldType for possible
|
||||
// types. A FINGERPRINTING_INFO event contains {one or more CHANNEL, one
|
||||
// CONTROL}.
|
||||
FINGERPRINTING_INFO = CAS_FINGERPRINTING_EVENT_START,
|
||||
// Fingerprinting control info for a session. The content of the event follows
|
||||
// TLV (Type (1 byte) - Length (2 bytes) - Value) format. See
|
||||
// SessionFingerprintingFieldType for possible types. It will contain {one
|
||||
// FINGERPRINTING_CONTROL}.
|
||||
SESSION_FINGERPRINTING_INFO,
|
||||
|
||||
// The content of SERVICE_BLOCKING_INFO events follows TLV (Type (1 byte) -
|
||||
// Length (2 bytes) - Value) format. See ServiceBlockingFieldType for possible
|
||||
// types. A SERVICE_BLOCKING_INFO event contains {one or more CHANNEL, one or
|
||||
// more DEVICE_GROUP, zero or one START_TIME_SECONDS, one END_TIME_SECONDS}.
|
||||
SERVICE_BLOCKING_INFO = CAS_SERVICE_BLOCKING_EVENT_START,
|
||||
// Service blocking device group for a session. The content of the event
|
||||
// follows TLV (Type (1 byte) - Length (2 bytes) - Value) format. See
|
||||
// SessionServiceBlockingFieldType for possible types. It will contain {one or
|
||||
// more SERVICE_BLOCKING_DEVICE_GROUP}.
|
||||
SESSION_SERVICE_BLOCKING_INFO,
|
||||
|
||||
TEST_FOR_ECHO =
|
||||
CAS_TEST_EVENT_START, // Request an ECHO response to test events passing.
|
||||
ECHO, // Respond to TEST_FOR_ECHO.
|
||||
} CasEventId;
|
||||
|
||||
// Types used inside an SESSION_FINGERPRINTING_CONTROL event.
|
||||
typedef enum {
|
||||
FINGERPRINTING_CONTROL = 0,
|
||||
} SessionFingerprintingFieldType;
|
||||
|
||||
// Types used inside an SESSION_SERVICE_BLOCKING_GROUPS event.
|
||||
typedef enum {
|
||||
SERVICE_BLOCKING_DEVICE_GROUP = 0,
|
||||
} SessionServiceBlockingFieldType;
|
||||
|
||||
#endif // CAS_EVENTS_H
|
||||
|
||||
@@ -110,6 +110,13 @@ class CasLicense : public wvutil::TimerHandler, public wvcas::CasEventListener {
|
||||
void OnAgeRestrictionUpdated(const WvCasSessionId& sessionId,
|
||||
uint8_t ecm_age_restriction) override;
|
||||
|
||||
void OnSessionFingerprintingUpdated(const WvCasSessionId& sessionId,
|
||||
const CasData& fingerprinting) override;
|
||||
|
||||
void OnSessionServiceBlockingUpdated(
|
||||
const WvCasSessionId& sessionId,
|
||||
const CasData& service_blocking) override;
|
||||
|
||||
// Query to see if the license is expired.
|
||||
virtual bool IsExpired() const;
|
||||
|
||||
|
||||
@@ -89,6 +89,14 @@ class CasEventListener {
|
||||
virtual void OnAgeRestrictionUpdated(const WvCasSessionId& sessionId,
|
||||
uint8_t ecm_age_restriction) = 0;
|
||||
|
||||
// Notifies listeners of new fingerprinting info.
|
||||
virtual void OnSessionFingerprintingUpdated(
|
||||
const WvCasSessionId& sessionId, const CasData& fingerprinting) = 0;
|
||||
|
||||
// Notifies listeners of new service blocking info.
|
||||
virtual void OnSessionServiceBlockingUpdated(
|
||||
const WvCasSessionId& sessionId, const CasData& service_blocking) = 0;
|
||||
|
||||
CasEventListener(const CasEventListener&) = delete;
|
||||
CasEventListener& operator=(const CasEventListener&) = delete;
|
||||
};
|
||||
|
||||
@@ -9,56 +9,42 @@
|
||||
#include <vector>
|
||||
|
||||
#include "cas_types.h"
|
||||
#include "media_cas.pb.h"
|
||||
|
||||
namespace wvcas {
|
||||
|
||||
enum class KeySlotId { kEvenKeySlot, kOddKeySlot };
|
||||
|
||||
struct EcmKeyData;
|
||||
|
||||
// EcmParser allows random access to the fields of an ECM.
|
||||
// The only validation performed is to ensure that the ecm
|
||||
// passed in is large enough to hold a single key entry.
|
||||
class EcmParser {
|
||||
protected:
|
||||
EcmParser() {}
|
||||
|
||||
public:
|
||||
EcmParser() = default;
|
||||
virtual ~EcmParser() {}
|
||||
|
||||
// The EcmParser factory method.
|
||||
// Validates the ecm. If validations is successful returns true and constructs
|
||||
// an EcmParser in |parser| using |ecm|.
|
||||
static bool create(const CasEcm& ecm,
|
||||
std::unique_ptr<const EcmParser>* parser);
|
||||
static std::unique_ptr<const EcmParser> Create(const CasEcm& ecm);
|
||||
|
||||
// Accessor methods.
|
||||
virtual uint8_t version() const;
|
||||
virtual uint8_t sequence_count() const;
|
||||
virtual CryptoMode crypto_mode() const;
|
||||
virtual bool rotation_enabled() const;
|
||||
virtual size_t content_iv_size() const;
|
||||
virtual uint8_t age_restriction() const;
|
||||
virtual const std::vector<uint8_t> entitlement_key_id(KeySlotId id) const;
|
||||
virtual const std::vector<uint8_t> content_key_id(KeySlotId id) const;
|
||||
virtual const std::vector<uint8_t> wrapped_key_data(KeySlotId id) const;
|
||||
virtual const std::vector<uint8_t> wrapped_key_iv(KeySlotId id) const;
|
||||
virtual const std::vector<uint8_t> content_iv(KeySlotId id) const;
|
||||
virtual uint8_t version() const = 0;
|
||||
virtual CryptoMode crypto_mode() const = 0;
|
||||
virtual bool rotation_enabled() const = 0;
|
||||
virtual size_t content_iv_size() const = 0;
|
||||
virtual uint8_t age_restriction() const = 0;
|
||||
virtual std::vector<uint8_t> entitlement_key_id(KeySlotId id) const = 0;
|
||||
virtual std::vector<uint8_t> content_key_id(KeySlotId id) const = 0;
|
||||
virtual std::vector<uint8_t> wrapped_key_data(KeySlotId id) const = 0;
|
||||
virtual std::vector<uint8_t> wrapped_key_iv(KeySlotId id) const = 0;
|
||||
virtual std::vector<uint8_t> content_iv(KeySlotId id) const = 0;
|
||||
|
||||
EcmParser(const EcmParser&) = delete;
|
||||
EcmParser& operator=(const EcmParser&) = delete;
|
||||
|
||||
private:
|
||||
// Constructs an EcmParser using |ecm|.
|
||||
explicit EcmParser(const CasEcm& ecm);
|
||||
|
||||
size_t key_data_size() const;
|
||||
// Returns false if the ecm used to construct the object is not a valid size.
|
||||
// TODO(jfore): Add validation using the version field.
|
||||
bool is_valid_size() const;
|
||||
const EcmKeyData* key_slot_data(KeySlotId id) const;
|
||||
|
||||
CasEcm ecm_;
|
||||
virtual bool has_fingerprinting() const = 0;
|
||||
virtual video_widevine::Fingerprinting fingerprinting() const = 0;
|
||||
virtual bool has_service_blocking() const = 0;
|
||||
virtual video_widevine::ServiceBlocking service_blocking() const = 0;
|
||||
// The serialized payload that the signature is calculated on.
|
||||
virtual std::string ecm_serialized_payload() const = 0;
|
||||
virtual std::string signature() const = 0;
|
||||
};
|
||||
|
||||
} // namespace wvcas
|
||||
|
||||
76
plugin/include/ecm_parser_v2.h
Normal file
76
plugin/include/ecm_parser_v2.h
Normal file
@@ -0,0 +1,76 @@
|
||||
// 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 ECM_PARSER_V2_H
|
||||
#define ECM_PARSER_V2_H
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include "cas_types.h"
|
||||
#include "ecm_parser.h"
|
||||
|
||||
namespace wvcas {
|
||||
|
||||
struct EcmKeyData;
|
||||
|
||||
// EcmParserV2 allows random access to the fields of an ECM version 2 and under.
|
||||
// It should be initialized via EcmParser factory create only.
|
||||
class EcmParserV2 : public EcmParser {
|
||||
public:
|
||||
~EcmParserV2() override = default;
|
||||
EcmParserV2(const EcmParserV2&) = delete;
|
||||
EcmParserV2& operator=(const EcmParserV2&) = delete;
|
||||
|
||||
// The EcmParserV2 factory method.
|
||||
// |ecm| must be Widevine ECM v2 or under without section header.
|
||||
// Validates the ecm. The only validation performed is to ensure that the ecm
|
||||
// passed in is large enough to hold a single key entry. If validations is
|
||||
// successful returns true and constructs an EcmParserV2 in |parser| using
|
||||
// |ecm|.
|
||||
static bool create(const CasEcm& cas_ecm,
|
||||
std::unique_ptr<const EcmParserV2>* parser);
|
||||
|
||||
// Accessor methods.
|
||||
uint8_t version() const override;
|
||||
CryptoMode crypto_mode() const override;
|
||||
bool rotation_enabled() const override;
|
||||
size_t content_iv_size() const override;
|
||||
uint8_t age_restriction() const override;
|
||||
std::vector<uint8_t> entitlement_key_id(KeySlotId id) const override;
|
||||
std::vector<uint8_t> content_key_id(KeySlotId id) const override;
|
||||
std::vector<uint8_t> wrapped_key_data(KeySlotId id) const override;
|
||||
std::vector<uint8_t> wrapped_key_iv(KeySlotId id) const override;
|
||||
std::vector<uint8_t> content_iv(KeySlotId id) const override;
|
||||
|
||||
// ECM v2 or under does not have these fields.
|
||||
bool has_fingerprinting() const override { return false; }
|
||||
video_widevine::Fingerprinting fingerprinting() const override {
|
||||
video_widevine::Fingerprinting fingerprinting;
|
||||
return fingerprinting;
|
||||
}
|
||||
bool has_service_blocking() const override { return false; };
|
||||
video_widevine::ServiceBlocking service_blocking() const override {
|
||||
video_widevine::ServiceBlocking service_blocking;
|
||||
return service_blocking;
|
||||
}
|
||||
std::string ecm_serialized_payload() const override { return ""; }
|
||||
std::string signature() const override { return ""; }
|
||||
|
||||
private:
|
||||
// Constructs an EcmParserV2 using |ecm|.
|
||||
explicit EcmParserV2(const CasEcm& ecm);
|
||||
|
||||
size_t key_data_size() const;
|
||||
// Returns false if the ecm used to construct the object is not a valid size.
|
||||
// TODO(jfore): Add validation using the version field.
|
||||
bool is_valid_size() const;
|
||||
const EcmKeyData* key_slot_data(KeySlotId id) const;
|
||||
|
||||
CasEcm ecm_;
|
||||
};
|
||||
|
||||
} // namespace wvcas
|
||||
|
||||
#endif // ECM_PARSER_V2_H
|
||||
60
plugin/include/ecm_parser_v3.h
Normal file
60
plugin/include/ecm_parser_v3.h
Normal file
@@ -0,0 +1,60 @@
|
||||
// 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 ECM_PARSER_V3_H
|
||||
#define ECM_PARSER_V3_H
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include "cas_types.h"
|
||||
#include "ecm_parser.h"
|
||||
#include "media_cas.pb.h"
|
||||
|
||||
namespace wvcas {
|
||||
|
||||
// EcmParser allows random access to the fields of an ECM.
|
||||
class EcmParserV3 : public EcmParser {
|
||||
public:
|
||||
~EcmParserV3() override = default;
|
||||
EcmParserV3(const EcmParserV3&) = delete;
|
||||
EcmParserV3& operator=(const EcmParserV3&) = delete;
|
||||
|
||||
// The EcmParserV3 factory method.
|
||||
// |ecm| must be Widevine ECM v3 (or higher if compatible) without section
|
||||
// header. Validates the ecm. If validations is successful returns an
|
||||
// EcmParserV3, otherwise an nullptr.
|
||||
static std::unique_ptr<const EcmParserV3> Create(const CasEcm& ecm);
|
||||
|
||||
// Accessor methods.
|
||||
uint8_t version() const override;
|
||||
CryptoMode crypto_mode() const override;
|
||||
bool rotation_enabled() const override;
|
||||
size_t content_iv_size() const override;
|
||||
uint8_t age_restriction() const override;
|
||||
std::vector<uint8_t> entitlement_key_id(KeySlotId id) const override;
|
||||
std::vector<uint8_t> content_key_id(KeySlotId id) const override;
|
||||
std::vector<uint8_t> wrapped_key_data(KeySlotId id) const override;
|
||||
std::vector<uint8_t> wrapped_key_iv(KeySlotId id) const override;
|
||||
std::vector<uint8_t> content_iv(KeySlotId id) const override;
|
||||
|
||||
bool has_fingerprinting() const override;
|
||||
video_widevine::Fingerprinting fingerprinting() const override;
|
||||
bool has_service_blocking() const override;
|
||||
video_widevine::ServiceBlocking service_blocking() const override;
|
||||
// The serialized payload that the signature is calculated on.
|
||||
std::string ecm_serialized_payload() const override;
|
||||
std::string signature() const override;
|
||||
|
||||
private:
|
||||
// Constructs an EcmParserV3 using |ecm|.
|
||||
EcmParserV3(video_widevine::SignedEcmPayload signed_ecm_payload,
|
||||
video_widevine::EcmPayload ecm_payload);
|
||||
video_widevine::SignedEcmPayload signed_ecm_payload_;
|
||||
video_widevine::EcmPayload ecm_payload_;
|
||||
};
|
||||
|
||||
} // namespace wvcas
|
||||
|
||||
#endif // ECM_PARSER_V3_H
|
||||
@@ -7,11 +7,13 @@
|
||||
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <set>
|
||||
#include <string>
|
||||
|
||||
#include "cas_types.h"
|
||||
#include "crypto_session.h"
|
||||
#include "ecm_parser.h"
|
||||
#include "media_cas.pb.h"
|
||||
|
||||
namespace wvcas {
|
||||
|
||||
@@ -45,7 +47,7 @@ class WidevineCasSession {
|
||||
virtual ~WidevineCasSession();
|
||||
|
||||
CasStatus initialize(std::shared_ptr<CryptoSession> crypto_session,
|
||||
uint32_t* session_id);
|
||||
CasEventListener* event_listener, uint32_t* session_id);
|
||||
|
||||
// Get the current key information. This method will be used by a descrambler
|
||||
// plugin to obtain the current key information.
|
||||
@@ -80,6 +82,13 @@ class WidevineCasSession {
|
||||
std::shared_ptr<CryptoSession> crypto_session_;
|
||||
// Id of the entitled key session in OEMCrypto associated with this session.
|
||||
uint32_t key_session_id_;
|
||||
CasEventListener* event_listener_ = nullptr;
|
||||
// Fingerprinting events sent in processing last ECM/EMM. Used to avoid
|
||||
// sending a same event again.
|
||||
std::vector<uint8_t> last_fingerprinting_message_;
|
||||
// Service blocking events sent in processing last ECM/EMM. Used to avoid
|
||||
// sending a same event again.
|
||||
std::vector<uint8_t> last_service_blocking_message_;
|
||||
};
|
||||
|
||||
} // namespace wvcas
|
||||
|
||||
@@ -112,6 +112,11 @@ class WidevineCasPlugin : public CasPlugin, public CasEventListener {
|
||||
void OnLicenseExpiration() override;
|
||||
void OnAgeRestrictionUpdated(const WvCasSessionId& sessionId,
|
||||
uint8_t ecm_age_restriction) override;
|
||||
void OnSessionFingerprintingUpdated(const WvCasSessionId& sessionId,
|
||||
const CasData& fingerprinting) override;
|
||||
void OnSessionServiceBlockingUpdated(
|
||||
const WvCasSessionId& sessionId,
|
||||
const CasData& service_blocking) override;
|
||||
|
||||
// Choose to use |callback_| or |callback_ext_| to send back information.
|
||||
// |sessionId| is ignored if |callback_ext_| is null,
|
||||
|
||||
Reference in New Issue
Block a user