1 //
2 // Copyright (C) 2020 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 #include "tpm_keymaster_context.h"
17 
18 #include <android-base/logging.h>
19 #include <keymaster/contexts/soft_attestation_cert.h>
20 #include <keymaster/km_openssl/aes_key.h>
21 #include <keymaster/km_openssl/attestation_utils.h>
22 #include <keymaster/km_openssl/asymmetric_key.h>
23 #include <keymaster/km_openssl/ec_key_factory.h>
24 #include <keymaster/km_openssl/hmac_key.h>
25 #include <keymaster/km_openssl/rsa_key_factory.h>
26 #include <keymaster/km_openssl/soft_keymaster_enforcement.h>
27 #include <keymaster/km_openssl/triple_des_key.h>
28 
29 #include "host/commands/secure_env/tpm_attestation_record.h"
30 #include "host/commands/secure_env/tpm_random_source.h"
31 #include "host/commands/secure_env/tpm_key_blob_maker.h"
32 
33 using keymaster::AuthorizationSet;
34 using keymaster::KeymasterKeyBlob;
35 using keymaster::KeyFactory;
36 using keymaster::OperationFactory;
37 
TpmKeymasterContext(TpmResourceManager * resource_manager)38 TpmKeymasterContext::TpmKeymasterContext(TpmResourceManager* resource_manager)
39     : resource_manager_(resource_manager)
40     , key_blob_maker_(new TpmKeyBlobMaker(resource_manager_))
41     , random_source_(new TpmRandomSource(resource_manager_->Esys()))
42     , enforcement_(new keymaster::SoftKeymasterEnforcement(64, 64))
43     , attestation_context_(new TpmAttestationRecordContext()) {
44   // TODO(b/155697375): Replace SoftKeymasterEnforcement
45   key_factories_.emplace(
46       KM_ALGORITHM_RSA, new keymaster::RsaKeyFactory(key_blob_maker_.get()));
47   key_factories_.emplace(
48       KM_ALGORITHM_EC, new keymaster::EcKeyFactory(key_blob_maker_.get()));
49   key_factories_.emplace(
50       KM_ALGORITHM_AES,
51       new keymaster::AesKeyFactory(
52           key_blob_maker_.get(), random_source_.get()));
53   key_factories_.emplace(
54       KM_ALGORITHM_TRIPLE_DES,
55       new keymaster::TripleDesKeyFactory(
56           key_blob_maker_.get(), random_source_.get()));
57   key_factories_.emplace(
58       KM_ALGORITHM_HMAC,
59       new keymaster::HmacKeyFactory(
60           key_blob_maker_.get(), random_source_.get()));
61   for (const auto& it : key_factories_) {
62     supported_algorithms_.push_back(it.first);
63   }
64 }
65 
SetSystemVersion(uint32_t os_version,uint32_t os_patchlevel)66 keymaster_error_t TpmKeymasterContext::SetSystemVersion(
67     uint32_t os_version, uint32_t os_patchlevel) {
68   // TODO(b/155697375): Only accept new values of these from the bootloader
69   os_version_ = os_version;
70   os_patchlevel_ = os_patchlevel;
71   return KM_ERROR_OK;
72 }
73 
GetSystemVersion(uint32_t * os_version,uint32_t * os_patchlevel) const74 void TpmKeymasterContext::GetSystemVersion(
75     uint32_t* os_version, uint32_t* os_patchlevel) const {
76   *os_version = os_version_;
77   *os_patchlevel = os_patchlevel_;
78 }
79 
GetKeyFactory(keymaster_algorithm_t algorithm) const80 const KeyFactory* TpmKeymasterContext::GetKeyFactory(
81     keymaster_algorithm_t algorithm) const {
82   auto it = key_factories_.find(algorithm);
83   if (it == key_factories_.end()) {
84     LOG(ERROR) << "Could not find key factory for " << algorithm;
85     return nullptr;
86   }
87   return it->second.get();
88 }
89 
GetOperationFactory(keymaster_algorithm_t algorithm,keymaster_purpose_t purpose) const90 const OperationFactory* TpmKeymasterContext::GetOperationFactory(
91     keymaster_algorithm_t algorithm, keymaster_purpose_t purpose) const {
92   auto key_factory = GetKeyFactory(algorithm);
93   if (key_factory == nullptr) {
94     LOG(ERROR) << "Tried to get operation factory for " << purpose
95               << " for invalid algorithm " << algorithm;
96     return nullptr;
97   }
98   auto operation_factory = key_factory->GetOperationFactory(purpose);
99   if (operation_factory == nullptr) {
100     LOG(ERROR) << "Could not get operation factory for " << purpose
101                << " from key factory for " << algorithm;
102   }
103   return operation_factory;
104 }
105 
GetSupportedAlgorithms(size_t * algorithms_count) const106 const keymaster_algorithm_t* TpmKeymasterContext::GetSupportedAlgorithms(
107       size_t* algorithms_count) const {
108   *algorithms_count = supported_algorithms_.size();
109   return supported_algorithms_.data();
110 }
111 
112 // Based on https://cs.android.com/android/platform/superproject/+/master:system/keymaster/key_blob_utils/software_keyblobs.cpp;l=44;drc=master
113 
UpgradeIntegerTag(keymaster_tag_t tag,uint32_t value,AuthorizationSet * set,bool * set_changed)114 static bool UpgradeIntegerTag(
115     keymaster_tag_t tag,
116     uint32_t value,
117     AuthorizationSet* set,
118     bool* set_changed) {
119   int index = set->find(tag);
120   if (index == -1) {
121     keymaster_key_param_t param;
122     param.tag = tag;
123     param.integer = value;
124     set->push_back(param);
125     *set_changed = true;
126     return true;
127   }
128 
129   if (set->params[index].integer > value) {
130     return false;
131   }
132 
133   if (set->params[index].integer != value) {
134     set->params[index].integer = value;
135     *set_changed = true;
136   }
137   return true;
138 }
139 
140 // Based on https://cs.android.com/android/platform/superproject/+/master:system/keymaster/key_blob_utils/software_keyblobs.cpp;l=310;drc=master
141 
UpgradeKeyBlob(const KeymasterKeyBlob & blob_to_upgrade,const AuthorizationSet & upgrade_params,KeymasterKeyBlob * upgraded_key) const142 keymaster_error_t TpmKeymasterContext::UpgradeKeyBlob(
143     const KeymasterKeyBlob& blob_to_upgrade,
144     const AuthorizationSet& upgrade_params,
145     KeymasterKeyBlob* upgraded_key) const {
146   keymaster::UniquePtr<keymaster::Key> key;
147   auto error = ParseKeyBlob(blob_to_upgrade, upgrade_params, &key);
148   if (error != KM_ERROR_OK) {
149     return error;
150   }
151 
152   bool set_changed = false;
153 
154   if (os_version_ == 0) {
155     // We need to allow "upgrading" OS version to zero, to support upgrading
156     // from proper numbered releases to unnumbered development and preview
157     // releases.
158 
159     int key_os_version_pos = key->sw_enforced().find(keymaster::TAG_OS_VERSION);
160     if (key_os_version_pos != -1) {
161       uint32_t key_os_version = key->sw_enforced()[key_os_version_pos].integer;
162       if (key_os_version != 0) {
163         key->sw_enforced()[key_os_version_pos].integer = os_version_;
164         set_changed = true;
165       }
166     }
167   }
168 
169   auto update_os = UpgradeIntegerTag(
170       keymaster::TAG_OS_VERSION,
171       os_version_,
172       &key->sw_enforced(),
173       &set_changed);
174 
175   auto update_patchlevel = UpgradeIntegerTag(
176       keymaster::TAG_OS_PATCHLEVEL,
177       os_patchlevel_,
178       &key->sw_enforced(),
179       &set_changed);
180 
181   if (!update_os || !update_patchlevel) {
182     // One of the version fields would have been a downgrade. Not allowed.
183     return KM_ERROR_INVALID_ARGUMENT;
184   }
185 
186   if (!set_changed) {
187     // Don't need an upgrade.
188     return KM_ERROR_OK;
189   }
190 
191   AuthorizationSet combined_authorization;
192   combined_authorization.Union(key->hw_enforced());
193   combined_authorization.Union(key->sw_enforced());
194 
195   keymaster_key_origin_t origin = KM_ORIGIN_UNKNOWN;
196   if (!combined_authorization.GetTagValue(keymaster::TAG_ORIGIN, &origin)) {
197     LOG(WARNING) << "Key converted with unknown origin";
198   }
199 
200   AuthorizationSet output_hw_enforced;
201   AuthorizationSet output_sw_enforced;
202 
203   return key_blob_maker_->CreateKeyBlob(
204       combined_authorization,
205       origin,
206       key->key_material(),
207       upgraded_key,
208       &output_hw_enforced,
209       &output_sw_enforced);
210 }
211 
ParseKeyBlob(const KeymasterKeyBlob & blob,const AuthorizationSet & additional_params,keymaster::UniquePtr<keymaster::Key> * key) const212 keymaster_error_t TpmKeymasterContext::ParseKeyBlob(
213     const KeymasterKeyBlob& blob,
214     const AuthorizationSet& additional_params,
215     keymaster::UniquePtr<keymaster::Key>* key) const {
216   keymaster::AuthorizationSet hw_enforced;
217   keymaster::AuthorizationSet sw_enforced;
218   keymaster::KeymasterKeyBlob key_material;
219 
220   auto rc =
221       key_blob_maker_->UnwrapKeyBlob(
222           blob,
223           &hw_enforced,
224           &sw_enforced,
225           &key_material);
226   if (rc != KM_ERROR_OK) {
227     LOG(ERROR) << "Failed to unwrap key: " << rc;
228     return rc;
229   }
230 
231   keymaster_algorithm_t algorithm;
232   if (!hw_enforced.GetTagValue(keymaster::TAG_ALGORITHM, &algorithm) &&
233       !sw_enforced.GetTagValue(keymaster::TAG_ALGORITHM, &algorithm)) {
234     LOG(ERROR) << "No TAG_ALGORITHM value in hw_enforced or sw_enforced.";
235     return KM_ERROR_UNKNOWN_ERROR;
236   }
237 
238   auto factory = GetKeyFactory(algorithm);
239   if (factory == nullptr) {
240     LOG(ERROR) << "Unable to find key factory for " << algorithm;
241     return KM_ERROR_UNSUPPORTED_ALGORITHM;
242   }
243   rc =
244       factory->LoadKey(
245           std::move(key_material),
246           additional_params,
247           std::move(hw_enforced),
248           std::move(sw_enforced),
249           key);
250   if (rc != KM_ERROR_OK) {
251     LOG(ERROR) << "Unable to load unwrapped key: " << rc;
252   }
253   return rc;
254 }
255 
AddRngEntropy(const uint8_t * buffer,size_t size) const256 keymaster_error_t TpmKeymasterContext::AddRngEntropy(
257     const uint8_t* buffer, size_t size) const {
258   return random_source_->AddRngEntropy(buffer, size);
259 }
260 
enforcement_policy()261 keymaster::KeymasterEnforcement* TpmKeymasterContext::enforcement_policy() {
262   return enforcement_.get();
263 }
264 
265 // Based on https://cs.android.com/android/platform/superproject/+/master:system/keymaster/contexts/pure_soft_keymaster_context.cpp;l=261;drc=8367d5351c4d417a11f49b12394b63a413faa02d
266 
GenerateAttestation(const keymaster::Key & key,const AuthorizationSet & attest_params,keymaster::CertChainPtr * cert_chain) const267 keymaster_error_t TpmKeymasterContext::GenerateAttestation(
268     const keymaster::Key& key,
269     const AuthorizationSet& attest_params,
270     keymaster::CertChainPtr* cert_chain) const {
271   LOG(INFO) << "TODO(b/155697200): Link attestation back to the TPM";
272   keymaster_error_t error = KM_ERROR_OK;
273   keymaster_algorithm_t key_algorithm;
274   if (!key.authorizations().GetTagValue(keymaster::TAG_ALGORITHM, &key_algorithm)) {
275     return KM_ERROR_UNKNOWN_ERROR;
276   }
277 
278   if ((key_algorithm != KM_ALGORITHM_RSA && key_algorithm != KM_ALGORITHM_EC)) {
279     return KM_ERROR_INCOMPATIBLE_ALGORITHM;
280   }
281 
282   // We have established that the given key has the correct algorithm, and
283   // because this is the TpmKeymasterContext we can assume that the Key is an
284   // AsymmetricKey. So we can downcast.
285   const keymaster::AsymmetricKey& asymmetric_key =
286       static_cast<const keymaster::AsymmetricKey&>(key);
287 
288   auto attestation_chain = keymaster::getAttestationChain(key_algorithm, &error);
289   if (error != KM_ERROR_OK) {
290     return error;
291   }
292 
293   auto attestation_key = keymaster::getAttestationKey(key_algorithm, &error);
294   if (error != KM_ERROR_OK) {
295     return error;
296   }
297 
298   return keymaster::generate_attestation(
299       asymmetric_key, attest_params,
300       *attestation_chain,
301       *attestation_key,
302       *attestation_context_,
303       cert_chain);
304 }
305 
UnwrapKey(const KeymasterKeyBlob &,const KeymasterKeyBlob &,const AuthorizationSet &,const KeymasterKeyBlob &,AuthorizationSet *,keymaster_key_format_t *,KeymasterKeyBlob *) const306 keymaster_error_t TpmKeymasterContext::UnwrapKey(
307     const KeymasterKeyBlob&,
308     const KeymasterKeyBlob&,
309     const AuthorizationSet&,
310     const KeymasterKeyBlob&,
311     AuthorizationSet*,
312     keymaster_key_format_t*,
313     KeymasterKeyBlob*) const {
314   LOG(ERROR) << "TODO(b/155697375): Implement UnwrapKey";
315   return KM_ERROR_UNIMPLEMENTED;
316 }
317