blob: 3bf3d7e9683ad2af9c2fa1af7d2aded8e7a8abe7 [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>
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 <memory>
28#include <optional>
29#include <string>
30#include <string_view>
31#include <vector>
32
33#include "cppbor_parse.h"
34
35using aidl::android::hardware::security::keymint::DeviceInfo;
36using aidl::android::hardware::security::keymint::IRemotelyProvisionedComponent;
37using aidl::android::hardware::security::keymint::MacedPublicKey;
38using aidl::android::hardware::security::keymint::ProtectedData;
39using aidl::android::hardware::security::keymint::RpcHardwareInfo;
40using aidl::android::hardware::security::keymint::remote_prov::getProdEekChain;
41using aidl::android::hardware::security::keymint::remote_prov::jsonEncodeCsrWithBuild;
42
43using namespace cppbor;
44using namespace cppcose;
45
46std::string toBase64(const std::vector<uint8_t>& buffer) {
47 size_t base64Length;
48 int rc = EVP_EncodedLength(&base64Length, buffer.size());
49 if (!rc) {
50 std::cerr << "Error getting base64 length. Size overflow?" << std::endl;
51 exit(-1);
52 }
53
54 std::string base64(base64Length, ' ');
55 rc = EVP_EncodeBlock(reinterpret_cast<uint8_t*>(base64.data()), buffer.data(), buffer.size());
56 ++rc; // Account for NUL, which BoringSSL does not for some reason.
57 if (rc != base64Length) {
58 std::cerr << "Error writing base64. Expected " << base64Length
59 << " bytes to be written, but " << rc << " bytes were actually written."
60 << std::endl;
61 exit(-1);
62 }
63
64 // BoringSSL automatically adds a NUL -- remove it from the string data
65 base64.pop_back();
66
67 return base64;
68}
69
70std::vector<uint8_t> generateChallenge() {
71 std::vector<uint8_t> challenge(kChallengeSize);
72
73 ssize_t bytesRemaining = static_cast<ssize_t>(challenge.size());
74 uint8_t* writePtr = challenge.data();
75 while (bytesRemaining > 0) {
76 int bytesRead = getrandom(writePtr, bytesRemaining, /*flags=*/0);
77 if (bytesRead < 0) {
78 if (errno == EINTR) {
79 continue;
80 } else {
81 std::cerr << errno << ": " << strerror(errno) << std::endl;
82 exit(-1);
83 }
84 }
85 bytesRemaining -= bytesRead;
86 writePtr += bytesRead;
87 }
88
89 return challenge;
90}
91
92CsrResult composeCertificateRequest(const ProtectedData& protectedData,
93 const DeviceInfo& verifiedDeviceInfo,
94 const std::vector<uint8_t>& challenge,
95 const std::vector<uint8_t>& keysToSignMac) {
96 Array macedKeysToSign = Array()
97 .add(Map().add(1, 5).encode()) // alg: hmac-sha256
98 .add(Map()) // empty unprotected headers
99 .add(Null()) // nil for the payload
100 .add(keysToSignMac); // MAC as returned from the HAL
101
102 auto [parsedVerifiedDeviceInfo, ignore1, errMsg] = parse(verifiedDeviceInfo.deviceInfo);
103 if (!parsedVerifiedDeviceInfo) {
104 std::cerr << "Error parsing device info: '" << errMsg << "'" << std::endl;
105 return {nullptr, errMsg};
106 }
107
108 auto [parsedProtectedData, ignore2, errMsg2] = parse(protectedData.protectedData);
109 if (!parsedProtectedData) {
110 std::cerr << "Error parsing protected data: '" << errMsg2 << "'" << std::endl;
111 return {nullptr, errMsg};
112 }
113
114 Array deviceInfo = Array().add(std::move(parsedVerifiedDeviceInfo)).add(Map());
115
116 auto certificateRequest = std::make_unique<Array>();
117 (*certificateRequest)
118 .add(std::move(deviceInfo))
119 .add(challenge)
120 .add(std::move(parsedProtectedData))
121 .add(std::move(macedKeysToSign));
122 return {std::move(certificateRequest), std::nullopt};
123}
124
125CsrResult getCsr(std::string_view componentName, IRemotelyProvisionedComponent* irpc) {
126 std::vector<uint8_t> keysToSignMac;
127 std::vector<MacedPublicKey> emptyKeys;
128 DeviceInfo verifiedDeviceInfo;
129 ProtectedData protectedData;
130 RpcHardwareInfo hwInfo;
131 ::ndk::ScopedAStatus status = irpc->getHardwareInfo(&hwInfo);
132 if (!status.isOk()) {
133 std::cerr << "Failed to get hardware info for '" << componentName
134 << "'. Error code: " << status.getServiceSpecificError() << "." << std::endl;
135 exit(-1);
136 }
137
138 const std::vector<uint8_t> eek = getProdEekChain(hwInfo.supportedEekCurve);
139 const std::vector<uint8_t> challenge = generateChallenge();
140 status = irpc->generateCertificateRequest(
141 /*test_mode=*/false, emptyKeys, eek, challenge, &verifiedDeviceInfo, &protectedData,
142 &keysToSignMac);
143 if (!status.isOk()) {
144 std::cerr << "Bundle extraction failed for '" << componentName
145 << "'. Error code: " << status.getServiceSpecificError() << "." << std::endl;
146 exit(-1);
147 }
148 return composeCertificateRequest(protectedData, verifiedDeviceInfo, challenge, keysToSignMac);
149}