Cas Client repo update.
-Parse EMM in Cas plugin -Entitlement key rotation support -Multi_content_license support
This commit is contained in:
49
plugin/include/emm_parser.h
Normal file
49
plugin/include/emm_parser.h
Normal file
@@ -0,0 +1,49 @@
|
||||
// Copyright 2020 Google LLC. All Rights Reserved. This file and proprietary
|
||||
// source code may only be used and distributed under the Widevine Master
|
||||
// License Agreement.
|
||||
|
||||
#ifndef EMM_PARSER_H
|
||||
#define EMM_PARSER_H
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include "cas_types.h"
|
||||
#include "media_cas.pb.h"
|
||||
|
||||
namespace wvcas {
|
||||
|
||||
using video_widevine::EmmPayload;
|
||||
|
||||
class EmmParser {
|
||||
public:
|
||||
EmmParser(const EmmParser&) = delete;
|
||||
EmmParser& operator=(const EmmParser&) = delete;
|
||||
virtual ~EmmParser() = default;
|
||||
|
||||
// The EmmParser factory method.
|
||||
// The methods validates the passed in |emm|. If validation is successful, it
|
||||
// constructs and returns an EmmParser. Otherwise, nullptr is returned.
|
||||
static std::unique_ptr<const EmmParser> Create(const CasEmm& emm);
|
||||
|
||||
// Accessor methods.
|
||||
virtual uint64_t timestamp() const { return timestamp_; }
|
||||
virtual std::string signature() const { return signature_; }
|
||||
virtual EmmPayload emm_payload() const { return emm_payload_; };
|
||||
|
||||
protected:
|
||||
// Called by the factory create and unit test.
|
||||
EmmParser() = default;
|
||||
|
||||
private:
|
||||
bool Parse(int start_index, const CasEmm& emm);
|
||||
|
||||
uint8_t version_;
|
||||
uint64_t timestamp_;
|
||||
EmmPayload emm_payload_;
|
||||
std::string signature_;
|
||||
};
|
||||
|
||||
} // namespace wvcas
|
||||
|
||||
#endif // EMM_PARSER_H
|
||||
75
plugin/src/emm_parser.cpp
Normal file
75
plugin/src/emm_parser.cpp
Normal file
@@ -0,0 +1,75 @@
|
||||
// Copyright 2020 Google LLC. All Rights Reserved. This file and proprietary
|
||||
// source code may only be used and distributed under the Widevine Master
|
||||
// License Agreement.
|
||||
|
||||
#include "emm_parser.h"
|
||||
|
||||
#include "log.h"
|
||||
|
||||
namespace wvcas {
|
||||
namespace {
|
||||
// ETSI ETR 289 specifies table ids 0x82 to 0x8F are for CA System private
|
||||
// usage, which are typically used by EMM, with one table id for each EMM type.
|
||||
constexpr uint16_t kSectionHeader = 0x82;
|
||||
constexpr size_t kSectionHeaderSize = 3;
|
||||
constexpr size_t kSectionHeaderWithPointerSize = 4;
|
||||
constexpr uint8_t kPointerFieldZero = 0x00;
|
||||
|
||||
// Returns the possible starting index of EMM. -1 will be returned in case of
|
||||
// error. It assumes the pointer field will always set to 0, if present.
|
||||
int find_emm_start_index(const CasEmm& cas_emm) {
|
||||
if (cas_emm.empty()) {
|
||||
return -1;
|
||||
}
|
||||
// Case 1: Pointer field (always set to 0); section header; EMM.
|
||||
if (cas_emm[0] == kPointerFieldZero) {
|
||||
return kSectionHeaderWithPointerSize < cas_emm.size()
|
||||
? kSectionHeaderWithPointerSize
|
||||
: -1;
|
||||
}
|
||||
// Case 2: Section header (3 bytes), EMM.
|
||||
if (cas_emm[0] == kSectionHeader) {
|
||||
return kSectionHeaderSize < cas_emm.size() ? kSectionHeaderSize : -1;
|
||||
}
|
||||
// Case 3: EMM.
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
std::unique_ptr<const EmmParser> EmmParser::Create(const CasEmm& emm) {
|
||||
auto parser = std::unique_ptr<EmmParser>(new EmmParser());
|
||||
if (!parser->Parse(find_emm_start_index(emm), emm)) {
|
||||
return nullptr;
|
||||
}
|
||||
return parser;
|
||||
}
|
||||
|
||||
bool EmmParser::Parse(int start_index, const CasEmm& emm) {
|
||||
if (start_index < 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
video_widevine::SignedEmmPayload signed_emm;
|
||||
if (!signed_emm.ParseFromArray(emm.data() + start_index,
|
||||
emm.size() - start_index)) {
|
||||
LOGE("Failed to parse signed EMM.");
|
||||
return false;
|
||||
}
|
||||
|
||||
signature_ = signed_emm.signature();
|
||||
if (signature_.empty()) {
|
||||
LOGE("No signature in the EMM.");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!emm_payload_.ParseFromString(signed_emm.serialized_payload())) {
|
||||
LOGE("Failed to parse EMM payload.");
|
||||
return false;
|
||||
}
|
||||
timestamp_ = emm_payload_.timestamp_secs();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace wvcas
|
||||
Reference in New Issue
Block a user