blob: 417ff4aab1e5cb0c2938b44e8de976d09262086a [file] [log] [blame]
Jiyong Parka7266ac2021-05-17 21:57:24 +09001/*
2 * Copyright (C) 2021 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 */
Andrew Scull2e6ab792022-01-30 16:04:08 +000016#include <aidl/android/security/dice/IDiceNode.h>
Inseob Kim06a64d62021-09-07 21:21:45 +090017#include <aidl/android/system/virtualmachineservice/IVirtualMachineService.h>
18#include <aidl/com/android/microdroid/testservice/BnTestService.h>
Inseob Kimdb319702022-01-20 13:12:43 +090019#include <android-base/file.h>
Inseob Kim691df6a2022-01-20 12:54:30 +090020#include <android-base/properties.h>
Andrew Scull11cf0902021-06-22 12:08:10 +000021#include <android-base/result.h>
Andrew Scull66616612021-06-17 16:41:03 +000022#include <android/binder_auto_utils.h>
23#include <android/binder_manager.h>
Inseob Kim06a64d62021-09-07 21:21:45 +090024#include <fcntl.h>
Inseob Kimdb319702022-01-20 13:12:43 +090025#include <fsverity_digests.pb.h>
Inseob Kim06a64d62021-09-07 21:21:45 +090026#include <linux/vm_sockets.h>
27#include <stdint.h>
Jiyong Parka7266ac2021-05-17 21:57:24 +090028#include <stdio.h>
Inseob Kim06a64d62021-09-07 21:21:45 +090029#include <sys/ioctl.h>
Jiyong Park23934392021-06-16 01:59:10 +090030#include <sys/system_properties.h>
Inseob Kim06a64d62021-09-07 21:21:45 +090031#include <unistd.h>
32
33#include <binder_rpc_unstable.hpp>
Inseob Kim691df6a2022-01-20 12:54:30 +090034#include <string>
Jiyong Parka7266ac2021-05-17 21:57:24 +090035
Andrew Scull2e6ab792022-01-30 16:04:08 +000036using aidl::android::hardware::security::dice::BccHandover;
37using aidl::android::security::dice::IDiceNode;
38
Inseob Kim06a64d62021-09-07 21:21:45 +090039using aidl::android::system::virtualmachineservice::IVirtualMachineService;
40
41using android::base::ErrnoError;
Andrew Scull11cf0902021-06-22 12:08:10 +000042using android::base::Error;
43using android::base::Result;
Andrew Scull66616612021-06-17 16:41:03 +000044
Jiyong Parkfe5b28e2021-06-24 00:19:02 +090045extern void testlib_sub();
46
Andrew Scull66616612021-06-17 16:41:03 +000047namespace {
48
Andrew Scull11cf0902021-06-22 12:08:10 +000049template <typename T>
Andrew Sculledbe75e2021-07-06 10:44:31 +000050Result<T> report_test(std::string name, Result<T> result) {
Andrew Scull11cf0902021-06-22 12:08:10 +000051 auto property = "debug.microdroid.test." + name;
52 std::stringstream outcome;
53 if (result.ok()) {
54 outcome << "PASS";
55 } else {
56 outcome << "FAIL: " << result.error();
Inseob Kimdb319702022-01-20 13:12:43 +090057 // Pollute stderr with the error in case the property is truncated.
58 std::cerr << "[" << name << "] test failed: " << result.error() << "\n";
Andrew Scull11cf0902021-06-22 12:08:10 +000059 }
60 __system_property_set(property.c_str(), outcome.str().c_str());
Andrew Sculledbe75e2021-07-06 10:44:31 +000061 return result;
Andrew Scull66616612021-06-17 16:41:03 +000062}
63
Inseob Kim06a64d62021-09-07 21:21:45 +090064Result<void> start_test_service() {
65 class TestService : public aidl::com::android::microdroid::testservice::BnTestService {
66 ndk::ScopedAStatus addInteger(int32_t a, int32_t b, int32_t* out) override {
67 *out = a + b;
68 return ndk::ScopedAStatus::ok();
69 }
Inseob Kim691df6a2022-01-20 12:54:30 +090070
71 ndk::ScopedAStatus readProperty(const std::string& prop, std::string* out) override {
72 *out = android::base::GetProperty(prop, "");
73 if (out->empty()) {
74 std::string msg = "cannot find property " + prop;
75 return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_SERVICE_SPECIFIC,
76 msg.c_str());
77 }
78
79 return ndk::ScopedAStatus::ok();
80 }
Andrew Scull2e6ab792022-01-30 16:04:08 +000081
82 ndk::ScopedAStatus insecurelyExposeSecret(std::vector<uint8_t>* out) override {
83 ndk::SpAIBinder binder(AServiceManager_getService("android.security.dice.IDiceNode"));
84 auto service = IDiceNode::fromBinder(binder);
85 if (service == nullptr) {
86 return ndk::ScopedAStatus::
87 fromServiceSpecificErrorWithMessage(0, "Failed to find diced");
88 }
89 BccHandover handover;
90 auto deriveStatus = service->derive({}, &handover);
91 if (!deriveStatus.isOk()) {
92 return ndk::ScopedAStatus::fromServiceSpecificErrorWithMessage(0,
93 "Failed call diced");
94 }
95 *out = {handover.cdiSeal.begin(), handover.cdiSeal.end()};
96 return ndk::ScopedAStatus::ok();
97 }
Inseob Kim06a64d62021-09-07 21:21:45 +090098 };
99 auto testService = ndk::SharedRefBase::make<TestService>();
100
101 auto callback = []([[maybe_unused]] void* param) {
102 // Tell microdroid_manager that we're ready.
103 // Failing to notify is not a fatal error; the payload can continue.
104 ndk::SpAIBinder binder(
105 RpcClient(VMADDR_CID_HOST, IVirtualMachineService::VM_BINDER_SERVICE_PORT));
106 auto virtualMachineService = IVirtualMachineService::fromBinder(binder);
107 if (virtualMachineService == nullptr) {
108 std::cerr << "failed to connect VirtualMachineService";
109 return;
110 }
Inseob Kimc7d28c72021-10-25 14:28:10 +0000111 if (!virtualMachineService->notifyPayloadReady().isOk()) {
Inseob Kim06a64d62021-09-07 21:21:45 +0900112 std::cerr << "failed to notify payload ready to virtualizationservice";
113 }
114 };
115
116 if (!RunRpcServerCallback(testService->asBinder().get(), testService->SERVICE_PORT, callback,
117 nullptr)) {
118 return Error() << "RPC Server failed to run";
119 }
120
121 return {};
122}
123
Inseob Kimdb319702022-01-20 13:12:43 +0900124Result<void> verify_apk() {
125 const char* path = "/mnt/extra-apk/0/assets/build_manifest.pb";
126
127 std::string str;
128 if (!android::base::ReadFileToString(path, &str)) {
129 return ErrnoError() << "failed to read build_manifest.pb";
130 }
131
132 if (!android::security::fsverity::FSVerityDigests().ParseFromString(str)) {
133 return Error() << "invalid build_manifest.pb";
134 }
135
136 return {};
137}
138
Andrew Scull66616612021-06-17 16:41:03 +0000139} // Anonymous namespace
140
Jiyong Park40699612021-05-24 16:55:06 +0900141extern "C" int android_native_main(int argc, char* argv[]) {
Inseob Kim06a64d62021-09-07 21:21:45 +0900142 // disable buffering to communicate seamlessly
143 setvbuf(stdin, nullptr, _IONBF, 0);
144 setvbuf(stdout, nullptr, _IONBF, 0);
145 setvbuf(stderr, nullptr, _IONBF, 0);
146
Jiyong Park40699612021-05-24 16:55:06 +0900147 printf("Hello Microdroid ");
148 for (int i = 0; i < argc; i++) {
149 printf("%s", argv[i]);
150 bool last = i == (argc - 1);
151 if (!last) {
152 printf(" ");
153 }
154 }
Jiyong Parkfe5b28e2021-06-24 00:19:02 +0900155 testlib_sub();
Jiyong Park40699612021-05-24 16:55:06 +0900156 printf("\n");
Jiyong Park23934392021-06-16 01:59:10 +0900157
Inseob Kimdb319702022-01-20 13:12:43 +0900158 // Extra apks may be missing; this is not a fatal error
159 report_test("extra_apk", verify_apk());
160
Jiyong Park23934392021-06-16 01:59:10 +0900161 __system_property_set("debug.microdroid.app.run", "true");
Andrew Sculledbe75e2021-07-06 10:44:31 +0000162
Inseob Kim06a64d62021-09-07 21:21:45 +0900163 if (auto res = start_test_service(); res.ok()) {
164 return 0;
165 } else {
166 std::cerr << "starting service failed: " << res.error();
167 return 1;
168 }
Jiyong Parka7266ac2021-05-17 21:57:24 +0900169}