/* * Copyright (C) 2017 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ //#define LOG_NDEBUG 0 #define LOG_TAG "ecm_generator" #include "ecm_generator.h" #include #include #include #include "protos/license_protos.pb.h" #include #include #include #include namespace android { namespace clearkeycas { // These constants are internal to this module. const uint16_t kEcmClearFieldsSize = 16; const uint32_t kContentKeyByteSize = 16; const uint16_t kTotalEcmSize = kEcmClearFieldsSize + kContentKeyByteSize; // clear fields + clear key #define UNALIGNED_LOAD32(_p) (*reinterpret_cast(_p)) static uint32_t Load32(const void *p) { return ntohl(UNALIGNED_LOAD32(p)); } static uint32_t LoadNext32(const uint8_t** pptr) { CHECK(pptr); CHECK(*pptr); const uint8_t* p = *pptr; *pptr += sizeof(uint32_t); return Load32(p); } namespace ecm_generator { status_t DecodeECM(const sp& ecm, Asset* asset, sp *content_key, DefaultEcmFields* default_fields) { CHECK(asset); CHECK(content_key); CHECK(default_fields); status_t status = DecodeECMClearFields(ecm, asset, default_fields); if (status != OK) { return status; } const uint8_t* ptr = ecm->data() + kEcmClearFieldsSize; *content_key = new ABuffer(kContentKeyByteSize); memcpy((*content_key)->data(), ptr, kContentKeyByteSize); return OK; } status_t DecodeECMClearFields(const sp& ecm, Asset* asset, DefaultEcmFields* default_fields) { CHECK(asset); CHECK(default_fields); if (ecm->size() < kTotalEcmSize) { ALOGE("Short ECM: expected_length=%d, actual_length=%zu", kTotalEcmSize, ecm->size()); return BAD_VALUE; } const uint8_t* ptr = ecm->data(); default_fields->old_version = LoadNext32(&ptr); default_fields->clear_lead = LoadNext32(&ptr); default_fields->system_id = LoadNext32(&ptr); // The real ecm version is hidden in the system id. default_fields->ecm_version = (default_fields->system_id >> 24) & 0xFF; default_fields->system_id &= 0x00FFFFFF; if (default_fields->system_id == 0) { ALOGE("Ecm has invalid system_id 0"); return CLEARKEY_STATUS_INVALIDSYSTEMID; } asset->set_id(LoadNext32(&ptr)); if (asset->id() == 0) { ALOGE("Ecm has invalid asset_id 0"); return CLEARKEY_STATUS_INVALIDASSETID; } return OK; } } // namespace ecm_generator } // namespace clearkeycas } // namespace android