Cas Client repo update.

-Parse EMM in Cas plugin
-Entitlement key rotation support
-Multi_content_license support
This commit is contained in:
huihli
2021-06-28 11:25:24 -07:00
parent 5c81c1aa9e
commit 4e4f8c468f
5 changed files with 349 additions and 0 deletions

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