Home | History | Annotate | Download | only in clearkey
      1 /*
      2  * Copyright (C) 2017 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 // Data objects encapsulating the clear key Ecm (Entitlement Control
     18 // Message) and related container messages. Deserialization and decryption
     19 // are handled externally to reduce build-time dependencies.
     20 //
     21 // Simplified typical client-side use:
     22 //   Asset asset; // from the AssetRegistry.
     23 //   uint8[] ecm_buffer; // received over network, contains an EcmContainer.
     24 //   EcmContainer ecm_container;
     25 //   util::Status status = ecm_container.Parse(ecm_buffer);
     26 //   status = ecm_container.descriptor(1).ecm().Decrypt(
     27 //      ecm_container.descriptor(1).ecm().buffer(), asset_key);
     28 //   string content_key;
     29 //   if (ecm_container.descriptor(1).ecm().has_content_key()) {
     30 //     content_key = ecm_container.descriptor(1).ecm().content_key();
     31 //   }
     32 //   // use |content_key| to decrypt content.
     33 //
     34 // Simplified typical server-side use:
     35 //   EcmContainer container;
     36 //   string encoded_ecm;
     37 //   // Use the ecm_generator API to encode and encrypt an ECM from data fields.
     38 //   util::Status status = ecm_generator::EncodeECM(..., &encoded_ecm);
     39 //   // Use |encoded_ecm| to initialized the Ecm from this library.
     40 //   Ecm ecm;
     41 //   util::Status status = ecm.Parse(encoded_ecm);
     42 //   EcmDescriptor descriptor(crypto_period_id, ecm);
     43 //   status = container.Add(descriptor);
     44 //   string serialized_container;
     45 //   status = container.Marshall(&serialized_container);
     46 //   // now |serialized_container| can be sent to the STB.
     47 //
     48 // Due to past overloading of the term "ECM" this library introduces some
     49 // new terminology.
     50 //
     51 // Ecm: the 32-byte message sent from the head end to a packager that contains
     52 // the asset_id, system_id, and content_key (clear).
     53 //
     54 // EcmDescriptor: contains an Ecm and an id (the crypto period id in the case
     55 // of the BroadcastEncryptor). It contains no encrypted fields.
     56 //
     57 // EcmContainer: sent by the server in the video stream using the ECM pid.
     58 // This contains 1 or 2 EcmDescriptors and a count. It contains no
     59 // encrypted fields.
     60 //
     61 // The first EcmContainer sent by the server has only one EcmDescriptor. After
     62 // the first crypto period change, an EcmContainer contains 2 EcmDescriptors.
     63 // One has an odd id and one has an even id. The decrypted content keys from the
     64 // Ecms in the EcmDescriptors are used by the Mpeg2 parser as odd and even
     65 // scrambling keys. As the crypto period changes, the oldest EcmDescriptor is
     66 // dropped from the EcmContainer and the new EcmDescriptor is added.
     67 //
     68 // These classes use a simplified protobuf model. For non-repeating fields,
     69 // - has_foo() indicates whether the field is populated.
     70 // - the accessor foo() returns either a value or a const reference.
     71 // - a mutator sets the value.  Primitive types and strings use
     72 //   set_foo(value) while for objects mutable_foo() returns a pointer.
     73 //
     74 // To prevent null references, objects (like the Asset contained in an Emm)
     75 // are allocated as members and can be accessed via foo() even if they have
     76 // not been populated. The caller must call has_foo() to make sure that the
     77 // object is valid. Calling mutable_foo() to obtain a pointer causes has_foo()
     78 // to return true.
     79 //
     80 // Repeated fields (like the EcmDescriptors contained in an EcmContainer) are
     81 // handled differently.
     82 // - foo_size() returns the number of instances.
     83 // - the accessor foo(index) returns either a value or a const reference to
     84 //   the instance at index. It is illegal to call with |index| >= the value
     85 //   returned by foo_size(). |index| is checked with CHECK.
     86 // - a mutator to change the value of the instance.  Primitive types and
     87 //   strings use set_foo(index, value) while for objects mutable_foo(index)
     88 //   returns a pointer. It is illegal to call with |index| >= the value
     89 //   returned by foo_size(). |index| is checked with CHECK.
     90 //
     91 // Accessing a repeated field with an invalid index causes CHECK to fail.
     92 // Be sure to call EcmContainer::decriptor_size() before calling descriptor()
     93 // or mutable_descriptor()!
     94 //
     95 #ifndef CLEAR_KEY_ECM_H_
     96 #define CLEAR_KEY_ECM_H_
     97 
     98 #include <stddef.h>
     99 #include <string>
    100 
    101 #include "protos/license_protos.pb.h"
    102 
    103 #include <media/stagefright/foundation/ABase.h>
    104 #include <media/stagefright/foundation/ABuffer.h>
    105 #include <utils/Errors.h>
    106 
    107 using namespace std;
    108 
    109 namespace android {
    110 namespace clearkeycas {
    111 
    112 // Entitlement Control Message. It contains clear fields. The asset_id
    113 // and system_id as well as the content_key are clear.
    114 //
    115 // This class is not thread-safe.
    116 class Ecm {
    117 public:
    118     // Wire size of ECM.
    119     static constexpr size_t kSizeBytes = 16 + 16; // clear fields + clear key
    120 
    121     // Creates an empty ECM which must be initialized via Parse().
    122     Ecm();
    123 
    124     ~Ecm();
    125 
    126     // Parses clear fields of Ecm serialized in |buffer_as_binary| and saves
    127     // a copy of |buffer_as_binary| for a future DecryptEcm call.
    128     // Returns:
    129     // - BAD_VALUE if |buffer_as_binary| is too small.
    130     // - CLEARKEY_STATUS_INVALIDASSETID via ecm_generator::DecodeEcmClearFields if
    131     //   asset_id is 0.
    132     // - CLEARKEY_STATUS_INVALIDSYSTEMID via ecm_generator::DecodeEcmClearFields if
    133     //   system_id is 0.
    134     // Postconditions:
    135     // - |asset_id_| and |system_id_| are populated with non-zero values.
    136     // - |buffer_| contains a copy of the serialized Ecm.
    137     status_t Parse(const sp<ABuffer>& buffer_as_binary);
    138 
    139     // Parses and decrypts Ecm serialized in |buffer_as_binary| using
    140     // |asset_from_emm|.asset_key().encryption_key(). It is not necessary to call
    141     // Parse() first.
    142     // Returns BAD_VALUE if |buffer_as_binary| is too small.
    143     // Returns CLEARKEY_STATUS_INVALIDASSETID via
    144     //   ecm_generator::DecodeEcmClearFields if asset_id is 0.
    145     // Returns CLEARKEY_STATUS_INVALIDSYSTEMID via
    146     //   ecm_generator::DecodeEcmClearFields if system_id is 0.
    147     // Returns CLEARKEY_STATUS_INVALID_PARAMETER if
    148     // - asset_id in |asset_from_emm| does not match asset_id in serialized Ecm.
    149     // Preconditions: |asset_from_emm| must contain asset_id and asset_key fields.
    150     // Postconditions: asset_id() and system_id() are populated with non-zero
    151     // values, content_key() is populated with the clear content key.
    152     status_t Decrypt(const sp<ABuffer>& buffer_as_binary,
    153             const Asset& asset_from_emm);
    154 
    155     // |buffer_| is a serialized copy of the Ecm used for later decryption or
    156     // for marshalling.
    157     inline bool has_buffer() const { return buffer_ != NULL; }
    158     const sp<ABuffer> buffer() const { return buffer_; }
    159     inline void set_buffer(const sp<ABuffer>& buffer) {
    160         buffer_ = ABuffer::CreateAsCopy(buffer->data(), buffer->size());
    161     }
    162 
    163     // |content_key| is the clear, encryption/decryption key generated by the server.
    164     inline bool has_content_key() const { return content_key_ != NULL; }
    165     inline void set_content_key(const sp<ABuffer>& value) {
    166         content_key_ = ABuffer::CreateAsCopy(value->data(), value->size());
    167     }
    168     inline const sp<ABuffer> content_key() const { return content_key_; }
    169 
    170     // |asset_id| from the server.
    171     inline bool has_asset_id() const { return asset_id_set_; }
    172     inline uint64_t asset_id() const { return asset_id_; }
    173     inline void set_asset_id(uint64_t value) {
    174         asset_id_ = value;
    175         asset_id_set_ = true;
    176     }
    177 
    178     // |system_id| from the server.
    179     inline bool has_system_id() const { return system_id_set_; }
    180     inline uint32_t system_id() const { return system_id_; }
    181     inline void set_system_id(uint32_t value) {
    182         system_id_ = value;
    183         system_id_set_ = true;
    184     }
    185 
    186 private:
    187     uint64_t asset_id_;
    188     bool asset_id_set_;
    189     sp<ABuffer> buffer_;
    190     sp<ABuffer> content_key_;
    191     uint32_t system_id_;
    192     bool system_id_set_;
    193 };
    194 
    195 // Contains an Ecm and and Id.
    196 // This class is not thread-safe.
    197 class EcmDescriptor {
    198 public:
    199     // Wire size of Id field.
    200     static constexpr size_t kIdSizeBytes = sizeof(uint16_t);
    201     // Wire size of EcmDescriptor.
    202     static constexpr size_t kSizeBytes = Ecm::kSizeBytes + kIdSizeBytes;
    203 
    204     // Client-side ctor. Populate from a buffer with Parse().
    205     EcmDescriptor();
    206 
    207     // Server-side ctor.
    208     // Args:
    209     // - |id| is the crypto period ID.
    210     // - |ecm| is an ECM which must have been intialized with Ecm::Parse().
    211     EcmDescriptor(uint16_t id, const Ecm& ecm);
    212 
    213     ~EcmDescriptor();
    214 
    215     // Parses EcmDescriptor and its contained Ecm which are serialized in the
    216     // binary string |buffer_as_binary|.
    217     // Returns
    218     // - BAD_VALUE if |buffer_as_binary| is too short to contain a
    219     //   serialized EcmDescriptor.
    220     // - Errors returned by Ecm::Parse.
    221     // Postconditions:
    222     // - id() is populated. Note that 0 is a legal value.
    223     // - the clear fields of the contained Ecm have been populated.
    224     status_t Parse(const sp<ABuffer>& buffer_as_binary);
    225 
    226     // |id| of the contained Ecm. Typically the crypto period id.
    227     inline bool has_id() const { return id_set_; }
    228     inline void set_id(uint16_t value) {
    229         id_ = value;
    230         id_set_ = true;
    231     }
    232     inline uint16_t id() const { return id_; }
    233 
    234     // The contained |ecm|.
    235     inline bool has_ecm() const { return ecm_set_; }
    236     inline Ecm* mutable_ecm() {
    237         ecm_set_ = true;
    238         return &ecm_;
    239     }
    240     inline const Ecm& ecm() const { return ecm_; }
    241 
    242 private:
    243     Ecm ecm_;
    244     bool ecm_set_;
    245     uint16_t id_;
    246     bool id_set_;
    247 };
    248 
    249 // Contains a count and 1 or 2 EcmDescriptors. This is included in the video
    250 // stream by the sender in the ECM pid.
    251 // This class is not thread-safe.
    252 class EcmContainer {
    253 public:
    254     // Wire size of the count field.
    255     static constexpr size_t kCountSizeBytes = sizeof(uint16_t);
    256     // Minimum wire size assuming one EcmDescriptor.
    257     static constexpr size_t kMinimumSizeBytes =
    258             EcmDescriptor::kSizeBytes + kCountSizeBytes;
    259     static constexpr size_t kMinDescriptorCount = 1;
    260     static constexpr size_t kMaxDescriptorCount = 2;
    261 
    262     // Creates an empty EcmContainer which must be populated via Parse()
    263     // (client-side) or Add() (server-side).
    264     EcmContainer();
    265 
    266     ~EcmContainer();
    267 
    268     // Adds an EcmDescriptor for server-side applications.
    269     // If |count_| is 2, |descriptor| replaces the oldest EcmDescriptor.
    270     //
    271     // Returns:
    272     // - INTERNAL if the EcmContainer is in a bad state (count != 0, 1, or 2).
    273     // Postconditions:
    274     // - count() is within bounds (1 or 2).
    275     status_t Add(const EcmDescriptor& descriptor);
    276 
    277     // Parses EcmContainer and its contained EcmDescriptors which are serialized
    278     // in |buffer_as_binary|.
    279     // Returns
    280     // - BAD_VALUE if |buffer_as_binary| is too short to contain a
    281     //   serialized EcmDescriptor.
    282     // - ERROR_OUT_OF_RANGE if the count contained in the serialized EcmContainer
    283     //   is not 1 or 2.
    284     // - Errors returned by EcmDescriptor::Parse.
    285     // Postconditions:
    286     // - count() is within bounds (1 or 2) and.
    287     // - contained EcmDescriptor(s) parsed and populated.
    288     status_t Parse(const sp<ABuffer>& buffer_as_binary);
    289 
    290     inline bool has_count() const { return count_set_; }
    291     // Sets the |count| of contained EcmDecriptors. Illegal values are silently
    292     // ignored.
    293     inline void set_count(size_t count) {
    294         if (!CountLegal(count)) return;
    295         count_ = count;
    296         count_set_ = true;
    297     }
    298     // Number of contained EcmDecriptors. Only 1 and 2 are legal values.
    299     inline size_t count() const { return count_; }
    300 
    301     // Returns the number of allowable descriptors. This is redundant but is
    302     // provided for protobuf compatibility.
    303     inline size_t descriptor_size() const { return count_; }
    304 
    305     // Returns a pointer to the EcmDescriptor at |index| for valid index values,
    306     // otherwise calls CHECK and aborts. Always call descriptor_size() first!
    307     inline EcmDescriptor* mutable_descriptor(size_t index) {
    308         //CHECK(IndexValid(index));
    309         return &descriptor_[index];
    310     }
    311 
    312     // Returns a reference to the EcmDescriptor at |index| for valid index
    313     // values, otherwise calls CHECK and aborts. Call descriptor_size() first!
    314     inline const EcmDescriptor& descriptor(size_t index) const {
    315         //CHECK(IndexValid(index));
    316         return descriptor_[index];
    317     }
    318 
    319 private:
    320     // Count value must be 1 or 2.
    321     inline bool CountLegal(size_t count) const {
    322         return count <= kMaxDescriptorCount && count >= kMinDescriptorCount;
    323     }
    324     // Index must be 0 or 1.
    325     inline bool IndexLegal(size_t index) const {
    326         return index < kMaxDescriptorCount;
    327     }
    328     // |index| is valid for this object: it is legal and < count_.
    329     inline bool IndexValid(size_t index) const {
    330         if (!IndexLegal(index)) return false;
    331         return index < count_;
    332     }
    333     size_t count_;
    334     bool count_set_;
    335     EcmDescriptor descriptor_[kMaxDescriptorCount];
    336 
    337     DISALLOW_EVIL_CONSTRUCTORS(EcmContainer);
    338 };
    339 
    340 }  // namespace clearkeycas
    341 }  // namespace android
    342 
    343 #endif  // CLEAR_KEY_ECM_H_
    344