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