blob: 2c2614d36f09aacfe436259cbe9b4a0523afe244 [file] [log] [blame]
Seth Moore708da932022-08-18 14:38:05 -07001/*
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>
Seth Moore7fc83ab2023-02-24 16:25:07 -080020#include <android-base/properties.h>
Seth Moore708da932022-08-18 14:38:05 -070021#include <android/binder_manager.h>
22#include <cppbor.h>
Seth Mooreb84a1fb2022-09-13 12:02:49 -070023#include <cstddef>
24#include <cstdint>
25#include <cstring>
26#include <iterator>
Seth Moore708da932022-08-18 14:38:05 -070027#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
40using aidl::android::hardware::security::keymint::DeviceInfo;
41using aidl::android::hardware::security::keymint::IRemotelyProvisionedComponent;
42using aidl::android::hardware::security::keymint::MacedPublicKey;
43using aidl::android::hardware::security::keymint::ProtectedData;
44using aidl::android::hardware::security::keymint::RpcHardwareInfo;
Seth Moore04756782022-09-13 16:09:15 -070045using aidl::android::hardware::security::keymint::remote_prov::EekChain;
46using aidl::android::hardware::security::keymint::remote_prov::generateEekChain;
Seth Moore708da932022-08-18 14:38:05 -070047using aidl::android::hardware::security::keymint::remote_prov::getProdEekChain;
48using aidl::android::hardware::security::keymint::remote_prov::jsonEncodeCsrWithBuild;
Seth Moore04756782022-09-13 16:09:15 -070049using aidl::android::hardware::security::keymint::remote_prov::parseAndValidateFactoryDeviceInfo;
Tri Voee773a22022-10-26 16:07:52 -070050using aidl::android::hardware::security::keymint::remote_prov::verifyFactoryCsr;
Seth Moore04756782022-09-13 16:09:15 -070051using aidl::android::hardware::security::keymint::remote_prov::verifyFactoryProtectedData;
Seth Moore708da932022-08-18 14:38:05 -070052
53using namespace cppbor;
54using namespace cppcose;
55
Tri Voee773a22022-10-26 16:07:52 -070056constexpr size_t kVersionWithoutSuperencryption = 3;
57
Seth Moore708da932022-08-18 14:38:05 -070058std::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
82std::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
Tri Voee773a22022-10-26 16:07:52 -0700104CborResult<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) {
Seth Moore708da932022-08-18 14:38:05 -0700109 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
Seth Mooreb84a1fb2022-09-13 12:02:49 -0700115 ErrMsgOr<std::unique_ptr<Map>> parsedVerifiedDeviceInfo =
Seth Moore04756782022-09-13 16:09:15 -0700116 parseAndValidateFactoryDeviceInfo(verifiedDeviceInfo.deviceInfo, provisionable);
Seth Moore708da932022-08-18 14:38:05 -0700117 if (!parsedVerifiedDeviceInfo) {
Seth Mooreb84a1fb2022-09-13 12:02:49 -0700118 return {nullptr, parsedVerifiedDeviceInfo.moveMessage()};
Seth Moore708da932022-08-18 14:38:05 -0700119 }
120
Seth Mooreb84a1fb2022-09-13 12:02:49 -0700121 auto [parsedProtectedData, ignore2, errMsg] = parse(protectedData.protectedData);
Seth Moore708da932022-08-18 14:38:05 -0700122 if (!parsedProtectedData) {
Seth Mooreb84a1fb2022-09-13 12:02:49 -0700123 std::cerr << "Error parsing protected data: '" << errMsg << "'" << std::endl;
Seth Moore708da932022-08-18 14:38:05 -0700124 return {nullptr, errMsg};
125 }
126
Seth Mooreb84a1fb2022-09-13 12:02:49 -0700127 Array deviceInfo = Array().add(parsedVerifiedDeviceInfo.moveValue()).add(Map());
Seth Moore708da932022-08-18 14:38:05 -0700128
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));
Seth Mooreb84a1fb2022-09-13 12:02:49 -0700135 return {std::move(certificateRequest), ""};
Seth Moore708da932022-08-18 14:38:05 -0700136}
137
Tri Voee773a22022-10-26 16:07:52 -0700138CborResult<Array> getCsrV1(std::string_view componentName, IRemotelyProvisionedComponent* irpc) {
Seth Moore708da932022-08-18 14:38:05 -0700139 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
Robert Shih6c3e15b2023-12-18 20:09:02 -0800147 << "'. Description: " << status.getDescription() << "." << std::endl;
Seth Moore708da932022-08-18 14:38:05 -0700148 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
Robert Shih6c3e15b2023-12-18 20:09:02 -0800158 << "'. Description: " << status.getDescription() << "." << std::endl;
Seth Moore708da932022-08-18 14:38:05 -0700159 exit(-1);
160 }
Tri Voee773a22022-10-26 16:07:52 -0700161 return composeCertificateRequestV1(protectedData, verifiedDeviceInfo, challenge, keysToSignMac,
162 irpc);
Seth Moore708da932022-08-18 14:38:05 -0700163}
Seth Moore04756782022-09-13 16:09:15 -0700164
Tri Voee773a22022-10-26 16:07:52 -0700165void selfTestGetCsrV1(std::string_view componentName, IRemotelyProvisionedComponent* irpc) {
Seth Moore04756782022-09-13 16:09:15 -0700166 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
Robert Shih6c3e15b2023-12-18 20:09:02 -0800174 << "'. Description: " << status.getDescription() << "." << std::endl;
Seth Moore04756782022-09-13 16:09:15 -0700175 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
Robert Shih6c3e15b2023-12-18 20:09:02 -0800190 << "'. Description: " << status.getDescription() << "." << std::endl;
Seth Moore04756782022-09-13 16:09:15 -0700191 exit(-1);
192 }
193
194 auto result = verifyFactoryProtectedData(verifiedDeviceInfo, /*keysToSign=*/{}, keysToSignMac,
195 protectedData, *eekChain, eekId,
196 hwInfo.supportedEekCurve, irpc, challenge);
197
Seth Mooredff09d02023-05-31 09:38:47 -0700198 if (!result) {
199 std::cerr << "Self test failed for IRemotelyProvisionedComponent '" << componentName
200 << "'. Error message: '" << result.message() << "'." << std::endl;
201 exit(-1);
202 }
Tri Voee773a22022-10-26 16:07:52 -0700203}
204
205CborResult<Array> composeCertificateRequestV3(const std::vector<uint8_t>& csr) {
Seth Moore7fc83ab2023-02-24 16:25:07 -0800206 const std::string kFingerprintProp = "ro.build.fingerprint";
207
Tri Voee773a22022-10-26 16:07:52 -0700208 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
Seth Moore7fc83ab2023-02-24 16:25:07 -0800216 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));
Tri Voee773a22022-10-26 16:07:52 -0700223 return {std::unique_ptr<Array>(parsedCsr.release()->asArray()), ""};
224}
225
226CborResult<cppbor::Array> getCsrV3(std::string_view componentName,
Karuna Wadhera4244d012024-09-04 14:41:07 +0000227 IRemotelyProvisionedComponent* irpc, bool selfTest,
228 bool allowDegenerate) {
Tri Voee773a22022-10-26 16:07:52 -0700229 std::vector<uint8_t> csr;
230 std::vector<MacedPublicKey> emptyKeys;
231 const std::vector<uint8_t> challenge = generateChallenge();
232
233 auto status = irpc->generateCertificateRequestV2(emptyKeys, challenge, &csr);
234 if (!status.isOk()) {
235 std::cerr << "Bundle extraction failed for '" << componentName
Robert Shih6c3e15b2023-12-18 20:09:02 -0800236 << "'. Description: " << status.getDescription() << "." << std::endl;
Tri Voee773a22022-10-26 16:07:52 -0700237 exit(-1);
238 }
239
Seth Mooredff09d02023-05-31 09:38:47 -0700240 if (selfTest) {
Karuna Wadhera4244d012024-09-04 14:41:07 +0000241 auto result =
242 verifyFactoryCsr(/*keysToSign=*/cppbor::Array(), csr, irpc, challenge, allowDegenerate);
Seth Mooredff09d02023-05-31 09:38:47 -0700243 if (!result) {
244 std::cerr << "Self test failed for IRemotelyProvisionedComponent '" << componentName
245 << "'. Error message: '" << result.message() << "'." << std::endl;
246 exit(-1);
247 }
248 }
249
Tri Voee773a22022-10-26 16:07:52 -0700250 return composeCertificateRequestV3(csr);
251}
252
Seth Mooredff09d02023-05-31 09:38:47 -0700253CborResult<Array> getCsr(std::string_view componentName, IRemotelyProvisionedComponent* irpc,
Karuna Wadhera4244d012024-09-04 14:41:07 +0000254 bool selfTest, bool allowDegenerate) {
Tri Voee773a22022-10-26 16:07:52 -0700255 RpcHardwareInfo hwInfo;
256 auto status = irpc->getHardwareInfo(&hwInfo);
257 if (!status.isOk()) {
258 std::cerr << "Failed to get hardware info for '" << componentName
Robert Shih6c3e15b2023-12-18 20:09:02 -0800259 << "'. Description: " << status.getDescription() << "." << std::endl;
Tri Voee773a22022-10-26 16:07:52 -0700260 exit(-1);
261 }
262
263 if (hwInfo.versionNumber < kVersionWithoutSuperencryption) {
Seth Mooredff09d02023-05-31 09:38:47 -0700264 if (selfTest) {
265 selfTestGetCsrV1(componentName, irpc);
266 }
Tri Voee773a22022-10-26 16:07:52 -0700267 return getCsrV1(componentName, irpc);
268 } else {
Karuna Wadhera4244d012024-09-04 14:41:07 +0000269 return getCsrV3(componentName, irpc, selfTest, allowDegenerate);
Tri Voee773a22022-10-26 16:07:52 -0700270 }
271}
Alice Wang16e34422024-06-07 12:41:22 +0000272
273bool isRemoteProvisioningSupported(IRemotelyProvisionedComponent* irpc) {
274 RpcHardwareInfo hwInfo;
275 auto status = irpc->getHardwareInfo(&hwInfo);
276 if (status.isOk()) {
277 return true;
278 }
279 if (status.getExceptionCode() == EX_UNSUPPORTED_OPERATION) {
280 return false;
281 }
282 std::cerr << "Unexpected error when getting hardware info. Description: "
283 << status.getDescription() << "." << std::endl;
284 exit(-1);
285}