blob: 831adba096306510bf0f94f9ed3860c5007176c9 [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;
44using aidl::android::hardware::security::keymint::remote_prov::getProdEekChain;
45using aidl::android::hardware::security::keymint::remote_prov::jsonEncodeCsrWithBuild;
Seth Mooreb84a1fb2022-09-13 12:02:49 -070046using aidl::android::hardware::security::keymint::remote_prov::parseAndValidateDeviceInfo;
Seth Moore708da932022-08-18 14:38:05 -070047
48using namespace cppbor;
49using namespace cppcose;
50
51std::string toBase64(const std::vector<uint8_t>& buffer) {
52 size_t base64Length;
53 int rc = EVP_EncodedLength(&base64Length, buffer.size());
54 if (!rc) {
55 std::cerr << "Error getting base64 length. Size overflow?" << std::endl;
56 exit(-1);
57 }
58
59 std::string base64(base64Length, ' ');
60 rc = EVP_EncodeBlock(reinterpret_cast<uint8_t*>(base64.data()), buffer.data(), buffer.size());
61 ++rc; // Account for NUL, which BoringSSL does not for some reason.
62 if (rc != base64Length) {
63 std::cerr << "Error writing base64. Expected " << base64Length
64 << " bytes to be written, but " << rc << " bytes were actually written."
65 << std::endl;
66 exit(-1);
67 }
68
69 // BoringSSL automatically adds a NUL -- remove it from the string data
70 base64.pop_back();
71
72 return base64;
73}
74
75std::vector<uint8_t> generateChallenge() {
76 std::vector<uint8_t> challenge(kChallengeSize);
77
78 ssize_t bytesRemaining = static_cast<ssize_t>(challenge.size());
79 uint8_t* writePtr = challenge.data();
80 while (bytesRemaining > 0) {
81 int bytesRead = getrandom(writePtr, bytesRemaining, /*flags=*/0);
82 if (bytesRead < 0) {
83 if (errno == EINTR) {
84 continue;
85 } else {
86 std::cerr << errno << ": " << strerror(errno) << std::endl;
87 exit(-1);
88 }
89 }
90 bytesRemaining -= bytesRead;
91 writePtr += bytesRead;
92 }
93
94 return challenge;
95}
96
Seth Mooreb84a1fb2022-09-13 12:02:49 -070097CborResult<Array> composeCertificateRequest(const ProtectedData& protectedData,
98 const DeviceInfo& verifiedDeviceInfo,
99 const std::vector<uint8_t>& challenge,
100 const std::vector<uint8_t>& keysToSignMac,
101 IRemotelyProvisionedComponent* provisionable) {
Seth Moore708da932022-08-18 14:38:05 -0700102 Array macedKeysToSign = Array()
103 .add(Map().add(1, 5).encode()) // alg: hmac-sha256
104 .add(Map()) // empty unprotected headers
105 .add(Null()) // nil for the payload
106 .add(keysToSignMac); // MAC as returned from the HAL
107
Seth Mooreb84a1fb2022-09-13 12:02:49 -0700108 ErrMsgOr<std::unique_ptr<Map>> parsedVerifiedDeviceInfo =
109 parseAndValidateDeviceInfo(verifiedDeviceInfo.deviceInfo, provisionable);
Seth Moore708da932022-08-18 14:38:05 -0700110 if (!parsedVerifiedDeviceInfo) {
Seth Mooreb84a1fb2022-09-13 12:02:49 -0700111 return {nullptr, parsedVerifiedDeviceInfo.moveMessage()};
Seth Moore708da932022-08-18 14:38:05 -0700112 }
113
Seth Mooreb84a1fb2022-09-13 12:02:49 -0700114 auto [parsedProtectedData, ignore2, errMsg] = parse(protectedData.protectedData);
Seth Moore708da932022-08-18 14:38:05 -0700115 if (!parsedProtectedData) {
Seth Mooreb84a1fb2022-09-13 12:02:49 -0700116 std::cerr << "Error parsing protected data: '" << errMsg << "'" << std::endl;
Seth Moore708da932022-08-18 14:38:05 -0700117 return {nullptr, errMsg};
118 }
119
Seth Mooreb84a1fb2022-09-13 12:02:49 -0700120 Array deviceInfo = Array().add(parsedVerifiedDeviceInfo.moveValue()).add(Map());
Seth Moore708da932022-08-18 14:38:05 -0700121
122 auto certificateRequest = std::make_unique<Array>();
123 (*certificateRequest)
124 .add(std::move(deviceInfo))
125 .add(challenge)
126 .add(std::move(parsedProtectedData))
127 .add(std::move(macedKeysToSign));
Seth Mooreb84a1fb2022-09-13 12:02:49 -0700128 return {std::move(certificateRequest), ""};
Seth Moore708da932022-08-18 14:38:05 -0700129}
130
Seth Mooreb84a1fb2022-09-13 12:02:49 -0700131CborResult<Array> getCsr(std::string_view componentName, IRemotelyProvisionedComponent* irpc) {
Seth Moore708da932022-08-18 14:38:05 -0700132 std::vector<uint8_t> keysToSignMac;
133 std::vector<MacedPublicKey> emptyKeys;
134 DeviceInfo verifiedDeviceInfo;
135 ProtectedData protectedData;
136 RpcHardwareInfo hwInfo;
137 ::ndk::ScopedAStatus status = irpc->getHardwareInfo(&hwInfo);
138 if (!status.isOk()) {
139 std::cerr << "Failed to get hardware info for '" << componentName
140 << "'. Error code: " << status.getServiceSpecificError() << "." << std::endl;
141 exit(-1);
142 }
143
144 const std::vector<uint8_t> eek = getProdEekChain(hwInfo.supportedEekCurve);
145 const std::vector<uint8_t> challenge = generateChallenge();
146 status = irpc->generateCertificateRequest(
147 /*test_mode=*/false, emptyKeys, eek, challenge, &verifiedDeviceInfo, &protectedData,
148 &keysToSignMac);
149 if (!status.isOk()) {
150 std::cerr << "Bundle extraction failed for '" << componentName
151 << "'. Error code: " << status.getServiceSpecificError() << "." << std::endl;
152 exit(-1);
153 }
Seth Mooreb84a1fb2022-09-13 12:02:49 -0700154 return composeCertificateRequest(protectedData, verifiedDeviceInfo, challenge, keysToSignMac,
155 irpc);
Seth Moore708da932022-08-18 14:38:05 -0700156}