1 /*
2 * Copyright 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 <aidl/android/hardware/drm/IDrmFactory.h>
18 #include <aidl/android/hardware/security/keymint/IRemotelyProvisionedComponent.h>
19 #include <android/binder_manager.h>
20 #include <cppbor.h>
21 #include <gflags/gflags.h>
22 #include <keymaster/cppcose/cppcose.h>
23 #include <openssl/base64.h>
24 #include <remote_prov/remote_prov_utils.h>
25 #include <sys/random.h>
26
27 #include <future>
28 #include <string>
29 #include <unordered_set>
30 #include <vector>
31
32 #include "DrmRkpAdapter.h"
33 #include "rkp_factory_extraction_lib.h"
34
35 using aidl::android::hardware::drm::IDrmFactory;
36 using aidl::android::hardware::security::keymint::IRemotelyProvisionedComponent;
37 using aidl::android::hardware::security::keymint::RpcHardwareInfo;
38 using aidl::android::hardware::security::keymint::remote_prov::jsonEncodeCsrWithBuild;
39 using aidl::android::hardware::security::keymint::remote_prov::RKPVM_INSTANCE_NAME;
40
41 DEFINE_string(output_format, "build+csr", "How to format the output. Defaults to 'build+csr'.");
42 DEFINE_bool(self_test, true,
43 "If true, this tool performs a self-test, validating the payload for correctness. "
44 "This checks that the device on the factory line is producing valid output "
45 "before attempting to upload the output to the device info service.");
46 DEFINE_bool(allow_degenerate, true,
47 "If true, self_test validation will allow degenerate DICE chains in the CSR.");
48 DEFINE_string(serialno_prop, "ro.serialno",
49 "The property of getting serial number. Defaults to 'ro.serialno'.");
50 DEFINE_string(require_uds_certs, "",
51 "The comma-delimited names of remotely provisioned "
52 "components whose UDS certificate chains are required to be present in the CSR. "
53 "Example: avf,default,strongbox");
54
55 namespace {
56
57 // Various supported --output_format values.
58 constexpr std::string_view kBinaryCsrOutput = "csr"; // Just the raw csr as binary
59 constexpr std::string_view kBuildPlusCsr = "build+csr"; // Text-encoded (JSON) build
60 // fingerprint plus CSR.
61
getFullServiceName(const char * descriptor,const char * name)62 std::string getFullServiceName(const char* descriptor, const char* name) {
63 return std::string(descriptor) + "/" + name;
64 }
65
writeOutput(const std::string instance_name,const cppbor::Array & csr)66 void writeOutput(const std::string instance_name, const cppbor::Array& csr) {
67 if (FLAGS_output_format == kBinaryCsrOutput) {
68 auto bytes = csr.encode();
69 std::copy(bytes.begin(), bytes.end(), std::ostream_iterator<char>(std::cout));
70 } else if (FLAGS_output_format == kBuildPlusCsr) {
71 auto [json, error] = jsonEncodeCsrWithBuild(instance_name, csr, FLAGS_serialno_prop);
72 if (!error.empty()) {
73 std::cerr << "Error JSON encoding the output: " << error << std::endl;
74 exit(-1);
75 }
76 std::cout << json << std::endl;
77 } else {
78 std::cerr << "Unexpected output_format '" << FLAGS_output_format << "'" << std::endl;
79 std::cerr << "Valid formats:" << std::endl;
80 std::cerr << " " << kBinaryCsrOutput << std::endl;
81 std::cerr << " " << kBuildPlusCsr << std::endl;
82 exit(-1);
83 }
84 }
85
getCsrForIRpc(const char * descriptor,const char * name,IRemotelyProvisionedComponent * irpc,bool requireUdsCerts)86 void getCsrForIRpc(const char* descriptor, const char* name, IRemotelyProvisionedComponent* irpc,
87 bool requireUdsCerts) {
88 auto fullName = getFullServiceName(descriptor, name);
89 // AVF RKP HAL is not always supported, so we need to check if it is supported before
90 // generating the CSR.
91 if (fullName == RKPVM_INSTANCE_NAME) {
92 RpcHardwareInfo hwInfo;
93 auto status = irpc->getHardwareInfo(&hwInfo);
94 if (!status.isOk()) {
95 return;
96 }
97 }
98
99 auto [request, errMsg] =
100 getCsr(name, irpc, FLAGS_self_test, FLAGS_allow_degenerate, requireUdsCerts);
101 if (!request) {
102 std::cerr << "Unable to build CSR for '" << fullName << "': " << errMsg << ", exiting."
103 << std::endl;
104 exit(-1);
105 }
106
107 writeOutput(std::string(name), *request);
108 }
109
110 // Callback for AServiceManager_forEachDeclaredInstance that writes out a CSR
111 // for every IRemotelyProvisionedComponent.
getCsrForInstance(const char * name,void * context)112 void getCsrForInstance(const char* name, void* context) {
113 auto fullName = getFullServiceName(IRemotelyProvisionedComponent::descriptor, name);
114 std::future<AIBinder*> waitForServiceFunc =
115 std::async(std::launch::async, AServiceManager_waitForService, fullName.c_str());
116 if (waitForServiceFunc.wait_for(std::chrono::seconds(10)) == std::future_status::timeout) {
117 std::cerr << "Wait for service timed out after 10 seconds: '" << fullName << "', exiting."
118 << std::endl;
119 exit(-1);
120 }
121 AIBinder* rkpAiBinder = waitForServiceFunc.get();
122 ::ndk::SpAIBinder rkp_binder(rkpAiBinder);
123 auto rkpService = IRemotelyProvisionedComponent::fromBinder(rkp_binder);
124 if (!rkpService) {
125 std::cerr << "Unable to get binder object for '" << fullName << "', exiting." << std::endl;
126 exit(-1);
127 }
128
129 if (context == nullptr) {
130 std::cerr << "Unable to get context for '" << fullName << "', exiting." << std::endl;
131 exit(-1);
132 }
133
134 auto requireUdsCertsRpcNames = static_cast<std::unordered_set<std::string>*>(context);
135 auto requireUdsCerts = requireUdsCertsRpcNames->count(name) != 0;
136 requireUdsCertsRpcNames->erase(name);
137 getCsrForIRpc(IRemotelyProvisionedComponent::descriptor, name, rkpService.get(),
138 requireUdsCerts);
139 }
140
141 } // namespace
142
main(int argc,char ** argv)143 int main(int argc, char** argv) {
144 gflags::ParseCommandLineFlags(&argc, &argv, /*remove_flags=*/true);
145
146 auto requireUdsCertsRpcNames = parseCommaDelimited(FLAGS_require_uds_certs);
147
148 AServiceManager_forEachDeclaredInstance(IRemotelyProvisionedComponent::descriptor,
149 &requireUdsCertsRpcNames, getCsrForInstance);
150
151 // Append drm CSRs
152 for (auto const& [name, irpc] : android::mediadrm::getDrmRemotelyProvisionedComponents()) {
153 auto requireUdsCerts = requireUdsCertsRpcNames.count(name) != 0;
154 requireUdsCertsRpcNames.erase(name);
155 getCsrForIRpc(IDrmFactory::descriptor, name.c_str(), irpc.get(), requireUdsCerts);
156 }
157
158 for (auto const& rpcName : requireUdsCertsRpcNames) {
159 std::cerr << "WARNING: You requested to enforce the presence of UDS Certs for '" << rpcName
160 << "', but no Remotely Provisioned Component had that name." << std::endl;
161 }
162
163 return 0;
164 }
165