• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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