1791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang/* 2791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang * Copyright (C) 2017 The Android Open Source Project 3791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang * 4791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang * Licensed under the Apache License, Version 2.0 (the "License"); 5791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang * you may not use this file except in compliance with the License. 6791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang * You may obtain a copy of the License at 7791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang * 8791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang * http://www.apache.org/licenses/LICENSE-2.0 9791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang * 10791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang * Unless required by applicable law or agreed to in writing, software 11791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang * distributed under the License is distributed on an "AS IS" BASIS, 12791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang * See the License for the specific language governing permissions and 14791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang * limitations under the License. 15791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang */ 16791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang 17791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang// Data objects encapsulating the clear key Ecm (Entitlement Control 18791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang// Message) and related container messages. Deserialization and decryption 19791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang// are handled externally to reduce build-time dependencies. 20791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang// 21791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang// Simplified typical client-side use: 22791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang// Asset asset; // from the AssetRegistry. 23791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang// uint8[] ecm_buffer; // received over network, contains an EcmContainer. 24791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang// EcmContainer ecm_container; 25791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang// util::Status status = ecm_container.Parse(ecm_buffer); 26791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang// status = ecm_container.descriptor(1).ecm().Decrypt( 27791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang// ecm_container.descriptor(1).ecm().buffer(), asset_key); 28791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang// string content_key; 29791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang// if (ecm_container.descriptor(1).ecm().has_content_key()) { 30791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang// content_key = ecm_container.descriptor(1).ecm().content_key(); 31791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang// } 32791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang// // use |content_key| to decrypt content. 33791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang// 34791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang// Simplified typical server-side use: 35791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang// EcmContainer container; 36791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang// string encoded_ecm; 37791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang// // Use the ecm_generator API to encode and encrypt an ECM from data fields. 38791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang// util::Status status = ecm_generator::EncodeECM(..., &encoded_ecm); 39791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang// // Use |encoded_ecm| to initialized the Ecm from this library. 40791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang// Ecm ecm; 41791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang// util::Status status = ecm.Parse(encoded_ecm); 42791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang// EcmDescriptor descriptor(crypto_period_id, ecm); 43791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang// status = container.Add(descriptor); 44791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang// string serialized_container; 45791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang// status = container.Marshall(&serialized_container); 46791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang// // now |serialized_container| can be sent to the STB. 47791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang// 48791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang// Due to past overloading of the term "ECM" this library introduces some 49791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang// new terminology. 50791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang// 51791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang// Ecm: the 32-byte message sent from the head end to a packager that contains 52791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang// the asset_id, system_id, and content_key (clear). 53791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang// 54791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang// EcmDescriptor: contains an Ecm and an id (the crypto period id in the case 55791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang// of the BroadcastEncryptor). It contains no encrypted fields. 56791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang// 57791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang// EcmContainer: sent by the server in the video stream using the ECM pid. 58791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang// This contains 1 or 2 EcmDescriptors and a count. It contains no 59791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang// encrypted fields. 60791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang// 61791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang// The first EcmContainer sent by the server has only one EcmDescriptor. After 62791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang// the first crypto period change, an EcmContainer contains 2 EcmDescriptors. 63791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang// One has an odd id and one has an even id. The decrypted content keys from the 64791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang// Ecms in the EcmDescriptors are used by the Mpeg2 parser as odd and even 65791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang// scrambling keys. As the crypto period changes, the oldest EcmDescriptor is 66791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang// dropped from the EcmContainer and the new EcmDescriptor is added. 67791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang// 68791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang// These classes use a simplified protobuf model. For non-repeating fields, 69791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang// - has_foo() indicates whether the field is populated. 70791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang// - the accessor foo() returns either a value or a const reference. 71791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang// - a mutator sets the value. Primitive types and strings use 72791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang// set_foo(value) while for objects mutable_foo() returns a pointer. 73791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang// 74791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang// To prevent null references, objects (like the Asset contained in an Emm) 75791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang// are allocated as members and can be accessed via foo() even if they have 76791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang// not been populated. The caller must call has_foo() to make sure that the 77791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang// object is valid. Calling mutable_foo() to obtain a pointer causes has_foo() 78791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang// to return true. 79791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang// 80791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang// Repeated fields (like the EcmDescriptors contained in an EcmContainer) are 81791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang// handled differently. 82791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang// - foo_size() returns the number of instances. 83791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang// - the accessor foo(index) returns either a value or a const reference to 84791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang// the instance at index. It is illegal to call with |index| >= the value 85791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang// returned by foo_size(). |index| is checked with CHECK. 86791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang// - a mutator to change the value of the instance. Primitive types and 87791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang// strings use set_foo(index, value) while for objects mutable_foo(index) 88791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang// returns a pointer. It is illegal to call with |index| >= the value 89791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang// returned by foo_size(). |index| is checked with CHECK. 90791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang// 91791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang// Accessing a repeated field with an invalid index causes CHECK to fail. 92791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang// Be sure to call EcmContainer::decriptor_size() before calling descriptor() 93791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang// or mutable_descriptor()! 94791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang// 95791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang#ifndef CLEAR_KEY_ECM_H_ 96791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang#define CLEAR_KEY_ECM_H_ 97791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang 98791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang#include <stddef.h> 99791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang#include <string> 100791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang 101791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang#include "protos/license_protos.pb.h" 102791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang 103791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang#include <media/stagefright/foundation/ABase.h> 104791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang#include <media/stagefright/foundation/ABuffer.h> 105791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang#include <utils/Errors.h> 106791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang 107791a1a206b56be8601a6fffd2614926e67d64790Chong Zhangusing namespace std; 108791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang 109791a1a206b56be8601a6fffd2614926e67d64790Chong Zhangnamespace android { 110791a1a206b56be8601a6fffd2614926e67d64790Chong Zhangnamespace clearkeycas { 111791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang 112791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang// Entitlement Control Message. It contains clear fields. The asset_id 113791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang// and system_id as well as the content_key are clear. 114791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang// 115791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang// This class is not thread-safe. 116791a1a206b56be8601a6fffd2614926e67d64790Chong Zhangclass Ecm { 117791a1a206b56be8601a6fffd2614926e67d64790Chong Zhangpublic: 118791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang // Wire size of ECM. 119791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang static constexpr size_t kSizeBytes = 16 + 16; // clear fields + clear key 120791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang 121791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang // Creates an empty ECM which must be initialized via Parse(). 122791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang Ecm(); 123791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang 124791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang ~Ecm(); 125791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang 126791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang // Parses clear fields of Ecm serialized in |buffer_as_binary| and saves 127791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang // a copy of |buffer_as_binary| for a future DecryptEcm call. 128791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang // Returns: 129791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang // - BAD_VALUE if |buffer_as_binary| is too small. 130791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang // - CLEARKEY_STATUS_INVALIDASSETID via ecm_generator::DecodeEcmClearFields if 131791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang // asset_id is 0. 132791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang // - CLEARKEY_STATUS_INVALIDSYSTEMID via ecm_generator::DecodeEcmClearFields if 133791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang // system_id is 0. 134791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang // Postconditions: 135791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang // - |asset_id_| and |system_id_| are populated with non-zero values. 136791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang // - |buffer_| contains a copy of the serialized Ecm. 137791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang status_t Parse(const sp<ABuffer>& buffer_as_binary); 138791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang 139791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang // Parses and decrypts Ecm serialized in |buffer_as_binary| using 140791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang // |asset_from_emm|.asset_key().encryption_key(). It is not necessary to call 141791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang // Parse() first. 142791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang // Returns BAD_VALUE if |buffer_as_binary| is too small. 143791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang // Returns CLEARKEY_STATUS_INVALIDASSETID via 144791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang // ecm_generator::DecodeEcmClearFields if asset_id is 0. 145791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang // Returns CLEARKEY_STATUS_INVALIDSYSTEMID via 146791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang // ecm_generator::DecodeEcmClearFields if system_id is 0. 147791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang // Returns CLEARKEY_STATUS_INVALID_PARAMETER if 148791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang // - asset_id in |asset_from_emm| does not match asset_id in serialized Ecm. 149791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang // Preconditions: |asset_from_emm| must contain asset_id and asset_key fields. 150791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang // Postconditions: asset_id() and system_id() are populated with non-zero 151791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang // values, content_key() is populated with the clear content key. 152791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang status_t Decrypt(const sp<ABuffer>& buffer_as_binary, 153791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang const Asset& asset_from_emm); 154791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang 155791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang // |buffer_| is a serialized copy of the Ecm used for later decryption or 156791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang // for marshalling. 157791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang inline bool has_buffer() const { return buffer_ != NULL; } 158791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang const sp<ABuffer> buffer() const { return buffer_; } 159791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang inline void set_buffer(const sp<ABuffer>& buffer) { 160791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang buffer_ = ABuffer::CreateAsCopy(buffer->data(), buffer->size()); 161791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang } 162791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang 163791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang // |content_key| is the clear, encryption/decryption key generated by the server. 164791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang inline bool has_content_key() const { return content_key_ != NULL; } 165791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang inline void set_content_key(const sp<ABuffer>& value) { 166791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang content_key_ = ABuffer::CreateAsCopy(value->data(), value->size()); 167791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang } 168791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang inline const sp<ABuffer> content_key() const { return content_key_; } 169791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang 170791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang // |asset_id| from the server. 171791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang inline bool has_asset_id() const { return asset_id_set_; } 172791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang inline uint64_t asset_id() const { return asset_id_; } 173791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang inline void set_asset_id(uint64_t value) { 174791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang asset_id_ = value; 175791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang asset_id_set_ = true; 176791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang } 177791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang 178791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang // |system_id| from the server. 179791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang inline bool has_system_id() const { return system_id_set_; } 180791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang inline uint32_t system_id() const { return system_id_; } 181791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang inline void set_system_id(uint32_t value) { 182791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang system_id_ = value; 183791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang system_id_set_ = true; 184791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang } 185791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang 186791a1a206b56be8601a6fffd2614926e67d64790Chong Zhangprivate: 187791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang uint64_t asset_id_; 188791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang bool asset_id_set_; 189791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang sp<ABuffer> buffer_; 190791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang sp<ABuffer> content_key_; 191791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang uint32_t system_id_; 192791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang bool system_id_set_; 193791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang}; 194791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang 195791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang// Contains an Ecm and and Id. 196791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang// This class is not thread-safe. 197791a1a206b56be8601a6fffd2614926e67d64790Chong Zhangclass EcmDescriptor { 198791a1a206b56be8601a6fffd2614926e67d64790Chong Zhangpublic: 199791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang // Wire size of Id field. 200791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang static constexpr size_t kIdSizeBytes = sizeof(uint16_t); 201791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang // Wire size of EcmDescriptor. 202791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang static constexpr size_t kSizeBytes = Ecm::kSizeBytes + kIdSizeBytes; 203791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang 204791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang // Client-side ctor. Populate from a buffer with Parse(). 205791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang EcmDescriptor(); 206791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang 207791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang // Server-side ctor. 208791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang // Args: 209791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang // - |id| is the crypto period ID. 210791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang // - |ecm| is an ECM which must have been intialized with Ecm::Parse(). 211791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang EcmDescriptor(uint16_t id, const Ecm& ecm); 212791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang 213791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang ~EcmDescriptor(); 214791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang 215791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang // Parses EcmDescriptor and its contained Ecm which are serialized in the 216791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang // binary string |buffer_as_binary|. 217791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang // Returns 218791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang // - BAD_VALUE if |buffer_as_binary| is too short to contain a 219791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang // serialized EcmDescriptor. 220791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang // - Errors returned by Ecm::Parse. 221791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang // Postconditions: 222791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang // - id() is populated. Note that 0 is a legal value. 223791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang // - the clear fields of the contained Ecm have been populated. 224791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang status_t Parse(const sp<ABuffer>& buffer_as_binary); 225791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang 226791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang // |id| of the contained Ecm. Typically the crypto period id. 227791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang inline bool has_id() const { return id_set_; } 228791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang inline void set_id(uint16_t value) { 229791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang id_ = value; 230791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang id_set_ = true; 231791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang } 232791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang inline uint16_t id() const { return id_; } 233791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang 234791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang // The contained |ecm|. 235791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang inline bool has_ecm() const { return ecm_set_; } 236791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang inline Ecm* mutable_ecm() { 237791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang ecm_set_ = true; 238791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang return &ecm_; 239791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang } 240791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang inline const Ecm& ecm() const { return ecm_; } 241791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang 242791a1a206b56be8601a6fffd2614926e67d64790Chong Zhangprivate: 243791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang Ecm ecm_; 244791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang bool ecm_set_; 245791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang uint16_t id_; 246791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang bool id_set_; 247791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang}; 248791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang 249791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang// Contains a count and 1 or 2 EcmDescriptors. This is included in the video 250791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang// stream by the sender in the ECM pid. 251791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang// This class is not thread-safe. 252791a1a206b56be8601a6fffd2614926e67d64790Chong Zhangclass EcmContainer { 253791a1a206b56be8601a6fffd2614926e67d64790Chong Zhangpublic: 254791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang // Wire size of the count field. 255791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang static constexpr size_t kCountSizeBytes = sizeof(uint16_t); 256791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang // Minimum wire size assuming one EcmDescriptor. 257791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang static constexpr size_t kMinimumSizeBytes = 258791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang EcmDescriptor::kSizeBytes + kCountSizeBytes; 259791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang static constexpr size_t kMinDescriptorCount = 1; 260791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang static constexpr size_t kMaxDescriptorCount = 2; 261791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang 262791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang // Creates an empty EcmContainer which must be populated via Parse() 263791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang // (client-side) or Add() (server-side). 264791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang EcmContainer(); 265791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang 266791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang ~EcmContainer(); 267791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang 268791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang // Adds an EcmDescriptor for server-side applications. 269791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang // If |count_| is 2, |descriptor| replaces the oldest EcmDescriptor. 270791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang // 271791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang // Returns: 272791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang // - INTERNAL if the EcmContainer is in a bad state (count != 0, 1, or 2). 273791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang // Postconditions: 274791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang // - count() is within bounds (1 or 2). 275791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang status_t Add(const EcmDescriptor& descriptor); 276791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang 277791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang // Parses EcmContainer and its contained EcmDescriptors which are serialized 278791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang // in |buffer_as_binary|. 279791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang // Returns 280791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang // - BAD_VALUE if |buffer_as_binary| is too short to contain a 281791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang // serialized EcmDescriptor. 282791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang // - ERROR_OUT_OF_RANGE if the count contained in the serialized EcmContainer 283791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang // is not 1 or 2. 284791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang // - Errors returned by EcmDescriptor::Parse. 285791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang // Postconditions: 286791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang // - count() is within bounds (1 or 2) and. 287791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang // - contained EcmDescriptor(s) parsed and populated. 288791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang status_t Parse(const sp<ABuffer>& buffer_as_binary); 289791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang 290791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang inline bool has_count() const { return count_set_; } 291791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang // Sets the |count| of contained EcmDecriptors. Illegal values are silently 292791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang // ignored. 293791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang inline void set_count(size_t count) { 294791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang if (!CountLegal(count)) return; 295791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang count_ = count; 296791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang count_set_ = true; 297791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang } 298791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang // Number of contained EcmDecriptors. Only 1 and 2 are legal values. 299791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang inline size_t count() const { return count_; } 300791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang 301791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang // Returns the number of allowable descriptors. This is redundant but is 302791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang // provided for protobuf compatibility. 303791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang inline size_t descriptor_size() const { return count_; } 304791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang 305791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang // Returns a pointer to the EcmDescriptor at |index| for valid index values, 306791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang // otherwise calls CHECK and aborts. Always call descriptor_size() first! 307791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang inline EcmDescriptor* mutable_descriptor(size_t index) { 308791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang //CHECK(IndexValid(index)); 309791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang return &descriptor_[index]; 310791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang } 311791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang 312791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang // Returns a reference to the EcmDescriptor at |index| for valid index 313791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang // values, otherwise calls CHECK and aborts. Call descriptor_size() first! 314791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang inline const EcmDescriptor& descriptor(size_t index) const { 315791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang //CHECK(IndexValid(index)); 316791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang return descriptor_[index]; 317791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang } 318791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang 319791a1a206b56be8601a6fffd2614926e67d64790Chong Zhangprivate: 320791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang // Count value must be 1 or 2. 321791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang inline bool CountLegal(size_t count) const { 322791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang return count <= kMaxDescriptorCount && count >= kMinDescriptorCount; 323791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang } 324791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang // Index must be 0 or 1. 325791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang inline bool IndexLegal(size_t index) const { 326791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang return index < kMaxDescriptorCount; 327791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang } 328791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang // |index| is valid for this object: it is legal and < count_. 329791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang inline bool IndexValid(size_t index) const { 330791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang if (!IndexLegal(index)) return false; 331791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang return index < count_; 332791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang } 333791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang size_t count_; 334791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang bool count_set_; 335791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang EcmDescriptor descriptor_[kMaxDescriptorCount]; 336791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang 337791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang DISALLOW_EVIL_CONSTRUCTORS(EcmContainer); 338791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang}; 339791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang 340791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang} // namespace clearkeycas 341791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang} // namespace android 342791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang 343791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang#endif // CLEAR_KEY_ECM_H_ 344