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
17 #include "VehicleBindingUtil.h"
18
19 #include <android-base/chrono_utils.h>
20 #include <android-base/logging.h>
21 #include <binder/IServiceManager.h>
22 #include <binder/Status.h>
23
24 #include <IVhalClient.h>
25
26 #include <iostream>
27 #include <map>
28 #include <string>
29 #include <thread> // NOLINT(build/c++11)
30
31 namespace {
32
33 using ::android::defaultServiceManager;
34 using ::android::automotive::security::BindingStatus;
35 using ::android::automotive::security::DefaultCsrng;
36 using ::android::automotive::security::DefaultExecutor;
37 using ::android::frameworks::automotive::vhal::IVhalClient;
38
39 static int printHelp(int argc, char* argv[]);
40 static int setBinding(int /*argc*/, char*[] /*argv*/);
41
42 constexpr int64_t SLEEP_TIME_MILLISECONDS = 100;
43 constexpr int64_t TIMEOUT_MILLISECONDS = 30000;
44
45 // Avoid calling complex destructor on cleanup.
46 const auto& subcommandTable = *new std::map<std::string, std::function<int(int, char*[])>>{
47 {"help", printHelp},
48 {"set_binding", setBinding},
49 };
50
setBinding(int,char * [])51 static int setBinding(int /*argc*/, char*[] /*argv*/) {
52 std::shared_ptr<IVhalClient> service = IVhalClient::tryCreate();
53 size_t retryCount = 0;
54 while (service == nullptr && retryCount < TIMEOUT_MILLISECONDS / SLEEP_TIME_MILLISECONDS) {
55 service = IVhalClient::tryCreate();
56 std::this_thread::sleep_for(std::chrono::milliseconds(SLEEP_TIME_MILLISECONDS));
57 retryCount++;
58 }
59
60 if (service == nullptr) {
61 LOG(ERROR) << "Timeout waiting for VHAL";
62 return static_cast<int>(BindingStatus::WAIT_VHAL_TIMEOUT);
63 }
64
65 auto status = setVehicleBindingSeed(service, DefaultExecutor{}, DefaultCsrng{});
66 if (status != BindingStatus::OK) {
67 LOG(ERROR) << "Unable to set the binding seed. Encryption keys are not "
68 << "bound to the platform.";
69 return static_cast<int>(status);
70 }
71
72 return 0;
73 }
74
printHelp(int,char * argv[])75 static int printHelp(int /*argc*/, char* argv[]) {
76 std::cout << "Usage: " << argv[0] << " <subcommand> [args]" << std::endl
77 << "Valid subcommands: " << std::endl;
78 for (const auto& i : subcommandTable) {
79 std::cout << " " << i.first << std::endl;
80 }
81 return 0;
82 }
83
84 } // namespace
85
main(int argc,char * argv[])86 int main(int argc, char* argv[]) {
87 setenv("ANDROID_LOG_TAGS", "*:v", 1);
88 android::base::InitLogging(argv,
89 (getppid() == 1) ? &android::base::KernelLogger
90 : &android::base::StderrLogger);
91 if (argc < 2) {
92 LOG(ERROR) << "Please specify a subcommand.";
93 printHelp(argc, argv);
94 return -1;
95 }
96
97 auto subcommand = subcommandTable.find(argv[1]);
98 if (subcommand == subcommandTable.end()) {
99 LOG(ERROR) << "Invalid subcommand: " << argv[1];
100 printHelp(argc, argv);
101 return -1;
102 }
103
104 return subcommand->second(argc, argv);
105 }
106