• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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