xref: /aosp_15_r20/system/security/provisioner/rkp_factory_extraction_tool.cpp (revision e1997b9af69e3155ead6e072d106a0077849ffba)
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