summaryrefslogtreecommitdiffstats
path: root/ec_keymaster1_key.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'ec_keymaster1_key.cpp')
-rw-r--r--ec_keymaster1_key.cpp125
1 files changed, 125 insertions, 0 deletions
diff --git a/ec_keymaster1_key.cpp b/ec_keymaster1_key.cpp
new file mode 100644
index 0000000..3958c5c
--- /dev/null
+++ b/ec_keymaster1_key.cpp
@@ -0,0 +1,125 @@
+/*
+ * 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_keymaster1_key.h"
+
+#include <memory>
+
+#include <keymaster/logger.h>
+
+#include "ecdsa_keymaster1_operation.h"
+#include "ecdsa_operation.h"
+
+using std::unique_ptr;
+
+namespace keymaster {
+
+EcdsaKeymaster1KeyFactory::EcdsaKeymaster1KeyFactory(const SoftKeymasterContext* context,
+ const Keymaster1Engine* engine)
+ : EcKeyFactory(context), engine_(engine),
+ sign_factory_(new EcdsaKeymaster1OperationFactory(KM_PURPOSE_SIGN, engine)),
+ // For pubkey ops we can use the normal operation factories.
+ verify_factory_(new EcdsaVerifyOperationFactory) {}
+
+static bool is_supported(uint32_t digest) {
+ return digest == KM_DIGEST_NONE || digest == KM_DIGEST_SHA_2_256;
+}
+
+static void UpdateToWorkAroundUnsupportedDigests(const AuthorizationSet& key_description,
+ AuthorizationSet* new_description) {
+ bool have_unsupported_digests = false;
+ bool have_digest_none = false;
+ for (const keymaster_key_param_t& entry : key_description) {
+ new_description->push_back(entry);
+
+ if (entry.tag == TAG_DIGEST) {
+ if (entry.enumerated == KM_DIGEST_NONE) {
+ have_digest_none = true;
+ } else if (!is_supported(entry.enumerated)) {
+ LOG_D("Found request for unsupported digest %u", entry.enumerated);
+ have_unsupported_digests = true;
+ }
+ }
+ }
+
+ if (have_unsupported_digests && !have_digest_none) {
+ LOG_I("Adding KM_DIGEST_NONE to key authorization, to enable software digesting", 0);
+ new_description->push_back(TAG_DIGEST, KM_DIGEST_NONE);
+ }
+}
+
+keymaster_error_t EcdsaKeymaster1KeyFactory::GenerateKey(const AuthorizationSet& key_description,
+ KeymasterKeyBlob* key_blob,
+ AuthorizationSet* hw_enforced,
+ AuthorizationSet* sw_enforced) const {
+ AuthorizationSet key_params_copy;
+ UpdateToWorkAroundUnsupportedDigests(key_description, &key_params_copy);
+ return engine_->GenerateKey(key_params_copy, key_blob, hw_enforced, sw_enforced);
+}
+
+keymaster_error_t EcdsaKeymaster1KeyFactory::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) const {
+ AuthorizationSet key_params_copy;
+ UpdateToWorkAroundUnsupportedDigests(key_description, &key_params_copy);
+ return engine_->ImportKey(key_params_copy, input_key_material_format, input_key_material,
+ output_key_blob, hw_enforced, sw_enforced);
+}
+
+keymaster_error_t EcdsaKeymaster1KeyFactory::LoadKey(const KeymasterKeyBlob& key_material,
+ const AuthorizationSet& additional_params,
+ const AuthorizationSet& hw_enforced,
+ const AuthorizationSet& sw_enforced,
+ UniquePtr<Key>* key) const {
+ if (!key)
+ return KM_ERROR_OUTPUT_PARAMETER_NULL;
+
+ keymaster_error_t error;
+ unique_ptr<EC_KEY, EC_Delete> ecdsa(
+ engine_->BuildEcKey(key_material, additional_params, &error));
+ if (!ecdsa)
+ return error;
+
+ key->reset(new (std::nothrow)
+ EcdsaKeymaster1Key(ecdsa.release(), hw_enforced, sw_enforced, engine_, &error));
+ if (!key->get())
+ error = KM_ERROR_MEMORY_ALLOCATION_FAILED;
+
+ if (error != KM_ERROR_OK)
+ return error;
+
+ return KM_ERROR_OK;
+}
+
+OperationFactory*
+EcdsaKeymaster1KeyFactory::GetOperationFactory(keymaster_purpose_t purpose) const {
+ switch (purpose) {
+ case KM_PURPOSE_SIGN:
+ return sign_factory_.get();
+ case KM_PURPOSE_VERIFY:
+ return verify_factory_.get();
+ default:
+ return nullptr;
+ }
+}
+
+EcdsaKeymaster1Key::EcdsaKeymaster1Key(EC_KEY* ecdsa_key, const AuthorizationSet& hw_enforced,
+ const AuthorizationSet& sw_enforced,
+ const Keymaster1Engine* engine, keymaster_error_t* error)
+ : EcKey(ecdsa_key, hw_enforced, sw_enforced, error), engine_(engine) {}
+
+} // namespace keymaster