diff options
author | Ricardo Cerqueira <ricardo@cyngn.com> | 2015-11-05 03:17:19 +0000 |
---|---|---|
committer | Ricardo Cerqueira <ricardo@cyngn.com> | 2015-11-05 03:17:24 +0000 |
commit | 18b04441a40a728bf0b7578d89ff7603b7b21f44 (patch) | |
tree | 430089cdf7fc7c26a6610e53e6b553d9e88505e3 | |
parent | b0f457efa768e7ae6b394a29a02e2fe56d5b4788 (diff) | |
parent | d8544338989c53f52f45d05e1d9e46df34e29b03 (diff) | |
download | android_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
49 files changed, 3083 insertions, 847 deletions
@@ -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 @@ -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 { @@ -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]; @@ -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 { @@ -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 @@ -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; |