summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRicardo Cerqueira <ricardo@cyngn.com>2015-11-05 03:17:19 +0000
committerRicardo Cerqueira <ricardo@cyngn.com>2015-11-05 03:17:24 +0000
commit18b04441a40a728bf0b7578d89ff7603b7b21f44 (patch)
tree430089cdf7fc7c26a6610e53e6b553d9e88505e3
parentb0f457efa768e7ae6b394a29a02e2fe56d5b4788 (diff)
parentd8544338989c53f52f45d05e1d9e46df34e29b03 (diff)
downloadandroid_system_keymaster-18b04441a40a728bf0b7578d89ff7603b7b21f44.tar.gz
android_system_keymaster-18b04441a40a728bf0b7578d89ff7603b7b21f44.tar.bz2
android_system_keymaster-18b04441a40a728bf0b7578d89ff7603b7b21f44.zip
Merge tag 'android-6.0.0_r26' into cm-13.0
Android 6.0.0 release 26 Change-Id: I03ff70b242510f7cecbbc319b3f4a50138bacd48
-rw-r--r--Android.mk19
-rw-r--r--Makefile17
-rw-r--r--aes_key.cpp1
-rw-r--r--aes_key.h1
-rw-r--r--android_keymaster.cpp17
-rw-r--r--android_keymaster_test.cpp715
-rw-r--r--android_keymaster_test_utils.cpp224
-rw-r--r--android_keymaster_test_utils.h10
-rw-r--r--asymmetric_key.cpp22
-rw-r--r--asymmetric_key.h1
-rw-r--r--asymmetric_key_factory.cpp1
-rw-r--r--auth_encrypted_key_blob.cpp4
-rw-r--r--authorization_set.cpp9
-rw-r--r--ec_key.h2
-rw-r--r--ec_keymaster0_key.cpp25
-rw-r--r--ec_keymaster0_key.h4
-rw-r--r--ec_keymaster1_key.cpp125
-rw-r--r--ec_keymaster1_key.h82
-rw-r--r--ecdsa_keymaster1_operation.cpp139
-rw-r--r--ecdsa_keymaster1_operation.h119
-rw-r--r--ecdsa_operation.cpp13
-rw-r--r--ecdsa_operation.h12
-rw-r--r--hmac_key.cpp1
-rw-r--r--hmac_key.h1
-rw-r--r--include/keymaster/android_keymaster.h2
-rw-r--r--include/keymaster/android_keymaster_utils.h11
-rw-r--r--include/keymaster/asymmetric_key_factory.h1
-rw-r--r--include/keymaster/authorization_set.h5
-rw-r--r--include/keymaster/key_factory.h1
-rw-r--r--include/keymaster/logger.h19
-rw-r--r--include/keymaster/soft_keymaster_context.h35
-rw-r--r--include/keymaster/soft_keymaster_device.h93
-rw-r--r--key.h5
-rw-r--r--keymaster0_engine.cpp86
-rw-r--r--keymaster0_engine.h8
-rw-r--r--keymaster1_engine.cpp415
-rw-r--r--keymaster1_engine.h121
-rw-r--r--openssl_utils.cpp11
-rw-r--r--openssl_utils.h7
-rw-r--r--rsa_keymaster0_key.cpp31
-rw-r--r--rsa_keymaster0_key.h4
-rw-r--r--rsa_keymaster1_key.cpp147
-rw-r--r--rsa_keymaster1_key.h84
-rw-r--r--rsa_keymaster1_operation.cpp180
-rw-r--r--rsa_keymaster1_operation.h119
-rw-r--r--rsa_operation.cpp4
-rw-r--r--rsa_operation.h12
-rw-r--r--soft_keymaster_context.cpp160
-rw-r--r--soft_keymaster_device.cpp805
49 files changed, 3083 insertions, 847 deletions
diff --git a/Android.mk b/Android.mk
index ed1a06e..5a6dbb4 100644
--- a/Android.mk
+++ b/Android.mk
@@ -76,7 +76,7 @@ LOCAL_C_INCLUDES := \
LOCAL_SHARED_LIBRARIES := libcrypto libkeymaster_messages
LOCAL_CFLAGS = -Wall -Werror -Wunused
LOCAL_CLANG_CFLAGS += -Wno-error=unused-const-variable -Wno-error=unused-private-field
-# Ignore benigh warnings for now.
+# Ignore benign warnings for now.
LOCAL_CLANG_CFLAGS += -Wno-error=unused-private-field
LOCAL_MODULE_TAGS := optional
LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
@@ -93,8 +93,13 @@ include $(CLEAR_VARS)
LOCAL_MODULE := libsoftkeymasterdevice
LOCAL_SRC_FILES := \
ec_keymaster0_key.cpp \
+ ec_keymaster1_key.cpp \
+ ecdsa_keymaster1_operation.cpp \
keymaster0_engine.cpp \
+ keymaster1_engine.cpp \
rsa_keymaster0_key.cpp \
+ rsa_keymaster1_key.cpp \
+ rsa_keymaster1_operation.cpp \
soft_keymaster_context.cpp \
soft_keymaster_device.cpp \
soft_keymaster_logger.cpp
@@ -109,6 +114,18 @@ LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
include $(BUILD_SHARED_LIBRARY)
+###
+# libkeymasterfiles is an empty library that exports all of the files in keymaster as includes.
+###
+include $(CLEAR_VARS)
+LOCAL_MODULE := libkeymasterfiles
+LOCAL_EXPORT_C_INCLUDE_DIRS := \
+ $(LOCAL_PATH) \
+ $(LOCAL_PATH)/include
+LOCAL_MODULE_TAGS := optional
+LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
+include $(BUILD_STATIC_LIBRARY)
+
# Unit tests for libkeymaster
include $(CLEAR_VARS)
LOCAL_MODULE := keymaster_tests
diff --git a/Makefile b/Makefile
index 83acdae..a90b0a0 100644
--- a/Makefile
+++ b/Makefile
@@ -44,14 +44,14 @@ CXX=/usr/bin/clang
CXXFLAGS +=-std=c++11 -DKEYMASTER_CLANG_TEST_BUILD
CFLAGS += -DKEYMASTER_CLANG_TEST_BUILD
else
-CXXFLAGS +=-std=c++0x -fprofile-arcs
-CFLAGS += -fprofile-arcs
+CXXFLAGS +=-std=c++0x -fprofile-arcs -ftest-coverage
+CFLAGS += -fprofile-arcs -ftest-coverage
endif
LDFLAGS += $(ARCH_FLAGS)
CPPFLAGS = $(INCLUDES) -g -O0 -MD -MP
CXXFLAGS += -Wall -Werror -Wno-unused -Winit-self -Wpointer-arith -Wunused-parameter \
- -Werror=sign-compare -ftest-coverage -fno-permissive \
+ -Werror=sign-compare -Werror=return-type -fno-permissive \
-Wno-deprecated-declarations -fno-exceptions -DKEYMASTER_NAME_TAGS $(ARCH_FLAGS)
CFLAGS += $(ARCH_FLAGS)
@@ -61,7 +61,6 @@ CFLAGS += $(ARCH_FLAGS)
LDLIBS=-L$(BASE)/../boringssl/build/crypto -lcrypto -lpthread -lstdc++ -lgcov
CPPSRCS=\
- aead_mode_operation.cpp \
aes_key.cpp \
aes_operation.cpp \
android_keymaster.cpp \
@@ -78,6 +77,8 @@ CPPSRCS=\
ec_key.cpp \
ec_key_factory.cpp \
ec_keymaster0_key.cpp \
+ ec_keymaster1_key.cpp \
+ ecdsa_keymaster1_operation.cpp \
ecdsa_operation.cpp \
gtest_main.cpp \
hkdf.cpp \
@@ -90,6 +91,7 @@ CPPSRCS=\
key.cpp \
key_blob_test.cpp \
keymaster0_engine.cpp \
+ keymaster1_engine.cpp \
keymaster_enforcement.cpp \
keymaster_enforcement_test.cpp \
logger.cpp \
@@ -101,6 +103,8 @@ CPPSRCS=\
rsa_key.cpp \
rsa_key_factory.cpp \
rsa_keymaster0_key.cpp \
+ rsa_keymaster1_key.cpp \
+ rsa_keymaster1_operation.cpp \
rsa_operation.cpp \
serializable.cpp \
soft_keymaster_context.cpp \
@@ -231,12 +235,15 @@ android_keymaster_test: android_keymaster_test.o \
ec_key.o \
ec_key_factory.o \
ec_keymaster0_key.o \
+ ec_keymaster1_key.o \
+ ecdsa_keymaster1_operation.o \
ecdsa_operation.o \
hmac_key.o \
hmac_operation.o \
integrity_assured_key_blob.o \
key.o \
keymaster0_engine.o \
+ keymaster1_engine.o \
keymaster_enforcement.o \
logger.o \
ocb.o \
@@ -248,6 +255,8 @@ android_keymaster_test: android_keymaster_test.o \
rsa_key.o \
rsa_key_factory.o \
rsa_keymaster0_key.o \
+ rsa_keymaster1_key.o \
+ rsa_keymaster1_operation.o \
rsa_operation.o \
serializable.o \
soft_keymaster_context.o \
diff --git a/aes_key.cpp b/aes_key.cpp
index 92ea66e..6b784b7 100644
--- a/aes_key.cpp
+++ b/aes_key.cpp
@@ -42,6 +42,7 @@ OperationFactory* AesKeyFactory::GetOperationFactory(keymaster_purpose_t purpose
}
keymaster_error_t AesKeyFactory::LoadKey(const KeymasterKeyBlob& key_material,
+ const AuthorizationSet& /* additional_params */,
const AuthorizationSet& hw_enforced,
const AuthorizationSet& sw_enforced,
UniquePtr<Key>* key) const {
diff --git a/aes_key.h b/aes_key.h
index 9c58647..fad4569 100644
--- a/aes_key.h
+++ b/aes_key.h
@@ -33,6 +33,7 @@ class AesKeyFactory : public SymmetricKeyFactory {
keymaster_algorithm_t registry_key() const { return KM_ALGORITHM_AES; }
keymaster_error_t LoadKey(const KeymasterKeyBlob& key_material,
+ const AuthorizationSet& additional_params,
const AuthorizationSet& hw_enforced,
const AuthorizationSet& sw_enforced,
UniquePtr<Key>* key) const override;
diff --git a/android_keymaster.cpp b/android_keymaster.cpp
index 2bc6ea7..f60d6ee 100644
--- a/android_keymaster.cpp
+++ b/android_keymaster.cpp
@@ -275,8 +275,10 @@ void AndroidKeymaster::UpdateOperation(const UpdateOperationRequest& request,
response->error = context_->enforcement_policy()->AuthorizeOperation(
operation->purpose(), operation->key_id(), operation->authorizations(),
request.additional_params, request.op_handle, false /* is_begin_operation */);
- if (response->error != KM_ERROR_OK)
+ if (response->error != KM_ERROR_OK) {
+ operation_table_->Delete(request.op_handle);
return;
+ }
}
response->error =
@@ -302,8 +304,10 @@ void AndroidKeymaster::FinishOperation(const FinishOperationRequest& request,
response->error = context_->enforcement_policy()->AuthorizeOperation(
operation->purpose(), operation->key_id(), operation->authorizations(),
request.additional_params, request.op_handle, false /* is_begin_operation */);
- if (response->error != KM_ERROR_OK)
+ if (response->error != KM_ERROR_OK) {
+ operation_table_->Delete(request.op_handle);
return;
+ }
}
response->error = operation->Finish(request.additional_params, request.signature,
@@ -346,7 +350,8 @@ void AndroidKeymaster::ExportKey(const ExportKeyRequest& request, ExportKeyRespo
return;
UniquePtr<Key> key;
- response->error = key_factory->LoadKey(key_material, hw_enforced, sw_enforced, &key);
+ response->error = key_factory->LoadKey(key_material, request.additional_params, hw_enforced,
+ sw_enforced, &key);
if (response->error != KM_ERROR_OK)
return;
@@ -392,6 +397,10 @@ void AndroidKeymaster::DeleteAllKeys(const DeleteAllKeysRequest&, DeleteAllKeysR
response->error = context_->DeleteAllKeys();
}
+bool AndroidKeymaster::has_operation(keymaster_operation_handle_t op_handle) const {
+ return operation_table_->Find(op_handle) != nullptr;
+}
+
keymaster_error_t AndroidKeymaster::LoadKey(const keymaster_key_blob_t& key_blob,
const AuthorizationSet& additional_params,
AuthorizationSet* hw_enforced,
@@ -408,7 +417,7 @@ keymaster_error_t AndroidKeymaster::LoadKey(const keymaster_key_blob_t& key_blob
if (error != KM_ERROR_OK)
return error;
- return (*factory)->LoadKey(key_material, *hw_enforced, *sw_enforced, key);
+ return (*factory)->LoadKey(key_material, additional_params, *hw_enforced, *sw_enforced, key);
}
} // namespace keymaster
diff --git a/android_keymaster_test.cpp b/android_keymaster_test.cpp
index af829e6..a340206 100644
--- a/android_keymaster_test.cpp
+++ b/android_keymaster_test.cpp
@@ -18,6 +18,9 @@
#include <string>
#include <vector>
+#include <openssl/evp.h>
+#include <openssl/x509.h>
+
#include <hardware/keymaster0.h>
#include <keymaster/key_factory.h>
#include <keymaster/soft_keymaster_context.h>
@@ -51,6 +54,11 @@ template <typename T> vector<T> make_vector(const T* array, size_t len) {
return vector<T>(array, array + len);
}
+/**
+ * KeymasterEnforcement class for use in testing. It's permissive in the sense that it doesn't
+ * check cryptoperiods, but restrictive in the sense that the clock never advances (so rate-limited
+ * keys will only work once).
+ */
class TestKeymasterEnforcement : public KeymasterEnforcement {
public:
TestKeymasterEnforcement() : KeymasterEnforcement(3, 3) {}
@@ -65,10 +73,13 @@ class TestKeymasterEnforcement : public KeymasterEnforcement {
virtual bool ValidateTokenSignature(const hw_auth_token_t& /* token */) const { return true; }
};
+/**
+ * Variant of SoftKeymasterContext that provides a TestKeymasterEnforcement.
+ */
class TestKeymasterContext : public SoftKeymasterContext {
public:
- TestKeymasterContext(keymaster0_device_t* keymaster0 = nullptr)
- : SoftKeymasterContext(keymaster0) {}
+ TestKeymasterContext() {}
+ TestKeymasterContext(const string& root_of_trust) : SoftKeymasterContext(root_of_trust) {}
KeymasterEnforcement* enforcement_policy() override { return &test_policy_; }
@@ -76,6 +87,9 @@ class TestKeymasterContext : public SoftKeymasterContext {
TestKeymasterEnforcement test_policy_;
};
+/**
+ * Test instance creator that builds a pure software keymaster1 implementations.
+ */
class SoftKeymasterTestInstanceCreator : public Keymaster1TestInstanceCreator {
public:
keymaster1_device_t* CreateDevice() const override {
@@ -84,10 +98,14 @@ class SoftKeymasterTestInstanceCreator : public Keymaster1TestInstanceCreator {
return device->keymaster_device();
}
- bool algorithm_in_hardware(keymaster_algorithm_t) const override { return false; }
+ bool algorithm_in_km0_hardware(keymaster_algorithm_t) const override { return false; }
int keymaster0_calls() const override { return 0; }
};
+/**
+ * Test instance creator that builds keymaster1 instances which wrap a faked hardware keymaster0
+ * instance, with or without EC support.
+ */
class Keymaster0AdapterTestInstanceCreator : public Keymaster1TestInstanceCreator {
public:
Keymaster0AdapterTestInstanceCreator(bool support_ec) : support_ec_(support_ec) {}
@@ -110,12 +128,12 @@ class Keymaster0AdapterTestInstanceCreator : public Keymaster1TestInstanceCreato
counting_keymaster0_device_ = new Keymaster0CountingWrapper(keymaster0_device);
- SoftKeymasterDevice* keymaster =
- new SoftKeymasterDevice(new TestKeymasterContext(counting_keymaster0_device_));
+ SoftKeymasterDevice* keymaster = new SoftKeymasterDevice(new TestKeymasterContext);
+ keymaster->SetHardwareDevice(counting_keymaster0_device_);
return keymaster->keymaster_device();
}
- bool algorithm_in_hardware(keymaster_algorithm_t algorithm) const override {
+ bool algorithm_in_km0_hardware(keymaster_algorithm_t algorithm) const override {
switch (algorithm) {
case KM_ALGORITHM_RSA:
return true;
@@ -132,10 +150,35 @@ class Keymaster0AdapterTestInstanceCreator : public Keymaster1TestInstanceCreato
bool support_ec_;
};
+/**
+ * Test instance creator that builds a SoftKeymasterDevice which wraps a fake hardware keymaster1
+ * instance, with minimal digest support.
+ */
+class Sha256OnlyKeymaster1TestInstanceCreator : public Keymaster1TestInstanceCreator {
+ keymaster1_device_t* CreateDevice() const {
+ std::cerr << "Creating keymaster1-backed device that supports only SHA256";
+
+ // fake_device doesn't leak because device (below) takes ownership of it.
+ keymaster1_device_t* fake_device = make_device_sha256_only(
+ (new SoftKeymasterDevice(new TestKeymasterContext("PseudoHW")))->keymaster_device());
+
+ // device doesn't leak; it's cleaned up by device->keymaster_device()->common.close().
+ SoftKeymasterDevice* device = new SoftKeymasterDevice(new TestKeymasterContext);
+ device->SetHardwareDevice(fake_device);
+
+ return device->keymaster_device();
+ }
+
+ bool algorithm_in_km0_hardware(keymaster_algorithm_t) const override { return false; }
+ int keymaster0_calls() const override { return 0; }
+ int minimal_digest_set() const override { return true; }
+};
+
static auto test_params = testing::Values(
InstanceCreatorPtr(new SoftKeymasterTestInstanceCreator),
InstanceCreatorPtr(new Keymaster0AdapterTestInstanceCreator(true /* support_ec */)),
- InstanceCreatorPtr(new Keymaster0AdapterTestInstanceCreator(false /* support_ec */)));
+ InstanceCreatorPtr(new Keymaster0AdapterTestInstanceCreator(false /* support_ec */)),
+ InstanceCreatorPtr(new Sha256OnlyKeymaster1TestInstanceCreator));
typedef Keymaster1Test CheckSupported;
INSTANTIATE_TEST_CASE_P(AndroidKeymasterTest, CheckSupported, test_params);
@@ -218,17 +261,38 @@ TEST_P(CheckSupported, SupportedDigests) {
keymaster_digest_t* digests;
ASSERT_EQ(KM_ERROR_OK, device()->get_supported_digests(device(), KM_ALGORITHM_RSA,
KM_PURPOSE_SIGN, &digests, &len));
- EXPECT_TRUE(
- ResponseContains({KM_DIGEST_NONE, KM_DIGEST_MD5, KM_DIGEST_SHA1, KM_DIGEST_SHA_2_224,
- KM_DIGEST_SHA_2_256, KM_DIGEST_SHA_2_384, KM_DIGEST_SHA_2_512},
- digests, len));
+ if (GetParam()->minimal_digest_set()) {
+ EXPECT_TRUE(ResponseContains({KM_DIGEST_NONE, KM_DIGEST_SHA_2_256}, digests, len));
+ } else {
+ EXPECT_TRUE(
+ ResponseContains({KM_DIGEST_NONE, KM_DIGEST_MD5, KM_DIGEST_SHA1, KM_DIGEST_SHA_2_224,
+ KM_DIGEST_SHA_2_256, KM_DIGEST_SHA_2_384, KM_DIGEST_SHA_2_512},
+ digests, len));
+ }
+ free(digests);
+
+ ASSERT_EQ(KM_ERROR_OK, device()->get_supported_digests(device(), KM_ALGORITHM_RSA,
+ KM_PURPOSE_ENCRYPT, &digests, &len));
+ if (GetParam()->minimal_digest_set()) {
+ EXPECT_TRUE(ResponseContains({KM_DIGEST_NONE, KM_DIGEST_SHA_2_256}, digests, len));
+ } else {
+ EXPECT_TRUE(
+ ResponseContains({KM_DIGEST_NONE, KM_DIGEST_MD5, KM_DIGEST_SHA1, KM_DIGEST_SHA_2_224,
+ KM_DIGEST_SHA_2_256, KM_DIGEST_SHA_2_384, KM_DIGEST_SHA_2_512},
+ digests, len));
+ }
free(digests);
ASSERT_EQ(KM_ERROR_OK, device()->get_supported_digests(device(), KM_ALGORITHM_EC,
KM_PURPOSE_SIGN, &digests, &len));
- EXPECT_TRUE(ResponseContains({KM_DIGEST_NONE, KM_DIGEST_SHA1, KM_DIGEST_SHA_2_224,
- KM_DIGEST_SHA_2_256, KM_DIGEST_SHA_2_384, KM_DIGEST_SHA_2_512},
- digests, len));
+ if (GetParam()->minimal_digest_set()) {
+ EXPECT_TRUE(ResponseContains({KM_DIGEST_NONE, KM_DIGEST_SHA_2_256}, digests, len));
+ } else {
+ EXPECT_TRUE(
+ ResponseContains({KM_DIGEST_NONE, KM_DIGEST_SHA1, KM_DIGEST_SHA_2_224,
+ KM_DIGEST_SHA_2_256, KM_DIGEST_SHA_2_384, KM_DIGEST_SHA_2_512},
+ digests, len));
+ }
free(digests);
EXPECT_EQ(KM_ERROR_UNSUPPORTED_PURPOSE,
@@ -237,9 +301,13 @@ TEST_P(CheckSupported, SupportedDigests) {
ASSERT_EQ(KM_ERROR_OK, device()->get_supported_digests(device(), KM_ALGORITHM_HMAC,
KM_PURPOSE_SIGN, &digests, &len));
- EXPECT_TRUE(ResponseContains({KM_DIGEST_SHA_2_224, KM_DIGEST_SHA_2_256, KM_DIGEST_SHA_2_384,
- KM_DIGEST_SHA_2_512, KM_DIGEST_SHA1},
- digests, len));
+ if (GetParam()->minimal_digest_set()) {
+ EXPECT_TRUE(ResponseContains(KM_DIGEST_SHA_2_256, digests, len));
+ } else {
+ EXPECT_TRUE(ResponseContains({KM_DIGEST_SHA_2_224, KM_DIGEST_SHA_2_256, KM_DIGEST_SHA_2_384,
+ KM_DIGEST_SHA_2_512, KM_DIGEST_SHA1},
+ digests, len));
+ }
free(digests);
EXPECT_EQ(0, GetParam()->keymaster0_calls());
@@ -341,7 +409,7 @@ TEST_P(NewKeyGeneration, Rsa) {
// Check specified tags are all present, and in the right set.
AuthorizationSet crypto_params;
AuthorizationSet non_crypto_params;
- if (GetParam()->algorithm_in_hardware(KM_ALGORITHM_RSA)) {
+ if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA)) {
EXPECT_NE(0U, hw_enforced().size());
EXPECT_NE(0U, sw_enforced().size());
crypto_params.push_back(hw_enforced());
@@ -359,7 +427,7 @@ TEST_P(NewKeyGeneration, Rsa) {
EXPECT_TRUE(contains(crypto_params, TAG_RSA_PUBLIC_EXPONENT, 3));
EXPECT_FALSE(contains(non_crypto_params, TAG_RSA_PUBLIC_EXPONENT, 3));
- if (GetParam()->algorithm_in_hardware(KM_ALGORITHM_RSA))
+ if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA))
EXPECT_EQ(1, GetParam()->keymaster0_calls());
}
@@ -381,7 +449,7 @@ TEST_P(NewKeyGeneration, Ecdsa) {
// Check specified tags are all present, and in the right set.
AuthorizationSet crypto_params;
AuthorizationSet non_crypto_params;
- if (GetParam()->algorithm_in_hardware(KM_ALGORITHM_EC)) {
+ if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_EC)) {
EXPECT_NE(0U, hw_enforced().size());
EXPECT_NE(0U, sw_enforced().size());
crypto_params.push_back(hw_enforced());
@@ -397,7 +465,7 @@ TEST_P(NewKeyGeneration, Ecdsa) {
EXPECT_TRUE(contains(crypto_params, TAG_KEY_SIZE, 224));
EXPECT_FALSE(contains(non_crypto_params, TAG_KEY_SIZE, 224));
- if (GetParam()->algorithm_in_hardware(KM_ALGORITHM_EC))
+ if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_EC))
EXPECT_EQ(1, GetParam()->keymaster0_calls());
}
@@ -412,7 +480,7 @@ TEST_P(NewKeyGeneration, EcdsaDefaultSize) {
}
TEST_P(NewKeyGeneration, EcdsaInvalidSize) {
- if (GetParam()->algorithm_in_hardware(KM_ALGORITHM_EC))
+ if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_EC))
ASSERT_EQ(
KM_ERROR_UNKNOWN_ERROR,
GenerateKey(AuthorizationSetBuilder().EcdsaSigningKey(190).Digest(KM_DIGEST_NONE)));
@@ -421,7 +489,7 @@ TEST_P(NewKeyGeneration, EcdsaInvalidSize) {
KM_ERROR_UNSUPPORTED_KEY_SIZE,
GenerateKey(AuthorizationSetBuilder().EcdsaSigningKey(190).Digest(KM_DIGEST_NONE)));
- if (GetParam()->algorithm_in_hardware(KM_ALGORITHM_EC))
+ if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_EC))
EXPECT_EQ(1, GetParam()->keymaster0_calls());
}
@@ -433,7 +501,7 @@ TEST_P(NewKeyGeneration, EcdsaAllValidSizes) {
<< "Failed to generate size: " << size;
}
- if (GetParam()->algorithm_in_hardware(KM_ALGORITHM_EC))
+ if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_EC))
EXPECT_EQ(4, GetParam()->keymaster0_calls());
}
@@ -510,7 +578,7 @@ TEST_P(GetKeyCharacteristics, SimpleRsa) {
ASSERT_EQ(KM_ERROR_OK, GetCharacteristics());
EXPECT_EQ(original, sw_enforced());
- if (GetParam()->algorithm_in_hardware(KM_ALGORITHM_RSA))
+ if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA))
EXPECT_EQ(1, GetParam()->keymaster0_calls());
}
@@ -526,7 +594,7 @@ TEST_P(SigningOperationsTest, RsaSuccess) {
string signature;
SignMessage(message, &signature, KM_DIGEST_NONE, KM_PAD_NONE);
- if (GetParam()->algorithm_in_hardware(KM_ALGORITHM_RSA))
+ if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA))
EXPECT_EQ(3, GetParam()->keymaster0_calls());
}
@@ -540,7 +608,7 @@ TEST_P(SigningOperationsTest, RsaPssSha256Success) {
string signature;
SignMessage(message, &signature, KM_DIGEST_SHA_2_256, KM_PAD_RSA_PSS);
- if (GetParam()->algorithm_in_hardware(KM_ALGORITHM_RSA))
+ if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA))
EXPECT_EQ(3, GetParam()->keymaster0_calls());
}
@@ -556,6 +624,9 @@ TEST_P(SigningOperationsTest, RsaPaddingNoneDoesNotAllowOther) {
begin_params.push_back(TAG_DIGEST, KM_DIGEST_NONE);
begin_params.push_back(TAG_PADDING, KM_PAD_RSA_PKCS1_1_5_SIGN);
EXPECT_EQ(KM_ERROR_INCOMPATIBLE_PADDING_MODE, BeginOperation(KM_PURPOSE_SIGN, begin_params));
+
+ if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA))
+ EXPECT_EQ(2, GetParam()->keymaster0_calls());
}
TEST_P(SigningOperationsTest, RsaPkcs1Sha256Success) {
@@ -567,7 +638,7 @@ TEST_P(SigningOperationsTest, RsaPkcs1Sha256Success) {
string signature;
SignMessage(message, &signature, KM_DIGEST_SHA_2_256, KM_PAD_RSA_PKCS1_1_5_SIGN);
- if (GetParam()->algorithm_in_hardware(KM_ALGORITHM_RSA))
+ if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA))
EXPECT_EQ(3, GetParam()->keymaster0_calls());
}
@@ -580,7 +651,7 @@ TEST_P(SigningOperationsTest, RsaPkcs1NoDigestSuccess) {
string signature;
SignMessage(message, &signature, KM_DIGEST_NONE, KM_PAD_RSA_PKCS1_1_5_SIGN);
- if (GetParam()->algorithm_in_hardware(KM_ALGORITHM_RSA))
+ if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA))
EXPECT_EQ(3, GetParam()->keymaster0_calls());
}
@@ -601,7 +672,7 @@ TEST_P(SigningOperationsTest, RsaPkcs1NoDigestTooLarge) {
string signature;
EXPECT_EQ(KM_ERROR_INVALID_INPUT_LENGTH, FinishOperation(&signature));
- if (GetParam()->algorithm_in_hardware(KM_ALGORITHM_RSA))
+ if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA))
EXPECT_EQ(2, GetParam()->keymaster0_calls());
}
@@ -636,7 +707,7 @@ TEST_P(SigningOperationsTest, RsaNoPaddingHugeData) {
size_t input_consumed;
EXPECT_EQ(KM_ERROR_INVALID_INPUT_LENGTH, UpdateOperation(message, &result, &input_consumed));
- if (GetParam()->algorithm_in_hardware(KM_ALGORITHM_RSA))
+ if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA))
EXPECT_EQ(2, GetParam()->keymaster0_calls());
}
@@ -653,7 +724,7 @@ TEST_P(SigningOperationsTest, RsaAbort) {
// Another abort should fail
EXPECT_EQ(KM_ERROR_INVALID_OPERATION_HANDLE, AbortOperation());
- if (GetParam()->algorithm_in_hardware(KM_ALGORITHM_RSA))
+ if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA))
EXPECT_EQ(2, GetParam()->keymaster0_calls());
}
@@ -666,7 +737,7 @@ TEST_P(SigningOperationsTest, RsaUnsupportedPadding) {
begin_params.push_back(TAG_DIGEST, KM_DIGEST_SHA_2_256);
ASSERT_EQ(KM_ERROR_UNSUPPORTED_PADDING_MODE, BeginOperation(KM_PURPOSE_SIGN, begin_params));
- if (GetParam()->algorithm_in_hardware(KM_ALGORITHM_RSA))
+ if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA))
EXPECT_EQ(2, GetParam()->keymaster0_calls());
}
@@ -681,7 +752,7 @@ TEST_P(SigningOperationsTest, RsaNoDigest) {
begin_params.push_back(TAG_PADDING, KM_PAD_RSA_PSS);
ASSERT_EQ(KM_ERROR_INCOMPATIBLE_DIGEST, BeginOperation(KM_PURPOSE_SIGN, begin_params));
- if (GetParam()->algorithm_in_hardware(KM_ALGORITHM_RSA))
+ if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA))
EXPECT_EQ(2, GetParam()->keymaster0_calls());
}
@@ -693,7 +764,7 @@ TEST_P(SigningOperationsTest, RsaNoPadding) {
begin_params.push_back(TAG_DIGEST, KM_DIGEST_NONE);
ASSERT_EQ(KM_ERROR_UNSUPPORTED_PADDING_MODE, BeginOperation(KM_PURPOSE_SIGN, begin_params));
- if (GetParam()->algorithm_in_hardware(KM_ALGORITHM_RSA))
+ if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA))
EXPECT_EQ(2, GetParam()->keymaster0_calls());
}
@@ -706,7 +777,7 @@ TEST_P(SigningOperationsTest, RsaTooShortMessage) {
string signature;
SignMessage(message, &signature, KM_DIGEST_NONE, KM_PAD_NONE);
- if (GetParam()->algorithm_in_hardware(KM_ALGORITHM_RSA))
+ if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA))
EXPECT_EQ(3, GetParam()->keymaster0_calls());
}
@@ -720,7 +791,7 @@ TEST_P(SigningOperationsTest, RsaSignWithEncryptionKey) {
begin_params.push_back(TAG_DIGEST, KM_DIGEST_NONE);
ASSERT_EQ(KM_ERROR_INCOMPATIBLE_PURPOSE, BeginOperation(KM_PURPOSE_SIGN, begin_params));
- if (GetParam()->algorithm_in_hardware(KM_ALGORITHM_RSA))
+ if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA))
EXPECT_EQ(2, GetParam()->keymaster0_calls());
}
@@ -731,7 +802,7 @@ TEST_P(SigningOperationsTest, EcdsaSuccess) {
string signature;
SignMessage(message, &signature, KM_DIGEST_NONE);
- if (GetParam()->algorithm_in_hardware(KM_ALGORITHM_EC))
+ if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_EC))
EXPECT_EQ(3, GetParam()->keymaster0_calls());
}
@@ -742,7 +813,18 @@ TEST_P(SigningOperationsTest, EcdsaSha256Success) {
string signature;
SignMessage(message, &signature, KM_DIGEST_SHA_2_256);
- if (GetParam()->algorithm_in_hardware(KM_ALGORITHM_EC))
+ if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_EC))
+ EXPECT_EQ(3, GetParam()->keymaster0_calls());
+}
+
+TEST_P(SigningOperationsTest, EcdsaSha384Success) {
+ ASSERT_EQ(KM_ERROR_OK, GenerateKey(AuthorizationSetBuilder().EcdsaSigningKey(224).Digest(
+ KM_DIGEST_SHA_2_384)));
+ string message(1024, 'a');
+ string signature;
+ SignMessage(message, &signature, KM_DIGEST_SHA_2_384);
+
+ if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_EC))
EXPECT_EQ(3, GetParam()->keymaster0_calls());
}
@@ -756,9 +838,9 @@ TEST_P(SigningOperationsTest, EcdsaNoPaddingHugeData) {
ASSERT_EQ(KM_ERROR_OK, BeginOperation(KM_PURPOSE_SIGN, begin_params));
string result;
size_t input_consumed;
- EXPECT_EQ(KM_ERROR_INVALID_INPUT_LENGTH, UpdateOperation(message, &result, &input_consumed));
+ EXPECT_EQ(KM_ERROR_OK, UpdateOperation(message, &result, &input_consumed));
- if (GetParam()->algorithm_in_hardware(KM_ALGORITHM_EC))
+ if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_EC))
EXPECT_EQ(2, GetParam()->keymaster0_calls());
}
@@ -785,7 +867,7 @@ TEST_P(SigningOperationsTest, EcsdaAllSizesAndHashes) {
}
}
- if (GetParam()->algorithm_in_hardware(KM_ALGORITHM_EC))
+ if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_EC))
EXPECT_EQ(digests.size() * key_sizes.size() * 3,
static_cast<size_t>(GetParam()->keymaster0_calls()));
}
@@ -801,6 +883,10 @@ TEST_P(SigningOperationsTest, AesEcbSign) {
}
TEST_P(SigningOperationsTest, HmacSha1Success) {
+ if (GetParam()->minimal_digest_set())
+ // Can't emulate other digests for HMAC.
+ return;
+
GenerateKey(AuthorizationSetBuilder()
.HmacKey(128)
.Digest(KM_DIGEST_SHA1)
@@ -814,6 +900,10 @@ TEST_P(SigningOperationsTest, HmacSha1Success) {
}
TEST_P(SigningOperationsTest, HmacSha224Success) {
+ if (GetParam()->minimal_digest_set())
+ // Can't emulate other digests for HMAC.
+ return;
+
ASSERT_EQ(KM_ERROR_OK, GenerateKey(AuthorizationSetBuilder()
.HmacKey(128)
.Digest(KM_DIGEST_SHA_2_224)
@@ -827,6 +917,10 @@ TEST_P(SigningOperationsTest, HmacSha224Success) {
}
TEST_P(SigningOperationsTest, HmacSha256Success) {
+ if (GetParam()->minimal_digest_set())
+ // Can't emulate other digests for HMAC.
+ return;
+
ASSERT_EQ(KM_ERROR_OK, GenerateKey(AuthorizationSetBuilder()
.HmacKey(128)
.Digest(KM_DIGEST_SHA_2_256)
@@ -840,6 +934,10 @@ TEST_P(SigningOperationsTest, HmacSha256Success) {
}
TEST_P(SigningOperationsTest, HmacSha384Success) {
+ if (GetParam()->minimal_digest_set())
+ // Can't emulate other digests for HMAC.
+ return;
+
ASSERT_EQ(KM_ERROR_OK, GenerateKey(AuthorizationSetBuilder()
.HmacKey(128)
.Digest(KM_DIGEST_SHA_2_384)
@@ -854,6 +952,10 @@ TEST_P(SigningOperationsTest, HmacSha384Success) {
}
TEST_P(SigningOperationsTest, HmacSha512Success) {
+ if (GetParam()->minimal_digest_set())
+ // Can't emulate other digests for HMAC.
+ return;
+
ASSERT_EQ(KM_ERROR_OK, GenerateKey(AuthorizationSetBuilder()
.HmacKey(128)
.Digest(KM_DIGEST_SHA_2_512)
@@ -870,12 +972,12 @@ TEST_P(SigningOperationsTest, HmacLengthInKey) {
// TODO(swillden): unified API should generate an error on key generation.
ASSERT_EQ(KM_ERROR_OK, GenerateKey(AuthorizationSetBuilder()
.HmacKey(128)
- .Digest(KM_DIGEST_SHA_2_512)
- .Authorization(TAG_MIN_MAC_LENGTH, 512)));
+ .Digest(KM_DIGEST_SHA_2_256)
+ .Authorization(TAG_MIN_MAC_LENGTH, 128)));
string message = "12345678901234567890123456789012";
string signature;
- MacMessage(message, &signature, 512);
- ASSERT_EQ(64U, signature.size());
+ MacMessage(message, &signature, 160);
+ ASSERT_EQ(20U, signature.size());
EXPECT_EQ(0, GetParam()->keymaster0_calls());
}
@@ -911,10 +1013,12 @@ TEST_P(SigningOperationsTest, HmacRfc4231TestCase1) {
string key = make_string(key_data);
- CheckHmacTestVector(key, message, KM_DIGEST_SHA_2_224, make_string(sha_224_expected));
CheckHmacTestVector(key, message, KM_DIGEST_SHA_2_256, make_string(sha_256_expected));
- CheckHmacTestVector(key, message, KM_DIGEST_SHA_2_384, make_string(sha_384_expected));
- CheckHmacTestVector(key, message, KM_DIGEST_SHA_2_512, make_string(sha_512_expected));
+ if (!GetParam()->minimal_digest_set()) {
+ CheckHmacTestVector(key, message, KM_DIGEST_SHA_2_224, make_string(sha_224_expected));
+ CheckHmacTestVector(key, message, KM_DIGEST_SHA_2_384, make_string(sha_384_expected));
+ CheckHmacTestVector(key, message, KM_DIGEST_SHA_2_512, make_string(sha_512_expected));
+ }
EXPECT_EQ(0, GetParam()->keymaster0_calls());
}
@@ -945,10 +1049,13 @@ TEST_P(SigningOperationsTest, HmacRfc4231TestCase2) {
0x4d, 0x4a, 0x6b, 0x4b, 0x63, 0x6e, 0x07, 0x0a, 0x38, 0xbc, 0xe7, 0x37,
};
- CheckHmacTestVector(key, message, KM_DIGEST_SHA_2_224, make_string(sha_224_expected));
CheckHmacTestVector(key, message, KM_DIGEST_SHA_2_256, make_string(sha_256_expected));
- CheckHmacTestVector(key, message, KM_DIGEST_SHA_2_384, make_string(sha_384_expected));
- CheckHmacTestVector(key, message, KM_DIGEST_SHA_2_512, make_string(sha_512_expected));
+ if (!GetParam()->minimal_digest_set()) {
+ CheckHmacTestVector(key, message, KM_DIGEST_SHA_2_224, make_string(sha_224_expected));
+ CheckHmacTestVector(key, message, KM_DIGEST_SHA_2_256, make_string(sha_256_expected));
+ CheckHmacTestVector(key, message, KM_DIGEST_SHA_2_384, make_string(sha_384_expected));
+ CheckHmacTestVector(key, message, KM_DIGEST_SHA_2_512, make_string(sha_512_expected));
+ }
EXPECT_EQ(0, GetParam()->keymaster0_calls());
}
@@ -979,10 +1086,13 @@ TEST_P(SigningOperationsTest, HmacRfc4231TestCase3) {
0xbe, 0xe8, 0x94, 0x26, 0x74, 0x27, 0x88, 0x59, 0xe1, 0x32, 0x92, 0xfb,
};
- CheckHmacTestVector(key, message, KM_DIGEST_SHA_2_224, make_string(sha_224_expected));
CheckHmacTestVector(key, message, KM_DIGEST_SHA_2_256, make_string(sha_256_expected));
- CheckHmacTestVector(key, message, KM_DIGEST_SHA_2_384, make_string(sha_384_expected));
- CheckHmacTestVector(key, message, KM_DIGEST_SHA_2_512, make_string(sha_512_expected));
+ if (!GetParam()->minimal_digest_set()) {
+ CheckHmacTestVector(key, message, KM_DIGEST_SHA_2_224, make_string(sha_224_expected));
+ CheckHmacTestVector(key, message, KM_DIGEST_SHA_2_256, make_string(sha_256_expected));
+ CheckHmacTestVector(key, message, KM_DIGEST_SHA_2_384, make_string(sha_384_expected));
+ CheckHmacTestVector(key, message, KM_DIGEST_SHA_2_512, make_string(sha_512_expected));
+ }
EXPECT_EQ(0, GetParam()->keymaster0_calls());
}
@@ -1017,10 +1127,13 @@ TEST_P(SigningOperationsTest, HmacRfc4231TestCase4) {
0x12, 0x0c, 0x4f, 0x2d, 0xe2, 0xad, 0xeb, 0xeb, 0x10, 0xa2, 0x98, 0xdd,
};
- CheckHmacTestVector(key, message, KM_DIGEST_SHA_2_224, make_string(sha_224_expected));
CheckHmacTestVector(key, message, KM_DIGEST_SHA_2_256, make_string(sha_256_expected));
- CheckHmacTestVector(key, message, KM_DIGEST_SHA_2_384, make_string(sha_384_expected));
- CheckHmacTestVector(key, message, KM_DIGEST_SHA_2_512, make_string(sha_512_expected));
+ if (!GetParam()->minimal_digest_set()) {
+ CheckHmacTestVector(key, message, KM_DIGEST_SHA_2_224, make_string(sha_224_expected));
+ CheckHmacTestVector(key, message, KM_DIGEST_SHA_2_256, make_string(sha_256_expected));
+ CheckHmacTestVector(key, message, KM_DIGEST_SHA_2_384, make_string(sha_384_expected));
+ CheckHmacTestVector(key, message, KM_DIGEST_SHA_2_512, make_string(sha_512_expected));
+ }
EXPECT_EQ(0, GetParam()->keymaster0_calls());
}
@@ -1046,10 +1159,12 @@ TEST_P(SigningOperationsTest, HmacRfc4231TestCase5) {
0x1d, 0x41, 0x79, 0xbc, 0x89, 0x1d, 0x87, 0xa6,
};
- CheckHmacTestVector(key, message, KM_DIGEST_SHA_2_224, make_string(sha_224_expected));
CheckHmacTestVector(key, message, KM_DIGEST_SHA_2_256, make_string(sha_256_expected));
- CheckHmacTestVector(key, message, KM_DIGEST_SHA_2_384, make_string(sha_384_expected));
- CheckHmacTestVector(key, message, KM_DIGEST_SHA_2_512, make_string(sha_512_expected));
+ if (!GetParam()->minimal_digest_set()) {
+ CheckHmacTestVector(key, message, KM_DIGEST_SHA_2_224, make_string(sha_224_expected));
+ CheckHmacTestVector(key, message, KM_DIGEST_SHA_2_384, make_string(sha_384_expected));
+ CheckHmacTestVector(key, message, KM_DIGEST_SHA_2_512, make_string(sha_512_expected));
+ }
EXPECT_EQ(0, GetParam()->keymaster0_calls());
}
@@ -1081,10 +1196,12 @@ TEST_P(SigningOperationsTest, HmacRfc4231TestCase6) {
0xf6, 0x3f, 0x0a, 0xec, 0x8b, 0x91, 0x5a, 0x98, 0x5d, 0x78, 0x65, 0x98,
};
- CheckHmacTestVector(key, message, KM_DIGEST_SHA_2_224, make_string(sha_224_expected));
CheckHmacTestVector(key, message, KM_DIGEST_SHA_2_256, make_string(sha_256_expected));
- CheckHmacTestVector(key, message, KM_DIGEST_SHA_2_384, make_string(sha_384_expected));
- CheckHmacTestVector(key, message, KM_DIGEST_SHA_2_512, make_string(sha_512_expected));
+ if (!GetParam()->minimal_digest_set()) {
+ CheckHmacTestVector(key, message, KM_DIGEST_SHA_2_224, make_string(sha_224_expected));
+ CheckHmacTestVector(key, message, KM_DIGEST_SHA_2_384, make_string(sha_384_expected));
+ CheckHmacTestVector(key, message, KM_DIGEST_SHA_2_512, make_string(sha_512_expected));
+ }
EXPECT_EQ(0, GetParam()->keymaster0_calls());
}
@@ -1118,10 +1235,12 @@ TEST_P(SigningOperationsTest, HmacRfc4231TestCase7) {
0x6d, 0xe0, 0x44, 0x60, 0x65, 0xc9, 0x74, 0x40, 0xfa, 0x8c, 0x6a, 0x58,
};
- CheckHmacTestVector(key, message, KM_DIGEST_SHA_2_224, make_string(sha_224_expected));
CheckHmacTestVector(key, message, KM_DIGEST_SHA_2_256, make_string(sha_256_expected));
- CheckHmacTestVector(key, message, KM_DIGEST_SHA_2_384, make_string(sha_384_expected));
- CheckHmacTestVector(key, message, KM_DIGEST_SHA_2_512, make_string(sha_512_expected));
+ if (!GetParam()->minimal_digest_set()) {
+ CheckHmacTestVector(key, message, KM_DIGEST_SHA_2_224, make_string(sha_224_expected));
+ CheckHmacTestVector(key, message, KM_DIGEST_SHA_2_384, make_string(sha_384_expected));
+ CheckHmacTestVector(key, message, KM_DIGEST_SHA_2_512, make_string(sha_512_expected));
+ }
EXPECT_EQ(0, GetParam()->keymaster0_calls());
}
@@ -1169,7 +1288,7 @@ TEST_P(VerificationOperationsTest, RsaSuccess) {
SignMessage(message, &signature, KM_DIGEST_NONE, KM_PAD_NONE);
VerifyMessage(message, signature, KM_DIGEST_NONE, KM_PAD_NONE);
- if (GetParam()->algorithm_in_hardware(KM_ALGORITHM_RSA))
+ if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA))
EXPECT_EQ(4, GetParam()->keymaster0_calls());
}
@@ -1184,10 +1303,46 @@ TEST_P(VerificationOperationsTest, RsaPssSha256Success) {
SignMessage(message, &signature, KM_DIGEST_SHA_2_256, KM_PAD_RSA_PSS);
VerifyMessage(message, signature, KM_DIGEST_SHA_2_256, KM_PAD_RSA_PSS);
- if (GetParam()->algorithm_in_hardware(KM_ALGORITHM_RSA))
+ if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA))
EXPECT_EQ(4, GetParam()->keymaster0_calls());
}
+TEST_P(VerificationOperationsTest, RsaPssSha224Success) {
+ ASSERT_EQ(KM_ERROR_OK, GenerateKey(AuthorizationSetBuilder()
+ .RsaSigningKey(512, 3)
+ .Digest(KM_DIGEST_SHA_2_224)
+ .Padding(KM_PAD_RSA_PSS)));
+ // Use large message, which won't work without digesting.
+ string message(1024, 'a');
+ string signature;
+ SignMessage(message, &signature, KM_DIGEST_SHA_2_224, KM_PAD_RSA_PSS);
+ VerifyMessage(message, signature, KM_DIGEST_SHA_2_224, KM_PAD_RSA_PSS);
+
+ if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA))
+ EXPECT_EQ(4, GetParam()->keymaster0_calls());
+
+ // Verify with OpenSSL.
+ string pubkey;
+ EXPECT_EQ(KM_ERROR_OK, ExportKey(KM_KEY_FORMAT_X509, &pubkey));
+
+ const uint8_t* p = reinterpret_cast<const uint8_t*>(pubkey.data());
+ unique_ptr<EVP_PKEY, EVP_PKEY_Delete> pkey(
+ d2i_PUBKEY(nullptr /* alloc new */, &p, pubkey.size()));
+ ASSERT_TRUE(pkey.get());
+
+ EVP_MD_CTX digest_ctx;
+ EVP_MD_CTX_init(&digest_ctx);
+ EVP_PKEY_CTX* pkey_ctx;
+ EXPECT_EQ(1, EVP_DigestVerifyInit(&digest_ctx, &pkey_ctx, EVP_sha224(), nullptr /* engine */,
+ pkey.get()));
+ EXPECT_EQ(1, EVP_PKEY_CTX_set_rsa_padding(pkey_ctx, RSA_PKCS1_PSS_PADDING));
+ EXPECT_EQ(1, EVP_DigestVerifyUpdate(&digest_ctx, message.data(), message.size()));
+ EXPECT_EQ(1,
+ EVP_DigestVerifyFinal(&digest_ctx, reinterpret_cast<const uint8_t*>(signature.data()),
+ signature.size()));
+ EVP_MD_CTX_cleanup(&digest_ctx);
+}
+
TEST_P(VerificationOperationsTest, RsaPssSha256CorruptSignature) {
GenerateKey(AuthorizationSetBuilder()
.RsaSigningKey(512, 3)
@@ -1209,7 +1364,7 @@ TEST_P(VerificationOperationsTest, RsaPssSha256CorruptSignature) {
EXPECT_EQ(message.size(), input_consumed);
EXPECT_EQ(KM_ERROR_VERIFICATION_FAILED, FinishOperation(signature, &result));
- if (GetParam()->algorithm_in_hardware(KM_ALGORITHM_RSA))
+ if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA))
EXPECT_EQ(4, GetParam()->keymaster0_calls());
}
@@ -1235,7 +1390,7 @@ TEST_P(VerificationOperationsTest, RsaPssSha256CorruptInput) {
EXPECT_EQ(message.size(), input_consumed);
EXPECT_EQ(KM_ERROR_VERIFICATION_FAILED, FinishOperation(signature, &result));
- if (GetParam()->algorithm_in_hardware(KM_ALGORITHM_RSA))
+ if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA))
EXPECT_EQ(4, GetParam()->keymaster0_calls());
}
@@ -1249,10 +1404,45 @@ TEST_P(VerificationOperationsTest, RsaPkcs1Sha256Success) {
SignMessage(message, &signature, KM_DIGEST_SHA_2_256, KM_PAD_RSA_PKCS1_1_5_SIGN);
VerifyMessage(message, signature, KM_DIGEST_SHA_2_256, KM_PAD_RSA_PKCS1_1_5_SIGN);
- if (GetParam()->algorithm_in_hardware(KM_ALGORITHM_RSA))
+ if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA))
EXPECT_EQ(4, GetParam()->keymaster0_calls());
}
+TEST_P(VerificationOperationsTest, RsaPks1Sha224Success) {
+ ASSERT_EQ(KM_ERROR_OK, GenerateKey(AuthorizationSetBuilder()
+ .RsaSigningKey(512, 3)
+ .Digest(KM_DIGEST_SHA_2_224)
+ .Padding(KM_PAD_RSA_PKCS1_1_5_SIGN)));
+ // Use large message, which won't work without digesting.
+ string message(1024, 'a');
+ string signature;
+ SignMessage(message, &signature, KM_DIGEST_SHA_2_224, KM_PAD_RSA_PKCS1_1_5_SIGN);
+ VerifyMessage(message, signature, KM_DIGEST_SHA_2_224, KM_PAD_RSA_PKCS1_1_5_SIGN);
+
+ if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA))
+ EXPECT_EQ(4, GetParam()->keymaster0_calls());
+
+ // Verify with OpenSSL.
+ string pubkey;
+ EXPECT_EQ(KM_ERROR_OK, ExportKey(KM_KEY_FORMAT_X509, &pubkey));
+
+ const uint8_t* p = reinterpret_cast<const uint8_t*>(pubkey.data());
+ unique_ptr<EVP_PKEY, EVP_PKEY_Delete> pkey(
+ d2i_PUBKEY(nullptr /* alloc new */, &p, pubkey.size()));
+ ASSERT_TRUE(pkey.get());
+
+ EVP_MD_CTX digest_ctx;
+ EVP_MD_CTX_init(&digest_ctx);
+ EVP_PKEY_CTX* pkey_ctx;
+ EXPECT_EQ(1, EVP_DigestVerifyInit(&digest_ctx, &pkey_ctx, EVP_sha224(), nullptr /* engine */,
+ pkey.get()));
+ EXPECT_EQ(1, EVP_DigestVerifyUpdate(&digest_ctx, message.data(), message.size()));
+ EXPECT_EQ(1,
+ EVP_DigestVerifyFinal(&digest_ctx, reinterpret_cast<const uint8_t*>(signature.data()),
+ signature.size()));
+ EVP_MD_CTX_cleanup(&digest_ctx);
+}
+
TEST_P(VerificationOperationsTest, RsaPkcs1Sha256CorruptSignature) {
GenerateKey(AuthorizationSetBuilder()
.RsaSigningKey(512, 3)
@@ -1274,7 +1464,7 @@ TEST_P(VerificationOperationsTest, RsaPkcs1Sha256CorruptSignature) {
EXPECT_EQ(message.size(), input_consumed);
EXPECT_EQ(KM_ERROR_VERIFICATION_FAILED, FinishOperation(signature, &result));
- if (GetParam()->algorithm_in_hardware(KM_ALGORITHM_RSA))
+ if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA))
EXPECT_EQ(4, GetParam()->keymaster0_calls());
}
@@ -1300,28 +1490,23 @@ TEST_P(VerificationOperationsTest, RsaPkcs1Sha256CorruptInput) {
EXPECT_EQ(message.size(), input_consumed);
EXPECT_EQ(KM_ERROR_VERIFICATION_FAILED, FinishOperation(signature, &result));
- if (GetParam()->algorithm_in_hardware(KM_ALGORITHM_RSA))
+ if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA))
EXPECT_EQ(4, GetParam()->keymaster0_calls());
}
TEST_P(VerificationOperationsTest, RsaAllDigestAndPadCombinations) {
- // Get all supported digests and padding modes.
- size_t digests_len;
- keymaster_digest_t* digests;
- ASSERT_EQ(KM_ERROR_OK,
- device()->get_supported_digests(device(), KM_ALGORITHM_RSA, KM_PURPOSE_SIGN, &digests,
- &digests_len));
+ vector<keymaster_digest_t> digests = {
+ KM_DIGEST_NONE, KM_DIGEST_MD5, KM_DIGEST_SHA1, KM_DIGEST_SHA_2_224,
+ KM_DIGEST_SHA_2_256, KM_DIGEST_SHA_2_384, KM_DIGEST_SHA_2_512,
+ };
- size_t padding_modes_len;
- keymaster_padding_t* padding_modes;
- ASSERT_EQ(KM_ERROR_OK,
- device()->get_supported_padding_modes(device(), KM_ALGORITHM_RSA, KM_PURPOSE_SIGN,
- &padding_modes, &padding_modes_len));
+ vector<keymaster_padding_t> padding_modes{
+ KM_PAD_NONE, KM_PAD_RSA_PKCS1_1_5_SIGN, KM_PAD_RSA_PSS,
+ };
- // Try them.
int trial_count = 0;
- for (keymaster_padding_t padding_mode : make_vector(padding_modes, padding_modes_len)) {
- for (keymaster_digest_t digest : make_vector(digests, digests_len)) {
+ for (keymaster_padding_t padding_mode : padding_modes) {
+ for (keymaster_digest_t digest : digests) {
if (digest != KM_DIGEST_NONE && padding_mode == KM_PAD_NONE)
// Digesting requires padding
continue;
@@ -1397,10 +1582,7 @@ TEST_P(VerificationOperationsTest, RsaAllDigestAndPadCombinations) {
}
}
- free(padding_modes);
- free(digests);
-
- if (GetParam()->algorithm_in_hardware(KM_ALGORITHM_RSA))
+ if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA))
EXPECT_EQ(trial_count * 4, GetParam()->keymaster0_calls());
}
@@ -1412,7 +1594,7 @@ TEST_P(VerificationOperationsTest, EcdsaSuccess) {
SignMessage(message, &signature, KM_DIGEST_NONE);
VerifyMessage(message, signature, KM_DIGEST_NONE);
- if (GetParam()->algorithm_in_hardware(KM_ALGORITHM_EC))
+ if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_EC))
EXPECT_EQ(4, GetParam()->keymaster0_calls());
}
@@ -1424,27 +1606,10 @@ TEST_P(VerificationOperationsTest, EcdsaTooShort) {
SignMessage(message, &signature, KM_DIGEST_NONE);
VerifyMessage(message, signature, KM_DIGEST_NONE);
- if (GetParam()->algorithm_in_hardware(KM_ALGORITHM_EC))
+ if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_EC))
EXPECT_EQ(4, GetParam()->keymaster0_calls());
}
-TEST_P(VerificationOperationsTest, EcdsaTooLong) {
- ASSERT_EQ(KM_ERROR_OK,
- GenerateKey(AuthorizationSetBuilder().EcdsaSigningKey(256).Digest(KM_DIGEST_NONE)));
- string message = "1234567890123456789012345678901234";
- string signature;
-
- AuthorizationSet begin_params(client_params());
- begin_params.push_back(TAG_DIGEST, KM_DIGEST_NONE);
- EXPECT_EQ(KM_ERROR_OK, BeginOperation(KM_PURPOSE_SIGN, begin_params));
- string output;
- size_t input_consumed;
- EXPECT_EQ(KM_ERROR_INVALID_INPUT_LENGTH, UpdateOperation(message, &output, &input_consumed));
-
- if (GetParam()->algorithm_in_hardware(KM_ALGORITHM_EC))
- EXPECT_EQ(2, GetParam()->keymaster0_calls());
-}
-
TEST_P(VerificationOperationsTest, EcdsaSlightlyTooLong) {
ASSERT_EQ(KM_ERROR_OK,
GenerateKey(AuthorizationSetBuilder().EcdsaSigningKey(521).Digest(KM_DIGEST_NONE)));
@@ -1458,7 +1623,7 @@ TEST_P(VerificationOperationsTest, EcdsaSlightlyTooLong) {
message[65] ^= 7;
VerifyMessage(message, signature, KM_DIGEST_NONE);
- if (GetParam()->algorithm_in_hardware(KM_ALGORITHM_EC))
+ if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_EC))
EXPECT_EQ(5, GetParam()->keymaster0_calls());
}
@@ -1472,7 +1637,7 @@ TEST_P(VerificationOperationsTest, EcdsaSha256Success) {
SignMessage(message, &signature, KM_DIGEST_SHA_2_256);
VerifyMessage(message, signature, KM_DIGEST_SHA_2_256);
- if (GetParam()->algorithm_in_hardware(KM_ALGORITHM_EC))
+ if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_EC))
EXPECT_EQ(4, GetParam()->keymaster0_calls());
// Just for giggles, try verifying with the wrong digest.
@@ -1487,7 +1652,63 @@ TEST_P(VerificationOperationsTest, EcdsaSha256Success) {
EXPECT_EQ(KM_ERROR_VERIFICATION_FAILED, FinishOperation(signature, &result));
}
+TEST_P(VerificationOperationsTest, EcdsaSha224Success) {
+ ASSERT_EQ(KM_ERROR_OK, GenerateKey(AuthorizationSetBuilder().EcdsaSigningKey(256).Digest(
+ KM_DIGEST_SHA_2_224)));
+
+ string message = "12345678901234567890123456789012";
+ string signature;
+ SignMessage(message, &signature, KM_DIGEST_SHA_2_224);
+ VerifyMessage(message, signature, KM_DIGEST_SHA_2_224);
+
+ if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_EC))
+ EXPECT_EQ(4, GetParam()->keymaster0_calls());
+
+ // Just for giggles, try verifying with the wrong digest.
+ AuthorizationSet begin_params(client_params());
+ begin_params.push_back(TAG_DIGEST, KM_DIGEST_NONE);
+ EXPECT_EQ(KM_ERROR_OK, BeginOperation(KM_PURPOSE_VERIFY, begin_params));
+
+ string result;
+ size_t input_consumed;
+ EXPECT_EQ(KM_ERROR_OK, UpdateOperation(message, &result, &input_consumed));
+ EXPECT_EQ(message.size(), input_consumed);
+ EXPECT_EQ(KM_ERROR_VERIFICATION_FAILED, FinishOperation(signature, &result));
+}
+
+TEST_P(VerificationOperationsTest, EcdsaAllDigestsAndKeySizes) {
+ keymaster_digest_t digests[] = {
+ KM_DIGEST_SHA1, KM_DIGEST_SHA_2_224, KM_DIGEST_SHA_2_256,
+ KM_DIGEST_SHA_2_384, KM_DIGEST_SHA_2_512,
+ };
+ size_t key_sizes[] = {224, 256, 384, 521};
+
+ string message = "1234567890";
+ string signature;
+
+ for (auto key_size : key_sizes) {
+ AuthorizationSetBuilder builder;
+ builder.EcdsaSigningKey(key_size);
+ for (auto digest : digests)
+ builder.Digest(digest);
+ ASSERT_EQ(KM_ERROR_OK, GenerateKey(builder));
+
+ for (auto digest : digests) {
+ SignMessage(message, &signature, digest);
+ VerifyMessage(message, signature, digest);
+ }
+ }
+
+ if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_EC))
+ EXPECT_EQ(static_cast<int>(array_length(key_sizes) * (1 + 3 * array_length(digests))),
+ GetParam()->keymaster0_calls());
+}
+
TEST_P(VerificationOperationsTest, HmacSha1Success) {
+ if (GetParam()->minimal_digest_set())
+ // Can't emulate missing digests for HMAC.
+ return;
+
GenerateKey(AuthorizationSetBuilder()
.HmacKey(128)
.Digest(KM_DIGEST_SHA1)
@@ -1501,6 +1722,10 @@ TEST_P(VerificationOperationsTest, HmacSha1Success) {
}
TEST_P(VerificationOperationsTest, HmacSha224Success) {
+ if (GetParam()->minimal_digest_set())
+ // Can't emulate missing digests for HMAC.
+ return;
+
GenerateKey(AuthorizationSetBuilder()
.HmacKey(128)
.Digest(KM_DIGEST_SHA_2_224)
@@ -1553,6 +1778,10 @@ TEST_P(VerificationOperationsTest, HmacSha256TooShortMac) {
}
TEST_P(VerificationOperationsTest, HmacSha384Success) {
+ if (GetParam()->minimal_digest_set())
+ // Can't emulate missing digests for HMAC.
+ return;
+
GenerateKey(AuthorizationSetBuilder()
.HmacKey(128)
.Digest(KM_DIGEST_SHA_2_384)
@@ -1566,6 +1795,10 @@ TEST_P(VerificationOperationsTest, HmacSha384Success) {
}
TEST_P(VerificationOperationsTest, HmacSha512Success) {
+ if (GetParam()->minimal_digest_set())
+ // Can't emulate missing digests for HMAC.
+ return;
+
GenerateKey(AuthorizationSetBuilder()
.HmacKey(128)
.Digest(KM_DIGEST_SHA_2_512)
@@ -1592,7 +1825,7 @@ TEST_P(ExportKeyTest, RsaSuccess) {
// TODO(swillden): Verify that the exported key is actually usable to verify signatures.
- if (GetParam()->algorithm_in_hardware(KM_ALGORITHM_RSA))
+ if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA))
EXPECT_EQ(2, GetParam()->keymaster0_calls());
}
@@ -1605,7 +1838,7 @@ TEST_P(ExportKeyTest, EcdsaSuccess) {
// TODO(swillden): Verify that the exported key is actually usable to verify signatures.
- if (GetParam()->algorithm_in_hardware(KM_ALGORITHM_EC))
+ if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_EC))
EXPECT_EQ(2, GetParam()->keymaster0_calls());
}
@@ -1617,7 +1850,7 @@ TEST_P(ExportKeyTest, RsaUnsupportedKeyFormat) {
string export_data;
ASSERT_EQ(KM_ERROR_UNSUPPORTED_KEY_FORMAT, ExportKey(KM_KEY_FORMAT_PKCS8, &export_data));
- if (GetParam()->algorithm_in_hardware(KM_ALGORITHM_RSA))
+ if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA))
EXPECT_EQ(2, GetParam()->keymaster0_calls());
}
@@ -1630,7 +1863,7 @@ TEST_P(ExportKeyTest, RsaCorruptedKeyBlob) {
string export_data;
ASSERT_EQ(KM_ERROR_INVALID_KEY_BLOB, ExportKey(KM_KEY_FORMAT_X509, &export_data));
- if (GetParam()->algorithm_in_hardware(KM_ALGORITHM_RSA))
+ if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA))
EXPECT_EQ(2, GetParam()->keymaster0_calls());
}
@@ -1666,18 +1899,18 @@ TEST_P(ImportKeyTest, RsaSuccess) {
KM_KEY_FORMAT_PKCS8, pk8_key));
// Check values derived from the key.
- EXPECT_TRUE(contains(GetParam()->algorithm_in_hardware(KM_ALGORITHM_RSA) ? hw_enforced()
- : sw_enforced(),
+ EXPECT_TRUE(contains(GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA) ? hw_enforced()
+ : sw_enforced(),
TAG_ALGORITHM, KM_ALGORITHM_RSA));
- EXPECT_TRUE(contains(GetParam()->algorithm_in_hardware(KM_ALGORITHM_RSA) ? hw_enforced()
- : sw_enforced(),
+ EXPECT_TRUE(contains(GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA) ? hw_enforced()
+ : sw_enforced(),
TAG_KEY_SIZE, 1024));
- EXPECT_TRUE(contains(GetParam()->algorithm_in_hardware(KM_ALGORITHM_RSA) ? hw_enforced()
- : sw_enforced(),
+ EXPECT_TRUE(contains(GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA) ? hw_enforced()
+ : sw_enforced(),
TAG_RSA_PUBLIC_EXPONENT, 65537U));
// And values provided by AndroidKeymaster
- if (GetParam()->algorithm_in_hardware(KM_ALGORITHM_RSA))
+ if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA))
EXPECT_TRUE(contains(hw_enforced(), TAG_ORIGIN, KM_ORIGIN_UNKNOWN));
else
EXPECT_TRUE(contains(sw_enforced(), TAG_ORIGIN, KM_ORIGIN_IMPORTED));
@@ -1688,35 +1921,7 @@ TEST_P(ImportKeyTest, RsaSuccess) {
SignMessage(message, &signature, KM_DIGEST_NONE, KM_PAD_NONE);
VerifyMessage(message, signature, KM_DIGEST_NONE, KM_PAD_NONE);
- if (GetParam()->algorithm_in_hardware(KM_ALGORITHM_RSA))
- EXPECT_EQ(4, GetParam()->keymaster0_calls());
-}
-
-TEST_P(ImportKeyTest, OldApiRsaSuccess) {
- string pk8_key = read_file("rsa_privkey_pk8.der");
- ASSERT_EQ(633U, pk8_key.size());
-
- // NOTE: This will break when the keymaster0 APIs are removed from keymaster1. But at that
- // point softkeymaster will no longer support keymaster0 APIs anyway.
- uint8_t* key_blob;
- size_t key_blob_length;
- ASSERT_EQ(0,
- device()->import_keypair(device(), reinterpret_cast<const uint8_t*>(pk8_key.data()),
- pk8_key.size(), &key_blob, &key_blob_length));
- set_key_blob(key_blob, key_blob_length);
-
- string message(1024 / 8, 'a');
- AuthorizationSet begin_params; // Don't use client data.
- begin_params.push_back(TAG_DIGEST, KM_DIGEST_NONE);
- begin_params.push_back(TAG_PADDING, KM_PAD_NONE);
- AuthorizationSet update_params;
- AuthorizationSet output_params;
- string signature =
- ProcessMessage(KM_PURPOSE_SIGN, message, begin_params, update_params, &output_params);
- ProcessMessage(KM_PURPOSE_VERIFY, message, signature, begin_params, update_params,
- &output_params);
-
- if (GetParam()->algorithm_in_hardware(KM_ALGORITHM_RSA))
+ if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA))
EXPECT_EQ(4, GetParam()->keymaster0_calls());
}
@@ -1755,15 +1960,15 @@ TEST_P(ImportKeyTest, EcdsaSuccess) {
KM_KEY_FORMAT_PKCS8, pk8_key));
// Check values derived from the key.
- EXPECT_TRUE(
- contains(GetParam()->algorithm_in_hardware(KM_ALGORITHM_EC) ? hw_enforced() : sw_enforced(),
- TAG_ALGORITHM, KM_ALGORITHM_EC));
- EXPECT_TRUE(
- contains(GetParam()->algorithm_in_hardware(KM_ALGORITHM_EC) ? hw_enforced() : sw_enforced(),
- TAG_KEY_SIZE, 256));
+ EXPECT_TRUE(contains(GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_EC) ? hw_enforced()
+ : sw_enforced(),
+ TAG_ALGORITHM, KM_ALGORITHM_EC));
+ EXPECT_TRUE(contains(GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_EC) ? hw_enforced()
+ : sw_enforced(),
+ TAG_KEY_SIZE, 256));
// And values provided by AndroidKeymaster
- if (GetParam()->algorithm_in_hardware(KM_ALGORITHM_EC))
+ if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_EC))
EXPECT_TRUE(contains(hw_enforced(), TAG_ORIGIN, KM_ORIGIN_UNKNOWN));
else
EXPECT_TRUE(contains(sw_enforced(), TAG_ORIGIN, KM_ORIGIN_IMPORTED));
@@ -1774,7 +1979,7 @@ TEST_P(ImportKeyTest, EcdsaSuccess) {
SignMessage(message, &signature, KM_DIGEST_NONE);
VerifyMessage(message, signature, KM_DIGEST_NONE);
- if (GetParam()->algorithm_in_hardware(KM_ALGORITHM_EC))
+ if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_EC))
EXPECT_EQ(4, GetParam()->keymaster0_calls());
}
@@ -1787,15 +1992,15 @@ TEST_P(ImportKeyTest, EcdsaSizeSpecified) {
KM_KEY_FORMAT_PKCS8, pk8_key));
// Check values derived from the key.
- EXPECT_TRUE(
- contains(GetParam()->algorithm_in_hardware(KM_ALGORITHM_EC) ? hw_enforced() : sw_enforced(),
- TAG_ALGORITHM, KM_ALGORITHM_EC));
- EXPECT_TRUE(
- contains(GetParam()->algorithm_in_hardware(KM_ALGORITHM_EC) ? hw_enforced() : sw_enforced(),
- TAG_KEY_SIZE, 256));
+ EXPECT_TRUE(contains(GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_EC) ? hw_enforced()
+ : sw_enforced(),
+ TAG_ALGORITHM, KM_ALGORITHM_EC));
+ EXPECT_TRUE(contains(GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_EC) ? hw_enforced()
+ : sw_enforced(),
+ TAG_KEY_SIZE, 256));
// And values provided by AndroidKeymaster
- if (GetParam()->algorithm_in_hardware(KM_ALGORITHM_EC))
+ if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_EC))
EXPECT_TRUE(contains(hw_enforced(), TAG_ORIGIN, KM_ORIGIN_UNKNOWN));
else
EXPECT_TRUE(contains(sw_enforced(), TAG_ORIGIN, KM_ORIGIN_IMPORTED));
@@ -1806,7 +2011,7 @@ TEST_P(ImportKeyTest, EcdsaSizeSpecified) {
SignMessage(message, &signature, KM_DIGEST_NONE);
VerifyMessage(message, signature, KM_DIGEST_NONE);
- if (GetParam()->algorithm_in_hardware(KM_ALGORITHM_EC))
+ if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_EC))
EXPECT_EQ(4, GetParam()->keymaster0_calls());
}
@@ -1856,7 +2061,7 @@ TEST_P(ImportKeyTest, HmacSha256KeySuccess) {
string message = "Hello World!";
string signature;
MacMessage(message, &signature, 256);
- VerifyMessage(message, signature, KM_DIGEST_SHA_2_256);
+ VerifyMac(message, signature);
EXPECT_EQ(0, GetParam()->keymaster0_calls());
}
@@ -1878,7 +2083,7 @@ TEST_P(EncryptionOperationsTest, RsaNoPaddingSuccess) {
// Unpadded RSA is deterministic
EXPECT_EQ(ciphertext1, ciphertext2);
- if (GetParam()->algorithm_in_hardware(KM_ALGORITHM_RSA))
+ if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA))
EXPECT_EQ(3, GetParam()->keymaster0_calls());
}
@@ -1896,7 +2101,7 @@ TEST_P(EncryptionOperationsTest, RsaNoPaddingTooShort) {
EXPECT_EQ(expected_plaintext, plaintext);
- if (GetParam()->algorithm_in_hardware(KM_ALGORITHM_RSA))
+ if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA))
EXPECT_EQ(4, GetParam()->keymaster0_calls());
}
@@ -1914,7 +2119,7 @@ TEST_P(EncryptionOperationsTest, RsaNoPaddingTooLong) {
size_t input_consumed;
EXPECT_EQ(KM_ERROR_INVALID_INPUT_LENGTH, UpdateOperation(message, &result, &input_consumed));
- if (GetParam()->algorithm_in_hardware(KM_ALGORITHM_RSA))
+ if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA))
EXPECT_EQ(2, GetParam()->keymaster0_calls());
}
@@ -1957,7 +2162,7 @@ TEST_P(EncryptionOperationsTest, RsaNoPaddingLargerThanModulus) {
EXPECT_EQ(KM_ERROR_OK, UpdateOperation(message, &result, &input_consumed));
EXPECT_EQ(KM_ERROR_OK, FinishOperation(&result));
- if (GetParam()->algorithm_in_hardware(KM_ALGORITHM_RSA))
+ if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA))
EXPECT_EQ(4, GetParam()->keymaster0_calls());
}
@@ -1978,7 +2183,28 @@ TEST_P(EncryptionOperationsTest, RsaOaepSuccess) {
// OAEP randomizes padding so every result should be different.
EXPECT_NE(ciphertext1, ciphertext2);
- if (GetParam()->algorithm_in_hardware(KM_ALGORITHM_RSA))
+ if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA))
+ EXPECT_EQ(3, GetParam()->keymaster0_calls());
+}
+
+TEST_P(EncryptionOperationsTest, RsaOaepSha224Success) {
+ size_t key_size = 768;
+ ASSERT_EQ(KM_ERROR_OK, GenerateKey(AuthorizationSetBuilder()
+ .RsaEncryptionKey(key_size, 3)
+ .Padding(KM_PAD_RSA_OAEP)
+ .Digest(KM_DIGEST_SHA_2_224)));
+
+ string message = "Hello";
+ string ciphertext1 = EncryptMessage(string(message), KM_DIGEST_SHA_2_224, KM_PAD_RSA_OAEP);
+ EXPECT_EQ(key_size / 8, ciphertext1.size());
+
+ string ciphertext2 = EncryptMessage(string(message), KM_DIGEST_SHA_2_224, KM_PAD_RSA_OAEP);
+ EXPECT_EQ(key_size / 8, ciphertext2.size());
+
+ // OAEP randomizes padding so every result should be different.
+ EXPECT_NE(ciphertext1, ciphertext2);
+
+ if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA))
EXPECT_EQ(3, GetParam()->keymaster0_calls());
}
@@ -1995,7 +2221,24 @@ TEST_P(EncryptionOperationsTest, RsaOaepRoundTrip) {
string plaintext = DecryptMessage(ciphertext, KM_DIGEST_SHA_2_256, KM_PAD_RSA_OAEP);
EXPECT_EQ(message, plaintext);
- if (GetParam()->algorithm_in_hardware(KM_ALGORITHM_RSA))
+ if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA))
+ EXPECT_EQ(4, GetParam()->keymaster0_calls());
+}
+
+TEST_P(EncryptionOperationsTest, RsaOaepSha224RoundTrip) {
+ size_t key_size = 768;
+ ASSERT_EQ(KM_ERROR_OK, GenerateKey(AuthorizationSetBuilder()
+ .RsaEncryptionKey(key_size, 3)
+ .Padding(KM_PAD_RSA_OAEP)
+ .Digest(KM_DIGEST_SHA_2_224)));
+ string message = "Hello World!";
+ string ciphertext = EncryptMessage(string(message), KM_DIGEST_SHA_2_224, KM_PAD_RSA_OAEP);
+ EXPECT_EQ(key_size / 8, ciphertext.size());
+
+ string plaintext = DecryptMessage(ciphertext, KM_DIGEST_SHA_2_224, KM_PAD_RSA_OAEP);
+ EXPECT_EQ(message, plaintext);
+
+ if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA))
EXPECT_EQ(4, GetParam()->keymaster0_calls());
}
@@ -2011,11 +2254,15 @@ TEST_P(EncryptionOperationsTest, RsaOaepInvalidDigest) {
begin_params.push_back(TAG_DIGEST, KM_DIGEST_NONE);
EXPECT_EQ(KM_ERROR_INCOMPATIBLE_DIGEST, BeginOperation(KM_PURPOSE_ENCRYPT, begin_params));
- if (GetParam()->algorithm_in_hardware(KM_ALGORITHM_RSA))
+ if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA))
EXPECT_EQ(2, GetParam()->keymaster0_calls());
}
TEST_P(EncryptionOperationsTest, RsaOaepUnauthorizedDigest) {
+ if (GetParam()->minimal_digest_set())
+ // We don't have two supported digests, so we can't try authorizing one and using another.
+ return;
+
ASSERT_EQ(KM_ERROR_OK, GenerateKey(AuthorizationSetBuilder()
.RsaEncryptionKey(512, 3)
.Padding(KM_PAD_RSA_OAEP)
@@ -2029,11 +2276,16 @@ TEST_P(EncryptionOperationsTest, RsaOaepUnauthorizedDigest) {
begin_params.push_back(TAG_DIGEST, KM_DIGEST_SHA1);
EXPECT_EQ(KM_ERROR_INCOMPATIBLE_DIGEST, BeginOperation(KM_PURPOSE_DECRYPT, begin_params));
- if (GetParam()->algorithm_in_hardware(KM_ALGORITHM_RSA))
+ if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA))
EXPECT_EQ(3, GetParam()->keymaster0_calls());
}
TEST_P(EncryptionOperationsTest, RsaOaepDecryptWithWrongDigest) {
+ if (GetParam()->minimal_digest_set())
+ // We don't have two supported digests, so we can't try encrypting with one and decrypting
+ // with another.
+ return;
+
ASSERT_EQ(KM_ERROR_OK, GenerateKey(AuthorizationSetBuilder()
.RsaEncryptionKey(768, 3)
.Padding(KM_PAD_RSA_OAEP)
@@ -2052,7 +2304,7 @@ TEST_P(EncryptionOperationsTest, RsaOaepDecryptWithWrongDigest) {
EXPECT_EQ(KM_ERROR_UNKNOWN_ERROR, FinishOperation(&result));
EXPECT_EQ(0U, result.size());
- if (GetParam()->algorithm_in_hardware(KM_ALGORITHM_RSA))
+ if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA))
EXPECT_EQ(4, GetParam()->keymaster0_calls());
}
@@ -2073,7 +2325,7 @@ TEST_P(EncryptionOperationsTest, RsaOaepTooLarge) {
EXPECT_EQ(KM_ERROR_INVALID_INPUT_LENGTH, FinishOperation(&result));
EXPECT_EQ(0U, result.size());
- if (GetParam()->algorithm_in_hardware(KM_ALGORITHM_RSA))
+ if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA))
EXPECT_EQ(2, GetParam()->keymaster0_calls());
}
@@ -2100,7 +2352,7 @@ TEST_P(EncryptionOperationsTest, RsaOaepCorruptedDecrypt) {
EXPECT_EQ(KM_ERROR_UNKNOWN_ERROR, FinishOperation(&result));
EXPECT_EQ(0U, result.size());
- if (GetParam()->algorithm_in_hardware(KM_ALGORITHM_RSA))
+ if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA))
EXPECT_EQ(4, GetParam()->keymaster0_calls());
}
@@ -2108,16 +2360,16 @@ TEST_P(EncryptionOperationsTest, RsaPkcs1Success) {
ASSERT_EQ(KM_ERROR_OK, GenerateKey(AuthorizationSetBuilder().RsaEncryptionKey(512, 3).Padding(
KM_PAD_RSA_PKCS1_1_5_ENCRYPT)));
string message = "Hello World!";
- string ciphertext1 = EncryptMessage(string(message), KM_PAD_RSA_PKCS1_1_5_ENCRYPT);
+ string ciphertext1 = EncryptMessage(message, KM_PAD_RSA_PKCS1_1_5_ENCRYPT);
EXPECT_EQ(512U / 8, ciphertext1.size());
- string ciphertext2 = EncryptMessage(string(message), KM_PAD_RSA_PKCS1_1_5_ENCRYPT);
+ string ciphertext2 = EncryptMessage(message, KM_PAD_RSA_PKCS1_1_5_ENCRYPT);
EXPECT_EQ(512U / 8, ciphertext2.size());
// PKCS1 v1.5 randomizes padding so every result should be different.
EXPECT_NE(ciphertext1, ciphertext2);
- if (GetParam()->algorithm_in_hardware(KM_ALGORITHM_RSA))
+ if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA))
EXPECT_EQ(3, GetParam()->keymaster0_calls());
}
@@ -2125,16 +2377,55 @@ TEST_P(EncryptionOperationsTest, RsaPkcs1RoundTrip) {
ASSERT_EQ(KM_ERROR_OK, GenerateKey(AuthorizationSetBuilder().RsaEncryptionKey(512, 3).Padding(
KM_PAD_RSA_PKCS1_1_5_ENCRYPT)));
string message = "Hello World!";
- string ciphertext = EncryptMessage(string(message), KM_PAD_RSA_PKCS1_1_5_ENCRYPT);
+ string ciphertext = EncryptMessage(message, KM_PAD_RSA_PKCS1_1_5_ENCRYPT);
EXPECT_EQ(512U / 8, ciphertext.size());
string plaintext = DecryptMessage(ciphertext, KM_PAD_RSA_PKCS1_1_5_ENCRYPT);
EXPECT_EQ(message, plaintext);
- if (GetParam()->algorithm_in_hardware(KM_ALGORITHM_RSA))
+ if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA))
EXPECT_EQ(4, GetParam()->keymaster0_calls());
}
+TEST_P(EncryptionOperationsTest, RsaRoundTripAllCombinations) {
+ size_t key_size = 2048;
+ ASSERT_EQ(KM_ERROR_OK, GenerateKey(AuthorizationSetBuilder()
+ .RsaEncryptionKey(key_size, 3)
+ .Padding(KM_PAD_RSA_PKCS1_1_5_ENCRYPT)
+ .Padding(KM_PAD_RSA_OAEP)
+ .Digest(KM_DIGEST_NONE)
+ .Digest(KM_DIGEST_MD5)
+ .Digest(KM_DIGEST_SHA1)
+ .Digest(KM_DIGEST_SHA_2_224)
+ .Digest(KM_DIGEST_SHA_2_256)
+ .Digest(KM_DIGEST_SHA_2_384)
+ .Digest(KM_DIGEST_SHA_2_512)));
+
+ string message = "Hello World!";
+
+ keymaster_padding_t padding_modes[] = {KM_PAD_RSA_OAEP, KM_PAD_RSA_PKCS1_1_5_ENCRYPT};
+ keymaster_digest_t digests[] = {
+ KM_DIGEST_NONE, KM_DIGEST_MD5, KM_DIGEST_SHA1, KM_DIGEST_SHA_2_224,
+ KM_DIGEST_SHA_2_256, KM_DIGEST_SHA_2_384, KM_DIGEST_SHA_2_512,
+ };
+
+ for (auto padding : padding_modes)
+ for (auto digest : digests) {
+ if (padding == KM_PAD_RSA_OAEP && digest == KM_DIGEST_NONE)
+ // OAEP requires a digest.
+ continue;
+
+ string ciphertext = EncryptMessage(message, digest, padding);
+ EXPECT_EQ(key_size / 8, ciphertext.size());
+
+ string plaintext = DecryptMessage(ciphertext, digest, padding);
+ EXPECT_EQ(message, plaintext);
+ }
+
+ if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA))
+ EXPECT_EQ(40, GetParam()->keymaster0_calls());
+}
+
TEST_P(EncryptionOperationsTest, RsaPkcs1TooLarge) {
ASSERT_EQ(KM_ERROR_OK, GenerateKey(AuthorizationSetBuilder().RsaEncryptionKey(512, 3).Padding(
KM_PAD_RSA_PKCS1_1_5_ENCRYPT)));
@@ -2149,24 +2440,7 @@ TEST_P(EncryptionOperationsTest, RsaPkcs1TooLarge) {
EXPECT_EQ(KM_ERROR_INVALID_INPUT_LENGTH, FinishOperation(&result));
EXPECT_EQ(0U, result.size());
- if (GetParam()->algorithm_in_hardware(KM_ALGORITHM_RSA))
- EXPECT_EQ(2, GetParam()->keymaster0_calls());
-}
-
-TEST_P(EncryptionOperationsTest, RsaPkcs1InvalidDigest) {
- ASSERT_EQ(KM_ERROR_OK, GenerateKey(AuthorizationSetBuilder()
- .RsaEncryptionKey(512, 3)
- .Padding(KM_PAD_RSA_PKCS1_1_5_ENCRYPT)
- .Digest(KM_DIGEST_NONE)));
- string message = "Hello World!";
- string result;
-
- AuthorizationSet begin_params(client_params());
- begin_params.push_back(TAG_PADDING, KM_PAD_RSA_PKCS1_1_5_ENCRYPT);
- begin_params.push_back(TAG_DIGEST, KM_DIGEST_NONE); // Any digest is invalid
- EXPECT_EQ(KM_ERROR_UNSUPPORTED_DIGEST, BeginOperation(KM_PURPOSE_ENCRYPT, begin_params));
-
- if (GetParam()->algorithm_in_hardware(KM_ALGORITHM_RSA))
+ if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA))
EXPECT_EQ(2, GetParam()->keymaster0_calls());
}
@@ -2189,7 +2463,7 @@ TEST_P(EncryptionOperationsTest, RsaPkcs1CorruptedDecrypt) {
EXPECT_EQ(KM_ERROR_UNKNOWN_ERROR, FinishOperation(&result));
EXPECT_EQ(0U, result.size());
- if (GetParam()->algorithm_in_hardware(KM_ALGORITHM_RSA))
+ if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA))
EXPECT_EQ(4, GetParam()->keymaster0_calls());
}
@@ -2201,7 +2475,7 @@ TEST_P(EncryptionOperationsTest, RsaEncryptWithSigningKey) {
begin_params.push_back(TAG_PADDING, KM_PAD_NONE);
ASSERT_EQ(KM_ERROR_INCOMPATIBLE_PURPOSE, BeginOperation(KM_PURPOSE_DECRYPT, begin_params));
- if (GetParam()->algorithm_in_hardware(KM_ALGORITHM_RSA))
+ if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA))
EXPECT_EQ(2, GetParam()->keymaster0_calls());
}
@@ -2211,7 +2485,7 @@ TEST_P(EncryptionOperationsTest, EcdsaEncrypt) {
ASSERT_EQ(KM_ERROR_UNSUPPORTED_PURPOSE, BeginOperation(KM_PURPOSE_ENCRYPT));
ASSERT_EQ(KM_ERROR_UNSUPPORTED_PURPOSE, BeginOperation(KM_PURPOSE_DECRYPT));
- if (GetParam()->algorithm_in_hardware(KM_ALGORITHM_EC))
+ if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_EC))
EXPECT_EQ(3, GetParam()->keymaster0_calls());
}
@@ -3339,5 +3613,32 @@ TEST_P(Keymaster0AdapterTest, OldHwKeymaster0RsaBlobGetCharacteristics) {
EXPECT_EQ(1, GetParam()->keymaster0_calls());
}
+TEST(SoftKeymasterWrapperTest, CheckKeymaster1Device) {
+ // Make a good fake device, and wrap it.
+ SoftKeymasterDevice* good_fake(new SoftKeymasterDevice(new TestKeymasterContext));
+
+ // Wrap it and check it.
+ SoftKeymasterDevice* good_fake_wrapper(new SoftKeymasterDevice(new TestKeymasterContext));
+ good_fake_wrapper->SetHardwareDevice(good_fake->keymaster_device());
+ EXPECT_TRUE(good_fake_wrapper->Keymaster1DeviceIsGood());
+
+ // Close and clean up wrapper and wrapped
+ good_fake_wrapper->keymaster_device()->common.close(good_fake_wrapper->hw_device());
+
+ // Make a "bad" (doesn't support all digests) device;
+ keymaster1_device_t* sha256_only_fake = make_device_sha256_only(
+ (new SoftKeymasterDevice(new TestKeymasterContext("256")))->keymaster_device());
+
+ // Wrap it and check it.
+ SoftKeymasterDevice* sha256_only_fake_wrapper(
+ (new SoftKeymasterDevice(new TestKeymasterContext)));
+ sha256_only_fake_wrapper->SetHardwareDevice(sha256_only_fake);
+ EXPECT_FALSE(sha256_only_fake_wrapper->Keymaster1DeviceIsGood());
+
+ // Close and clean up wrapper and wrapped
+ sha256_only_fake_wrapper->keymaster_device()->common.close(
+ sha256_only_fake_wrapper->hw_device());
+}
+
} // namespace test
} // namespace keymaster
diff --git a/android_keymaster_test_utils.cpp b/android_keymaster_test_utils.cpp
index dacc413..3f058c5 100644
--- a/android_keymaster_test_utils.cpp
+++ b/android_keymaster_test_utils.cpp
@@ -23,6 +23,8 @@
#include <keymaster/android_keymaster_messages.h>
#include <keymaster/android_keymaster_utils.h>
+using std::copy_if;
+using std::find_if;
using std::is_permutation;
using std::ostream;
using std::string;
@@ -636,5 +638,227 @@ void Keymaster1Test::corrupt_key_blob() {
++tmp[blob_.key_material_size / 2];
}
+class Sha256OnlyWrapper {
+ public:
+ Sha256OnlyWrapper(const keymaster1_device_t* wrapped_device) : wrapped_device_(wrapped_device) {
+
+ new_module = *wrapped_device_->common.module;
+ new_module_name = std::string("SHA 256-only ") + wrapped_device_->common.module->name;
+ new_module.name = new_module_name.c_str();
+
+ memset(&device_, 0, sizeof(device_));
+ device_.common.module = &new_module;
+
+ device_.common.close = close_device;
+ device_.get_supported_algorithms = get_supported_algorithms;
+ device_.get_supported_block_modes = get_supported_block_modes;
+ device_.get_supported_padding_modes = get_supported_padding_modes;
+ device_.get_supported_digests = get_supported_digests;
+ device_.get_supported_import_formats = get_supported_import_formats;
+ device_.get_supported_export_formats = get_supported_export_formats;
+ device_.add_rng_entropy = add_rng_entropy;
+ device_.generate_key = generate_key;
+ device_.get_key_characteristics = get_key_characteristics;
+ device_.import_key = import_key;
+ device_.export_key = export_key;
+ device_.begin = begin;
+ device_.update = update;
+ device_.finish = finish;
+ device_.abort = abort;
+ }
+
+ keymaster1_device_t* keymaster_device() { return &device_; }
+
+ static bool is_supported(keymaster_digest_t digest) {
+ return digest == KM_DIGEST_NONE || digest == KM_DIGEST_SHA_2_256;
+ }
+
+ static bool all_digests_supported(const keymaster_key_param_set_t* params) {
+ for (size_t i = 0; i < params->length; ++i)
+ if (params->params[i].tag == TAG_DIGEST)
+ if (!is_supported(static_cast<keymaster_digest_t>(params->params[i].enumerated)))
+ return false;
+ return true;
+ }
+
+ static const keymaster_key_param_t*
+ get_algorithm_param(const keymaster_key_param_set_t* params) {
+ keymaster_key_param_t* end = params->params + params->length;
+ auto alg_ptr = std::find_if(params->params, end, [](keymaster_key_param_t& p) {
+ return p.tag == KM_TAG_ALGORITHM;
+ });
+ if (alg_ptr == end)
+ return nullptr;
+ return alg_ptr;
+ }
+
+ static int close_device(hw_device_t* dev) {
+ Sha256OnlyWrapper* wrapper = reinterpret_cast<Sha256OnlyWrapper*>(dev);
+ const keymaster1_device_t* wrapped_device = wrapper->wrapped_device_;
+ delete wrapper;
+ return wrapped_device->common.close(const_cast<hw_device_t*>(&wrapped_device->common));
+ }
+
+ static const keymaster1_device_t* unwrap(const keymaster1_device_t* dev) {
+ return reinterpret_cast<const Sha256OnlyWrapper*>(dev)->wrapped_device_;
+ }
+
+ static keymaster_error_t get_supported_algorithms(const struct keymaster1_device* dev,
+ keymaster_algorithm_t** algorithms,
+ size_t* algorithms_length) {
+ return unwrap(dev)->get_supported_algorithms(unwrap(dev), algorithms, algorithms_length);
+ }
+ static keymaster_error_t get_supported_block_modes(const struct keymaster1_device* dev,
+ keymaster_algorithm_t algorithm,
+ keymaster_purpose_t purpose,
+ keymaster_block_mode_t** modes,
+ size_t* modes_length) {
+ return unwrap(dev)
+ ->get_supported_block_modes(unwrap(dev), algorithm, purpose, modes, modes_length);
+ }
+ static keymaster_error_t get_supported_padding_modes(const struct keymaster1_device* dev,
+ keymaster_algorithm_t algorithm,
+ keymaster_purpose_t purpose,
+ keymaster_padding_t** modes,
+ size_t* modes_length) {
+ return unwrap(dev)
+ ->get_supported_padding_modes(unwrap(dev), algorithm, purpose, modes, modes_length);
+ }
+
+ static keymaster_error_t get_supported_digests(const keymaster1_device_t* dev,
+ keymaster_algorithm_t algorithm,
+ keymaster_purpose_t purpose,
+ keymaster_digest_t** digests,
+ size_t* digests_length) {
+ keymaster_error_t error = unwrap(dev)->get_supported_digests(
+ unwrap(dev), algorithm, purpose, digests, digests_length);
+ if (error != KM_ERROR_OK)
+ return error;
+
+ std::vector<keymaster_digest_t> filtered_digests;
+ std::copy_if(*digests, *digests + *digests_length, std::back_inserter(filtered_digests),
+ [](keymaster_digest_t digest) { return is_supported(digest); });
+
+ free(*digests);
+ *digests_length = filtered_digests.size();
+ *digests = reinterpret_cast<keymaster_digest_t*>(
+ malloc(*digests_length * sizeof(keymaster_digest_t)));
+ std::copy(filtered_digests.begin(), filtered_digests.end(), *digests);
+
+ return KM_ERROR_OK;
+ }
+
+ static keymaster_error_t get_supported_import_formats(const struct keymaster1_device* dev,
+ keymaster_algorithm_t algorithm,
+ keymaster_key_format_t** formats,
+ size_t* formats_length) {
+ return unwrap(dev)
+ ->get_supported_import_formats(unwrap(dev), algorithm, formats, formats_length);
+ }
+ static keymaster_error_t get_supported_export_formats(const struct keymaster1_device* dev,
+ keymaster_algorithm_t algorithm,
+ keymaster_key_format_t** formats,
+ size_t* formats_length) {
+ return unwrap(dev)
+ ->get_supported_export_formats(unwrap(dev), algorithm, formats, formats_length);
+ }
+ static keymaster_error_t add_rng_entropy(const struct keymaster1_device* dev,
+ const uint8_t* data, size_t data_length) {
+ return unwrap(dev)->add_rng_entropy(unwrap(dev), data, data_length);
+ }
+
+ static keymaster_error_t generate_key(const keymaster1_device_t* dev,
+ const keymaster_key_param_set_t* params,
+ keymaster_key_blob_t* key_blob,
+ keymaster_key_characteristics_t** characteristics) {
+ auto alg_ptr = get_algorithm_param(params);
+ if (!alg_ptr)
+ return KM_ERROR_UNSUPPORTED_ALGORITHM;
+ if (alg_ptr->enumerated == KM_ALGORITHM_HMAC && !all_digests_supported(params))
+ return KM_ERROR_UNSUPPORTED_DIGEST;
+
+ return unwrap(dev)->generate_key(unwrap(dev), params, key_blob, characteristics);
+ }
+
+ static keymaster_error_t
+ get_key_characteristics(const struct keymaster1_device* dev,
+ const keymaster_key_blob_t* key_blob, const keymaster_blob_t* client_id,
+ const keymaster_blob_t* app_data,
+ keymaster_key_characteristics_t** characteristics) {
+ return unwrap(dev)
+ ->get_key_characteristics(unwrap(dev), key_blob, client_id, app_data, characteristics);
+ }
+
+ static keymaster_error_t
+ import_key(const keymaster1_device_t* dev, const keymaster_key_param_set_t* params,
+ keymaster_key_format_t key_format, const keymaster_blob_t* key_data,
+ keymaster_key_blob_t* key_blob, keymaster_key_characteristics_t** characteristics) {
+ auto alg_ptr = get_algorithm_param(params);
+ if (!alg_ptr)
+ return KM_ERROR_UNSUPPORTED_ALGORITHM;
+ if (alg_ptr->enumerated == KM_ALGORITHM_HMAC && !all_digests_supported(params))
+ return KM_ERROR_UNSUPPORTED_DIGEST;
+
+ return unwrap(dev)
+ ->import_key(unwrap(dev), params, key_format, key_data, key_blob, characteristics);
+ }
+
+ static keymaster_error_t export_key(const struct keymaster1_device* dev, //
+ keymaster_key_format_t export_format,
+ const keymaster_key_blob_t* key_to_export,
+ const keymaster_blob_t* client_id,
+ const keymaster_blob_t* app_data,
+ keymaster_blob_t* export_data) {
+ return unwrap(dev)->export_key(unwrap(dev), export_format, key_to_export, client_id,
+ app_data, export_data);
+ }
+
+ static keymaster_error_t begin(const keymaster1_device_t* dev, //
+ keymaster_purpose_t purpose, const keymaster_key_blob_t* key,
+ const keymaster_key_param_set_t* in_params,
+ keymaster_key_param_set_t* out_params,
+ keymaster_operation_handle_t* operation_handle) {
+ if (!all_digests_supported(in_params))
+ return KM_ERROR_UNSUPPORTED_DIGEST;
+ return unwrap(dev)
+ ->begin(unwrap(dev), purpose, key, in_params, out_params, operation_handle);
+ }
+
+ static keymaster_error_t update(const keymaster1_device_t* dev,
+ keymaster_operation_handle_t operation_handle,
+ const keymaster_key_param_set_t* in_params,
+ const keymaster_blob_t* input, size_t* input_consumed,
+ keymaster_key_param_set_t* out_params,
+ keymaster_blob_t* output) {
+ return unwrap(dev)->update(unwrap(dev), operation_handle, in_params, input, input_consumed,
+ out_params, output);
+ }
+
+ static keymaster_error_t finish(const struct keymaster1_device* dev, //
+ keymaster_operation_handle_t operation_handle,
+ const keymaster_key_param_set_t* in_params,
+ const keymaster_blob_t* signature,
+ keymaster_key_param_set_t* out_params,
+ keymaster_blob_t* output) {
+ return unwrap(dev)
+ ->finish(unwrap(dev), operation_handle, in_params, signature, out_params, output);
+ }
+
+ static keymaster_error_t abort(const struct keymaster1_device* dev,
+ keymaster_operation_handle_t operation_handle) {
+ return unwrap(dev)->abort(unwrap(dev), operation_handle);
+ }
+
+ private:
+ keymaster1_device_t device_;
+ const keymaster1_device_t* wrapped_device_;
+ hw_module_t new_module;
+ string new_module_name;
+};
+
+keymaster1_device_t* make_device_sha256_only(keymaster1_device_t* device) {
+ return (new Sha256OnlyWrapper(device))->keymaster_device();
+}
+
} // namespace test
} // namespace keymaster
diff --git a/android_keymaster_test_utils.h b/android_keymaster_test_utils.h
index 3d9e26a..c7177ea 100644
--- a/android_keymaster_test_utils.h
+++ b/android_keymaster_test_utils.h
@@ -158,8 +158,9 @@ class Keymaster1TestInstanceCreator {
virtual ~Keymaster1TestInstanceCreator(){};
virtual keymaster1_device_t* CreateDevice() const = 0;
- virtual bool algorithm_in_hardware(keymaster_algorithm_t algorithm) const = 0;
+ virtual bool algorithm_in_km0_hardware(keymaster_algorithm_t algorithm) const = 0;
virtual int keymaster0_calls() const = 0;
+ virtual int minimal_digest_set() const { return false; }
};
// Use a shared_ptr because it's copyable.
@@ -444,6 +445,13 @@ struct Keymaster0CountingWrapper : public keymaster0_device_t {
int counter_;
};
+
+/**
+ * This function takes a keymaster1_device_t and wraps it in an adapter that supports only
+ * KM_DIGEST_SHA_2_256.
+ */
+keymaster1_device_t* make_device_sha256_only(keymaster1_device_t* device);
+
} // namespace test
} // namespace keymaster
diff --git a/asymmetric_key.cpp b/asymmetric_key.cpp
index 74751f7..2ead3c5 100644
--- a/asymmetric_key.cpp
+++ b/asymmetric_key.cpp
@@ -25,28 +25,6 @@
namespace keymaster {
-keymaster_error_t AsymmetricKey::key_material(UniquePtr<uint8_t[]>* material, size_t* size) const {
- if (material == NULL || size == NULL)
- return KM_ERROR_OUTPUT_PARAMETER_NULL;
-
- UniquePtr<EVP_PKEY, EVP_PKEY_Delete> pkey(EVP_PKEY_new());
- if (pkey.get() == NULL)
- return KM_ERROR_MEMORY_ALLOCATION_FAILED;
-
- if (!InternalToEvp(pkey.get()))
- return TranslateLastOpenSslError();
-
- *size = i2d_PrivateKey(pkey.get(), NULL /* key_data*/);
- if (*size <= 0)
- return TranslateLastOpenSslError();
-
- material->reset(new (std::nothrow) uint8_t[*size]);
- uint8_t* tmp = material->get();
- i2d_PrivateKey(pkey.get(), &tmp);
-
- return KM_ERROR_OK;
-}
-
keymaster_error_t AsymmetricKey::formatted_key_material(keymaster_key_format_t format,
UniquePtr<uint8_t[]>* material,
size_t* size) const {
diff --git a/asymmetric_key.h b/asymmetric_key.h
index d8606dc..1a3b09f 100644
--- a/asymmetric_key.h
+++ b/asymmetric_key.h
@@ -29,7 +29,6 @@ class AsymmetricKey : public Key {
keymaster_error_t* error)
: Key(hw_enforced, sw_enforced, error) {}
- keymaster_error_t key_material(UniquePtr<uint8_t[]>* material, size_t* size) const override;
keymaster_error_t formatted_key_material(keymaster_key_format_t format,
UniquePtr<uint8_t[]>* material,
size_t* size) const override;
diff --git a/asymmetric_key_factory.cpp b/asymmetric_key_factory.cpp
index 05b69e4..b06d0d8 100644
--- a/asymmetric_key_factory.cpp
+++ b/asymmetric_key_factory.cpp
@@ -39,6 +39,7 @@ AsymmetricKeyFactory::SupportedExportFormats(size_t* format_count) const {
}
keymaster_error_t AsymmetricKeyFactory::LoadKey(const KeymasterKeyBlob& key_material,
+ const AuthorizationSet& /* additional_params */,
const AuthorizationSet& hw_enforced,
const AuthorizationSet& sw_enforced,
UniquePtr<Key>* key) const {
diff --git a/auth_encrypted_key_blob.cpp b/auth_encrypted_key_blob.cpp
index e7511d1..655bc12 100644
--- a/auth_encrypted_key_blob.cpp
+++ b/auth_encrypted_key_blob.cpp
@@ -71,7 +71,7 @@ static keymaster_error_t DeserializeUnversionedBlob(const KeymasterKeyBlob& key_
!copy_from_buf(buf_ptr, end, tag->peek_write(), OCB_TAG_LENGTH) ||
!hw_enforced->Deserialize(buf_ptr, end) || //
!sw_enforced->Deserialize(buf_ptr, end)) {
- LOG_I("Failed to deserialize unversioned blob (may be a HW-backed key)", 0);
+ LOG_D("Failed to deserialize unversioned blob (may be a HW-backed key)", 0);
return KM_ERROR_INVALID_KEY_BLOB;
}
if (!nonce->advance_write(OCB_NONCE_LENGTH) || !tag->advance_write(OCB_TAG_LENGTH))
@@ -127,7 +127,7 @@ keymaster_error_t DeserializeAuthEncryptedBlob(const KeymasterKeyBlob& key_blob,
// Based on those two checks alone, the probability of interpreting an unversioned blob as a
// version 0 blob is 1/2^40. That's small enough to be negligible, but there are additional
// checks which lower it further.
- LOG_I("Failed to deserialize versioned key blob. Assuming unversioned.", 0);
+ LOG_D("Failed to deserialize versioned key blob. Assuming unversioned.", 0);
return DeserializeUnversionedBlob(key_blob, encrypted_key_material, hw_enforced,
sw_enforced, nonce, tag);
}
diff --git a/authorization_set.cpp b/authorization_set.cpp
index 7ddb524..9a2b36a 100644
--- a/authorization_set.cpp
+++ b/authorization_set.cpp
@@ -191,6 +191,15 @@ int AuthorizationSet::find(keymaster_tag_t tag, int begin) const {
}
keymaster_key_param_t empty;
+keymaster_key_param_t& AuthorizationSet::operator[](int at) {
+ if (is_valid() == OK && at < (int)elems_size_) {
+ return elems_[at];
+ }
+ memset(&empty, 0, sizeof(empty));
+ return empty;
+}
+
+
keymaster_key_param_t AuthorizationSet::operator[](int at) const {
if (is_valid() == OK && at < (int)elems_size_) {
return elems_[at];
diff --git a/ec_key.h b/ec_key.h
index 2f66eb1..96c2635 100644
--- a/ec_key.h
+++ b/ec_key.h
@@ -35,7 +35,7 @@ class EcKey : public AsymmetricKey {
bool InternalToEvp(EVP_PKEY* pkey) const override;
bool EvpToInternal(const EVP_PKEY* pkey) override;
- EC_KEY* key() const { return EC_KEY_dup(ec_key_.get()); }
+ EC_KEY* key() const { return ec_key_.get(); }
protected:
EcKey(EC_KEY* ec_key, const AuthorizationSet& hw_enforced, const AuthorizationSet& sw_enforced,
diff --git a/ec_keymaster0_key.cpp b/ec_keymaster0_key.cpp
index 8cea462..c10a014 100644
--- a/ec_keymaster0_key.cpp
+++ b/ec_keymaster0_key.cpp
@@ -31,8 +31,7 @@ namespace keymaster {
EcdsaKeymaster0KeyFactory::EcdsaKeymaster0KeyFactory(const SoftKeymasterContext* context,
const Keymaster0Engine* engine)
- : EcKeyFactory(context), engine_(engine), soft_context_(context) {
-}
+ : EcKeyFactory(context), engine_(engine) {}
keymaster_error_t EcdsaKeymaster0KeyFactory::GenerateKey(const AuthorizationSet& key_description,
KeymasterKeyBlob* key_blob,
@@ -97,6 +96,7 @@ keymaster_error_t EcdsaKeymaster0KeyFactory::ImportKey(
}
keymaster_error_t EcdsaKeymaster0KeyFactory::LoadKey(const KeymasterKeyBlob& key_material,
+ const AuthorizationSet& additional_params,
const AuthorizationSet& hw_enforced,
const AuthorizationSet& sw_enforced,
UniquePtr<Key>* key) const {
@@ -104,7 +104,7 @@ keymaster_error_t EcdsaKeymaster0KeyFactory::LoadKey(const KeymasterKeyBlob& key
return KM_ERROR_OUTPUT_PARAMETER_NULL;
if (sw_enforced.GetTagCount(TAG_ALGORITHM) == 1)
- return super::LoadKey(key_material, hw_enforced, sw_enforced, key);
+ return super::LoadKey(key_material, additional_params, hw_enforced, sw_enforced, key);
unique_ptr<EC_KEY, EC_Delete> ec_key(engine_->BlobToEcKey(key_material));
if (!ec_key)
@@ -122,23 +122,6 @@ keymaster_error_t EcdsaKeymaster0KeyFactory::LoadKey(const KeymasterKeyBlob& key
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(dup_buffer(blob->key_material, *size));
- if (!material->get())
- return KM_ERROR_MEMORY_ALLOCATION_FAILED;
- return KM_ERROR_OK;
-}
+ : EcKey(ec_key, hw_enforced, sw_enforced, error), engine_(engine) {}
} // namespace keymaster
diff --git a/ec_keymaster0_key.h b/ec_keymaster0_key.h
index 428c2b5..1d5cfe2 100644
--- a/ec_keymaster0_key.h
+++ b/ec_keymaster0_key.h
@@ -49,13 +49,13 @@ class EcdsaKeymaster0KeyFactory : public EcKeyFactory {
AuthorizationSet* sw_enforced) const override;
keymaster_error_t LoadKey(const KeymasterKeyBlob& key_material,
+ const AuthorizationSet& additional_params,
const AuthorizationSet& hw_enforced,
const AuthorizationSet& sw_enforced,
UniquePtr<Key>* key) const override;
private:
const Keymaster0Engine* engine_;
- const SoftKeymasterContext* soft_context_;
};
class EcKeymaster0Key : public EcKey {
@@ -66,8 +66,6 @@ class EcKeymaster0Key : public EcKey {
const AuthorizationSet& sw_enforced, const Keymaster0Engine* engine,
keymaster_error_t* error);
- keymaster_error_t key_material(UniquePtr<uint8_t[]>* material, size_t* size) const override;
-
private:
const Keymaster0Engine* engine_;
};
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
diff --git a/ec_keymaster1_key.h b/ec_keymaster1_key.h
new file mode 100644
index 0000000..b4c347a
--- /dev/null
+++ b/ec_keymaster1_key.h
@@ -0,0 +1,82 @@
+/*
+ * 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.
+ */
+
+#ifndef SYSTEM_KEYMASTER_EC_KEYMASTER1_KEY_H_
+#define SYSTEM_KEYMASTER_EC_KEYMASTER1_KEY_H_
+
+#include <openssl/ecdsa.h>
+
+#include <hardware/keymaster1.h>
+#include <keymaster/android_keymaster_utils.h>
+#include <keymaster/logger.h>
+#include <keymaster/ec_key_factory.h>
+#include <keymaster/soft_keymaster_context.h>
+
+#include "ec_key.h"
+#include "keymaster1_engine.h"
+
+namespace keymaster {
+
+class SoftKeymasterContext;
+
+/**
+ * EcdsaKeymaster1KeyFactory is a KeyFactory that creates and loads keys which are actually backed
+ * by a hardware keymaster1 module, but which does not support all keymaster1 digests. During
+ * generation or import any unsupported digests in the key description are silently replaced with
+ * KM_DIGEST_NONE.
+ */
+class EcdsaKeymaster1KeyFactory : public EcKeyFactory {
+ public:
+ EcdsaKeymaster1KeyFactory(const SoftKeymasterContext* context, const Keymaster1Engine* engine);
+
+ keymaster_error_t GenerateKey(const AuthorizationSet& key_description,
+ KeymasterKeyBlob* key_blob, AuthorizationSet* hw_enforced,
+ AuthorizationSet* sw_enforced) const override;
+
+ keymaster_error_t 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 override;
+
+ keymaster_error_t LoadKey(const KeymasterKeyBlob& key_material,
+ const AuthorizationSet& additional_params,
+ const AuthorizationSet& hw_enforced,
+ const AuthorizationSet& sw_enforced,
+ UniquePtr<Key>* key) const override;
+
+ OperationFactory* GetOperationFactory(keymaster_purpose_t purpose) const override;
+
+ private:
+ const Keymaster1Engine* engine_;
+
+ std::unique_ptr<OperationFactory> sign_factory_;
+ std::unique_ptr<OperationFactory> verify_factory_;
+};
+
+class EcdsaKeymaster1Key : public EcKey {
+ public:
+ EcdsaKeymaster1Key(EC_KEY* ecdsa_key, const AuthorizationSet& hw_enforced,
+ const AuthorizationSet& sw_enforced, const Keymaster1Engine* engine,
+ keymaster_error_t* error);
+
+ private:
+ const Keymaster1Engine* engine_;
+};
+
+} // namespace keymaster
+
+#endif // SYSTEM_KEYMASTER_ECDSA_KEYMASTER1_KEY_H_
diff --git a/ecdsa_keymaster1_operation.cpp b/ecdsa_keymaster1_operation.cpp
new file mode 100644
index 0000000..7e1a4f5
--- /dev/null
+++ b/ecdsa_keymaster1_operation.cpp
@@ -0,0 +1,139 @@
+/*
+ * 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 "ecdsa_keymaster1_operation.h"
+
+#include <memory>
+
+#include <keymaster/android_keymaster_utils.h>
+
+#include "openssl_err.h"
+#include "openssl_utils.h"
+#include "ec_keymaster1_key.h"
+
+using std::unique_ptr;
+
+namespace keymaster {
+
+keymaster_error_t EcdsaKeymaster1WrappedOperation::Begin(EVP_PKEY* ecdsa_key,
+ const AuthorizationSet& input_params) {
+ Keymaster1Engine::KeyData* key_data = engine_->GetData(ecdsa_key);
+ if (!key_data)
+ return KM_ERROR_UNKNOWN_ERROR;
+
+ // Copy the input params and substitute KM_DIGEST_NONE for whatever was specified. Also change
+ // KM_PAD_ECDSA_PSS and KM_PAD_OAEP to KM_PAD_NONE, if necessary. These are the params we'll
+ // pass
+ // to the hardware module. The regular Ecdsa*Operation classes will do software digesting and
+ // padding where we've told the HW not to.
+ //
+ // The reason we don't change KM_PAD_ECDSA_PKCS1_1_5_SIGN or KM_PAD_ECDSA_PKCS1_1_5_ENCRYPT to
+ // KM_PAD_NONE is because the hardware can to those padding modes, since they don't involve
+ // digesting.
+ //
+ // We also cache in the key the padding value that we expect to be passed to the engine crypto
+ // operation. This just allows us to double-check that the correct padding value is reaching
+ // that layer.
+ AuthorizationSet begin_params(input_params);
+ int pos = begin_params.find(TAG_DIGEST);
+ if (pos == -1)
+ return KM_ERROR_UNSUPPORTED_DIGEST;
+ begin_params[pos].enumerated = KM_DIGEST_NONE;
+
+ return engine_->device()->begin(engine_->device(), purpose_, &key_data->key_material,
+ &begin_params, nullptr /* out_params */, &operation_handle_);
+}
+
+keymaster_error_t
+EcdsaKeymaster1WrappedOperation::PrepareFinish(EVP_PKEY* ecdsa_key,
+ const AuthorizationSet& input_params) {
+ Keymaster1Engine::KeyData* key_data = engine_->GetData(ecdsa_key);
+ if (!key_data) {
+ LOG_E("Could not get extended key data... not a Keymaster1Engine key?", 0);
+ return KM_ERROR_UNKNOWN_ERROR;
+ }
+ key_data->op_handle = operation_handle_;
+ key_data->finish_params.Reinitialize(input_params);
+
+ return KM_ERROR_OK;
+}
+
+keymaster_error_t EcdsaKeymaster1WrappedOperation::Abort() {
+ return engine_->device()->abort(engine_->device(), operation_handle_);
+}
+
+keymaster_error_t EcdsaKeymaster1WrappedOperation::GetError(EVP_PKEY* ecdsa_key) {
+ Keymaster1Engine::KeyData* key_data = engine_->GetData(ecdsa_key);
+ if (!key_data)
+ return KM_ERROR_UNKNOWN_ERROR;
+ return key_data->error;
+}
+
+static EVP_PKEY* GetEvpKey(const EcdsaKeymaster1Key& key, keymaster_error_t* error) {
+ if (!key.key()) {
+ *error = KM_ERROR_UNKNOWN_ERROR;
+ return nullptr;
+ }
+
+ UniquePtr<EVP_PKEY, EVP_PKEY_Delete> pkey(EVP_PKEY_new());
+ if (!key.InternalToEvp(pkey.get())) {
+ *error = KM_ERROR_UNKNOWN_ERROR;
+ return nullptr;
+ }
+ return pkey.release();
+}
+
+Operation* EcdsaKeymaster1OperationFactory::CreateOperation(const Key& key,
+ const AuthorizationSet& begin_params,
+ keymaster_error_t* error) {
+ keymaster_digest_t digest;
+ if (!GetAndValidateDigest(begin_params, key, &digest, error))
+ return nullptr;
+
+ const EcdsaKeymaster1Key& ecdsa_km1_key(static_cast<const EcdsaKeymaster1Key&>(key));
+ unique_ptr<EVP_PKEY, EVP_PKEY_Delete> ecdsa(GetEvpKey(ecdsa_km1_key, error));
+ if (!ecdsa)
+ return nullptr;
+
+ switch (purpose_) {
+ case KM_PURPOSE_SIGN:
+ return new EcdsaKeymaster1Operation<EcdsaSignOperation>(digest, ecdsa.release(), engine_);
+ default:
+ LOG_E(
+ "Bug: Pubkey operation requested. Those should be handled by normal ECDSA operations.",
+ 0);
+ *error = KM_ERROR_UNSUPPORTED_PURPOSE;
+ return nullptr;
+ }
+}
+
+static const keymaster_digest_t supported_digests[] = {
+ KM_DIGEST_NONE, KM_DIGEST_MD5, KM_DIGEST_SHA1, KM_DIGEST_SHA_2_224,
+ KM_DIGEST_SHA_2_256, KM_DIGEST_SHA_2_384, KM_DIGEST_SHA_2_512};
+
+const keymaster_digest_t*
+EcdsaKeymaster1OperationFactory::SupportedDigests(size_t* digest_count) const {
+ *digest_count = array_length(supported_digests);
+ return supported_digests;
+}
+
+const keymaster_padding_t*
+EcdsaKeymaster1OperationFactory::SupportedPaddingModes(size_t* padding_mode_count) const {
+ *padding_mode_count = 0;
+ return nullptr;
+}
+
+} // namespace keymaster
diff --git a/ecdsa_keymaster1_operation.h b/ecdsa_keymaster1_operation.h
new file mode 100644
index 0000000..7530fbb
--- /dev/null
+++ b/ecdsa_keymaster1_operation.h
@@ -0,0 +1,119 @@
+/*
+ * 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.
+ */
+
+#ifndef SYSTEM_KEYMASTER_ECDSA_KEYMASTER1_OPERATION_H_
+#define SYSTEM_KEYMASTER_ECDSA_KEYMASTER1_OPERATION_H_
+
+#include <openssl/evp.h>
+
+#include <hardware/keymaster1.h>
+#include <keymaster/android_keymaster_utils.h>
+
+#include "ecdsa_operation.h"
+#include "keymaster1_engine.h"
+
+namespace keymaster {
+
+class EcdsaKeymaster1WrappedOperation {
+ public:
+ EcdsaKeymaster1WrappedOperation(keymaster_purpose_t purpose, const Keymaster1Engine* engine)
+ : purpose_(purpose), operation_handle_(0), engine_(engine) {}
+ ~EcdsaKeymaster1WrappedOperation() {
+ if (operation_handle_)
+ Abort();
+ }
+
+ keymaster_error_t Begin(EVP_PKEY* ecdsa_key, const AuthorizationSet& input_params);
+ keymaster_error_t PrepareFinish(EVP_PKEY* ecdsa_key, const AuthorizationSet& input_params);
+ void Finish() { operation_handle_ = 0; }
+ keymaster_error_t Abort();
+
+ keymaster_error_t GetError(EVP_PKEY* ecdsa_key);
+
+ protected:
+ keymaster_purpose_t purpose_;
+ keymaster_operation_handle_t operation_handle_;
+ const Keymaster1Engine* engine_;
+};
+
+template <typename BaseOperation> class EcdsaKeymaster1Operation : public BaseOperation {
+ typedef BaseOperation super;
+
+ public:
+ EcdsaKeymaster1Operation(keymaster_digest_t digest, EVP_PKEY* key,
+ const Keymaster1Engine* engine)
+ : BaseOperation(digest, key), wrapped_operation_(super::purpose(), engine) {
+ // Shouldn't be instantiated for public key operations.
+ assert(super::purpose() != KM_PURPOSE_VERIFY);
+ assert(super::purpose() != KM_PURPOSE_ENCRYPT);
+ }
+
+ keymaster_error_t Begin(const AuthorizationSet& input_params,
+ AuthorizationSet* output_params) override {
+ keymaster_error_t error = wrapped_operation_.Begin(super::ecdsa_key_, input_params);
+ if (error != KM_ERROR_OK)
+ return error;
+ return super::Begin(input_params, output_params);
+ }
+
+ keymaster_error_t Finish(const AuthorizationSet& input_params, const Buffer& signature,
+ AuthorizationSet* output_params, Buffer* output) override {
+ keymaster_error_t error = wrapped_operation_.PrepareFinish(super::ecdsa_key_, input_params);
+ if (error != KM_ERROR_OK)
+ return error;
+ error = super::Finish(input_params, signature, output_params, output);
+ if (wrapped_operation_.GetError(super::ecdsa_key_) != KM_ERROR_OK)
+ error = wrapped_operation_.GetError(super::ecdsa_key_);
+ if (error == KM_ERROR_OK)
+ wrapped_operation_.Finish();
+ return error;
+ }
+
+ keymaster_error_t Abort() override {
+ keymaster_error_t error = wrapped_operation_.Abort();
+ if (error != KM_ERROR_OK)
+ return error;
+ return super::Abort();
+ }
+
+ private:
+ EcdsaKeymaster1WrappedOperation wrapped_operation_;
+};
+
+/**
+ * Factory that produces EcdsaKeymaster1Operations. This is instantiated and
+ * provided by EcdsaKeymaster1KeyFactory.
+ */
+class EcdsaKeymaster1OperationFactory : public OperationFactory {
+ public:
+ EcdsaKeymaster1OperationFactory(keymaster_purpose_t purpose, const Keymaster1Engine* engine)
+ : purpose_(purpose), engine_(engine) {}
+ KeyType registry_key() const override { return KeyType(KM_ALGORITHM_EC, purpose_); }
+
+ Operation* CreateOperation(const Key& key, const AuthorizationSet& begin_params,
+ keymaster_error_t* error) override;
+
+ const keymaster_digest_t* SupportedDigests(size_t* digest_count) const override;
+ const keymaster_padding_t* SupportedPaddingModes(size_t* padding_mode_count) const override;
+
+ private:
+ keymaster_purpose_t purpose_;
+ const Keymaster1Engine* engine_;
+};
+
+} // namespace keymaster
+
+#endif // SYSTEM_KEYMASTER_ECDSA_KEYMASTER1_OPERATION_H_
diff --git a/ecdsa_operation.cpp b/ecdsa_operation.cpp
index 54af6b2..6da23f5 100644
--- a/ecdsa_operation.cpp
+++ b/ecdsa_operation.cpp
@@ -91,16 +91,17 @@ keymaster_error_t EcdsaOperation::InitDigest() {
}
}
+inline size_t min(size_t a, size_t b) {
+ return (a < b) ? a : b;
+}
+
keymaster_error_t EcdsaOperation::StoreData(const Buffer& input, size_t* input_consumed) {
if (!data_.reserve((EVP_PKEY_bits(ecdsa_key_) + 7) / 8))
return KM_ERROR_MEMORY_ALLOCATION_FAILED;
- // If the write fails, it's because input length exceeds key size.
- if (!data_.write(input.peek_read(), input.available_read())) {
- LOG_E("Input too long: cannot sign %u bytes of data with %u-bit ECDSA key",
- input.available_read() + data_.available_read(), EVP_PKEY_bits(ecdsa_key_));
- return KM_ERROR_INVALID_INPUT_LENGTH;
- }
+ if (!data_.write(input.peek_read(), min(data_.available_write(), input.available_read())))
+ return KM_ERROR_UNKNOWN_ERROR;
+
*input_consumed = input.available_read();
return KM_ERROR_OK;
}
diff --git a/ecdsa_operation.h b/ecdsa_operation.h
index fdca143..fba743f 100644
--- a/ecdsa_operation.h
+++ b/ecdsa_operation.h
@@ -49,8 +49,8 @@ class EcdsaOperation : public Operation {
class EcdsaSignOperation : public EcdsaOperation {
public:
- EcdsaSignOperation(keymaster_purpose_t purpose, keymaster_digest_t digest, EVP_PKEY* key)
- : EcdsaOperation(purpose, digest, key) {}
+ EcdsaSignOperation(keymaster_digest_t digest, EVP_PKEY* key)
+ : EcdsaOperation(KM_PURPOSE_SIGN, digest, key) {}
keymaster_error_t Begin(const AuthorizationSet& input_params,
AuthorizationSet* output_params) override;
keymaster_error_t Update(const AuthorizationSet& additional_params, const Buffer& input,
@@ -62,8 +62,8 @@ class EcdsaSignOperation : public EcdsaOperation {
class EcdsaVerifyOperation : public EcdsaOperation {
public:
- EcdsaVerifyOperation(keymaster_purpose_t purpose, keymaster_digest_t digest, EVP_PKEY* key)
- : EcdsaOperation(purpose, digest, key) {}
+ EcdsaVerifyOperation(keymaster_digest_t digest, EVP_PKEY* key)
+ : EcdsaOperation(KM_PURPOSE_VERIFY, digest, key) {}
keymaster_error_t Begin(const AuthorizationSet& input_params,
AuthorizationSet* output_params) override;
keymaster_error_t Update(const AuthorizationSet& additional_params, const Buffer& input,
@@ -88,7 +88,7 @@ class EcdsaSignOperationFactory : public EcdsaOperationFactory {
private:
keymaster_purpose_t purpose() const override { return KM_PURPOSE_SIGN; }
Operation* InstantiateOperation(keymaster_digest_t digest, EVP_PKEY* key) {
- return new (std::nothrow) EcdsaSignOperation(purpose(), digest, key);
+ return new (std::nothrow) EcdsaSignOperation(digest, key);
}
};
@@ -96,7 +96,7 @@ class EcdsaVerifyOperationFactory : public EcdsaOperationFactory {
public:
keymaster_purpose_t purpose() const override { return KM_PURPOSE_VERIFY; }
Operation* InstantiateOperation(keymaster_digest_t digest, EVP_PKEY* key) {
- return new (std::nothrow) EcdsaVerifyOperation(KM_PURPOSE_VERIFY, digest, key);
+ return new (std::nothrow) EcdsaVerifyOperation(digest, key);
}
};
diff --git a/hmac_key.cpp b/hmac_key.cpp
index 91455e3..40a8906 100644
--- a/hmac_key.cpp
+++ b/hmac_key.cpp
@@ -40,6 +40,7 @@ OperationFactory* HmacKeyFactory::GetOperationFactory(keymaster_purpose_t purpos
}
keymaster_error_t HmacKeyFactory::LoadKey(const KeymasterKeyBlob& key_material,
+ const AuthorizationSet& /* additional_params */,
const AuthorizationSet& hw_enforced,
const AuthorizationSet& sw_enforced,
UniquePtr<Key>* key) const {
diff --git a/hmac_key.h b/hmac_key.h
index c877a12..69d5331 100644
--- a/hmac_key.h
+++ b/hmac_key.h
@@ -28,6 +28,7 @@ class HmacKeyFactory : public SymmetricKeyFactory {
HmacKeyFactory(const KeymasterContext* context) : SymmetricKeyFactory(context) {}
keymaster_error_t LoadKey(const KeymasterKeyBlob& key_material,
+ const AuthorizationSet& additional_params,
const AuthorizationSet& hw_enforced,
const AuthorizationSet& sw_enforced,
UniquePtr<Key>* key) const override;
diff --git a/include/keymaster/android_keymaster.h b/include/keymaster/android_keymaster.h
index e85ba25..24954d9 100644
--- a/include/keymaster/android_keymaster.h
+++ b/include/keymaster/android_keymaster.h
@@ -77,6 +77,8 @@ class AndroidKeymaster {
void AbortOperation(const AbortOperationRequest& request, AbortOperationResponse* response);
void GetVersion(const GetVersionRequest& request, GetVersionResponse* response);
+ bool has_operation(keymaster_operation_handle_t op_handle) const;
+
private:
keymaster_error_t LoadKey(const keymaster_key_blob_t& key_blob,
const AuthorizationSet& additional_params,
diff --git a/include/keymaster/android_keymaster_utils.h b/include/keymaster/android_keymaster_utils.h
index b957dd1..1964f1f 100644
--- a/include/keymaster/android_keymaster_utils.h
+++ b/include/keymaster/android_keymaster_utils.h
@@ -301,6 +301,17 @@ struct KeymasterKeyBlob : public keymaster_key_blob_t {
}
};
+struct Characteristics_Delete {
+ void operator()(keymaster_key_characteristics_t* p) {
+ keymaster_free_characteristics(p);
+ free(p);
+ }
+};
+
+struct Malloc_Delete {
+ void operator()(void* p) { free(p); }
+};
+
} // namespace keymaster
#endif // SYSTEM_KEYMASTER_ANDROID_KEYMASTER_UTILS_H_
diff --git a/include/keymaster/asymmetric_key_factory.h b/include/keymaster/asymmetric_key_factory.h
index 22dfcde..a306d20 100644
--- a/include/keymaster/asymmetric_key_factory.h
+++ b/include/keymaster/asymmetric_key_factory.h
@@ -30,6 +30,7 @@ class AsymmetricKeyFactory : public KeyFactory {
AsymmetricKeyFactory(const KeymasterContext* context) : KeyFactory(context) {}
keymaster_error_t LoadKey(const KeymasterKeyBlob& key_material,
+ const AuthorizationSet& additional_params,
const AuthorizationSet& hw_enforced,
const AuthorizationSet& sw_enforced,
UniquePtr<Key>* key) const override;
diff --git a/include/keymaster/authorization_set.h b/include/keymaster/authorization_set.h
index 360e532..c638b7d 100644
--- a/include/keymaster/authorization_set.h
+++ b/include/keymaster/authorization_set.h
@@ -159,6 +159,11 @@ class AuthorizationSet : public Serializable, public keymaster_key_param_set_t {
/**
* Returns the nth element of the set.
*/
+ keymaster_key_param_t& operator[](int n);
+
+ /**
+ * Returns the nth element of the set.
+ */
keymaster_key_param_t operator[](int n) const;
/**
diff --git a/include/keymaster/key_factory.h b/include/keymaster/key_factory.h
index 4ce3ddb..c77275a 100644
--- a/include/keymaster/key_factory.h
+++ b/include/keymaster/key_factory.h
@@ -49,6 +49,7 @@ class KeyFactory {
AuthorizationSet* sw_enforced) const = 0;
virtual keymaster_error_t LoadKey(const KeymasterKeyBlob& key_material,
+ const AuthorizationSet& additional_params,
const AuthorizationSet& hw_enforced,
const AuthorizationSet& sw_enforced,
UniquePtr<Key>* key) const = 0;
diff --git a/include/keymaster/logger.h b/include/keymaster/logger.h
index 7b9e6d5..a4fdea3 100644
--- a/include/keymaster/logger.h
+++ b/include/keymaster/logger.h
@@ -59,23 +59,8 @@ class Logger {
#define STRINGIFY(x) STR(x)
#define FILE_LINE __FILE__ ", Line " STRINGIFY(__LINE__) ": "
-#ifdef DEBUG
-#define DEBUG_LOGS 1
-#else
-#define DEBUG_LOGS 0
-#endif
-
-#define LOG_D(fmt, ...) \
- do { \
- if (DEBUG_LOGS) \
- Logger::Debug(FILE_LINE fmt, __VA_ARGS__); \
- } while (0)
-#define LOG_I(fmt, ...) \
- do { \
- if (DEBUG_LOGS) \
- Logger::Info(FILE_LINE fmt, __VA_ARGS__); \
- } while (0)
-
+#define LOG_D(fmt, ...) Logger::Debug(FILE_LINE fmt, __VA_ARGS__)
+#define LOG_I(fmt, ...) Logger::Info(FILE_LINE fmt, __VA_ARGS__)
#define LOG_W(fmt, ...) Logger::Warning(FILE_LINE fmt, __VA_ARGS__)
#define LOG_E(fmt, ...) Logger::Error(FILE_LINE fmt, __VA_ARGS__)
#define LOG_S(fmt, ...) Logger::Severe(FILE_LINE fmt, __VA_ARGS__)
diff --git a/include/keymaster/soft_keymaster_context.h b/include/keymaster/soft_keymaster_context.h
index 8f6fe2d..dac376a 100644
--- a/include/keymaster/soft_keymaster_context.h
+++ b/include/keymaster/soft_keymaster_context.h
@@ -18,23 +18,40 @@
#define SYSTEM_KEYMASTER_SOFT_KEYMASTER_CONTEXT_H_
#include <memory>
+#include <string>
#include <openssl/evp.h>
#include <hardware/keymaster0.h>
+#include <hardware/keymaster1.h>
#include <keymaster/keymaster_context.h>
namespace keymaster {
class SoftKeymasterKeyRegistrations;
class Keymaster0Engine;
+class Keymaster1Engine;
/**
* SoftKeymasterContext provides the context for a non-secure implementation of AndroidKeymaster.
*/
class SoftKeymasterContext : public KeymasterContext {
public:
- SoftKeymasterContext(keymaster0_device_t* keymaster0_device);
+ SoftKeymasterContext(const std::string& root_of_trust = "SW");
+ ~SoftKeymasterContext() override;
+
+ /**
+ * Use the specified HW keymaster0 device for the operations it supports. Takes ownership of
+ * the specified device (will call keymaster0_device->common.close());
+ */
+ keymaster_error_t SetHardwareDevice(keymaster0_device_t* keymaster0_device);
+
+ /**
+ * Use the specified HW keymaster1 device for performing undigested RSA and EC operations after
+ * digesting has been done in software. Takes ownership of the specified device (will call
+ * keymaster1_device->common.close());
+ */
+ keymaster_error_t SetHardwareDevice(keymaster1_device_t* keymaster1_device);
KeyFactory* GetKeyFactory(keymaster_algorithm_t algorithm) const override;
OperationFactory* GetOperationFactory(keymaster_algorithm_t algorithm,
@@ -62,14 +79,28 @@ class SoftKeymasterContext : public KeymasterContext {
KeymasterKeyBlob* key_material,
AuthorizationSet* hw_enforced,
AuthorizationSet* sw_enforced) const;
+ keymaster_error_t ParseKeymaster1HwBlob(const KeymasterKeyBlob& blob,
+ const AuthorizationSet& additional_params,
+ KeymasterKeyBlob* key_material,
+ AuthorizationSet* hw_enforced,
+ AuthorizationSet* sw_enforced) const;
+ keymaster_error_t ParseKeymaster0HwBlob(const KeymasterKeyBlob& blob,
+ KeymasterKeyBlob* key_material,
+ AuthorizationSet* hw_enforced,
+ AuthorizationSet* sw_enforced) const;
keymaster_error_t FakeKeyAuthorizations(EVP_PKEY* pubkey, AuthorizationSet* hw_enforced,
AuthorizationSet* sw_enforced) const;
+ keymaster_error_t BuildHiddenAuthorizations(const AuthorizationSet& input_set,
+ AuthorizationSet* hidden) const;
- std::unique_ptr<Keymaster0Engine> engine_;
+ std::unique_ptr<Keymaster0Engine> km0_engine_;
+ std::unique_ptr<Keymaster1Engine> km1_engine_;
std::unique_ptr<KeyFactory> rsa_factory_;
std::unique_ptr<KeyFactory> ec_factory_;
std::unique_ptr<KeyFactory> aes_factory_;
std::unique_ptr<KeyFactory> hmac_factory_;
+ keymaster1_device* km1_dev_;
+ const std::string root_of_trust_;
};
} // namespace keymaster
diff --git a/include/keymaster/soft_keymaster_device.h b/include/keymaster/soft_keymaster_device.h
index 86ad260..5d7b83b 100644
--- a/include/keymaster/soft_keymaster_device.h
+++ b/include/keymaster/soft_keymaster_device.h
@@ -17,14 +17,15 @@
#ifndef SYSTEM_KEYMASTER_SOFT_KEYMASTER_DEVICE_H_
#define SYSTEM_KEYMASTER_SOFT_KEYMASTER_DEVICE_H_
-#include <stdlib.h>
+#include <cstdlib>
+#include <map>
+#include <vector>
#include <hardware/keymaster0.h>
#include <hardware/keymaster1.h>
#include <keymaster/android_keymaster.h>
-#include <keymaster/keymaster_context.h>
-#include <keymaster/logger.h>
+#include <keymaster/soft_keymaster_context.h>
#include <UniquePtr.h>
@@ -45,19 +46,28 @@ class AuthorizationSet;
*/
class SoftKeymasterDevice {
public:
+ SoftKeymasterDevice();
+
+ // Public only for testing.
+ SoftKeymasterDevice(SoftKeymasterContext* context);
+
+ /**
+ * Set SoftKeymasterDevice to wrap the speicified HW keymaster0 device. Takes ownership of the
+ * specified device (will call keymaster0_device->common.close());
+ */
+ keymaster_error_t SetHardwareDevice(keymaster0_device_t* keymaster0_device);
+
/**
- * Create a SoftKeymasterDevice wrapping the specified HW keymaster0 device, which may be NULL.
- *
- * Uses SoftKeymaserContext.
+ * Set SoftKeymasterDevice to wrap specified HW keymaster1 device. Takes ownership of the
+ * specified device (will call keymaster1_device->common.close());
*/
- SoftKeymasterDevice(keymaster0_device_t* keymaster0_device = nullptr);
+ keymaster_error_t SetHardwareDevice(keymaster1_device_t* keymaster1_device);
/**
- * Create a SoftKeymasterDevice that uses the specified KeymasterContext.
- *
- * TODO(swillden): Refactor SoftKeymasterDevice construction to make all components injectable.
+ * Returns true if a keymaster1_device_t has been set as the hardware device, and if that
+ * hardware device should be used directly.
*/
- SoftKeymasterDevice(KeymasterContext* context);
+ bool Keymaster1DeviceIsGood();
hw_device_t* hw_device();
keymaster1_device_t* keymaster_device();
@@ -68,7 +78,13 @@ class SoftKeymasterDevice {
}
private:
- void initialize(keymaster0_device_t* keymaster0_device);
+ void initialize_device_struct();
+ bool FindUnsupportedDigest(keymaster_algorithm_t algorithm, keymaster_purpose_t purpose,
+ const AuthorizationSet& params,
+ keymaster_digest_t* unsupported) const;
+ bool RequiresSoftwareDigesting(keymaster_algorithm_t algorithm, keymaster_purpose_t purpose,
+ const AuthorizationSet& params) const;
+ bool KeyRequiresSoftwareDigesting(const AuthorizationSet& key_description) const;
static void StoreDefaultNewKeyParams(keymaster_algorithm_t algorithm,
AuthorizationSet* auth_set);
@@ -81,28 +97,6 @@ class SoftKeymasterDevice {
* These static methods are the functions referenced through the function pointers in
* keymaster_device.
*/
-
- // keymaster0 APIs
- static int generate_keypair(const keymaster1_device_t* dev, const keymaster_keypair_t key_type,
- const void* key_params, uint8_t** keyBlob, size_t* keyBlobLength);
- static int import_keypair(const struct keymaster1_device* dev, const uint8_t* key,
- const size_t key_length, uint8_t** key_blob, size_t* key_blob_length);
- static int get_keypair_public(const keymaster1_device_t* dev, const uint8_t* key_blob,
- const size_t key_blob_length, uint8_t** x509_data,
- size_t* x509_data_length);
- static int delete_keypair(const struct keymaster1_device* dev, const uint8_t* key_blob,
- const size_t key_blob_length);
- static int delete_all(const struct keymaster1_device* dev);
- static int sign_data(const keymaster1_device_t* dev, const void* signing_params,
- const uint8_t* key_blob, const size_t key_blob_length, const uint8_t* data,
- const size_t data_length, uint8_t** signed_data,
- size_t* signed_data_length);
- static int verify_data(const keymaster1_device_t* dev, const void* signing_params,
- const uint8_t* key_blob, const size_t key_blob_length,
- const uint8_t* signed_data, const size_t signed_data_length,
- const uint8_t* signature, const size_t signature_length);
-
- // keymaster1 APIs.
static keymaster_error_t get_supported_algorithms(const keymaster1_device_t* dev,
keymaster_algorithm_t** algorithms,
size_t* algorithms_length);
@@ -160,20 +154,33 @@ class SoftKeymasterDevice {
const keymaster_key_param_set_t* in_params,
keymaster_key_param_set_t* out_params,
keymaster_operation_handle_t* operation_handle);
- static keymaster_error_t
- update(const keymaster1_device_t* dev, keymaster_operation_handle_t operation_handle,
- const keymaster_key_param_set_t* in_params, const keymaster_blob_t* input,
- size_t* input_consumed, keymaster_key_param_set_t* out_params, keymaster_blob_t* output);
- static keymaster_error_t
- finish(const keymaster1_device_t* dev, keymaster_operation_handle_t operation_handle,
- const keymaster_key_param_set_t* in_params, const keymaster_blob_t* signature,
- keymaster_key_param_set_t* out_params, keymaster_blob_t* output);
+ static keymaster_error_t update(const keymaster1_device_t* dev, //
+ keymaster_operation_handle_t operation_handle,
+ const keymaster_key_param_set_t* in_params,
+ const keymaster_blob_t* input, size_t* input_consumed,
+ keymaster_key_param_set_t* out_params,
+ keymaster_blob_t* output);
+ static keymaster_error_t finish(const keymaster1_device_t* dev, //
+ keymaster_operation_handle_t operation_handle,
+ const keymaster_key_param_set_t* in_params,
+ const keymaster_blob_t* signature,
+ keymaster_key_param_set_t* out_params,
+ keymaster_blob_t* output);
+
static keymaster_error_t abort(const keymaster1_device_t* dev,
keymaster_operation_handle_t operation_handle);
+ typedef std::map<std::pair<keymaster_algorithm_t, keymaster_purpose_t>,
+ std::vector<keymaster_digest_t>> DigestMap;
+
keymaster1_device_t device_;
- keymaster0_device_t* wrapped_device_;
+ keymaster0_device_t* wrapped_km0_device_;
+ keymaster1_device_t* wrapped_km1_device_;
+ DigestMap km1_device_digests_;
+ SoftKeymasterContext* context_;
UniquePtr<AndroidKeymaster> impl_;
+ std::string module_name_;
+ hw_module_t updated_module_;
};
} // namespace keymaster
diff --git a/key.h b/key.h
index ca0ceb9..959729e 100644
--- a/key.h
+++ b/key.h
@@ -29,11 +29,6 @@ class Key {
virtual ~Key() {}
/**
- * Return a copy of raw key material, in the key's preferred binary format.
- */
- virtual keymaster_error_t key_material(UniquePtr<uint8_t[]>*, size_t* size) const = 0;
-
- /**
* Return a copy of raw key material, in the specified format.
*/
virtual keymaster_error_t formatted_key_material(keymaster_key_format_t format,
diff --git a/keymaster0_engine.cpp b/keymaster0_engine.cpp
index d7ad709..995bc0b 100644
--- a/keymaster0_engine.cpp
+++ b/keymaster0_engine.cpp
@@ -36,52 +36,7 @@ using std::unique_ptr;
namespace keymaster {
-// int Keymaster0Engine::rsa_index_ = -1;
-// int Keymaster0Engine::ec_key_index_ = -1;
Keymaster0Engine* Keymaster0Engine::instance_ = nullptr;
-const RSA_METHOD Keymaster0Engine::rsa_method_ = {
- .common =
- {
- 0, // references
- 1 // is_static
- },
- .app_data = nullptr,
- .init = nullptr,
- .finish = nullptr,
- .size = nullptr,
- .sign = nullptr,
- .verify = nullptr,
-
- .encrypt = nullptr,
- .sign_raw = nullptr,
- .decrypt = nullptr,
- .verify_raw = nullptr,
-
- .private_transform = Keymaster0Engine::rsa_private_transform,
-
- .mod_exp = nullptr,
- .bn_mod_exp = BN_mod_exp_mont,
-
- .flags = RSA_FLAG_OPAQUE,
-
- .keygen = nullptr,
- .supports_digest = nullptr,
-};
-
-const ECDSA_METHOD Keymaster0Engine::ecdsa_method_ = {
- .common =
- {
- 0, // references
- 1 // is_static
- },
- .app_data = nullptr,
- .init = nullptr,
- .finish = nullptr,
- .group_order_size = nullptr,
- .sign = Keymaster0Engine::ecdsa_sign,
- .verify = nullptr,
- .flags = ECDSA_FLAG_OPAQUE,
-};
Keymaster0Engine::Keymaster0Engine(const keymaster0_device_t* keymaster0_device)
: keymaster0_device_(keymaster0_device), engine_(ENGINE_new()), supports_ec_(false) {
@@ -93,10 +48,40 @@ Keymaster0Engine::Keymaster0Engine(const keymaster0_device_t* keymaster0_device)
ec_key_index_ = EC_KEY_get_ex_new_index(0 /* argl */, NULL /* argp */, NULL /* new_func */,
keyblob_dup, keyblob_free);
+ rsa_method_.common.references = 0;
+ rsa_method_.common.is_static = 1;
+ rsa_method_.app_data = nullptr;
+ rsa_method_.init = nullptr;
+ rsa_method_.finish = nullptr;
+ rsa_method_.size = nullptr;
+ rsa_method_.sign = nullptr;
+ rsa_method_.verify = nullptr;
+ rsa_method_.encrypt = nullptr;
+ rsa_method_.sign_raw = nullptr;
+ rsa_method_.decrypt = nullptr;
+ rsa_method_.verify_raw = nullptr;
+ rsa_method_.private_transform = Keymaster0Engine::rsa_private_transform;
+ rsa_method_.mod_exp = nullptr;
+ rsa_method_.bn_mod_exp = BN_mod_exp_mont;
+ rsa_method_.flags = RSA_FLAG_OPAQUE;
+ rsa_method_.keygen = nullptr;
+ rsa_method_.supports_digest = nullptr;
+
ENGINE_set_RSA_method(engine_, &rsa_method_, sizeof(rsa_method_));
if ((keymaster0_device_->flags & KEYMASTER_SUPPORTS_EC) != 0) {
supports_ec_ = true;
+
+ ecdsa_method_.common.references = 0;
+ ecdsa_method_.common.is_static = 1;
+ ecdsa_method_.app_data = nullptr;
+ ecdsa_method_.init = nullptr;
+ ecdsa_method_.finish = nullptr;
+ ecdsa_method_.group_order_size = nullptr;
+ ecdsa_method_.sign = Keymaster0Engine::ecdsa_sign;
+ ecdsa_method_.verify = nullptr;
+ ecdsa_method_.flags = ECDSA_FLAG_OPAQUE;
+
ENGINE_set_ECDSA_method(engine_, &ecdsa_method_, sizeof(ecdsa_method_));
}
}
@@ -346,17 +331,6 @@ int Keymaster0Engine::RsaPrivateTransform(RSA* rsa, uint8_t* out, const uint8_t*
return 1;
}
-static size_t ec_group_size_bits(EC_KEY* ec_key) {
- const EC_GROUP* group = EC_KEY_get0_group(ec_key);
- unique_ptr<BN_CTX, BN_CTX_Delete> bn_ctx(BN_CTX_new());
- unique_ptr<BIGNUM, BIGNUM_Delete> order(BN_new());
- if (!EC_GROUP_get_order(group, order.get(), bn_ctx.get())) {
- ALOGE("Failed to get EC group order");
- return 0;
- }
- return BN_num_bits(order.get());
-}
-
int Keymaster0Engine::EcdsaSign(const uint8_t* digest, size_t digest_len, uint8_t* sig,
unsigned int* sig_len, EC_KEY* ec_key) const {
const keymaster_key_blob_t* key_blob = EcKeyToBlob(ec_key);
diff --git a/keymaster0_engine.h b/keymaster0_engine.h
index 90aec93..71f550b 100644
--- a/keymaster0_engine.h
+++ b/keymaster0_engine.h
@@ -31,7 +31,7 @@ namespace keymaster {
struct KeymasterKeyBlob;
-/* Keymaster0Engine is a BoringSSL ENGINE that implements RSA by forwarding the requested
+/* Keymaster0Engine is a BoringSSL ENGINE that implements RSA & EC by forwarding the requested
* operations to a keymaster0 module. */
class Keymaster0Engine {
public:
@@ -57,6 +57,8 @@ class Keymaster0Engine {
const keymaster_key_blob_t* RsaKeyToBlob(const RSA* rsa) const;
const keymaster_key_blob_t* EcKeyToBlob(const EC_KEY* rsa) const;
+ const keymaster0_device_t* device() { return keymaster0_device_; }
+
EVP_PKEY* GetKeymaster0PublicKey(const KeymasterKeyBlob& blob) const;
private:
@@ -88,9 +90,9 @@ class Keymaster0Engine {
ENGINE* const engine_;
int rsa_index_, ec_key_index_;
bool supports_ec_;
+ RSA_METHOD rsa_method_;
+ ECDSA_METHOD ecdsa_method_;
- static const RSA_METHOD rsa_method_;
- static const ECDSA_METHOD ecdsa_method_;
static Keymaster0Engine* instance_;
};
diff --git a/keymaster1_engine.cpp b/keymaster1_engine.cpp
new file mode 100644
index 0000000..866a255
--- /dev/null
+++ b/keymaster1_engine.cpp
@@ -0,0 +1,415 @@
+/*
+ * 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 "keymaster1_engine.h"
+
+#include <assert.h>
+
+#include <algorithm>
+#include <memory>
+
+#define LOG_TAG "Keymaster1Engine"
+#include <cutils/log.h>
+
+#include "keymaster/android_keymaster_utils.h"
+
+#include <openssl/bn.h>
+#include <openssl/ec_key.h>
+#include <openssl/ecdsa.h>
+
+#include "openssl_err.h"
+#include "openssl_utils.h"
+
+using std::shared_ptr;
+using std::unique_ptr;
+
+namespace keymaster {
+
+Keymaster1Engine* Keymaster1Engine::instance_ = nullptr;
+
+Keymaster1Engine::Keymaster1Engine(const keymaster1_device_t* keymaster1_device)
+ : keymaster1_device_(keymaster1_device), engine_(ENGINE_new()),
+ rsa_index_(RSA_get_ex_new_index(0 /* argl */, NULL /* argp */, NULL /* new_func */,
+ Keymaster1Engine::duplicate_key_data,
+ Keymaster1Engine::free_key_data)),
+ ec_key_index_(EC_KEY_get_ex_new_index(0 /* argl */, NULL /* argp */, NULL /* new_func */,
+ Keymaster1Engine::duplicate_key_data,
+ Keymaster1Engine::free_key_data)),
+ rsa_method_(BuildRsaMethod()), ecdsa_method_(BuildEcdsaMethod()) {
+ assert(rsa_index_ != -1);
+ assert(ec_key_index_ != -1);
+ assert(keymaster1_device);
+ assert(!instance_);
+
+ instance_ = this;
+
+ ENGINE_set_RSA_method(engine_.get(), &rsa_method_, sizeof(rsa_method_));
+ ENGINE_set_ECDSA_method(engine_.get(), &ecdsa_method_, sizeof(ecdsa_method_));
+}
+
+Keymaster1Engine::~Keymaster1Engine() {
+ keymaster1_device_->common.close(
+ reinterpret_cast<hw_device_t*>(const_cast<keymaster1_device_t*>(keymaster1_device_)));
+ instance_ = nullptr;
+}
+
+static void ConvertCharacteristics(keymaster_key_characteristics_t* characteristics,
+ AuthorizationSet* hw_enforced, AuthorizationSet* sw_enforced) {
+ unique_ptr<keymaster_key_characteristics_t, Characteristics_Delete> characteristics_deleter(
+ characteristics);
+ if (hw_enforced)
+ hw_enforced->Reinitialize(characteristics->hw_enforced);
+ if (sw_enforced)
+ sw_enforced->Reinitialize(characteristics->sw_enforced);
+}
+
+keymaster_error_t Keymaster1Engine::GenerateKey(const AuthorizationSet& key_description,
+ KeymasterKeyBlob* key_blob,
+ AuthorizationSet* hw_enforced,
+ AuthorizationSet* sw_enforced) const {
+ assert(key_blob);
+
+ keymaster_key_characteristics_t* characteristics;
+ keymaster_key_blob_t blob;
+ keymaster_error_t error = keymaster1_device_->generate_key(keymaster1_device_, &key_description,
+ &blob, &characteristics);
+ if (error != KM_ERROR_OK)
+ return error;
+ unique_ptr<uint8_t, Malloc_Delete> blob_deleter(const_cast<uint8_t*>(blob.key_material));
+ key_blob->key_material = dup_buffer(blob.key_material, blob.key_material_size);
+ key_blob->key_material_size = blob.key_material_size;
+
+ ConvertCharacteristics(characteristics, hw_enforced, sw_enforced);
+ return error;
+}
+
+keymaster_error_t Keymaster1Engine::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 {
+ assert(output_key_blob);
+
+ keymaster_key_characteristics_t* characteristics;
+ const keymaster_blob_t input_key = {input_key_material.key_material,
+ input_key_material.key_material_size};
+ keymaster_key_blob_t blob;
+ keymaster_error_t error = keymaster1_device_->import_key(keymaster1_device_, &key_description,
+ input_key_material_format, &input_key,
+ &blob, &characteristics);
+ if (error != KM_ERROR_OK)
+ return error;
+ unique_ptr<uint8_t, Malloc_Delete> blob_deleter(const_cast<uint8_t*>(blob.key_material));
+ output_key_blob->key_material = dup_buffer(blob.key_material, blob.key_material_size);
+ output_key_blob->key_material_size = blob.key_material_size;
+
+ ConvertCharacteristics(characteristics, hw_enforced, sw_enforced);
+ return error;
+}
+
+RSA* Keymaster1Engine::BuildRsaKey(const KeymasterKeyBlob& blob,
+ const AuthorizationSet& additional_params,
+ keymaster_error_t* error) const {
+ // Create new RSA key (with engine methods) and add metadata
+ unique_ptr<RSA, RSA_Delete> rsa(RSA_new_method(engine_.get()));
+ if (!rsa) {
+ *error = TranslateLastOpenSslError();
+ return nullptr;
+ }
+
+ KeyData* key_data = new KeyData(blob, additional_params);
+ if (!RSA_set_ex_data(rsa.get(), rsa_index_, key_data)) {
+ *error = TranslateLastOpenSslError();
+ delete key_data;
+ return nullptr;
+ }
+
+ // Copy public key into new RSA key
+ unique_ptr<EVP_PKEY, EVP_PKEY_Delete> pkey(
+ GetKeymaster1PublicKey(key_data->key_material, key_data->begin_params, error));
+ if (!pkey) {
+ *error = TranslateLastOpenSslError();
+ return nullptr;
+ }
+
+ unique_ptr<RSA, RSA_Delete> public_rsa(EVP_PKEY_get1_RSA(pkey.get()));
+ if (!public_rsa) {
+ *error = TranslateLastOpenSslError();
+ return nullptr;
+ }
+
+ rsa->n = BN_dup(public_rsa->n);
+ rsa->e = BN_dup(public_rsa->e);
+ if (!rsa->n || !rsa->e) {
+ *error = TranslateLastOpenSslError();
+ return nullptr;
+ }
+
+ *error = KM_ERROR_OK;
+ return rsa.release();
+}
+
+EC_KEY* Keymaster1Engine::BuildEcKey(const KeymasterKeyBlob& blob,
+ const AuthorizationSet& additional_params,
+ keymaster_error_t* error) const {
+ // Create new EC key (with engine methods) and insert blob
+ unique_ptr<EC_KEY, EC_Delete> ec_key(EC_KEY_new_method(engine_.get()));
+ if (!ec_key) {
+ *error = TranslateLastOpenSslError();
+ return nullptr;
+ }
+
+ KeyData* key_data = new KeyData(blob, additional_params);
+ if (!EC_KEY_set_ex_data(ec_key.get(), ec_key_index_, key_data)) {
+ *error = TranslateLastOpenSslError();
+ delete key_data;
+ return nullptr;
+ }
+
+ // Copy public key into new EC key
+ unique_ptr<EVP_PKEY, EVP_PKEY_Delete> pkey(
+ GetKeymaster1PublicKey(blob, additional_params, error));
+ if (!pkey) {
+ *error = TranslateLastOpenSslError();
+ return nullptr;
+ }
+
+ unique_ptr<EC_KEY, EC_Delete> public_ec_key(EVP_PKEY_get1_EC_KEY(pkey.get()));
+ if (!public_ec_key) {
+ *error = TranslateLastOpenSslError();
+ return nullptr;
+ }
+
+ if (!EC_KEY_set_group(ec_key.get(), EC_KEY_get0_group(public_ec_key.get())) ||
+ !EC_KEY_set_public_key(ec_key.get(), EC_KEY_get0_public_key(public_ec_key.get()))) {
+ *error = TranslateLastOpenSslError();
+ return nullptr;
+ }
+
+ *error = KM_ERROR_OK;
+ return ec_key.release();
+}
+
+Keymaster1Engine::KeyData* Keymaster1Engine::GetData(EVP_PKEY* key) const {
+ switch (EVP_PKEY_type(key->type)) {
+ case EVP_PKEY_RSA: {
+ unique_ptr<RSA, RSA_Delete> rsa(EVP_PKEY_get1_RSA(key));
+ return GetData(rsa.get());
+ }
+
+ case EVP_PKEY_EC: {
+ unique_ptr<EC_KEY, EC_Delete> ec_key(EVP_PKEY_get1_EC_KEY(key));
+ return GetData(ec_key.get());
+ }
+
+ default:
+ return nullptr;
+ };
+}
+
+Keymaster1Engine::KeyData* Keymaster1Engine::GetData(const RSA* rsa) const {
+ if (!rsa)
+ return nullptr;
+ return reinterpret_cast<KeyData*>(RSA_get_ex_data(rsa, rsa_index_));
+}
+
+Keymaster1Engine::KeyData* Keymaster1Engine::GetData(const EC_KEY* ec_key) const {
+ if (!ec_key)
+ return nullptr;
+ return reinterpret_cast<KeyData*>(EC_KEY_get_ex_data(ec_key, ec_key_index_));
+}
+
+/* static */
+int Keymaster1Engine::duplicate_key_data(CRYPTO_EX_DATA* /* to */, const CRYPTO_EX_DATA* /* from */,
+ void** from_d, int /* index */, long /* argl */,
+ void* /* argp */) {
+ KeyData* data = reinterpret_cast<KeyData*>(*from_d);
+ if (!data)
+ return 1;
+
+ // Default copy ctor is good.
+ *from_d = new KeyData(*data);
+ if (*from_d)
+ return 1;
+ return 0;
+}
+
+/* static */
+void Keymaster1Engine::free_key_data(void* /* parent */, void* ptr, CRYPTO_EX_DATA* /* data */,
+ int /* index*/, long /* argl */, void* /* argp */) {
+ delete reinterpret_cast<KeyData*>(ptr);
+}
+
+keymaster_error_t Keymaster1Engine::Keymaster1Finish(const KeyData* key_data,
+ const keymaster_blob_t& input,
+ keymaster_blob_t* output) {
+ if (key_data->op_handle == 0)
+ return KM_ERROR_UNKNOWN_ERROR;
+
+ size_t input_consumed;
+ // Note: devices are required to consume all input in a single update call for undigested
+ // signing operations and encryption operations. No need to loop here.
+ keymaster_error_t error =
+ device()->update(device(), key_data->op_handle, &key_data->finish_params, &input,
+ &input_consumed, nullptr /* out_params */, nullptr /* output */);
+ if (error != KM_ERROR_OK)
+ return error;
+
+ return device()->finish(device(), key_data->op_handle, &key_data->finish_params,
+ nullptr /* signature */, nullptr /* out_params */, output);
+}
+
+/* static */
+int Keymaster1Engine::rsa_sign_raw(RSA* rsa, size_t* out_len, uint8_t* out, size_t max_out,
+ const uint8_t* in, size_t in_len, int padding) {
+ KeyData* key_data = instance_->GetData(rsa);
+ if (!key_data)
+ return 0;
+
+ if (padding != key_data->expected_openssl_padding) {
+ LOG_E("Expected sign_raw with padding %d but got padding %d",
+ key_data->expected_openssl_padding, padding);
+ return KM_ERROR_UNKNOWN_ERROR;
+ }
+
+ keymaster_blob_t input = {in, in_len};
+ keymaster_blob_t output;
+ key_data->error = instance_->Keymaster1Finish(key_data, input, &output);
+ if (key_data->error != KM_ERROR_OK)
+ return 0;
+ unique_ptr<uint8_t, Malloc_Delete> output_deleter(const_cast<uint8_t*>(output.data));
+
+ *out_len = std::min(output.data_length, max_out);
+ memcpy(out, output.data, *out_len);
+ return 1;
+}
+
+/* static */
+int Keymaster1Engine::rsa_decrypt(RSA* rsa, size_t* out_len, uint8_t* out, size_t max_out,
+ const uint8_t* in, size_t in_len, int padding) {
+ KeyData* key_data = instance_->GetData(rsa);
+ if (!key_data)
+ return 0;
+
+ if (padding != key_data->expected_openssl_padding) {
+ LOG_E("Expected sign_raw with padding %d but got padding %d",
+ key_data->expected_openssl_padding, padding);
+ return KM_ERROR_UNKNOWN_ERROR;
+ }
+
+ keymaster_blob_t input = {in, in_len};
+ keymaster_blob_t output;
+ key_data->error = instance_->Keymaster1Finish(key_data, input, &output);
+ if (key_data->error != KM_ERROR_OK)
+ return 0;
+ unique_ptr<uint8_t, Malloc_Delete> output_deleter(const_cast<uint8_t*>(output.data));
+
+ *out_len = std::min(output.data_length, max_out);
+ memcpy(out, output.data, *out_len);
+ return 1;
+}
+
+/* static */
+int Keymaster1Engine::ecdsa_sign(const uint8_t* digest, size_t digest_len, uint8_t* sig,
+ unsigned int* sig_len, EC_KEY* ec_key) {
+ KeyData* key_data = instance_->GetData(ec_key);
+ if (!key_data)
+ return 0;
+
+ // Truncate digest if it's too long
+ size_t max_input_len = (ec_group_size_bits(ec_key) + 7) / 8;
+ if (digest_len > max_input_len)
+ digest_len = max_input_len;
+
+ keymaster_blob_t input = {digest, digest_len};
+ keymaster_blob_t output;
+ key_data->error = instance_->Keymaster1Finish(key_data, input, &output);
+ if (key_data->error != KM_ERROR_OK)
+ return 0;
+ unique_ptr<uint8_t, Malloc_Delete> output_deleter(const_cast<uint8_t*>(output.data));
+
+ *sig_len = std::min(output.data_length, ECDSA_size(ec_key));
+ memcpy(sig, output.data, *sig_len);
+ return 1;
+}
+
+EVP_PKEY* Keymaster1Engine::GetKeymaster1PublicKey(const KeymasterKeyBlob& blob,
+ const AuthorizationSet& additional_params,
+ keymaster_error_t* error) const {
+ keymaster_blob_t client_id = {nullptr, 0};
+ keymaster_blob_t app_data = {nullptr, 0};
+ keymaster_blob_t* client_id_ptr = nullptr;
+ keymaster_blob_t* app_data_ptr = nullptr;
+ if (additional_params.GetTagValue(TAG_APPLICATION_ID, &client_id))
+ client_id_ptr = &client_id;
+ if (additional_params.GetTagValue(TAG_APPLICATION_DATA, &app_data))
+ app_data_ptr = &app_data;
+
+ keymaster_blob_t export_data = {nullptr, 0};
+ *error = keymaster1_device_->export_key(keymaster1_device_, KM_KEY_FORMAT_X509, &blob,
+ client_id_ptr, app_data_ptr, &export_data);
+ if (*error != KM_ERROR_OK)
+ return nullptr;
+
+ unique_ptr<uint8_t, Malloc_Delete> pub_key(const_cast<uint8_t*>(export_data.data));
+
+ const uint8_t* p = export_data.data;
+ return d2i_PUBKEY(nullptr /* allocate new struct */, &p, export_data.data_length);
+}
+
+RSA_METHOD Keymaster1Engine::BuildRsaMethod() {
+ RSA_METHOD method;
+
+ method.common.references = 0;
+ method.common.is_static = 1;
+ method.app_data = nullptr;
+ method.init = nullptr;
+ method.finish = nullptr;
+ method.size = nullptr;
+ method.sign = nullptr;
+ method.verify = nullptr;
+ method.encrypt = nullptr;
+ method.sign_raw = Keymaster1Engine::rsa_sign_raw;
+ method.decrypt = Keymaster1Engine::rsa_decrypt;
+ method.verify_raw = nullptr;
+ method.private_transform = nullptr;
+ method.mod_exp = nullptr;
+ method.bn_mod_exp = BN_mod_exp_mont;
+ method.flags = RSA_FLAG_OPAQUE;
+ method.keygen = nullptr;
+ method.supports_digest = nullptr;
+
+ return method;
+}
+
+ECDSA_METHOD Keymaster1Engine::BuildEcdsaMethod() {
+ ECDSA_METHOD method;
+
+ method.common.references = 0;
+ method.common.is_static = 1;
+ method.app_data = nullptr;
+ method.init = nullptr;
+ method.finish = nullptr;
+ method.group_order_size = nullptr;
+ method.sign = Keymaster1Engine::ecdsa_sign;
+ method.verify = nullptr;
+ method.flags = ECDSA_FLAG_OPAQUE;
+
+ return method;
+}
+
+} // namespace keymaster
diff --git a/keymaster1_engine.h b/keymaster1_engine.h
new file mode 100644
index 0000000..9d696df
--- /dev/null
+++ b/keymaster1_engine.h
@@ -0,0 +1,121 @@
+/*
+ * 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.
+ */
+
+#ifndef SYSTEM_KEYMASTER_KEYMASTER1_ENGINE_H_
+#define SYSTEM_KEYMASTER_KEYMASTER1_ENGINE_H_
+
+#include <memory>
+
+#include <openssl/ec.h>
+#include <openssl/engine.h>
+#include <openssl/ex_data.h>
+#include <openssl/rsa.h>
+
+#include <hardware/keymaster1.h>
+#include <hardware/keymaster_defs.h>
+
+#include <keymaster/android_keymaster_utils.h>
+#include <keymaster/authorization_set.h>
+
+#include "openssl_utils.h"
+
+namespace keymaster {
+
+class Keymaster1Engine {
+ public:
+ /**
+ * Create a Keymaster1Engine, wrapping the provided keymaster1_device. The engine takes
+ * ownership of the device, and will close it during destruction.
+ */
+ Keymaster1Engine(const keymaster1_device_t* keymaster1_device);
+ ~Keymaster1Engine();
+
+ keymaster_error_t GenerateKey(const AuthorizationSet& key_description,
+ KeymasterKeyBlob* key_material, AuthorizationSet* hw_enforced,
+ AuthorizationSet* sw_enforced) const;
+
+ keymaster_error_t 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;
+
+ struct KeyData {
+ KeyData(const KeymasterKeyBlob& blob, const AuthorizationSet& params)
+ : op_handle(0), begin_params(params), key_material(blob), error(KM_ERROR_OK),
+ expected_openssl_padding(-1) {}
+
+ keymaster_operation_handle_t op_handle;
+ AuthorizationSet begin_params;
+ AuthorizationSet finish_params;
+ KeymasterKeyBlob key_material;
+ keymaster_error_t error;
+ int expected_openssl_padding;
+ };
+
+ RSA* BuildRsaKey(const KeymasterKeyBlob& blob, const AuthorizationSet& additional_params,
+ keymaster_error_t* error) const;
+ EC_KEY* BuildEcKey(const KeymasterKeyBlob& blob, const AuthorizationSet& additional_params,
+ keymaster_error_t* error) const;
+
+ KeyData* GetData(EVP_PKEY* key) const;
+ KeyData* GetData(const RSA* rsa) const;
+ KeyData* GetData(const EC_KEY* rsa) const;
+
+ const keymaster1_device_t* device() const { return keymaster1_device_; }
+
+ EVP_PKEY* GetKeymaster1PublicKey(const KeymasterKeyBlob& blob,
+ const AuthorizationSet& additional_params,
+ keymaster_error_t* error) const;
+
+ private:
+ Keymaster1Engine(const Keymaster1Engine&); // Uncopyable
+ void operator=(const Keymaster1Engine&); // Unassignable
+
+ RSA_METHOD BuildRsaMethod();
+ ECDSA_METHOD BuildEcdsaMethod();
+ void ConfigureEngineForRsa();
+ void ConfigureEngineForEcdsa();
+
+ keymaster_error_t Keymaster1Finish(const KeyData* key_data, const keymaster_blob_t& input,
+ keymaster_blob_t* output);
+
+ static int duplicate_key_data(CRYPTO_EX_DATA* to, const CRYPTO_EX_DATA* from, void** from_d,
+ int index, long argl, void* argp);
+ static void free_key_data(void* parent, void* ptr, CRYPTO_EX_DATA* data, int index, long argl,
+ void* argp);
+
+ static int rsa_sign_raw(RSA* rsa, size_t* out_len, uint8_t* out, size_t max_out,
+ const uint8_t* in, size_t in_len, int padding);
+ static int rsa_decrypt(RSA* rsa, size_t* out_len, uint8_t* out, size_t max_out,
+ const uint8_t* in, size_t in_len, int padding);
+ static int ecdsa_sign(const uint8_t* digest, size_t digest_len, uint8_t* sig,
+ unsigned int* sig_len, EC_KEY* ec_key);
+
+ const keymaster1_device_t* const keymaster1_device_;
+ const std::unique_ptr<ENGINE, ENGINE_Delete> engine_;
+ const int rsa_index_;
+ const int ec_key_index_;
+
+ const RSA_METHOD rsa_method_;
+ const ECDSA_METHOD ecdsa_method_;
+
+ static Keymaster1Engine* instance_;
+};
+
+} // namespace keymaster
+
+#endif // SYSTEM_KEYMASTER_KEYMASTER1_ENGINE_H_
diff --git a/openssl_utils.cpp b/openssl_utils.cpp
index 3d29c86..1e25ca5 100644
--- a/openssl_utils.cpp
+++ b/openssl_utils.cpp
@@ -82,4 +82,15 @@ keymaster_error_t EvpKeyToKeyMaterial(const EVP_PKEY* pkey, KeymasterKeyBlob* ke
return KM_ERROR_OK;
}
+size_t ec_group_size_bits(EC_KEY* ec_key) {
+ const EC_GROUP* group = EC_KEY_get0_group(ec_key);
+ UniquePtr<BN_CTX, BN_CTX_Delete> bn_ctx(BN_CTX_new());
+ UniquePtr<BIGNUM, BIGNUM_Delete> order(BN_new());
+ if (!EC_GROUP_get_order(group, order.get(), bn_ctx.get())) {
+ LOG_E("Failed to get EC group order", 0);
+ return 0;
+ }
+ return BN_num_bits(order.get());
+}
+
} // namespace keymaster
diff --git a/openssl_utils.h b/openssl_utils.h
index 97c2b5a..a66ef43 100644
--- a/openssl_utils.h
+++ b/openssl_utils.h
@@ -20,6 +20,7 @@
#include <openssl/bn.h>
#include <openssl/evp.h>
#include <openssl/ec.h>
+#include <openssl/engine.h>
#include <openssl/rsa.h>
#include <openssl/x509.h>
@@ -59,6 +60,10 @@ struct EC_Delete {
void operator()(EC_KEY* p) { EC_KEY_free(p); }
};
+struct ENGINE_Delete {
+ void operator()(ENGINE* p) { ENGINE_free(p); }
+};
+
/**
* Many OpenSSL APIs take ownership of an argument on success but don't free the argument on
* failure. This means we need to tell our scoped pointers when we've transferred ownership, without
@@ -80,6 +85,8 @@ keymaster_error_t KeyMaterialToEvpKey(keymaster_key_format_t key_format,
keymaster_error_t EvpKeyToKeyMaterial(const EVP_PKEY* evp_pkey, KeymasterKeyBlob* key_blob);
+size_t ec_group_size_bits(EC_KEY* ec_key);
+
} // namespace keymaster
#endif // SYSTEM_KEYMASTER_OPENSSL_UTILS_H_
diff --git a/rsa_keymaster0_key.cpp b/rsa_keymaster0_key.cpp
index 3afd024..8df05ae 100644
--- a/rsa_keymaster0_key.cpp
+++ b/rsa_keymaster0_key.cpp
@@ -18,9 +18,6 @@
#include <memory>
-#define LOG_TAG "RsaKeymaster0Key"
-#include <cutils/log.h>
-
#include <keymaster/android_keymaster_utils.h>
#include <keymaster/logger.h>
#include <keymaster/soft_keymaster_context.h>
@@ -34,7 +31,7 @@ namespace keymaster {
RsaKeymaster0KeyFactory::RsaKeymaster0KeyFactory(const SoftKeymasterContext* context,
const Keymaster0Engine* engine)
- : RsaKeyFactory(context), engine_(engine), soft_context_(context) {}
+ : RsaKeyFactory(context), engine_(engine) {}
keymaster_error_t RsaKeymaster0KeyFactory::GenerateKey(const AuthorizationSet& key_description,
KeymasterKeyBlob* key_blob,
@@ -43,9 +40,6 @@ keymaster_error_t RsaKeymaster0KeyFactory::GenerateKey(const AuthorizationSet& k
if (!key_blob || !hw_enforced || !sw_enforced)
return KM_ERROR_OUTPUT_PARAMETER_NULL;
- if (!engine_)
- return super::GenerateKey(key_description, key_blob, hw_enforced, sw_enforced);
-
uint64_t public_exponent;
if (!key_description.GetTagValue(TAG_RSA_PUBLIC_EXPONENT, &public_exponent)) {
LOG_E("%s", "No public exponent specified for RSA key generation");
@@ -80,10 +74,6 @@ keymaster_error_t RsaKeymaster0KeyFactory::ImportKey(
if (!output_key_blob || !hw_enforced || !sw_enforced)
return KM_ERROR_OUTPUT_PARAMETER_NULL;
- if (!engine_)
- return super::ImportKey(key_description, input_key_material_format, input_key_material,
- output_key_blob, hw_enforced, sw_enforced);
-
AuthorizationSet authorizations;
uint64_t public_exponent;
uint32_t key_size;
@@ -109,6 +99,7 @@ keymaster_error_t RsaKeymaster0KeyFactory::ImportKey(
}
keymaster_error_t RsaKeymaster0KeyFactory::LoadKey(const KeymasterKeyBlob& key_material,
+ const AuthorizationSet& additional_params,
const AuthorizationSet& hw_enforced,
const AuthorizationSet& sw_enforced,
UniquePtr<Key>* key) const {
@@ -116,7 +107,7 @@ keymaster_error_t RsaKeymaster0KeyFactory::LoadKey(const KeymasterKeyBlob& key_m
return KM_ERROR_OUTPUT_PARAMETER_NULL;
if (sw_enforced.GetTagCount(TAG_ALGORITHM) == 1)
- return super::LoadKey(key_material, hw_enforced, sw_enforced, key);
+ return super::LoadKey(key_material, additional_params, hw_enforced, sw_enforced, key);
unique_ptr<RSA, RSA_Delete> rsa(engine_->BlobToRsaKey(key_material));
if (!rsa)
@@ -139,20 +130,4 @@ RsaKeymaster0Key::RsaKeymaster0Key(RSA* rsa_key, const AuthorizationSet& hw_enfo
const Keymaster0Engine* engine, keymaster_error_t* error)
: RsaKey(rsa_key, hw_enforced, sw_enforced, error), engine_(engine) {}
-keymaster_error_t RsaKeymaster0Key::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_->RsaKeyToBlob(key());
- if (!blob)
- return KM_ERROR_UNKNOWN_ERROR;
-
- *size = blob->key_material_size;
- material->reset(dup_buffer(blob->key_material, *size));
- if (!material->get())
- return KM_ERROR_MEMORY_ALLOCATION_FAILED;
- return KM_ERROR_OK;
-}
-
} // namespace keymaster
diff --git a/rsa_keymaster0_key.h b/rsa_keymaster0_key.h
index 2090d04..9fd9fac 100644
--- a/rsa_keymaster0_key.h
+++ b/rsa_keymaster0_key.h
@@ -49,13 +49,13 @@ class RsaKeymaster0KeyFactory : public RsaKeyFactory {
AuthorizationSet* sw_enforced) const override;
keymaster_error_t LoadKey(const KeymasterKeyBlob& key_material,
+ const AuthorizationSet& additional_params,
const AuthorizationSet& hw_enforced,
const AuthorizationSet& sw_enforced,
UniquePtr<Key>* key) const override;
private:
const Keymaster0Engine* engine_;
- const SoftKeymasterContext* soft_context_;
};
class RsaKeymaster0Key : public RsaKey {
@@ -66,8 +66,6 @@ class RsaKeymaster0Key : public RsaKey {
const AuthorizationSet& sw_enforced, const Keymaster0Engine* engine,
keymaster_error_t* error);
- keymaster_error_t key_material(UniquePtr<uint8_t[]>* material, size_t* size) const override;
-
private:
const Keymaster0Engine* engine_;
};
diff --git a/rsa_keymaster1_key.cpp b/rsa_keymaster1_key.cpp
new file mode 100644
index 0000000..94f3cab
--- /dev/null
+++ b/rsa_keymaster1_key.cpp
@@ -0,0 +1,147 @@
+/*
+ * 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 "rsa_keymaster1_key.h"
+
+#include <memory>
+
+#include <keymaster/logger.h>
+#include <keymaster/soft_keymaster_context.h>
+
+#include "rsa_keymaster1_operation.h"
+
+using std::unique_ptr;
+
+namespace keymaster {
+
+RsaKeymaster1KeyFactory::RsaKeymaster1KeyFactory(const SoftKeymasterContext* context,
+ const Keymaster1Engine* engine)
+ : RsaKeyFactory(context), engine_(engine),
+ sign_factory_(new RsaKeymaster1OperationFactory(KM_PURPOSE_SIGN, engine)),
+ decrypt_factory_(new RsaKeymaster1OperationFactory(KM_PURPOSE_DECRYPT, engine)),
+ // For pubkey ops we can use the normal operation factories.
+ verify_factory_(new RsaVerificationOperationFactory),
+ encrypt_factory_(new RsaEncryptionOperationFactory) {}
+
+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;
+ bool have_pad_none = false;
+ bool have_padding_requiring_digest = 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 (entry.tag == TAG_PADDING) {
+ switch (entry.enumerated) {
+ case KM_PAD_RSA_PSS:
+ case KM_PAD_RSA_OAEP:
+ have_padding_requiring_digest = true;
+ break;
+ case KM_PAD_NONE:
+ have_pad_none = true;
+ break;
+ }
+ }
+ }
+
+ 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);
+ }
+
+ if (have_unsupported_digests && have_padding_requiring_digest && !have_pad_none) {
+ LOG_I("Adding KM_PAD_NONE to key authorization, to enable PSS or OAEP software padding", 0);
+ new_description->push_back(TAG_PADDING, KM_PAD_NONE);
+ }
+}
+
+keymaster_error_t RsaKeymaster1KeyFactory::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 RsaKeymaster1KeyFactory::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 RsaKeymaster1KeyFactory::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<RSA, RSA_Delete> rsa(engine_->BuildRsaKey(key_material, additional_params, &error));
+ if (!rsa)
+ return error;
+
+ key->reset(new (std::nothrow)
+ RsaKeymaster1Key(rsa.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* RsaKeymaster1KeyFactory::GetOperationFactory(keymaster_purpose_t purpose) const {
+ switch (purpose) {
+ case KM_PURPOSE_SIGN:
+ return sign_factory_.get();
+ case KM_PURPOSE_VERIFY:
+ return verify_factory_.get();
+ case KM_PURPOSE_ENCRYPT:
+ return encrypt_factory_.get();
+ case KM_PURPOSE_DECRYPT:
+ return decrypt_factory_.get();
+ }
+ return nullptr;
+}
+
+RsaKeymaster1Key::RsaKeymaster1Key(RSA* rsa_key, const AuthorizationSet& hw_enforced,
+ const AuthorizationSet& sw_enforced,
+ const Keymaster1Engine* engine, keymaster_error_t* error)
+ : RsaKey(rsa_key, hw_enforced, sw_enforced, error), engine_(engine) {}
+
+} // namespace keymaster
diff --git a/rsa_keymaster1_key.h b/rsa_keymaster1_key.h
new file mode 100644
index 0000000..4d5a3bd
--- /dev/null
+++ b/rsa_keymaster1_key.h
@@ -0,0 +1,84 @@
+/*
+ * 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.
+ */
+
+#ifndef SYSTEM_KEYMASTER_RSA_KEYMASTER1_KEY_H_
+#define SYSTEM_KEYMASTER_RSA_KEYMASTER1_KEY_H_
+
+#include <openssl/rsa.h>
+
+#include <keymaster/rsa_key_factory.h>
+
+#include "keymaster1_engine.h"
+#include "rsa_key.h"
+
+namespace keymaster {
+
+class SoftKeymasterContext;
+
+/**
+ * RsaKeymaster1KeyFactory is a KeyFactory that creates and loads keys which are actually backed by
+ * a hardware keymaster1 module, but which does not support all keymaster1 digests. If unsupported
+ * digests are found during generation or import, KM_DIGEST_NONE is added to the key description,
+ * then the operations handle the unsupported digests in software.
+ *
+ * If unsupported digests are requested and KM_PAD_RSA_PSS or KM_PAD_RSA_OAEP is also requested, but
+ * KM_PAD_NONE is not present KM_PAD_NONE will be added to the description, to allow for
+ * software padding as well as software digesting.
+ */
+class RsaKeymaster1KeyFactory : public RsaKeyFactory {
+ public:
+ RsaKeymaster1KeyFactory(const SoftKeymasterContext* context, const Keymaster1Engine* engine);
+
+ keymaster_error_t GenerateKey(const AuthorizationSet& key_description,
+ KeymasterKeyBlob* key_blob, AuthorizationSet* hw_enforced,
+ AuthorizationSet* sw_enforced) const override;
+
+ keymaster_error_t 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 override;
+
+ keymaster_error_t LoadKey(const KeymasterKeyBlob& key_material,
+ const AuthorizationSet& additional_params,
+ const AuthorizationSet& hw_enforced,
+ const AuthorizationSet& sw_enforced,
+ UniquePtr<Key>* key) const override;
+
+ OperationFactory* GetOperationFactory(keymaster_purpose_t purpose) const override;
+
+ private:
+ const Keymaster1Engine* engine_;
+
+ std::unique_ptr<OperationFactory> sign_factory_;
+ std::unique_ptr<OperationFactory> decrypt_factory_;
+ std::unique_ptr<OperationFactory> verify_factory_;
+ std::unique_ptr<OperationFactory> encrypt_factory_;
+};
+
+class RsaKeymaster1Key : public RsaKey {
+ public:
+ RsaKeymaster1Key(RSA* rsa_key, const AuthorizationSet& hw_enforced,
+ const AuthorizationSet& sw_enforced, const Keymaster1Engine* engine,
+ keymaster_error_t* error);
+
+ private:
+ const Keymaster1Engine* engine_;
+};
+
+} // namespace keymaster
+
+#endif // SYSTEM_KEYMASTER_RSA_KEYMASTER1_KEY_H_
diff --git a/rsa_keymaster1_operation.cpp b/rsa_keymaster1_operation.cpp
new file mode 100644
index 0000000..002930e
--- /dev/null
+++ b/rsa_keymaster1_operation.cpp
@@ -0,0 +1,180 @@
+/*
+ * 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 "rsa_keymaster1_operation.h"
+
+#include <memory>
+
+#include <keymaster/android_keymaster_utils.h>
+
+#include "openssl_err.h"
+#include "openssl_utils.h"
+#include "rsa_keymaster1_key.h"
+
+using std::unique_ptr;
+
+namespace keymaster {
+
+keymaster_error_t RsaKeymaster1WrappedOperation::Begin(EVP_PKEY* rsa_key,
+ const AuthorizationSet& input_params) {
+ Keymaster1Engine::KeyData* key_data = engine_->GetData(rsa_key);
+ if (!key_data)
+ return KM_ERROR_UNKNOWN_ERROR;
+
+ // Copy the input params and substitute KM_DIGEST_NONE for whatever was specified. Also change
+ // KM_PAD_RSA_PSS and KM_PAD_OAEP to KM_PAD_NONE, if necessary. These are the params we'll pass
+ // to the hardware module. The regular Rsa*Operation classes will do software digesting and
+ // padding where we've told the HW not to.
+ //
+ // The reason we don't change KM_PAD_RSA_PKCS1_1_5_SIGN or KM_PAD_RSA_PKCS1_1_5_ENCRYPT to
+ // KM_PAD_NONE is because the hardware can perform those padding modes, since they don't involve
+ // digesting.
+ //
+ // We also cache in the key the padding value that we expect to be passed to the engine crypto
+ // operation. This just allows us to double-check that the correct padding value is reaching
+ // that layer.
+ AuthorizationSet begin_params(input_params);
+ int pos = begin_params.find(TAG_DIGEST);
+ if (pos == -1)
+ return KM_ERROR_UNSUPPORTED_DIGEST;
+ begin_params[pos].enumerated = KM_DIGEST_NONE;
+
+ pos = begin_params.find(TAG_PADDING);
+ if (pos == -1)
+ return KM_ERROR_UNSUPPORTED_PADDING_MODE;
+ switch (begin_params[pos].enumerated) {
+
+ case KM_PAD_RSA_PSS:
+ case KM_PAD_RSA_OAEP:
+ key_data->expected_openssl_padding = RSA_NO_PADDING;
+ begin_params[pos].enumerated = KM_PAD_NONE;
+ break;
+
+ case KM_PAD_RSA_PKCS1_1_5_ENCRYPT:
+ case KM_PAD_RSA_PKCS1_1_5_SIGN:
+ key_data->expected_openssl_padding = RSA_PKCS1_PADDING;
+ break;
+ }
+
+ return engine_->device()->begin(engine_->device(), purpose_, &key_data->key_material,
+ &begin_params, nullptr /* out_params */, &operation_handle_);
+}
+
+keymaster_error_t
+RsaKeymaster1WrappedOperation::PrepareFinish(EVP_PKEY* rsa_key,
+ const AuthorizationSet& input_params) {
+ Keymaster1Engine::KeyData* key_data = engine_->GetData(rsa_key);
+ if (!key_data) {
+ LOG_E("Could not get extended key data... not a Keymaster1Engine key?", 0);
+ return KM_ERROR_UNKNOWN_ERROR;
+ }
+ key_data->op_handle = operation_handle_;
+ key_data->finish_params.Reinitialize(input_params);
+
+ return KM_ERROR_OK;
+}
+
+keymaster_error_t RsaKeymaster1WrappedOperation::Abort() {
+ return engine_->device()->abort(engine_->device(), operation_handle_);
+}
+
+keymaster_error_t RsaKeymaster1WrappedOperation::GetError(EVP_PKEY* rsa_key) {
+ Keymaster1Engine::KeyData* key_data = engine_->GetData(rsa_key); // key_data is owned by rsa
+ if (!key_data)
+ return KM_ERROR_UNKNOWN_ERROR;
+ return key_data->error;
+}
+
+static EVP_PKEY* GetEvpKey(const RsaKeymaster1Key& key, keymaster_error_t* error) {
+ if (!key.key()) {
+ *error = KM_ERROR_UNKNOWN_ERROR;
+ return nullptr;
+ }
+
+ UniquePtr<EVP_PKEY, EVP_PKEY_Delete> pkey(EVP_PKEY_new());
+ if (!key.InternalToEvp(pkey.get())) {
+ *error = KM_ERROR_UNKNOWN_ERROR;
+ return nullptr;
+ }
+ return pkey.release();
+}
+
+Operation* RsaKeymaster1OperationFactory::CreateOperation(const Key& key,
+ const AuthorizationSet& begin_params,
+ keymaster_error_t* error) {
+ keymaster_digest_t digest;
+ if (!GetAndValidateDigest(begin_params, key, &digest, error))
+ return nullptr;
+
+ keymaster_padding_t padding;
+ if (!GetAndValidatePadding(begin_params, key, &padding, error))
+ return nullptr;
+
+ const RsaKeymaster1Key& rsa_km1_key(static_cast<const RsaKeymaster1Key&>(key));
+ unique_ptr<EVP_PKEY, EVP_PKEY_Delete> rsa(GetEvpKey(rsa_km1_key, error));
+ if (!rsa)
+ return nullptr;
+
+ switch (purpose_) {
+ case KM_PURPOSE_SIGN:
+ return new RsaKeymaster1Operation<RsaSignOperation>(digest, padding, rsa.release(),
+ engine_);
+ case KM_PURPOSE_DECRYPT:
+ return new RsaKeymaster1Operation<RsaDecryptOperation>(digest, padding, rsa.release(),
+ engine_);
+ default:
+ LOG_E("Bug: Pubkey operation requested. Those should be handled by normal RSA operations.",
+ 0);
+ *error = KM_ERROR_UNSUPPORTED_PURPOSE;
+ return nullptr;
+ }
+}
+
+static const keymaster_digest_t supported_digests[] = {
+ KM_DIGEST_NONE, KM_DIGEST_MD5, KM_DIGEST_SHA1, KM_DIGEST_SHA_2_224,
+ KM_DIGEST_SHA_2_256, KM_DIGEST_SHA_2_384, KM_DIGEST_SHA_2_512};
+
+const keymaster_digest_t*
+RsaKeymaster1OperationFactory::SupportedDigests(size_t* digest_count) const {
+ *digest_count = array_length(supported_digests);
+ return supported_digests;
+}
+
+static const keymaster_padding_t supported_sig_padding[] = {
+ KM_PAD_NONE, KM_PAD_RSA_PKCS1_1_5_SIGN, KM_PAD_RSA_PSS,
+};
+static const keymaster_padding_t supported_crypt_padding[] = {
+ KM_PAD_NONE, KM_PAD_RSA_PKCS1_1_5_ENCRYPT, KM_PAD_RSA_OAEP,
+};
+
+const keymaster_padding_t*
+RsaKeymaster1OperationFactory::SupportedPaddingModes(size_t* padding_mode_count) const {
+ switch (purpose_) {
+ case KM_PURPOSE_SIGN:
+ case KM_PURPOSE_VERIFY:
+ *padding_mode_count = array_length(supported_sig_padding);
+ return supported_sig_padding;
+ case KM_PURPOSE_ENCRYPT:
+ case KM_PURPOSE_DECRYPT:
+ *padding_mode_count = array_length(supported_crypt_padding);
+ return supported_crypt_padding;
+ default:
+ *padding_mode_count = 0;
+ return nullptr;
+ }
+}
+
+} // namespace keymaster
diff --git a/rsa_keymaster1_operation.h b/rsa_keymaster1_operation.h
new file mode 100644
index 0000000..bdf1a4e
--- /dev/null
+++ b/rsa_keymaster1_operation.h
@@ -0,0 +1,119 @@
+/*
+ * 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.
+ */
+
+#ifndef SYSTEM_KEYMASTER_RSA_KEYMASTER1_OPERATION_H_
+#define SYSTEM_KEYMASTER_RSA_KEYMASTER1_OPERATION_H_
+
+#include <openssl/evp.h>
+
+#include <hardware/keymaster1.h>
+#include <keymaster/android_keymaster_utils.h>
+
+#include "rsa_operation.h"
+#include "keymaster1_engine.h"
+
+namespace keymaster {
+
+class RsaKeymaster1WrappedOperation {
+ public:
+ RsaKeymaster1WrappedOperation(keymaster_purpose_t purpose, const Keymaster1Engine* engine)
+ : purpose_(purpose), operation_handle_(0), engine_(engine) {}
+ ~RsaKeymaster1WrappedOperation() {
+ if (operation_handle_)
+ Abort();
+ }
+
+ keymaster_error_t Begin(EVP_PKEY* rsa_key, const AuthorizationSet& input_params);
+ keymaster_error_t PrepareFinish(EVP_PKEY* rsa_key, const AuthorizationSet& input_params);
+ void Finish() { operation_handle_ = 0; }
+ keymaster_error_t Abort();
+
+ keymaster_error_t GetError(EVP_PKEY* rsa_key);
+
+ protected:
+ keymaster_purpose_t purpose_;
+ keymaster_operation_handle_t operation_handle_;
+ const Keymaster1Engine* engine_;
+};
+
+template <typename BaseOperation> class RsaKeymaster1Operation : public BaseOperation {
+ typedef BaseOperation super;
+
+ public:
+ RsaKeymaster1Operation(keymaster_digest_t digest, keymaster_padding_t padding, EVP_PKEY* key,
+ const Keymaster1Engine* engine)
+ : BaseOperation(digest, padding, key), wrapped_operation_(super::purpose(), engine) {
+ // Shouldn't be instantiated for public key operations.
+ assert(super::purpose() != KM_PURPOSE_VERIFY);
+ assert(super::purpose() != KM_PURPOSE_ENCRYPT);
+ }
+
+ keymaster_error_t Begin(const AuthorizationSet& input_params,
+ AuthorizationSet* output_params) override {
+ keymaster_error_t error = wrapped_operation_.Begin(super::rsa_key_, input_params);
+ if (error != KM_ERROR_OK)
+ return error;
+ return super::Begin(input_params, output_params);
+ }
+
+ keymaster_error_t Finish(const AuthorizationSet& input_params, const Buffer& signature,
+ AuthorizationSet* output_params, Buffer* output) override {
+ keymaster_error_t error = wrapped_operation_.PrepareFinish(super::rsa_key_, input_params);
+ if (error != KM_ERROR_OK)
+ return error;
+ error = super::Finish(input_params, signature, output_params, output);
+ if (wrapped_operation_.GetError(super::rsa_key_) != KM_ERROR_OK)
+ error = wrapped_operation_.GetError(super::rsa_key_);
+ if (error == KM_ERROR_OK)
+ wrapped_operation_.Finish();
+ return error;
+ }
+
+ keymaster_error_t Abort() override {
+ keymaster_error_t error = wrapped_operation_.Abort();
+ if (error != KM_ERROR_OK)
+ return error;
+ return super::Abort();
+ }
+
+ private:
+ RsaKeymaster1WrappedOperation wrapped_operation_;
+};
+
+/**
+ * Factory that produces RsaKeymaster1Operations. This is instantiated and
+ * provided by RsaKeymaster1KeyFactory.
+ */
+class RsaKeymaster1OperationFactory : public OperationFactory {
+ public:
+ RsaKeymaster1OperationFactory(keymaster_purpose_t purpose, const Keymaster1Engine* engine)
+ : purpose_(purpose), engine_(engine) {}
+ KeyType registry_key() const override { return KeyType(KM_ALGORITHM_RSA, purpose_); }
+
+ Operation* CreateOperation(const Key& key, const AuthorizationSet& begin_params,
+ keymaster_error_t* error) override;
+
+ const keymaster_digest_t* SupportedDigests(size_t* digest_count) const override;
+ const keymaster_padding_t* SupportedPaddingModes(size_t* padding_mode_count) const override;
+
+ private:
+ keymaster_purpose_t purpose_;
+ const Keymaster1Engine* engine_;
+};
+
+} // namespace keymaster
+
+#endif // SYSTEM_KEYMASTER_RSA_KEYMASTER1_OPERATION_H_
diff --git a/rsa_operation.cpp b/rsa_operation.cpp
index 076f333..7b6514c 100644
--- a/rsa_operation.cpp
+++ b/rsa_operation.cpp
@@ -76,10 +76,6 @@ RsaOperation* RsaOperationFactory::CreateRsaOperation(const Key& key,
keymaster_digest_t digest = KM_DIGEST_NONE;
if (require_digest && !GetAndValidateDigest(begin_params, key, &digest, error))
return nullptr;
- if (!require_digest && begin_params.find(TAG_DIGEST) != -1) {
- *error = KM_ERROR_UNSUPPORTED_DIGEST;
- return nullptr;
- }
UniquePtr<EVP_PKEY, EVP_PKEY_Delete> rsa(GetRsaKey(key, error));
if (!rsa.get())
diff --git a/rsa_operation.h b/rsa_operation.h
index 30ea3c5..3ad4f0d 100644
--- a/rsa_operation.h
+++ b/rsa_operation.h
@@ -58,7 +58,7 @@ class RsaOperation : public Operation {
keymaster_error_t InitDigest();
EVP_PKEY* rsa_key_;
- keymaster_padding_t padding_;
+ const keymaster_padding_t padding_;
Buffer data_;
const keymaster_digest_t digest_;
const EVP_MD* digest_algorithm_;
@@ -129,9 +129,9 @@ class RsaVerifyOperation : public RsaDigestingOperation {
*/
class RsaCryptOperation : public RsaOperation {
public:
- RsaCryptOperation(keymaster_purpose_t, keymaster_digest_t digest, keymaster_padding_t padding,
- EVP_PKEY* key)
- : RsaOperation(KM_PURPOSE_ENCRYPT, digest, padding, key) {}
+ RsaCryptOperation(keymaster_purpose_t purpose, keymaster_digest_t digest,
+ keymaster_padding_t padding, EVP_PKEY* key)
+ : RsaOperation(purpose, digest, padding, key) {}
protected:
keymaster_error_t SetOaepDigestIfRequired(EVP_PKEY_CTX* pkey_ctx);
@@ -189,9 +189,7 @@ class RsaOperationFactory : public OperationFactory {
};
/**
- * Abstract base for RSA operations that digest their input (signing and verification). This class
- * does most of the work of creation of RSA digesting operations, delegating only the actual
- * operation instantiation.
+ * Abstract base for RSA operations that digest their input (signing and verification).
*/
class RsaDigestingOperationFactory : public RsaOperationFactory {
public:
diff --git a/soft_keymaster_context.cpp b/soft_keymaster_context.cpp
index 3e5fc35..288a350 100644
--- a/soft_keymaster_context.cpp
+++ b/soft_keymaster_context.cpp
@@ -29,12 +29,14 @@
#include "aes_key.h"
#include "auth_encrypted_key_blob.h"
#include "ec_keymaster0_key.h"
+#include "ec_keymaster1_key.h"
#include "hmac_key.h"
#include "integrity_assured_key_blob.h"
#include "keymaster0_engine.h"
#include "ocb_utils.h"
#include "openssl_err.h"
#include "rsa_keymaster0_key.h"
+#include "rsa_keymaster1_key.h"
using std::unique_ptr;
@@ -47,13 +49,47 @@ const int TAG_LENGTH = 16;
const KeymasterKeyBlob MASTER_KEY(master_key_bytes, array_length(master_key_bytes));
} // anonymous namespace
-SoftKeymasterContext::SoftKeymasterContext(keymaster0_device_t* keymaster0_device) {
- if (keymaster0_device && (keymaster0_device->flags & KEYMASTER_SOFTWARE_ONLY) == 0)
- engine_.reset(new Keymaster0Engine(keymaster0_device));
- rsa_factory_.reset(new RsaKeymaster0KeyFactory(this, engine_.get()));
- ec_factory_.reset(new EcdsaKeymaster0KeyFactory(this, engine_.get()));
- aes_factory_.reset(new AesKeyFactory(this));
- hmac_factory_.reset(new HmacKeyFactory(this));
+SoftKeymasterContext::SoftKeymasterContext(const std::string& root_of_trust)
+ : rsa_factory_(new RsaKeyFactory(this)), ec_factory_(new EcKeyFactory(this)),
+ aes_factory_(new AesKeyFactory(this)), hmac_factory_(new HmacKeyFactory(this)),
+ km1_dev_(nullptr), root_of_trust_(root_of_trust) {}
+
+SoftKeymasterContext::~SoftKeymasterContext() {}
+
+keymaster_error_t SoftKeymasterContext::SetHardwareDevice(keymaster0_device_t* keymaster0_device) {
+ if (!keymaster0_device)
+ return KM_ERROR_UNEXPECTED_NULL_POINTER;
+
+ if ((keymaster0_device->flags & KEYMASTER_SOFTWARE_ONLY) != 0) {
+ LOG_E("SoftKeymasterContext only wraps hardware keymaster0 devices", 0);
+ return KM_ERROR_INVALID_ARGUMENT;
+ }
+
+ km0_engine_.reset(new Keymaster0Engine(keymaster0_device));
+ rsa_factory_.reset(new RsaKeymaster0KeyFactory(this, km0_engine_.get()));
+ ec_factory_.reset(new EcdsaKeymaster0KeyFactory(this, km0_engine_.get()));
+ // Keep AES and HMAC factories.
+
+ return KM_ERROR_OK;
+}
+
+keymaster_error_t SoftKeymasterContext::SetHardwareDevice(keymaster1_device_t* keymaster1_device) {
+ if (!keymaster1_device)
+ return KM_ERROR_UNEXPECTED_NULL_POINTER;
+
+ km1_dev_ = keymaster1_device;
+
+ km1_engine_.reset(new Keymaster1Engine(keymaster1_device));
+ rsa_factory_.reset(new RsaKeymaster1KeyFactory(this, km1_engine_.get()));
+ ec_factory_.reset(new EcdsaKeymaster1KeyFactory(this, km1_engine_.get()));
+
+ // All AES and HMAC operations should be passed directly to the keymaster1 device. Explicitly
+ // do not handle them, to provoke errors in case the higher layers fail to send them to the
+ // device.
+ aes_factory_.reset(nullptr);
+ hmac_factory_.reset(nullptr);
+
+ return KM_ERROR_OK;
}
KeyFactory* SoftKeymasterContext::GetKeyFactory(keymaster_algorithm_t algorithm) const {
@@ -100,23 +136,6 @@ static keymaster_error_t TranslateAuthorizationSetError(AuthorizationSet::Error
return KM_ERROR_OK;
}
-static keymaster_error_t BuildHiddenAuthorizations(const AuthorizationSet& input_set,
- AuthorizationSet* hidden) {
- keymaster_blob_t entry;
- if (input_set.GetTagValue(TAG_APPLICATION_ID, &entry))
- hidden->push_back(TAG_APPLICATION_ID, entry.data, entry.data_length);
- if (input_set.GetTagValue(TAG_APPLICATION_DATA, &entry))
- hidden->push_back(TAG_APPLICATION_DATA, entry.data, entry.data_length);
-
- keymaster_key_param_t root_of_trust;
- root_of_trust.tag = KM_TAG_ROOT_OF_TRUST;
- root_of_trust.blob.data = reinterpret_cast<const uint8_t*>("SW");
- root_of_trust.blob.data_length = 2;
- hidden->push_back(root_of_trust);
-
- return TranslateAuthorizationSetError(hidden->is_valid());
-}
-
static keymaster_error_t SetAuthorizations(const AuthorizationSet& key_description,
keymaster_key_origin_t origin,
AuthorizationSet* hw_enforced,
@@ -293,7 +312,10 @@ keymaster_error_t SoftKeymasterContext::ParseKeyBlob(const KeymasterKeyBlob& blo
// they're protected by the keymaster0 hardware implementation). The keymaster0 key blob
// and auth sets should be extracted and returned.
//
- // 5. Old keymaster0 hardware key blobs. These are raw hardware key blobs. They don't have
+ // 5. Keymaster1 hardware key blobs. These are raw hardware key blobs. They contain auth
+ // sets, which we retrieve from the hardware module.
+ //
+ // 6. Old keymaster0 hardware key blobs. These are raw hardware key blobs. They don't have
// auth sets so reasonable defaults are generated and returned along with the key blob.
//
// Determining what kind of blob has arrived is somewhat tricky. What helps is that
@@ -328,17 +350,72 @@ keymaster_error_t SoftKeymasterContext::ParseKeyBlob(const KeymasterKeyBlob& blo
if (error != KM_ERROR_INVALID_KEY_BLOB)
return error;
- // Not an old softkeymaster blob, either. The only remaining option is old HW keymaster0.
- if (!engine_)
- return KM_ERROR_INVALID_KEY_BLOB;
+ if (km1_dev_)
+ return ParseKeymaster1HwBlob(blob, additional_params, key_material, hw_enforced,
+ sw_enforced);
+ else if (km0_engine_)
+ return ParseKeymaster0HwBlob(blob, key_material, hw_enforced, sw_enforced);
+
+ LOG_E("Failed to parse key; not a valid software blob, no hardware module configured", 0);
+ return KM_ERROR_INVALID_KEY_BLOB;
+}
+
+keymaster_error_t SoftKeymasterContext::AddRngEntropy(const uint8_t* buf, size_t length) const {
+ RAND_add(buf, length, 0 /* Don't assume any entropy is added to the pool. */);
+ return KM_ERROR_OK;
+}
+
+keymaster_error_t SoftKeymasterContext::GenerateRandom(uint8_t* buf, size_t length) const {
+ if (RAND_bytes(buf, length) != 1)
+ return KM_ERROR_UNKNOWN_ERROR;
+ return KM_ERROR_OK;
+}
+
+keymaster_error_t SoftKeymasterContext::ParseKeymaster1HwBlob(
+ const KeymasterKeyBlob& blob, const AuthorizationSet& additional_params,
+ KeymasterKeyBlob* key_material, AuthorizationSet* hw_enforced,
+ AuthorizationSet* sw_enforced) const {
+ assert(km1_dev_);
+
+ keymaster_blob_t client_id = {nullptr, 0};
+ keymaster_blob_t app_data = {nullptr, 0};
+ keymaster_blob_t* client_id_ptr = nullptr;
+ keymaster_blob_t* app_data_ptr = nullptr;
+ if (additional_params.GetTagValue(TAG_APPLICATION_ID, &client_id))
+ client_id_ptr = &client_id;
+ if (additional_params.GetTagValue(TAG_APPLICATION_DATA, &app_data))
+ app_data_ptr = &app_data;
+
+ // Get key characteristics, which incidentally verifies that the HW recognizes the key.
+ keymaster_key_characteristics_t* characteristics;
+ keymaster_error_t error = km1_dev_->get_key_characteristics(km1_dev_, &blob, client_id_ptr,
+ app_data_ptr, &characteristics);
+ if (error != KM_ERROR_OK)
+ return error;
+ unique_ptr<keymaster_key_characteristics_t, Characteristics_Delete> characteristics_deleter(
+ characteristics);
+
+ LOG_D("Module \"%s\" accepted key", km1_dev_->common.module->name);
+
+ hw_enforced->Reinitialize(characteristics->hw_enforced);
+ sw_enforced->Reinitialize(characteristics->sw_enforced);
+ *key_material = blob;
+ return KM_ERROR_OK;
+}
+
+keymaster_error_t SoftKeymasterContext::ParseKeymaster0HwBlob(const KeymasterKeyBlob& blob,
+ KeymasterKeyBlob* key_material,
+ AuthorizationSet* hw_enforced,
+ AuthorizationSet* sw_enforced) const {
+ assert(km0_engine_);
+
+ unique_ptr<EVP_PKEY, EVP_PKEY_Delete> tmp_key(km0_engine_->GetKeymaster0PublicKey(blob));
- // See if the HW thinks it's valid.
- unique_ptr<EVP_PKEY, EVP_PKEY_Delete> tmp_key(engine_->GetKeymaster0PublicKey(blob));
if (!tmp_key)
return KM_ERROR_INVALID_KEY_BLOB;
- else
- error = FakeKeyAuthorizations(tmp_key.get(), hw_enforced, sw_enforced);
+ LOG_D("Module \"%s\" accepted key", km0_engine_->device()->common.module->name);
+ keymaster_error_t error = FakeKeyAuthorizations(tmp_key.get(), hw_enforced, sw_enforced);
if (error == KM_ERROR_OK)
*key_material = blob;
@@ -418,15 +495,18 @@ keymaster_error_t SoftKeymasterContext::FakeKeyAuthorizations(EVP_PKEY* pubkey,
return KM_ERROR_OK;
}
-keymaster_error_t SoftKeymasterContext::AddRngEntropy(const uint8_t* buf, size_t length) const {
- RAND_add(buf, length, 0 /* Don't assume any entropy is added to the pool. */);
- return KM_ERROR_OK;
-}
+keymaster_error_t SoftKeymasterContext::BuildHiddenAuthorizations(const AuthorizationSet& input_set,
+ AuthorizationSet* hidden) const {
+ keymaster_blob_t entry;
+ if (input_set.GetTagValue(TAG_APPLICATION_ID, &entry))
+ hidden->push_back(TAG_APPLICATION_ID, entry.data, entry.data_length);
+ if (input_set.GetTagValue(TAG_APPLICATION_DATA, &entry))
+ hidden->push_back(TAG_APPLICATION_DATA, entry.data, entry.data_length);
-keymaster_error_t SoftKeymasterContext::GenerateRandom(uint8_t* buf, size_t length) const {
- if (RAND_bytes(buf, length) != 1)
- return KM_ERROR_UNKNOWN_ERROR;
- return KM_ERROR_OK;
+ hidden->push_back(TAG_ROOT_OF_TRUST, reinterpret_cast<const uint8_t*>(root_of_trust_.data()),
+ root_of_trust_.size());
+
+ return TranslateAuthorizationSetError(hidden->is_valid());
}
} // namespace keymaster
diff --git a/soft_keymaster_device.cpp b/soft_keymaster_device.cpp
index e1d9090..9f3418e 100644
--- a/soft_keymaster_device.cpp
+++ b/soft_keymaster_device.cpp
@@ -48,7 +48,7 @@ struct keystore_module soft_keymaster_device_module = {
.module_api_version = KEYMASTER_MODULE_API_VERSION_1_0,
.hal_api_version = HARDWARE_HAL_API_VERSION,
.id = KEYSTORE_HARDWARE_MODULE_ID,
- .name = "Keymaster OpenSSL HAL",
+ .name = "OpenSSL-based SoftKeymaster HAL",
.author = "The Android Open Source Project",
.methods = NULL,
.dso = 0,
@@ -58,18 +58,61 @@ struct keystore_module soft_keymaster_device_module = {
namespace keymaster {
-SoftKeymasterDevice::SoftKeymasterDevice(keymaster0_device_t* keymaster0_device)
- : wrapped_device_(keymaster0_device),
- impl_(new AndroidKeymaster(new SoftKeymasterContext(keymaster0_device), 16)) {
- initialize(keymaster0_device);
+const size_t kOperationTableSize = 16;
+
+typedef std::map<std::pair<keymaster_algorithm_t, keymaster_purpose_t>,
+ std::vector<keymaster_digest_t>> DigestMap;
+
+template <typename T> std::vector<T> make_vector(const T* array, size_t len) {
+ return std::vector<T>(array, array + len);
}
-SoftKeymasterDevice::SoftKeymasterDevice(KeymasterContext* context)
- : impl_(new AndroidKeymaster(context, 16)) {
- initialize(nullptr);
+static keymaster_error_t add_digests(keymaster1_device_t* dev, keymaster_algorithm_t algorithm,
+ keymaster_purpose_t purpose, DigestMap* map) {
+ auto key = std::make_pair(algorithm, purpose);
+
+ keymaster_digest_t* digests;
+ size_t digests_length;
+ keymaster_error_t error =
+ dev->get_supported_digests(dev, algorithm, purpose, &digests, &digests_length);
+ if (error != KM_ERROR_OK) {
+ LOG_E("Error %d getting supported digests from keymaster1 device", error);
+ return error;
+ }
+ std::unique_ptr<keymaster_digest_t, Malloc_Delete> digests_deleter(digests);
+
+ (*map)[key] = make_vector(digests, digests_length);
+ return KM_ERROR_OK;
}
-void SoftKeymasterDevice::initialize(keymaster0_device_t* keymaster0_device) {
+static keymaster_error_t map_digests(keymaster1_device_t* dev, DigestMap* map) {
+ map->clear();
+
+ keymaster_algorithm_t sig_algorithms[] = {KM_ALGORITHM_RSA, KM_ALGORITHM_EC};
+ keymaster_purpose_t sig_purposes[] = {KM_PURPOSE_SIGN, KM_PURPOSE_VERIFY};
+ for (auto algorithm : sig_algorithms)
+ for (auto purpose : sig_purposes) {
+ keymaster_error_t error = add_digests(dev, algorithm, purpose, map);
+ if (error != KM_ERROR_OK)
+ return error;
+ }
+
+ keymaster_algorithm_t crypt_algorithms[] = {KM_ALGORITHM_RSA};
+ keymaster_purpose_t crypt_purposes[] = {KM_PURPOSE_ENCRYPT, KM_PURPOSE_DECRYPT};
+ for (auto algorithm : crypt_algorithms)
+ for (auto purpose : crypt_purposes) {
+ keymaster_error_t error = add_digests(dev, algorithm, purpose, map);
+ if (error != KM_ERROR_OK)
+ return error;
+ }
+
+ return KM_ERROR_OK;
+}
+
+SoftKeymasterDevice::SoftKeymasterDevice()
+ : wrapped_km0_device_(nullptr), wrapped_km1_device_(nullptr),
+ context_(new SoftKeymasterContext),
+ impl_(new AndroidKeymaster(context_, kOperationTableSize)) {
static_assert(std::is_standard_layout<SoftKeymasterDevice>::value,
"SoftKeymasterDevice must be standard layout");
static_assert(offsetof(SoftKeymasterDevice, device_) == 0,
@@ -79,6 +122,106 @@ void SoftKeymasterDevice::initialize(keymaster0_device_t* keymaster0_device) {
LOG_I("Creating device", 0);
LOG_D("Device address: %p", this);
+ initialize_device_struct();
+}
+
+SoftKeymasterDevice::SoftKeymasterDevice(SoftKeymasterContext* context)
+ : wrapped_km0_device_(nullptr), wrapped_km1_device_(nullptr), context_(context),
+ impl_(new AndroidKeymaster(context_, kOperationTableSize)) {
+ static_assert(std::is_standard_layout<SoftKeymasterDevice>::value,
+ "SoftKeymasterDevice must be standard layout");
+ static_assert(offsetof(SoftKeymasterDevice, device_) == 0,
+ "device_ must be the first member of SoftKeymasterDevice");
+ static_assert(offsetof(SoftKeymasterDevice, device_.common) == 0,
+ "common must be the first member of keymaster_device");
+ LOG_I("Creating test device", 0);
+ LOG_D("Device address: %p", this);
+
+ initialize_device_struct();
+}
+
+keymaster_error_t SoftKeymasterDevice::SetHardwareDevice(keymaster0_device_t* keymaster0_device) {
+ assert(keymaster0_device);
+ LOG_D("Reinitializing SoftKeymasterDevice to use HW keymaster0", 0);
+
+ if (!context_)
+ return KM_ERROR_UNEXPECTED_NULL_POINTER;
+
+ keymaster_error_t error = context_->SetHardwareDevice(keymaster0_device);
+ if (error != KM_ERROR_OK)
+ return error;
+
+ initialize_device_struct();
+
+ module_name_ = device_.common.module->name;
+ module_name_.append("(Wrapping ");
+ module_name_.append(keymaster0_device->common.module->name);
+ module_name_.append(")");
+
+ updated_module_ = *device_.common.module;
+ updated_module_.name = module_name_.c_str();
+
+ device_.common.module = &updated_module_;
+
+ wrapped_km0_device_ = keymaster0_device;
+ wrapped_km1_device_ = nullptr;
+ return KM_ERROR_OK;
+}
+
+keymaster_error_t SoftKeymasterDevice::SetHardwareDevice(keymaster1_device_t* keymaster1_device) {
+ assert(keymaster1_device);
+ LOG_D("Reinitializing SoftKeymasterDevice to use HW keymaster1", 0);
+
+ if (!context_)
+ return KM_ERROR_UNEXPECTED_NULL_POINTER;
+
+ keymaster_error_t error = map_digests(keymaster1_device, &km1_device_digests_);
+ if (error != KM_ERROR_OK)
+ return error;
+
+ error = context_->SetHardwareDevice(keymaster1_device);
+ if (error != KM_ERROR_OK)
+ return error;
+
+ initialize_device_struct();
+
+ module_name_ = device_.common.module->name;
+ module_name_.append(" (Wrapping ");
+ module_name_.append(keymaster1_device->common.module->name);
+ module_name_.append(")");
+
+ updated_module_ = *device_.common.module;
+ updated_module_.name = module_name_.c_str();
+
+ device_.common.module = &updated_module_;
+
+ wrapped_km0_device_ = nullptr;
+ wrapped_km1_device_ = keymaster1_device;
+ return KM_ERROR_OK;
+}
+
+bool SoftKeymasterDevice::Keymaster1DeviceIsGood() {
+ std::vector<keymaster_digest_t> expected_rsa_digests = {
+ KM_DIGEST_NONE, KM_DIGEST_MD5, KM_DIGEST_SHA1, KM_DIGEST_SHA_2_224,
+ KM_DIGEST_SHA_2_256, KM_DIGEST_SHA_2_384, KM_DIGEST_SHA_2_512};
+ std::vector<keymaster_digest_t> expected_ec_digests = {
+ KM_DIGEST_NONE, KM_DIGEST_SHA1, KM_DIGEST_SHA_2_224,
+ KM_DIGEST_SHA_2_256, KM_DIGEST_SHA_2_384, KM_DIGEST_SHA_2_512};
+
+ for (auto& entry : km1_device_digests_) {
+ if (entry.first.first == KM_ALGORITHM_RSA)
+ if (!std::is_permutation(entry.second.begin(), entry.second.end(),
+ expected_rsa_digests.begin()))
+ return false;
+ if (entry.first.first == KM_ALGORITHM_EC)
+ if (!std::is_permutation(entry.second.begin(), entry.second.end(),
+ expected_ec_digests.begin()))
+ return false;
+ }
+ return true;
+}
+
+void SoftKeymasterDevice::initialize_device_struct() {
memset(&device_, 0, sizeof(device_));
device_.common.tag = HARDWARE_DEVICE_TAG;
@@ -87,28 +230,15 @@ void SoftKeymasterDevice::initialize(keymaster0_device_t* keymaster0_device) {
device_.common.close = &close_device;
device_.flags = KEYMASTER_BLOBS_ARE_STANDALONE | KEYMASTER_SUPPORTS_EC;
- if (keymaster0_device) {
- device_.flags |= keymaster0_device->flags & KEYMASTER_SOFTWARE_ONLY;
- } else {
- device_.flags |= KEYMASTER_SOFTWARE_ONLY;
- }
// keymaster0 APIs
- device_.generate_keypair = generate_keypair;
- device_.import_keypair = import_keypair;
- device_.get_keypair_public = get_keypair_public;
- if (keymaster0_device && keymaster0_device->delete_keypair) {
- device_.delete_keypair = delete_keypair;
- } else {
- device_.delete_keypair = nullptr;
- }
- if (keymaster0_device && keymaster0_device->delete_all) {
- device_.delete_all = delete_all;
- } else {
- device_.delete_all = nullptr;
- }
- device_.sign_data = sign_data;
- device_.verify_data = verify_data;
+ device_.generate_keypair = nullptr;
+ device_.import_keypair = nullptr;
+ device_.get_keypair_public = nullptr;
+ device_.delete_keypair = nullptr;
+ device_.delete_all = nullptr;
+ device_.sign_data = nullptr;
+ device_.verify_data = nullptr;
// keymaster1 APIs
device_.get_supported_algorithms = get_supported_algorithms;
@@ -175,295 +305,6 @@ int SoftKeymasterDevice::close_device(hw_device_t* dev) {
}
/* static */
-int SoftKeymasterDevice::generate_keypair(const keymaster1_device_t* dev,
- const keymaster_keypair_t key_type,
- const void* key_params, uint8_t** key_blob,
- size_t* key_blob_length) {
- LOG_D("%s", "Device received generate_keypair");
- if (!dev || !key_params)
- return KM_ERROR_UNEXPECTED_NULL_POINTER;
-
- if (!key_blob || !key_blob_length)
- return KM_ERROR_OUTPUT_PARAMETER_NULL;
-
- GenerateKeyRequest req;
-
- switch (key_type) {
- case TYPE_RSA: {
- req.key_description.push_back(TAG_ALGORITHM, KM_ALGORITHM_RSA);
- StoreDefaultNewKeyParams(KM_ALGORITHM_RSA, &req.key_description);
- const keymaster_rsa_keygen_params_t* rsa_params =
- static_cast<const keymaster_rsa_keygen_params_t*>(key_params);
- LOG_D("Generating RSA pair, modulus size: %u, public exponent: %lu",
- rsa_params->modulus_size, rsa_params->public_exponent);
- req.key_description.push_back(TAG_KEY_SIZE, rsa_params->modulus_size);
- req.key_description.push_back(TAG_RSA_PUBLIC_EXPONENT, rsa_params->public_exponent);
- break;
- }
-
- case TYPE_EC: {
- req.key_description.push_back(TAG_ALGORITHM, KM_ALGORITHM_EC);
- StoreDefaultNewKeyParams(KM_ALGORITHM_EC, &req.key_description);
- const keymaster_ec_keygen_params_t* ec_params =
- static_cast<const keymaster_ec_keygen_params_t*>(key_params);
- LOG_D("Generating ECDSA pair, key size: %u", ec_params->field_size);
- req.key_description.push_back(TAG_KEY_SIZE, ec_params->field_size);
- break;
- }
-
- default:
- LOG_D("Received request for unsuported key type %d", key_type);
- return KM_ERROR_UNSUPPORTED_ALGORITHM;
- }
-
- GenerateKeyResponse rsp;
- convert_device(dev)->impl_->GenerateKey(req, &rsp);
- if (rsp.error != KM_ERROR_OK) {
- LOG_E("Key generation failed with error: %d", rsp.error);
- return rsp.error;
- }
-
- *key_blob_length = rsp.key_blob.key_material_size;
- *key_blob = static_cast<uint8_t*>(malloc(*key_blob_length));
- if (!*key_blob) {
- LOG_E("Failed to allocate %d bytes", *key_blob_length);
- return KM_ERROR_MEMORY_ALLOCATION_FAILED;
- }
- memcpy(*key_blob, rsp.key_blob.key_material, *key_blob_length);
- LOG_D("Returning %d bytes in key blob\n", (int)*key_blob_length);
-
- return KM_ERROR_OK;
-}
-
-/* static */
-int SoftKeymasterDevice::import_keypair(const keymaster1_device_t* dev, const uint8_t* key,
- const size_t key_length, uint8_t** key_blob,
- size_t* key_blob_length) {
- LOG_D("Device received import_keypair", 0);
-
- if (!dev || !key)
- return KM_ERROR_UNEXPECTED_NULL_POINTER;
-
- if (!key_blob || !key_blob_length)
- return KM_ERROR_OUTPUT_PARAMETER_NULL;
-
- ImportKeyRequest request;
- keymaster_algorithm_t algorithm;
- keymaster_error_t err = GetPkcs8KeyAlgorithm(key, key_length, &algorithm);
- if (err != KM_ERROR_OK)
- return err;
- request.key_description.push_back(TAG_ALGORITHM, algorithm);
- StoreDefaultNewKeyParams(algorithm, &request.key_description);
- request.SetKeyMaterial(key, key_length);
- request.key_format = KM_KEY_FORMAT_PKCS8;
-
- ImportKeyResponse response;
- convert_device(dev)->impl_->ImportKey(request, &response);
- if (response.error != KM_ERROR_OK) {
- LOG_E("Key import failed with error: %d", response.error);
- return response.error;
- }
-
- *key_blob_length = response.key_blob.key_material_size;
- *key_blob = static_cast<uint8_t*>(malloc(*key_blob_length));
- if (!*key_blob) {
- LOG_E("Failed to allocate %d bytes", *key_blob_length);
- return KM_ERROR_MEMORY_ALLOCATION_FAILED;
- }
- memcpy(*key_blob, response.key_blob.key_material, *key_blob_length);
- LOG_D("Returning %d bytes in key blob\n", (int)*key_blob_length);
-
- return KM_ERROR_OK;
-}
-
-/* static */
-keymaster_error_t SoftKeymasterDevice::GetPkcs8KeyAlgorithm(const uint8_t* key, size_t key_length,
- keymaster_algorithm_t* algorithm) {
- if (key == NULL) {
- LOG_E("No key specified for import", 0);
- return KM_ERROR_UNEXPECTED_NULL_POINTER;
- }
-
- UniquePtr<PKCS8_PRIV_KEY_INFO, PKCS8_PRIV_KEY_INFO_Delete> pkcs8(
- d2i_PKCS8_PRIV_KEY_INFO(NULL, &key, key_length));
- if (pkcs8.get() == NULL) {
- LOG_E("Could not parse PKCS8 key blob", 0);
- return KM_ERROR_INVALID_KEY_BLOB;
- }
-
- UniquePtr<EVP_PKEY, EVP_PKEY_Delete> pkey(EVP_PKCS82PKEY(pkcs8.get()));
- if (pkey.get() == NULL) {
- LOG_E("Could not extract key from PKCS8 key blob", 0);
- return KM_ERROR_INVALID_KEY_BLOB;
- }
-
- switch (EVP_PKEY_type(pkey->type)) {
- case EVP_PKEY_RSA:
- *algorithm = KM_ALGORITHM_RSA;
- break;
- case EVP_PKEY_EC:
- *algorithm = KM_ALGORITHM_EC;
- break;
- default:
- LOG_E("Unsupported algorithm %d", EVP_PKEY_type(pkey->type));
- return KM_ERROR_UNSUPPORTED_ALGORITHM;
- }
-
- return KM_ERROR_OK;
-}
-
-/* static */
-int SoftKeymasterDevice::get_keypair_public(const struct keymaster1_device* dev,
- const uint8_t* key_blob, const size_t key_blob_length,
- uint8_t** x509_data, size_t* x509_data_length) {
- LOG_D("Device received get_keypair_public", 0);
-
- if (!dev || !key_blob)
- return KM_ERROR_UNEXPECTED_NULL_POINTER;
-
- if (!x509_data || !x509_data_length)
- return KM_ERROR_OUTPUT_PARAMETER_NULL;
-
- ExportKeyRequest req;
- req.SetKeyMaterial(key_blob, key_blob_length);
- req.key_format = KM_KEY_FORMAT_X509;
-
- ExportKeyResponse rsp;
- convert_device(dev)->impl_->ExportKey(req, &rsp);
- if (rsp.error != KM_ERROR_OK) {
- LOG_E("get_keypair_public failed with error: %d", rsp.error);
- return rsp.error;
- }
-
- *x509_data_length = rsp.key_data_length;
- *x509_data = static_cast<uint8_t*>(malloc(*x509_data_length));
- if (!*x509_data)
- return KM_ERROR_MEMORY_ALLOCATION_FAILED;
- memcpy(*x509_data, rsp.key_data, *x509_data_length);
- LOG_D("Returning %d bytes in x509 key\n", (int)*x509_data_length);
-
- return KM_ERROR_OK;
-}
-
-/* static */
-int SoftKeymasterDevice::delete_keypair(const struct keymaster1_device* dev,
- const uint8_t* key_blob, const size_t key_blob_length) {
- if (!dev || !dev->delete_keypair) {
- return KM_ERROR_UNEXPECTED_NULL_POINTER;
- }
- return dev->delete_keypair(dev, key_blob, key_blob_length);
-}
-
-/* static */
-int SoftKeymasterDevice::delete_all(const struct keymaster1_device* dev) {
- if (!dev || !dev->delete_all) {
- return KM_ERROR_UNEXPECTED_NULL_POINTER;
- }
- return dev->delete_all(dev);
-}
-
-/* static */
-int SoftKeymasterDevice::sign_data(const keymaster1_device_t* dev, const void* params,
- const uint8_t* key_blob, const size_t key_blob_length,
- const uint8_t* data, const size_t data_length,
- uint8_t** signed_data, size_t* signed_data_length) {
- LOG_D("Device received sign_data", 0);
-
- if (!dev || !params || !key_blob)
- return KM_ERROR_UNEXPECTED_NULL_POINTER;
-
- if (!signed_data || !signed_data_length)
- return KM_ERROR_OUTPUT_PARAMETER_NULL;
-
- *signed_data_length = 0;
-
- BeginOperationRequest begin_request;
- begin_request.purpose = KM_PURPOSE_SIGN;
- begin_request.SetKeyMaterial(key_blob, key_blob_length);
- begin_request.additional_params.push_back(TAG_DIGEST, KM_DIGEST_NONE);
- begin_request.additional_params.push_back(TAG_PADDING, KM_PAD_NONE);
-
- BeginOperationResponse begin_response;
- convert_device(dev)->impl_->BeginOperation(begin_request, &begin_response);
- if (begin_response.error != KM_ERROR_OK) {
- LOG_E("sign_data begin operation failed with error: %d", begin_response.error);
- return begin_response.error;
- }
-
- UpdateOperationRequest update_request;
- update_request.op_handle = begin_response.op_handle;
- update_request.input.Reinitialize(data, data_length);
- UpdateOperationResponse update_response;
- convert_device(dev)->impl_->UpdateOperation(update_request, &update_response);
- if (update_response.error != KM_ERROR_OK) {
- LOG_E("sign_data update operation failed with error: %d", update_response.error);
- return update_response.error;
- }
-
- FinishOperationRequest finish_request;
- finish_request.op_handle = begin_response.op_handle;
- FinishOperationResponse finish_response;
- convert_device(dev)->impl_->FinishOperation(finish_request, &finish_response);
- if (finish_response.error != KM_ERROR_OK) {
- LOG_E("sign_data finish operation failed with error: %d", finish_response.error);
- return finish_response.error;
- }
-
- *signed_data_length = finish_response.output.available_read();
- *signed_data = static_cast<uint8_t*>(malloc(*signed_data_length));
- if (!*signed_data)
- return KM_ERROR_MEMORY_ALLOCATION_FAILED;
- if (!finish_response.output.read(*signed_data, *signed_data_length))
- return KM_ERROR_UNKNOWN_ERROR;
- return KM_ERROR_OK;
-}
-
-/* static */
-int SoftKeymasterDevice::verify_data(const keymaster1_device_t* dev, const void* params,
- const uint8_t* key_blob, const size_t key_blob_length,
- const uint8_t* signed_data, const size_t signed_data_length,
- const uint8_t* signature, const size_t signature_length) {
- LOG_D("Device received verify_data", 0);
-
- if (!dev || !params || !key_blob || !signed_data || !signature)
- return KM_ERROR_UNEXPECTED_NULL_POINTER;
-
- BeginOperationRequest begin_request;
- begin_request.purpose = KM_PURPOSE_VERIFY;
- begin_request.SetKeyMaterial(key_blob, key_blob_length);
- begin_request.additional_params.push_back(TAG_DIGEST, KM_DIGEST_NONE);
- begin_request.additional_params.push_back(TAG_PADDING, KM_PAD_NONE);
-
- BeginOperationResponse begin_response;
- convert_device(dev)->impl_->BeginOperation(begin_request, &begin_response);
- if (begin_response.error != KM_ERROR_OK) {
- LOG_E("verify_data begin operation failed with error: %d", begin_response.error);
- return begin_response.error;
- }
-
- UpdateOperationRequest update_request;
- update_request.op_handle = begin_response.op_handle;
- update_request.input.Reinitialize(signed_data, signed_data_length);
- UpdateOperationResponse update_response;
- convert_device(dev)->impl_->UpdateOperation(update_request, &update_response);
- if (update_response.error != KM_ERROR_OK) {
- LOG_E("verify_data update operation failed with error: %d", update_response.error);
- return update_response.error;
- }
-
- FinishOperationRequest finish_request;
- finish_request.op_handle = begin_response.op_handle;
- finish_request.signature.Reinitialize(signature, signature_length);
- FinishOperationResponse finish_response;
- convert_device(dev)->impl_->FinishOperation(finish_request, &finish_response);
- if (finish_response.error != KM_ERROR_OK) {
- LOG_E("verify_data finish operation failed with error: %d", finish_response.error);
- return finish_response.error;
- }
- return KM_ERROR_OK;
-}
-
-/* static */
keymaster_error_t SoftKeymasterDevice::get_supported_algorithms(const keymaster1_device_t* dev,
keymaster_algorithm_t** algorithms,
size_t* algorithms_length) {
@@ -473,6 +314,10 @@ keymaster_error_t SoftKeymasterDevice::get_supported_algorithms(const keymaster1
if (!algorithms || !algorithms_length)
return KM_ERROR_OUTPUT_PARAMETER_NULL;
+ const keymaster1_device_t* km1_dev = convert_device(dev)->wrapped_km1_device_;
+ if (km1_dev)
+ return km1_dev->get_supported_algorithms(km1_dev, algorithms, algorithms_length);
+
SupportedAlgorithmsRequest request;
SupportedAlgorithmsResponse response;
convert_device(dev)->impl_->SupportedAlgorithms(request, &response);
@@ -503,6 +348,10 @@ keymaster_error_t SoftKeymasterDevice::get_supported_block_modes(const keymaster
if (!modes || !modes_length)
return KM_ERROR_OUTPUT_PARAMETER_NULL;
+ const keymaster1_device_t* km1_dev = convert_device(dev)->wrapped_km1_device_;
+ if (km1_dev)
+ return km1_dev->get_supported_block_modes(km1_dev, algorithm, purpose, modes, modes_length);
+
SupportedBlockModesRequest request;
request.algorithm = algorithm;
request.purpose = purpose;
@@ -535,6 +384,11 @@ keymaster_error_t SoftKeymasterDevice::get_supported_padding_modes(const keymast
if (!modes || !modes_length)
return KM_ERROR_OUTPUT_PARAMETER_NULL;
+ const keymaster1_device_t* km1_dev = convert_device(dev)->wrapped_km1_device_;
+ if (km1_dev)
+ return km1_dev->get_supported_padding_modes(km1_dev, algorithm, purpose, modes,
+ modes_length);
+
SupportedPaddingModesRequest request;
request.algorithm = algorithm;
request.purpose = purpose;
@@ -566,6 +420,10 @@ keymaster_error_t SoftKeymasterDevice::get_supported_digests(const keymaster1_de
if (!digests || !digests_length)
return KM_ERROR_OUTPUT_PARAMETER_NULL;
+ const keymaster1_device_t* km1_dev = convert_device(dev)->wrapped_km1_device_;
+ if (km1_dev)
+ return km1_dev->get_supported_digests(km1_dev, algorithm, purpose, digests, digests_length);
+
SupportedDigestsRequest request;
request.algorithm = algorithm;
request.purpose = purpose;
@@ -595,6 +453,10 @@ keymaster_error_t SoftKeymasterDevice::get_supported_import_formats(
if (!formats || !formats_length)
return KM_ERROR_OUTPUT_PARAMETER_NULL;
+ const keymaster1_device_t* km1_dev = convert_device(dev)->wrapped_km1_device_;
+ if (km1_dev)
+ return km1_dev->get_supported_import_formats(km1_dev, algorithm, formats, formats_length);
+
SupportedImportFormatsRequest request;
request.algorithm = algorithm;
SupportedImportFormatsResponse response;
@@ -624,6 +486,10 @@ keymaster_error_t SoftKeymasterDevice::get_supported_export_formats(
if (!formats || !formats_length)
return KM_ERROR_OUTPUT_PARAMETER_NULL;
+ const keymaster1_device_t* km1_dev = convert_device(dev)->wrapped_km1_device_;
+ if (km1_dev)
+ return km1_dev->get_supported_export_formats(km1_dev, algorithm, formats, formats_length);
+
SupportedExportFormatsRequest request;
request.algorithm = algorithm;
SupportedExportFormatsResponse response;
@@ -649,6 +515,10 @@ keymaster_error_t SoftKeymasterDevice::add_rng_entropy(const keymaster1_device_t
if (!dev)
return KM_ERROR_UNEXPECTED_NULL_POINTER;
+ const keymaster1_device_t* km1_dev = convert_device(dev)->wrapped_km1_device_;
+ if (km1_dev)
+ return km1_dev->add_rng_entropy(km1_dev, data, data_length);
+
AddEntropyRequest request;
request.random_data.Reinitialize(data, data_length);
AddEntropyResponse response;
@@ -658,6 +528,80 @@ keymaster_error_t SoftKeymasterDevice::add_rng_entropy(const keymaster1_device_t
return response.error;
}
+template <typename Collection, typename Value> bool contains(const Collection& c, const Value& v) {
+ return std::find(c.begin(), c.end(), v) != c.end();
+}
+
+bool SoftKeymasterDevice::FindUnsupportedDigest(keymaster_algorithm_t algorithm,
+ keymaster_purpose_t purpose,
+ const AuthorizationSet& params,
+ keymaster_digest_t* unsupported) const {
+ assert(wrapped_km1_device_);
+
+ auto supported_digests = km1_device_digests_.find(std::make_pair(algorithm, purpose));
+ if (supported_digests == km1_device_digests_.end())
+ // Invalid algorith/purpose pair (e.g. EC encrypt). Let the error be handled by HW module.
+ return false;
+
+ for (auto& entry : params)
+ if (entry.tag == TAG_DIGEST)
+ if (!contains(supported_digests->second, entry.enumerated)) {
+ LOG_I("Digest %d requested but not supported by module %s", entry.enumerated,
+ wrapped_km1_device_->common.module->name);
+ *unsupported = static_cast<keymaster_digest_t>(entry.enumerated);
+ return true;
+ }
+ return false;
+}
+
+bool SoftKeymasterDevice::RequiresSoftwareDigesting(keymaster_algorithm_t algorithm,
+ keymaster_purpose_t purpose,
+ const AuthorizationSet& params) const {
+ assert(wrapped_km1_device_);
+ if (!wrapped_km1_device_)
+ return true;
+
+ switch (algorithm) {
+ case KM_ALGORITHM_AES:
+ case KM_ALGORITHM_HMAC:
+ LOG_D("Not performing software digesting for algorithm %d", algorithm);
+ return false;
+ case KM_ALGORITHM_RSA:
+ case KM_ALGORITHM_EC:
+ break;
+ }
+
+ keymaster_digest_t unsupported;
+ if (!FindUnsupportedDigest(algorithm, purpose, params, &unsupported)) {
+ LOG_D("Requested digest(s) supported for algorithm %d and purpose %d", algorithm, purpose);
+ return false;
+ }
+
+ return true;
+}
+
+bool SoftKeymasterDevice::KeyRequiresSoftwareDigesting(
+ const AuthorizationSet& key_description) const {
+ assert(wrapped_km1_device_);
+ if (!wrapped_km1_device_)
+ return true;
+
+ keymaster_algorithm_t algorithm;
+ if (!key_description.GetTagValue(TAG_ALGORITHM, &algorithm)) {
+ // The hardware module will return an error during keygen.
+ return false;
+ }
+
+ for (auto& entry : key_description)
+ if (entry.tag == TAG_PURPOSE) {
+ keymaster_purpose_t purpose = static_cast<keymaster_purpose_t>(entry.enumerated);
+ if (RequiresSoftwareDigesting(algorithm, purpose, key_description))
+ return true;
+ }
+
+ return false;
+}
+
/* static */
keymaster_error_t SoftKeymasterDevice::generate_key(
const keymaster1_device_t* dev, const keymaster_key_param_set_t* params,
@@ -668,11 +612,17 @@ keymaster_error_t SoftKeymasterDevice::generate_key(
if (!key_blob)
return KM_ERROR_OUTPUT_PARAMETER_NULL;
+ SoftKeymasterDevice* sk_dev = convert_device(dev);
+
GenerateKeyRequest request;
request.key_description.Reinitialize(*params);
+ keymaster1_device_t* km1_dev = sk_dev->wrapped_km1_device_;
+ if (km1_dev && !sk_dev->KeyRequiresSoftwareDigesting(request.key_description))
+ return km1_dev->generate_key(km1_dev, params, key_blob, characteristics);
+
GenerateKeyResponse response;
- convert_device(dev)->impl_->GenerateKey(request, &response);
+ sk_dev->impl_->GenerateKey(request, &response);
if (response.error != KM_ERROR_OK)
return response.error;
@@ -703,6 +653,11 @@ keymaster_error_t SoftKeymasterDevice::get_key_characteristics(
if (!characteristics)
return KM_ERROR_OUTPUT_PARAMETER_NULL;
+ const keymaster1_device_t* km1_dev = convert_device(dev)->wrapped_km1_device_;
+ if (km1_dev)
+ return km1_dev->get_key_characteristics(km1_dev, key_blob, client_id, app_data,
+ characteristics);
+
GetKeyCharacteristicsRequest request;
request.SetKeyMaterial(*key_blob);
AddClientAndAppData(client_id, app_data, &request);
@@ -729,10 +684,18 @@ keymaster_error_t SoftKeymasterDevice::import_key(
if (!key_blob)
return KM_ERROR_OUTPUT_PARAMETER_NULL;
- *characteristics = nullptr;
+ SoftKeymasterDevice* sk_dev = convert_device(dev);
ImportKeyRequest request;
request.key_description.Reinitialize(*params);
+
+ keymaster1_device_t* km1_dev = sk_dev->wrapped_km1_device_;
+ if (km1_dev && !sk_dev->KeyRequiresSoftwareDigesting(request.key_description))
+ return km1_dev->import_key(km1_dev, params, key_format, key_data, key_blob,
+ characteristics);
+
+ *characteristics = nullptr;
+
request.key_format = key_format;
request.SetKeyMaterial(key_data->data, key_data->data_length);
@@ -769,6 +732,11 @@ keymaster_error_t SoftKeymasterDevice::export_key(const keymaster1_device_t* dev
if (!export_data)
return KM_ERROR_OUTPUT_PARAMETER_NULL;
+ const keymaster1_device_t* km1_dev = convert_device(dev)->wrapped_km1_device_;
+ if (km1_dev)
+ return km1_dev->export_key(km1_dev, export_format, key_to_export, client_id, app_data,
+ export_data);
+
export_data->data = nullptr;
export_data->data_length = 0;
@@ -797,11 +765,15 @@ keymaster_error_t SoftKeymasterDevice::delete_key(const struct keymaster1_device
if (!dev || !key || !key->key_material)
return KM_ERROR_UNEXPECTED_NULL_POINTER;
- keymaster0_device_t* wrapped = convert_device(dev)->wrapped_device_;
+ const keymaster1_device_t* km1_dev = convert_device(dev)->wrapped_km1_device_;
+ if (km1_dev && km1_dev->delete_key)
+ return km1_dev->delete_key(km1_dev, key);
- if (wrapped && wrapped->delete_keypair)
- if (wrapped->delete_keypair(wrapped, key->key_material, key->key_material_size) < 0)
+ const keymaster0_device_t* km0_dev = convert_device(dev)->wrapped_km0_device_;
+ if (km0_dev && km0_dev->delete_keypair)
+ if (km0_dev->delete_keypair(km0_dev, key->key_material, key->key_material_size) < 0)
return KM_ERROR_UNKNOWN_ERROR;
+
return KM_ERROR_OK;
}
@@ -810,14 +782,58 @@ keymaster_error_t SoftKeymasterDevice::delete_all_keys(const struct keymaster1_d
if (!dev)
return KM_ERROR_UNEXPECTED_NULL_POINTER;
- keymaster0_device_t* wrapped = convert_device(dev)->wrapped_device_;
+ const keymaster1_device_t* km1_dev = convert_device(dev)->wrapped_km1_device_;
+ if (km1_dev && km1_dev->delete_all_keys)
+ return km1_dev->delete_all_keys(km1_dev);
- if (wrapped && wrapped->delete_all)
- if (wrapped->delete_all(wrapped) < 0)
+ const keymaster0_device_t* km0_dev = convert_device(dev)->wrapped_km0_device_;
+ if (km0_dev && km0_dev->delete_all)
+ if (km0_dev->delete_all(km0_dev) < 0)
return KM_ERROR_UNKNOWN_ERROR;
+
return KM_ERROR_OK;
}
+static bool FindAlgorithm(const keymaster_key_param_set_t& params,
+ keymaster_algorithm_t* algorithm) {
+ for (size_t i = 0; i < params.length; ++i)
+ if (params.params[i].tag == KM_TAG_ALGORITHM) {
+ *algorithm = static_cast<keymaster_algorithm_t>(params.params[i].enumerated);
+ return true;
+ }
+ return false;
+}
+
+static keymaster_error_t GetAlgorithm(const keymaster1_device_t* dev,
+ const keymaster_key_blob_t& key,
+ const AuthorizationSet& in_params,
+ keymaster_algorithm_t* algorithm) {
+ keymaster_blob_t client_id = {nullptr, 0};
+ keymaster_blob_t app_data = {nullptr, 0};
+ keymaster_blob_t* client_id_ptr = nullptr;
+ keymaster_blob_t* app_data_ptr = nullptr;
+ if (in_params.GetTagValue(TAG_APPLICATION_ID, &client_id))
+ client_id_ptr = &client_id;
+ if (in_params.GetTagValue(TAG_APPLICATION_DATA, &app_data))
+ app_data_ptr = &app_data;
+
+ keymaster_key_characteristics_t* characteristics;
+ keymaster_error_t error =
+ dev->get_key_characteristics(dev, &key, client_id_ptr, app_data_ptr, &characteristics);
+ if (error != KM_ERROR_OK)
+ return error;
+ std::unique_ptr<keymaster_key_characteristics_t, Characteristics_Delete>
+ characteristics_deleter(characteristics);
+
+ if (FindAlgorithm(characteristics->hw_enforced, algorithm))
+ return KM_ERROR_OK;
+
+ if (FindAlgorithm(characteristics->sw_enforced, algorithm))
+ return KM_ERROR_OK;
+
+ return KM_ERROR_INVALID_KEY_BLOB;
+}
+
/* static */
keymaster_error_t SoftKeymasterDevice::begin(const keymaster1_device_t* dev,
keymaster_purpose_t purpose,
@@ -828,11 +844,30 @@ keymaster_error_t SoftKeymasterDevice::begin(const keymaster1_device_t* dev,
if (!key || !key->key_material)
return KM_ERROR_UNEXPECTED_NULL_POINTER;
- if (!operation_handle || !out_params)
+ if (!operation_handle)
return KM_ERROR_OUTPUT_PARAMETER_NULL;
- out_params->params = nullptr;
- out_params->length = 0;
+ const keymaster1_device_t* km1_dev = convert_device(dev)->wrapped_km1_device_;
+ if (km1_dev) {
+ AuthorizationSet in_params_set(*in_params);
+
+ keymaster_algorithm_t algorithm = KM_ALGORITHM_AES;
+ keymaster_error_t error = GetAlgorithm(km1_dev, *key, in_params_set, &algorithm);
+ if (error != KM_ERROR_OK)
+ return error;
+
+ if (!convert_device(dev)->RequiresSoftwareDigesting(algorithm, purpose, in_params_set)) {
+ LOG_D("Operation supported by %s, passing through to keymaster1 module",
+ km1_dev->common.module->name);
+ return km1_dev->begin(km1_dev, purpose, key, in_params, out_params, operation_handle);
+ }
+ LOG_I("Doing software digesting for keymaster1 module %s", km1_dev->common.module->name);
+ }
+
+ if (out_params) {
+ out_params->params = nullptr;
+ out_params->length = 0;
+ }
BeginOperationRequest request;
request.purpose = purpose;
@@ -844,8 +879,12 @@ keymaster_error_t SoftKeymasterDevice::begin(const keymaster1_device_t* dev,
if (response.error != KM_ERROR_OK)
return response.error;
- if (response.output_params.size() > 0)
- response.output_params.CopyToParamSet(out_params);
+ if (response.output_params.size() > 0) {
+ if (out_params)
+ response.output_params.CopyToParamSet(out_params);
+ else
+ return KM_ERROR_OUTPUT_PARAMETER_NULL;
+ }
*operation_handle = response.op_handle;
return KM_ERROR_OK;
@@ -861,13 +900,26 @@ keymaster_error_t SoftKeymasterDevice::update(const keymaster1_device_t* dev,
if (!input)
return KM_ERROR_UNEXPECTED_NULL_POINTER;
- if (!input_consumed || !output || !out_params)
+ if (!input_consumed)
return KM_ERROR_OUTPUT_PARAMETER_NULL;
- out_params->params = nullptr;
- out_params->length = 0;
- output->data = nullptr;
- output->data_length = 0;
+ const keymaster1_device_t* km1_dev = convert_device(dev)->wrapped_km1_device_;
+ if (km1_dev && !convert_device(dev)->impl_->has_operation(operation_handle)) {
+ // This operation is being handled by km1_dev (or doesn't exist). Pass it through to
+ // km1_dev. Otherwise, we'll use the software AndroidKeymaster, which may delegate to
+ // km1_dev after doing necessary digesting.
+ return km1_dev->update(km1_dev, operation_handle, in_params, input, input_consumed,
+ out_params, output);
+ }
+
+ if (out_params) {
+ out_params->params = nullptr;
+ out_params->length = 0;
+ }
+ if (output) {
+ output->data = nullptr;
+ output->data_length = 0;
+ }
UpdateOperationRequest request;
request.op_handle = operation_handle;
@@ -881,16 +933,24 @@ keymaster_error_t SoftKeymasterDevice::update(const keymaster1_device_t* dev,
if (response.error != KM_ERROR_OK)
return response.error;
- if (response.output_params.size() > 0)
- response.output_params.CopyToParamSet(out_params);
+ if (response.output_params.size() > 0) {
+ if (out_params)
+ response.output_params.CopyToParamSet(out_params);
+ else
+ return KM_ERROR_OUTPUT_PARAMETER_NULL;
+ }
*input_consumed = response.input_consumed;
- output->data_length = response.output.available_read();
- uint8_t* tmp = reinterpret_cast<uint8_t*>(malloc(output->data_length));
- if (!tmp)
- return KM_ERROR_MEMORY_ALLOCATION_FAILED;
- memcpy(tmp, response.output.peek_read(), output->data_length);
- output->data = tmp;
+ if (output) {
+ output->data_length = response.output.available_read();
+ uint8_t* tmp = reinterpret_cast<uint8_t*>(malloc(output->data_length));
+ if (!tmp)
+ return KM_ERROR_MEMORY_ALLOCATION_FAILED;
+ memcpy(tmp, response.output.peek_read(), output->data_length);
+ output->data = tmp;
+ } else if (response.output.available_read() > 0) {
+ return KM_ERROR_OUTPUT_PARAMETER_NULL;
+ }
return KM_ERROR_OK;
}
@@ -901,17 +961,27 @@ keymaster_error_t SoftKeymasterDevice::finish(const keymaster1_device_t* dev,
const keymaster_blob_t* signature,
keymaster_key_param_set_t* out_params,
keymaster_blob_t* output) {
- if (!output || !out_params)
- return KM_ERROR_OUTPUT_PARAMETER_NULL;
+ const keymaster1_device_t* km1_dev = convert_device(dev)->wrapped_km1_device_;
+ if (km1_dev && !convert_device(dev)->impl_->has_operation(operation_handle)) {
+ // This operation is being handled by km1_dev (or doesn't exist). Pass it through to
+ // km1_dev. Otherwise, we'll use the software AndroidKeymaster, which may delegate to
+ // km1_dev after doing necessary digesting.
+ return km1_dev->finish(km1_dev, operation_handle, params, signature, out_params, output);
+ }
+
+ if (out_params) {
+ out_params->params = nullptr;
+ out_params->length = 0;
+ }
- out_params->params = nullptr;
- out_params->length = 0;
- output->data = nullptr;
- output->data_length = 0;
+ if (output) {
+ output->data = nullptr;
+ output->data_length = 0;
+ }
FinishOperationRequest request;
request.op_handle = operation_handle;
- if (signature)
+ if (signature && signature->data_length > 0)
request.signature.Reinitialize(signature->data, signature->data_length);
request.additional_params.Reinitialize(*params);
@@ -920,22 +990,37 @@ keymaster_error_t SoftKeymasterDevice::finish(const keymaster1_device_t* dev,
if (response.error != KM_ERROR_OK)
return response.error;
- if (response.output_params.size() > 0)
- response.output_params.CopyToParamSet(out_params);
- else
-
+ if (response.output_params.size() > 0) {
+ if (out_params)
+ response.output_params.CopyToParamSet(out_params);
+ else
+ return KM_ERROR_OUTPUT_PARAMETER_NULL;
+ }
+ if (output) {
output->data_length = response.output.available_read();
- uint8_t* tmp = reinterpret_cast<uint8_t*>(malloc(output->data_length));
- if (!tmp)
- return KM_ERROR_MEMORY_ALLOCATION_FAILED;
- memcpy(tmp, response.output.peek_read(), output->data_length);
- output->data = tmp;
+ uint8_t* tmp = reinterpret_cast<uint8_t*>(malloc(output->data_length));
+ if (!tmp)
+ return KM_ERROR_MEMORY_ALLOCATION_FAILED;
+ memcpy(tmp, response.output.peek_read(), output->data_length);
+ output->data = tmp;
+ } else if (response.output.available_read() > 0) {
+ return KM_ERROR_OUTPUT_PARAMETER_NULL;
+ }
+
return KM_ERROR_OK;
}
/* static */
keymaster_error_t SoftKeymasterDevice::abort(const keymaster1_device_t* dev,
keymaster_operation_handle_t operation_handle) {
+ const keymaster1_device_t* km1_dev = convert_device(dev)->wrapped_km1_device_;
+ if (km1_dev && !convert_device(dev)->impl_->has_operation(operation_handle)) {
+ // This operation is being handled by km1_dev (or doesn't exist). Pass it through to
+ // km1_dev. Otherwise, we'll use the software AndroidKeymaster, which may delegate to
+ // km1_dev.
+ return km1_dev->abort(km1_dev, operation_handle);
+ }
+
AbortOperationRequest request;
request.op_handle = operation_handle;
AbortOperationResponse response;