1 /*
2 * Copyright 2021 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 "trusty_remote_provisioning_context.h"
18
19 #include <assert.h>
20 #include <keymaster/cppcose/cppcose.h>
21 #include <keymaster/logger.h>
22 #include <lib/hwbcc/client/hwbcc.h>
23 #include <lib/hwkey/hwkey.h>
24 #include <lib/system_state/system_state.h>
25 #include <openssl/bn.h>
26 #include <openssl/ec.h>
27 #include <openssl/hkdf.h>
28 #include <openssl/rand.h>
29 #include <algorithm>
30 #include <cstdint>
31
32 #include "keymaster_attributes.pb.h"
33 #include "secure_storage_manager.h"
34
35 namespace keymaster {
36
37 using cppcose::ALGORITHM;
38 using cppcose::constructCoseSign1;
39 using cppcose::CoseKey;
40 using cppcose::ED25519;
41 using cppcose::EDDSA;
42 using cppcose::ErrMsgOr;
43 using cppcose::OCTET_KEY_PAIR;
44 using cppcose::VERIFY;
45
46 constexpr uint32_t kMacKeyLength = 32;
47 constexpr uint32_t kRkpVersion = TRUSTY_KM_RKP_VERSION;
48
49 static const uint8_t kMasterKeyDerivationData[kMacKeyLength] =
50 "RemoteKeyProvisioningMasterKey";
51
DeriveBytesFromHbk(const std::string & context,size_t num_bytes) const52 std::vector<uint8_t> TrustyRemoteProvisioningContext::DeriveBytesFromHbk(
53 const std::string& context,
54 size_t num_bytes) const {
55 long rc = hwkey_open();
56 if (rc < 0) {
57 LOG_S("Couldn't open hwkey session: %ld", rc);
58 return {};
59 }
60
61 hwkey_session_t session = static_cast<hwkey_session_t>(rc);
62 std::array<uint8_t, kMacKeyLength> hw_backed_key;
63
64 uint32_t kdf_version = HWKEY_KDF_VERSION_1;
65 rc = hwkey_derive(session, &kdf_version, kMasterKeyDerivationData,
66 hw_backed_key.data(), kMacKeyLength);
67
68 if (rc < 0) {
69 LOG_S("Error deriving master key: %ld", rc);
70 return {};
71 }
72
73 hwkey_close(session);
74
75 std::vector<uint8_t> result(num_bytes);
76
77 // TODO: Figure out if HKDF can fail. It doesn't seem like it should be
78 // able to, but the function does return an error code.
79 HKDF(result.data(), num_bytes, //
80 EVP_sha256(), //
81 hw_backed_key.data(), hw_backed_key.size(), //
82 nullptr /* salt */, 0 /* salt len */, //
83 reinterpret_cast<const uint8_t*>(context.data()), context.size());
84
85 return result;
86 }
87
ReadAttestationIds(AttestationIds * ids)88 keymaster_error_t ReadAttestationIds(AttestationIds* ids) {
89 SecureStorageManager* ss_manager = SecureStorageManager::get_instance();
90 if (ss_manager == nullptr) {
91 LOG_E("Failed to open secure storage session.");
92 return KM_ERROR_SECURE_HW_BUSY;
93 }
94
95 auto err = ss_manager->ReadAttestationIds(ids);
96 if (err != KM_ERROR_OK) {
97 LOG_E("Failed to read attestation IDs");
98 return err;
99 }
100 return KM_ERROR_OK;
101 }
102
103 #define ADD_ID_FIELD(array, proto, field_name) \
104 if ((proto).size > 0) { \
105 (array)->add( \
106 (field_name), \
107 cppbor::Tstr((proto).bytes, (proto).bytes + (proto).size)); \
108 }
109
CreateDeviceInfo(uint32_t csrVersion) const110 std::unique_ptr<cppbor::Map> TrustyRemoteProvisioningContext::CreateDeviceInfo(
111 uint32_t csrVersion) const {
112 auto result = std::make_unique<cppbor::Map>();
113 AttestationIds ids;
114 if (ReadAttestationIds(&ids) != KM_ERROR_OK) {
115 return result;
116 }
117 ADD_ID_FIELD(result, ids.brand, "brand")
118 ADD_ID_FIELD(result, ids.manufacturer, "manufacturer")
119 ADD_ID_FIELD(result, ids.product, "product")
120 ADD_ID_FIELD(result, ids.model, "model")
121 ADD_ID_FIELD(result, ids.device, "device")
122 if (bootParams_) {
123 // KM validated device_locked and verified_boot_state combinations, so
124 // there is no need to re-validate here.
125 switch (bootParams_->verified_boot_state) {
126 case KM_VERIFIED_BOOT_VERIFIED:
127 result->add("vb_state", "green");
128 break;
129 case KM_VERIFIED_BOOT_SELF_SIGNED:
130 result->add("vb_state", "yellow");
131 break;
132 case KM_VERIFIED_BOOT_UNVERIFIED:
133 result->add("vb_state", "orange");
134 break;
135 default:
136 break;
137 }
138 result->add("bootloader_state",
139 bootParams_->device_locked ? "locked" : "unlocked");
140 result->add("vbmeta_digest",
141 cppbor::Bstr(bootParams_->verified_boot_hash.begin(),
142 bootParams_->verified_boot_hash.end()));
143 result->add("os_version", std::to_string(bootParams_->boot_os_version));
144 result->add("system_patch_level",
145 cppbor::Uint(bootParams_->boot_os_patchlevel));
146 result->add("boot_patch_level", cppbor::Uint(boot_patchlevel_));
147 result->add("vendor_patch_level", cppbor::Uint(vendor_patchlevel_));
148 result->add("fused", system_state_get_flag_default(
149 SYSTEM_STATE_FLAG_APP_LOADING_UNLOCKED,
150 0 /* default */)
151 ? 0
152 : 1);
153 result->add("security_level", "tee");
154 // "version" field was removed from DeviceInfo in CSR v3.
155 if (csrVersion < 3) {
156 result->add("version", csrVersion);
157 }
158 }
159
160 result->canonicalize();
161 return result;
162 }
163
164 cppcose::ErrMsgOr<std::vector<uint8_t>>
BuildProtectedDataPayload(bool testMode,const std::vector<uint8_t> & macKey,const std::vector<uint8_t> & aad) const165 TrustyRemoteProvisioningContext::BuildProtectedDataPayload(
166 bool testMode,
167 const std::vector<uint8_t>& macKey,
168 const std::vector<uint8_t>& aad) const {
169 std::vector<uint8_t> signedOutput(HWBCC_MAX_RESP_PAYLOAD_SIZE);
170 std::vector<uint8_t> bcc(HWBCC_MAX_RESP_PAYLOAD_SIZE);
171 size_t actualBccSize = 0;
172 size_t actualSignedMacKeySize = 0;
173 int rc = hwbcc_get_protected_data(
174 testMode, EDDSA, macKey.data(), macKey.size(), aad.data(),
175 aad.size(), signedOutput.data(), signedOutput.size(),
176 &actualSignedMacKeySize, bcc.data(), bcc.size(), &actualBccSize);
177 if (rc != 0) {
178 LOG_E("Error: [%d] Failed to sign the MAC key on WHI", rc);
179 return "Failed to sign the MAC key on WHI";
180 }
181 signedOutput.resize(actualSignedMacKeySize);
182 bcc.resize(actualBccSize);
183 return cppbor::Array()
184 .add(cppbor::EncodedItem(std::move(signedOutput)))
185 .add(cppbor::EncodedItem(std::move(bcc)))
186 .encode();
187 }
188
189 std::optional<cppcose::HmacSha256>
GenerateHmacSha256(const cppcose::bytevec & input) const190 TrustyRemoteProvisioningContext::GenerateHmacSha256(
191 const cppcose::bytevec& input) const {
192 auto key = DeriveBytesFromHbk("Key to MAC public keys", kMacKeyLength);
193 auto result = cppcose::generateHmacSha256(key, input);
194 if (!result) {
195 LOG_E("Error signing MAC: %s", result.message().c_str());
196 return std::nullopt;
197 }
198 return *result;
199 }
200
GetHwInfo(GetHwInfoResponse * hwInfo) const201 void TrustyRemoteProvisioningContext::GetHwInfo(
202 GetHwInfoResponse* hwInfo) const {
203 hwInfo->version = kRkpVersion;
204 hwInfo->rpcAuthorName = "Google";
205 hwInfo->supportedEekCurve =
206 kRkpVersion >= 3 ? 0 /* CURVE_NONE */ : 2 /* CURVE_25519 */;
207 hwInfo->uniqueId = "Google Trusty Implementation";
208 hwInfo->supportedNumKeysInCsr = 20;
209 }
210
BuildCsr(const std::vector<uint8_t> & challenge,cppbor::Array keysToSign) const211 cppcose::ErrMsgOr<cppbor::Array> TrustyRemoteProvisioningContext::BuildCsr(
212 const std::vector<uint8_t>& challenge,
213 cppbor::Array keysToSign) const {
214 uint32_t csrVersion = 3;
215 auto deviceInfo = std::move(*CreateDeviceInfo(csrVersion));
216 auto csrPayload = cppbor::Array()
217 .add(csrVersion)
218 .add("keymint" /* CertificateType */)
219 .add(std::move(deviceInfo))
220 .add(std::move(keysToSign))
221 .encode();
222 auto signedDataPayload = cppbor::Array()
223 .add(challenge)
224 .add(cppbor::Bstr(csrPayload))
225 .encode();
226
227 std::vector<uint8_t> signedData(HWBCC_MAX_RESP_PAYLOAD_SIZE);
228 std::vector<uint8_t> bcc(HWBCC_MAX_RESP_PAYLOAD_SIZE);
229 size_t actualSignedDataSize = 0;
230 size_t actualBccSize = 0;
231
232 int rc = hwbcc_get_protected_data(
233 false /* test_mode */, EDDSA, signedDataPayload.data(),
234 signedDataPayload.size(), NULL, 0, signedData.data(),
235 signedData.size(), &actualSignedDataSize, bcc.data(), bcc.size(),
236 &actualBccSize);
237 if (rc != 0) {
238 LOG_E("Error: [%d] Failed hwbcc_get_protected_data()", rc);
239 return "Failed hwbcc_get_protected_data";
240 }
241 signedData.resize(actualSignedDataSize);
242 bcc.resize(actualBccSize);
243
244 return cppbor::Array()
245 .add(1 /* version */)
246 .add(cppbor::Map() /* UdsCerts */)
247 .add(cppbor::EncodedItem(std::move(bcc)))
248 .add(cppbor::EncodedItem(std::move(signedData)));
249 }
250
SetBootParams(const BootParams * bootParams)251 void TrustyRemoteProvisioningContext::SetBootParams(
252 const BootParams* bootParams) {
253 if (bootParamsSet_) {
254 LOG_E("Boot parameters are already set in the remote provisioning context");
255 }
256 bootParamsSet_ = true;
257 bootParams_ = bootParams;
258 }
259
260 } // namespace keymaster
261