1 /*
2  * Copyright 2022 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 "rkp_factory_extraction_lib.h"
18 
19 #include <aidl/android/hardware/security/keymint/IRemotelyProvisionedComponent.h>
20 #include <android-base/properties.h>
21 #include <android/binder_manager.h>
22 #include <cppbor.h>
23 #include <cstddef>
24 #include <cstdint>
25 #include <cstring>
26 #include <iterator>
27 #include <keymaster/cppcose/cppcose.h>
28 #include <openssl/base64.h>
29 #include <remote_prov/remote_prov_utils.h>
30 #include <sys/random.h>
31 
32 #include <memory>
33 #include <optional>
34 #include <string>
35 #include <string_view>
36 #include <vector>
37 
38 #include "cppbor_parse.h"
39 
40 using aidl::android::hardware::security::keymint::DeviceInfo;
41 using aidl::android::hardware::security::keymint::IRemotelyProvisionedComponent;
42 using aidl::android::hardware::security::keymint::MacedPublicKey;
43 using aidl::android::hardware::security::keymint::ProtectedData;
44 using aidl::android::hardware::security::keymint::RpcHardwareInfo;
45 using aidl::android::hardware::security::keymint::remote_prov::EekChain;
46 using aidl::android::hardware::security::keymint::remote_prov::generateEekChain;
47 using aidl::android::hardware::security::keymint::remote_prov::getProdEekChain;
48 using aidl::android::hardware::security::keymint::remote_prov::jsonEncodeCsrWithBuild;
49 using aidl::android::hardware::security::keymint::remote_prov::parseAndValidateFactoryDeviceInfo;
50 using aidl::android::hardware::security::keymint::remote_prov::verifyFactoryCsr;
51 using aidl::android::hardware::security::keymint::remote_prov::verifyFactoryProtectedData;
52 
53 using namespace cppbor;
54 using namespace cppcose;
55 
56 constexpr size_t kVersionWithoutSuperencryption = 3;
57 
toBase64(const std::vector<uint8_t> & buffer)58 std::string toBase64(const std::vector<uint8_t>& buffer) {
59     size_t base64Length;
60     int rc = EVP_EncodedLength(&base64Length, buffer.size());
61     if (!rc) {
62         std::cerr << "Error getting base64 length. Size overflow?" << std::endl;
63         exit(-1);
64     }
65 
66     std::string base64(base64Length, ' ');
67     rc = EVP_EncodeBlock(reinterpret_cast<uint8_t*>(base64.data()), buffer.data(), buffer.size());
68     ++rc;  // Account for NUL, which BoringSSL does not for some reason.
69     if (rc != base64Length) {
70         std::cerr << "Error writing base64. Expected " << base64Length
71                   << " bytes to be written, but " << rc << " bytes were actually written."
72                   << std::endl;
73         exit(-1);
74     }
75 
76     // BoringSSL automatically adds a NUL -- remove it from the string data
77     base64.pop_back();
78 
79     return base64;
80 }
81 
generateChallenge()82 std::vector<uint8_t> generateChallenge() {
83     std::vector<uint8_t> challenge(kChallengeSize);
84 
85     ssize_t bytesRemaining = static_cast<ssize_t>(challenge.size());
86     uint8_t* writePtr = challenge.data();
87     while (bytesRemaining > 0) {
88         int bytesRead = getrandom(writePtr, bytesRemaining, /*flags=*/0);
89         if (bytesRead < 0) {
90             if (errno == EINTR) {
91                 continue;
92             } else {
93                 std::cerr << errno << ": " << strerror(errno) << std::endl;
94                 exit(-1);
95             }
96         }
97         bytesRemaining -= bytesRead;
98         writePtr += bytesRead;
99     }
100 
101     return challenge;
102 }
103 
composeCertificateRequestV1(const ProtectedData & protectedData,const DeviceInfo & verifiedDeviceInfo,const std::vector<uint8_t> & challenge,const std::vector<uint8_t> & keysToSignMac,IRemotelyProvisionedComponent * provisionable)104 CborResult<Array> composeCertificateRequestV1(const ProtectedData& protectedData,
105                                               const DeviceInfo& verifiedDeviceInfo,
106                                               const std::vector<uint8_t>& challenge,
107                                               const std::vector<uint8_t>& keysToSignMac,
108                                               IRemotelyProvisionedComponent* provisionable) {
109     Array macedKeysToSign = Array()
110                                 .add(Map().add(1, 5).encode())  // alg: hmac-sha256
111                                 .add(Map())                     // empty unprotected headers
112                                 .add(Null())                    // nil for the payload
113                                 .add(keysToSignMac);            // MAC as returned from the HAL
114 
115     ErrMsgOr<std::unique_ptr<Map>> parsedVerifiedDeviceInfo =
116         parseAndValidateFactoryDeviceInfo(verifiedDeviceInfo.deviceInfo, provisionable);
117     if (!parsedVerifiedDeviceInfo) {
118         return {nullptr, parsedVerifiedDeviceInfo.moveMessage()};
119     }
120 
121     auto [parsedProtectedData, ignore2, errMsg] = parse(protectedData.protectedData);
122     if (!parsedProtectedData) {
123         std::cerr << "Error parsing protected data: '" << errMsg << "'" << std::endl;
124         return {nullptr, errMsg};
125     }
126 
127     Array deviceInfo = Array().add(parsedVerifiedDeviceInfo.moveValue()).add(Map());
128 
129     auto certificateRequest = std::make_unique<Array>();
130     (*certificateRequest)
131         .add(std::move(deviceInfo))
132         .add(challenge)
133         .add(std::move(parsedProtectedData))
134         .add(std::move(macedKeysToSign));
135     return {std::move(certificateRequest), ""};
136 }
137 
getCsrV1(std::string_view componentName,IRemotelyProvisionedComponent * irpc)138 CborResult<Array> getCsrV1(std::string_view componentName, IRemotelyProvisionedComponent* irpc) {
139     std::vector<uint8_t> keysToSignMac;
140     std::vector<MacedPublicKey> emptyKeys;
141     DeviceInfo verifiedDeviceInfo;
142     ProtectedData protectedData;
143     RpcHardwareInfo hwInfo;
144     ::ndk::ScopedAStatus status = irpc->getHardwareInfo(&hwInfo);
145     if (!status.isOk()) {
146         std::cerr << "Failed to get hardware info for '" << componentName
147                   << "'. Description: " << status.getDescription() << "." << std::endl;
148         exit(-1);
149     }
150 
151     const std::vector<uint8_t> eek = getProdEekChain(hwInfo.supportedEekCurve);
152     const std::vector<uint8_t> challenge = generateChallenge();
153     status = irpc->generateCertificateRequest(
154         /*test_mode=*/false, emptyKeys, eek, challenge, &verifiedDeviceInfo, &protectedData,
155         &keysToSignMac);
156     if (!status.isOk()) {
157         std::cerr << "Bundle extraction failed for '" << componentName
158                   << "'. Description: " << status.getDescription() << "." << std::endl;
159         exit(-1);
160     }
161     return composeCertificateRequestV1(protectedData, verifiedDeviceInfo, challenge, keysToSignMac,
162                                        irpc);
163 }
164 
selfTestGetCsrV1(std::string_view componentName,IRemotelyProvisionedComponent * irpc)165 void selfTestGetCsrV1(std::string_view componentName, IRemotelyProvisionedComponent* irpc) {
166     std::vector<uint8_t> keysToSignMac;
167     std::vector<MacedPublicKey> emptyKeys;
168     DeviceInfo verifiedDeviceInfo;
169     ProtectedData protectedData;
170     RpcHardwareInfo hwInfo;
171     ::ndk::ScopedAStatus status = irpc->getHardwareInfo(&hwInfo);
172     if (!status.isOk()) {
173         std::cerr << "Failed to get hardware info for '" << componentName
174                   << "'. Description: " << status.getDescription() << "." << std::endl;
175         exit(-1);
176     }
177 
178     const std::vector<uint8_t> eekId = {0, 1, 2, 3, 4, 5, 6, 7};
179     ErrMsgOr<EekChain> eekChain = generateEekChain(hwInfo.supportedEekCurve, /*length=*/3, eekId);
180     if (!eekChain) {
181         std::cerr << "Error generating test EEK certificate chain: " << eekChain.message();
182         exit(-1);
183     }
184     const std::vector<uint8_t> challenge = generateChallenge();
185     status = irpc->generateCertificateRequest(
186         /*test_mode=*/true, emptyKeys, eekChain->chain, challenge, &verifiedDeviceInfo,
187         &protectedData, &keysToSignMac);
188     if (!status.isOk()) {
189         std::cerr << "Error generating test cert chain for '" << componentName
190                   << "'. Description: " << status.getDescription() << "." << std::endl;
191         exit(-1);
192     }
193 
194     auto result = verifyFactoryProtectedData(verifiedDeviceInfo, /*keysToSign=*/{}, keysToSignMac,
195                                              protectedData, *eekChain, eekId,
196                                              hwInfo.supportedEekCurve, irpc, challenge);
197 
198     if (!result) {
199         std::cerr << "Self test failed for IRemotelyProvisionedComponent '" << componentName
200                   << "'. Error message: '" << result.message() << "'." << std::endl;
201         exit(-1);
202     }
203 }
204 
composeCertificateRequestV3(const std::vector<uint8_t> & csr)205 CborResult<Array> composeCertificateRequestV3(const std::vector<uint8_t>& csr) {
206     const std::string kFingerprintProp = "ro.build.fingerprint";
207 
208     auto [parsedCsr, _, csrErrMsg] = cppbor::parse(csr);
209     if (!parsedCsr) {
210         return {nullptr, csrErrMsg};
211     }
212     if (!parsedCsr->asArray()) {
213         return {nullptr, "CSR is not a CBOR array."};
214     }
215 
216     if (!::android::base::WaitForPropertyCreation(kFingerprintProp)) {
217         return {nullptr, "Unable to read build fingerprint"};
218     }
219 
220     Map unverifiedDeviceInfo =
221         Map().add("fingerprint", ::android::base::GetProperty(kFingerprintProp, /*default=*/""));
222     parsedCsr->asArray()->add(std::move(unverifiedDeviceInfo));
223     return {std::unique_ptr<Array>(parsedCsr.release()->asArray()), ""};
224 }
225 
getCsrV3(std::string_view componentName,IRemotelyProvisionedComponent * irpc,bool selfTest)226 CborResult<cppbor::Array> getCsrV3(std::string_view componentName,
227                                    IRemotelyProvisionedComponent* irpc, bool selfTest) {
228     std::vector<uint8_t> csr;
229     std::vector<MacedPublicKey> emptyKeys;
230     const std::vector<uint8_t> challenge = generateChallenge();
231 
232     auto status = irpc->generateCertificateRequestV2(emptyKeys, challenge, &csr);
233     if (!status.isOk()) {
234         std::cerr << "Bundle extraction failed for '" << componentName
235                   << "'. Description: " << status.getDescription() << "." << std::endl;
236         exit(-1);
237     }
238 
239     if (selfTest) {
240         auto result = verifyFactoryCsr(/*keysToSign=*/cppbor::Array(), csr, irpc, challenge);
241         if (!result) {
242             std::cerr << "Self test failed for IRemotelyProvisionedComponent '" << componentName
243                       << "'. Error message: '" << result.message() << "'." << std::endl;
244             exit(-1);
245         }
246     }
247 
248     return composeCertificateRequestV3(csr);
249 }
250 
getCsr(std::string_view componentName,IRemotelyProvisionedComponent * irpc,bool selfTest)251 CborResult<Array> getCsr(std::string_view componentName, IRemotelyProvisionedComponent* irpc,
252                          bool selfTest) {
253     RpcHardwareInfo hwInfo;
254     auto status = irpc->getHardwareInfo(&hwInfo);
255     if (!status.isOk()) {
256         std::cerr << "Failed to get hardware info for '" << componentName
257                   << "'. Description: " << status.getDescription() << "." << std::endl;
258         exit(-1);
259     }
260 
261     if (hwInfo.versionNumber < kVersionWithoutSuperencryption) {
262         if (selfTest) {
263             selfTestGetCsrV1(componentName, irpc);
264         }
265         return getCsrV1(componentName, irpc);
266     } else {
267         return getCsrV3(componentName, irpc, selfTest);
268     }
269 }
270 
isRemoteProvisioningSupported(IRemotelyProvisionedComponent * irpc)271 bool isRemoteProvisioningSupported(IRemotelyProvisionedComponent* irpc) {
272     RpcHardwareInfo hwInfo;
273     auto status = irpc->getHardwareInfo(&hwInfo);
274     if (status.isOk()) {
275         return true;
276     }
277     if (status.getExceptionCode() == EX_UNSUPPORTED_OPERATION) {
278         return false;
279     }
280     std::cerr << "Unexpected error when getting hardware info. Description: "
281               << status.getDescription() << "." << std::endl;
282     exit(-1);
283 }
284