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 <keymaster/contexts/pure_soft_remote_provisioning_context.h>
18
19 #include <algorithm>
20 #include <android-base/logging.h>
21 #include <assert.h>
22
23 #include <keymaster/cppcose/cppcose.h>
24 #include <keymaster/logger.h>
25
26 #include <openssl/bn.h>
27 #include <openssl/ec.h>
28 #include <openssl/hkdf.h>
29 #include <openssl/rand.h>
30
31 namespace keymaster {
32 namespace {
33
34 using cppcose::constructCoseSign1;
35 using cppcose::CoseKey;
36 using cppcose::ED25519;
37 using cppcose::EDDSA;
38 using cppcose::ErrMsgOr;
39 using cppcose::OCTET_KEY_PAIR;
40 using cppcose::VERIFY;
41
GetRandomBytes()42 std::array<uint8_t, 32> GetRandomBytes() {
43 std::array<uint8_t, 32> bytes;
44 // This is used in code paths that cannot fail, so CHECK. If it turns
45 // out that we can actually run out of entropy during thes code paths,
46 // we'll need to refactor the interfaces to allow errors to propagate.
47 CHECK_EQ(RAND_bytes(bytes.data(), bytes.size()), 1) << "Unable to get random bytes";
48 return bytes;
49 }
50
51 } // namespace
52
PureSoftRemoteProvisioningContext(keymaster_security_level_t security_level)53 PureSoftRemoteProvisioningContext::PureSoftRemoteProvisioningContext(
54 keymaster_security_level_t security_level)
55 : security_level_(security_level) {}
56
57 std::vector<uint8_t>
DeriveBytesFromHbk(const std::string & context,size_t num_bytes) const58 PureSoftRemoteProvisioningContext::DeriveBytesFromHbk(const std::string& context,
59 size_t num_bytes) const {
60 static const std::array<uint8_t, 32> fakeHbk = GetRandomBytes();
61 std::vector<uint8_t> result(num_bytes);
62
63 // TODO: Figure out if HKDF can fail. It doesn't seem like it should be able to,
64 // but the function does return an error code.
65 HKDF(result.data(), num_bytes, //
66 EVP_sha256(), //
67 fakeHbk.data(), fakeHbk.size(), //
68 nullptr /* salt */, 0 /* salt len */, //
69 reinterpret_cast<const uint8_t*>(context.data()), context.size());
70
71 return result;
72 }
73
74 std::unique_ptr<cppbor::Map>
CreateDeviceInfo(uint32_t csrVersion) const75 PureSoftRemoteProvisioningContext::CreateDeviceInfo(uint32_t csrVersion) const {
76 auto result = std::make_unique<cppbor::Map>(cppbor::Map());
77
78 // The following placeholders show how the DeviceInfo map would be populated.
79 result->add(cppbor::Tstr("brand"), cppbor::Tstr("Google"));
80 result->add(cppbor::Tstr("manufacturer"), cppbor::Tstr("Google"));
81 result->add(cppbor::Tstr("product"), cppbor::Tstr("Fake Product"));
82 result->add(cppbor::Tstr("model"), cppbor::Tstr("Fake Model"));
83 result->add(cppbor::Tstr("device"), cppbor::Tstr("Fake Device"));
84 if (bootloader_state_) {
85 result->add(cppbor::Tstr("bootloader_state"), cppbor::Tstr(*bootloader_state_));
86 }
87 if (verified_boot_state_) {
88 result->add(cppbor::Tstr("vb_state"), cppbor::Tstr(*verified_boot_state_));
89 }
90 if (vbmeta_digest_) {
91 result->add(cppbor::Tstr("vbmeta_digest"), cppbor::Bstr(*vbmeta_digest_));
92 }
93 if (os_version_) {
94 result->add(cppbor::Tstr("os_version"), cppbor::Tstr(std::to_string(*os_version_)));
95 }
96 if (os_patchlevel_) {
97 result->add(cppbor::Tstr("system_patch_level"), cppbor::Uint(*os_patchlevel_));
98 }
99 if (boot_patchlevel_) {
100 result->add(cppbor::Tstr("boot_patch_level"), cppbor::Uint(*boot_patchlevel_));
101 }
102 if (vendor_patchlevel_) {
103 result->add(cppbor::Tstr("vendor_patch_level"), cppbor::Uint(*vendor_patchlevel_));
104 }
105 // "version" field was removed from DeviceInfo in CSR v3.
106 if (csrVersion < 3) {
107 result->add(cppbor::Tstr("version"), cppbor::Uint(csrVersion));
108 }
109 result->add(cppbor::Tstr("fused"), cppbor::Uint(0));
110
111 // "software" security level is not supported, so lie and say we're a TEE
112 // even if we're software.
113 const char* security_level =
114 security_level_ == KM_SECURITY_LEVEL_STRONGBOX ? "strongbox" : "tee";
115 result->add(cppbor::Tstr("security_level"), cppbor::Tstr(security_level));
116
117 result->canonicalize();
118 return result;
119 }
120
LazyInitProdBcc() const121 void PureSoftRemoteProvisioningContext::LazyInitProdBcc() const {
122 std::call_once(bccInitFlag_,
123 [this]() { std::tie(devicePrivKey_, bcc_) = GenerateBcc(/*testMode=*/false); });
124 }
125
126 std::pair<std::vector<uint8_t> /* privKey */, cppbor::Array /* BCC */>
GenerateBcc(bool testMode) const127 PureSoftRemoteProvisioningContext::GenerateBcc(bool testMode) const {
128 std::vector<uint8_t> privKey(ED25519_PRIVATE_KEY_LEN);
129 std::vector<uint8_t> pubKey(ED25519_PUBLIC_KEY_LEN);
130
131 std::array<uint8_t, 32> seed; // Length is hard-coded in the BoringCrypto API
132 if (testMode) {
133 seed = GetRandomBytes();
134 } else {
135 auto seed_vector = DeriveBytesFromHbk("Device Key Seed", sizeof(seed));
136 std::copy(seed_vector.begin(), seed_vector.end(), seed.begin());
137 }
138 ED25519_keypair_from_seed(pubKey.data(), privKey.data(), seed.data());
139
140 auto coseKey = cppbor::Map()
141 .add(CoseKey::KEY_TYPE, OCTET_KEY_PAIR)
142 .add(CoseKey::ALGORITHM, EDDSA)
143 .add(CoseKey::CURVE, ED25519)
144 .add(CoseKey::PUBKEY_X, pubKey)
145 .canonicalize();
146 auto sign1Payload = cppbor::Map()
147 .add(1 /* Issuer */, "Issuer")
148 .add(2 /* Subject */, "Subject")
149 .add(-4670552 /* Subject Pub Key */, coseKey.encode())
150 .add(-4670553 /* Key Usage (little-endian order) */,
151 std::vector<uint8_t>{0x20} /* keyCertSign = 1<<5 */)
152 .canonicalize()
153 .encode();
154 auto coseSign1 = constructCoseSign1(privKey, /* signing key */
155 cppbor::Map(), /* extra protected */
156 sign1Payload, {} /* AAD */);
157 assert(coseSign1);
158
159 return {privKey, cppbor::Array().add(std::move(coseKey)).add(coseSign1.moveValue())};
160 }
161
BuildProtectedDataPayload(bool isTestMode,const std::vector<uint8_t> & macKey,const std::vector<uint8_t> & aad) const162 ErrMsgOr<std::vector<uint8_t>> PureSoftRemoteProvisioningContext::BuildProtectedDataPayload(
163 bool isTestMode, //
164 const std::vector<uint8_t>& macKey, //
165 const std::vector<uint8_t>& aad) const {
166 std::vector<uint8_t> devicePrivKey;
167 cppbor::Array bcc;
168 if (isTestMode) {
169 std::tie(devicePrivKey, bcc) = GenerateBcc(/*testMode=*/true);
170 } else {
171 LazyInitProdBcc();
172 devicePrivKey = devicePrivKey_;
173 auto clone = bcc_.clone();
174 if (!clone->asArray()) {
175 return "The BCC is not an array";
176 }
177 bcc = std::move(*clone->asArray());
178 }
179 auto sign1 = constructCoseSign1(devicePrivKey, macKey, aad);
180 if (!sign1) {
181 return sign1.moveMessage();
182 }
183 return cppbor::Array().add(sign1.moveValue()).add(std::move(bcc)).encode();
184 }
185
186 std::optional<cppcose::HmacSha256>
GenerateHmacSha256(const cppcose::bytevec & input) const187 PureSoftRemoteProvisioningContext::GenerateHmacSha256(const cppcose::bytevec& input) const {
188 // Fix the key for now, else HMACs will fail to verify after reboot.
189 static const uint8_t kHmacKey[] = "Key to MAC public keys";
190 std::vector<uint8_t> key(std::begin(kHmacKey), std::end(kHmacKey));
191 auto result = cppcose::generateHmacSha256(key, input);
192 if (!result) {
193 LOG_E("Error signing MAC: %s", result.message().c_str());
194 return std::nullopt;
195 }
196 return *result;
197 }
198
GetHwInfo(GetHwInfoResponse * hwInfo) const199 void PureSoftRemoteProvisioningContext::GetHwInfo(GetHwInfoResponse* hwInfo) const {
200 hwInfo->version = 3;
201 hwInfo->rpcAuthorName = "Google";
202 hwInfo->supportedEekCurve = 2 /* CURVE_25519 */;
203 hwInfo->uniqueId = "default keymint";
204 hwInfo->supportedNumKeysInCsr = 20;
205 }
206
207 cppcose::ErrMsgOr<cppbor::Array>
BuildCsr(const std::vector<uint8_t> & challenge,cppbor::Array keysToSign) const208 PureSoftRemoteProvisioningContext::BuildCsr(const std::vector<uint8_t>& challenge,
209 cppbor::Array keysToSign) const {
210 LazyInitProdBcc();
211 uint32_t csrVersion = 3;
212 auto deviceInfo = std::move(*CreateDeviceInfo(csrVersion));
213 auto csrPayload = cppbor::Array()
214 .add(csrVersion)
215 .add("keymint" /* CertificateType */)
216 .add(std::move(deviceInfo))
217 .add(std::move(keysToSign));
218 auto signedDataPayload = cppbor::Array().add(challenge).add(cppbor::Bstr(csrPayload.encode()));
219 auto signedData = constructCoseSign1(devicePrivKey_, signedDataPayload.encode(), {} /* aad */);
220
221 return cppbor::Array()
222 .add(1 /* version */)
223 .add(cppbor::Map() /* UdsCerts */)
224 .add(std::move(*bcc_.clone()->asArray()) /* DiceCertChain */)
225 .add(std::move(*signedData) /* SignedData */);
226 }
227
SetSystemVersion(uint32_t os_version,uint32_t os_patchlevel)228 void PureSoftRemoteProvisioningContext::SetSystemVersion(uint32_t os_version,
229 uint32_t os_patchlevel) {
230 os_version_ = os_version;
231 os_patchlevel_ = os_patchlevel;
232 }
233
SetVendorPatchlevel(uint32_t vendor_patchlevel)234 void PureSoftRemoteProvisioningContext::SetVendorPatchlevel(uint32_t vendor_patchlevel) {
235 vendor_patchlevel_ = vendor_patchlevel;
236 }
237
SetBootPatchlevel(uint32_t boot_patchlevel)238 void PureSoftRemoteProvisioningContext::SetBootPatchlevel(uint32_t boot_patchlevel) {
239 boot_patchlevel_ = boot_patchlevel;
240 }
241
SetVerifiedBootInfo(std::string_view boot_state,std::string_view bootloader_state,const std::vector<uint8_t> & vbmeta_digest)242 void PureSoftRemoteProvisioningContext::SetVerifiedBootInfo(
243 std::string_view boot_state, std::string_view bootloader_state,
244 const std::vector<uint8_t>& vbmeta_digest) {
245 verified_boot_state_ = boot_state;
246 bootloader_state_ = bootloader_state;
247 vbmeta_digest_ = vbmeta_digest;
248 }
249
250 } // namespace keymaster
251