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
CreateDeviceInfo() const74 std::unique_ptr<cppbor::Map> PureSoftRemoteProvisioningContext::CreateDeviceInfo() const {
75 auto result = std::make_unique<cppbor::Map>(cppbor::Map());
76
77 // The following placeholders show how the DeviceInfo map would be populated.
78 result->add(cppbor::Tstr("brand"), cppbor::Tstr("Google"));
79 result->add(cppbor::Tstr("manufacturer"), cppbor::Tstr("Google"));
80 result->add(cppbor::Tstr("product"), cppbor::Tstr("Fake Product"));
81 result->add(cppbor::Tstr("model"), cppbor::Tstr("Fake Model"));
82 result->add(cppbor::Tstr("device"), cppbor::Tstr("Fake Device"));
83 if (bootloader_state_) {
84 result->add(cppbor::Tstr("bootloader_state"), cppbor::Tstr(*bootloader_state_));
85 }
86 if (verified_boot_state_) {
87 result->add(cppbor::Tstr("vb_state"), cppbor::Tstr(*verified_boot_state_));
88 }
89 if (vbmeta_digest_) {
90 result->add(cppbor::Tstr("vbmeta_digest"), cppbor::Bstr(*vbmeta_digest_));
91 }
92 if (os_version_) {
93 result->add(cppbor::Tstr("os_version"), cppbor::Tstr(std::to_string(*os_version_)));
94 }
95 if (os_patchlevel_) {
96 result->add(cppbor::Tstr("system_patch_level"), cppbor::Uint(*os_patchlevel_));
97 }
98 if (boot_patchlevel_) {
99 result->add(cppbor::Tstr("boot_patch_level"), cppbor::Uint(*boot_patchlevel_));
100 }
101 if (vendor_patchlevel_) {
102 result->add(cppbor::Tstr("vendor_patch_level"), cppbor::Uint(*vendor_patchlevel_));
103 }
104 result->add(cppbor::Tstr("version"), cppbor::Uint(2));
105 result->add(cppbor::Tstr("fused"), cppbor::Uint(0));
106
107 // "software" security level is not supported, so lie and say we're a TEE
108 // even if we're software.
109 const char* security_level =
110 security_level_ == KM_SECURITY_LEVEL_STRONGBOX ? "strongbox" : "tee";
111 result->add(cppbor::Tstr("security_level"), cppbor::Tstr(security_level));
112
113 result->canonicalize();
114 return result;
115 }
116
LazyInitProdBcc() const117 void PureSoftRemoteProvisioningContext::LazyInitProdBcc() const {
118 std::call_once(bccInitFlag_,
119 [this]() { std::tie(devicePrivKey_, bcc_) = GenerateBcc(/*testMode=*/false); });
120 }
121
122 std::pair<std::vector<uint8_t> /* privKey */, cppbor::Array /* BCC */>
GenerateBcc(bool testMode) const123 PureSoftRemoteProvisioningContext::GenerateBcc(bool testMode) const {
124 std::vector<uint8_t> privKey(ED25519_PRIVATE_KEY_LEN);
125 std::vector<uint8_t> pubKey(ED25519_PUBLIC_KEY_LEN);
126
127 std::array<uint8_t, 32> seed; // Length is hard-coded in the BoringCrypto API
128 if (testMode) {
129 seed = GetRandomBytes();
130 } else {
131 auto seed_vector = DeriveBytesFromHbk("Device Key Seed", sizeof(seed));
132 std::copy(seed_vector.begin(), seed_vector.end(), seed.begin());
133 }
134 ED25519_keypair_from_seed(pubKey.data(), privKey.data(), seed.data());
135
136 auto coseKey = cppbor::Map()
137 .add(CoseKey::KEY_TYPE, OCTET_KEY_PAIR)
138 .add(CoseKey::ALGORITHM, EDDSA)
139 .add(CoseKey::CURVE, ED25519)
140 .add(CoseKey::KEY_OPS, VERIFY)
141 .add(CoseKey::PUBKEY_X, pubKey)
142 .canonicalize();
143 auto sign1Payload = cppbor::Map()
144 .add(1 /* Issuer */, "Issuer")
145 .add(2 /* Subject */, "Subject")
146 .add(-4670552 /* Subject Pub Key */, coseKey.encode())
147 .add(-4670553 /* Key Usage (little-endian order) */,
148 std::vector<uint8_t>{0x20} /* keyCertSign = 1<<5 */)
149 .canonicalize()
150 .encode();
151 auto coseSign1 = constructCoseSign1(privKey, /* signing key */
152 cppbor::Map(), /* extra protected */
153 sign1Payload, {} /* AAD */);
154 assert(coseSign1);
155
156 return {privKey, cppbor::Array().add(std::move(coseKey)).add(coseSign1.moveValue())};
157 }
158
BuildProtectedDataPayload(bool isTestMode,const std::vector<uint8_t> & macKey,const std::vector<uint8_t> & aad) const159 ErrMsgOr<std::vector<uint8_t>> PureSoftRemoteProvisioningContext::BuildProtectedDataPayload(
160 bool isTestMode, //
161 const std::vector<uint8_t>& macKey, //
162 const std::vector<uint8_t>& aad) const {
163 std::vector<uint8_t> devicePrivKey;
164 cppbor::Array bcc;
165 if (isTestMode) {
166 std::tie(devicePrivKey, bcc) = GenerateBcc(/*testMode=*/true);
167 } else {
168 LazyInitProdBcc();
169 devicePrivKey = devicePrivKey_;
170 auto clone = bcc_.clone();
171 if (!clone->asArray()) {
172 return "The BCC is not an array";
173 }
174 bcc = std::move(*clone->asArray());
175 }
176 auto sign1 = constructCoseSign1(devicePrivKey, macKey, aad);
177 if (!sign1) {
178 return sign1.moveMessage();
179 }
180 return cppbor::Array().add(sign1.moveValue()).add(std::move(bcc)).encode();
181 }
182
183 std::optional<cppcose::HmacSha256>
GenerateHmacSha256(const cppcose::bytevec & input) const184 PureSoftRemoteProvisioningContext::GenerateHmacSha256(const cppcose::bytevec& input) const {
185 // Fix the key for now, else HMACs will fail to verify after reboot.
186 static const uint8_t kHmacKey[] = "Key to MAC public keys";
187 std::vector<uint8_t> key(std::begin(kHmacKey), std::end(kHmacKey));
188 auto result = cppcose::generateHmacSha256(key, input);
189 if (!result) {
190 LOG_E("Error signing MAC: %s", result.message().c_str());
191 return std::nullopt;
192 }
193 return *result;
194 }
195
SetSystemVersion(uint32_t os_version,uint32_t os_patchlevel)196 void PureSoftRemoteProvisioningContext::SetSystemVersion(uint32_t os_version,
197 uint32_t os_patchlevel) {
198 os_version_ = os_version;
199 os_patchlevel_ = os_patchlevel;
200 }
201
SetVendorPatchlevel(uint32_t vendor_patchlevel)202 void PureSoftRemoteProvisioningContext::SetVendorPatchlevel(uint32_t vendor_patchlevel) {
203 vendor_patchlevel_ = vendor_patchlevel;
204 }
205
SetBootPatchlevel(uint32_t boot_patchlevel)206 void PureSoftRemoteProvisioningContext::SetBootPatchlevel(uint32_t boot_patchlevel) {
207 boot_patchlevel_ = boot_patchlevel;
208 }
209
SetVerifiedBootInfo(std::string_view boot_state,std::string_view bootloader_state,const std::vector<uint8_t> & vbmeta_digest)210 void PureSoftRemoteProvisioningContext::SetVerifiedBootInfo(
211 std::string_view boot_state, std::string_view bootloader_state,
212 const std::vector<uint8_t>& vbmeta_digest) {
213 verified_boot_state_ = boot_state;
214 bootloader_state_ = bootloader_state;
215 vbmeta_digest_ = vbmeta_digest;
216 }
217
218 } // namespace keymaster
219