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//#define LOG_NDEBUG 0 18791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang#define LOG_TAG "ecm" 19791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang 20791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang#include "ecm.h" 21791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang#include "ecm_generator.h" 22791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang#include "protos/license_protos.pb.h" 23791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang 24791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang#include <media/stagefright/foundation/ADebug.h> 25791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang#include <media/stagefright/MediaErrors.h> 26791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang#include <utils/Log.h> 27791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang 28791a1a206b56be8601a6fffd2614926e67d64790Chong Zhangnamespace android { 29791a1a206b56be8601a6fffd2614926e67d64790Chong Zhangnamespace clearkeycas { 30791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang 31791a1a206b56be8601a6fffd2614926e67d64790Chong ZhangEcm::Ecm() 32791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang : asset_id_(0), 33791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang asset_id_set_(false), 34791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang system_id_(0), 35791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang system_id_set_(false) {} 36791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang 37791a1a206b56be8601a6fffd2614926e67d64790Chong ZhangEcm::~Ecm() {} 38791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang 39791a1a206b56be8601a6fffd2614926e67d64790Chong Zhangstatus_t Ecm::Parse(const sp<ABuffer>& buffer_as_binary) { 40791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang if (buffer_as_binary->size() < kSizeBytes) { 41791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang ALOGE("Short Ecm buffer: expected %zu, received %zu.", 42791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang kSizeBytes, buffer_as_binary->size()); 43791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang return BAD_VALUE; 44791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang } 45791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang 46791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang Asset asset; 47791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang ecm_generator::DefaultEcmFields default_fields; 48791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang status_t status = ecm_generator::DecodeECMClearFields( 49791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang buffer_as_binary, &asset, &default_fields); 50791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang if (status != OK) { 51791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang ALOGE("DecodeECMClearFields failed with status %d", status); 52791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang return status; 53791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang } 54791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang set_asset_id(asset.id()); 55791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang set_system_id(default_fields.system_id); 56791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang 57791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang // Save a copy of the buffer_as_binary for a future DecryptEcm call. 58791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang set_buffer(buffer_as_binary); 59791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang return OK; 60791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang} 61791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang 62791a1a206b56be8601a6fffd2614926e67d64790Chong Zhangstatus_t Ecm::Decrypt( 63791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang const sp<ABuffer>& buffer_as_binary, 64791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang const Asset& asset_from_emm) { 65791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang // Invariant: asset has id. These are postconditions for Emm::Decrypt(). 66791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang CHECK(asset_from_emm.has_id()); 67791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang 68791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang // DecodeEcm fills in |asset|.id() with the asset_id from the encoded Ecm. 69791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang Asset asset(asset_from_emm); 70791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang ecm_generator::DefaultEcmFields default_fields; 71791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang sp<ABuffer> content_key; 72791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang status_t status = ecm_generator::DecodeECM( 73791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang buffer_as_binary, &asset, &content_key, &default_fields); 74791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang if (status != OK) { 75791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang ALOGE("DecodeECM failed with status %d", status); 76791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang return status; 77791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang } 78791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang if (asset.id() != asset_from_emm.id()) { 79791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang ALOGE("Asset_id from Emm (%llu) does not match asset_id from Ecm (%llu).", 80791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang asset_from_emm.id(), asset.id()); 81791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang return CLEARKEY_STATUS_INVALID_PARAMETER; 82791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang } 83791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang set_asset_id(asset.id()); 84791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang set_system_id(default_fields.system_id); 85791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang set_content_key(content_key); 86791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang return status; 87791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang} 88791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang 89791a1a206b56be8601a6fffd2614926e67d64790Chong ZhangEcmDescriptor::EcmDescriptor() : ecm_set_(false), id_(0), id_set_(false) {} 90791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang 91791a1a206b56be8601a6fffd2614926e67d64790Chong ZhangEcmDescriptor::EcmDescriptor(uint16_t id, const Ecm& ecm) 92791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang: ecm_(ecm), ecm_set_(true), id_(id), id_set_(true) {} 93791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang 94791a1a206b56be8601a6fffd2614926e67d64790Chong ZhangEcmDescriptor::~EcmDescriptor() {} 95791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang 96791a1a206b56be8601a6fffd2614926e67d64790Chong Zhangstatus_t EcmDescriptor::Parse(const sp<ABuffer>& buffer_as_binary) { 97791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang if (buffer_as_binary->size() < kSizeBytes) { 98791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang ALOGE("Short EcmDescriptor buffer: expected %zu, received %zu.", 99791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang kSizeBytes, buffer_as_binary->size()); 100791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang return BAD_VALUE; 101791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang } 102791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang sp<ABuffer> id_buffer = new ABuffer(buffer_as_binary->data(), kIdSizeBytes); 103791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang const uint8_t *id_bytes = id_buffer->data(); 104791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang uint16_t id = (id_bytes[0] << 8) | id_bytes[1]; 105791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang set_id(id); 106791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang 107791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang // Unmarshall the contained Ecm. 108791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang sp<ABuffer> ecm_buffer = new ABuffer( 109791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang buffer_as_binary->data() + kIdSizeBytes, Ecm::kSizeBytes); 110791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang status_t status = mutable_ecm()->Parse(ecm_buffer); 111791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang if (status != OK) { 112791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang return status; 113791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang } 114791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang return OK; 115791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang} 116791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang 117791a1a206b56be8601a6fffd2614926e67d64790Chong ZhangEcmContainer::EcmContainer() : count_(0), count_set_(false) {} 118791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang 119791a1a206b56be8601a6fffd2614926e67d64790Chong ZhangEcmContainer::~EcmContainer() {} 120791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang 121791a1a206b56be8601a6fffd2614926e67d64790Chong Zhangstatus_t EcmContainer::Add(const EcmDescriptor& descriptor) { 122791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang switch (count_) { 123791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang case 0: 124791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang descriptor_[0] = descriptor; 125791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang count_ = 1; 126791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang break; 127791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang case 1: 128791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang descriptor_[1] = descriptor; 129791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang count_ = 2; 130791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang break; 131791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang case 2: 132791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang descriptor_[0] = descriptor_[1]; 133791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang descriptor_[1] = descriptor; 134791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang break; 135791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang default: 136791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang ALOGE("Bad state."); 137791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang return INVALID_OPERATION; 138791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang } 139791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang count_set_ = true; 140791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang return OK; 141791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang} 142791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang 143791a1a206b56be8601a6fffd2614926e67d64790Chong Zhangstatus_t EcmContainer::Parse(const sp<ABuffer>& buffer_as_binary) { 144791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang // EcmContainer can contain 1 or 2 EcmDescriptors so this is a check for 145791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang // minimum size. 146791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang if (buffer_as_binary->size() < kMinimumSizeBytes) { 147791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang ALOGE("Short EcmContainer buffer: expected >= %zu, received %zu.", 148791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang kMinimumSizeBytes, buffer_as_binary->size()); 149791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang return BAD_VALUE; 150791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang } 151791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang 152791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang sp<ABuffer> count_buffer = new ABuffer( 153791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang buffer_as_binary->data(), kCountSizeBytes); 154791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang const uint8_t *count_bytes = count_buffer->data(); 155791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang size_t count = (count_bytes[0] << 8) | count_bytes[1]; 156791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang // Check that count is a legal value. 157791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang if (!CountLegal(count)) { 158791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang ALOGE("Invalid descriptor count: expected %zu <= count <= %zu, received %zu.", 159791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang kMinDescriptorCount, kMaxDescriptorCount, count); 160791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang return ERROR_OUT_OF_RANGE; 161791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang } 162791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang // If needed, check that buffer_as_binary can hold 2 EcmDescriptors. 163791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang if (count > kMinDescriptorCount) { 164791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang size_t expected_bytes = 165791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang kCountSizeBytes + (count * EcmDescriptor::kSizeBytes); 166791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang if (buffer_as_binary->size() < expected_bytes) { 167791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang ALOGE("Short EcmContainer buffer: expected %zu, received %zu.", 168791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang expected_bytes, buffer_as_binary->size()); 169791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang return BAD_VALUE; 170791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang } 171791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang } 172791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang set_count(count); 173791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang // Unmarshall the contained EcmDescriptors. 174791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang size_t offset = kCountSizeBytes; 175791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang for (size_t i = 0; i < count_; ++i) { 176791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang sp<ABuffer> descriptor_buffer = new ABuffer( 177791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang buffer_as_binary->data() + offset, EcmDescriptor::kSizeBytes); 178791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang status_t status = mutable_descriptor(i)->Parse(descriptor_buffer); 179791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang if (status != OK) { 180791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang return status; 181791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang } 182791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang offset += EcmDescriptor::kSizeBytes; 183791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang } 184791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang return OK; 185791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang} 186791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang 187791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang} // namespace clearkeycas 188791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang} // namespace android 189