blob: d85e85f644a0ed62a8cfef04f3dc18b8b60ed00a [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>
20#include <android/binder_manager.h>
21#include <cppbor.h>
Seth Mooreb84a1fb2022-09-13 12:02:49 -070022#include <cstddef>
23#include <cstdint>
24#include <cstring>
25#include <iterator>
Seth Moore708da932022-08-18 14:38:05 -070026#include <keymaster/cppcose/cppcose.h>
27#include <openssl/base64.h>
28#include <remote_prov/remote_prov_utils.h>
29#include <sys/random.h>
30
31#include <memory>
32#include <optional>
33#include <string>
34#include <string_view>
35#include <vector>
36
37#include "cppbor_parse.h"
38
39using aidl::android::hardware::security::keymint::DeviceInfo;
40using aidl::android::hardware::security::keymint::IRemotelyProvisionedComponent;
41using aidl::android::hardware::security::keymint::MacedPublicKey;
42using aidl::android::hardware::security::keymint::ProtectedData;
43using aidl::android::hardware::security::keymint::RpcHardwareInfo;
Seth Moore04756782022-09-13 16:09:15 -070044using aidl::android::hardware::security::keymint::remote_prov::EekChain;
45using aidl::android::hardware::security::keymint::remote_prov::generateEekChain;
Seth Moore708da932022-08-18 14:38:05 -070046using aidl::android::hardware::security::keymint::remote_prov::getProdEekChain;
47using aidl::android::hardware::security::keymint::remote_prov::jsonEncodeCsrWithBuild;
Seth Moore04756782022-09-13 16:09:15 -070048using aidl::android::hardware::security::keymint::remote_prov::parseAndValidateFactoryDeviceInfo;
Tri Voee773a22022-10-26 16:07:52 -070049using aidl::android::hardware::security::keymint::remote_prov::verifyFactoryCsr;
Seth Moore04756782022-09-13 16:09:15 -070050using aidl::android::hardware::security::keymint::remote_prov::verifyFactoryProtectedData;
Seth Moore708da932022-08-18 14:38:05 -070051
52using namespace cppbor;
53using namespace cppcose;
54
Tri Voee773a22022-10-26 16:07:52 -070055constexpr size_t kVersionWithoutSuperencryption = 3;
56
Seth Moore708da932022-08-18 14:38:05 -070057std::string toBase64(const std::vector<uint8_t>& buffer) {
58 size_t base64Length;
59 int rc = EVP_EncodedLength(&base64Length, buffer.size());
60 if (!rc) {
61 std::cerr << "Error getting base64 length. Size overflow?" << std::endl;
62 exit(-1);
63 }
64
65 std::string base64(base64Length, ' ');
66 rc = EVP_EncodeBlock(reinterpret_cast<uint8_t*>(base64.data()), buffer.data(), buffer.size());
67 ++rc; // Account for NUL, which BoringSSL does not for some reason.
68 if (rc != base64Length) {
69 std::cerr << "Error writing base64. Expected " << base64Length
70 << " bytes to be written, but " << rc << " bytes were actually written."
71 << std::endl;
72 exit(-1);
73 }
74
75 // BoringSSL automatically adds a NUL -- remove it from the string data
76 base64.pop_back();
77
78 return base64;
79}
80
81std::vector<uint8_t> generateChallenge() {
82 std::vector<uint8_t> challenge(kChallengeSize);
83
84 ssize_t bytesRemaining = static_cast<ssize_t>(challenge.size());
85 uint8_t* writePtr = challenge.data();
86 while (bytesRemaining > 0) {
87 int bytesRead = getrandom(writePtr, bytesRemaining, /*flags=*/0);
88 if (bytesRead < 0) {
89 if (errno == EINTR) {
90 continue;
91 } else {
92 std::cerr << errno << ": " << strerror(errno) << std::endl;
93 exit(-1);
94 }
95 }
96 bytesRemaining -= bytesRead;
97 writePtr += bytesRead;
98 }
99
100 return challenge;
101}
102
Tri Voee773a22022-10-26 16:07:52 -0700103CborResult<Array> composeCertificateRequestV1(const ProtectedData& protectedData,
104 const DeviceInfo& verifiedDeviceInfo,
105 const std::vector<uint8_t>& challenge,
106 const std::vector<uint8_t>& keysToSignMac,
107 IRemotelyProvisionedComponent* provisionable) {
Seth Moore708da932022-08-18 14:38:05 -0700108 Array macedKeysToSign = Array()
109 .add(Map().add(1, 5).encode()) // alg: hmac-sha256
110 .add(Map()) // empty unprotected headers
111 .add(Null()) // nil for the payload
112 .add(keysToSignMac); // MAC as returned from the HAL
113
Seth Mooreb84a1fb2022-09-13 12:02:49 -0700114 ErrMsgOr<std::unique_ptr<Map>> parsedVerifiedDeviceInfo =
Seth Moore04756782022-09-13 16:09:15 -0700115 parseAndValidateFactoryDeviceInfo(verifiedDeviceInfo.deviceInfo, provisionable);
Seth Moore708da932022-08-18 14:38:05 -0700116 if (!parsedVerifiedDeviceInfo) {
Seth Mooreb84a1fb2022-09-13 12:02:49 -0700117 return {nullptr, parsedVerifiedDeviceInfo.moveMessage()};
Seth Moore708da932022-08-18 14:38:05 -0700118 }
119
Seth Mooreb84a1fb2022-09-13 12:02:49 -0700120 auto [parsedProtectedData, ignore2, errMsg] = parse(protectedData.protectedData);
Seth Moore708da932022-08-18 14:38:05 -0700121 if (!parsedProtectedData) {
Seth Mooreb84a1fb2022-09-13 12:02:49 -0700122 std::cerr << "Error parsing protected data: '" << errMsg << "'" << std::endl;
Seth Moore708da932022-08-18 14:38:05 -0700123 return {nullptr, errMsg};
124 }
125
Seth Mooreb84a1fb2022-09-13 12:02:49 -0700126 Array deviceInfo = Array().add(parsedVerifiedDeviceInfo.moveValue()).add(Map());
Seth Moore708da932022-08-18 14:38:05 -0700127
128 auto certificateRequest = std::make_unique<Array>();
129 (*certificateRequest)
130 .add(std::move(deviceInfo))
131 .add(challenge)
132 .add(std::move(parsedProtectedData))
133 .add(std::move(macedKeysToSign));
Seth Mooreb84a1fb2022-09-13 12:02:49 -0700134 return {std::move(certificateRequest), ""};
Seth Moore708da932022-08-18 14:38:05 -0700135}
136
Tri Voee773a22022-10-26 16:07:52 -0700137CborResult<Array> getCsrV1(std::string_view componentName, IRemotelyProvisionedComponent* irpc) {
Seth Moore708da932022-08-18 14:38:05 -0700138 std::vector<uint8_t> keysToSignMac;
139 std::vector<MacedPublicKey> emptyKeys;
140 DeviceInfo verifiedDeviceInfo;
141 ProtectedData protectedData;
142 RpcHardwareInfo hwInfo;
143 ::ndk::ScopedAStatus status = irpc->getHardwareInfo(&hwInfo);
144 if (!status.isOk()) {
145 std::cerr << "Failed to get hardware info for '" << componentName
146 << "'. Error code: " << status.getServiceSpecificError() << "." << std::endl;
147 exit(-1);
148 }
149
150 const std::vector<uint8_t> eek = getProdEekChain(hwInfo.supportedEekCurve);
151 const std::vector<uint8_t> challenge = generateChallenge();
152 status = irpc->generateCertificateRequest(
153 /*test_mode=*/false, emptyKeys, eek, challenge, &verifiedDeviceInfo, &protectedData,
154 &keysToSignMac);
155 if (!status.isOk()) {
156 std::cerr << "Bundle extraction failed for '" << componentName
157 << "'. Error code: " << status.getServiceSpecificError() << "." << std::endl;
158 exit(-1);
159 }
Tri Voee773a22022-10-26 16:07:52 -0700160 return composeCertificateRequestV1(protectedData, verifiedDeviceInfo, challenge, keysToSignMac,
161 irpc);
Seth Moore708da932022-08-18 14:38:05 -0700162}
Seth Moore04756782022-09-13 16:09:15 -0700163
Tri Voee773a22022-10-26 16:07:52 -0700164void selfTestGetCsrV1(std::string_view componentName, IRemotelyProvisionedComponent* irpc) {
Seth Moore04756782022-09-13 16:09:15 -0700165 std::vector<uint8_t> keysToSignMac;
166 std::vector<MacedPublicKey> emptyKeys;
167 DeviceInfo verifiedDeviceInfo;
168 ProtectedData protectedData;
169 RpcHardwareInfo hwInfo;
170 ::ndk::ScopedAStatus status = irpc->getHardwareInfo(&hwInfo);
171 if (!status.isOk()) {
172 std::cerr << "Failed to get hardware info for '" << componentName
173 << "'. Error code: " << status.getServiceSpecificError() << "." << std::endl;
174 exit(-1);
175 }
176
177 const std::vector<uint8_t> eekId = {0, 1, 2, 3, 4, 5, 6, 7};
178 ErrMsgOr<EekChain> eekChain = generateEekChain(hwInfo.supportedEekCurve, /*length=*/3, eekId);
179 if (!eekChain) {
180 std::cerr << "Error generating test EEK certificate chain: " << eekChain.message();
181 exit(-1);
182 }
183 const std::vector<uint8_t> challenge = generateChallenge();
184 status = irpc->generateCertificateRequest(
185 /*test_mode=*/true, emptyKeys, eekChain->chain, challenge, &verifiedDeviceInfo,
186 &protectedData, &keysToSignMac);
187 if (!status.isOk()) {
188 std::cerr << "Error generating test cert chain for '" << componentName
189 << "'. Error code: " << status.getServiceSpecificError() << "." << std::endl;
190 exit(-1);
191 }
192
193 auto result = verifyFactoryProtectedData(verifiedDeviceInfo, /*keysToSign=*/{}, keysToSignMac,
194 protectedData, *eekChain, eekId,
195 hwInfo.supportedEekCurve, irpc, challenge);
196
197 std::cout << "Self test successful." << std::endl;
Tri Voee773a22022-10-26 16:07:52 -0700198}
199
200CborResult<Array> composeCertificateRequestV3(const std::vector<uint8_t>& csr) {
201 auto [parsedCsr, _, csrErrMsg] = cppbor::parse(csr);
202 if (!parsedCsr) {
203 return {nullptr, csrErrMsg};
204 }
205 if (!parsedCsr->asArray()) {
206 return {nullptr, "CSR is not a CBOR array."};
207 }
208
209 return {std::unique_ptr<Array>(parsedCsr.release()->asArray()), ""};
210}
211
212CborResult<cppbor::Array> getCsrV3(std::string_view componentName,
213 IRemotelyProvisionedComponent* irpc) {
214 std::vector<uint8_t> csr;
215 std::vector<MacedPublicKey> emptyKeys;
216 const std::vector<uint8_t> challenge = generateChallenge();
217
218 auto status = irpc->generateCertificateRequestV2(emptyKeys, challenge, &csr);
219 if (!status.isOk()) {
220 std::cerr << "Bundle extraction failed for '" << componentName
221 << "'. Error code: " << status.getServiceSpecificError() << "." << std::endl;
222 exit(-1);
223 }
224
225 return composeCertificateRequestV3(csr);
226}
227
228void selfTestGetCsrV3(std::string_view componentName, IRemotelyProvisionedComponent* irpc) {
229 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
236 << "'. Error code: " << status.getServiceSpecificError() << "." << std::endl;
237 exit(-1);
238 }
239
240 auto result = verifyFactoryCsr(/*keysToSign=*/cppbor::Array(), csr, irpc, challenge);
241 if (!result) {
242 std::cerr << "Self test failed for '" << componentName
243 << "'. Error message: " << result.message() << "." << std::endl;
244 exit(-1);
245 }
246
247 std::cout << "Self test successful." << std::endl;
248}
249
250CborResult<Array> getCsr(std::string_view componentName, IRemotelyProvisionedComponent* irpc) {
251 RpcHardwareInfo hwInfo;
252 auto status = irpc->getHardwareInfo(&hwInfo);
253 if (!status.isOk()) {
254 std::cerr << "Failed to get hardware info for '" << componentName
255 << "'. Error code: " << status.getServiceSpecificError() << "." << std::endl;
256 exit(-1);
257 }
258
259 if (hwInfo.versionNumber < kVersionWithoutSuperencryption) {
260 return getCsrV1(componentName, irpc);
261 } else {
262 return getCsrV3(componentName, irpc);
263 }
264}
265
266void selfTestGetCsr(std::string_view componentName, IRemotelyProvisionedComponent* irpc) {
267 RpcHardwareInfo hwInfo;
268 auto status = irpc->getHardwareInfo(&hwInfo);
269 if (!status.isOk()) {
270 std::cerr << "Failed to get hardware info for '" << componentName
271 << "'. Error code: " << status.getServiceSpecificError() << "." << std::endl;
272 exit(-1);
273 }
274
275 if (hwInfo.versionNumber < kVersionWithoutSuperencryption) {
276 selfTestGetCsrV1(componentName, irpc);
277 } else {
278 selfTestGetCsrV3(componentName, irpc);
279 }
280}