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