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 "ClearKeyFetcher" 19791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang 20791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang#include <algorithm> 21b01fb48fcc755d6bfad9bc94d8c227349155e1b5Chong Zhang#include <inttypes.h> 22791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang#include <string> 23791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang 24791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang#include "ClearKeyFetcher.h" 25791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang#include "ecm.h" 26791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang#include "LicenseFetcher.h" 27791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang 28791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang#include <media/stagefright/foundation/ADebug.h> 29791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang#include <utils/Log.h> 30791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang 31791a1a206b56be8601a6fffd2614926e67d64790Chong Zhangnamespace android { 32791a1a206b56be8601a6fffd2614926e67d64790Chong Zhangnamespace clearkeycas { 33791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang 34791a1a206b56be8601a6fffd2614926e67d64790Chong ZhangClearKeyFetcher::ClearKeyFetcher( 35791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang std::unique_ptr<LicenseFetcher> license_fetcher) : 36791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang initialized_(false), 37791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang license_fetcher_(std::move(license_fetcher)) { 38791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang CHECK(license_fetcher_); 39791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang} 40791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang 41791a1a206b56be8601a6fffd2614926e67d64790Chong ZhangClearKeyFetcher::~ClearKeyFetcher() {} 42791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang 43791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang// This is a no-op but other KeyFetcher subclasses require initialization 44791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang// so this is necessary to preserve the contract. 45791a1a206b56be8601a6fffd2614926e67d64790Chong Zhangstatus_t ClearKeyFetcher::Init() { 46791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang initialized_ = true; 47791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang return OK; 48791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang} 49791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang 50791a1a206b56be8601a6fffd2614926e67d64790Chong Zhangstatus_t ClearKeyFetcher::ObtainKey(const sp<ABuffer>& buffer, 51791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang uint64_t* asset_id, std::vector<KeyInfo>* keys) { 52791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang CHECK(asset_id); 53791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang CHECK(keys); 54791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang CHECK(initialized_); 55791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang *asset_id = 0; 56791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang keys->clear(); 57791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang 58791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang EcmContainer container; 59791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang status_t status = container.Parse(buffer); 60791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang if (status != OK) { 61791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang return status; 62791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang } 63791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang ALOGV("descriptor_size=%zu", container.descriptor_size()); 64791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang 65791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang // Sanity check to verify that the BroadcastEncryptor is sending a properly 66791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang // formed EcmContainer. If it contains two Ecms, the ids should have different 67791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang // parity (one odd, one even). This does not necessarily affect decryption 68791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang // but indicates a problem with Ecm generation. 69791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang if (container.descriptor_size() == 2) { 70791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang // XOR the least significant bits to verify different parity. 71791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang bool same_parity = (((container.descriptor(0).id() & 0x01) ^ 72791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang (container.descriptor(1).id() & 0x01)) == 0); 73791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang if (same_parity) { 74b01fb48fcc755d6bfad9bc94d8c227349155e1b5Chong Zhang ALOGW("asset_id=%" PRIu64 ": malformed Ecm, " 75791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang "content keys have same parity, id0=%d, id1=%d", 76791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang container.descriptor(0).ecm().asset_id(), 77791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang container.descriptor(0).id(), 78791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang container.descriptor(1).id()); 79791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang } 80791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang } 81791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang 82791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang *asset_id = container.descriptor(0).ecm().asset_id(); 83791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang 84791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang // Detect asset_id change. This could be caused by a configuration change 85791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang // in the BroadcastEncryptor. This is unusual so log it in case it is an 86791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang // operational mistake. This invalidates the current asset_key causing a 87791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang // new license to be fetched. 88791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang // TODO(rkint): test against BroadcastEncryptor to verify what BE sends on 89791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang // asset_id change. If it sends an EcmContainer with 2 Ecms with different 90791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang // asset_ids (old and new) then it might be best to prefetch the Emm. 91791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang if ((asset_.id() != 0) && (*asset_id != asset_.id())) { 92843328ff13456dbdfca72e3825222bcc65f4fac3George Burgess IV ALOGW("Asset_id change from %llu to %" PRIu64, asset_.id(), *asset_id); 93791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang asset_.Clear(); 94791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang } 95791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang 96791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang // Fetch license to get asset_id 97791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang if (!asset_.has_id()) { 98791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang status = license_fetcher_->FetchLicense(*asset_id, &asset_); 99791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang if (status != OK) { 100791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang *asset_id = 0; 101791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang return status; 102791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang } 103791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang ALOGV("FetchLicense succeeded, has_id=%d", asset_.has_id()); 104791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang } 105791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang keys->resize(container.descriptor_size()); 106791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang 107791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang for (size_t i = 0; i < container.descriptor_size(); ++i) { 108791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang status = container.mutable_descriptor(i)->mutable_ecm()->Decrypt( 109791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang container.descriptor(i).ecm().buffer(), asset_); 110791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang if (status != OK) { 111791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang *asset_id = 0; 112791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang keys->clear(); 113791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang return status; 114791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang } 115791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang // TODO: if 2 Ecms have same parity, key from Ecm with higher id 116791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang // should be keys[1]. 117791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang KeyInfo key; 118791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang key.key_id = container.descriptor(i).id(); 119791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang key.key_bytes = container.descriptor(i).ecm().content_key(); 120791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang 121791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang keys->at(key.key_id & 1) = key; 122791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang } 123791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang return OK; 124791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang} 125791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang 126791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang} // namespace clearkeycas 127791a1a206b56be8601a6fffd2614926e67d64790Chong Zhang} // namespace android 128