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