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 28namespace android { 29namespace clearkeycas { 30 31Ecm::Ecm() 32 : asset_id_(0), 33 asset_id_set_(false), 34 system_id_(0), 35 system_id_set_(false) {} 36 37Ecm::~Ecm() {} 38 39status_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 62status_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 89EcmDescriptor::EcmDescriptor() : ecm_set_(false), id_(0), id_set_(false) {} 90 91EcmDescriptor::EcmDescriptor(uint16_t id, const Ecm& ecm) 92: ecm_(ecm), ecm_set_(true), id_(id), id_set_(true) {} 93 94EcmDescriptor::~EcmDescriptor() {} 95 96status_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 117EcmContainer::EcmContainer() : count_(0), count_set_(false) {} 118 119EcmContainer::~EcmContainer() {} 120 121status_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 143status_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