• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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  */
16 #include <aidl/android/security/dice/IDiceNode.h>
17 #include <aidl/android/system/virtualmachineservice/IVirtualMachineService.h>
18 #include <aidl/com/android/microdroid/testservice/BnTestService.h>
19 #include <android-base/file.h>
20 #include <android-base/properties.h>
21 #include <android-base/result.h>
22 #include <android/binder_auto_utils.h>
23 #include <android/binder_manager.h>
24 #include <fcntl.h>
25 #include <fsverity_digests.pb.h>
26 #include <linux/vm_sockets.h>
27 #include <stdint.h>
28 #include <stdio.h>
29 #include <sys/ioctl.h>
30 #include <sys/system_properties.h>
31 #include <unistd.h>
32 
33 #include <binder_rpc_unstable.hpp>
34 #include <string>
35 
36 using aidl::android::hardware::security::dice::BccHandover;
37 using aidl::android::security::dice::IDiceNode;
38 
39 using aidl::android::system::virtualmachineservice::IVirtualMachineService;
40 
41 using android::base::ErrnoError;
42 using android::base::Error;
43 using android::base::Result;
44 
45 extern void testlib_sub();
46 
47 namespace {
48 
49 template <typename T>
report_test(std::string name,Result<T> result)50 Result<T> report_test(std::string name, Result<T> result) {
51     auto property = "debug.microdroid.test." + name;
52     std::stringstream outcome;
53     if (result.ok()) {
54         outcome << "PASS";
55     } else {
56         outcome << "FAIL: " << result.error();
57         // Pollute stderr with the error in case the property is truncated.
58         std::cerr << "[" << name << "] test failed: " << result.error() << "\n";
59     }
60     __system_property_set(property.c_str(), outcome.str().c_str());
61     return result;
62 }
63 
start_test_service()64 Result<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         }
70 
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         }
81 
82         ndk::ScopedAStatus insecurelyExposeSealingCdi(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         }
98 
99         ndk::ScopedAStatus insecurelyExposeAttestationCdi(std::vector<uint8_t>* out) override {
100             ndk::SpAIBinder binder(AServiceManager_getService("android.security.dice.IDiceNode"));
101             auto service = IDiceNode::fromBinder(binder);
102             if (service == nullptr) {
103                 return ndk::ScopedAStatus::
104                         fromServiceSpecificErrorWithMessage(0, "Failed to find diced");
105             }
106             BccHandover handover;
107             auto deriveStatus = service->derive({}, &handover);
108             if (!deriveStatus.isOk()) {
109                 return ndk::ScopedAStatus::fromServiceSpecificErrorWithMessage(0,
110                                                                                "Failed call diced");
111             }
112             *out = {handover.cdiAttest.begin(), handover.cdiAttest.end()};
113             return ndk::ScopedAStatus::ok();
114         }
115 
116         ndk::ScopedAStatus getBcc(std::vector<uint8_t>* out) override {
117             ndk::SpAIBinder binder(AServiceManager_getService("android.security.dice.IDiceNode"));
118             auto service = IDiceNode::fromBinder(binder);
119             if (service == nullptr) {
120                 return ndk::ScopedAStatus::
121                         fromServiceSpecificErrorWithMessage(0, "Failed to find diced");
122             }
123             BccHandover handover;
124             auto deriveStatus = service->derive({}, &handover);
125             if (!deriveStatus.isOk()) {
126                 return ndk::ScopedAStatus::fromServiceSpecificErrorWithMessage(0,
127                                                                                "Failed call diced");
128             }
129             *out = {handover.bcc.data.begin(), handover.bcc.data.end()};
130             return ndk::ScopedAStatus::ok();
131         }
132     };
133     auto testService = ndk::SharedRefBase::make<TestService>();
134 
135     auto callback = []([[maybe_unused]] void* param) {
136         // Tell microdroid_manager that we're ready.
137         // Failing to notify is not a fatal error; the payload can continue.
138         ndk::SpAIBinder binder(
139                 RpcClient(VMADDR_CID_HOST, IVirtualMachineService::VM_BINDER_SERVICE_PORT));
140         auto virtualMachineService = IVirtualMachineService::fromBinder(binder);
141         if (virtualMachineService == nullptr) {
142             std::cerr << "failed to connect VirtualMachineService";
143             return;
144         }
145         if (!virtualMachineService->notifyPayloadReady().isOk()) {
146             std::cerr << "failed to notify payload ready to virtualizationservice";
147         }
148     };
149 
150     if (!RunRpcServerCallback(testService->asBinder().get(), testService->SERVICE_PORT, callback,
151                               nullptr)) {
152         return Error() << "RPC Server failed to run";
153     }
154 
155     return {};
156 }
157 
verify_apk()158 Result<void> verify_apk() {
159     const char* path = "/mnt/extra-apk/0/assets/build_manifest.pb";
160 
161     std::string str;
162     if (!android::base::ReadFileToString(path, &str)) {
163         return ErrnoError() << "failed to read build_manifest.pb";
164     }
165 
166     if (!android::security::fsverity::FSVerityDigests().ParseFromString(str)) {
167         return Error() << "invalid build_manifest.pb";
168     }
169 
170     return {};
171 }
172 
173 } // Anonymous namespace
174 
android_native_main(int argc,char * argv[])175 extern "C" int android_native_main(int argc, char* argv[]) {
176     // disable buffering to communicate seamlessly
177     setvbuf(stdin, nullptr, _IONBF, 0);
178     setvbuf(stdout, nullptr, _IONBF, 0);
179     setvbuf(stderr, nullptr, _IONBF, 0);
180 
181     printf("Hello Microdroid ");
182     for (int i = 0; i < argc; i++) {
183         printf("%s", argv[i]);
184         bool last = i == (argc - 1);
185         if (!last) {
186             printf(" ");
187         }
188     }
189     testlib_sub();
190     printf("\n");
191 
192     // Extra apks may be missing; this is not a fatal error
193     report_test("extra_apk", verify_apk());
194 
195     __system_property_set("debug.microdroid.app.run", "true");
196 
197     if (auto res = start_test_service(); res.ok()) {
198         return 0;
199     } else {
200         std::cerr << "starting service failed: " << res.error();
201         return 1;
202     }
203 }
204