diff options
author | Shawn Willden <swillden@google.com> | 2015-05-26 13:12:24 -0600 |
---|---|---|
committer | Shawn Willden <swillden@google.com> | 2015-05-28 07:28:52 -0600 |
commit | 6270aca8571399aca8ea538acd7386ddecdcc112 (patch) | |
tree | 46a54b1056acfb42a77b385829584ed4c0cf628e /ec_keymaster0_key.cpp | |
parent | 4f83b89b2bdb1dacfa1c208786e29c0cd66f0b15 (diff) | |
download | keymaster-6270aca8571399aca8ea538acd7386ddecdcc112.tar.gz |
Delegate ECDSA keys to keymaster0 in SoftKeymasterDevice.
Bug: 20912868
Change-Id: If63899e3244aed45d939d0165e6d94a1caa9d220
Diffstat (limited to 'ec_keymaster0_key.cpp')
-rw-r--r-- | ec_keymaster0_key.cpp | 143 |
1 files changed, 143 insertions, 0 deletions
diff --git a/ec_keymaster0_key.cpp b/ec_keymaster0_key.cpp new file mode 100644 index 0000000..d171d58 --- /dev/null +++ b/ec_keymaster0_key.cpp @@ -0,0 +1,143 @@ +/* + * Copyright 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ec_keymaster0_key.h" + +#include <memory> + +#define LOG_TAG "EcKeymaster0Key" +#include <cutils/log.h> + +#include <keymaster/soft_keymaster_context.h> + +#include "keymaster0_engine.h" +#include "openssl_utils.h" + +using std::unique_ptr; + +namespace keymaster { + +EcdsaKeymaster0KeyFactory::EcdsaKeymaster0KeyFactory(const SoftKeymasterContext* context, + const Keymaster0Engine* engine) + : EcdsaKeyFactory(context), engine_(engine), soft_context_(context) { +} + +keymaster_error_t EcdsaKeymaster0KeyFactory::GenerateKey(const AuthorizationSet& key_description, + KeymasterKeyBlob* key_blob, + AuthorizationSet* hw_enforced, + AuthorizationSet* sw_enforced) { + if (!key_blob || !hw_enforced || !sw_enforced) + return KM_ERROR_OUTPUT_PARAMETER_NULL; + + if (!engine_ || !engine_->supports_ec()) + return super::GenerateKey(key_description, key_blob, hw_enforced, sw_enforced); + + uint32_t key_size; + if (!key_description.GetTagValue(TAG_KEY_SIZE, &key_size)) { + LOG_E("%s", "No key size specified for EC key generation"); + return KM_ERROR_UNSUPPORTED_KEY_SIZE; + } + + KeymasterKeyBlob key_material; + if (!engine_->GenerateEcKey(key_size, &key_material)) + return KM_ERROR_UNKNOWN_ERROR; + + // These tags are hardware-enforced. Putting them in the hw_enforced set here will ensure that + // context_->CreateKeyBlob doesn't put them in sw_enforced. + hw_enforced->push_back(TAG_ALGORITHM, KM_ALGORITHM_EC); + hw_enforced->push_back(TAG_KEY_SIZE, key_size); + + return context_->CreateKeyBlob(key_description, KM_ORIGIN_GENERATED, key_material, key_blob, + hw_enforced, sw_enforced); +} + +keymaster_error_t EcdsaKeymaster0KeyFactory::ImportKey( + const AuthorizationSet& key_description, keymaster_key_format_t input_key_material_format, + const KeymasterKeyBlob& input_key_material, KeymasterKeyBlob* output_key_blob, + AuthorizationSet* hw_enforced, AuthorizationSet* sw_enforced) { + if (!output_key_blob || !hw_enforced || !sw_enforced) + return KM_ERROR_OUTPUT_PARAMETER_NULL; + + if (!engine_ || !engine_->supports_ec()) + return super::ImportKey(key_description, input_key_material_format, input_key_material, + output_key_blob, hw_enforced, sw_enforced); + + AuthorizationSet authorizations; + uint32_t key_size; + keymaster_error_t error = UpdateImportKeyDescription( + key_description, input_key_material_format, input_key_material, &authorizations, &key_size); + if (error != KM_ERROR_OK) + return error; + + KeymasterKeyBlob imported_hw_key; + if (!engine_->ImportKey(input_key_material_format, input_key_material, &imported_hw_key)) + return KM_ERROR_UNKNOWN_ERROR; + + // These tags are hardware-enforced. Putting them in the hw_enforced set here will ensure that + // context_->CreateKeyBlob doesn't put them in sw_enforced. + hw_enforced->push_back(TAG_ALGORITHM, KM_ALGORITHM_EC); + hw_enforced->push_back(TAG_KEY_SIZE, key_size); + + return context_->CreateKeyBlob(authorizations, KM_ORIGIN_IMPORTED, imported_hw_key, + output_key_blob, hw_enforced, sw_enforced); +} + +keymaster_error_t EcdsaKeymaster0KeyFactory::LoadKey(const KeymasterKeyBlob& key_material, + const AuthorizationSet& hw_enforced, + const AuthorizationSet& sw_enforced, + UniquePtr<Key>* key) { + if (!key) + return KM_ERROR_OUTPUT_PARAMETER_NULL; + + if (sw_enforced.GetTagCount(TAG_ALGORITHM) == 1) + return super::LoadKey(key_material, hw_enforced, sw_enforced, key); + + unique_ptr<EC_KEY, EC_Delete> ec_key(engine_->BlobToEcKey(key_material)); + if (!ec_key) + return KM_ERROR_UNKNOWN_ERROR; + + keymaster_error_t error; + key->reset(new EcKeymaster0Key(ec_key.release(), hw_enforced, sw_enforced, engine_, &error)); + if (error != KM_ERROR_OK) + return error; + + return KM_ERROR_OK; +} + +EcKeymaster0Key::EcKeymaster0Key(EC_KEY* ec_key, const AuthorizationSet& hw_enforced, + const AuthorizationSet& sw_enforced, + const Keymaster0Engine* engine, keymaster_error_t* error) + : EcKey(ec_key, hw_enforced, sw_enforced, error), engine_(engine) { +} + +keymaster_error_t EcKeymaster0Key::key_material(UniquePtr<uint8_t[]>* material, + size_t* size) const { + if (!engine_) + return super::key_material(material, size); + + const keymaster_key_blob_t* blob = engine_->EcKeyToBlob(key()); + if (!blob) + return KM_ERROR_UNKNOWN_ERROR; + + *size = blob->key_material_size; + material->reset(new uint8_t[*size]); + if (!material->get()) + return KM_ERROR_MEMORY_ALLOCATION_FAILED; + memcpy(material->get(), blob->key_material, *size); + return KM_ERROR_OK; +} + +} // namespace keymaster |