• 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 <assert.h>
21 
22 #include <keymaster/cppcose/cppcose.h>
23 #include <keymaster/logger.h>
24 
25 #include <openssl/bn.h>
26 #include <openssl/ec.h>
27 #include <openssl/hkdf.h>
28 #include <openssl/rand.h>
29 
30 namespace keymaster {
31 
32 using cppcose::constructCoseSign1;
33 using cppcose::CoseKey;
34 using cppcose::ED25519;
35 using cppcose::EDDSA;
36 using cppcose::OCTET_KEY_PAIR;
37 using cppcose::VERIFY;
38 
39 constexpr uint32_t kMacKeyLength = 32;
40 
PureSoftRemoteProvisioningContext()41 PureSoftRemoteProvisioningContext::PureSoftRemoteProvisioningContext() {
42     std::tie(devicePrivKey_, bcc_) = GenerateBcc(/*testMode=*/false);
43 }
44 
~PureSoftRemoteProvisioningContext()45 PureSoftRemoteProvisioningContext::~PureSoftRemoteProvisioningContext() {}
46 
47 std::vector<uint8_t>
DeriveBytesFromHbk(const std::string & context,size_t num_bytes) const48 PureSoftRemoteProvisioningContext::DeriveBytesFromHbk(const std::string& context,
49                                                       size_t num_bytes) const {
50     // bytevec fakeHbk(32, 0);
51     // bytevec result(numBytes);
52     // is it safe to revert the call below back to the call above?
53     std::vector<uint8_t> fakeHbk(32);
54     std::vector<uint8_t> result(num_bytes);
55 
56     // TODO: Figure out if HKDF can fail.  It doesn't seem like it should be able to,
57     // but the function does return an error code.
58     HKDF(result.data(), num_bytes,              //
59          EVP_sha256(),                          //
60          fakeHbk.data(), fakeHbk.size(),        //
61          nullptr /* salt */, 0 /* salt len */,  //
62          reinterpret_cast<const uint8_t*>(context.data()), context.size());
63 
64     return result;
65 }
66 
CreateDeviceInfo() const67 std::unique_ptr<cppbor::Map> PureSoftRemoteProvisioningContext::CreateDeviceInfo() const {
68     auto result = std::make_unique<cppbor::Map>(cppbor::Map());
69 
70     // The following placeholders show how the DeviceInfo map would be populated.
71     // result->add(cppbor::Tstr("brand"), cppbor::Tstr("Google"));
72     // result->add(cppbor::Tstr("manufacturer"), cppbor::Tstr("Google"));
73     // result->add(cppbor::Tstr("product"), cppbor::Tstr("Fake"));
74     // result->add(cppbor::Tstr("model"), cppbor::Tstr("Imaginary"));
75     // result->add(cppbor::Tstr("board"), cppbor::Tstr("Chess"));
76     // result->add(cppbor::Tstr("vb_state"), cppbor::Tstr("orange"));
77     // result->add(cppbor::Tstr("bootloader_state"), cppbor::Tstr("unlocked"));
78     // result->add(cppbor::Tstr("os_version"), cppbor::Tstr("SC"));
79     // result->add(cppbor::Tstr("system_patch_level"), cppbor::Uint(20210331));
80     // result->add(cppbor::Tstr("boot_patch_level"), cppbor::Uint(20210331));
81     // result->add(cppbor::Tstr("vendor_patch_level"), cppbor::Uint(20210331));
82 
83     result->canonicalize();
84     return result;
85 }
86 
87 std::pair<std::vector<uint8_t> /* privKey */, cppbor::Array /* BCC */>
GenerateBcc(bool testMode) const88 PureSoftRemoteProvisioningContext::GenerateBcc(bool testMode) const {
89     std::vector<uint8_t> privKey(ED25519_PRIVATE_KEY_LEN);
90     std::vector<uint8_t> pubKey(ED25519_PUBLIC_KEY_LEN);
91 
92     uint8_t seed[32];  // Length is hard-coded in the BoringCrypto API
93     if (testMode) {
94         RAND_bytes(seed, sizeof(seed));
95     } else {
96         auto seed_vector = DeriveBytesFromHbk("Device Key Seed", sizeof(seed));
97         std::copy(seed_vector.begin(), seed_vector.end(), seed);
98     }
99     ED25519_keypair_from_seed(pubKey.data(), privKey.data(), seed);
100 
101     auto coseKey = cppbor::Map()
102                        .add(CoseKey::KEY_TYPE, OCTET_KEY_PAIR)
103                        .add(CoseKey::ALGORITHM, EDDSA)
104                        .add(CoseKey::CURVE, ED25519)
105                        .add(CoseKey::KEY_OPS, VERIFY)
106                        .add(CoseKey::PUBKEY_X, pubKey)
107                        .canonicalize();
108     auto sign1Payload = cppbor::Map()
109                             .add(1 /* Issuer */, "Issuer")
110                             .add(2 /* Subject */, "Subject")
111                             .add(-4670552 /* Subject Pub Key */, coseKey.encode())
112                             .add(-4670553 /* Key Usage (little-endian order) */,
113                                  std::vector<uint8_t>{0x20} /* keyCertSign = 1<<5 */)
114                             .canonicalize()
115                             .encode();
116     auto coseSign1 = constructCoseSign1(privKey,       /* signing key */
117                                         cppbor::Map(), /* extra protected */
118                                         sign1Payload, {} /* AAD */);
119     assert(coseSign1);
120 
121     return {privKey, cppbor::Array().add(std::move(coseKey)).add(coseSign1.moveValue())};
122 }
123 
124 std::optional<cppcose::HmacSha256>
GenerateHmacSha256(const cppcose::bytevec & input) const125 PureSoftRemoteProvisioningContext::GenerateHmacSha256(const cppcose::bytevec& input) const {
126     auto key = DeriveBytesFromHbk("Key to MAC public keys", kMacKeyLength);
127     auto result = cppcose::generateHmacSha256(key, input);
128     if (!result) {
129         LOG_E("Error signing MAC: %s", result.message().c_str());
130         return std::nullopt;
131     }
132     return *result;
133 }
134 
135 }  // namespace keymaster
136