• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 //#define LOG_NDEBUG 0
18 #define LOG_TAG "ecm"
19 
20 #include "ecm.h"
21 #include "ecm_generator.h"
22 #include "protos/license_protos.pb.h"
23 
24 #include <media/stagefright/foundation/ADebug.h>
25 #include <media/stagefright/MediaErrors.h>
26 #include <utils/Log.h>
27 
28 namespace android {
29 namespace clearkeycas {
30 
Ecm()31 Ecm::Ecm()
32     : asset_id_(0),
33       asset_id_set_(false),
34       system_id_(0),
35       system_id_set_(false) {}
36 
~Ecm()37 Ecm::~Ecm() {}
38 
Parse(const sp<ABuffer> & buffer_as_binary)39 status_t Ecm::Parse(const sp<ABuffer>& buffer_as_binary) {
40     if (buffer_as_binary->size() < kSizeBytes) {
41         ALOGE("Short Ecm buffer: expected %zu, received %zu.",
42                 kSizeBytes, buffer_as_binary->size());
43         return BAD_VALUE;
44     }
45 
46     Asset asset;
47     ecm_generator::DefaultEcmFields default_fields;
48     status_t status = ecm_generator::DecodeECMClearFields(
49             buffer_as_binary, &asset, &default_fields);
50     if (status != OK) {
51         ALOGE("DecodeECMClearFields failed with status %d", status);
52         return status;
53     }
54     set_asset_id(asset.id());
55     set_system_id(default_fields.system_id);
56 
57     // Save a copy of the buffer_as_binary for a future DecryptEcm call.
58     set_buffer(buffer_as_binary);
59     return OK;
60 }
61 
Decrypt(const sp<ABuffer> & buffer_as_binary,const Asset & asset_from_emm)62 status_t Ecm::Decrypt(
63         const sp<ABuffer>& buffer_as_binary,
64         const Asset& asset_from_emm) {
65     // Invariant: asset has id. These are postconditions for Emm::Decrypt().
66     CHECK(asset_from_emm.has_id());
67 
68     // DecodeEcm fills in |asset|.id() with the asset_id from the encoded Ecm.
69     Asset asset(asset_from_emm);
70     ecm_generator::DefaultEcmFields default_fields;
71     sp<ABuffer> content_key;
72     status_t status = ecm_generator::DecodeECM(
73             buffer_as_binary, &asset, &content_key, &default_fields);
74     if (status != OK) {
75         ALOGE("DecodeECM failed with status %d", status);
76         return status;
77     }
78     if (asset.id() != asset_from_emm.id()) {
79         ALOGE("Asset_id from Emm (%llu) does not match asset_id from Ecm (%llu).",
80                 asset_from_emm.id(), asset.id());
81         return CLEARKEY_STATUS_INVALID_PARAMETER;
82     }
83     set_asset_id(asset.id());
84     set_system_id(default_fields.system_id);
85     set_content_key(content_key);
86     return status;
87 }
88 
EcmDescriptor()89 EcmDescriptor::EcmDescriptor() : ecm_set_(false), id_(0), id_set_(false) {}
90 
EcmDescriptor(uint16_t id,const Ecm & ecm)91 EcmDescriptor::EcmDescriptor(uint16_t id, const Ecm& ecm)
92 : ecm_(ecm), ecm_set_(true), id_(id), id_set_(true) {}
93 
~EcmDescriptor()94 EcmDescriptor::~EcmDescriptor() {}
95 
Parse(const sp<ABuffer> & buffer_as_binary)96 status_t EcmDescriptor::Parse(const sp<ABuffer>& buffer_as_binary) {
97     if (buffer_as_binary->size() < kSizeBytes) {
98         ALOGE("Short EcmDescriptor buffer: expected %zu, received %zu.",
99                 kSizeBytes, buffer_as_binary->size());
100         return BAD_VALUE;
101     }
102     sp<ABuffer> id_buffer = new ABuffer(buffer_as_binary->data(), kIdSizeBytes);
103     const uint8_t *id_bytes = id_buffer->data();
104     uint16_t id = (id_bytes[0] << 8) | id_bytes[1];
105     set_id(id);
106 
107     // Unmarshall the contained Ecm.
108     sp<ABuffer> ecm_buffer = new ABuffer(
109             buffer_as_binary->data() + kIdSizeBytes, Ecm::kSizeBytes);
110     status_t status = mutable_ecm()->Parse(ecm_buffer);
111     if (status != OK) {
112         return status;
113     }
114     return OK;
115 }
116 
EcmContainer()117 EcmContainer::EcmContainer() : count_(0), count_set_(false) {}
118 
~EcmContainer()119 EcmContainer::~EcmContainer() {}
120 
Add(const EcmDescriptor & descriptor)121 status_t EcmContainer::Add(const EcmDescriptor& descriptor) {
122     switch (count_) {
123     case 0:
124         descriptor_[0] = descriptor;
125         count_ = 1;
126         break;
127     case 1:
128         descriptor_[1] = descriptor;
129         count_ = 2;
130         break;
131     case 2:
132         descriptor_[0] = descriptor_[1];
133         descriptor_[1] = descriptor;
134         break;
135     default:
136         ALOGE("Bad state.");
137         return INVALID_OPERATION;
138     }
139     count_set_ = true;
140     return OK;
141 }
142 
Parse(const sp<ABuffer> & buffer_as_binary)143 status_t EcmContainer::Parse(const sp<ABuffer>& buffer_as_binary) {
144     // EcmContainer can contain 1 or 2 EcmDescriptors so this is a check for
145     // minimum size.
146     if (buffer_as_binary->size() < kMinimumSizeBytes) {
147         ALOGE("Short EcmContainer buffer: expected >= %zu, received %zu.",
148                 kMinimumSizeBytes, buffer_as_binary->size());
149         return BAD_VALUE;
150     }
151 
152     sp<ABuffer> count_buffer = new ABuffer(
153             buffer_as_binary->data(), kCountSizeBytes);
154     const uint8_t *count_bytes = count_buffer->data();
155     size_t count = (count_bytes[0] << 8) | count_bytes[1];
156     // Check that count is a legal value.
157     if (!CountLegal(count)) {
158         ALOGE("Invalid descriptor count: expected %zu <= count <= %zu, received %zu.",
159                 kMinDescriptorCount, kMaxDescriptorCount, count);
160         return ERROR_OUT_OF_RANGE;
161     }
162     // If needed, check that buffer_as_binary can hold 2 EcmDescriptors.
163     if (count > kMinDescriptorCount) {
164         size_t expected_bytes =
165                 kCountSizeBytes + (count * EcmDescriptor::kSizeBytes);
166         if (buffer_as_binary->size() < expected_bytes) {
167             ALOGE("Short EcmContainer buffer: expected %zu, received %zu.",
168                     expected_bytes, buffer_as_binary->size());
169             return BAD_VALUE;
170         }
171     }
172     set_count(count);
173     // Unmarshall the contained EcmDescriptors.
174     size_t offset = kCountSizeBytes;
175     for (size_t i = 0; i < count_; ++i) {
176         sp<ABuffer> descriptor_buffer = new ABuffer(
177                 buffer_as_binary->data() + offset, EcmDescriptor::kSizeBytes);
178         status_t status = mutable_descriptor(i)->Parse(descriptor_buffer);
179         if (status != OK) {
180             return status;
181         }
182         offset += EcmDescriptor::kSizeBytes;
183     }
184     return OK;
185 }
186 
187 }  // namespace clearkeycas
188 }  // namespace android
189