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 "Whether to validate the output for correctness. If enabled, this checks that the "
44 "device on the factory line is producing valid output before attempting to upload the "
45 "output to the device info service. Defaults to true.");
46 DEFINE_string(allow_degenerate, "",
47 "Comma-delimited list of names of IRemotelyProvisionedComponent instances for which "
48 "self_test validation allows degenerate DICE chains in the CSR. Example: "
49 "avf,default,strongbox. Defaults to the empty string.");
50 DEFINE_string(serialno_prop, "ro.serialno",
51 "System property from which the serial number should be retrieved. Defaults to "
52 "'ro.serialno'.");
53 DEFINE_string(require_uds_certs, "",
54 "Comma-delimited list of names of IRemotelyProvisionedComponent instances for which "
55 "UDS certificate chains are required to be present in the CSR. Example: "
56 "avf,default,strongbox. Defaults to the empty string.");
57
58 namespace {
59
60 // Various supported --output_format values.
61 constexpr std::string_view kBinaryCsrOutput = "csr"; // Just the raw csr as binary
62 constexpr std::string_view kBuildPlusCsr = "build+csr"; // Text-encoded (JSON) build
63 // fingerprint plus CSR.
64
getFullServiceName(const char * descriptor,const char * name)65 std::string getFullServiceName(const char* descriptor, const char* name) {
66 return std::string(descriptor) + "/" + name;
67 }
68
writeOutput(const std::string instance_name,const cppbor::Array & csr)69 void writeOutput(const std::string instance_name, const cppbor::Array& csr) {
70 if (FLAGS_output_format == kBinaryCsrOutput) {
71 auto bytes = csr.encode();
72 std::copy(bytes.begin(), bytes.end(), std::ostream_iterator<char>(std::cout));
73 } else if (FLAGS_output_format == kBuildPlusCsr) {
74 auto [json, error] = jsonEncodeCsrWithBuild(instance_name, csr, FLAGS_serialno_prop);
75 if (!error.empty()) {
76 std::cerr << "Error JSON encoding the output: " << error << std::endl;
77 exit(-1);
78 }
79 std::cout << json << std::endl;
80 } else {
81 std::cerr << "Unexpected output_format '" << FLAGS_output_format << "'" << std::endl;
82 std::cerr << "Valid formats:" << std::endl;
83 std::cerr << " " << kBinaryCsrOutput << std::endl;
84 std::cerr << " " << kBuildPlusCsr << std::endl;
85 exit(-1);
86 }
87 }
88
getCsrForIRpc(const char * descriptor,const char * name,IRemotelyProvisionedComponent * irpc,bool allowDegenerate,bool requireUdsCerts)89 void getCsrForIRpc(const char* descriptor, const char* name, IRemotelyProvisionedComponent* irpc,
90 bool allowDegenerate, bool requireUdsCerts) {
91 auto fullName = getFullServiceName(descriptor, name);
92 // AVF RKP HAL is not always supported, so we need to check if it is supported before
93 // generating the CSR.
94 if (fullName == RKPVM_INSTANCE_NAME) {
95 RpcHardwareInfo hwInfo;
96 auto status = irpc->getHardwareInfo(&hwInfo);
97 if (!status.isOk()) {
98 return;
99 }
100 }
101
102 auto [request, errMsg] = getCsr(name, irpc, FLAGS_self_test, allowDegenerate, requireUdsCerts);
103 if (!request) {
104 std::cerr << "Unable to build CSR for '" << fullName << "': " << errMsg << ", exiting."
105 << std::endl;
106 exit(-1);
107 }
108
109 writeOutput(std::string(name), *request);
110 }
111
112 // Callback for AServiceManager_forEachDeclaredInstance that writes out a CSR
113 // for every IRemotelyProvisionedComponent.
getCsrForInstance(const char * name,void * context)114 void getCsrForInstance(const char* name, void* context) {
115 auto fullName = getFullServiceName(IRemotelyProvisionedComponent::descriptor, name);
116 std::future<AIBinder*> waitForServiceFunc =
117 std::async(std::launch::async, AServiceManager_waitForService, fullName.c_str());
118 if (waitForServiceFunc.wait_for(std::chrono::seconds(10)) == std::future_status::timeout) {
119 std::cerr << "Wait for service timed out after 10 seconds: '" << fullName << "', exiting."
120 << std::endl;
121 exit(-1);
122 }
123 AIBinder* rkpAiBinder = waitForServiceFunc.get();
124 ::ndk::SpAIBinder rkp_binder(rkpAiBinder);
125 auto rkpService = IRemotelyProvisionedComponent::fromBinder(rkp_binder);
126 if (!rkpService) {
127 std::cerr << "Unable to get binder object for '" << fullName << "', exiting." << std::endl;
128 exit(-1);
129 }
130
131 if (context == nullptr) {
132 std::cerr << "Unable to get context for '" << fullName << "', exiting." << std::endl;
133 exit(-1);
134 }
135
136 auto csrValidationConfig = static_cast<CsrValidationConfig*>(context);
137 bool allowDegenerateFieldNotNull = csrValidationConfig->allow_degenerate_irpc_names != nullptr;
138 bool allowDegenerate = allowDegenerateFieldNotNull &&
139 csrValidationConfig->allow_degenerate_irpc_names->count(name) > 0;
140 bool requireUdsCertsFieldNotNull = csrValidationConfig->require_uds_certs_irpc_names != nullptr;
141 bool requireUdsCerts = requireUdsCertsFieldNotNull &&
142 csrValidationConfig->require_uds_certs_irpc_names->count(name) > 0;
143
144 // Record the fact that this IRemotelyProvisionedComponent instance was found by removing it
145 // from the sets in the context.
146 if (allowDegenerateFieldNotNull) {
147 csrValidationConfig->allow_degenerate_irpc_names->erase(name);
148 }
149 if (requireUdsCertsFieldNotNull) {
150 csrValidationConfig->require_uds_certs_irpc_names->erase(name);
151 }
152
153 getCsrForIRpc(IRemotelyProvisionedComponent::descriptor, name, rkpService.get(),
154 allowDegenerate, requireUdsCerts);
155 }
156
157 } // namespace
158
main(int argc,char ** argv)159 int main(int argc, char** argv) {
160 gflags::ParseCommandLineFlags(&argc, &argv, /*remove_flags=*/true);
161
162 auto allowDegenerateIRpcNames = parseCommaDelimited(FLAGS_allow_degenerate);
163 auto requireUdsCertsIRpcNames = parseCommaDelimited(FLAGS_require_uds_certs);
164 CsrValidationConfig csrValidationConfig = {
165 .allow_degenerate_irpc_names = &allowDegenerateIRpcNames,
166 .require_uds_certs_irpc_names = &requireUdsCertsIRpcNames,
167 };
168
169 AServiceManager_forEachDeclaredInstance(IRemotelyProvisionedComponent::descriptor,
170 &csrValidationConfig, getCsrForInstance);
171
172 // Append drm CSRs
173 for (auto const& [name, irpc] : android::mediadrm::getDrmRemotelyProvisionedComponents()) {
174 bool allowDegenerate = allowDegenerateIRpcNames.count(name) != 0;
175 allowDegenerateIRpcNames.erase(name);
176 auto requireUdsCerts = requireUdsCertsIRpcNames.count(name) != 0;
177 requireUdsCertsIRpcNames.erase(name);
178 getCsrForIRpc(IDrmFactory::descriptor, name.c_str(), irpc.get(), allowDegenerate,
179 requireUdsCerts);
180 }
181
182 // Print a warning for IRemotelyProvisionedComponent instance names that were passed
183 // in as parameters to the "require_uds_certs" and "allow_degenerate" flags but were
184 // ignored because no instances with those names were found.
185 for (const auto& irpcName : allowDegenerateIRpcNames) {
186 std::cerr << "WARNING: You requested special handling of 'self_test' validation checks "
187 << "for '" << irpcName << "' via the 'allow_degenerate' flag but no such "
188 << "IRemotelyProvisionedComponent instance exists." << std::endl;
189 }
190 for (const auto& irpcName : requireUdsCertsIRpcNames) {
191 std::cerr << "WARNING: You requested special handling of 'self_test' validation checks "
192 << "for '" << irpcName << "' via the 'require_uds_certs' flag but no such "
193 << "IRemotelyProvisionedComponent instance exists." << std::endl;
194 }
195
196 return 0;
197 }
198