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:
Lu Chen
2021-01-05 10:16:26 -08:00
parent 66d8498d2c
commit 00785b2ccd
38 changed files with 2234 additions and 747 deletions

View File

@@ -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

View File

@@ -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;

View File

@@ -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;
};

View File

@@ -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

View 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

View 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

View File

@@ -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

View File

@@ -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,