Snap for 6199579 from 2b06348d8ff10896b859f6fe13f1a4e396dccf79 to rvc-release am: 41b4eeeafb
Original change: https://googleplex-android-review.googlesource.com/c/platform/system/keymaster/+/10303038
Change-Id: I88aef5e5a87e24928e5ec6ea18332b198a39b725
diff --git a/Android.bp b/Android.bp
index e0bcd41..b56af0f 100644
--- a/Android.bp
+++ b/Android.bp
@@ -14,6 +14,37 @@
// libkeymaster_messages contains just the code necessary to communicate with a
// AndroidKeymaster implementation, e.g. one running in TrustZone.
+package {
+ default_applicable_licenses: ["system_keymaster_license"],
+}
+
+// Added automatically by a large-scale-change that took the approach of
+// 'apply every license found to every target'. While this makes sure we respect
+// every license restriction, it may not be entirely correct.
+//
+// e.g. GPL in an MIT project might only apply to the contrib/ directory.
+//
+// Please consider splitting the single license below into multiple licenses,
+// taking care not to lose any license_kind information, and overriding the
+// default license using the 'licenses: [...]' property on targets as needed.
+//
+// For unused files, consider creating a 'fileGroup' with "//visibility:private"
+// to attach the license to, and including a comment whether the files may be
+// used in the current project.
+// See: http://go/android-license-faq
+license {
+ name: "system_keymaster_license",
+ visibility: [":__subpackages__"],
+ license_kinds: [
+ "SPDX-license-identifier-Apache-2.0",
+ "SPDX-license-identifier-ISC",
+ "legacy_unencumbered",
+ ],
+ license_text: [
+ "NOTICE",
+ ],
+}
+
cc_defaults {
name: "keymaster_defaults",
vendor_available: true,
@@ -31,6 +62,10 @@
// Currently, if enabled, these flags will cause an internal error in Clang.
"-fno-sanitize-coverage=edge,indirect-calls,8bit-counters,trace-cmp"
],
+ tidy: true,
+ tidy_checks: [
+ "-performance-noexcept-move-constructor",
+ ],
sanitize: {
integer_overflow: false,
},
@@ -45,15 +80,21 @@
"android_keymaster/keymaster_tags.cpp",
"android_keymaster/logger.cpp",
"android_keymaster/serializable.cpp",
- "android_keymaster/keymaster_stl.cpp",
],
header_libs: ["libhardware_headers"],
defaults: ["keymaster_defaults" ],
clang_cflags: [
"-DKEYMASTER_NAME_TAGS",
],
- stl: "none",
export_include_dirs: ["include"],
+ host_supported: true,
+ target: {
+ host: {
+ clang_cflags: [
+ "-fno-rtti", // TODO(b/156427382): Remove workaround when possible.
+ ],
+ },
+ },
}
// libkeymaster_portable contains almost everything needed for a keymaster
@@ -68,11 +109,12 @@
"android_keymaster/android_keymaster_utils.cpp",
"android_keymaster/authorization_set.cpp",
"android_keymaster/keymaster_enforcement.cpp",
- "android_keymaster/keymaster_stl.cpp",
"android_keymaster/keymaster_tags.cpp",
"android_keymaster/logger.cpp",
"android_keymaster/operation.cpp",
"android_keymaster/operation_table.cpp",
+ "android_keymaster/pure_soft_secure_key_storage.cpp",
+ "android_keymaster/remote_provisioning_utils.cpp",
"android_keymaster/serializable.cpp",
"key_blob_utils/auth_encrypted_key_blob.cpp",
"key_blob_utils/integrity_assured_key_blob.cpp",
@@ -86,9 +128,11 @@
"km_openssl/attestation_record.cpp",
"km_openssl/attestation_utils.cpp",
"km_openssl/block_cipher_operation.cpp",
+ "km_openssl/certificate_utils.cpp",
"km_openssl/ckdf.cpp",
"km_openssl/ec_key.cpp",
"km_openssl/ec_key_factory.cpp",
+ "km_openssl/ecdh_operation.cpp",
"km_openssl/ecdsa_operation.cpp",
"km_openssl/ecies_kem.cpp",
"km_openssl/hkdf.cpp",
@@ -112,19 +156,22 @@
shared_libs: [
"libcrypto",
+ "libcppbor_external",
+ "libcppcose_rkp",
],
+ export_shared_lib_headers: ["libcppbor_external"],
header_libs: ["libhardware_headers"],
export_header_lib_headers: ["libhardware_headers"],
defaults: ["keymaster_defaults" ],
- cflags: [
- "-DBORINGSSL_NO_CXX",
- ],
- // NOTE: libkeymaster_portable must run unchanged in the trusty runtime environment.
- // Therefore, it must not link against any c++ stl library. keymaster_stl.cpp
- // weakly defines the subset of stl symbols required for this library to work
- // and which are also available in the trusty context.
- stl: "none",
+ host_supported: true,
export_include_dirs: ["include"],
+ target: {
+ host: {
+ clang_cflags: [
+ "-fno-rtti", // TODO(b/156427382): Remove workaround when possible.
+ ],
+ },
+ },
}
// libsoftkeymaster provides a software-based keymaster HAL implementation.
@@ -134,28 +181,29 @@
name: "libsoftkeymasterdevice",
srcs: [
"android_keymaster/keymaster_configuration.cpp",
- "legacy_support/ec_keymaster0_key.cpp",
+ "contexts/pure_soft_keymaster_context.cpp",
+ "contexts/pure_soft_remote_provisioning_context.cpp",
+ "contexts/soft_attestation_context.cpp",
+ "contexts/soft_keymaster_context.cpp",
+ "contexts/soft_keymaster_device.cpp",
+ "contexts/soft_keymaster_logger.cpp",
+ "km_openssl/soft_keymaster_enforcement.cpp",
"legacy_support/ec_keymaster1_key.cpp",
"legacy_support/ecdsa_keymaster1_operation.cpp",
- "legacy_support/keymaster0_engine.cpp",
"legacy_support/keymaster1_engine.cpp",
- "legacy_support/rsa_keymaster0_key.cpp",
+ "legacy_support/keymaster1_legacy_support.cpp",
"legacy_support/rsa_keymaster1_key.cpp",
"legacy_support/rsa_keymaster1_operation.cpp",
- "legacy_support/keymaster1_legacy_support.cpp",
- "contexts/soft_attestation_cert.cpp",
- "contexts/soft_keymaster_context.cpp",
- "contexts/pure_soft_keymaster_context.cpp",
- "contexts/soft_keymaster_device.cpp",
- "km_openssl/soft_keymaster_enforcement.cpp",
- "contexts/soft_keymaster_logger.cpp",
],
defaults: ["keymaster_defaults"],
shared_libs: [
"libkeymaster_messages",
"libkeymaster_portable",
+ "libsoft_attestation_cert",
"liblog",
"libbase",
+ "libcppbor_external",
+ "libcppcose_rkp",
"libcrypto",
"libcutils",
],
@@ -163,11 +211,26 @@
}
cc_library {
+ name: "libsoft_attestation_cert",
+ srcs: [
+ "contexts/soft_attestation_cert.cpp",
+ ],
+ defaults: ["keymaster_defaults"],
+ shared_libs: [
+ "libkeymaster_portable",
+ ],
+
+ host_supported: true,
+ export_include_dirs: ["include"],
+}
+
+cc_library {
name: "libpuresoftkeymasterdevice",
srcs: [
"android_keymaster/keymaster_configuration.cpp",
- "contexts/soft_attestation_cert.cpp",
+ "contexts/soft_attestation_context.cpp",
"contexts/pure_soft_keymaster_context.cpp",
+ "contexts/pure_soft_remote_provisioning_context.cpp",
"contexts/soft_keymaster_logger.cpp",
"km_openssl/soft_keymaster_enforcement.cpp",
],
@@ -175,12 +238,44 @@
shared_libs: [
"libkeymaster_messages",
"libkeymaster_portable",
+ "libsoft_attestation_cert",
"liblog",
+ "libcppbor_external",
+ "libcppcose_rkp",
"libcrypto",
"libcutils",
"libbase",
],
+ export_include_dirs: ["include"],
+}
+cc_library {
+ name: "libpuresoftkeymasterdevice_host",
+ srcs: [
+ "contexts/pure_soft_keymaster_context.cpp",
+ "contexts/pure_soft_remote_provisioning_context.cpp",
+ "contexts/soft_attestation_context.cpp",
+ "contexts/soft_keymaster_logger.cpp",
+ "km_openssl/soft_keymaster_enforcement.cpp",
+ ],
+ defaults: ["keymaster_defaults"],
+ host_supported: true,
+ device_supported: false,
+ shared_libs: [
+ "libkeymaster_messages",
+ "libkeymaster_portable",
+ "libsoft_attestation_cert",
+ "liblog",
+ "libcppbor_external",
+ "libcppcose_rkp",
+ "libcrypto",
+ "libcutils",
+ "libbase",
+ ],
+ clang_cflags: [
+ "-DKEYMASTER_NAME_TAGS",
+ "-fno-rtti", // TODO(b/156427382): Remove workaround when possible.
+ ],
export_include_dirs: ["include"],
}
@@ -194,13 +289,10 @@
"contexts/keymaster2_passthrough_context.cpp",
"ng/AndroidKeymaster3Device.cpp",
"android_keymaster/keymaster_configuration.cpp",
- "legacy_support/ec_keymaster0_key.cpp",
"legacy_support/ec_keymaster1_key.cpp",
"legacy_support/ecdsa_keymaster1_operation.cpp",
- "legacy_support/keymaster0_engine.cpp",
"legacy_support/keymaster1_engine.cpp",
"legacy_support/keymaster1_legacy_support.cpp",
- "legacy_support/rsa_keymaster0_key.cpp",
"legacy_support/rsa_keymaster1_key.cpp",
"legacy_support/rsa_keymaster1_operation.cpp",
],
@@ -213,8 +305,9 @@
"libbase",
"libhidlbase",
"libkeymaster_portable",
- "libpuresoftkeymasterdevice",
"liblog",
+ "libpuresoftkeymasterdevice",
+ "libsoft_attestation_cert",
"libutils",
],
export_include_dirs: ["include", "ng/include"],
@@ -243,7 +336,10 @@
"libutils",
"libkeymaster4support",
],
- export_include_dirs: ["ng/include"],
+ export_include_dirs: [
+ "ng/include",
+ "include"
+ ],
}
cc_library_shared {
@@ -272,11 +368,114 @@
export_include_dirs: ["ng/include"],
}
-// libkeymasterfiles is an empty library that exports all of the files in keymaster as includes.
-cc_library_static {
- name: "libkeymasterfiles",
+cc_library {
+ name: "lib_android_keymaster_keymint_utils",
+ vendor_available: true,
+ srcs: [
+ "ng/KeyMintUtils.cpp",
+ ],
+ defaults: ["keymaster_defaults"],
+ shared_libs: [
+ "android.hardware.security.keymint-V1-ndk_platform",
+ "libbase",
+ "libhardware",
+ ],
export_include_dirs: [
- ".",
+ "ng/include",
"include",
],
}
+
+cc_library {
+ name: "libkeymint",
+ vendor_available: true,
+ srcs: [
+ "android_keymaster/keymaster_configuration.cpp",
+ "legacy_support/keymaster_passthrough_engine.cpp",
+ "legacy_support/keymaster_passthrough_key.cpp",
+ "legacy_support/keymaster_passthrough_operation.cpp",
+ "ng/AndroidKeyMintDevice.cpp",
+ "ng/AndroidKeyMintOperation.cpp",
+ "ng/AndroidRemotelyProvisionedComponentDevice.cpp",
+ "ng/AndroidSharedSecret.cpp",
+ "ng/AndroidSecureClock.cpp",
+ ],
+ defaults: ["keymaster_defaults"],
+ shared_libs: [
+ "libhidlbase",
+ "android.hardware.security.keymint-V1-ndk_platform",
+ "android.hardware.security.secureclock-V1-ndk_platform",
+ "android.hardware.security.sharedsecret-V1-ndk_platform",
+ "lib_android_keymaster_keymint_utils",
+ "libbase",
+ "libbinder_ndk",
+ "libcppbor_external",
+ "libcrypto",
+ "libcutils",
+ "libkeymaster_messages",
+ "libkeymaster_portable",
+ "liblog",
+ "libpuresoftkeymasterdevice",
+ "libutils",
+ ],
+ export_include_dirs: ["include", "ng/include"],
+}
+
+cc_library {
+ name: "libcppcose_rkp",
+ vendor_available: true,
+ host_supported: true,
+ srcs: [
+ "cppcose/cppcose.cpp",
+ ],
+ export_include_dirs: [
+ "include",
+ ],
+ shared_libs: [
+ "libcppbor_external",
+ "libcrypto",
+ "liblog",
+ ],
+}
+
+cc_defaults {
+ name: "keymaster_fuzz_defaults",
+ header_libs: ["libhardware_headers"],
+ shared_libs: [
+ "libkeymaster_messages",
+ ],
+ // Not using defaults because the fuzzer relies on sanitizers that are explicitly disabled there.
+ cflags: [
+ "-Wall",
+ "-Werror",
+ "-Wunused",
+ "-Wno-error=unused-const-variable",
+ "-Wno-error=unused-private-field",
+ "-Wimplicit-fallthrough",
+ "-DKEYMASTER_NAME_TAGS",
+ ],
+ host_supported: true,
+ target: {
+ host: {
+ clang_cflags: [
+ "-fno-rtti", // TODO(b/156427382): Remove when default library removes this
+ ],
+ },
+ },
+}
+
+cc_fuzz {
+ name: "libkeymaster_fuzz_buffer",
+ defaults: ["keymaster_fuzz_defaults"],
+ srcs: [
+ "tests/fuzzers/buffer_fuzz.cpp",
+ ],
+}
+
+cc_fuzz {
+ name: "libkeymaster_fuzz_serializable",
+ defaults: ["keymaster_fuzz_defaults"],
+ srcs: [
+ "tests/fuzzers/message_serializable_fuzz.cpp",
+ ],
+}
diff --git a/METADATA b/METADATA
new file mode 100644
index 0000000..d97975c
--- /dev/null
+++ b/METADATA
@@ -0,0 +1,3 @@
+third_party {
+ license_type: NOTICE
+}
diff --git a/Makefile b/Makefile
deleted file mode 100644
index fdb11ac..0000000
--- a/Makefile
+++ /dev/null
@@ -1,441 +0,0 @@
-#####
-# Local unit test Makefile
-#
-# This makefile builds and runs the keymaster unit tests locally on the development
-# machine, not on an Android device. Android.mk builds the same tests into the
-# "keymaster_tests" binary for execution on-device, but this Makefile runs them locally,
-# for a very fast edit/build/test development cycle.
-#
-# To build and run these tests, one pre-requisite must be manually installed: BoringSSL.
-# This Makefile expects to find BoringSSL in a directory adjacent to $ANDROID_BUILD_TOP.
-# To get and build it, first install the Ninja build tool (e.g. apt-get install
-# ninja-build), then do:
-#
-# cd $ANDROID_BUILD_TOP/..
-# git clone https://boringssl.googlesource.com/boringssl
-# cd boringssl
-# mdkir build
-# cd build
-# cmake -GNinja ..
-# ninja
-#
-# Then return to $ANDROID_BUILD_TOP/system/keymaster and run "make".
-#####
-
-BASE=../..
-SUBS=system/core \
- hardware/libhardware \
- external/gtest \
- system/security/softkeymaster \
- system/security/keystore
-GTEST=$(BASE)/external/googletest/googletest
-
-INCLUDES=$(foreach dir,$(SUBS),-I $(BASE)/$(dir)/include) \
- -I $(BASE)/libnativehelper/include/nativehelper \
- -I $(GTEST)/include -isystem $(GTEST) -Iinclude -I$(BASE)/../boringssl/include
-
-ifdef FORCE_32_BIT
-ARCH_FLAGS = -m32
-endif
-
-ifdef USE_GCC
-CXXFLAGS +=-std=c++14 -fprofile-arcs -ftest-coverage
-CFLAGS += -fprofile-arcs -ftest-coverage
-else
-CC=$(BASE)/prebuilts/clang/host/linux-x86/clang-r370808/bin/clang
-CXX=$(BASE)/prebuilts/clang/host/linux-x86/clang-r370808/bin/clang++
-CXXFLAGS +=-std=c++14 -DKEYMASTER_CLANG_TEST_BUILD
-CFLAGS += -DKEYMASTER_CLANG_TEST_BUILD
-endif
-
-LDFLAGS += $(ARCH_FLAGS)
-CPPFLAGS = $(INCLUDES) -g -O0 -MD -MP $(ARCH_FLAGS) -DKEYMASTER_UNIT_TEST_BUILD -DHOST_BUILD
-CXXFLAGS += -Wall -Werror -Wno-unused -Winit-self -Wpointer-arith -Wunused-parameter \
- -Werror=sign-compare -Werror=return-type -fno-permissive \
- -Wno-deprecated-declarations -fno-exceptions -DKEYMASTER_NAME_TAGS $(ARCH_FLAGS)
-CFLAGS += $(ARCH_FLAGS) -DKEYMASTER_UNIT_TEST_BUILD -DHOST_BUILD
-
-# Uncomment to enable debug logging.
-# CXXFLAGS += -DDEBUG
-
-LDLIBS=-L$(BASE)/../boringssl/build/crypto -lcrypto -lpthread -lstdc++ -lgcov
-
-CPPSRCS=\
- km_openssl/aes_key.cpp \
- km_openssl/aes_operation.cpp \
- km_openssl/triple_des_key.cpp \
- km_openssl/triple_des_operation.cpp \
- android_keymaster/android_keymaster.cpp \
- android_keymaster/android_keymaster_messages.cpp \
- tests/android_keymaster_messages_test.cpp \
- tests/android_keymaster_test.cpp \
- tests/android_keymaster_test_utils.cpp \
- android_keymaster/android_keymaster_utils.cpp \
- km_openssl/asymmetric_key.cpp \
- km_openssl/asymmetric_key_factory.cpp \
- km_openssl/attestation_record.cpp \
- km_openssl/block_cipher_operation.cpp \
- tests/attestation_record_test.cpp \
- key_blob_utils/auth_encrypted_key_blob.cpp \
- android_keymaster/authorization_set.cpp \
- tests/authorization_set_test.cpp \
- km_openssl/ec_key.cpp \
- km_openssl/ec_key_factory.cpp \
- legacy_support/ec_keymaster0_key.cpp \
- legacy_support/ec_keymaster1_key.cpp \
- legacy_support/ecdsa_keymaster1_operation.cpp \
- km_openssl/ecdsa_operation.cpp \
- km_openssl/ecies_kem.cpp \
- tests/ecies_kem_test.cpp \
- tests/gtest_main.cpp \
- km_openssl/ckdf.cpp \
- tests/hkdf_test.cpp \
- km_openssl/hkdf.cpp \
- tests/hkdf_test.cpp \
- km_openssl/hmac.cpp \
- km_openssl/hmac_key.cpp \
- km_openssl/hmac_operation.cpp \
- tests/hmac_test.cpp \
- key_blob_utils/integrity_assured_key_blob.cpp \
- km_openssl/iso18033kdf.cpp \
- km_openssl/kdf.cpp \
- tests/kdf1_test.cpp \
- tests/kdf2_test.cpp \
- tests/kdf_test.cpp \
- tests/key_blob_test.cpp \
- legacy_support/keymaster0_engine.cpp \
- legacy_support/keymaster1_engine.cpp \
- android_keymaster/keymaster_configuration.cpp \
- tests/keymaster_configuration_test.cpp \
- android_keymaster/keymaster_enforcement.cpp \
- km_openssl/soft_keymaster_enforcement.cpp \
- tests/keymaster_enforcement_test.cpp \
- android_keymaster/keymaster_tags.cpp \
- android_keymaster/logger.cpp \
- km_openssl/nist_curve_key_exchange.cpp \
- tests/nist_curve_key_exchange_test.cpp \
- key_blob_utils/ocb_utils.cpp \
- km_openssl/openssl_err.cpp \
- km_openssl/openssl_utils.cpp \
- android_keymaster/operation.cpp \
- android_keymaster/operation_table.cpp \
- km_openssl/rsa_key.cpp \
- km_openssl/rsa_key_factory.cpp \
- legacy_support/rsa_keymaster0_key.cpp \
- legacy_support/rsa_keymaster1_key.cpp \
- legacy_support/rsa_keymaster1_operation.cpp \
- km_openssl/rsa_operation.cpp \
- android_keymaster/serializable.cpp \
- contexts/soft_keymaster_context.cpp \
- contexts/soft_keymaster_device.cpp \
- contexts/pure_soft_keymaster_context.cpp \
- km_openssl/symmetric_key.cpp \
- km_openssl/software_random_source.cpp \
- contexts/soft_attestation_cert.cpp \
- km_openssl/attestation_utils.cpp \
- key_blob_utils/software_keyblobs.cpp \
- km_openssl/wrapped_key.cpp
-
-CCSRCS=$(GTEST)/src/gtest-all.cc
-CSRCS=key_blob_utils/ocb.c
-
-OBJS=$(CPPSRCS:.cpp=.o) $(CCSRCS:.cc=.o) $(CSRCS:.c=.o)
-DEPS=$(CPPSRCS:.cpp=.d) $(CCSRCS:.cc=.d) $(CSRCS:.c=.d)
-
-BINARIES = \
- tests/android_keymaster_messages_test \
- tests/android_keymaster_test \
- tests/attestation_record_test \
- tests/authorization_set_test \
- tests/ecies_kem_test \
- tests/ckdf_test \
- tests/hkdf_test \
- tests/hmac_test \
- tests/kdf1_test \
- tests/kdf2_test \
- tests/kdf_test \
- tests/key_blob_test \
- tests/keymaster_configuration_test \
- tests/keymaster_enforcement_test \
- tests/nist_curve_key_exchange_test
-
-.PHONY: coverage memcheck massif clean run
-
-%.run: %
- ./$<
- touch $@
-
-run: $(BINARIES:=.run)
-
-coverage: coverage.info
- genhtml coverage.info --output-directory coverage
-
-coverage.info: run
- lcov --capture --directory=. --output-file coverage.info
-
-%.coverage : %
- $(MAKE) clean && $(MAKE) $<
- ./$<
- lcov --capture --directory=. --output-file coverage.info
- genhtml coverage.info --output-directory coverage
-
-#UNINIT_OPTS=--track-origins=yes
-UNINIT_OPTS=--undef-value-errors=no
-
-MEMCHECK_OPTS=--leak-check=full \
- --show-reachable=yes \
- --vgdb=full \
- $(UNINIT_OPTS) \
- --error-exitcode=1 \
- --suppressions=valgrind.supp \
- --gen-suppressions=all
-
-MASSIF_OPTS=--tool=massif \
- --stacks=yes
-
-%.memcheck : %
- valgrind $(MEMCHECK_OPTS) ./$< && \
- touch $@
-
-%.massif : %
- valgrind $(MASSIF_OPTS) --massif-out-file=$@ ./$<
-
-memcheck: $(BINARIES:=.memcheck)
-
-massif: $(BINARIES:=.massif)
-
-GTEST_OBJS = $(GTEST)/src/gtest-all.o tests/gtest_main.o
-
-tests/keymaster_configuration_test: tests/keymaster_configuration_test.o \
- android_keymaster/authorization_set.o \
- android_keymaster/serializable.o \
- android_keymaster/logger.o \
- android_keymaster/keymaster_configuration.o \
- $(GTEST_OBJS)
-
-tests/hmac_test: tests/hmac_test.o \
- tests/android_keymaster_test_utils.o \
- android_keymaster/android_keymaster_utils.o \
- android_keymaster/authorization_set.o \
- km_openssl/hmac.o \
- android_keymaster/keymaster_tags.o \
- android_keymaster/logger.o \
- android_keymaster/serializable.o \
- $(GTEST_OBJS)
-
-tests/ckdf_test: tests/ckdf_test.o \
- tests/android_keymaster_test_utils.o \
- android_keymaster/android_keymaster_utils.o \
- android_keymaster/authorization_set.o \
- android_keymaster/keymaster_tags.o \
- android_keymaster/logger.o \
- android_keymaster/serializable.o \
- km_openssl/ckdf.o \
- km_openssl/openssl_err.o \
- $(GTEST_OBJS)
-
-tests/hkdf_test: tests/hkdf_test.o \
- tests/android_keymaster_test_utils.o \
- android_keymaster/android_keymaster_utils.o \
- android_keymaster/authorization_set.o \
- km_openssl/hkdf.o \
- km_openssl/hmac.o \
- km_openssl/kdf.o \
- android_keymaster/keymaster_tags.o \
- android_keymaster/logger.o \
- android_keymaster/serializable.o \
- $(GTEST_OBJS)
-
-tests/kdf_test: tests/kdf_test.o \
- android_keymaster/android_keymaster_utils.o \
- km_openssl/kdf.o \
- android_keymaster/logger.o \
- android_keymaster/serializable.o \
- $(GTEST_OBJS)
-
-tests/kdf1_test: tests/kdf1_test.o \
- tests/android_keymaster_test_utils.o \
- android_keymaster/android_keymaster_utils.o \
- android_keymaster/authorization_set.o \
- km_openssl/iso18033kdf.o \
- km_openssl/kdf.o \
- android_keymaster/keymaster_tags.o \
- android_keymaster/logger.o \
- android_keymaster/serializable.o \
- $(GTEST_OBJS)
-
-tests/kdf2_test: tests/kdf2_test.o \
- tests/android_keymaster_test_utils.o \
- android_keymaster/android_keymaster_utils.o \
- android_keymaster/authorization_set.o \
- km_openssl/iso18033kdf.o \
- km_openssl/kdf.o \
- android_keymaster/keymaster_tags.o \
- android_keymaster/logger.o \
- android_keymaster/serializable.o \
- $(GTEST_OBJS)
-
-tests/nist_curve_key_exchange_test: tests/nist_curve_key_exchange_test.o \
- tests/android_keymaster_test_utils.o \
- android_keymaster/authorization_set.o \
- android_keymaster/keymaster_tags.o \
- android_keymaster/logger.o \
- km_openssl/nist_curve_key_exchange.o \
- km_openssl/openssl_err.o \
- km_openssl/openssl_utils.o \
- android_keymaster/serializable.o \
- $(GTEST_OBJS)
-
-tests/ecies_kem_test: tests/ecies_kem_test.o \
- android_keymaster/android_keymaster_utils.o \
- tests/android_keymaster_test_utils.o \
- android_keymaster/authorization_set.o \
- km_openssl/ecies_kem.o \
- km_openssl/hkdf.o \
- km_openssl/hmac.o \
- km_openssl/kdf.o \
- android_keymaster/keymaster_tags.o \
- android_keymaster/logger.o \
- km_openssl/nist_curve_key_exchange.o \
- km_openssl/openssl_err.o \
- km_openssl/openssl_utils.o \
- android_keymaster/serializable.o \
- $(GTEST_OBJS)
-
-tests/authorization_set_test: tests/authorization_set_test.o \
- tests/android_keymaster_test_utils.o \
- android_keymaster/authorization_set.o \
- android_keymaster/keymaster_tags.o \
- android_keymaster/logger.o \
- android_keymaster/serializable.o \
- $(GTEST_OBJS)
-
-tests/key_blob_test: tests/key_blob_test.o \
- tests/android_keymaster_test_utils.o \
- android_keymaster/android_keymaster_utils.o \
- key_blob_utils/auth_encrypted_key_blob.o \
- android_keymaster/authorization_set.o \
- key_blob_utils/integrity_assured_key_blob.o \
- android_keymaster/keymaster_tags.o \
- android_keymaster/logger.o \
- key_blob_utils/ocb.o \
- key_blob_utils/ocb_utils.o \
- km_openssl/openssl_err.o \
- android_keymaster/serializable.o \
- $(GTEST_OBJS)
-
-tests/android_keymaster_messages_test: tests/android_keymaster_messages_test.o \
- android_keymaster/android_keymaster_messages.o \
- tests/android_keymaster_test_utils.o \
- android_keymaster/android_keymaster_utils.o \
- android_keymaster/authorization_set.o \
- android_keymaster/keymaster_tags.o \
- android_keymaster/logger.o \
- android_keymaster/serializable.o \
- $(GTEST_OBJS)
-
-tests/android_keymaster_test: tests/android_keymaster_test.o \
- android_keymaster/android_keymaster.o \
- android_keymaster/android_keymaster_messages.o \
- android_keymaster/android_keymaster_utils.o \
- android_keymaster/authorization_set.o \
- android_keymaster/keymaster_enforcement.o \
- android_keymaster/keymaster_tags.o \
- android_keymaster/logger.o \
- android_keymaster/operation.o \
- android_keymaster/operation_table.o \
- android_keymaster/serializable.o \
- contexts/pure_soft_keymaster_context.o \
- contexts/soft_attestation_cert.o \
- contexts/soft_keymaster_context.o \
- contexts/soft_keymaster_device.o \
- key_blob_utils/auth_encrypted_key_blob.o \
- key_blob_utils/integrity_assured_key_blob.o \
- key_blob_utils/ocb.o \
- key_blob_utils/ocb_utils.o \
- key_blob_utils/software_keyblobs.o \
- km_openssl/aes_key.o \
- km_openssl/aes_key.o \
- km_openssl/aes_operation.o \
- km_openssl/aes_operation.o \
- km_openssl/asymmetric_key.o \
- km_openssl/asymmetric_key_factory.o \
- km_openssl/attestation_record.o \
- km_openssl/attestation_utils.o \
- km_openssl/block_cipher_operation.o \
- km_openssl/ckdf.o \
- km_openssl/ec_key.o \
- km_openssl/ec_key_factory.o \
- km_openssl/ecdsa_operation.o \
- km_openssl/hmac_key.o \
- km_openssl/hmac_operation.o \
- km_openssl/openssl_err.o \
- km_openssl/openssl_utils.o \
- km_openssl/rsa_key.o \
- km_openssl/rsa_key_factory.o \
- km_openssl/rsa_operation.o \
- km_openssl/soft_keymaster_enforcement.o \
- km_openssl/software_random_source.o \
- km_openssl/symmetric_key.o \
- km_openssl/triple_des_key.o \
- km_openssl/triple_des_operation.o \
- km_openssl/wrapped_key.o \
- legacy_support/ec_keymaster0_key.o \
- legacy_support/ec_keymaster1_key.o \
- legacy_support/ecdsa_keymaster1_operation.o \
- legacy_support/keymaster0_engine.o \
- legacy_support/keymaster1_engine.o \
- legacy_support/rsa_keymaster0_key.o \
- legacy_support/rsa_keymaster1_key.o \
- legacy_support/rsa_keymaster1_operation.o \
- tests/android_keymaster_test_utils.o \
- $(BASE)/system/security/keystore/keyblob_utils.o \
- $(GTEST_OBJS)
-
-tests/keymaster_enforcement_test: tests/keymaster_enforcement_test.o \
- android_keymaster/android_keymaster_messages.o \
- tests/android_keymaster_test_utils.o \
- android_keymaster/android_keymaster_utils.o \
- android_keymaster/authorization_set.o \
- android_keymaster/keymaster_enforcement.o \
- km_openssl/ckdf.o \
- km_openssl/openssl_err.o \
- km_openssl/soft_keymaster_enforcement.o \
- android_keymaster/keymaster_tags.o \
- android_keymaster/logger.o \
- android_keymaster/serializable.o \
- $(GTEST_OBJS)
-
-tests/attestation_record_test: tests/attestation_record_test.o \
- tests/android_keymaster_test_utils.o \
- android_keymaster/android_keymaster_utils.o \
- km_openssl/attestation_record.o \
- android_keymaster/authorization_set.o \
- android_keymaster/keymaster_tags.o \
- android_keymaster/logger.o \
- km_openssl/openssl_err.o \
- android_keymaster/serializable.o \
- $(GTEST_OBJS)
-
-tests/wrapped_key_test: tests/wrapped_key_test.o \
- tests/android_keymaster_test_utils.o \
- android_keymaster/android_keymaster_utils.o \
- km_openssl/attestation_record.o \
- android_keymaster/authorization_set.o \
- android_keymaster/keymaster_tags.o \
- android_keymaster/logger.o \
- km_openssl/openssl_err.o \
- android_keymaster/serializable.o \
- km_openssl/wrapped_key.o \
- $(GTEST_OBJS)
-
-$(GTEST)/src/gtest-all.o: CXXFLAGS:=$(subst -Wmissing-declarations,,$(CXXFLAGS))
-
-clean:
- rm -f $(OBJS) $(DEPS) $(BINARIES) \
- $(BINARIES:=.run) $(BINARIES:=.memcheck) $(BINARIES:=.massif) \
- *gcov *gcno *gcda coverage.info
- rm -rf coverage
-
--include $(CPPSRCS:.cpp=.d)
--include $(CCSRCS:.cc=.d)
diff --git a/OWNERS b/OWNERS
index c1c7bb8..2b2ad2a 100644
--- a/OWNERS
+++ b/OWNERS
@@ -1,4 +1,4 @@
-cbrubaker@google.com
+jbires@google.com
jdanis@google.com
-kroot@google.com
swillden@google.com
+zeuthen@google.com
\ No newline at end of file
diff --git a/android_keymaster/android_keymaster.cpp b/android_keymaster/android_keymaster.cpp
index 195a797..00fa837 100644
--- a/android_keymaster/android_keymaster.cpp
+++ b/android_keymaster/android_keymaster.cpp
@@ -16,28 +16,61 @@
#include <keymaster/android_keymaster.h>
+#include <vector>
+
#include <assert.h>
#include <string.h>
#include <stddef.h>
+#include <cppbor.h>
+#include <cppbor_parse.h>
+
#include <keymaster/UniquePtr.h>
#include <keymaster/android_keymaster_utils.h>
+#include <keymaster/cppcose/cppcose.h>
#include <keymaster/key.h>
#include <keymaster/key_blob_utils/ae.h>
#include <keymaster/key_factory.h>
#include <keymaster/keymaster_context.h>
+#include <keymaster/km_date.h>
#include <keymaster/km_openssl/openssl_err.h>
+#include <keymaster/km_openssl/openssl_utils.h>
+#include <keymaster/logger.h>
#include <keymaster/operation.h>
#include <keymaster/operation_table.h>
+#include <keymaster/remote_provisioning_utils.h>
namespace keymaster {
namespace {
-const uint8_t MAJOR_VER = 2;
-const uint8_t MINOR_VER = 0;
-const uint8_t SUBMINOR_VER = 0;
+using cppcose::constructCoseEncrypt;
+using cppcose::constructCoseMac0;
+using cppcose::constructCoseSign1;
+using cppcose::CoseKey;
+using cppcose::EC2;
+using cppcose::ES256;
+using cppcose::generateCoseMac0Mac;
+using cppcose::kAesGcmNonceLength;
+using cppcose::P256;
+using cppcose::x25519_HKDF_DeriveKey;
+
+template <keymaster_tag_t T>
+keymaster_error_t CheckPatchLevel(const AuthorizationSet& tee_enforced,
+ const AuthorizationSet& sw_enforced, TypedTag<KM_UINT, T> tag,
+ uint32_t current_patchlevel) {
+ uint32_t key_patchlevel;
+ if (tee_enforced.GetTagValue(tag, &key_patchlevel) ||
+ sw_enforced.GetTagValue(tag, &key_patchlevel)) {
+ if (key_patchlevel < current_patchlevel) {
+ return KM_ERROR_KEY_REQUIRES_UPGRADE;
+ } else if (key_patchlevel > current_patchlevel) {
+ return KM_ERROR_INVALID_KEY_BLOB;
+ }
+ }
+ return KM_ERROR_OK;
+}
keymaster_error_t CheckVersionInfo(const AuthorizationSet& tee_enforced,
const AuthorizationSet& sw_enforced,
@@ -46,22 +79,61 @@
uint32_t os_patchlevel;
context.GetSystemVersion(&os_version, &os_patchlevel);
- uint32_t key_os_patchlevel;
- if (tee_enforced.GetTagValue(TAG_OS_PATCHLEVEL, &key_os_patchlevel) ||
- sw_enforced.GetTagValue(TAG_OS_PATCHLEVEL, &key_os_patchlevel)) {
- if (key_os_patchlevel < os_patchlevel)
- return KM_ERROR_KEY_REQUIRES_UPGRADE;
- else if (key_os_patchlevel > os_patchlevel)
- return KM_ERROR_INVALID_KEY_BLOB;
+ keymaster_error_t err =
+ CheckPatchLevel(tee_enforced, sw_enforced, TAG_OS_PATCHLEVEL, os_patchlevel);
+ if (err != KM_ERROR_OK) return err;
+
+ // Also check the vendor and boot patchlevels if available.
+ auto vendor_patchlevel = context.GetVendorPatchlevel();
+ if (vendor_patchlevel.has_value()) {
+ err = CheckPatchLevel(tee_enforced, sw_enforced, TAG_VENDOR_PATCHLEVEL,
+ vendor_patchlevel.value());
+ if (err != KM_ERROR_OK) return err;
+ }
+ auto boot_patchlevel = context.GetBootPatchlevel();
+ if (boot_patchlevel.has_value()) {
+ err = CheckPatchLevel(tee_enforced, sw_enforced, TAG_BOOT_PATCHLEVEL,
+ boot_patchlevel.value());
+ if (err != KM_ERROR_OK) return err;
}
return KM_ERROR_OK;
}
+const keymaster_key_param_t kKeyMintEcdsaP256Params[] = {
+ Authorization(TAG_PURPOSE, KM_PURPOSE_ATTEST_KEY),
+ Authorization(TAG_ALGORITHM, KM_ALGORITHM_EC), Authorization(TAG_KEY_SIZE, 256),
+ Authorization(TAG_DIGEST, KM_DIGEST_SHA_2_256), Authorization(TAG_EC_CURVE, KM_EC_CURVE_P_256),
+ Authorization(TAG_NO_AUTH_REQUIRED),
+ // The certificate generated by KM will be discarded, these values don't matter.
+ Authorization(TAG_CERTIFICATE_NOT_BEFORE, 0), Authorization(TAG_CERTIFICATE_NOT_AFTER, 0)};
+
+cppcose::HmacSha256Function getMacFunction(bool test_mode,
+ RemoteProvisioningContext* rem_prov_ctx) {
+ if (test_mode) {
+ return [](const cppcose::bytevec& input) {
+ const cppcose::bytevec macKey(32);
+ return cppcose::generateHmacSha256(macKey, input);
+ };
+ }
+
+ return [rem_prov_ctx](const cppcose::bytevec& input) -> cppcose::ErrMsgOr<cppcose::HmacSha256> {
+ auto mac = rem_prov_ctx->GenerateHmacSha256(input);
+ if (!mac) {
+ return "Remote provisioning context failed to sign MAC.";
+ }
+ return *mac;
+ };
+}
+
+constexpr int kP256AffinePointSize = 32;
+
} // anonymous namespace
-AndroidKeymaster::AndroidKeymaster(KeymasterContext* context, size_t operation_table_size)
- : context_(context), operation_table_(new(std::nothrow) OperationTable(operation_table_size)) {}
+AndroidKeymaster::AndroidKeymaster(KeymasterContext* context, size_t operation_table_size,
+ uint32_t message_version)
+ : context_(context), operation_table_(new (std::nothrow) OperationTable(operation_table_size)),
+ message_version_(message_version) {}
AndroidKeymaster::~AndroidKeymaster() {}
@@ -85,30 +157,41 @@
}
void AndroidKeymaster::GetVersion(const GetVersionRequest&, GetVersionResponse* rsp) {
- if (rsp == nullptr)
- return;
+ if (rsp == nullptr) return;
- rsp->major_ver = MAJOR_VER;
- rsp->minor_ver = MINOR_VER;
- rsp->subminor_ver = SUBMINOR_VER;
+ rsp->major_ver = 2;
+ rsp->minor_ver = 0;
+ rsp->subminor_ver = 0;
rsp->error = KM_ERROR_OK;
}
+GetVersion2Response AndroidKeymaster::GetVersion2(const GetVersion2Request& req) {
+ GetVersion2Response rsp;
+ rsp.km_version = context_->GetKmVersion();
+ rsp.km_date = kKmDate;
+ rsp.max_message_version = MessageVersion(rsp.km_version, rsp.km_date);
+ rsp.error = KM_ERROR_OK;
+
+ // Determine what message version we should use.
+ message_version_ = NegotiateMessageVersion(req, rsp);
+
+ LOG_D("GetVersion2 results: %d, %d, %d, %d", rsp.km_version, rsp.km_date,
+ rsp.max_message_version, message_version_);
+ return rsp;
+}
+
void AndroidKeymaster::SupportedAlgorithms(const SupportedAlgorithmsRequest& /* request */,
SupportedAlgorithmsResponse* response) {
- if (response == nullptr)
- return;
+ if (response == nullptr) return;
response->error = KM_ERROR_OK;
size_t algorithm_count = 0;
const keymaster_algorithm_t* algorithms = context_->GetSupportedAlgorithms(&algorithm_count);
- if (algorithm_count == 0)
- return;
+ if (algorithm_count == 0) return;
response->results_length = algorithm_count;
response->results = dup_array(algorithms, algorithm_count);
- if (!response->results)
- response->error = KM_ERROR_MEMORY_ALLOCATION_FAILED;
+ if (!response->results) response->error = KM_ERROR_MEMORY_ALLOCATION_FAILED;
}
template <typename T>
@@ -116,8 +199,7 @@
keymaster_purpose_t purpose,
const T* (OperationFactory::*get_supported_method)(size_t* count) const,
SupportedResponse<T>* response) {
- if (response == nullptr || !check_supported(context, algorithm, response))
- return;
+ if (response == nullptr || !check_supported(context, algorithm, response)) return;
const OperationFactory* factory = context.GetOperationFactory(algorithm, purpose);
if (!factory) {
@@ -150,8 +232,7 @@
void AndroidKeymaster::SupportedImportFormats(const SupportedImportFormatsRequest& request,
SupportedImportFormatsResponse* response) {
- if (response == nullptr || !check_supported(*context_, request.algorithm, response))
- return;
+ if (response == nullptr || !check_supported(*context_, request.algorithm, response)) return;
size_t count;
const keymaster_key_format_t* formats =
@@ -161,8 +242,7 @@
void AndroidKeymaster::SupportedExportFormats(const SupportedExportFormatsRequest& request,
SupportedExportFormatsResponse* response) {
- if (response == nullptr || !check_supported(*context_, request.algorithm, response))
- return;
+ if (response == nullptr || !check_supported(*context_, request.algorithm, response)) return;
size_t count;
const keymaster_key_format_t* formats =
@@ -171,7 +251,7 @@
}
GetHmacSharingParametersResponse AndroidKeymaster::GetHmacSharingParameters() {
- GetHmacSharingParametersResponse response;
+ GetHmacSharingParametersResponse response(message_version());
KeymasterEnforcement* policy = context_->enforcement_policy();
if (!policy) {
response.error = KM_ERROR_UNIMPLEMENTED;
@@ -184,14 +264,14 @@
ComputeSharedHmacResponse
AndroidKeymaster::ComputeSharedHmac(const ComputeSharedHmacRequest& request) {
- ComputeSharedHmacResponse response;
+ ComputeSharedHmacResponse response(message_version());
KeymasterEnforcement* policy = context_->enforcement_policy();
if (!policy) {
response.error = KM_ERROR_UNIMPLEMENTED;
return response;
}
-
response.error = policy->ComputeSharedHmac(request.params_array, &response.sharing_check);
+
return response;
}
@@ -199,7 +279,7 @@
AndroidKeymaster::VerifyAuthorization(const VerifyAuthorizationRequest& request) {
KeymasterEnforcement* policy = context_->enforcement_policy();
if (!policy) {
- VerifyAuthorizationResponse response;
+ VerifyAuthorizationResponse response(message_version());
response.error = KM_ERROR_UNIMPLEMENTED;
return response;
}
@@ -207,45 +287,245 @@
return policy->VerifyAuthorization(request);
}
+void AndroidKeymaster::GenerateTimestampToken(GenerateTimestampTokenRequest& request,
+ GenerateTimestampTokenResponse* response) {
+ KeymasterEnforcement* policy = context_->enforcement_policy();
+ if (!policy) {
+ response->error = KM_ERROR_UNIMPLEMENTED;
+ } else {
+ response->token.challenge = request.challenge;
+ response->error = policy->GenerateTimestampToken(&response->token);
+ }
+}
+
void AndroidKeymaster::AddRngEntropy(const AddEntropyRequest& request,
AddEntropyResponse* response) {
response->error = context_->AddRngEntropy(request.random_data.peek_read(),
request.random_data.available_read());
}
+const KeyFactory* get_key_factory(const AuthorizationSet& key_description,
+ const KeymasterContext& context, //
+ keymaster_error_t* error) {
+ keymaster_algorithm_t algorithm;
+ const KeyFactory* factory{};
+ if (!key_description.GetTagValue(TAG_ALGORITHM, &algorithm) ||
+ !(factory = context.GetKeyFactory(algorithm))) {
+ *error = KM_ERROR_UNSUPPORTED_ALGORITHM;
+ }
+ return factory;
+}
+
void AndroidKeymaster::GenerateKey(const GenerateKeyRequest& request,
GenerateKeyResponse* response) {
- if (response == nullptr)
- return;
+ if (response == nullptr) return;
- keymaster_algorithm_t algorithm;
- const KeyFactory* factory = nullptr;
- UniquePtr<Key> key;
- if (!request.key_description.GetTagValue(TAG_ALGORITHM, &algorithm) ||
- !(factory = context_->GetKeyFactory(algorithm)))
- response->error = KM_ERROR_UNSUPPORTED_ALGORITHM;
- else {
- KeymasterKeyBlob key_blob;
- response->enforced.Clear();
- response->unenforced.Clear();
- response->error = factory->GenerateKey(request.key_description, &key_blob,
- &response->enforced, &response->unenforced);
- if (response->error == KM_ERROR_OK)
- response->key_blob = key_blob.release();
+ const KeyFactory* factory =
+ get_key_factory(request.key_description, *context_, &response->error);
+ if (!factory) return;
+
+ UniquePtr<Key> attest_key;
+ if (request.attestation_signing_key_blob.key_material_size) {
+ attest_key = LoadKey(request.attestation_signing_key_blob, request.attest_key_params,
+ &response->error);
+ if (response->error != KM_ERROR_OK) return;
}
+
+ response->enforced.Clear();
+ response->unenforced.Clear();
+ response->error = factory->GenerateKey(request.key_description,
+ move(attest_key), //
+ request.issuer_subject,
+ &response->key_blob, //
+ &response->enforced,
+ &response->unenforced, //
+ &response->certificate_chain);
+}
+
+void AndroidKeymaster::GenerateRkpKey(const GenerateRkpKeyRequest& request,
+ GenerateRkpKeyResponse* response) {
+ if (response == nullptr) return;
+
+ auto rem_prov_ctx = context_->GetRemoteProvisioningContext();
+ if (rem_prov_ctx == nullptr) {
+ response->error = static_cast<keymaster_error_t>(kStatusFailed);
+ return;
+ }
+
+ // Generate the keypair that will become the attestation key.
+ GenerateKeyRequest gen_key_request(message_version_);
+ gen_key_request.key_description.Reinitialize(kKeyMintEcdsaP256Params,
+ array_length(kKeyMintEcdsaP256Params));
+ GenerateKeyResponse gen_key_response(message_version_);
+ GenerateKey(gen_key_request, &gen_key_response);
+ if (gen_key_response.error != KM_ERROR_OK) {
+ response->error = static_cast<keymaster_error_t>(kStatusFailed);
+ return;
+ }
+
+ // Retrieve the certificate and parse it to build a COSE_Key
+ if (gen_key_response.certificate_chain.entry_count != 1) {
+ // Error: Need the single non-signed certificate with the public key in it.
+ response->error = static_cast<keymaster_error_t>(kStatusFailed);
+ return;
+ }
+ std::vector<uint8_t> x_coord(kP256AffinePointSize);
+ std::vector<uint8_t> y_coord(kP256AffinePointSize);
+ response->error =
+ GetEcdsa256KeyFromCert(gen_key_response.certificate_chain.begin(), x_coord.data(),
+ x_coord.size(), y_coord.data(), y_coord.size());
+ if (response->error != KM_ERROR_OK) {
+ response->error = static_cast<keymaster_error_t>(kStatusFailed);
+ return;
+ }
+
+ cppbor::Map cose_public_key_map = cppbor::Map()
+ .add(CoseKey::KEY_TYPE, EC2)
+ .add(CoseKey::ALGORITHM, ES256)
+ .add(CoseKey::CURVE, P256)
+ .add(CoseKey::PUBKEY_X, x_coord)
+ .add(CoseKey::PUBKEY_Y, y_coord);
+ if (request.test_mode) {
+ cose_public_key_map.add(CoseKey::TEST_KEY, cppbor::Null());
+ }
+
+ std::vector<uint8_t> cosePublicKey = cose_public_key_map.canonicalize().encode();
+
+ auto macFunction = getMacFunction(request.test_mode, rem_prov_ctx);
+ auto macedKey = constructCoseMac0(macFunction, {} /* externalAad */, cosePublicKey);
+ if (!macedKey) {
+ response->error = static_cast<keymaster_error_t>(kStatusFailed);
+ return;
+ }
+ std::vector<uint8_t> enc = macedKey->encode();
+ response->maced_public_key = KeymasterBlob(enc.data(), enc.size());
+ response->key_blob = std::move(gen_key_response.key_blob);
+ response->error = KM_ERROR_OK;
+}
+
+void AndroidKeymaster::GenerateCsr(const GenerateCsrRequest& request,
+ GenerateCsrResponse* response) {
+ if (response == nullptr) return;
+
+ auto rem_prov_ctx = context_->GetRemoteProvisioningContext();
+ if (rem_prov_ctx == nullptr) {
+ LOG_E("Couldn't get a pointer to the remote provisioning context, returned null.", 0);
+ response->error = static_cast<keymaster_error_t>(kStatusFailed);
+ return;
+ }
+
+ auto macFunction = getMacFunction(request.test_mode, rem_prov_ctx);
+ auto pubKeysToSign = validateAndExtractPubkeys(request.test_mode, request.num_keys,
+ request.keys_to_sign_array, macFunction);
+ if (!pubKeysToSign.isOk()) {
+ LOG_E("Failed to validate and extract the public keys for the CSR", 0);
+ response->error = static_cast<keymaster_error_t>(pubKeysToSign.moveError());
+ return;
+ }
+
+ std::vector<uint8_t> ephemeral_mac_key(SHA256_DIGEST_LENGTH, 0 /* value */);
+ if (GenerateRandom(ephemeral_mac_key.data(), ephemeral_mac_key.size()) != KM_ERROR_OK) {
+ LOG_E("Failed to generate a random mac key.", 0);
+ response->error = static_cast<keymaster_error_t>(kStatusFailed);
+ return;
+ }
+
+ auto ephemeral_mac_function = [&ephemeral_mac_key](const cppcose::bytevec& input) {
+ return cppcose::generateHmacSha256(ephemeral_mac_key, input);
+ };
+
+ auto pubKeysToSignMac =
+ generateCoseMac0Mac(ephemeral_mac_function, std::vector<uint8_t>{}, *pubKeysToSign);
+ if (!pubKeysToSignMac) {
+ LOG_E("Failed to generate COSE_Mac0 over the public keys to sign.", 0);
+ response->error = static_cast<keymaster_error_t>(kStatusFailed);
+ return;
+ }
+ response->keys_to_sign_mac = KeymasterBlob(pubKeysToSignMac->data(), pubKeysToSignMac->size());
+
+ std::vector<uint8_t> devicePrivKey;
+ cppbor::Array bcc;
+ if (request.test_mode) {
+ std::tie(devicePrivKey, bcc) = rem_prov_ctx->GenerateBcc(/*testMode=*/true);
+ } else {
+ devicePrivKey = rem_prov_ctx->devicePrivKey_;
+ auto clone = rem_prov_ctx->bcc_.clone();
+ if (!clone->asArray()) {
+ LOG_E("The BCC is not an array.", 0);
+ response->error = static_cast<keymaster_error_t>(kStatusFailed);
+ return;
+ }
+ bcc = std::move(*clone->asArray());
+ }
+ std::unique_ptr<cppbor::Map> device_info_map = rem_prov_ctx->CreateDeviceInfo();
+ std::vector<uint8_t> device_info = device_info_map->encode();
+ response->device_info_blob = KeymasterBlob(device_info.data(), device_info.size());
+ auto signedMac =
+ constructCoseSign1(devicePrivKey /* Signing key */, //
+ ephemeral_mac_key /* Payload */,
+ cppbor::Array() /* AAD */
+ .add(std::pair(request.challenge.begin(),
+ request.challenge.end() - request.challenge.begin()))
+ .add(std::move(device_info_map))
+ .add(std::pair(pubKeysToSignMac->data(), pubKeysToSignMac->size()))
+ .encode());
+ if (!signedMac) {
+ LOG_E("Failed to construct COSE_Sign1 over the ephemeral mac key.", 0);
+ response->error = static_cast<keymaster_error_t>(kStatusFailed);
+ return;
+ }
+
+ std::vector<uint8_t> ephemeralPrivKey(X25519_PRIVATE_KEY_LEN);
+ std::vector<uint8_t> ephemeralPubKey(X25519_PUBLIC_VALUE_LEN);
+ X25519_keypair(ephemeralPubKey.data(), ephemeralPrivKey.data());
+
+ auto eek = validateAndExtractEekPubAndId(request.test_mode, request.endpoint_enc_cert_chain);
+ if (!eek.isOk()) {
+ LOG_E("Failed to validate and extract the endpoint encryption key.", 0);
+ response->error = static_cast<keymaster_error_t>(eek.moveError());
+ return;
+ }
+
+ auto sessionKey =
+ x25519_HKDF_DeriveKey(ephemeralPubKey, ephemeralPrivKey, eek->first, true /* senderIsA */);
+ if (!sessionKey) {
+ LOG_E("Failed to derive the session key.", 0);
+ response->error = static_cast<keymaster_error_t>(kStatusFailed);
+ return;
+ }
+
+ std::vector<uint8_t> nonce(kAesGcmNonceLength, 0 /* value */);
+ if (GenerateRandom(nonce.data(), nonce.size()) != KM_ERROR_OK) {
+ LOG_E("Failed to generate a random nonce.", 0);
+ response->error = static_cast<keymaster_error_t>(kStatusFailed);
+ return;
+ }
+ auto coseEncrypted = constructCoseEncrypt(*sessionKey, nonce,
+ cppbor::Array() // payload
+ .add(signedMac.moveValue())
+ .add(std::move(bcc))
+ .encode(),
+ {}, // aad
+ buildCertReqRecipients(ephemeralPubKey, eek->second));
+
+ if (!coseEncrypted) {
+ LOG_E("Failed to construct a COSE_Encrypt ProtectedData structure", 0);
+ response->error = static_cast<keymaster_error_t>(kStatusFailed);
+ return;
+ }
+ std::vector<uint8_t> payload = coseEncrypted->encode();
+ response->protected_data_blob = KeymasterBlob(payload.data(), payload.size());
+ response->error = KM_ERROR_OK;
}
void AndroidKeymaster::GetKeyCharacteristics(const GetKeyCharacteristicsRequest& request,
GetKeyCharacteristicsResponse* response) {
- if (response == nullptr)
- return;
+ if (response == nullptr) return;
UniquePtr<Key> key;
response->error =
- context_->ParseKeyBlob(KeymasterKeyBlob(request.key_blob), request.additional_params,
- &key);
- if (response->error != KM_ERROR_OK)
- return;
+ context_->ParseKeyBlob(KeymasterKeyBlob(request.key_blob), request.additional_params, &key);
+ if (response->error != KM_ERROR_OK) return;
// scavenge the key object for the auth lists
response->enforced = move(key->hw_enforced());
@@ -256,29 +536,31 @@
void AndroidKeymaster::BeginOperation(const BeginOperationRequest& request,
BeginOperationResponse* response) {
- if (response == nullptr)
- return;
+ if (response == nullptr) return;
response->op_handle = 0;
- const KeyFactory* key_factory;
- UniquePtr<Key> key;
- response->error = LoadKey(request.key_blob, request.additional_params, &key_factory, &key);
- if (response->error != KM_ERROR_OK)
- return;
+ UniquePtr<Key> key = LoadKey(request.key_blob, request.additional_params, &response->error);
+ if (!key) return;
response->error = KM_ERROR_UNKNOWN_ERROR;
keymaster_algorithm_t key_algorithm;
- if (!key->authorizations().GetTagValue(TAG_ALGORITHM, &key_algorithm))
- return;
+ if (!key->authorizations().GetTagValue(TAG_ALGORITHM, &key_algorithm)) return;
response->error = KM_ERROR_UNSUPPORTED_PURPOSE;
- OperationFactory* factory = key_factory->GetOperationFactory(request.purpose);
+ OperationFactory* factory = key->key_factory()->GetOperationFactory(request.purpose);
if (!factory) return;
OperationPtr operation(
factory->CreateOperation(move(*key), request.additional_params, &response->error));
if (operation.get() == nullptr) return;
+ if (operation->authorizations().Contains(TAG_TRUSTED_CONFIRMATION_REQUIRED)) {
+ if (!operation->create_confirmation_verifier_buffer()) {
+ response->error = KM_ERROR_MEMORY_ALLOCATION_FAILED;
+ return;
+ }
+ }
+
if (context_->enforcement_policy()) {
km_id_t key_id;
response->error = KM_ERROR_UNKNOWN_ERROR;
@@ -292,8 +574,7 @@
response->output_params.Clear();
response->error = operation->Begin(request.additional_params, &response->output_params);
- if (response->error != KM_ERROR_OK)
- return;
+ if (response->error != KM_ERROR_OK) return;
response->op_handle = operation->operation_handle();
response->error = operation_table_->Add(move(operation));
@@ -301,13 +582,28 @@
void AndroidKeymaster::UpdateOperation(const UpdateOperationRequest& request,
UpdateOperationResponse* response) {
- if (response == nullptr)
- return;
+ if (response == nullptr) return;
response->error = KM_ERROR_INVALID_OPERATION_HANDLE;
Operation* operation = operation_table_->Find(request.op_handle);
- if (operation == nullptr)
- return;
+ if (operation == nullptr) return;
+
+ Buffer* confirmation_verifier_buffer = operation->get_confirmation_verifier_buffer();
+ if (confirmation_verifier_buffer != nullptr) {
+ size_t input_num_bytes = request.input.available_read();
+ if (input_num_bytes + confirmation_verifier_buffer->available_read() >
+ kConfirmationMessageMaxSize + kConfirmationTokenMessageTagSize) {
+ response->error = KM_ERROR_INVALID_ARGUMENT;
+ operation_table_->Delete(request.op_handle);
+ return;
+ }
+ if (!confirmation_verifier_buffer->reserve(input_num_bytes)) {
+ response->error = KM_ERROR_MEMORY_ALLOCATION_FAILED;
+ operation_table_->Delete(request.op_handle);
+ return;
+ }
+ confirmation_verifier_buffer->write(request.input.peek_read(), input_num_bytes);
+ }
if (context_->enforcement_policy()) {
response->error = context_->enforcement_policy()->AuthorizeOperation(
@@ -330,13 +626,28 @@
void AndroidKeymaster::FinishOperation(const FinishOperationRequest& request,
FinishOperationResponse* response) {
- if (response == nullptr)
- return;
+ if (response == nullptr) return;
response->error = KM_ERROR_INVALID_OPERATION_HANDLE;
Operation* operation = operation_table_->Find(request.op_handle);
- if (operation == nullptr)
- return;
+ if (operation == nullptr) return;
+
+ Buffer* confirmation_verifier_buffer = operation->get_confirmation_verifier_buffer();
+ if (confirmation_verifier_buffer != nullptr) {
+ size_t input_num_bytes = request.input.available_read();
+ if (input_num_bytes + confirmation_verifier_buffer->available_read() >
+ kConfirmationMessageMaxSize + kConfirmationTokenMessageTagSize) {
+ response->error = KM_ERROR_INVALID_ARGUMENT;
+ operation_table_->Delete(request.op_handle);
+ return;
+ }
+ if (!confirmation_verifier_buffer->reserve(input_num_bytes)) {
+ response->error = KM_ERROR_MEMORY_ALLOCATION_FAILED;
+ operation_table_->Delete(request.op_handle);
+ return;
+ }
+ confirmation_verifier_buffer->write(request.input.peek_read(), input_num_bytes);
+ }
if (context_->enforcement_policy()) {
response->error = context_->enforcement_policy()->AuthorizeOperation(
@@ -350,13 +661,49 @@
response->error = operation->Finish(request.additional_params, request.input, request.signature,
&response->output_params, &response->output);
+ if (response->error != KM_ERROR_OK) {
+ operation_table_->Delete(request.op_handle);
+ return;
+ }
+
+ // Invalidate the single use key from secure storage after finish.
+ if (operation->hw_enforced().Contains(TAG_USAGE_COUNT_LIMIT, 1) &&
+ context_->secure_key_storage() != nullptr) {
+ response->error = context_->secure_key_storage()->DeleteKey(operation->key_id());
+ }
+
+ // If the operation succeeded and TAG_TRUSTED_CONFIRMATION_REQUIRED was
+ // set, the input must be checked against the confirmation token.
+ if (response->error == KM_ERROR_OK && confirmation_verifier_buffer != nullptr) {
+ keymaster_blob_t confirmation_token_blob;
+ if (!request.additional_params.GetTagValue(TAG_CONFIRMATION_TOKEN,
+ &confirmation_token_blob)) {
+ response->error = KM_ERROR_NO_USER_CONFIRMATION;
+ response->output.Clear();
+ } else {
+ if (confirmation_token_blob.data_length != kConfirmationTokenSize) {
+ LOG_E("TAG_CONFIRMATION_TOKEN wrong size, was %zd expected %zd",
+ confirmation_token_blob.data_length, kConfirmationTokenSize);
+ response->error = KM_ERROR_INVALID_ARGUMENT;
+ response->output.Clear();
+ } else {
+ keymaster_error_t verification_result = context_->CheckConfirmationToken(
+ confirmation_verifier_buffer->begin(),
+ confirmation_verifier_buffer->available_read(), confirmation_token_blob.data);
+ if (verification_result != KM_ERROR_OK) {
+ response->error = verification_result;
+ response->output.Clear();
+ }
+ }
+ }
+ }
+
operation_table_->Delete(request.op_handle);
}
void AndroidKeymaster::AbortOperation(const AbortOperationRequest& request,
AbortOperationResponse* response) {
- if (!response)
- return;
+ if (!response) return;
Operation* operation = operation_table_->Find(request.op_handle);
if (!operation) {
@@ -369,14 +716,12 @@
}
void AndroidKeymaster::ExportKey(const ExportKeyRequest& request, ExportKeyResponse* response) {
- if (response == nullptr)
- return;
+ if (response == nullptr) return;
UniquePtr<Key> key;
response->error =
context_->ParseKeyBlob(KeymasterKeyBlob(request.key_blob), request.additional_params, &key);
- if (response->error != KM_ERROR_OK)
- return;
+ if (response->error != KM_ERROR_OK) return;
UniquePtr<uint8_t[]> out_key;
size_t size;
@@ -388,15 +733,10 @@
}
void AndroidKeymaster::AttestKey(const AttestKeyRequest& request, AttestKeyResponse* response) {
- if (!response)
- return;
+ if (!response) return;
- const KeyFactory* key_factory;
- UniquePtr<Key> key;
- response->error = LoadKey(request.key_blob, request.attest_params,
- &key_factory, &key);
- if (response->error != KM_ERROR_OK)
- return;
+ UniquePtr<Key> key = LoadKey(request.key_blob, request.attest_params, &response->error);
+ if (!key) return;
keymaster_blob_t attestation_application_id;
if (request.attest_params.GetTagValue(TAG_ATTESTATION_APPLICATION_ID,
@@ -404,82 +744,101 @@
key->sw_enforced().push_back(TAG_ATTESTATION_APPLICATION_ID, attestation_application_id);
}
- CertChainPtr certchain;
- response->error = context_->GenerateAttestation(*key, request.attest_params, &certchain);
- if (response->error == KM_ERROR_OK) {
- response->certificate_chain = *certchain;
- // response->certificate_chain took possession of secondary resources. So we shallowly
- // delete the keymaster_cert_chain_t object, but nothing else.
- // TODO Can we switch to managed types eventually?
- delete certchain.release();
- }
+ response->certificate_chain =
+ context_->GenerateAttestation(*key, request.attest_params, {} /* attestation_signing_key */,
+ {} /* issuer_subject */, &response->error);
}
void AndroidKeymaster::UpgradeKey(const UpgradeKeyRequest& request, UpgradeKeyResponse* response) {
- if (!response)
- return;
+ if (!response) return;
KeymasterKeyBlob upgraded_key;
response->error = context_->UpgradeKeyBlob(KeymasterKeyBlob(request.key_blob),
request.upgrade_params, &upgraded_key);
- if (response->error != KM_ERROR_OK)
- return;
+ if (response->error != KM_ERROR_OK) return;
response->upgraded_key = upgraded_key.release();
}
void AndroidKeymaster::ImportKey(const ImportKeyRequest& request, ImportKeyResponse* response) {
- if (response == nullptr)
- return;
+ if (response == nullptr) return;
- keymaster_algorithm_t algorithm;
- const KeyFactory* factory = nullptr;
- UniquePtr<Key> key;
- if (!request.key_description.GetTagValue(TAG_ALGORITHM, &algorithm) ||
- !(factory = context_->GetKeyFactory(algorithm)))
- response->error = KM_ERROR_UNSUPPORTED_ALGORITHM;
- else {
- keymaster_key_blob_t key_material = {request.key_data, request.key_data_length};
- KeymasterKeyBlob key_blob;
- response->error = factory->ImportKey(request.key_description, request.key_format,
- KeymasterKeyBlob(key_material), &key_blob,
- &response->enforced, &response->unenforced);
- if (response->error == KM_ERROR_OK)
- response->key_blob = key_blob.release();
+ const KeyFactory* factory =
+ get_key_factory(request.key_description, *context_, &response->error);
+ if (!factory) return;
+
+ if (context_->enforcement_policy() &&
+ request.key_description.GetTagValue(TAG_EARLY_BOOT_ONLY) &&
+ !context_->enforcement_policy()->in_early_boot()) {
+ response->error = KM_ERROR_EARLY_BOOT_ENDED;
+ return;
}
+
+ UniquePtr<Key> attest_key;
+ if (request.attestation_signing_key_blob.key_material_size) {
+
+ attest_key =
+ LoadKey(request.attestation_signing_key_blob, {} /* params */, &response->error);
+ if (response->error != KM_ERROR_OK) return;
+ }
+
+ response->error = factory->ImportKey(request.key_description, //
+ request.key_format, //
+ request.key_data, //
+ move(attest_key), //
+ request.issuer_subject, //
+ &response->key_blob, //
+ &response->enforced, //
+ &response->unenforced, //
+ &response->certificate_chain);
}
void AndroidKeymaster::DeleteKey(const DeleteKeyRequest& request, DeleteKeyResponse* response) {
- if (!response)
- return;
+ if (!response) return;
response->error = context_->DeleteKey(KeymasterKeyBlob(request.key_blob));
}
void AndroidKeymaster::DeleteAllKeys(const DeleteAllKeysRequest&, DeleteAllKeysResponse* response) {
- if (!response)
- return;
+ if (!response) return;
response->error = context_->DeleteAllKeys();
}
void AndroidKeymaster::Configure(const ConfigureRequest& request, ConfigureResponse* response) {
- if (!response)
- return;
+ if (!response) return;
response->error = context_->SetSystemVersion(request.os_version, request.os_patchlevel);
}
+ConfigureVendorPatchlevelResponse
+AndroidKeymaster::ConfigureVendorPatchlevel(const ConfigureVendorPatchlevelRequest& request) {
+ ConfigureVendorPatchlevelResponse rsp(message_version());
+ rsp.error = context_->SetVendorPatchlevel(request.vendor_patchlevel);
+ return rsp;
+}
+
+ConfigureBootPatchlevelResponse
+AndroidKeymaster::ConfigureBootPatchlevel(const ConfigureBootPatchlevelRequest& request) {
+ ConfigureBootPatchlevelResponse rsp(message_version());
+ rsp.error = context_->SetBootPatchlevel(request.boot_patchlevel);
+ return rsp;
+}
+
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,
- const KeyFactory** factory, UniquePtr<Key>* key) {
+UniquePtr<Key> AndroidKeymaster::LoadKey(const keymaster_key_blob_t& key_blob,
+ const AuthorizationSet& additional_params,
+ keymaster_error_t* error) {
+ if (!error) return {};
+
+ UniquePtr<Key> key;
KeymasterKeyBlob key_material;
- keymaster_error_t error = context_->ParseKeyBlob(KeymasterKeyBlob(key_blob), additional_params,
- key);
- if (error != KM_ERROR_OK)
- return error;
- if (factory) *factory = (*key)->key_factory();
- return CheckVersionInfo((*key)->hw_enforced(), (*key)->sw_enforced(), *context_);
+ *error = context_->ParseKeyBlob(KeymasterKeyBlob(key_blob), additional_params, &key);
+ if (*error != KM_ERROR_OK) return {};
+
+ *error = CheckVersionInfo(key->hw_enforced(), key->sw_enforced(), *context_);
+ if (*error != KM_ERROR_OK) return {};
+
+ return key;
}
void AndroidKeymaster::ImportWrappedKey(const ImportWrappedKeyRequest& request,
@@ -511,22 +870,39 @@
if (sids & HW_AUTH_FINGERPRINT) {
key_description.push_back(TAG_USER_SECURE_ID, request.biometric_sid);
}
- }
- keymaster_algorithm_t algorithm;
- const KeyFactory* factory = nullptr;
- if (!key_description.GetTagValue(TAG_ALGORITHM, &algorithm) ||
- !(factory = context_->GetKeyFactory(algorithm))) {
- response->error = KM_ERROR_UNSUPPORTED_ALGORITHM;
- } else {
- KeymasterKeyBlob key_blob;
- response->error =
- factory->ImportKey(key_description, key_format, KeymasterKeyBlob(secret_key), &key_blob,
- &response->enforced, &response->unenforced);
- if (response->error == KM_ERROR_OK) {
- response->key_blob = key_blob;
+ if (context_->GetKmVersion() >= KmVersion::KEYMINT_1) {
+ key_description.push_back(TAG_CERTIFICATE_NOT_BEFORE, 0);
+ key_description.push_back(TAG_CERTIFICATE_NOT_AFTER, kUndefinedExpirationDateTime);
}
}
+
+ const KeyFactory* factory = get_key_factory(key_description, *context_, &response->error);
+ if (!factory) return;
+
+ response->error = factory->ImportKey(key_description, //
+ key_format, //
+ secret_key, //
+ {} /* attest_key */, //
+ {} /* issuer_subject */, //
+ &response->key_blob, //
+ &response->enforced, //
+ &response->unenforced, //
+ &response->certificate_chain);
+}
+
+EarlyBootEndedResponse AndroidKeymaster::EarlyBootEnded() {
+ if (context_->enforcement_policy()) {
+ context_->enforcement_policy()->early_boot_ended();
+ }
+ return EarlyBootEndedResponse(message_version());
+}
+
+DeviceLockedResponse AndroidKeymaster::DeviceLocked(const DeviceLockedRequest& request) {
+ if (context_->enforcement_policy()) {
+ context_->enforcement_policy()->device_locked(request.passwordOnly);
+ }
+ return DeviceLockedResponse(message_version());
}
} // namespace keymaster
diff --git a/android_keymaster/android_keymaster_messages.cpp b/android_keymaster/android_keymaster_messages.cpp
index 6eb6a5f..3dfd529 100644
--- a/android_keymaster/android_keymaster_messages.cpp
+++ b/android_keymaster/android_keymaster_messages.cpp
@@ -19,27 +19,29 @@
namespace keymaster {
+namespace {
+
/*
* Helper functions for working with key blobs.
*/
-static void set_key_blob(keymaster_key_blob_t* key_blob, const void* key_material, size_t length) {
+void set_key_blob(keymaster_key_blob_t* key_blob, const void* key_material, size_t length) {
delete[] key_blob->key_material;
key_blob->key_material = dup_buffer(key_material, length);
key_blob->key_material_size = length;
}
-static size_t key_blob_size(const keymaster_key_blob_t& key_blob) {
+size_t key_blob_size(const keymaster_key_blob_t& key_blob) {
return sizeof(uint32_t) /* key size */ + key_blob.key_material_size;
}
-static uint8_t* serialize_key_blob(const keymaster_key_blob_t& key_blob, uint8_t* buf,
- const uint8_t* end) {
+uint8_t* serialize_key_blob(const keymaster_key_blob_t& key_blob, uint8_t* buf,
+ const uint8_t* end) {
return append_size_and_data_to_buf(buf, end, key_blob.key_material, key_blob.key_material_size);
}
-static bool deserialize_key_blob(keymaster_key_blob_t* key_blob, const uint8_t** buf_ptr,
- const uint8_t* end) {
+bool deserialize_key_blob(keymaster_key_blob_t* key_blob, const uint8_t** buf_ptr,
+ const uint8_t* end) {
delete[] key_blob->key_material;
key_blob->key_material = nullptr;
UniquePtr<uint8_t[]> deserialized_key_material;
@@ -50,15 +52,23 @@
return true;
}
-static size_t blob_size(const keymaster_blob_t& blob) {
+void set_blob(keymaster_blob_t* blob, const void* data, size_t length) {
+ assert(blob);
+ assert(data);
+ delete[] blob->data;
+ blob->data = dup_buffer(data, length);
+ blob->data_length = length;
+}
+
+size_t blob_size(const keymaster_blob_t& blob) {
return sizeof(uint32_t) /* data size */ + blob.data_length;
}
-static uint8_t* serialize_blob(const keymaster_blob_t& blob, uint8_t* buf, const uint8_t* end) {
+uint8_t* serialize_blob(const keymaster_blob_t& blob, uint8_t* buf, const uint8_t* end) {
return append_size_and_data_to_buf(buf, end, blob.data, blob.data_length);
}
-static bool deserialize_blob(keymaster_blob_t* blob, const uint8_t** buf_ptr, const uint8_t* end) {
+bool deserialize_blob(keymaster_blob_t* blob, const uint8_t** buf_ptr, const uint8_t* end) {
delete[] blob->data;
*blob = {};
UniquePtr<uint8_t[]> deserialized_blob;
@@ -68,6 +78,87 @@
return true;
}
+/*
+ * Helper functions for working with certificate chains.
+ */
+const size_t kMaxChainEntryCount = 10;
+
+size_t chain_size(const keymaster_cert_chain_t& certificate_chain) {
+ size_t result = sizeof(uint32_t); /* certificate_chain.entry_count */
+ for (size_t i = 0; i < certificate_chain.entry_count; ++i) {
+ result += sizeof(uint32_t); /* certificate_chain.entries[i].data_length */
+ result += certificate_chain.entries[i].data_length;
+ }
+ return result;
+}
+
+uint8_t* serialize_chain(const keymaster_cert_chain_t& certificate_chain, uint8_t* buf,
+ const uint8_t* end) {
+ buf = append_uint32_to_buf(buf, end, certificate_chain.entry_count);
+ for (size_t i = 0; i < certificate_chain.entry_count; ++i) {
+ buf = append_size_and_data_to_buf(buf, end, certificate_chain.entries[i].data,
+ certificate_chain.entries[i].data_length);
+ }
+ return buf;
+}
+
+CertificateChain deserialize_chain(const uint8_t** buf_ptr, const uint8_t* end) {
+ size_t entry_count;
+ if (!copy_uint32_from_buf(buf_ptr, end, &entry_count) || entry_count > kMaxChainEntryCount) {
+ return {};
+ }
+
+ CertificateChain certificate_chain(entry_count);
+ if (!certificate_chain.entries) return {};
+
+ for (size_t i = 0; i < certificate_chain.entry_count; ++i) {
+ UniquePtr<uint8_t[]> data;
+ size_t data_length;
+ if (!copy_size_and_data_from_buf(buf_ptr, end, &data_length, &data)) return {};
+ certificate_chain.entries[i].data = data.release();
+ certificate_chain.entries[i].data_length = data_length;
+ }
+
+ return certificate_chain;
+}
+
+} // namespace
+
+int32_t NegotiateMessageVersion(const GetVersionResponse& response, keymaster_error_t* error) {
+ switch (response.major_ver) {
+ case 1: // KM1
+ switch (response.minor_ver) {
+ case 0:
+ return MessageVersion(KmVersion::KEYMASTER_1, 0 /* km_date */);
+ case 1:
+ return MessageVersion(KmVersion::KEYMASTER_1_1, 0 /* km_date */);
+ }
+ break;
+ case 2:
+ return MessageVersion(KmVersion::KEYMASTER_2, 0 /* km_date */);
+ case 3:
+ return MessageVersion(KmVersion::KEYMASTER_3, 0 /* km_date */);
+ case 4:
+ switch (response.minor_ver) {
+ case 0:
+ return MessageVersion(KmVersion::KEYMASTER_4, 0 /* km_date */);
+ case 1:
+ return MessageVersion(KmVersion::KEYMASTER_4_1, 0 /* km_date */);
+ }
+ break;
+ }
+
+ *error = KM_ERROR_UNKNOWN_ERROR;
+ return -1;
+}
+
+int32_t NegotiateMessageVersion(const GetVersion2Request& request,
+ const GetVersion2Response& response) {
+ return request.max_message_version < response.max_message_version
+ ? request.max_message_version
+ : response.max_message_version;
+}
+
size_t KeymasterResponse::SerializedSize() const {
if (error != KM_ERROR_OK)
return sizeof(int32_t);
@@ -77,36 +168,146 @@
uint8_t* KeymasterResponse::Serialize(uint8_t* buf, const uint8_t* end) const {
buf = append_uint32_to_buf(buf, end, static_cast<uint32_t>(error));
- if (error == KM_ERROR_OK)
- buf = NonErrorSerialize(buf, end);
+ if (error == KM_ERROR_OK) buf = NonErrorSerialize(buf, end);
return buf;
}
bool KeymasterResponse::Deserialize(const uint8_t** buf_ptr, const uint8_t* end) {
- if (!copy_uint32_from_buf(buf_ptr, end, &error))
- return false;
- if (error != KM_ERROR_OK)
- return true;
+ if (!copy_uint32_from_buf(buf_ptr, end, &error)) return false;
+ if (error != KM_ERROR_OK) return true;
return NonErrorDeserialize(buf_ptr, end);
}
-GenerateKeyResponse::~GenerateKeyResponse() {
- delete[] key_blob.key_material;
+size_t GenerateKeyRequest::SerializedSize() const {
+ size_t size = key_description.SerializedSize();
+ if (message_version < 4) return size;
+ return size //
+ + key_blob_size(attestation_signing_key_blob) //
+ + attest_key_params.SerializedSize() //
+ + blob_size(issuer_subject);
+}
+
+uint8_t* GenerateKeyRequest::Serialize(uint8_t* buf, const uint8_t* end) const {
+ buf = key_description.Serialize(buf, end);
+ if (message_version < 4) return buf;
+ buf = serialize_key_blob(attestation_signing_key_blob, buf, end);
+ buf = attest_key_params.Serialize(buf, end);
+ return serialize_blob(issuer_subject, buf, end);
+}
+
+bool GenerateKeyRequest::Deserialize(const uint8_t** buf_ptr, const uint8_t* end) {
+ if (!key_description.Deserialize(buf_ptr, end)) return false;
+ if (message_version < 4) return true;
+ return deserialize_key_blob(&attestation_signing_key_blob, buf_ptr, end) //
+ && attest_key_params.Deserialize(buf_ptr, end) //
+ && deserialize_blob(&issuer_subject, buf_ptr, end);
}
size_t GenerateKeyResponse::NonErrorSerializedSize() const {
- return key_blob_size(key_blob) + enforced.SerializedSize() + unenforced.SerializedSize();
+ size_t result =
+ key_blob_size(key_blob) + enforced.SerializedSize() + unenforced.SerializedSize();
+ if (message_version < 4) return result;
+ return result + chain_size(certificate_chain);
}
uint8_t* GenerateKeyResponse::NonErrorSerialize(uint8_t* buf, const uint8_t* end) const {
buf = serialize_key_blob(key_blob, buf, end);
buf = enforced.Serialize(buf, end);
- return unenforced.Serialize(buf, end);
+ buf = unenforced.Serialize(buf, end);
+ if (message_version < 4) return buf;
+ return serialize_chain(certificate_chain, buf, end);
}
bool GenerateKeyResponse::NonErrorDeserialize(const uint8_t** buf_ptr, const uint8_t* end) {
- return deserialize_key_blob(&key_blob, buf_ptr, end) && enforced.Deserialize(buf_ptr, end) &&
- unenforced.Deserialize(buf_ptr, end);
+ if (!deserialize_key_blob(&key_blob, buf_ptr, end) || //
+ !enforced.Deserialize(buf_ptr, end) || //
+ !unenforced.Deserialize(buf_ptr, end)) {
+ return false;
+ }
+ if (message_version < 4) return true;
+ certificate_chain = deserialize_chain(buf_ptr, end);
+ return !!certificate_chain.entries;
+}
+
+size_t GenerateRkpKeyResponse::NonErrorSerializedSize() const {
+ return key_blob_size(key_blob) + blob_size(maced_public_key);
+}
+
+uint8_t* GenerateRkpKeyResponse::NonErrorSerialize(uint8_t* buf, const uint8_t* end) const {
+ buf = serialize_key_blob(key_blob, buf, end);
+ return serialize_blob(maced_public_key, buf, end);
+}
+
+bool GenerateRkpKeyResponse::NonErrorDeserialize(const uint8_t** buf_ptr, const uint8_t* end) {
+ return deserialize_key_blob(&key_blob, buf_ptr, end) &&
+ deserialize_blob(&maced_public_key, buf_ptr, end);
+}
+
+size_t GenerateCsrRequest::SerializedSize() const {
+ size_t size = sizeof(uint8_t); /* test_mode */
+ size += sizeof(uint32_t); /* num_keys */
+ for (size_t i = 0; i < num_keys; i++) {
+ size += blob_size(keys_to_sign_array[i]);
+ }
+ size += blob_size(endpoint_enc_cert_chain);
+ size += blob_size(challenge);
+ return size;
+}
+
+uint8_t* GenerateCsrRequest::Serialize(uint8_t* buf, const uint8_t* end) const {
+ buf = append_to_buf(buf, end, &test_mode, sizeof(uint8_t));
+ buf = append_uint32_to_buf(buf, end, num_keys);
+ for (size_t i = 0; i < num_keys; i++) {
+ buf = serialize_blob(keys_to_sign_array[i], buf, end);
+ }
+ buf = serialize_blob(endpoint_enc_cert_chain, buf, end);
+ return serialize_blob(challenge, buf, end);
+}
+
+bool GenerateCsrRequest::Deserialize(const uint8_t** buf_ptr, const uint8_t* end) {
+ if (!copy_from_buf(buf_ptr, end, &test_mode, sizeof(uint8_t)) ||
+ !copy_from_buf(buf_ptr, end, &num_keys, sizeof(uint32_t))) {
+ return false;
+ }
+ keys_to_sign_array = new (std::nothrow) KeymasterBlob[num_keys];
+ if (!keys_to_sign_array) return false;
+ for (size_t i = 0; i < num_keys; i++) {
+ if (!deserialize_blob(&keys_to_sign_array[i], buf_ptr, end)) return false;
+ }
+ return deserialize_blob(&endpoint_enc_cert_chain, buf_ptr, end) &&
+ deserialize_blob(&challenge, buf_ptr, end);
+}
+
+void GenerateCsrRequest::SetKeyToSign(uint32_t index, const void* data, size_t length) {
+ if (index >= num_keys) {
+ return;
+ }
+ set_blob(&keys_to_sign_array[index], data, length);
+}
+
+void GenerateCsrRequest::SetEndpointEncCertChain(const void* data, size_t length) {
+ set_blob(&endpoint_enc_cert_chain, data, length);
+}
+
+void GenerateCsrRequest::SetChallenge(const void* data, size_t length) {
+ set_blob(&challenge, data, length);
+}
+
+size_t GenerateCsrResponse::NonErrorSerializedSize() const {
+ return blob_size(keys_to_sign_mac) + blob_size(device_info_blob) +
+ blob_size(protected_data_blob);
+}
+
+uint8_t* GenerateCsrResponse::NonErrorSerialize(uint8_t* buf, const uint8_t* end) const {
+ buf = serialize_blob(keys_to_sign_mac, buf, end);
+ buf = serialize_blob(device_info_blob, buf, end);
+ return serialize_blob(protected_data_blob, buf, end);
+}
+
+bool GenerateCsrResponse::NonErrorDeserialize(const uint8_t** buf_ptr, const uint8_t* end) {
+ return deserialize_blob(&keys_to_sign_mac, buf_ptr, end) &&
+ deserialize_blob(&device_info_blob, buf_ptr, end) &&
+ deserialize_blob(&protected_data_blob, buf_ptr, end);
}
GetKeyCharacteristicsRequest::~GetKeyCharacteristicsRequest() {
@@ -175,15 +376,13 @@
uint8_t* BeginOperationResponse::NonErrorSerialize(uint8_t* buf, const uint8_t* end) const {
buf = append_uint64_to_buf(buf, end, op_handle);
- if (message_version > 0)
- buf = output_params.Serialize(buf, end);
+ if (message_version > 0) buf = output_params.Serialize(buf, end);
return buf;
}
bool BeginOperationResponse::NonErrorDeserialize(const uint8_t** buf_ptr, const uint8_t* end) {
bool retval = copy_uint64_from_buf(buf_ptr, end, &op_handle);
- if (retval && message_version > 0)
- retval = output_params.Deserialize(buf_ptr, end);
+ if (retval && message_version > 0) retval = output_params.Deserialize(buf_ptr, end);
return retval;
}
@@ -197,21 +396,20 @@
uint8_t* UpdateOperationRequest::Serialize(uint8_t* buf, const uint8_t* end) const {
buf = append_uint64_to_buf(buf, end, op_handle);
buf = input.Serialize(buf, end);
- if (message_version > 0)
- buf = additional_params.Serialize(buf, end);
+ if (message_version > 0) buf = additional_params.Serialize(buf, end);
return buf;
}
bool UpdateOperationRequest::Deserialize(const uint8_t** buf_ptr, const uint8_t* end) {
bool retval = copy_uint64_from_buf(buf_ptr, end, &op_handle) && input.Deserialize(buf_ptr, end);
- if (retval && message_version > 0)
- retval = additional_params.Deserialize(buf_ptr, end);
+ if (retval && message_version > 0) retval = additional_params.Deserialize(buf_ptr, end);
return retval;
}
size_t UpdateOperationResponse::NonErrorSerializedSize() const {
size_t size = 0;
switch (message_version) {
+ case 4:
case 3:
case 2:
size += output_params.SerializedSize();
@@ -232,25 +430,22 @@
uint8_t* UpdateOperationResponse::NonErrorSerialize(uint8_t* buf, const uint8_t* end) const {
buf = output.Serialize(buf, end);
- if (message_version > 0)
- buf = append_uint32_to_buf(buf, end, input_consumed);
- if (message_version > 1)
- buf = output_params.Serialize(buf, end);
+ if (message_version > 0) buf = append_uint32_to_buf(buf, end, input_consumed);
+ if (message_version > 1) buf = output_params.Serialize(buf, end);
return buf;
}
bool UpdateOperationResponse::NonErrorDeserialize(const uint8_t** buf_ptr, const uint8_t* end) {
bool retval = output.Deserialize(buf_ptr, end);
- if (retval && message_version > 0)
- retval = copy_uint32_from_buf(buf_ptr, end, &input_consumed);
- if (retval && message_version > 1)
- retval = output_params.Deserialize(buf_ptr, end);
+ if (retval && message_version > 0) retval = copy_uint32_from_buf(buf_ptr, end, &input_consumed);
+ if (retval && message_version > 1) retval = output_params.Deserialize(buf_ptr, end);
return retval;
}
size_t FinishOperationRequest::SerializedSize() const {
size_t size = 0;
switch (message_version) {
+ case 4:
case 3:
size += input.SerializedSize();
FALLTHROUGH;
@@ -272,20 +467,16 @@
uint8_t* FinishOperationRequest::Serialize(uint8_t* buf, const uint8_t* end) const {
buf = append_uint64_to_buf(buf, end, op_handle);
buf = signature.Serialize(buf, end);
- if (message_version > 0)
- buf = additional_params.Serialize(buf, end);
- if (message_version > 2)
- buf = input.Serialize(buf, end);
+ if (message_version > 0) buf = additional_params.Serialize(buf, end);
+ if (message_version > 2) buf = input.Serialize(buf, end);
return buf;
}
bool FinishOperationRequest::Deserialize(const uint8_t** buf_ptr, const uint8_t* end) {
bool retval =
copy_uint64_from_buf(buf_ptr, end, &op_handle) && signature.Deserialize(buf_ptr, end);
- if (retval && message_version > 0)
- retval = additional_params.Deserialize(buf_ptr, end);
- if (retval && message_version > 2)
- retval = input.Deserialize(buf_ptr, end);
+ if (retval && message_version > 0) retval = additional_params.Deserialize(buf_ptr, end);
+ if (retval && message_version > 2) retval = input.Deserialize(buf_ptr, end);
return retval;
}
@@ -298,15 +489,13 @@
uint8_t* FinishOperationResponse::NonErrorSerialize(uint8_t* buf, const uint8_t* end) const {
buf = output.Serialize(buf, end);
- if (message_version > 1)
- buf = output_params.Serialize(buf, end);
+ if (message_version > 1) buf = output_params.Serialize(buf, end);
return buf;
}
bool FinishOperationResponse::NonErrorDeserialize(const uint8_t** buf_ptr, const uint8_t* end) {
bool retval = output.Deserialize(buf_ptr, end);
- if (retval && message_version > 1)
- retval = output_params.Deserialize(buf_ptr, end);
+ if (retval && message_version > 1) retval = output_params.Deserialize(buf_ptr, end);
return retval;
}
@@ -322,33 +511,38 @@
return random_data.Deserialize(buf_ptr, end);
}
-void ImportKeyRequest::SetKeyMaterial(const void* key_material, size_t length) {
- delete[] key_data;
- key_data = dup_buffer(key_material, length);
- key_data_length = length;
-}
-
size_t ImportKeyRequest::SerializedSize() const {
- return key_description.SerializedSize() + sizeof(uint32_t) /* key_format */ +
- sizeof(uint32_t) /* key_data_length */ + key_data_length;
+ size_t size = key_description.SerializedSize() //
+ + sizeof(uint32_t) /* key_format */ //
+ + key_blob_size(key_data);
+ if (message_version < 4) return size;
+ return size //
+ + key_blob_size(attestation_signing_key_blob) //
+ + attest_key_params.SerializedSize() //
+ + blob_size(issuer_subject);
}
uint8_t* ImportKeyRequest::Serialize(uint8_t* buf, const uint8_t* end) const {
buf = key_description.Serialize(buf, end);
buf = append_uint32_to_buf(buf, end, key_format);
- return append_size_and_data_to_buf(buf, end, key_data, key_data_length);
+ buf = serialize_key_blob(key_data, buf, end);
+ if (message_version < 4) return buf;
+ buf = serialize_key_blob(attestation_signing_key_blob, buf, end);
+ buf = attest_key_params.Serialize(buf, end);
+ return serialize_blob(issuer_subject, buf, end);
}
bool ImportKeyRequest::Deserialize(const uint8_t** buf_ptr, const uint8_t* end) {
- delete[] key_data;
- key_data = nullptr;
- UniquePtr<uint8_t[]> deserialized_key_material;
- if (!key_description.Deserialize(buf_ptr, end) ||
- !copy_uint32_from_buf(buf_ptr, end, &key_format) ||
- !copy_size_and_data_from_buf(buf_ptr, end, &key_data_length, &deserialized_key_material))
+ if (!(key_description.Deserialize(buf_ptr, end) &&
+ copy_uint32_from_buf(buf_ptr, end, &key_format) &&
+ deserialize_key_blob(&key_data, buf_ptr, end))) {
return false;
- key_data = deserialized_key_material.release();
- return true;
+ }
+ if (message_version < 4) return true;
+
+ return deserialize_key_blob(&attestation_signing_key_blob, buf_ptr, end) //
+ && attest_key_params.Deserialize(buf_ptr, end) //
+ && deserialize_blob(&issuer_subject, buf_ptr, end);
}
void ImportKeyResponse::SetKeyMaterial(const void* key_material, size_t length) {
@@ -356,18 +550,29 @@
}
size_t ImportKeyResponse::NonErrorSerializedSize() const {
- return key_blob_size(key_blob) + enforced.SerializedSize() + unenforced.SerializedSize();
+ size_t result =
+ key_blob_size(key_blob) + enforced.SerializedSize() + unenforced.SerializedSize();
+ if (message_version < 4) return result;
+ return result + chain_size(certificate_chain);
}
uint8_t* ImportKeyResponse::NonErrorSerialize(uint8_t* buf, const uint8_t* end) const {
buf = serialize_key_blob(key_blob, buf, end);
buf = enforced.Serialize(buf, end);
- return unenforced.Serialize(buf, end);
+ buf = unenforced.Serialize(buf, end);
+ if (message_version < 4) return buf;
+ return serialize_chain(certificate_chain, buf, end);
}
bool ImportKeyResponse::NonErrorDeserialize(const uint8_t** buf_ptr, const uint8_t* end) {
- return deserialize_key_blob(&key_blob, buf_ptr, end) && enforced.Deserialize(buf_ptr, end) &&
- unenforced.Deserialize(buf_ptr, end);
+ if (!deserialize_key_blob(&key_blob, buf_ptr, end) || //
+ !enforced.Deserialize(buf_ptr, end) || //
+ !unenforced.Deserialize(buf_ptr, end)) {
+ return false;
+ }
+ if (message_version < 4) return true;
+ certificate_chain = deserialize_chain(buf_ptr, end);
+ return !!certificate_chain.entries;
}
void ExportKeyRequest::SetKeyMaterial(const void* key_material, size_t length) {
@@ -447,8 +652,7 @@
}
bool GetVersionResponse::NonErrorDeserialize(const uint8_t** buf_ptr, const uint8_t* end) {
- if (*buf_ptr + NonErrorSerializedSize() > end)
- return false;
+ if (*buf_ptr + NonErrorSerializedSize() > end) return false;
const uint8_t* tmp = *buf_ptr;
major_ver = *tmp++;
minor_ver = *tmp++;
@@ -478,67 +682,17 @@
return deserialize_key_blob(&key_blob, buf_ptr, end) && attest_params.Deserialize(buf_ptr, end);
}
-AttestKeyResponse::~AttestKeyResponse() {
- for (size_t i = 0; i < certificate_chain.entry_count; ++i)
- delete[] certificate_chain.entries[i].data;
- delete[] certificate_chain.entries;
-}
-
-const size_t kMaxChainEntryCount = 10;
-bool AttestKeyResponse::AllocateChain(size_t entry_count) {
- if (entry_count > kMaxChainEntryCount)
- return false;
-
- if (certificate_chain.entries) {
- for (size_t i = 0; i < certificate_chain.entry_count; ++i)
- delete[] certificate_chain.entries[i].data;
- delete[] certificate_chain.entries;
- }
-
- certificate_chain.entry_count = entry_count;
- certificate_chain.entries = new (std::nothrow) keymaster_blob_t[entry_count];
- if (!certificate_chain.entries) {
- certificate_chain.entry_count = 0;
- return false;
- }
-
- memset(certificate_chain.entries, 0, sizeof(certificate_chain.entries[0]) * entry_count);
- return true;
-}
-
size_t AttestKeyResponse::NonErrorSerializedSize() const {
- size_t result = sizeof(uint32_t); /* certificate_chain.entry_count */
- for (size_t i = 0; i < certificate_chain.entry_count; ++i) {
- result += sizeof(uint32_t); /* certificate_chain.entries[i].data_length */
- result += certificate_chain.entries[i].data_length;
- }
- return result;
+ return chain_size(certificate_chain);
}
uint8_t* AttestKeyResponse::NonErrorSerialize(uint8_t* buf, const uint8_t* end) const {
- buf = append_uint32_to_buf(buf, end, certificate_chain.entry_count);
- for (size_t i = 0; i < certificate_chain.entry_count; ++i) {
- buf = append_size_and_data_to_buf(buf, end, certificate_chain.entries[i].data,
- certificate_chain.entries[i].data_length);
- }
- return buf;
+ return serialize_chain(certificate_chain, buf, end);
}
bool AttestKeyResponse::NonErrorDeserialize(const uint8_t** buf_ptr, const uint8_t* end) {
- size_t entry_count;
- if (!copy_uint32_from_buf(buf_ptr, end, &entry_count) || !AllocateChain(entry_count))
- return false;
-
- for (size_t i = 0; i < certificate_chain.entry_count; ++i) {
- UniquePtr<uint8_t[]> data;
- size_t data_length;
- if (!copy_size_and_data_from_buf(buf_ptr, end, &data_length, &data))
- return false;
- certificate_chain.entries[i].data = data.release();
- certificate_chain.entries[i].data_length = data_length;
- }
-
- return true;
+ certificate_chain = deserialize_chain(buf_ptr, end);
+ return !!certificate_chain.entries;
}
UpgradeKeyRequest::~UpgradeKeyRequest() {
@@ -632,11 +786,9 @@
}
size_t ImportWrappedKeyRequest::SerializedSize() const {
- return sizeof(uint32_t) /* wrapped_key_data_length */ + wrapped_key.key_material_size +
- sizeof(uint32_t) /* wrapping_key_data_length */ + wrapping_key.key_material_size +
- sizeof(uint32_t) /* masking_key_data_length */ + masking_key.key_material_size +
- additional_params.SerializedSize() + sizeof(uint64_t) /* password_sid */ +
- sizeof(uint64_t) /* biometric_sid */;
+ return key_blob_size(wrapped_key) + key_blob_size(wrapping_key) + key_blob_size(masking_key) +
+ additional_params.SerializedSize() + sizeof(uint64_t) // password_sid
+ + sizeof(uint64_t); // biometric_sid
}
uint8_t* ImportWrappedKeyRequest::Serialize(uint8_t* buf, const uint8_t* end) const {
@@ -674,18 +826,29 @@
}
size_t ImportWrappedKeyResponse::NonErrorSerializedSize() const {
- return key_blob_size(key_blob) + enforced.SerializedSize() + unenforced.SerializedSize();
+ size_t result =
+ key_blob_size(key_blob) + enforced.SerializedSize() + unenforced.SerializedSize();
+ if (message_version < 4) return result;
+ return result + chain_size(certificate_chain);
}
uint8_t* ImportWrappedKeyResponse::NonErrorSerialize(uint8_t* buf, const uint8_t* end) const {
buf = serialize_key_blob(key_blob, buf, end);
buf = enforced.Serialize(buf, end);
- return unenforced.Serialize(buf, end);
+ buf = unenforced.Serialize(buf, end);
+ if (message_version < 4) return buf;
+ return serialize_chain(certificate_chain, buf, end);
}
bool ImportWrappedKeyResponse::NonErrorDeserialize(const uint8_t** buf_ptr, const uint8_t* end) {
- return deserialize_key_blob(&key_blob, buf_ptr, end) && enforced.Deserialize(buf_ptr, end) &&
- unenforced.Deserialize(buf_ptr, end);
+ if (!deserialize_key_blob(&key_blob, buf_ptr, end) || //
+ !enforced.Deserialize(buf_ptr, end) || //
+ !unenforced.Deserialize(buf_ptr, end)) {
+ return false;
+ }
+ if (message_version < 4) return true;
+ certificate_chain = deserialize_chain(buf_ptr, end);
+ return !!certificate_chain.entries;
}
size_t HardwareAuthToken::SerializedSize() const {
@@ -732,4 +895,22 @@
deserialize_blob(&mac, buf_ptr, end);
}
+size_t GetVersion2Response::NonErrorSerializedSize() const {
+ return sizeof(max_message_version) + //
+ sizeof(km_version) + //
+ sizeof(km_date);
+}
+
+uint8_t* GetVersion2Response::NonErrorSerialize(uint8_t* buf, const uint8_t* end) const {
+ buf = append_uint32_to_buf(buf, end, max_message_version);
+ buf = append_uint32_to_buf(buf, end, km_version);
+ return append_uint32_to_buf(buf, end, km_date);
+}
+
+bool GetVersion2Response::NonErrorDeserialize(const uint8_t** buf_ptr, const uint8_t* end) {
+ return copy_uint32_from_buf(buf_ptr, end, &max_message_version) &&
+ copy_uint32_from_buf(buf_ptr, end, &km_version) &&
+ copy_uint32_from_buf(buf_ptr, end, &km_date);
+}
+
} // namespace keymaster
diff --git a/android_keymaster/android_keymaster_utils.cpp b/android_keymaster/android_keymaster_utils.cpp
index fb45fc9..b966a61 100644
--- a/android_keymaster/android_keymaster_utils.cpp
+++ b/android_keymaster/android_keymaster_utils.cpp
@@ -14,9 +14,9 @@
* limitations under the License.
*/
-#include <keymaster/android_keymaster_utils.h>
+#include <new>
-#include <keymaster/new.h>
+#include <keymaster/android_keymaster_utils.h>
namespace keymaster {
@@ -25,11 +25,9 @@
const size_t kMaxDupBufferSize = 16 * 1024 * 1024;
uint8_t* dup_buffer(const void* buf, size_t size) {
- if (size >= kMaxDupBufferSize)
- return nullptr;
+ if (size >= kMaxDupBufferSize) return nullptr;
uint8_t* retval = new (std::nothrow) uint8_t[size];
- if (retval)
- memcpy(retval, buf, size);
+ if (retval) memcpy(retval, buf, size);
return retval;
}
diff --git a/android_keymaster/authorization_set.cpp b/android_keymaster/authorization_set.cpp
index e09b73c..2d76cad 100644
--- a/android_keymaster/authorization_set.cpp
+++ b/android_keymaster/authorization_set.cpp
@@ -21,8 +21,6 @@
#include <stdlib.h>
#include <string.h>
-#include <keymaster/new.h>
-
#include <keymaster/android_keymaster_utils.h>
#include <keymaster/logger.h>
@@ -62,8 +60,7 @@
}
bool AuthorizationSet::reserve_elems(size_t count) {
- if (is_valid() != OK)
- return false;
+ if (is_valid() != OK) return false;
if (count > elems_capacity_) {
keymaster_key_param_t* new_elems = new (std::nothrow) keymaster_key_param_t[count];
@@ -80,8 +77,7 @@
}
bool AuthorizationSet::reserve_indirect(size_t length) {
- if (is_valid() != OK)
- return false;
+ if (is_valid() != OK) return false;
if (length > indirect_data_capacity_) {
uint8_t* new_data = new (std::nothrow) uint8_t[length];
@@ -128,11 +124,9 @@
return true;
}
- if (!reserve_elems(count))
- return false;
+ if (!reserve_elems(count)) return false;
- if (!reserve_indirect(ComputeIndirectDataSize(elems, count)))
- return false;
+ if (!reserve_indirect(ComputeIndirectDataSize(elems, count))) return false;
memcpy(elems_, elems, sizeof(keymaster_key_param_t) * count);
elems_size_ = count;
@@ -166,11 +160,9 @@
++invalid_count;
}
}
- if (size() > 0 && elems_[size() - 1].tag == KM_TAG_INVALID)
- ++invalid_count;
+ if (size() > 0 && elems_[size() - 1].tag == KM_TAG_INVALID) ++invalid_count;
- if (invalid_count == 0)
- return;
+ if (invalid_count == 0) return;
Sort();
@@ -180,16 +172,14 @@
}
void AuthorizationSet::Union(const keymaster_key_param_set_t& set) {
- if (set.length == 0)
- return;
+ if (set.length == 0) return;
push_back(set);
Deduplicate();
}
void AuthorizationSet::Difference(const keymaster_key_param_set_t& set) {
- if (set.length == 0)
- return;
+ if (set.length == 0) return;
Deduplicate();
@@ -227,8 +217,7 @@
}
int AuthorizationSet::find(keymaster_tag_t tag, int begin) const {
- if (is_valid() != OK)
- return -1;
+ if (is_valid() != OK) return -1;
int i = ++begin;
while (i < (int)elems_size_ && elems_[i].tag != tag)
@@ -240,8 +229,7 @@
}
bool AuthorizationSet::erase(int index) {
- if (index < 0 || index >= static_cast<int>(size()))
- return false;
+ if (index < 0 || index >= static_cast<int>(size())) return false;
--elems_size_;
for (size_t i = index; i < elems_size_; ++i)
@@ -267,25 +255,21 @@
}
bool AuthorizationSet::push_back(const keymaster_key_param_set_t& set) {
- if (is_valid() != OK)
- return false;
+ if (is_valid() != OK) return false;
- if (!reserve_elems(elems_size_ + set.length))
- return false;
+ if (!reserve_elems(elems_size_ + set.length)) return false;
if (!reserve_indirect(indirect_data_size_ + ComputeIndirectDataSize(set.params, set.length)))
return false;
for (size_t i = 0; i < set.length; ++i)
- if (!push_back(set.params[i]))
- return false;
+ if (!push_back(set.params[i])) return false;
return true;
}
bool AuthorizationSet::push_back(keymaster_key_param_t elem) {
- if (is_valid() != OK)
- return false;
+ if (is_valid() != OK) return false;
if (elems_size_ >= elems_capacity_)
if (!reserve_elems(elems_capacity_ ? elems_capacity_ * 2 : STARTING_ELEMS_CAPACITY))
@@ -350,8 +334,7 @@
buf = append_uint64_to_buf(buf, end, param.date_time);
break;
case KM_BOOL:
- if (buf < end)
- *buf = static_cast<uint8_t>(param.boolean);
+ if (buf < end) *buf = static_cast<uint8_t>(param.boolean);
buf++;
break;
case KM_BIGNUM:
@@ -365,8 +348,7 @@
static bool deserialize(keymaster_key_param_t* param, const uint8_t** buf_ptr, const uint8_t* end,
const uint8_t* indirect_base, const uint8_t* indirect_end) {
- if (!copy_uint32_from_buf(buf_ptr, end, ¶m->tag))
- return false;
+ if (!copy_uint32_from_buf(buf_ptr, end, ¶m->tag)) return false;
switch (keymaster_tag_get_type(param->tag)) {
case KM_INVALID:
@@ -465,11 +447,11 @@
// elems_ arrays which are clearly too large to be reasonable.
size_t elems_refs_size;
size_t elems_alloc_size;
- bool refs_size_overflow = __builtin_mul_overflow(elements_count, sizeof(uint32_t),
- &elems_refs_size);
- bool alloc_size_overflow = __builtin_mul_overflow(elements_count, sizeof(*elems_),
- &elems_alloc_size);
- /* elements_size must fit in the buffer */
+ bool refs_size_overflow =
+ __builtin_mul_overflow(elements_count, sizeof(uint32_t), &elems_refs_size);
+ bool alloc_size_overflow =
+ __builtin_mul_overflow(elements_count, sizeof(*elems_), &elems_alloc_size);
+ /* elements_size must fit in the buffer */
if (static_cast<ptrdiff_t>(elements_size) > end - *buf_ptr ||
/* The element refs must all fit within elements_size */
elems_refs_size > elements_size ||
@@ -482,8 +464,7 @@
return false;
}
- if (!reserve_elems(elements_count))
- return false;
+ if (!reserve_elems(elements_count)) return false;
uint8_t* indirect_end = indirect_data_ + indirect_data_size_;
const uint8_t* elements_end = *buf_ptr + elements_size;
@@ -677,15 +658,13 @@
bool AuthorizationSet::ContainsEnumValue(keymaster_tag_t tag, uint32_t value) const {
for (auto& entry : *this)
- if (entry.tag == tag && entry.enumerated == value)
- return true;
+ if (entry.tag == tag && entry.enumerated == value) return true;
return false;
}
bool AuthorizationSet::ContainsIntValue(keymaster_tag_t tag, uint32_t value) const {
for (auto& entry : *this)
- if (entry.tag == tag && entry.integer == value)
- return true;
+ if (entry.tag == tag && entry.integer == value) return true;
return false;
}
diff --git a/android_keymaster/keymaster_configuration.cpp b/android_keymaster/keymaster_configuration.cpp
index 0bcf6f9..ca78863 100644
--- a/android_keymaster/keymaster_configuration.cpp
+++ b/android_keymaster/keymaster_configuration.cpp
@@ -40,14 +40,15 @@
constexpr size_t kPlatformVersionMatchCount = kSubminorVersionMatch + 1;
constexpr char kPlatformPatchlevelProp[] = "ro.build.version.security_patch";
-constexpr char kPlatformPatchlevelRegex[] = "^([0-9]{4})-([0-9]{2})-[0-9]{2}$";
+constexpr char kVendorPatchlevelProp[] = "ro.vendor.build.security_patch";
+constexpr char kPatchlevelRegex[] = "^([0-9]{4})-([0-9]{2})-([0-9]{2})$";
constexpr size_t kYearMatch = 1;
constexpr size_t kMonthMatch = 2;
-constexpr size_t kPlatformPatchlevelMatchCount = kMonthMatch + 1;
+constexpr size_t kDayMatch = 3;
+constexpr size_t kPatchlevelMatchCount = kDayMatch + 1;
uint32_t match_to_uint32(const char* expression, const regmatch_t& match) {
- if (match.rm_so == -1)
- return 0;
+ if (match.rm_so == -1) return 0;
size_t len = match.rm_eo - match.rm_so;
std::string s(expression + match.rm_so, len);
@@ -65,6 +66,46 @@
return prop_value;
}
+enum class PatchlevelOutput { kYearMonthDay, kYearMonth };
+
+uint32_t GetPatchlevel(const char* patchlevel_str, PatchlevelOutput detail) {
+ regex_t regex;
+ if (regcomp(®ex, kPatchlevelRegex, REG_EXTENDED) != 0) {
+ ALOGE("Failed to compile platform patchlevel regex! (%s)", kPatchlevelRegex);
+ return 0;
+ }
+
+ regmatch_t matches[kPatchlevelMatchCount];
+ int not_match = regexec(®ex, patchlevel_str, kPatchlevelMatchCount, matches, 0 /* flags */);
+ regfree(®ex);
+ if (not_match) {
+ ALOGI(" patchlevel string does not match expected format. Using patchlevel 0");
+ return 0;
+ }
+
+ uint32_t year = match_to_uint32(patchlevel_str, matches[kYearMatch]);
+ uint32_t month = match_to_uint32(patchlevel_str, matches[kMonthMatch]);
+
+ if (month < 1 || month > 12) {
+ ALOGE("Invalid patch month %d", month);
+ return 0;
+ }
+
+ switch (detail) {
+ case PatchlevelOutput::kYearMonthDay: {
+ uint32_t day = match_to_uint32(patchlevel_str, matches[kDayMatch]);
+ if (day < 1 || day > 31) {
+ ALOGE("Invalid patch day %d", day);
+ return 0;
+ }
+ return year * 10000 + month * 100 + day;
+ }
+ case PatchlevelOutput::kYearMonth:
+ return year * 100 + month;
+ }
+ return 0;
+}
+
} // anonymous namespace
keymaster_error_t ConfigureDevice(keymaster2_device_t* dev, uint32_t os_version,
@@ -91,7 +132,8 @@
regexec(®ex, version_str, kPlatformVersionMatchCount, matches, 0 /* flags */);
regfree(®ex);
if (not_match) {
- ALOGI("Platform version string does not match expected format. Using version 0.");
+ ALOGI("Platform version string \"%s\" does not match expected format. Using version 0.",
+ version_str);
return 0;
}
@@ -108,29 +150,7 @@
}
uint32_t GetOsPatchlevel(const char* patchlevel_str) {
- regex_t regex;
- if (regcomp(®ex, kPlatformPatchlevelRegex, REG_EXTENDED) != 0) {
- ALOGE("Failed to compile platform patchlevel regex! (%s)", kPlatformPatchlevelRegex);
- return 0;
- }
-
- regmatch_t matches[kPlatformPatchlevelMatchCount];
- int not_match =
- regexec(®ex, patchlevel_str, kPlatformPatchlevelMatchCount, matches, 0 /* flags */);
- regfree(®ex);
- if (not_match) {
- ALOGI("Platform patchlevel string does not match expected format. Using patchlevel 0");
- return 0;
- }
-
- uint32_t year = match_to_uint32(patchlevel_str, matches[kYearMatch]);
- uint32_t month = match_to_uint32(patchlevel_str, matches[kMonthMatch]);
-
- if (month < 1 || month > 12) {
- ALOGE("Invalid patch month %d", month);
- return 0;
- }
- return year * 100 + month;
+ return GetPatchlevel(patchlevel_str, PatchlevelOutput::kYearMonth);
}
uint32_t GetOsPatchlevel() {
@@ -138,4 +158,9 @@
return GetOsPatchlevel(patchlevel.c_str());
}
+uint32_t GetVendorPatchlevel() {
+ std::string patchlevel = wait_and_get_property(kVendorPatchlevelProp);
+ return GetPatchlevel(patchlevel.c_str(), PatchlevelOutput::kYearMonthDay);
+}
+
} // namespace keymaster
diff --git a/android_keymaster/keymaster_enforcement.cpp b/android_keymaster/keymaster_enforcement.cpp
index 8f07cbf..de768cb 100644
--- a/android_keymaster/keymaster_enforcement.cpp
+++ b/android_keymaster/keymaster_enforcement.cpp
@@ -23,9 +23,9 @@
#include <openssl/evp.h>
#include <hardware/hw_auth_token.h>
+#include <keymaster/List.h>
#include <keymaster/android_keymaster_utils.h>
#include <keymaster/logger.h>
-#include <keymaster/List.h>
namespace keymaster {
@@ -86,8 +86,8 @@
case KM_PURPOSE_SIGN:
case KM_PURPOSE_DECRYPT:
case KM_PURPOSE_WRAP:
- if (auth_set.Contains(TAG_PURPOSE, purpose))
- return KM_ERROR_OK;
+ case KM_PURPOSE_AGREE_KEY:
+ if (auth_set.Contains(TAG_PURPOSE, purpose)) return KM_ERROR_OK;
return KM_ERROR_INCOMPATIBLE_PURPOSE;
default:
@@ -130,6 +130,8 @@
case KM_PURPOSE_SIGN:
case KM_PURPOSE_DERIVE_KEY:
case KM_PURPOSE_WRAP:
+ case KM_PURPOSE_AGREE_KEY:
+ case KM_PURPOSE_ATTEST_KEY:
break;
};
};
@@ -147,7 +149,6 @@
const AuthorizationSet& operation_params,
keymaster_operation_handle_t op_handle) {
int auth_type_index = -1;
- int trusted_confirmation_index = -1;
bool no_auth_required = false;
for (size_t pos = 0; pos < auth_set.size(); ++pos) {
switch (auth_set[pos].tag) {
@@ -155,9 +156,6 @@
auth_type_index = pos;
break;
- case KM_TAG_TRUSTED_CONFIRMATION_REQUIRED:
- trusted_confirmation_index = pos;
- break;
case KM_TAG_NO_AUTH_REQUIRED:
case KM_TAG_AUTH_TIMEOUT:
// If no auth is required or if auth is timeout-based, we have nothing to check.
@@ -168,12 +166,6 @@
}
}
- // TODO verify trusted confirmation mac once we have a shared secret established
- // For now, since we do not have such a service, any token offered here must be invalid.
- if (trusted_confirmation_index != -1) {
- return KM_ERROR_NO_USER_CONFIRMATION;
- }
-
// If NO_AUTH_REQUIRED or AUTH_TIMEOUT was set, we need not check an auth token.
if (no_auth_required) {
return KM_ERROR_OK;
@@ -230,8 +222,7 @@
}
keymaster_error_t error = authorized_purpose(purpose, auth_set);
- if (error != KM_ERROR_OK)
- return error;
+ if (error != KM_ERROR_OK) return error;
// If successful, and if key has a min time between ops, this will be set to the time limit
uint32_t min_ops_timeout = UINT32_MAX;
@@ -245,14 +236,12 @@
// KM_TAG_PADDING_OLD and KM_TAG_DIGEST_OLD aren't actually members of the enum, so we can't
// switch on them. There's nothing to validate for them, though, so just ignore them.
- if (param.tag == KM_TAG_PADDING_OLD || param.tag == KM_TAG_DIGEST_OLD)
- continue;
+ if (param.tag == KM_TAG_PADDING_OLD || param.tag == KM_TAG_DIGEST_OLD) continue;
switch (param.tag) {
case KM_TAG_ACTIVE_DATETIME:
- if (!activation_date_valid(param.date_time))
- return KM_ERROR_KEY_NOT_YET_VALID;
+ if (!activation_date_valid(param.date_time)) return KM_ERROR_KEY_NOT_YET_VALID;
break;
case KM_TAG_ORIGINATION_EXPIRE_DATETIME:
@@ -292,6 +281,22 @@
}
break;
+ case KM_TAG_UNLOCKED_DEVICE_REQUIRED:
+ if (device_locked_at_ > 0) {
+ const hw_auth_token_t* auth_token;
+ uint32_t token_auth_type;
+ if (!GetAndValidateAuthToken(operation_params, &auth_token, &token_auth_type)) {
+ return KM_ERROR_DEVICE_LOCKED;
+ }
+
+ uint64_t token_timestamp_millis = ntoh(auth_token->timestamp);
+ if (token_timestamp_millis <= device_locked_at_ ||
+ (password_unlock_only_ && !(token_auth_type & HW_AUTH_PASSWORD))) {
+ return KM_ERROR_DEVICE_LOCKED;
+ }
+ }
+ break;
+
case KM_TAG_CALLER_NONCE:
caller_nonce_authorized_by_key = true;
break;
@@ -311,6 +316,11 @@
case KM_TAG_ATTESTATION_ID_MEID:
case KM_TAG_ATTESTATION_ID_MANUFACTURER:
case KM_TAG_ATTESTATION_ID_MODEL:
+ case KM_TAG_DEVICE_UNIQUE_ATTESTATION:
+ case KM_TAG_CERTIFICATE_SUBJECT:
+ case KM_TAG_CERTIFICATE_SERIAL:
+ case KM_TAG_CERTIFICATE_NOT_AFTER:
+ case KM_TAG_CERTIFICATE_NOT_BEFORE:
return KM_ERROR_INVALID_KEY_BLOB;
/* Tags used for cryptographic parameters in keygen. Nothing to enforce. */
@@ -333,12 +343,14 @@
/* Algorithm specific parameters not used for access control. */
case KM_TAG_RSA_PUBLIC_EXPONENT:
case KM_TAG_ECIES_SINGLE_HASH_MODE:
+ case KM_TAG_RSA_OAEP_MGF_DIGEST:
/* Informational tags. */
case KM_TAG_CREATION_DATETIME:
case KM_TAG_ORIGIN:
case KM_TAG_ROLLBACK_RESISTANCE:
case KM_TAG_ROLLBACK_RESISTANT:
+ case KM_TAG_USER_ID:
/* Tags handled when KM_TAG_USER_SECURE_ID is handled */
case KM_TAG_NO_AUTH_REQUIRED:
@@ -353,26 +365,32 @@
case KM_TAG_APPLICATION_ID:
case KM_TAG_OS_VERSION:
case KM_TAG_OS_PATCHLEVEL:
+ case KM_TAG_BOOT_PATCHLEVEL:
+ case KM_TAG_VENDOR_PATCHLEVEL:
+ case KM_TAG_STORAGE_KEY:
/* Ignored pending removal */
case KM_TAG_ALL_USERS:
- /* TODO(swillden): Handle these */
+ /* Tags that are not enforced by begin */
case KM_TAG_INCLUDE_UNIQUE_ID:
case KM_TAG_UNIQUE_ID:
case KM_TAG_RESET_SINCE_ID_ROTATION:
case KM_TAG_ALLOW_WHILE_ON_BODY:
case KM_TAG_TRUSTED_CONFIRMATION_REQUIRED:
+ case KM_TAG_TRUSTED_USER_PRESENCE_REQUIRED:
+ case KM_TAG_CONFIRMATION_TOKEN:
+ case KM_TAG_USAGE_COUNT_LIMIT:
+ case KM_TAG_MAX_BOOT_LEVEL:
break;
- /* TODO(bcyoung): This is currently handled in keystore, but may move to keymaster in the
- * future */
- case KM_TAG_USER_ID:
- case KM_TAG_UNLOCKED_DEVICE_REQUIRED:
- break;
-
+ case KM_TAG_IDENTITY_CREDENTIAL_KEY:
case KM_TAG_BOOTLOADER_ONLY:
return KM_ERROR_INVALID_KEY_BLOB;
+
+ case KM_TAG_EARLY_BOOT_ONLY:
+ if (!in_early_boot()) return KM_ERROR_EARLY_BOOT_ENDED;
+ break;
}
}
@@ -399,7 +417,7 @@
if (update_access_count) {
if (!access_count_map_) {
- LOG_S("Usage-count limited keys tabel not allocated. Count-limited keys disabled", 0);
+ LOG_S("Usage-count limited keys table not allocated. Count-limited keys disabled", 0);
return KM_ERROR_MEMORY_ALLOCATION_FAILED;
}
@@ -413,25 +431,53 @@
}
bool KeymasterEnforcement::MinTimeBetweenOpsPassed(uint32_t min_time_between, const km_id_t keyid) {
- if (!access_time_map_)
- return false;
+ if (!access_time_map_) return false;
uint32_t last_access_time;
- if (!access_time_map_->LastKeyAccessTime(keyid, &last_access_time))
- return true;
+ if (!access_time_map_->LastKeyAccessTime(keyid, &last_access_time)) return true;
return min_time_between <= static_cast<int64_t>(get_current_time()) - last_access_time;
}
bool KeymasterEnforcement::MaxUsesPerBootNotExceeded(const km_id_t keyid, uint32_t max_uses) {
- if (!access_count_map_)
- return false;
+ if (!access_count_map_) return false;
uint32_t key_access_count;
- if (!access_count_map_->KeyAccessCount(keyid, &key_access_count))
- return true;
+ if (!access_count_map_->KeyAccessCount(keyid, &key_access_count)) return true;
return key_access_count < max_uses;
}
+bool KeymasterEnforcement::GetAndValidateAuthToken(const AuthorizationSet& operation_params,
+ const hw_auth_token_t** auth_token,
+ uint32_t* token_auth_type) const {
+ keymaster_blob_t auth_token_blob;
+ if (!operation_params.GetTagValue(TAG_AUTH_TOKEN, &auth_token_blob)) {
+ LOG_E("Authentication required, but auth token not provided", 0);
+ return false;
+ }
+
+ if (auth_token_blob.data_length != sizeof(**auth_token)) {
+ LOG_E("Bug: Auth token is the wrong size (%d expected, %d found)", sizeof(hw_auth_token_t),
+ auth_token_blob.data_length);
+ return false;
+ }
+
+ *auth_token = reinterpret_cast<const hw_auth_token_t*>(auth_token_blob.data);
+ if ((*auth_token)->version != HW_AUTH_TOKEN_VERSION) {
+ LOG_E("Bug: Auth token is the version %d (or is not an auth token). Expected %d",
+ (*auth_token)->version, HW_AUTH_TOKEN_VERSION);
+ return false;
+ }
+
+ if (!ValidateTokenSignature(**auth_token)) {
+ LOG_E("Auth token signature invalid", 0);
+ return false;
+ }
+
+ *token_auth_type = ntoh((*auth_token)->authenticator_type);
+
+ return true;
+}
+
bool KeymasterEnforcement::AuthTokenMatches(const AuthProxy& auth_set,
const AuthorizationSet& operation_params,
const uint64_t user_secure_id,
@@ -441,39 +487,18 @@
assert(auth_type_index < static_cast<int>(auth_set.size()));
assert(auth_timeout_index < static_cast<int>(auth_set.size()));
- keymaster_blob_t auth_token_blob;
- if (!operation_params.GetTagValue(TAG_AUTH_TOKEN, &auth_token_blob)) {
- LOG_E("Authentication required, but auth token not provided", 0);
+ const hw_auth_token_t* auth_token;
+ uint32_t token_auth_type;
+ if (!GetAndValidateAuthToken(operation_params, &auth_token, &token_auth_type)) return false;
+
+ if (auth_timeout_index == -1 && op_handle && op_handle != auth_token->challenge) {
+ LOG_E("Auth token has the challenge %llu, need %llu", auth_token->challenge, op_handle);
return false;
}
- if (auth_token_blob.data_length != sizeof(hw_auth_token_t)) {
- LOG_E("Bug: Auth token is the wrong size (%d expected, %d found)", sizeof(hw_auth_token_t),
- auth_token_blob.data_length);
- return false;
- }
-
- hw_auth_token_t auth_token;
- memcpy(&auth_token, auth_token_blob.data, sizeof(hw_auth_token_t));
- if (auth_token.version != HW_AUTH_TOKEN_VERSION) {
- LOG_E("Bug: Auth token is the version %d (or is not an auth token). Expected %d",
- auth_token.version, HW_AUTH_TOKEN_VERSION);
- return false;
- }
-
- if (!ValidateTokenSignature(auth_token)) {
- LOG_E("Auth token signature invalid", 0);
- return false;
- }
-
- if (auth_timeout_index == -1 && op_handle && op_handle != auth_token.challenge) {
- LOG_E("Auth token has the challenge %llu, need %llu", auth_token.challenge, op_handle);
- return false;
- }
-
- if (user_secure_id != auth_token.user_id && user_secure_id != auth_token.authenticator_id) {
- LOG_I("Auth token SIDs %llu and %llu do not match key SID %llu", auth_token.user_id,
- auth_token.authenticator_id, user_secure_id);
+ if (user_secure_id != auth_token->user_id && user_secure_id != auth_token->authenticator_id) {
+ LOG_I("Auth token SIDs %llu and %llu do not match key SID %llu", auth_token->user_id,
+ auth_token->authenticator_id, user_secure_id);
return false;
}
@@ -483,11 +508,9 @@
}
assert(auth_set[auth_type_index].tag == KM_TAG_USER_AUTH_TYPE);
- if (auth_set[auth_type_index].tag != KM_TAG_USER_AUTH_TYPE)
- return false;
+ if (auth_set[auth_type_index].tag != KM_TAG_USER_AUTH_TYPE) return false;
uint32_t key_auth_type_mask = auth_set[auth_type_index].integer;
- uint32_t token_auth_type = ntoh(auth_token.authenticator_type);
if ((key_auth_type_mask & token_auth_type) == 0) {
LOG_E("Key requires match of auth type mask 0%uo, but token contained 0%uo",
key_auth_type_mask, token_auth_type);
@@ -496,10 +519,9 @@
if (auth_timeout_index != -1 && is_begin_operation) {
assert(auth_set[auth_timeout_index].tag == KM_TAG_AUTH_TIMEOUT);
- if (auth_set[auth_timeout_index].tag != KM_TAG_AUTH_TIMEOUT)
- return false;
+ if (auth_set[auth_timeout_index].tag != KM_TAG_AUTH_TIMEOUT) return false;
- if (auth_token_timed_out(auth_token, auth_set[auth_timeout_index].integer)) {
+ if (auth_token_timed_out(*auth_token, auth_set[auth_timeout_index].integer)) {
LOG_E("Auth token has timed out", 0);
return false;
}
@@ -509,6 +531,10 @@
return true;
}
+keymaster_error_t KeymasterEnforcement::GenerateTimestampToken(TimestampToken* /*token*/) {
+ return KM_ERROR_UNIMPLEMENTED;
+}
+
bool AccessTimeMap::LastKeyAccessTime(km_id_t keyid, uint32_t* last_access_time) const {
for (auto& entry : last_access_list_)
if (entry.keyid == keyid) {
@@ -534,8 +560,7 @@
++iter;
}
- if (last_access_list_.size() >= max_size_)
- return false;
+ if (last_access_list_.size() >= max_size_) return false;
AccessTime new_entry;
new_entry.keyid = keyid;
@@ -562,13 +587,11 @@
// operation requests will be rejected and access_count won't be incremented any more.
// And, besides, UINT64_MAX is huge. But we ensure that it doesn't wrap anyway, out of
// an abundance of caution.
- if (entry.access_count < UINT64_MAX)
- ++entry.access_count;
+ if (entry.access_count < UINT64_MAX) ++entry.access_count;
return true;
}
- if (access_count_list_.size() >= max_size_)
- return false;
+ if (access_count_list_.size() >= max_size_) return false;
AccessCount new_entry;
new_entry.keyid = keyid;
diff --git a/android_keymaster/keymaster_stl.cpp b/android_keymaster/keymaster_stl.cpp
deleted file mode 100644
index 62c486c..0000000
--- a/android_keymaster/keymaster_stl.cpp
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
-**
-** Copyright 2017, 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 <keymaster/new.h>
-#include <stdlib.h>
-
-namespace std {
-struct nothrow_t {};
-}
-
-extern const std::nothrow_t __attribute__((weak)) std::nothrow = {};
-
-void* __attribute__((weak)) operator new(size_t __sz, const std::nothrow_t&) {
- return malloc(__sz);
-}
-void* __attribute__((weak)) operator new[](size_t __sz, const std::nothrow_t&) {
- return malloc(__sz);
-}
-
-void __attribute__((weak)) operator delete(void* ptr) {
- if (ptr)
- free(ptr);
-}
-
-void __attribute__((weak)) operator delete[](void* ptr) {
- if (ptr)
- free(ptr);
-}
-
-extern "C" {
-void __attribute__((weak)) __cxa_pure_virtual() {
- abort();
-}
-}
diff --git a/android_keymaster/keymaster_tags.cpp b/android_keymaster/keymaster_tags.cpp
index 8716c1f..dc42061 100644
--- a/android_keymaster/keymaster_tags.cpp
+++ b/android_keymaster/keymaster_tags.cpp
@@ -55,6 +55,8 @@
return "KM_TAG_MIN_SECONDS_BETWEEN_OPS";
case KM_TAG_MAX_USES_PER_BOOT:
return "KM_TAG_MAX_USES_PER_BOOT";
+ case KM_TAG_USAGE_COUNT_LIMIT:
+ return "KM_TAG_USAGE_COUNT_LIMIT";
case KM_TAG_ALL_USERS:
return "KM_TAG_ALL_USERS";
case KM_TAG_USER_ID:
@@ -135,6 +137,34 @@
return "KM_TAG_ATTESTATION_ID_MANUFACTURER";
case KM_TAG_ATTESTATION_ID_MODEL:
return "KM_TAG_ATTESTATION_ID_MODEL";
+ case KM_TAG_EARLY_BOOT_ONLY:
+ return "KM_TAG_EARLY_BOOT_ONLY";
+ case KM_TAG_DEVICE_UNIQUE_ATTESTATION:
+ return "KM_TAG_DEVICE_UNIQUE_ATTESTATION";
+ case KM_TAG_IDENTITY_CREDENTIAL_KEY:
+ return "KM_TAG_IDENTITY_CREDENTIAL_KEY";
+ case KM_TAG_CONFIRMATION_TOKEN:
+ return "KM_TAG_CONFIRMATION_TOKEN";
+ case KM_TAG_CERTIFICATE_SERIAL:
+ return "KM_TAG_CERTIFICATE_SERIAL";
+ case KM_TAG_CERTIFICATE_SUBJECT:
+ return "KM_TAG_CERTIFICATE_SUBJECT";
+ case KM_TAG_CERTIFICATE_NOT_BEFORE:
+ return "KM_TAG_CERTIFICATE_NOT_BEFORE";
+ case KM_TAG_CERTIFICATE_NOT_AFTER:
+ return "KM_TAG_CERTIFICATE_NOT_AFTER";
+ case KM_TAG_STORAGE_KEY:
+ return "KM_TAG_STORAGE_KEY";
+ case KM_TAG_TRUSTED_USER_PRESENCE_REQUIRED:
+ return "KM_TAG_TRUSTED_USER_PRESENCE_REQUIRED";
+ case KM_TAG_BOOT_PATCHLEVEL:
+ return "KM_TAG_BOOT_PATCHLEVEL";
+ case KM_TAG_VENDOR_PATCHLEVEL:
+ return "KM_TAG_VENDOR_PATCHLEVEL";
+ case KM_TAG_RSA_OAEP_MGF_DIGEST:
+ return "KM_TAG_RSA_OAEP_MGF_DIGEST";
+ case KM_TAG_MAX_BOOT_LEVEL:
+ return "KM_TAG_MAX_BOOT_LEVEL";
}
return "<Unknown>";
}
@@ -156,6 +186,7 @@
DEFINE_KEYMASTER_TAG(KM_DATE, TAG_USAGE_EXPIRE_DATETIME);
DEFINE_KEYMASTER_TAG(KM_UINT, TAG_MIN_SECONDS_BETWEEN_OPS);
DEFINE_KEYMASTER_TAG(KM_UINT, TAG_MAX_USES_PER_BOOT);
+DEFINE_KEYMASTER_TAG(KM_UINT, TAG_USAGE_COUNT_LIMIT);
DEFINE_KEYMASTER_TAG(KM_BOOL, TAG_ALL_USERS);
DEFINE_KEYMASTER_TAG(KM_UINT, TAG_USER_ID);
DEFINE_KEYMASTER_TAG(KM_ULONG_REP, TAG_USER_SECURE_ID);
@@ -176,6 +207,7 @@
DEFINE_KEYMASTER_TAG(KM_UINT, TAG_OS_VERSION);
DEFINE_KEYMASTER_TAG(KM_UINT, TAG_OS_PATCHLEVEL);
DEFINE_KEYMASTER_TAG(KM_BYTES, TAG_UNIQUE_ID);
+DEFINE_KEYMASTER_TAG(KM_BYTES, TAG_ATTESTATION_CHALLENGE);
DEFINE_KEYMASTER_TAG(KM_BYTES, TAG_ATTESTATION_APPLICATION_ID);
DEFINE_KEYMASTER_TAG(KM_BYTES, TAG_ATTESTATION_ID_BRAND);
DEFINE_KEYMASTER_TAG(KM_BYTES, TAG_ATTESTATION_ID_DEVICE);
@@ -187,6 +219,19 @@
DEFINE_KEYMASTER_TAG(KM_BYTES, TAG_ATTESTATION_ID_MODEL);
DEFINE_KEYMASTER_TAG(KM_BOOL, TAG_UNLOCKED_DEVICE_REQUIRED);
DEFINE_KEYMASTER_TAG(KM_BOOL, TAG_TRUSTED_CONFIRMATION_REQUIRED);
+DEFINE_KEYMASTER_TAG(KM_BOOL, TAG_EARLY_BOOT_ONLY);
+DEFINE_KEYMASTER_TAG(KM_BOOL, TAG_DEVICE_UNIQUE_ATTESTATION);
+DEFINE_KEYMASTER_TAG(KM_BOOL, TAG_IDENTITY_CREDENTIAL_KEY);
+DEFINE_KEYMASTER_TAG(KM_BOOL, TAG_TRUSTED_USER_PRESENCE_REQUIRED);
+DEFINE_KEYMASTER_TAG(KM_BYTES, TAG_CONFIRMATION_TOKEN);
+DEFINE_KEYMASTER_TAG(KM_BIGNUM, TAG_CERTIFICATE_SERIAL);
+DEFINE_KEYMASTER_TAG(KM_BYTES, TAG_CERTIFICATE_SUBJECT);
+DEFINE_KEYMASTER_TAG(KM_DATE, TAG_CERTIFICATE_NOT_BEFORE);
+DEFINE_KEYMASTER_TAG(KM_DATE, TAG_CERTIFICATE_NOT_AFTER);
+DEFINE_KEYMASTER_TAG(KM_BOOL, TAG_STORAGE_KEY);
+DEFINE_KEYMASTER_TAG(KM_UINT, TAG_BOOT_PATCHLEVEL);
+DEFINE_KEYMASTER_TAG(KM_UINT, TAG_VENDOR_PATCHLEVEL);
+DEFINE_KEYMASTER_TAG(KM_UINT, TAG_MAX_BOOT_LEVEL);
// DEFINE_KEYMASTER_ENUM_TAG is used to create TypedEnumTag instances for each enum keymaster tag.
@@ -205,5 +250,6 @@
DEFINE_KEYMASTER_ENUM_TAG(KM_ENUM, TAG_USER_AUTH_TYPE, hw_authenticator_type_t);
DEFINE_KEYMASTER_ENUM_TAG(KM_ENUM_REP, TAG_KDF, keymaster_kdf_t);
DEFINE_KEYMASTER_ENUM_TAG(KM_ENUM, TAG_EC_CURVE, keymaster_ec_curve_t);
+DEFINE_KEYMASTER_ENUM_TAG(KM_ENUM_REP, TAG_RSA_OAEP_MGF_DIGEST, keymaster_digest_t);
} // namespace keymaster
diff --git a/android_keymaster/logger.cpp b/android_keymaster/logger.cpp
index 0d1d4af..fdee6a0 100644
--- a/android_keymaster/logger.cpp
+++ b/android_keymaster/logger.cpp
@@ -21,13 +21,14 @@
Logger* Logger::instance_ = nullptr;
/* static */
+// NOLINTNEXTLINE(cert-dcl50-cpp)
int Logger::Log(LogLevel level, const char* fmt, va_list args) {
- if (!instance_)
- return 0;
+ if (!instance_) return 0;
return instance_->log_msg(level, fmt, args);
}
/* static */
+// NOLINTNEXTLINE(cert-dcl50-cpp)
int Logger::Log(LogLevel level, const char* fmt, ...) {
va_list args;
va_start(args, fmt);
@@ -37,6 +38,7 @@
}
/* static */
+// NOLINTNEXTLINE(cert-dcl50-cpp)
int Logger::Debug(const char* fmt, ...) {
va_list args;
va_start(args, fmt);
@@ -46,6 +48,7 @@
}
/* static */
+// NOLINTNEXTLINE(cert-dcl50-cpp)
int Logger::Info(const char* fmt, ...) {
va_list args;
va_start(args, fmt);
@@ -53,7 +56,9 @@
va_end(args);
return result;
}
+
/* static */
+// NOLINTNEXTLINE(cert-dcl50-cpp)
int Logger::Warning(const char* fmt, ...) {
va_list args;
va_start(args, fmt);
@@ -61,7 +66,9 @@
va_end(args);
return result;
}
+
/* static */
+// NOLINTNEXTLINE(cert-dcl50-cpp)
int Logger::Error(const char* fmt, ...) {
va_list args;
va_start(args, fmt);
@@ -69,7 +76,9 @@
va_end(args);
return result;
}
+
/* static */
+// NOLINTNEXTLINE(cert-dcl50-cpp)
int Logger::Severe(const char* fmt, ...) {
va_list args;
va_start(args, fmt);
@@ -78,5 +87,4 @@
return result;
}
-
} // namespace keymaster
diff --git a/android_keymaster/operation.cpp b/android_keymaster/operation.cpp
index 3180ab0..8d94b3c 100644
--- a/android_keymaster/operation.cpp
+++ b/android_keymaster/operation.cpp
@@ -18,15 +18,13 @@
#include <keymaster/key.h>
#include <keymaster/operation.h>
-
namespace keymaster {
bool OperationFactory::supported(keymaster_padding_t padding) const {
size_t padding_count;
const keymaster_padding_t* supported_paddings = SupportedPaddingModes(&padding_count);
for (size_t i = 0; i < padding_count; ++i)
- if (padding == supported_paddings[i])
- return true;
+ if (padding == supported_paddings[i]) return true;
return false;
}
@@ -34,8 +32,7 @@
size_t block_mode_count;
const keymaster_block_mode_t* supported_block_modes = SupportedBlockModes(&block_mode_count);
for (size_t i = 0; i < block_mode_count; ++i)
- if (block_mode == supported_block_modes[i])
- return true;
+ if (block_mode == supported_block_modes[i]) return true;
return false;
}
@@ -43,8 +40,7 @@
size_t digest_count;
const keymaster_digest_t* supported_digests = SupportedDigests(&digest_count);
for (size_t i = 0; i < digest_count; ++i)
- if (digest == supported_digests[i])
- return true;
+ if (digest == supported_digests[i]) return true;
return false;
}
@@ -67,8 +63,7 @@
bool OperationFactory::is_public_key_operation() const {
KeyType key_type = registry_key();
- if (!is_public_key_algorithm(key_type.algorithm))
- return false;
+ if (!is_public_key_algorithm(key_type.algorithm)) return false;
switch (key_type.purpose) {
case KM_PURPOSE_VERIFY:
@@ -78,6 +73,8 @@
case KM_PURPOSE_SIGN:
case KM_PURPOSE_DECRYPT:
case KM_PURPOSE_DERIVE_KEY:
+ case KM_PURPOSE_AGREE_KEY:
+ case KM_PURPOSE_ATTEST_KEY:
return false;
};
@@ -129,7 +126,7 @@
*digest = KM_DIGEST_NONE;
} else {
LOG_E("%d digests specified in begin params and NONE not authorized",
- begin_params.GetTagCount(TAG_DIGEST));
+ begin_params.GetTagCount(TAG_DIGEST));
return false;
}
} else if (!supported(*digest)) {
@@ -157,8 +154,7 @@
AuthorizationSet output_params;
keymaster_error_t error =
Update(input_params, input, &output_params, &output, &input_consumed);
- if (error != KM_ERROR_OK)
- return error;
+ if (error != KM_ERROR_OK) return error;
assert(input_consumed == input.available_read());
assert(output_params.empty());
assert(output.available_read() == 0);
diff --git a/android_keymaster/operation_table.cpp b/android_keymaster/operation_table.cpp
index ff9d2bb..50d47f5 100644
--- a/android_keymaster/operation_table.cpp
+++ b/android_keymaster/operation_table.cpp
@@ -14,19 +14,16 @@
* limitations under the License.
*/
-#include <keymaster/operation_table.h>
-#include <keymaster/operation.h>
#include <keymaster/android_keymaster_utils.h>
-
-#include <keymaster/new.h>
+#include <keymaster/operation.h>
+#include <keymaster/operation_table.h>
namespace keymaster {
keymaster_error_t OperationTable::Add(OperationPtr&& operation) {
if (!table_) {
table_.reset(new (std::nothrow) OperationPtr[table_size_]);
- if (!table_)
- return KM_ERROR_MEMORY_ALLOCATION_FAILED;
+ if (!table_) return KM_ERROR_MEMORY_ALLOCATION_FAILED;
}
for (size_t i = 0; i < table_size_; ++i) {
if (!table_[i]) {
@@ -38,22 +35,18 @@
}
Operation* OperationTable::Find(keymaster_operation_handle_t op_handle) {
- if (op_handle == 0)
- return nullptr;
+ if (op_handle == 0) return nullptr;
- if (!table_.get())
- return nullptr;
+ if (!table_.get()) return nullptr;
for (size_t i = 0; i < table_size_; ++i) {
- if (table_[i] && table_[i]->operation_handle() == op_handle)
- return table_[i].get();
+ if (table_[i] && table_[i]->operation_handle() == op_handle) return table_[i].get();
}
return nullptr;
}
bool OperationTable::Delete(keymaster_operation_handle_t op_handle) {
- if (!table_.get())
- return false;
+ if (!table_.get()) return false;
for (size_t i = 0; i < table_size_; ++i) {
if (table_[i] && table_[i]->operation_handle() == op_handle) {
diff --git a/android_keymaster/pure_soft_secure_key_storage.cpp b/android_keymaster/pure_soft_secure_key_storage.cpp
new file mode 100644
index 0000000..2c0a739
--- /dev/null
+++ b/android_keymaster/pure_soft_secure_key_storage.cpp
@@ -0,0 +1,142 @@
+/*
+ * Copyright 2021, 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 <keymaster/pure_soft_secure_key_storage.h>
+
+#include <vector>
+
+#include <keymaster/logger.h>
+
+namespace keymaster {
+
+class PureSoftSecureStorageMap {
+ public:
+ explicit PureSoftSecureStorageMap(uint32_t max_size) : max_size_(max_size) {}
+
+ /* Writes key id into pure software secure storage. Returns false if the list has
+ * already reached maximum size. */
+ bool WriteKey(km_id_t keyid);
+
+ /* Checks if the key id exists in the list. */
+ bool KeyExists(km_id_t keyid) const;
+
+ /* Deletes the key id from the list, if it is not existed then do nothing. */
+ void DeleteKey(km_id_t keyid);
+
+ /* Deletes all key ids from the list. */
+ void DeleteAllKeys();
+
+ /* Checks if there is still available slot to write key. */
+ bool HasSlot() const;
+
+ private:
+ std::vector<km_id_t> keyid_list_;
+ const uint32_t max_size_;
+};
+
+bool PureSoftSecureStorageMap::WriteKey(km_id_t keyid) {
+ if (keyid_list_.size() >= max_size_) return false;
+ keyid_list_.push_back(keyid);
+ return true;
+}
+
+bool PureSoftSecureStorageMap::KeyExists(km_id_t keyid) const {
+ for (km_id_t key_id : keyid_list_)
+ if (key_id == keyid) return true;
+ return false;
+}
+
+void PureSoftSecureStorageMap::DeleteKey(km_id_t keyid) {
+ std::vector<km_id_t>::iterator iter;
+ for (iter = keyid_list_.begin(); iter != keyid_list_.end();) {
+ if (*iter == keyid)
+ iter = keyid_list_.erase(iter);
+ else
+ ++iter;
+ }
+}
+
+void PureSoftSecureStorageMap::DeleteAllKeys() {
+ keyid_list_.clear();
+}
+
+bool PureSoftSecureStorageMap::HasSlot() const {
+ return keyid_list_.size() < max_size_;
+}
+
+PureSoftSecureKeyStorage::PureSoftSecureKeyStorage(uint32_t max_slot)
+ : pure_soft_secure_storage_map_(new (std::nothrow) PureSoftSecureStorageMap(max_slot)) {}
+
+PureSoftSecureKeyStorage::~PureSoftSecureKeyStorage() {
+ delete pure_soft_secure_storage_map_;
+}
+
+keymaster_error_t PureSoftSecureKeyStorage::WriteKey(const km_id_t keyid,
+ const KeymasterKeyBlob& /* blob */) {
+ if (!pure_soft_secure_storage_map_) {
+ LOG_S("Pure software secure key storage table not allocated.", 0);
+ return KM_ERROR_MEMORY_ALLOCATION_FAILED;
+ }
+
+ if (!pure_soft_secure_storage_map_->WriteKey(keyid)) {
+ LOG_E("Pure software secure key storage slot full.", 0);
+ return KM_ERROR_UNKNOWN_ERROR;
+ }
+
+ return KM_ERROR_OK;
+}
+
+keymaster_error_t PureSoftSecureKeyStorage::KeyExists(const km_id_t keyid, bool* exists) {
+ if (!pure_soft_secure_storage_map_) {
+ LOG_S("Pure software secure key storage table not allocated.", 0);
+ return KM_ERROR_MEMORY_ALLOCATION_FAILED;
+ }
+
+ *exists = pure_soft_secure_storage_map_->KeyExists(keyid);
+ return KM_ERROR_OK;
+}
+
+keymaster_error_t PureSoftSecureKeyStorage::DeleteKey(const km_id_t keyid) {
+ if (!pure_soft_secure_storage_map_) {
+ LOG_S("Pure software secure key storage table not allocated.", 0);
+ return KM_ERROR_MEMORY_ALLOCATION_FAILED;
+ }
+
+ pure_soft_secure_storage_map_->DeleteKey(keyid);
+ return KM_ERROR_OK;
+}
+
+keymaster_error_t PureSoftSecureKeyStorage::DeleteAllKeys() {
+ if (!pure_soft_secure_storage_map_) {
+ LOG_S("Pure software secure key storage table not allocated.", 0);
+ return KM_ERROR_MEMORY_ALLOCATION_FAILED;
+ }
+
+ pure_soft_secure_storage_map_->DeleteAllKeys();
+ return KM_ERROR_OK;
+}
+
+keymaster_error_t PureSoftSecureKeyStorage::HasSlot(bool* has_slot) {
+ if (!pure_soft_secure_storage_map_) {
+ LOG_S("Pure software secure key storage table not allocated.", 0);
+ return KM_ERROR_MEMORY_ALLOCATION_FAILED;
+ }
+
+ *has_slot = pure_soft_secure_storage_map_->HasSlot();
+ return KM_ERROR_OK;
+}
+
+} // namespace keymaster
diff --git a/android_keymaster/remote_provisioning_utils.cpp b/android_keymaster/remote_provisioning_utils.cpp
new file mode 100644
index 0000000..8cb635b
--- /dev/null
+++ b/android_keymaster/remote_provisioning_utils.cpp
@@ -0,0 +1,211 @@
+/*
+ * Copyright 2021 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 "keymaster/cppcose/cppcose.h"
+#include <keymaster/logger.h>
+#include <keymaster/remote_provisioning_utils.h>
+#include <string_view>
+
+namespace keymaster {
+
+using cppcose::ALGORITHM;
+using cppcose::COSE_KEY;
+using cppcose::CoseKey;
+using cppcose::CoseKeyCurve;
+using cppcose::EC2;
+using cppcose::ECDH_ES_HKDF_256;
+using cppcose::ES256;
+using cppcose::generateCoseMac0Mac;
+using cppcose::HMAC_256;
+using cppcose::kCoseMac0EntryCount;
+using cppcose::kCoseMac0Payload;
+using cppcose::kCoseMac0ProtectedParams;
+using cppcose::kCoseMac0Tag;
+using cppcose::kCoseMac0UnprotectedParams;
+using cppcose::KEY_ID;
+using cppcose::OCTET_KEY_PAIR;
+using cppcose::P256;
+using cppcose::verifyAndParseCoseSign1;
+
+using byte_view = std::basic_string_view<uint8_t>;
+
+struct KeyInfo {
+ CoseKeyCurve curve;
+ byte_view pubkey;
+ // Note: There's no need to include algorithm here, since it is assumed
+ // that all root keys are EDDSA.
+
+ bool operator==(const KeyInfo& other) const {
+ return curve == other.curve && pubkey == other.pubkey;
+ }
+};
+
+// The production root signing key for Google Endpoint Encryption Key cert chains.
+inline constexpr uint8_t kGeekRoot[] = {
+ 0x99, 0xB9, 0xEE, 0xDD, 0x5E, 0xE4, 0x52, 0xF6, 0x85, 0xC6, 0x4C, 0x62, 0xDC, 0x3E, 0x61, 0xAB,
+ 0x57, 0x48, 0x7D, 0x75, 0x37, 0x29, 0xAD, 0x76, 0x80, 0x32, 0xD2, 0xB3, 0xCB, 0x63, 0x58, 0xD9};
+
+// Hard-coded set of acceptable public COSE_Keys that can act as roots of EEK chains.
+inline constexpr KeyInfo kAuthorizedEekRoots[] = {
+ {CoseKeyCurve::ED25519, byte_view(kGeekRoot, sizeof(kGeekRoot))},
+};
+
+StatusOr<std::pair<std::vector<uint8_t> /* EEK pub */, std::vector<uint8_t> /* EEK ID */>>
+validateAndExtractEekPubAndId(bool testMode, const KeymasterBlob& endpointEncryptionCertChain) {
+ auto [item, newPos, errMsg] =
+ cppbor::parse(endpointEncryptionCertChain.begin(), endpointEncryptionCertChain.end());
+
+ if (!item || !item->asArray()) {
+ LOG_E("Error parsing EEK chain: %s", errMsg.c_str());
+ return kStatusFailed;
+ }
+
+ const cppbor::Array* certArr = item->asArray();
+ std::vector<uint8_t> lastPubKey;
+ for (size_t i = 0; i < certArr->size(); ++i) {
+ auto cosePubKey =
+ verifyAndParseCoseSign1(certArr->get(i)->asArray(), lastPubKey, {} /* AAD */);
+ if (!cosePubKey) {
+ LOG_E("Failed to validate EEK chain: %s", cosePubKey.moveMessage().c_str());
+ return kStatusInvalidEek;
+ }
+ lastPubKey = *std::move(cosePubKey);
+
+ // In prod mode the first pubkey should match a well-known Google public key.
+ if (!testMode && i == 0) {
+ auto parsedPubKey = CoseKey::parse(lastPubKey);
+ if (!parsedPubKey) {
+ LOG_E("%s", parsedPubKey.moveMessage().c_str());
+ return kStatusFailed;
+ }
+
+ auto curve = parsedPubKey->getIntValue(CoseKey::CURVE);
+ if (!curve) {
+ LOG_E("Key is missing required label 'CURVE'", 0);
+ return kStatusInvalidEek;
+ }
+
+ auto rawPubKey = parsedPubKey->getBstrValue(CoseKey::PUBKEY_X);
+ if (!rawPubKey) {
+ LOG_E("Key is missing required label 'PUBKEY_X'", 0);
+ return kStatusInvalidEek;
+ }
+
+ KeyInfo matcher = {static_cast<CoseKeyCurve>(*curve),
+ byte_view(rawPubKey->data(), rawPubKey->size())};
+ if (std::find(std::begin(kAuthorizedEekRoots), std::end(kAuthorizedEekRoots),
+ matcher) == std::end(kAuthorizedEekRoots)) {
+ LOG_E("Unrecognized root of EEK chain", 0);
+ return kStatusInvalidEek;
+ }
+ }
+ }
+
+ auto eek = CoseKey::parseX25519(lastPubKey, true /* requireKid */);
+ if (!eek) {
+ LOG_E("Failed to get EEK: %s", eek.moveMessage().c_str());
+ return kStatusInvalidEek;
+ }
+
+ return std::make_pair(eek->getBstrValue(CoseKey::PUBKEY_X).value(),
+ eek->getBstrValue(CoseKey::KEY_ID).value());
+}
+
+StatusOr<std::vector<uint8_t> /* pubkeys */>
+validateAndExtractPubkeys(bool testMode, uint32_t numKeys, KeymasterBlob* keysToSign,
+ cppcose::HmacSha256Function macFunction) {
+ auto pubKeysToMac = cppbor::Array();
+ for (size_t i = 0; i < numKeys; i++) {
+ auto [macedKeyItem, _, coseMacErrMsg] =
+ cppbor::parse(keysToSign[i].begin(), keysToSign[i].end());
+ if (!macedKeyItem || !macedKeyItem->asArray() ||
+ macedKeyItem->asArray()->size() != kCoseMac0EntryCount) {
+ LOG_E("Invalid COSE_Mac0 structure", 0);
+ return kStatusFailed;
+ }
+
+ auto protectedParms = macedKeyItem->asArray()->get(kCoseMac0ProtectedParams)->asBstr();
+ auto unprotectedParms = macedKeyItem->asArray()->get(kCoseMac0UnprotectedParams)->asMap();
+ auto payload = macedKeyItem->asArray()->get(kCoseMac0Payload)->asBstr();
+ auto tag = macedKeyItem->asArray()->get(kCoseMac0Tag)->asBstr();
+ if (!protectedParms || !unprotectedParms || !payload || !tag) {
+ LOG_E("Invalid COSE_Mac0 contents", 0);
+ return kStatusFailed;
+ }
+
+ auto [protectedMap, __, errMsg] = cppbor::parse(protectedParms);
+ if (!protectedMap || !protectedMap->asMap()) {
+ LOG_E("Invalid Mac0 protected: %s", errMsg.c_str());
+ return kStatusFailed;
+ }
+ auto& algo = protectedMap->asMap()->get(ALGORITHM);
+ if (!algo || !algo->asInt() || algo->asInt()->value() != HMAC_256) {
+ LOG_E("Unsupported Mac0 algorithm", 0);
+ return kStatusFailed;
+ }
+
+ auto pubKey = CoseKey::parse(payload->value(), EC2, ES256, P256);
+ if (!pubKey) {
+ LOG_E("%s", pubKey.moveMessage().c_str());
+ return kStatusFailed;
+ }
+
+ bool testKey = static_cast<bool>(pubKey->getMap().get(CoseKey::TEST_KEY));
+ if (testMode && !testKey) {
+ LOG_E("Production key in test request", 0);
+ return kStatusProductionKeyInTestRequest;
+ } else if (!testMode && testKey) {
+ LOG_E("Test key in production request", 0);
+ return kStatusTestKeyInProductionRequest;
+ }
+
+ auto macTag = generateCoseMac0Mac(macFunction, {} /* external_aad */, payload->value());
+ if (!macTag) {
+ LOG_E("%s", macTag.moveMessage().c_str());
+ return kStatusInvalidMac;
+ }
+ if (macTag->size() != tag->value().size() ||
+ CRYPTO_memcmp(macTag->data(), tag->value().data(), macTag->size()) != 0) {
+ LOG_E("MAC tag mismatch", 0);
+ return kStatusInvalidMac;
+ }
+
+ pubKeysToMac.add(pubKey->moveMap());
+ }
+
+ return pubKeysToMac.encode();
+}
+
+cppbor::Array buildCertReqRecipients(const std::vector<uint8_t>& pubkey,
+ const std::vector<uint8_t>& kid) {
+ return cppbor::Array() // Array of recipients
+ .add(cppbor::Array() // Recipient
+ .add(cppbor::Map() // Protected
+ .add(ALGORITHM, ECDH_ES_HKDF_256)
+ .canonicalize()
+ .encode())
+ .add(cppbor::Map() // Unprotected
+ .add(COSE_KEY, cppbor::Map()
+ .add(CoseKey::KEY_TYPE, OCTET_KEY_PAIR)
+ .add(CoseKey::CURVE, cppcose::X25519)
+ .add(CoseKey::PUBKEY_X, pubkey)
+ .canonicalize())
+ .add(KEY_ID, kid)
+ .canonicalize())
+ .add(cppbor::Null())); // No ciphertext
+}
+
+} // namespace keymaster
diff --git a/android_keymaster/serializable.cpp b/android_keymaster/serializable.cpp
index 1f795e2..b1f1e31 100644
--- a/android_keymaster/serializable.cpp
+++ b/android_keymaster/serializable.cpp
@@ -18,8 +18,6 @@
#include <assert.h>
-#include <keymaster/new.h>
-
#include <keymaster/android_keymaster_utils.h>
namespace keymaster {
@@ -33,7 +31,7 @@
return (!overflow_occurred) && (buf_next <= __pval(end));
}
-}
+} // namespace
uint8_t* append_to_buf(uint8_t* buf, const uint8_t* end, const void* data, size_t data_len) {
if (buffer_bound_check(buf, end, data_len)) {
@@ -56,8 +54,7 @@
bool copy_size_and_data_from_buf(const uint8_t** buf_ptr, const uint8_t* end, size_t* size,
UniquePtr<uint8_t[]>* dest) {
- if (!copy_uint32_from_buf(buf_ptr, end, size))
- return false;
+ if (!copy_uint32_from_buf(buf_ptr, end, size)) return false;
if (*size == 0) {
dest->reset();
@@ -79,8 +76,7 @@
if (available_write() < size) {
size_t new_size = buffer_size_ + size - available_write();
uint8_t* new_buffer = new (std::nothrow) uint8_t[new_size];
- if (!new_buffer)
- return false;
+ if (!new_buffer) return false;
memcpy(new_buffer, buffer_.get() + read_position_, available_read());
memset_s(buffer_.get(), 0, buffer_size_);
buffer_.reset(new_buffer);
@@ -94,8 +90,7 @@
bool Buffer::Reinitialize(size_t size) {
Clear();
buffer_.reset(new (std::nothrow) uint8_t[size]);
- if (!buffer_.get())
- return false;
+ if (!buffer_.get()) return false;
buffer_size_ = size;
read_position_ = 0;
write_position_ = 0;
@@ -107,8 +102,7 @@
if (__pval(data) + data_len < __pval(data)) // Pointer wrap check
return false;
buffer_.reset(new (std::nothrow) uint8_t[data_len]);
- if (!buffer_.get())
- return false;
+ if (!buffer_.get()) return false;
buffer_size_ = data_len;
memcpy(buffer_.get(), data, data_len);
read_position_ = 0;
@@ -128,16 +122,14 @@
}
bool Buffer::write(const uint8_t* src, size_t write_length) {
- if (available_write() < write_length)
- return false;
+ if (available_write() < write_length) return false;
memcpy(buffer_.get() + write_position_, src, write_length);
write_position_ += write_length;
return true;
}
bool Buffer::read(uint8_t* dest, size_t read_length) {
- if (available_read() < read_length)
- return false;
+ if (available_read() < read_length) return false;
memcpy(dest, buffer_.get() + read_position_, read_length);
read_position_ += read_length;
return true;
diff --git a/contexts/keymaster1_passthrough_context.cpp b/contexts/keymaster1_passthrough_context.cpp
index dab8f37..b15cdb3 100644
--- a/contexts/keymaster1_passthrough_context.cpp
+++ b/contexts/keymaster1_passthrough_context.cpp
@@ -17,37 +17,38 @@
#include <keymaster/contexts/keymaster1_passthrough_context.h>
-#include <keymaster/legacy_support/keymaster_passthrough_key.h>
-#include <keymaster/legacy_support/keymaster_passthrough_engine.h>
-#include <keymaster/legacy_support/keymaster1_legacy_support.h>
-#include <keymaster/legacy_support/keymaster1_engine.h>
-#include <keymaster/legacy_support/rsa_keymaster1_key.h>
-#include <keymaster/legacy_support/ec_keymaster1_key.h>
-#include <keymaster/key_blob_utils/software_keyblobs.h>
+#include <keymaster/contexts/soft_attestation_cert.h>
#include <keymaster/key_blob_utils/integrity_assured_key_blob.h>
#include <keymaster/key_blob_utils/ocb_utils.h>
+#include <keymaster/key_blob_utils/software_keyblobs.h>
#include <keymaster/km_openssl/aes_key.h>
-#include <keymaster/km_openssl/hmac_key.h>
#include <keymaster/km_openssl/attestation_utils.h>
-#include "soft_attestation_cert.h"
+#include <keymaster/km_openssl/hmac_key.h>
+#include <keymaster/km_version.h>
+#include <keymaster/legacy_support/ec_keymaster1_key.h>
+#include <keymaster/legacy_support/keymaster1_engine.h>
+#include <keymaster/legacy_support/keymaster1_legacy_support.h>
+#include <keymaster/legacy_support/keymaster_passthrough_engine.h>
+#include <keymaster/legacy_support/keymaster_passthrough_key.h>
+#include <keymaster/legacy_support/rsa_keymaster1_key.h>
namespace keymaster {
-Keymaster1PassthroughContext::Keymaster1PassthroughContext(keymaster1_device_t* dev)
- : device_(dev), pt_engine_(KeymasterPassthroughEngine::createInstance(dev)),
- km1_engine_(new Keymaster1Engine(dev)) {
-
-}
+Keymaster1PassthroughContext::Keymaster1PassthroughContext(KmVersion version,
+ keymaster1_device_t* dev)
+ : SoftAttestationContext(version), device_(dev),
+ pt_engine_(KeymasterPassthroughEngine::createInstance(dev)),
+ km1_engine_(new Keymaster1Engine(dev)) {}
keymaster_error_t Keymaster1PassthroughContext::SetSystemVersion(uint32_t os_version,
- uint32_t os_patchlevel) {
+ uint32_t os_patchlevel) {
os_version_ = os_version;
os_patchlevel_ = os_patchlevel;
return KM_ERROR_OK;
}
void Keymaster1PassthroughContext::GetSystemVersion(uint32_t* os_version,
- uint32_t* os_patchlevel) const {
+ uint32_t* os_patchlevel) const {
if (os_version) *os_version = os_version_;
if (os_patchlevel) *os_patchlevel = os_patchlevel_;
}
@@ -55,22 +56,26 @@
KeyFactory* Keymaster1PassthroughContext::GetKeyFactory(keymaster_algorithm_t algorithm) const {
auto& result = factories_[algorithm];
if (!result) {
- switch(algorithm) {
+ switch (algorithm) {
case KM_ALGORITHM_RSA:
- result.reset(new Keymaster1ArbitrationFactory<RsaKeymaster1KeyFactory>(pt_engine_.get(),
- KM_ALGORITHM_RSA, device_, this, km1_engine_.get()));
+ result.reset(new Keymaster1ArbitrationFactory<RsaKeymaster1KeyFactory>(
+ pt_engine_.get(), KM_ALGORITHM_RSA, device_, *this /* blob_maker */,
+ *this /* context */, km1_engine_.get()));
break;
case KM_ALGORITHM_EC:
- result.reset(new Keymaster1ArbitrationFactory<EcdsaKeymaster1KeyFactory>(pt_engine_.get(),
- KM_ALGORITHM_EC, device_, this, km1_engine_.get()));
+ result.reset(new Keymaster1ArbitrationFactory<EcdsaKeymaster1KeyFactory>(
+ pt_engine_.get(), KM_ALGORITHM_EC, device_, *this /* blob_maker */,
+ *this /* context */, km1_engine_.get()));
break;
case KM_ALGORITHM_AES:
- result.reset(new Keymaster1ArbitrationFactory<AesKeyFactory>(pt_engine_.get(),
- KM_ALGORITHM_AES, device_, this, this));
+ result.reset(new Keymaster1ArbitrationFactory<AesKeyFactory>(
+ pt_engine_.get(), KM_ALGORITHM_AES, device_, *this /* blob_maker */,
+ *this /* random_source */));
break;
case KM_ALGORITHM_HMAC:
- result.reset(new Keymaster1ArbitrationFactory<HmacKeyFactory>(pt_engine_.get(),
- KM_ALGORITHM_HMAC, device_, this, this));
+ result.reset(new Keymaster1ArbitrationFactory<HmacKeyFactory>(
+ pt_engine_.get(), KM_ALGORITHM_HMAC, device_, *this /* blob_maker */,
+ *this /* random_source */));
break;
case KM_ALGORITHM_TRIPLE_DES:
// Not supported by KM1.
@@ -79,55 +84,51 @@
}
return result.get();
}
-OperationFactory* Keymaster1PassthroughContext::GetOperationFactory(keymaster_algorithm_t algorithm,
- keymaster_purpose_t purpose) const {
+OperationFactory*
+Keymaster1PassthroughContext::GetOperationFactory(keymaster_algorithm_t algorithm,
+ keymaster_purpose_t purpose) const {
auto keyfactory = GetKeyFactory(algorithm);
return keyfactory->GetOperationFactory(purpose);
}
-keymaster_algorithm_t* Keymaster1PassthroughContext::GetSupportedAlgorithms(
- size_t* algorithms_count) const {
+keymaster_algorithm_t*
+Keymaster1PassthroughContext::GetSupportedAlgorithms(size_t* algorithms_count) const {
if (algorithms_count) *algorithms_count = 0;
return nullptr;
}
-keymaster_error_t Keymaster1PassthroughContext::UpgradeKeyBlob(
- const KeymasterKeyBlob& key_to_upgrade, const AuthorizationSet& upgrade_params,
- KeymasterKeyBlob* upgraded_key) const {
+keymaster_error_t
+Keymaster1PassthroughContext::UpgradeKeyBlob(const KeymasterKeyBlob& key_to_upgrade,
+ const AuthorizationSet& upgrade_params,
+ KeymasterKeyBlob* upgraded_key) const {
UniquePtr<Key> key;
keymaster_error_t error = ParseKeyBlob(key_to_upgrade, upgrade_params, &key);
- if (error != KM_ERROR_OK)
- return error;
+ if (error != KM_ERROR_OK) return error;
if (key->hw_enforced().Contains(TAG_PURPOSE) &&
- !key->hw_enforced().Contains(TAG_OS_PATCHLEVEL)) {
+ !key->hw_enforced().Contains(TAG_OS_PATCHLEVEL)) {
return KM_ERROR_INVALID_ARGUMENT;
}
return UpgradeSoftKeyBlob(key, os_version_, os_patchlevel_, upgrade_params, upgraded_key);
}
-static keymaster_error_t parseKeymaster1HwBlob(const keymaster1_device_t* device,
- const KeymasterKeyBlob& blob,
- const AuthorizationSet& additional_params,
- KeymasterKeyBlob* key_material,
- AuthorizationSet* hw_enforced,
- AuthorizationSet* sw_enforced) {
+static keymaster_error_t
+parseKeymaster1HwBlob(const keymaster1_device_t* device, const KeymasterKeyBlob& blob,
+ const AuthorizationSet& additional_params, KeymasterKeyBlob* key_material,
+ AuthorizationSet* hw_enforced, AuthorizationSet* sw_enforced) {
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;
+ 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 = device->get_key_characteristics(device, &blob, client_id_ptr,
- app_data_ptr, &characteristics);
- if (error != KM_ERROR_OK)
- return error;
+ app_data_ptr, &characteristics);
+ if (error != KM_ERROR_OK) return error;
UniquePtr<keymaster_key_characteristics_t, Characteristics_Delete> characteristics_deleter(
characteristics);
@@ -138,26 +139,27 @@
return KM_ERROR_OK;
}
-keymaster_error_t Keymaster1PassthroughContext::ParseKeyBlob(const KeymasterKeyBlob& blob,
- const AuthorizationSet& additional_params, UniquePtr<Key>* key) const {
+keymaster_error_t
+Keymaster1PassthroughContext::ParseKeyBlob(const KeymasterKeyBlob& blob,
+ const AuthorizationSet& additional_params,
+ UniquePtr<Key>* key) const {
AuthorizationSet hw_enforced;
AuthorizationSet sw_enforced;
KeymasterKeyBlob key_material;
AuthorizationSet hidden;
- keymaster_error_t error = BuildHiddenAuthorizations(additional_params, &hidden,
- softwareRootOfTrust);
- if (error != KM_ERROR_OK)
- return error;
+ keymaster_error_t error =
+ BuildHiddenAuthorizations(additional_params, &hidden, softwareRootOfTrust);
+ if (error != KM_ERROR_OK) return error;
// Assume it's an integrity-assured blob (new software-only blob
- error = DeserializeIntegrityAssuredBlob(blob, hidden, &key_material, &hw_enforced, &sw_enforced);
- if (error != KM_ERROR_INVALID_KEY_BLOB && error != KM_ERROR_OK)
- return error;
+ error =
+ DeserializeIntegrityAssuredBlob(blob, hidden, &key_material, &hw_enforced, &sw_enforced);
+ if (error != KM_ERROR_INVALID_KEY_BLOB && error != KM_ERROR_OK) return error;
if (error == KM_ERROR_INVALID_KEY_BLOB) {
- error = parseKeymaster1HwBlob(km1_engine_->device(), blob, additional_params,
- &key_material, &hw_enforced, &sw_enforced);
+ error = parseKeymaster1HwBlob(km1_engine_->device(), blob, additional_params, &key_material,
+ &hw_enforced, &sw_enforced);
if (error != KM_ERROR_OK) return error;
}
@@ -174,26 +176,26 @@
}
keymaster_error_t Keymaster1PassthroughContext::DeleteKey(const KeymasterKeyBlob& blob) const {
- // HACK. Due to a bug with Qualcomm's Keymaster implementation, which causes the device to
- // reboot if we pass it a key blob it doesn't understand, we need to check for software
- // keys. If it looks like a software key there's nothing to do so we just return.
- // Can be removed once b/33385206 is fixed
- KeymasterKeyBlob key_material;
- AuthorizationSet hw_enforced, sw_enforced;
- keymaster_error_t error = DeserializeIntegrityAssuredBlob_NoHmacCheck(
- blob, &key_material, &hw_enforced, &sw_enforced);
- if (error == KM_ERROR_OK) {
- return KM_ERROR_OK;
- }
+ // HACK. Due to a bug with Qualcomm's Keymaster implementation, which causes the device to
+ // reboot if we pass it a key blob it doesn't understand, we need to check for software
+ // keys. If it looks like a software key there's nothing to do so we just return.
+ // Can be removed once b/33385206 is fixed
+ KeymasterKeyBlob key_material;
+ AuthorizationSet hw_enforced, sw_enforced;
+ keymaster_error_t error = DeserializeIntegrityAssuredBlob_NoHmacCheck(
+ blob, &key_material, &hw_enforced, &sw_enforced);
+ if (error == KM_ERROR_OK) {
+ return KM_ERROR_OK;
+ }
- error = km1_engine_->DeleteKey(blob);
- if (error == KM_ERROR_INVALID_KEY_BLOB) {
- // Some implementations diagnose invalid keys.
- // However, all care we about is that the key blob, as supplied, is not usable after the
- // call.
- return KM_ERROR_OK;
- }
- return error;
+ error = km1_engine_->DeleteKey(blob);
+ if (error == KM_ERROR_INVALID_KEY_BLOB) {
+ // Some implementations diagnose invalid keys.
+ // However, all care we about is that the key blob, as supplied, is not usable after the
+ // call.
+ return KM_ERROR_OK;
+ }
+ return error;
}
keymaster_error_t Keymaster1PassthroughContext::DeleteAllKeys() const {
@@ -201,57 +203,49 @@
}
keymaster_error_t Keymaster1PassthroughContext::AddRngEntropy(const uint8_t* buf,
- size_t length) const {
+ size_t length) const {
return device_->add_rng_entropy(device_, buf, length);
}
-
KeymasterEnforcement* Keymaster1PassthroughContext::enforcement_policy() {
return nullptr;
}
-keymaster_error_t Keymaster1PassthroughContext::CreateKeyBlob(const AuthorizationSet& key_description,
- const keymaster_key_origin_t origin,
- const KeymasterKeyBlob& key_material,
- KeymasterKeyBlob* blob,
- AuthorizationSet* hw_enforced,
- AuthorizationSet* sw_enforced) const {
+keymaster_error_t Keymaster1PassthroughContext::CreateKeyBlob(
+ const AuthorizationSet& key_description, const keymaster_key_origin_t origin,
+ const KeymasterKeyBlob& key_material, KeymasterKeyBlob* blob, AuthorizationSet* hw_enforced,
+ AuthorizationSet* sw_enforced) const {
keymaster_error_t error = SetKeyBlobAuthorizations(key_description, origin, os_version_,
os_patchlevel_, hw_enforced, sw_enforced);
- if (error != KM_ERROR_OK)
- return error;
+ if (error != KM_ERROR_OK) return error;
AuthorizationSet hidden;
error = BuildHiddenAuthorizations(key_description, &hidden, softwareRootOfTrust);
- if (error != KM_ERROR_OK)
- return error;
+ if (error != KM_ERROR_OK) return error;
return SerializeIntegrityAssuredBlob(key_material, hidden, *hw_enforced, *sw_enforced, blob);
}
-keymaster_error_t Keymaster1PassthroughContext::GenerateAttestation(const Key& key,
- const AuthorizationSet& attest_params, CertChainPtr* cert_chain) const {
- keymaster_error_t error = KM_ERROR_OK;
+CertificateChain Keymaster1PassthroughContext::GenerateAttestation(
+ const Key& key, const AuthorizationSet& attest_params, UniquePtr<Key> /* attest_key */,
+ const KeymasterBlob& /* issuer_subject */, keymaster_error_t* error) const {
keymaster_algorithm_t key_algorithm;
if (!key.authorizations().GetTagValue(TAG_ALGORITHM, &key_algorithm)) {
- return KM_ERROR_UNKNOWN_ERROR;
+ *error = KM_ERROR_UNKNOWN_ERROR;
+ return {};
}
- if ((key_algorithm != KM_ALGORITHM_RSA && key_algorithm != KM_ALGORITHM_EC))
- return KM_ERROR_INCOMPATIBLE_ALGORITHM;
+ if ((key_algorithm != KM_ALGORITHM_RSA && key_algorithm != KM_ALGORITHM_EC)) {
+ *error = KM_ERROR_INCOMPATIBLE_ALGORITHM;
+ return {};
+ }
// We have established that the given key has the correct algorithm, and because this is the
// SoftKeymasterContext we can assume that the Key is an AsymmetricKey. So we can downcast.
const AsymmetricKey& asymmetric_key = static_cast<const AsymmetricKey&>(key);
- auto attestation_chain = getAttestationChain(key_algorithm, &error);
- if (error != KM_ERROR_OK) return error;
-
- auto attestation_key = getAttestationKey(key_algorithm, &error);
- if (error != KM_ERROR_OK) return error;
-
- return generate_attestation(asymmetric_key, attest_params,
- *attestation_chain, *attestation_key, *this, cert_chain);
+ return generate_attestation(asymmetric_key, attest_params, {} /* attest_key */,
+ *this /* AttestationContext */, error);
}
keymaster_error_t Keymaster1PassthroughContext::UnwrapKey(
@@ -260,4 +254,4 @@
return KM_ERROR_UNIMPLEMENTED;
}
-} // namespace keymaster
+} // namespace keymaster
diff --git a/contexts/keymaster2_passthrough_context.cpp b/contexts/keymaster2_passthrough_context.cpp
index 678eaaa..fe83de8 100644
--- a/contexts/keymaster2_passthrough_context.cpp
+++ b/contexts/keymaster2_passthrough_context.cpp
@@ -17,25 +17,24 @@
#include <keymaster/contexts/keymaster2_passthrough_context.h>
-#include <keymaster/legacy_support/keymaster_passthrough_key.h>
#include <keymaster/legacy_support/keymaster_passthrough_engine.h>
+#include <keymaster/legacy_support/keymaster_passthrough_key.h>
namespace keymaster {
-Keymaster2PassthroughContext::Keymaster2PassthroughContext(keymaster2_device_t* dev)
- : device_(dev), engine_(KeymasterPassthroughEngine::createInstance(dev)) {
-
-}
+Keymaster2PassthroughContext::Keymaster2PassthroughContext(KmVersion version,
+ keymaster2_device_t* dev)
+ : device_(dev), engine_(KeymasterPassthroughEngine::createInstance(dev)), version_(version) {}
keymaster_error_t Keymaster2PassthroughContext::SetSystemVersion(uint32_t os_version,
- uint32_t os_patchlevel) {
+ uint32_t os_patchlevel) {
os_version_ = os_version;
os_patchlevel_ = os_patchlevel;
return KM_ERROR_OK;
}
void Keymaster2PassthroughContext::GetSystemVersion(uint32_t* os_version,
- uint32_t* os_patchlevel) const {
+ uint32_t* os_patchlevel) const {
if (os_version) *os_version = os_version_;
if (os_patchlevel) *os_patchlevel = os_patchlevel_;
}
@@ -47,27 +46,31 @@
}
return result.get();
}
-OperationFactory* Keymaster2PassthroughContext::GetOperationFactory(keymaster_algorithm_t algorithm,
- keymaster_purpose_t purpose) const {
+OperationFactory*
+Keymaster2PassthroughContext::GetOperationFactory(keymaster_algorithm_t algorithm,
+ keymaster_purpose_t purpose) const {
auto keyfactory = GetKeyFactory(algorithm);
return keyfactory->GetOperationFactory(purpose);
}
-keymaster_algorithm_t* Keymaster2PassthroughContext::GetSupportedAlgorithms(
- size_t* algorithms_count) const {
+keymaster_algorithm_t*
+Keymaster2PassthroughContext::GetSupportedAlgorithms(size_t* algorithms_count) const {
if (algorithms_count) *algorithms_count = 0;
return nullptr;
}
-keymaster_error_t Keymaster2PassthroughContext::UpgradeKeyBlob(
- const KeymasterKeyBlob& key_to_upgrade, const AuthorizationSet& upgrade_params,
- KeymasterKeyBlob* upgraded_key) const {
+keymaster_error_t
+Keymaster2PassthroughContext::UpgradeKeyBlob(const KeymasterKeyBlob& key_to_upgrade,
+ const AuthorizationSet& upgrade_params,
+ KeymasterKeyBlob* upgraded_key) const {
if (!upgraded_key) return KM_ERROR_UNEXPECTED_NULL_POINTER;
*upgraded_key = {};
return device_->upgrade_key(device_, &key_to_upgrade, &upgrade_params, upgraded_key);
}
-keymaster_error_t Keymaster2PassthroughContext::ParseKeyBlob(const KeymasterKeyBlob& blob,
- const AuthorizationSet& additional_params, UniquePtr<Key>* key) const {
+keymaster_error_t
+Keymaster2PassthroughContext::ParseKeyBlob(const KeymasterKeyBlob& blob,
+ const AuthorizationSet& additional_params,
+ UniquePtr<Key>* key) const {
keymaster_key_characteristics_t characteristics = {};
keymaster_blob_t clientId;
keymaster_blob_t applicationData;
@@ -115,34 +118,27 @@
}
keymaster_error_t Keymaster2PassthroughContext::AddRngEntropy(const uint8_t* buf,
- size_t length) const {
+ size_t length) const {
return device_->add_rng_entropy(device_, buf, length);
}
-
KeymasterEnforcement* Keymaster2PassthroughContext::enforcement_policy() {
return nullptr;
}
-keymaster_error_t Keymaster2PassthroughContext::GenerateAttestation(const Key& key,
- const AuthorizationSet& attest_params, CertChainPtr* cert_chain) const {
- if (!cert_chain) return KM_ERROR_UNEXPECTED_NULL_POINTER;
-
+CertificateChain Keymaster2PassthroughContext::GenerateAttestation(
+ const Key& key, const AuthorizationSet& attest_params, UniquePtr<Key> /* attest_key */,
+ const KeymasterBlob& /* issuer_subject */, keymaster_error_t* error) const {
keymaster_cert_chain_t cchain{};
-
auto rc = device_->attest_key(device_, &key.key_material(), &attest_params, &cchain);
- if (rc == KM_ERROR_OK) {
- cert_chain->reset(new keymaster_cert_chain_t);
- **cert_chain = { new keymaster_blob_t[cchain.entry_count], cchain.entry_count };
- for (size_t i = 0; i < cchain.entry_count; ++i) {
- (*cert_chain)->entries[i] = { dup_array(cchain.entries[i].data,
- cchain.entries[i].data_length),
- cchain.entries[i].data_length };
- free(const_cast<uint8_t*>(cchain.entries[i].data));
- }
- free(cchain.entries);
+ if (rc != KM_ERROR_OK) {
+ *error = rc;
+ return {};
}
- return rc;
+
+ CertificateChain retval = CertificateChain::clone(cchain);
+ keymaster_free_cert_chain(&cchain);
+ return retval;
}
keymaster_error_t Keymaster2PassthroughContext::UnwrapKey(
@@ -151,4 +147,4 @@
return KM_ERROR_UNIMPLEMENTED;
}
-} // namespace keymaster
+} // namespace keymaster
diff --git a/contexts/pure_soft_keymaster_context.cpp b/contexts/pure_soft_keymaster_context.cpp
index d52fe2e..bfa92a4 100644
--- a/contexts/pure_soft_keymaster_context.cpp
+++ b/contexts/pure_soft_keymaster_context.cpp
@@ -16,6 +16,7 @@
#include <keymaster/contexts/pure_soft_keymaster_context.h>
+#include <assert.h>
#include <memory>
#include <openssl/aes.h>
@@ -33,6 +34,7 @@
#include <keymaster/km_openssl/aes_key.h>
#include <keymaster/km_openssl/asymmetric_key.h>
#include <keymaster/km_openssl/attestation_utils.h>
+#include <keymaster/km_openssl/certificate_utils.h>
#include <keymaster/km_openssl/ec_key_factory.h>
#include <keymaster/km_openssl/hmac_key.h>
#include <keymaster/km_openssl/openssl_err.h>
@@ -44,29 +46,43 @@
#include <keymaster/operation.h>
#include <keymaster/wrapped_key.h>
-#include "soft_attestation_cert.h"
-
-using std::unique_ptr;
+#include <keymaster/contexts/soft_attestation_cert.h>
namespace keymaster {
-PureSoftKeymasterContext::PureSoftKeymasterContext(keymaster_security_level_t security_level)
- : rsa_factory_(new RsaKeyFactory(this)), ec_factory_(new EcKeyFactory(this)),
- aes_factory_(new AesKeyFactory(this, this)),
- tdes_factory_(new TripleDesKeyFactory(this, this)),
- hmac_factory_(new HmacKeyFactory(this, this)), os_version_(0), os_patchlevel_(0),
- soft_keymaster_enforcement_(64, 64), security_level_(security_level) {}
+PureSoftKeymasterContext::PureSoftKeymasterContext(KmVersion version,
+ keymaster_security_level_t security_level)
+
+ : SoftAttestationContext(version),
+ rsa_factory_(new RsaKeyFactory(*this /* blob_maker */, *this /* context */)),
+ ec_factory_(new EcKeyFactory(*this /* blob_maker */, *this /* context */)),
+ aes_factory_(new AesKeyFactory(*this /* blob_maker */, *this /* random_source */)),
+ tdes_factory_(new TripleDesKeyFactory(*this /* blob_maker */, *this /* random_source */)),
+ hmac_factory_(new HmacKeyFactory(*this /* blob_maker */, *this /* random_source */)),
+ os_version_(0), os_patchlevel_(0), soft_keymaster_enforcement_(64, 64),
+ security_level_(security_level) {
+ // We're pretending to be some sort of secure hardware which supports secure key storage,
+ // this must only be used for testing.
+ if (security_level != KM_SECURITY_LEVEL_SOFTWARE) {
+ pure_soft_secure_key_storage_ = std::make_unique<PureSoftSecureKeyStorage>(64);
+ }
+ if (version >= KmVersion::KEYMINT_1) {
+ pure_soft_remote_provisioning_context_ =
+ std::make_unique<PureSoftRemoteProvisioningContext>();
+ }
+}
PureSoftKeymasterContext::~PureSoftKeymasterContext() {}
keymaster_error_t PureSoftKeymasterContext::SetSystemVersion(uint32_t os_version,
- uint32_t os_patchlevel) {
+ uint32_t os_patchlevel) {
os_version_ = os_version;
os_patchlevel_ = os_patchlevel;
return KM_ERROR_OK;
}
-void PureSoftKeymasterContext::GetSystemVersion(uint32_t* os_version, uint32_t* os_patchlevel) const {
+void PureSoftKeymasterContext::GetSystemVersion(uint32_t* os_version,
+ uint32_t* os_patchlevel) const {
*os_version = os_version_;
*os_patchlevel = os_patchlevel_;
}
@@ -98,10 +114,9 @@
}
OperationFactory* PureSoftKeymasterContext::GetOperationFactory(keymaster_algorithm_t algorithm,
- keymaster_purpose_t purpose) const {
+ keymaster_purpose_t purpose) const {
KeyFactory* key_factory = GetKeyFactory(algorithm);
- if (!key_factory)
- return nullptr;
+ if (!key_factory) return nullptr;
return key_factory->GetOperationFactory(purpose);
}
@@ -111,8 +126,17 @@
KeymasterKeyBlob* blob,
AuthorizationSet* hw_enforced,
AuthorizationSet* sw_enforced) const {
+ // Check whether the key blob can be securely stored by pure software secure key storage.
+ bool canStoreBySecureKeyStorageIfRequired = false;
+ if (GetSecurityLevel() != KM_SECURITY_LEVEL_SOFTWARE &&
+ pure_soft_secure_key_storage_ != nullptr) {
+ pure_soft_secure_key_storage_->HasSlot(&canStoreBySecureKeyStorageIfRequired);
+ }
+
+ bool needStoreBySecureKeyStorage = false;
if (key_description.GetTagValue(TAG_ROLLBACK_RESISTANCE)) {
- return KM_ERROR_ROLLBACK_RESISTANCE_UNAVAILABLE;
+ needStoreBySecureKeyStorage = true;
+ if (!canStoreBySecureKeyStorageIfRequired) return KM_ERROR_ROLLBACK_RESISTANCE_UNAVAILABLE;
}
if (GetSecurityLevel() != KM_SECURITY_LEVEL_SOFTWARE) {
@@ -141,8 +165,19 @@
case KM_TAG_ORIGIN:
case KM_TAG_OS_VERSION:
case KM_TAG_OS_PATCHLEVEL:
+ case KM_TAG_EARLY_BOOT_ONLY:
+ case KM_TAG_UNLOCKED_DEVICE_REQUIRED:
+ case KM_TAG_RSA_OAEP_MGF_DIGEST:
+ case KM_TAG_ROLLBACK_RESISTANCE:
hw_enforced->push_back(entry);
break;
+ case KM_TAG_USAGE_COUNT_LIMIT:
+ // Enforce single use key with usage count limit = 1 into secure key storage.
+ if (canStoreBySecureKeyStorageIfRequired && entry.integer == 1) {
+ needStoreBySecureKeyStorage = true;
+ hw_enforced->push_back(entry);
+ }
+ break;
default:
break;
}
@@ -152,23 +187,34 @@
keymaster_error_t error = SetKeyBlobAuthorizations(key_description, origin, os_version_,
os_patchlevel_, hw_enforced, sw_enforced);
if (error != KM_ERROR_OK) return error;
+ error =
+ ExtendKeyBlobAuthorizations(hw_enforced, sw_enforced, vendor_patchlevel_, boot_patchlevel_);
+ if (error != KM_ERROR_OK) return error;
AuthorizationSet hidden;
error = BuildHiddenAuthorizations(key_description, &hidden, softwareRootOfTrust);
if (error != KM_ERROR_OK) return error;
- return SerializeIntegrityAssuredBlob(key_material, hidden, *hw_enforced, *sw_enforced, blob);
+ error = SerializeIntegrityAssuredBlob(key_material, hidden, *hw_enforced, *sw_enforced, blob);
+ if (error != KM_ERROR_OK) return error;
+
+ // Pretend to be some sort of secure hardware that can securely store the key blob.
+ if (!needStoreBySecureKeyStorage) return KM_ERROR_OK;
+ km_id_t keyid;
+ if (!soft_keymaster_enforcement_.CreateKeyId(*blob, &keyid)) return KM_ERROR_UNKNOWN_ERROR;
+ assert(needStoreBySecureKeyStorage && canStoreBySecureKeyStorageIfRequired);
+ return pure_soft_secure_key_storage_->WriteKey(keyid, *blob);
}
keymaster_error_t PureSoftKeymasterContext::UpgradeKeyBlob(const KeymasterKeyBlob& key_to_upgrade,
- const AuthorizationSet& upgrade_params,
- KeymasterKeyBlob* upgraded_key) const {
+ const AuthorizationSet& upgrade_params,
+ KeymasterKeyBlob* upgraded_key) const {
UniquePtr<Key> key;
keymaster_error_t error = ParseKeyBlob(key_to_upgrade, upgrade_params, &key);
- if (error != KM_ERROR_OK)
- return error;
+ if (error != KM_ERROR_OK) return error;
- return UpgradeSoftKeyBlob(key, os_version_, os_patchlevel_, upgrade_params, upgraded_key);
+ return FullUpgradeSoftKeyBlob(key, os_version_, os_patchlevel_, vendor_patchlevel_,
+ boot_patchlevel_, upgrade_params, upgraded_key);
}
keymaster_error_t PureSoftKeymasterContext::ParseKeyBlob(const KeymasterKeyBlob& blob,
@@ -201,7 +247,7 @@
KeymasterKeyBlob key_material;
keymaster_error_t error;
- auto constructKey = [&, this] () mutable -> keymaster_error_t {
+ auto constructKey = [&, this]() mutable -> keymaster_error_t {
// GetKeyFactory
if (error != KM_ERROR_OK) return error;
keymaster_algorithm_t algorithm;
@@ -209,6 +255,20 @@
!sw_enforced.GetTagValue(TAG_ALGORITHM, &algorithm)) {
return KM_ERROR_INVALID_ARGUMENT;
}
+
+ // Pretend to be some sort of secure hardware that can securely store
+ // the key blob. Check the key blob is still securely stored now.
+ if (hw_enforced.Contains(KM_TAG_ROLLBACK_RESISTANCE) ||
+ hw_enforced.Contains(KM_TAG_USAGE_COUNT_LIMIT)) {
+ if (pure_soft_secure_key_storage_ == nullptr) return KM_ERROR_INVALID_KEY_BLOB;
+ km_id_t keyid;
+ bool exists;
+ if (!soft_keymaster_enforcement_.CreateKeyId(blob, &keyid))
+ return KM_ERROR_INVALID_KEY_BLOB;
+ error = pure_soft_secure_key_storage_->KeyExists(keyid, &exists);
+ if (error != KM_ERROR_OK || !exists) return KM_ERROR_INVALID_KEY_BLOB;
+ }
+
auto factory = GetKeyFactory(algorithm);
return factory->LoadKey(move(key_material), additional_params, move(hw_enforced),
move(sw_enforced), key);
@@ -216,71 +276,114 @@
AuthorizationSet hidden;
error = BuildHiddenAuthorizations(additional_params, &hidden, softwareRootOfTrust);
- if (error != KM_ERROR_OK)
- return error;
+ if (error != KM_ERROR_OK) return error;
// Assume it's an integrity-assured blob (new software-only blob, or new keymaster0-backed
// blob).
- error = DeserializeIntegrityAssuredBlob(blob, hidden, &key_material, &hw_enforced, &sw_enforced);
- if (error != KM_ERROR_INVALID_KEY_BLOB)
- return constructKey();
+ error =
+ DeserializeIntegrityAssuredBlob(blob, hidden, &key_material, &hw_enforced, &sw_enforced);
+ if (error != KM_ERROR_INVALID_KEY_BLOB) return constructKey();
- // Wasn't an integrity-assured blob. Maybe it's an OCB-encrypted blob.
- error = ParseOcbAuthEncryptedBlob(blob, hidden, &key_material, &hw_enforced, &sw_enforced);
- if (error == KM_ERROR_OK)
- LOG_D("Parsed an old keymaster1 software key", 0);
- if (error != KM_ERROR_INVALID_KEY_BLOB)
- return constructKey();
+ // Wasn't an integrity-assured blob. Maybe it's an auth-encrypted blob.
+ error = ParseAuthEncryptedBlob(blob, hidden, &key_material, &hw_enforced, &sw_enforced);
+ if (error == KM_ERROR_OK) LOG_D("Parsed an old keymaster1 software key", 0);
+ if (error != KM_ERROR_INVALID_KEY_BLOB) return constructKey();
- // Wasn't an OCB-encrypted blob. Maybe it's an old softkeymaster blob.
+ // Wasn't an auth-encrypted blob. Maybe it's an old softkeymaster blob.
error = ParseOldSoftkeymasterBlob(blob, &key_material, &hw_enforced, &sw_enforced);
- if (error == KM_ERROR_OK)
- LOG_D("Parsed an old sofkeymaster key", 0);
+ if (error == KM_ERROR_OK) LOG_D("Parsed an old sofkeymaster key", 0);
return constructKey();
}
-keymaster_error_t PureSoftKeymasterContext::DeleteKey(const KeymasterKeyBlob& /* blob */) const {
- // Nothing to do for software-only contexts.
+keymaster_error_t PureSoftKeymasterContext::DeleteKey(const KeymasterKeyBlob& blob) const {
+ // Pretend to be some secure hardware with secure storage.
+ if (GetSecurityLevel() != KM_SECURITY_LEVEL_SOFTWARE &&
+ pure_soft_secure_key_storage_ != nullptr) {
+ km_id_t keyid;
+ if (!soft_keymaster_enforcement_.CreateKeyId(blob, &keyid)) return KM_ERROR_UNKNOWN_ERROR;
+ return pure_soft_secure_key_storage_->DeleteKey(keyid);
+ }
+
+ // Otherwise, nothing to do for software-only contexts.
return KM_ERROR_OK;
}
keymaster_error_t PureSoftKeymasterContext::DeleteAllKeys() const {
+ // Pretend to be some secure hardware with secure storage.
+ if (GetSecurityLevel() != KM_SECURITY_LEVEL_SOFTWARE &&
+ pure_soft_secure_key_storage_ != nullptr) {
+ return pure_soft_secure_key_storage_->DeleteAllKeys();
+ }
+
+ // Otherwise, nothing to do for software-only contexts.
return KM_ERROR_OK;
}
keymaster_error_t PureSoftKeymasterContext::AddRngEntropy(const uint8_t* buf, size_t length) const {
+ if (length > 2 * 1024) {
+ // At most 2KiB is allowed to be added at once.
+ return KM_ERROR_INVALID_INPUT_LENGTH;
+ }
// XXX TODO according to boringssl openssl/rand.h RAND_add is deprecated and does
// nothing
RAND_add(buf, length, 0 /* Don't assume any entropy is added to the pool. */);
return KM_ERROR_OK;
}
-keymaster_error_t PureSoftKeymasterContext::GenerateAttestation(const Key& key,
- const AuthorizationSet& attest_params,
- CertChainPtr* cert_chain) const {
+CertificateChain
+PureSoftKeymasterContext::GenerateAttestation(const Key& key, //
+ const AuthorizationSet& attest_params, //
+ UniquePtr<Key> attest_key,
+ const KeymasterBlob& issuer_subject,
+ keymaster_error_t* error) const {
+ if (!error) return {};
+ *error = KM_ERROR_OK;
- keymaster_error_t error = KM_ERROR_OK;
keymaster_algorithm_t key_algorithm;
if (!key.authorizations().GetTagValue(TAG_ALGORITHM, &key_algorithm)) {
- return KM_ERROR_UNKNOWN_ERROR;
+ *error = KM_ERROR_UNKNOWN_ERROR;
+ return {};
}
- if ((key_algorithm != KM_ALGORITHM_RSA && key_algorithm != KM_ALGORITHM_EC))
- return KM_ERROR_INCOMPATIBLE_ALGORITHM;
+ if ((key_algorithm != KM_ALGORITHM_RSA && key_algorithm != KM_ALGORITHM_EC)) {
+ *error = KM_ERROR_INCOMPATIBLE_ALGORITHM;
+ return {};
+ }
+
+ if (attest_params.GetTagValue(TAG_DEVICE_UNIQUE_ATTESTATION)) {
+ *error = KM_ERROR_UNIMPLEMENTED;
+ return {};
+ }
+ // We have established that the given key has the correct algorithm, and because this is the
+ // SoftKeymasterContext we can assume that the Key is an AsymmetricKey. So we can downcast.
+ const AsymmetricKey& asymmetric_key = static_cast<const AsymmetricKey&>(key);
+
+ AttestKeyInfo attest_key_info(attest_key, &issuer_subject, error);
+ if (*error != KM_ERROR_OK) return {};
+
+ return generate_attestation(asymmetric_key, attest_params, move(attest_key_info), *this, error);
+}
+
+CertificateChain PureSoftKeymasterContext::GenerateSelfSignedCertificate(
+ const Key& key, const AuthorizationSet& cert_params, bool fake_signature,
+ keymaster_error_t* error) const {
+ keymaster_algorithm_t key_algorithm;
+ if (!key.authorizations().GetTagValue(TAG_ALGORITHM, &key_algorithm)) {
+ *error = KM_ERROR_UNKNOWN_ERROR;
+ return {};
+ }
+
+ if ((key_algorithm != KM_ALGORITHM_RSA && key_algorithm != KM_ALGORITHM_EC)) {
+ *error = KM_ERROR_INCOMPATIBLE_ALGORITHM;
+ return {};
+ }
// We have established that the given key has the correct algorithm, and because this is the
// SoftKeymasterContext we can assume that the Key is an AsymmetricKey. So we can downcast.
const AsymmetricKey& asymmetric_key = static_cast<const AsymmetricKey&>(key);
- auto attestation_chain = getAttestationChain(key_algorithm, &error);
- if (error != KM_ERROR_OK) return error;
-
- auto attestation_key = getAttestationKey(key_algorithm, &error);
- if (error != KM_ERROR_OK) return error;
-
- return generate_attestation(asymmetric_key, attest_params,
- *attestation_chain, *attestation_key, *this, cert_chain);
+ return generate_self_signed_cert(asymmetric_key, cert_params, fake_signature, error);
}
static keymaster_error_t TranslateAuthorizationSetError(AuthorizationSet::Error err) {
@@ -421,7 +524,7 @@
wrapped_key_description.data_length)
.build();
if (update_params.is_valid() != AuthorizationSet::Error::OK) {
- return TranslateAuthorizationSetError(transit_key_authorizations.is_valid());
+ return TranslateAuthorizationSetError(update_params.is_valid());
}
error = aes_operation->Update(update_params, encrypted_key, &update_outparams, &plaintext,
@@ -442,16 +545,17 @@
return error;
}
-keymaster_error_t PureSoftKeymasterContext::GetVerifiedBootParams(
- keymaster_blob_t* verified_boot_key, keymaster_blob_t* verified_boot_hash,
- keymaster_verified_boot_t* verified_boot_state, bool* device_locked) const {
- // TODO(swillden): See if there might be some sort of vbmeta data in goldfish/cuttlefish.
- static std::string fake_vb_key = "12345678901234567890123456789012";
- *verified_boot_key = {reinterpret_cast<uint8_t*>(fake_vb_key.data()), fake_vb_key.size()};
- *verified_boot_hash = {reinterpret_cast<uint8_t*>(fake_vb_key.data()), fake_vb_key.size()};
- *verified_boot_state = KM_VERIFIED_BOOT_UNVERIFIED;
- *device_locked = false;
- return KM_ERROR_OK;
+const AttestationContext::VerifiedBootParams*
+PureSoftKeymasterContext::GetVerifiedBootParams(keymaster_error_t* error) const {
+ static VerifiedBootParams params;
+ static std::string fake_vb_key(32, 0);
+ params.verified_boot_key = {reinterpret_cast<uint8_t*>(fake_vb_key.data()), fake_vb_key.size()};
+ params.verified_boot_hash = {reinterpret_cast<uint8_t*>(fake_vb_key.data()),
+ fake_vb_key.size()};
+ params.verified_boot_state = KM_VERIFIED_BOOT_UNVERIFIED;
+ params.device_locked = false;
+ *error = KM_ERROR_OK;
+ return ¶ms;
}
} // namespace keymaster
diff --git a/contexts/pure_soft_remote_provisioning_context.cpp b/contexts/pure_soft_remote_provisioning_context.cpp
new file mode 100644
index 0000000..a943f42
--- /dev/null
+++ b/contexts/pure_soft_remote_provisioning_context.cpp
@@ -0,0 +1,135 @@
+/*
+ * Copyright 2021 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 <keymaster/contexts/pure_soft_remote_provisioning_context.h>
+
+#include <algorithm>
+#include <assert.h>
+
+#include <keymaster/cppcose/cppcose.h>
+#include <keymaster/logger.h>
+
+#include <openssl/bn.h>
+#include <openssl/ec.h>
+#include <openssl/hkdf.h>
+#include <openssl/rand.h>
+
+namespace keymaster {
+
+using cppcose::constructCoseSign1;
+using cppcose::CoseKey;
+using cppcose::ED25519;
+using cppcose::EDDSA;
+using cppcose::OCTET_KEY_PAIR;
+using cppcose::VERIFY;
+
+constexpr uint32_t kMacKeyLength = 32;
+
+PureSoftRemoteProvisioningContext::PureSoftRemoteProvisioningContext() {
+ std::tie(devicePrivKey_, bcc_) = GenerateBcc(/*testMode=*/false);
+}
+
+PureSoftRemoteProvisioningContext::~PureSoftRemoteProvisioningContext() {}
+
+std::vector<uint8_t>
+PureSoftRemoteProvisioningContext::DeriveBytesFromHbk(const std::string& context,
+ size_t num_bytes) const {
+ // bytevec fakeHbk(32, 0);
+ // bytevec result(numBytes);
+ // is it safe to revert the call below back to the call above?
+ std::vector<uint8_t> fakeHbk(32);
+ std::vector<uint8_t> result(num_bytes);
+
+ // TODO: Figure out if HKDF can fail. It doesn't seem like it should be able to,
+ // but the function does return an error code.
+ HKDF(result.data(), num_bytes, //
+ EVP_sha256(), //
+ fakeHbk.data(), fakeHbk.size(), //
+ nullptr /* salt */, 0 /* salt len */, //
+ reinterpret_cast<const uint8_t*>(context.data()), context.size());
+
+ return result;
+}
+
+std::unique_ptr<cppbor::Map> PureSoftRemoteProvisioningContext::CreateDeviceInfo() const {
+ auto result = std::make_unique<cppbor::Map>(cppbor::Map());
+
+ // The following placeholders show how the DeviceInfo map would be populated.
+ // result->add(cppbor::Tstr("brand"), cppbor::Tstr("Google"));
+ // result->add(cppbor::Tstr("manufacturer"), cppbor::Tstr("Google"));
+ // result->add(cppbor::Tstr("product"), cppbor::Tstr("Fake"));
+ // result->add(cppbor::Tstr("model"), cppbor::Tstr("Imaginary"));
+ // result->add(cppbor::Tstr("board"), cppbor::Tstr("Chess"));
+ // result->add(cppbor::Tstr("vb_state"), cppbor::Tstr("orange"));
+ // result->add(cppbor::Tstr("bootloader_state"), cppbor::Tstr("unlocked"));
+ // result->add(cppbor::Tstr("os_version"), cppbor::Tstr("SC"));
+ // result->add(cppbor::Tstr("system_patch_level"), cppbor::Uint(20210331));
+ // result->add(cppbor::Tstr("boot_patch_level"), cppbor::Uint(20210331));
+ // result->add(cppbor::Tstr("vendor_patch_level"), cppbor::Uint(20210331));
+
+ result->canonicalize();
+ return result;
+}
+
+std::pair<std::vector<uint8_t> /* privKey */, cppbor::Array /* BCC */>
+PureSoftRemoteProvisioningContext::GenerateBcc(bool testMode) const {
+ std::vector<uint8_t> privKey(ED25519_PRIVATE_KEY_LEN);
+ std::vector<uint8_t> pubKey(ED25519_PUBLIC_KEY_LEN);
+
+ uint8_t seed[32]; // Length is hard-coded in the BoringCrypto API
+ if (testMode) {
+ RAND_bytes(seed, sizeof(seed));
+ } else {
+ auto seed_vector = DeriveBytesFromHbk("Device Key Seed", sizeof(seed));
+ std::copy(seed_vector.begin(), seed_vector.end(), seed);
+ }
+ ED25519_keypair_from_seed(pubKey.data(), privKey.data(), seed);
+
+ auto coseKey = cppbor::Map()
+ .add(CoseKey::KEY_TYPE, OCTET_KEY_PAIR)
+ .add(CoseKey::ALGORITHM, EDDSA)
+ .add(CoseKey::CURVE, ED25519)
+ .add(CoseKey::KEY_OPS, VERIFY)
+ .add(CoseKey::PUBKEY_X, pubKey)
+ .canonicalize();
+ auto sign1Payload = cppbor::Map()
+ .add(1 /* Issuer */, "Issuer")
+ .add(2 /* Subject */, "Subject")
+ .add(-4670552 /* Subject Pub Key */, coseKey.encode())
+ .add(-4670553 /* Key Usage (little-endian order) */,
+ std::vector<uint8_t>{0x20} /* keyCertSign = 1<<5 */)
+ .canonicalize()
+ .encode();
+ auto coseSign1 = constructCoseSign1(privKey, /* signing key */
+ cppbor::Map(), /* extra protected */
+ sign1Payload, {} /* AAD */);
+ assert(coseSign1);
+
+ return {privKey, cppbor::Array().add(std::move(coseKey)).add(coseSign1.moveValue())};
+}
+
+std::optional<cppcose::HmacSha256>
+PureSoftRemoteProvisioningContext::GenerateHmacSha256(const cppcose::bytevec& input) const {
+ auto key = DeriveBytesFromHbk("Key to MAC public keys", kMacKeyLength);
+ auto result = cppcose::generateHmacSha256(key, input);
+ if (!result) {
+ LOG_E("Error signing MAC: %s", result.message().c_str());
+ return std::nullopt;
+ }
+ return *result;
+}
+
+} // namespace keymaster
diff --git a/contexts/soft_attestation_cert.cpp b/contexts/soft_attestation_cert.cpp
index cc9d104..87110a6 100644
--- a/contexts/soft_attestation_cert.cpp
+++ b/contexts/soft_attestation_cert.cpp
@@ -15,12 +15,11 @@
** limitations under the License.
*/
-#include "soft_attestation_cert.h"
+#include <keymaster/contexts/soft_attestation_cert.h>
-#include <stdint.h>
#include <hardware/keymaster_defs.h>
#include <keymaster/android_keymaster_utils.h>
-#include <openssl/aes.h>
+#include <stdint.h>
namespace keymaster {
@@ -68,9 +67,8 @@
0x25,
};
-static const keymaster_key_blob_t kRsaAttestKeyBlob = {
- (const uint8_t*)&kRsaAttestKey, sizeof(kRsaAttestKey)
-};
+static const keymaster_key_blob_t kRsaAttestKeyBlob = {(const uint8_t*)&kRsaAttestKey,
+ sizeof(kRsaAttestKey)};
static const uint8_t kRsaAttestCert[] = {
0x30, 0x82, 0x02, 0xb6, 0x30, 0x82, 0x02, 0x1f, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x02, 0x10,
@@ -166,12 +164,10 @@
};
static keymaster_blob_t kRsaAttestChainBlobs[] = {
- {(const uint8_t*)&kRsaAttestCert, sizeof(kRsaAttestCert)},
- {(const uint8_t*)&kRsaAttestRootCert, sizeof(kRsaAttestRootCert)}
-};
+ {(const uint8_t*)&kRsaAttestCert, sizeof(kRsaAttestCert)},
+ {(const uint8_t*)&kRsaAttestRootCert, sizeof(kRsaAttestRootCert)}};
-static const keymaster_cert_chain_t kRsaAttestChain = { (keymaster_blob_t*)&kRsaAttestChainBlobs, 2 };
-
+static const keymaster_cert_chain_t kRsaAttestChain = {(keymaster_blob_t*)&kRsaAttestChainBlobs, 2};
static const uint8_t kEcAttestKey[] = {
0x30, 0x77, 0x02, 0x01, 0x01, 0x04, 0x20, 0x21, 0xe0, 0x86, 0x43, 0x2a, 0x15, 0x19, 0x84, 0x59,
@@ -184,9 +180,8 @@
0x71, 0x58, 0x3e, 0xdb, 0x3e, 0x11, 0xae, 0x10, 0x14,
};
-static const keymaster_key_blob_t kEcAttestKeyBlob = {
- (const uint8_t*)&kEcAttestKey, sizeof(kEcAttestKey)
-};
+static const keymaster_key_blob_t kEcAttestKeyBlob = {(const uint8_t*)&kEcAttestKey,
+ sizeof(kEcAttestKey)};
static const uint8_t kEcAttestCert[] = {
0x30, 0x82, 0x02, 0x78, 0x30, 0x82, 0x02, 0x1e, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x02, 0x10,
@@ -276,15 +271,15 @@
};
static keymaster_blob_t kEcAttestChainBlobs[] = {
- {(const uint8_t*)&kEcAttestCert, sizeof(kEcAttestCert)},
- {(const uint8_t*)&kEcAttestRootCert, sizeof(kEcAttestRootCert)}
-};
+ {(const uint8_t*)&kEcAttestCert, sizeof(kEcAttestCert)},
+ {(const uint8_t*)&kEcAttestRootCert, sizeof(kEcAttestRootCert)}};
-static const keymaster_cert_chain_t kEcAttestChain = { (keymaster_blob_t*)&kEcAttestChainBlobs, 2 };
+static const keymaster_cert_chain_t kEcAttestChain = {(keymaster_blob_t*)&kEcAttestChainBlobs, 2};
-}
+} // namespace
-const keymaster_key_blob_t* getAttestationKey(keymaster_algorithm_t algorithm, keymaster_error_t* error) {
+const keymaster_key_blob_t* getAttestationKey(keymaster_algorithm_t algorithm,
+ keymaster_error_t* error) {
if (error) *error = KM_ERROR_OK;
@@ -301,24 +296,26 @@
}
}
-
-const keymaster_cert_chain_t* getAttestationChain(
- keymaster_algorithm_t algorithm, keymaster_error_t* error) {
-
+CertificateChain getAttestationChain(keymaster_algorithm_t algorithm, keymaster_error_t* error) {
if (error) *error = KM_ERROR_OK;
- switch(algorithm) {
+ CertificateChain retval;
+
+ switch (algorithm) {
case KM_ALGORITHM_RSA:
- return &kRsaAttestChain;
+ retval = CertificateChain::clone(kRsaAttestChain);
+ if (!retval.entries && error) *error = KM_ERROR_MEMORY_ALLOCATION_FAILED;
break;
case KM_ALGORITHM_EC:
- return &kEcAttestChain;
+ retval = CertificateChain::clone(kEcAttestChain);
+ if (!retval.entries && error) *error = KM_ERROR_MEMORY_ALLOCATION_FAILED;
break;
default:
if (error) *error = KM_ERROR_UNSUPPORTED_ALGORITHM;
+ break;
}
- return nullptr;
+
+ return retval;
}
-} // namespace keymaster
-
+} // namespace keymaster
diff --git a/contexts/soft_attestation_context.cpp b/contexts/soft_attestation_context.cpp
new file mode 100644
index 0000000..4a2ba9f
--- /dev/null
+++ b/contexts/soft_attestation_context.cpp
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2020 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 <keymaster/contexts/soft_attestation_context.h>
+
+#include <string>
+
+#include <keymaster/km_openssl/asymmetric_key.h>
+#include <keymaster/km_openssl/attestation_utils.h>
+
+namespace keymaster {
+
+const AttestationContext::VerifiedBootParams*
+SoftAttestationContext::GetVerifiedBootParams(keymaster_error_t* error) const {
+ static AttestationContext::VerifiedBootParams params;
+ static std::string fake_vb_key(32, 0);
+
+ params.verified_boot_key = {reinterpret_cast<uint8_t*>(fake_vb_key.data()), fake_vb_key.size()};
+ params.verified_boot_hash = {reinterpret_cast<uint8_t*>(fake_vb_key.data()),
+ fake_vb_key.size()};
+ params.verified_boot_state = KM_VERIFIED_BOOT_UNVERIFIED;
+ params.device_locked = false;
+ *error = KM_ERROR_OK;
+ return ¶ms;
+}
+
+} // namespace keymaster
diff --git a/contexts/soft_keymaster_context.cpp b/contexts/soft_keymaster_context.cpp
index a0a42d3..86bdd3f 100644
--- a/contexts/soft_keymaster_context.cpp
+++ b/contexts/soft_keymaster_context.cpp
@@ -28,17 +28,15 @@
#include <keymaster/km_openssl/aes_key.h>
#include <keymaster/km_openssl/asymmetric_key.h>
#include <keymaster/km_openssl/attestation_utils.h>
+#include <keymaster/km_openssl/certificate_utils.h>
#include <keymaster/km_openssl/hmac_key.h>
#include <keymaster/km_openssl/openssl_err.h>
#include <keymaster/km_openssl/triple_des_key.h>
-#include <keymaster/legacy_support/ec_keymaster0_key.h>
#include <keymaster/legacy_support/ec_keymaster1_key.h>
-#include <keymaster/legacy_support/keymaster0_engine.h>
-#include <keymaster/legacy_support/rsa_keymaster0_key.h>
#include <keymaster/legacy_support/rsa_keymaster1_key.h>
#include <keymaster/logger.h>
-#include "soft_attestation_cert.h"
+#include <keymaster/contexts/soft_attestation_cert.h>
using std::unique_ptr;
@@ -52,41 +50,28 @@
} // anonymous namespace
-SoftKeymasterContext::SoftKeymasterContext(const std::string& root_of_trust)
- : rsa_factory_(new RsaKeyFactory(this)), ec_factory_(new EcKeyFactory(this)),
- aes_factory_(new AesKeyFactory(this, this)),
- tdes_factory_(new TripleDesKeyFactory(this, this)),
- hmac_factory_(new HmacKeyFactory(this, this)), km1_dev_(nullptr),
- root_of_trust_(string2Blob(root_of_trust)), os_version_(0), os_patchlevel_(0) {}
+SoftKeymasterContext::SoftKeymasterContext(KmVersion version, const std::string& root_of_trust)
+ : SoftAttestationContext(version), //
+ rsa_factory_(new RsaKeyFactory(*this /* blob_maker */, *this /* context */)),
+ ec_factory_(new EcKeyFactory(*this /* blob_maker */, *this /* context */)),
+ aes_factory_(new AesKeyFactory(*this /* blob_maker */, *this /* random_source */)),
+ tdes_factory_(new TripleDesKeyFactory(*this /* blob_maker */, *this /* random_source */)),
+ hmac_factory_(new HmacKeyFactory(*this /* blob_maker */, *this /* random_source */)),
+ km1_dev_(nullptr), root_of_trust_(string2Blob(root_of_trust)), os_version_(0),
+ os_patchlevel_(0) {}
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;
+ 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()));
+ rsa_factory_.reset(new RsaKeymaster1KeyFactory(
+ *this /* blob_maker */, *this /* attestation_context */, km1_engine_.get()));
+ ec_factory_.reset(new EcdsaKeymaster1KeyFactory(
+ *this /* blob_maker */, *this /* attestation_context */, km1_engine_.get()));
// Use default HMAC and AES key factories. Higher layers will pass HMAC/AES keys/ops that are
// supported by the hardware to it and other ones to the software-only factory.
@@ -135,8 +120,7 @@
OperationFactory* SoftKeymasterContext::GetOperationFactory(keymaster_algorithm_t algorithm,
keymaster_purpose_t purpose) const {
KeyFactory* key_factory = GetKeyFactory(algorithm);
- if (!key_factory)
- return nullptr;
+ if (!key_factory) return nullptr;
return key_factory->GetOperationFactory(purpose);
}
@@ -179,8 +163,7 @@
// Everything else we just copy into sw_enforced, unless the KeyFactory has placed it in
// hw_enforced, in which case we defer to its decision.
default:
- if (hw_enforced->GetTagCount(entry.tag) == 0)
- sw_enforced->push_back(entry);
+ if (hw_enforced->GetTagCount(entry.tag) == 0) sw_enforced->push_back(entry);
break;
}
}
@@ -201,13 +184,11 @@
AuthorizationSet* sw_enforced) const {
keymaster_error_t error = SetAuthorizations(key_description, origin, os_version_,
os_patchlevel_, hw_enforced, sw_enforced);
- if (error != KM_ERROR_OK)
- return error;
+ if (error != KM_ERROR_OK) return error;
AuthorizationSet hidden;
error = BuildHiddenAuthorizations(key_description, &hidden, root_of_trust_);
- if (error != KM_ERROR_OK)
- return error;
+ if (error != KM_ERROR_OK) return error;
return SerializeIntegrityAssuredBlob(key_material, hidden, *hw_enforced, *sw_enforced, blob);
}
@@ -217,8 +198,7 @@
KeymasterKeyBlob* upgraded_key) const {
UniquePtr<Key> key;
keymaster_error_t error = ParseKeyBlob(key_to_upgrade, upgrade_params, &key);
- if (error != KM_ERROR_OK)
- return error;
+ if (error != KM_ERROR_OK) return error;
// Three cases here:
//
@@ -233,7 +213,7 @@
// Handle case 3.
if (km1_dev_ && key->hw_enforced().Contains(TAG_PURPOSE) &&
- !key->hw_enforced().Contains(TAG_OS_PATCHLEVEL))
+ !key->hw_enforced().Contains(TAG_OS_PATCHLEVEL))
return KM_ERROR_INVALID_ARGUMENT;
// Handle case 1 and 2
@@ -281,7 +261,7 @@
AuthorizationSet hidden;
keymaster_error_t error;
- auto constructKey = [&, this] () mutable -> keymaster_error_t {
+ auto constructKey = [&, this]() mutable -> keymaster_error_t {
// GetKeyFactory
if (error != KM_ERROR_OK) return error;
keymaster_algorithm_t algorithm;
@@ -295,34 +275,27 @@
};
error = BuildHiddenAuthorizations(additional_params, &hidden, root_of_trust_);
- if (error != KM_ERROR_OK)
- return error;
+ if (error != KM_ERROR_OK) return error;
// Assume it's an integrity-assured blob (new software-only blob, or new keymaster0-backed
// blob).
- error = DeserializeIntegrityAssuredBlob(blob, hidden, &key_material, &hw_enforced, &sw_enforced);
- if (error != KM_ERROR_INVALID_KEY_BLOB)
- return constructKey();
+ error =
+ DeserializeIntegrityAssuredBlob(blob, hidden, &key_material, &hw_enforced, &sw_enforced);
+ if (error != KM_ERROR_INVALID_KEY_BLOB) return constructKey();
- // Wasn't an integrity-assured blob. Maybe it's an OCB-encrypted blob.
- error = ParseOcbAuthEncryptedBlob(blob, hidden, &key_material, &hw_enforced, &sw_enforced);
- if (error == KM_ERROR_OK)
- LOG_D("Parsed an old keymaster1 software key", 0);
- if (error != KM_ERROR_INVALID_KEY_BLOB)
- return constructKey();
+ // Wasn't an integrity-assured blob. Maybe it's an Auth-encrypted blob.
+ error = ParseAuthEncryptedBlob(blob, hidden, &key_material, &hw_enforced, &sw_enforced);
+ if (error == KM_ERROR_OK) LOG_D("Parsed an old keymaster1 software key", 0);
+ if (error != KM_ERROR_INVALID_KEY_BLOB) return constructKey();
// Wasn't an OCB-encrypted blob. Maybe it's an old softkeymaster blob.
error = ParseOldSoftkeymasterBlob(blob, &key_material, &hw_enforced, &sw_enforced);
- if (error == KM_ERROR_OK)
- LOG_D("Parsed an old sofkeymaster key", 0);
- if (error != KM_ERROR_INVALID_KEY_BLOB)
- return constructKey();
+ if (error == KM_ERROR_OK) LOG_D("Parsed an old sofkeymaster key", 0);
+ if (error != KM_ERROR_INVALID_KEY_BLOB) return constructKey();
if (km1_dev_) {
error = ParseKeymaster1HwBlob(blob, additional_params, &key_material, &hw_enforced,
&sw_enforced);
- } else if (km0_engine_) {
- error = ParseKeymaster0HwBlob(blob, &key_material, &hw_enforced, &sw_enforced);
} else {
return KM_ERROR_INVALID_KEY_BLOB;
}
@@ -345,45 +318,12 @@
return km1_engine_->DeleteKey(blob);
}
- if (km0_engine_) {
- // This could be a keymaster0 hardware key, and it could be either raw or encapsulated in an
- // integrity-assured blob. If it's integrity-assured, we can't validate it strongly,
- // because we don't have the necessary additional_params data. However, the probability
- // that anything other than an integrity-assured blob would have all of the structure
- // required to decode as a valid blob is low -- unless it's maliciously-constructed, but the
- // deserializer should be proof against bad data, as should the keymaster0 hardware.
- //
- // Thus, we first try to parse it as integrity-assured. If that works, we pass the result
- // to the underlying hardware. If not, we pass blob unmodified to the underlying hardware.
- KeymasterKeyBlob key_material;
- AuthorizationSet hw_enforced, sw_enforced;
- keymaster_error_t error = DeserializeIntegrityAssuredBlob_NoHmacCheck(
- blob, &key_material, &hw_enforced, &sw_enforced);
- if (error == KM_ERROR_OK && km0_engine_->DeleteKey(key_material))
- return KM_ERROR_OK;
-
- km0_engine_->DeleteKey(blob);
-
- // We succeed unconditionally at this point, even if delete failed. Failure indicates that
- // either the blob is a software blob (which we can't distinguish with certainty without
- // additional_params) or because it is a hardware blob and the hardware failed. In the
- // first case, there is no error. In the second case, the client can't do anything to fix
- // it anyway, so it's not too harmful to simply swallow the error. This is not ideal, but
- // it's the least-bad alternative.
- return KM_ERROR_OK;
- }
-
// Nothing to do for software-only contexts.
return KM_ERROR_OK;
}
keymaster_error_t SoftKeymasterContext::DeleteAllKeys() const {
- if (km1_engine_)
- return km1_engine_->DeleteAllKeys();
-
- if (km0_engine_ && !km0_engine_->DeleteAllKeys())
- return KM_ERROR_UNKNOWN_ERROR;
-
+ if (km1_engine_) return km1_engine_->DeleteAllKeys();
return KM_ERROR_OK;
}
@@ -402,17 +342,14 @@
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;
+ 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;
+ if (error != KM_ERROR_OK) return error;
unique_ptr<keymaster_key_characteristics_t, Characteristics_Delete> characteristics_deleter(
characteristics);
@@ -424,49 +361,49 @@
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));
-
- if (!tmp_key)
- return KM_ERROR_INVALID_KEY_BLOB;
-
- 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;
-
- return error;
-}
-
-keymaster_error_t SoftKeymasterContext::GenerateAttestation(const Key& key,
- const AuthorizationSet& attest_params, CertChainPtr* cert_chain) const {
-
- keymaster_error_t error = KM_ERROR_OK;
+CertificateChain
+SoftKeymasterContext::GenerateAttestation(const Key& key, //
+ const AuthorizationSet& attest_params,
+ UniquePtr<Key> /* attest_key */,
+ const KeymasterBlob& /* issuer_subject */, //
+ keymaster_error_t* error) const {
keymaster_algorithm_t key_algorithm;
if (!key.authorizations().GetTagValue(TAG_ALGORITHM, &key_algorithm)) {
- return KM_ERROR_UNKNOWN_ERROR;
+ *error = KM_ERROR_UNKNOWN_ERROR;
+ return {};
}
- if ((key_algorithm != KM_ALGORITHM_RSA && key_algorithm != KM_ALGORITHM_EC))
- return KM_ERROR_INCOMPATIBLE_ALGORITHM;
+ if ((key_algorithm != KM_ALGORITHM_RSA && key_algorithm != KM_ALGORITHM_EC)) {
+ *error = KM_ERROR_INCOMPATIBLE_ALGORITHM;
+ return {};
+ }
// We have established that the given key has the correct algorithm, and because this is the
// SoftKeymasterContext we can assume that the Key is an AsymmetricKey. So we can downcast.
const AsymmetricKey& asymmetric_key = static_cast<const AsymmetricKey&>(key);
- auto attestation_chain = getAttestationChain(key_algorithm, &error);
- if (error != KM_ERROR_OK) return error;
+ return generate_attestation(asymmetric_key, attest_params, {} /* attest_key */, *this, error);
+}
- auto attestation_key = getAttestationKey(key_algorithm, &error);
- if (error != KM_ERROR_OK) return error;
+CertificateChain SoftKeymasterContext::GenerateSelfSignedCertificate(
+ const Key& key, const AuthorizationSet& cert_params, bool fake_signature,
+ keymaster_error_t* error) const {
+ keymaster_algorithm_t key_algorithm;
+ if (!key.authorizations().GetTagValue(TAG_ALGORITHM, &key_algorithm)) {
+ *error = KM_ERROR_UNKNOWN_ERROR;
+ return {};
+ }
- return generate_attestation(asymmetric_key, attest_params,
- *attestation_chain, *attestation_key, *this, cert_chain);
+ if ((key_algorithm != KM_ALGORITHM_RSA && key_algorithm != KM_ALGORITHM_EC)) {
+ *error = KM_ERROR_INCOMPATIBLE_ALGORITHM;
+ return {};
+ }
+
+ // We have established that the given key has the correct algorithm, and because this is the
+ // SoftKeymasterContext we can assume that the Key is an AsymmetricKey. So we can downcast.
+ const AsymmetricKey& asymmetric_key = static_cast<const AsymmetricKey&>(key);
+
+ return generate_self_signed_cert(asymmetric_key, cert_params, fake_signature, error);
}
keymaster_error_t SoftKeymasterContext::UnwrapKey(const KeymasterKeyBlob&, const KeymasterKeyBlob&,
diff --git a/contexts/soft_keymaster_device.cpp b/contexts/soft_keymaster_device.cpp
index 455c40a..71b0dd1 100644
--- a/contexts/soft_keymaster_device.cpp
+++ b/contexts/soft_keymaster_device.cpp
@@ -38,11 +38,10 @@
#include <keymaster/android_keymaster_messages.h>
#include <keymaster/android_keymaster_utils.h>
#include <keymaster/authorization_set.h>
-#include <keymaster/km_openssl/openssl_utils.h>
#include <keymaster/contexts/soft_keymaster_context.h>
-#include <keymaster/soft_keymaster_logger.h>
#include <keymaster/key.h>
-
+#include <keymaster/km_openssl/openssl_utils.h>
+#include <keymaster/soft_keymaster_logger.h>
struct keystore_module soft_keymaster1_device_module = {
.common =
@@ -140,8 +139,7 @@
bool alg_purpose_supports_all;
keymaster_error_t error =
add_digests(dev, algorithm, purpose, map, &alg_purpose_supports_all);
- if (error != KM_ERROR_OK)
- return error;
+ if (error != KM_ERROR_OK) return error;
*supports_all &= alg_purpose_supports_all;
}
@@ -152,17 +150,15 @@
bool alg_purpose_supports_all;
keymaster_error_t error =
add_digests(dev, algorithm, purpose, map, &alg_purpose_supports_all);
- if (error != KM_ERROR_OK)
- return error;
+ if (error != KM_ERROR_OK) return error;
*supports_all &= alg_purpose_supports_all;
}
return KM_ERROR_OK;
}
-SoftKeymasterDevice::SoftKeymasterDevice()
- : wrapped_km1_device_(nullptr),
- context_(new SoftKeymasterContext),
+SoftKeymasterDevice::SoftKeymasterDevice(KmVersion version)
+ : wrapped_km1_device_(nullptr), context_(new SoftKeymasterContext(version)),
impl_(new AndroidKeymaster(context_, kOperationTableSize)), configured_(false) {
LOG_I("Creating device", 0);
LOG_D("Device address: %p", this);
@@ -181,49 +177,18 @@
KEYMASTER_SUPPORTS_EC);
}
-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;
-
- supports_all_digests_ = false;
- keymaster_error_t error = context_->SetHardwareDevice(keymaster0_device);
- if (error != KM_ERROR_OK)
- return error;
-
- initialize_device_struct(keymaster0_device->flags);
-
- module_name_ = km1_device_.common.module->name;
- module_name_.append("(Wrapping ");
- module_name_.append(keymaster0_device->common.module->name);
- module_name_.append(")");
-
- updated_module_ = *km1_device_.common.module;
- updated_module_.name = module_name_.c_str();
-
- km1_device_.common.module = &updated_module_;
-
- 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;
+ if (!context_) return KM_ERROR_UNEXPECTED_NULL_POINTER;
keymaster_error_t error =
map_digests(keymaster1_device, &km1_device_digests_, &supports_all_digests_);
- if (error != KM_ERROR_OK)
- return error;
+ if (error != KM_ERROR_OK) return error;
error = context_->SetHardwareDevice(keymaster1_device);
- if (error != KM_ERROR_OK)
- return error;
+ if (error != KM_ERROR_OK) return error;
initialize_device_struct(keymaster1_device->flags);
@@ -359,15 +324,12 @@
void AddClientAndAppData(const keymaster_blob_t* client_id, const keymaster_blob_t* app_data,
RequestType* request) {
request->additional_params.Clear();
- if (client_id)
- request->additional_params.push_back(TAG_APPLICATION_ID, *client_id);
- if (app_data)
- request->additional_params.push_back(TAG_APPLICATION_DATA, *app_data);
+ if (client_id) request->additional_params.push_back(TAG_APPLICATION_ID, *client_id);
+ if (app_data) request->additional_params.push_back(TAG_APPLICATION_DATA, *app_data);
}
template <typename T> SoftKeymasterDevice* convert_device(const T* dev) {
- static_assert((std::is_same<T, keymaster0_device_t>::value ||
- std::is_same<T, keymaster1_device_t>::value ||
+ static_assert((std::is_same<T, keymaster1_device_t>::value ||
std::is_same<T, keymaster2_device_t>::value),
"convert_device should only be applied to keymaster devices");
return reinterpret_cast<SoftKeymasterDevice*>(dev->context);
@@ -384,7 +346,7 @@
return false;
}
-} // unnamed namespaced
+} // namespace
/* static */
int SoftKeymasterDevice::close_device(hw_device_t* dev) {
@@ -410,19 +372,17 @@
keymaster_error_t SoftKeymasterDevice::get_supported_algorithms(const keymaster1_device_t* dev,
keymaster_algorithm_t** algorithms,
size_t* algorithms_length) {
- if (!dev)
- return KM_ERROR_UNEXPECTED_NULL_POINTER;
+ if (!dev) return KM_ERROR_UNEXPECTED_NULL_POINTER;
- if (!algorithms || !algorithms_length)
- return KM_ERROR_OUTPUT_PARAMETER_NULL;
+ 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);
+ 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);
+ auto& impl_ = convert_device(dev)->impl_;
+ SupportedAlgorithmsRequest request(impl_->message_version());
+ SupportedAlgorithmsResponse response(impl_->message_version());
+ impl_->SupportedAlgorithms(request, &response);
if (response.error != KM_ERROR_OK) {
LOG_E("get_supported_algorithms failed with %d", response.error);
@@ -432,8 +392,7 @@
*algorithms_length = response.results_length;
*algorithms =
reinterpret_cast<keymaster_algorithm_t*>(malloc(*algorithms_length * sizeof(**algorithms)));
- if (!*algorithms)
- return KM_ERROR_MEMORY_ALLOCATION_FAILED;
+ if (!*algorithms) return KM_ERROR_MEMORY_ALLOCATION_FAILED;
std::copy(response.results, response.results + response.results_length, *algorithms);
return KM_ERROR_OK;
}
@@ -444,21 +403,20 @@
keymaster_purpose_t purpose,
keymaster_block_mode_t** modes,
size_t* modes_length) {
- if (!dev)
- return KM_ERROR_UNEXPECTED_NULL_POINTER;
+ if (!dev) return KM_ERROR_UNEXPECTED_NULL_POINTER;
- if (!modes || !modes_length)
- return KM_ERROR_OUTPUT_PARAMETER_NULL;
+ 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;
+ auto& impl_ = convert_device(dev)->impl_;
+ SupportedBlockModesRequest request(impl_->message_version());
request.algorithm = algorithm;
request.purpose = purpose;
- SupportedBlockModesResponse response;
- convert_device(dev)->impl_->SupportedBlockModes(request, &response);
+ SupportedBlockModesResponse response(impl_->message_version());
+ impl_->SupportedBlockModes(request, &response);
if (response.error != KM_ERROR_OK) {
LOG_E("get_supported_block_modes failed with %d", response.error);
@@ -468,8 +426,7 @@
*modes_length = response.results_length;
*modes = reinterpret_cast<keymaster_block_mode_t*>(malloc(*modes_length * sizeof(**modes)));
- if (!*modes)
- return KM_ERROR_MEMORY_ALLOCATION_FAILED;
+ if (!*modes) return KM_ERROR_MEMORY_ALLOCATION_FAILED;
std::copy(response.results, response.results + response.results_length, *modes);
return KM_ERROR_OK;
}
@@ -480,21 +437,20 @@
keymaster_purpose_t purpose,
keymaster_padding_t** modes,
size_t* modes_length) {
- if (!dev)
- return KM_ERROR_UNEXPECTED_NULL_POINTER;
+ if (!dev) return KM_ERROR_UNEXPECTED_NULL_POINTER;
- if (!modes || !modes_length)
- return KM_ERROR_OUTPUT_PARAMETER_NULL;
+ 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;
+ auto& impl_ = convert_device(dev)->impl_;
+ SupportedPaddingModesRequest request(impl_->message_version());
request.algorithm = algorithm;
request.purpose = purpose;
- SupportedPaddingModesResponse response;
+ SupportedPaddingModesResponse response(impl_->message_version());
convert_device(dev)->impl_->SupportedPaddingModes(request, &response);
if (response.error != KM_ERROR_OK) {
@@ -504,8 +460,7 @@
*modes_length = response.results_length;
*modes = reinterpret_cast<keymaster_padding_t*>(malloc(*modes_length * sizeof(**modes)));
- if (!*modes)
- return KM_ERROR_MEMORY_ALLOCATION_FAILED;
+ if (!*modes) return KM_ERROR_MEMORY_ALLOCATION_FAILED;
std::copy(response.results, response.results + response.results_length, *modes);
return KM_ERROR_OK;
}
@@ -516,21 +471,20 @@
keymaster_purpose_t purpose,
keymaster_digest_t** digests,
size_t* digests_length) {
- if (!dev)
- return KM_ERROR_UNEXPECTED_NULL_POINTER;
+ if (!dev) return KM_ERROR_UNEXPECTED_NULL_POINTER;
- if (!digests || !digests_length)
- return KM_ERROR_OUTPUT_PARAMETER_NULL;
+ 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;
+ auto& impl_ = convert_device(dev)->impl_;
+ SupportedDigestsRequest request(impl_->message_version());
request.algorithm = algorithm;
request.purpose = purpose;
- SupportedDigestsResponse response;
- convert_device(dev)->impl_->SupportedDigests(request, &response);
+ SupportedDigestsResponse response(impl_->message_version());
+ impl_->SupportedDigests(request, &response);
if (response.error != KM_ERROR_OK) {
LOG_E("get_supported_digests failed with %d", response.error);
@@ -539,8 +493,7 @@
*digests_length = response.results_length;
*digests = reinterpret_cast<keymaster_digest_t*>(malloc(*digests_length * sizeof(**digests)));
- if (!*digests)
- return KM_ERROR_MEMORY_ALLOCATION_FAILED;
+ if (!*digests) return KM_ERROR_MEMORY_ALLOCATION_FAILED;
std::copy(response.results, response.results + response.results_length, *digests);
return KM_ERROR_OK;
}
@@ -549,20 +502,19 @@
keymaster_error_t SoftKeymasterDevice::get_supported_import_formats(
const keymaster1_device_t* dev, keymaster_algorithm_t algorithm,
keymaster_key_format_t** formats, size_t* formats_length) {
- if (!dev)
- return KM_ERROR_UNEXPECTED_NULL_POINTER;
+ if (!dev) return KM_ERROR_UNEXPECTED_NULL_POINTER;
- if (!formats || !formats_length)
- return KM_ERROR_OUTPUT_PARAMETER_NULL;
+ 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;
+ auto& impl_ = convert_device(dev)->impl_;
+ SupportedImportFormatsRequest request(impl_->message_version());
request.algorithm = algorithm;
- SupportedImportFormatsResponse response;
- convert_device(dev)->impl_->SupportedImportFormats(request, &response);
+ SupportedImportFormatsResponse response(impl_->message_version());
+ impl_->SupportedImportFormats(request, &response);
if (response.error != KM_ERROR_OK) {
LOG_E("get_supported_import_formats failed with %d", response.error);
@@ -572,8 +524,7 @@
*formats_length = response.results_length;
*formats =
reinterpret_cast<keymaster_key_format_t*>(malloc(*formats_length * sizeof(**formats)));
- if (!*formats)
- return KM_ERROR_MEMORY_ALLOCATION_FAILED;
+ if (!*formats) return KM_ERROR_MEMORY_ALLOCATION_FAILED;
std::copy(response.results, response.results + response.results_length, *formats);
return KM_ERROR_OK;
}
@@ -582,20 +533,19 @@
keymaster_error_t SoftKeymasterDevice::get_supported_export_formats(
const keymaster1_device_t* dev, keymaster_algorithm_t algorithm,
keymaster_key_format_t** formats, size_t* formats_length) {
- if (!dev)
- return KM_ERROR_UNEXPECTED_NULL_POINTER;
+ if (!dev) return KM_ERROR_UNEXPECTED_NULL_POINTER;
- if (!formats || !formats_length)
- return KM_ERROR_OUTPUT_PARAMETER_NULL;
+ 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;
+ auto& impl_ = convert_device(dev)->impl_;
+ SupportedExportFormatsRequest request(impl_->message_version());
request.algorithm = algorithm;
- SupportedExportFormatsResponse response;
- convert_device(dev)->impl_->SupportedExportFormats(request, &response);
+ SupportedExportFormatsResponse response(impl_->message_version());
+ impl_->SupportedExportFormats(request, &response);
if (response.error != KM_ERROR_OK) {
LOG_E("get_supported_export_formats failed with %d", response.error);
@@ -605,8 +555,7 @@
*formats_length = response.results_length;
*formats =
reinterpret_cast<keymaster_key_format_t*>(malloc(*formats_length * sizeof(**formats)));
- if (!*formats)
- return KM_ERROR_MEMORY_ALLOCATION_FAILED;
+ if (!*formats) return KM_ERROR_MEMORY_ALLOCATION_FAILED;
std::copy(response.results, response.results + *formats_length, *formats);
return KM_ERROR_OK;
}
@@ -615,46 +564,42 @@
keymaster_error_t SoftKeymasterDevice::configure(const keymaster2_device_t* dev,
const keymaster_key_param_set_t* params) {
AuthorizationSet params_copy(*params);
- ConfigureRequest request;
+ auto& impl_ = convert_device(dev)->impl_;
+ ConfigureRequest request(impl_->message_version());
if (!params_copy.GetTagValue(TAG_OS_VERSION, &request.os_version) ||
!params_copy.GetTagValue(TAG_OS_PATCHLEVEL, &request.os_patchlevel)) {
LOG_E("Configuration parameters must contain OS version and patch level", 0);
return KM_ERROR_INVALID_ARGUMENT;
}
- ConfigureResponse response;
- convert_device(dev)->impl_->Configure(request, &response);
- if (response.error == KM_ERROR_OK)
- convert_device(dev)->configured_ = true;
+ ConfigureResponse response(impl_->message_version());
+ impl_->Configure(request, &response);
+ if (response.error == KM_ERROR_OK) convert_device(dev)->configured_ = true;
return response.error;
}
/* static */
keymaster_error_t SoftKeymasterDevice::add_rng_entropy(const keymaster1_device_t* dev,
const uint8_t* data, size_t data_length) {
- if (!dev)
- return KM_ERROR_UNEXPECTED_NULL_POINTER;
+ 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);
+ if (km1_dev) return km1_dev->add_rng_entropy(km1_dev, data, data_length);
- AddEntropyRequest request;
+ auto& impl_ = convert_device(dev)->impl_;
+ AddEntropyRequest request(impl_->message_version());
request.random_data.Reinitialize(data, data_length);
- AddEntropyResponse response;
- convert_device(dev)->impl_->AddRngEntropy(request, &response);
- if (response.error != KM_ERROR_OK)
- LOG_E("add_rng_entropy failed with %d", response.error);
+ AddEntropyResponse response(impl_->message_version());
+ impl_->AddRngEntropy(request, &response);
+ if (response.error != KM_ERROR_OK) LOG_E("add_rng_entropy failed with %d", response.error);
return response.error;
}
/* static */
keymaster_error_t SoftKeymasterDevice::add_rng_entropy(const keymaster2_device_t* dev,
const uint8_t* data, size_t data_length) {
- if (!dev)
- return KM_ERROR_UNEXPECTED_NULL_POINTER;
+ if (!dev) return KM_ERROR_UNEXPECTED_NULL_POINTER;
- if (!convert_device(dev)->configured())
- return KM_ERROR_KEYMASTER_NOT_CONFIGURED;
+ if (!convert_device(dev)->configured()) return KM_ERROR_KEYMASTER_NOT_CONFIGURED;
SoftKeymasterDevice* sk_dev = convert_device(dev);
return add_rng_entropy(&sk_dev->km1_device_, data, data_length);
@@ -690,8 +635,7 @@
keymaster_purpose_t purpose,
const AuthorizationSet& params) const {
assert(wrapped_km1_device_);
- if (!wrapped_km1_device_)
- return true;
+ if (!wrapped_km1_device_) return true;
switch (algorithm) {
case KM_ALGORITHM_AES:
@@ -716,8 +660,7 @@
bool SoftKeymasterDevice::KeyRequiresSoftwareDigesting(
const AuthorizationSet& key_description) const {
assert(wrapped_km1_device_);
- if (!wrapped_km1_device_)
- return true;
+ if (!wrapped_km1_device_) return true;
keymaster_algorithm_t algorithm;
if (!key_description.GetTagValue(TAG_ALGORITHM, &algorithm)) {
@@ -728,8 +671,7 @@
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;
+ if (RequiresSoftwareDigesting(algorithm, purpose, key_description)) return true;
}
return false;
@@ -739,30 +681,27 @@
keymaster_error_t SoftKeymasterDevice::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) {
- if (!dev || !params)
- return KM_ERROR_UNEXPECTED_NULL_POINTER;
+ if (!dev || !params) return KM_ERROR_UNEXPECTED_NULL_POINTER;
- if (!key_blob)
- return KM_ERROR_OUTPUT_PARAMETER_NULL;
+ if (!key_blob) return KM_ERROR_OUTPUT_PARAMETER_NULL;
SoftKeymasterDevice* sk_dev = convert_device(dev);
- GenerateKeyRequest request;
+ auto& impl_ = sk_dev->impl_;
+ GenerateKeyRequest request(impl_->message_version());
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;
- sk_dev->impl_->GenerateKey(request, &response);
- if (response.error != KM_ERROR_OK)
- return response.error;
+ GenerateKeyResponse response(impl_->message_version());
+ impl_->GenerateKey(request, &response);
+ if (response.error != KM_ERROR_OK) return response.error;
key_blob->key_material_size = response.key_blob.key_material_size;
uint8_t* tmp = reinterpret_cast<uint8_t*>(malloc(key_blob->key_material_size));
- if (!tmp)
- return KM_ERROR_MEMORY_ALLOCATION_FAILED;
+ if (!tmp) return KM_ERROR_MEMORY_ALLOCATION_FAILED;
memcpy(tmp, response.key_blob.key_material, response.key_blob.key_material_size);
key_blob->key_material = tmp;
@@ -774,8 +713,7 @@
response.unenforced.erase(response.unenforced.find(TAG_OS_PATCHLEVEL));
*characteristics = BuildCharacteristics(response.enforced, response.unenforced);
- if (!*characteristics)
- return KM_ERROR_MEMORY_ALLOCATION_FAILED;
+ if (!*characteristics) return KM_ERROR_MEMORY_ALLOCATION_FAILED;
}
return KM_ERROR_OK;
@@ -786,18 +724,16 @@
const keymaster_key_param_set_t* params,
keymaster_key_blob_t* key_blob,
keymaster_key_characteristics_t* characteristics) {
- if (!dev)
- return KM_ERROR_UNEXPECTED_NULL_POINTER;
+ if (!dev) return KM_ERROR_UNEXPECTED_NULL_POINTER;
- if (!convert_device(dev)->configured())
- return KM_ERROR_KEYMASTER_NOT_CONFIGURED;
+ if (!convert_device(dev)->configured()) return KM_ERROR_KEYMASTER_NOT_CONFIGURED;
- if (!key_blob)
- return KM_ERROR_OUTPUT_PARAMETER_NULL;
+ if (!key_blob) return KM_ERROR_OUTPUT_PARAMETER_NULL;
SoftKeymasterDevice* sk_dev = convert_device(dev);
- GenerateKeyRequest request;
+ auto& impl_ = sk_dev->impl_;
+ GenerateKeyRequest request(impl_->message_version());
request.key_description.Reinitialize(*params);
keymaster1_device_t* km1_dev = sk_dev->wrapped_km1_device_;
@@ -825,8 +761,7 @@
keymaster_key_characteristics_t* chars_ptr;
keymaster_error_t error = km1_dev->generate_key(km1_dev, &request.key_description, key_blob,
characteristics ? &chars_ptr : nullptr);
- if (error != KM_ERROR_OK)
- return error;
+ if (error != KM_ERROR_OK) return error;
if (characteristics) {
*characteristics = *chars_ptr;
@@ -836,15 +771,13 @@
return KM_ERROR_OK;
}
- GenerateKeyResponse response;
- sk_dev->impl_->GenerateKey(request, &response);
- if (response.error != KM_ERROR_OK)
- return response.error;
+ GenerateKeyResponse response(impl_->message_version());
+ impl_->GenerateKey(request, &response);
+ if (response.error != KM_ERROR_OK) return response.error;
key_blob->key_material_size = response.key_blob.key_material_size;
uint8_t* tmp = reinterpret_cast<uint8_t*>(malloc(key_blob->key_material_size));
- if (!tmp)
- return KM_ERROR_MEMORY_ALLOCATION_FAILED;
+ if (!tmp) return KM_ERROR_MEMORY_ALLOCATION_FAILED;
memcpy(tmp, response.key_blob.key_material, response.key_blob.key_material_size);
key_blob->key_material = tmp;
@@ -861,11 +794,9 @@
const keymaster1_device_t* 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) {
- if (!dev || !key_blob || !key_blob->key_material)
- return KM_ERROR_UNEXPECTED_NULL_POINTER;
+ if (!dev || !key_blob || !key_blob->key_material) return KM_ERROR_UNEXPECTED_NULL_POINTER;
- if (!characteristics)
- return KM_ERROR_OUTPUT_PARAMETER_NULL;
+ if (!characteristics) return KM_ERROR_OUTPUT_PARAMETER_NULL;
const keymaster1_device_t* km1_dev = convert_device(dev)->wrapped_km1_device_;
if (km1_dev) {
@@ -878,14 +809,14 @@
// software key blob.
}
- GetKeyCharacteristicsRequest request;
+ auto& impl_ = convert_device(dev)->impl_;
+ GetKeyCharacteristicsRequest request(impl_->message_version());
request.SetKeyMaterial(*key_blob);
AddClientAndAppData(client_id, app_data, &request);
- GetKeyCharacteristicsResponse response;
- convert_device(dev)->impl_->GetKeyCharacteristics(request, &response);
- if (response.error != KM_ERROR_OK)
- return response.error;
+ GetKeyCharacteristicsResponse response(impl_->message_version());
+ impl_->GetKeyCharacteristics(request, &response);
+ if (response.error != KM_ERROR_OK) return response.error;
// This is a keymaster1 method, and keymaster1 doesn't include version info, so remove it.
response.enforced.erase(response.enforced.find(TAG_OS_VERSION));
@@ -894,8 +825,7 @@
response.unenforced.erase(response.unenforced.find(TAG_OS_PATCHLEVEL));
*characteristics = BuildCharacteristics(response.enforced, response.unenforced);
- if (!*characteristics)
- return KM_ERROR_MEMORY_ALLOCATION_FAILED;
+ if (!*characteristics) return KM_ERROR_MEMORY_ALLOCATION_FAILED;
return KM_ERROR_OK;
}
@@ -905,25 +835,22 @@
const keymaster2_device_t* 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) {
- if (!dev)
- return KM_ERROR_UNEXPECTED_NULL_POINTER;
+ if (!dev) return KM_ERROR_UNEXPECTED_NULL_POINTER;
- if (!convert_device(dev)->configured())
- return KM_ERROR_KEYMASTER_NOT_CONFIGURED;
+ if (!convert_device(dev)->configured()) return KM_ERROR_KEYMASTER_NOT_CONFIGURED;
- if (!characteristics)
- return KM_ERROR_OUTPUT_PARAMETER_NULL;
+ if (!characteristics) return KM_ERROR_OUTPUT_PARAMETER_NULL;
SoftKeymasterDevice* sk_dev = convert_device(dev);
- GetKeyCharacteristicsRequest request;
+ auto& impl_ = sk_dev->impl_;
+ GetKeyCharacteristicsRequest request(impl_->message_version());
request.SetKeyMaterial(*key_blob);
AddClientAndAppData(client_id, app_data, &request);
- GetKeyCharacteristicsResponse response;
- sk_dev->impl_->GetKeyCharacteristics(request, &response);
- if (response.error != KM_ERROR_OK)
- return response.error;
+ GetKeyCharacteristicsResponse response(impl_->message_version());
+ impl_->GetKeyCharacteristics(request, &response);
+ if (response.error != KM_ERROR_OK) return response.error;
response.enforced.CopyToParamSet(&characteristics->hw_enforced);
response.unenforced.CopyToParamSet(&characteristics->sw_enforced);
@@ -936,15 +863,14 @@
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) {
- if (!params || !key_data)
- return KM_ERROR_UNEXPECTED_NULL_POINTER;
+ if (!params || !key_data) return KM_ERROR_UNEXPECTED_NULL_POINTER;
- if (!key_blob)
- return KM_ERROR_OUTPUT_PARAMETER_NULL;
+ if (!key_blob) return KM_ERROR_OUTPUT_PARAMETER_NULL;
SoftKeymasterDevice* sk_dev = convert_device(dev);
- ImportKeyRequest request;
+ auto& impl_ = sk_dev->impl_;
+ ImportKeyRequest request(impl_->message_version());
request.key_description.Reinitialize(*params);
keymaster1_device_t* km1_dev = sk_dev->wrapped_km1_device_;
@@ -952,28 +878,24 @@
return km1_dev->import_key(km1_dev, params, key_format, key_data, key_blob,
characteristics);
- if (characteristics)
- *characteristics = nullptr;
+ if (characteristics) *characteristics = nullptr;
request.key_format = key_format;
- request.SetKeyMaterial(key_data->data, key_data->data_length);
+ request.key_data = KeymasterKeyBlob(key_data->data, key_data->data_length);
- ImportKeyResponse response;
- convert_device(dev)->impl_->ImportKey(request, &response);
- if (response.error != KM_ERROR_OK)
- return response.error;
+ ImportKeyResponse response(impl_->message_version());
+ impl_->ImportKey(request, &response);
+ if (response.error != KM_ERROR_OK) return response.error;
key_blob->key_material_size = response.key_blob.key_material_size;
key_blob->key_material = reinterpret_cast<uint8_t*>(malloc(key_blob->key_material_size));
- if (!key_blob->key_material)
- return KM_ERROR_MEMORY_ALLOCATION_FAILED;
+ if (!key_blob->key_material) return KM_ERROR_MEMORY_ALLOCATION_FAILED;
memcpy(const_cast<uint8_t*>(key_blob->key_material), response.key_blob.key_material,
response.key_blob.key_material_size);
if (characteristics) {
*characteristics = BuildCharacteristics(response.enforced, response.unenforced);
- if (!*characteristics)
- return KM_ERROR_MEMORY_ALLOCATION_FAILED;
+ if (!*characteristics) return KM_ERROR_MEMORY_ALLOCATION_FAILED;
}
return KM_ERROR_OK;
}
@@ -983,11 +905,9 @@
const keymaster2_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) {
- if (!dev)
- return KM_ERROR_UNEXPECTED_NULL_POINTER;
+ if (!dev) return KM_ERROR_UNEXPECTED_NULL_POINTER;
- if (!convert_device(dev)->configured())
- return KM_ERROR_KEYMASTER_NOT_CONFIGURED;
+ if (!convert_device(dev)->configured()) return KM_ERROR_KEYMASTER_NOT_CONFIGURED;
SoftKeymasterDevice* sk_dev = convert_device(dev);
@@ -1014,11 +934,9 @@
const keymaster_blob_t* client_id,
const keymaster_blob_t* app_data,
keymaster_blob_t* export_data) {
- if (!key_to_export || !key_to_export->key_material)
- return KM_ERROR_UNEXPECTED_NULL_POINTER;
+ if (!key_to_export || !key_to_export->key_material) return KM_ERROR_UNEXPECTED_NULL_POINTER;
- if (!export_data)
- return KM_ERROR_OUTPUT_PARAMETER_NULL;
+ if (!export_data) return KM_ERROR_OUTPUT_PARAMETER_NULL;
const keymaster1_device_t* km1_dev = convert_device(dev)->wrapped_km1_device_;
if (km1_dev)
@@ -1028,20 +946,19 @@
export_data->data = nullptr;
export_data->data_length = 0;
- ExportKeyRequest request;
+ auto& impl_ = convert_device(dev)->impl_;
+ ExportKeyRequest request(impl_->message_version());
request.key_format = export_format;
request.SetKeyMaterial(*key_to_export);
AddClientAndAppData(client_id, app_data, &request);
- ExportKeyResponse response;
- convert_device(dev)->impl_->ExportKey(request, &response);
- if (response.error != KM_ERROR_OK)
- return response.error;
+ ExportKeyResponse response(impl_->message_version());
+ impl_->ExportKey(request, &response);
+ if (response.error != KM_ERROR_OK) return response.error;
export_data->data_length = response.key_data_length;
uint8_t* tmp = reinterpret_cast<uint8_t*>(malloc(export_data->data_length));
- if (!tmp)
- return KM_ERROR_MEMORY_ALLOCATION_FAILED;
+ if (!tmp) return KM_ERROR_MEMORY_ALLOCATION_FAILED;
memcpy(tmp, response.key_data, export_data->data_length);
export_data->data = tmp;
return KM_ERROR_OK;
@@ -1054,11 +971,9 @@
const keymaster_blob_t* client_id,
const keymaster_blob_t* app_data,
keymaster_blob_t* export_data) {
- if (!dev)
- return KM_ERROR_UNEXPECTED_NULL_POINTER;
+ if (!dev) return KM_ERROR_UNEXPECTED_NULL_POINTER;
- if (!convert_device(dev)->configured())
- return KM_ERROR_KEYMASTER_NOT_CONFIGURED;
+ if (!convert_device(dev)->configured()) return KM_ERROR_KEYMASTER_NOT_CONFIGURED;
SoftKeymasterDevice* sk_dev = convert_device(dev);
return export_key(&sk_dev->km1_device_, export_format, key_to_export, client_id, app_data,
@@ -1073,12 +988,12 @@
if (!dev || !key_to_attest || !attest_params || !cert_chain)
return KM_ERROR_UNEXPECTED_NULL_POINTER;
- if (!convert_device(dev)->configured())
- return KM_ERROR_KEYMASTER_NOT_CONFIGURED;
+ if (!convert_device(dev)->configured()) return KM_ERROR_KEYMASTER_NOT_CONFIGURED;
*cert_chain = {};
- AttestKeyRequest request;
+ auto& impl_ = convert_device(dev)->impl_;
+ AttestKeyRequest request(impl_->message_version());
request.SetKeyMaterial(*key_to_attest);
request.attest_params.Reinitialize(*attest_params);
@@ -1090,17 +1005,15 @@
return KM_ERROR_INVALID_INPUT_LENGTH;
}
- AttestKeyResponse response;
- convert_device(dev)->impl_->AttestKey(request, &response);
- if (response.error != KM_ERROR_OK)
- return response.error;
+ AttestKeyResponse response(impl_->message_version());
+ impl_->AttestKey(request, &response);
+ if (response.error != KM_ERROR_OK) return response.error;
// Allocate and clear storage for cert_chain.
keymaster_cert_chain_t& rsp_chain = response.certificate_chain;
cert_chain->entries = reinterpret_cast<keymaster_blob_t*>(
malloc(rsp_chain.entry_count * sizeof(*cert_chain->entries)));
- if (!cert_chain->entries)
- return KM_ERROR_MEMORY_ALLOCATION_FAILED;
+ if (!cert_chain->entries) return KM_ERROR_MEMORY_ALLOCATION_FAILED;
cert_chain->entry_count = rsp_chain.entry_count;
for (keymaster_blob_t& entry : array_range(cert_chain->entries, cert_chain->entry_count))
entry = {};
@@ -1126,28 +1039,24 @@
const keymaster_key_blob_t* key_to_upgrade,
const keymaster_key_param_set_t* upgrade_params,
keymaster_key_blob_t* upgraded_key) {
- if (!dev || !key_to_upgrade || !upgrade_params)
- return KM_ERROR_UNEXPECTED_NULL_POINTER;
+ if (!dev || !key_to_upgrade || !upgrade_params) return KM_ERROR_UNEXPECTED_NULL_POINTER;
- if (!upgraded_key)
- return KM_ERROR_OUTPUT_PARAMETER_NULL;
+ if (!upgraded_key) return KM_ERROR_OUTPUT_PARAMETER_NULL;
- if (!convert_device(dev)->configured())
- return KM_ERROR_KEYMASTER_NOT_CONFIGURED;
+ if (!convert_device(dev)->configured()) return KM_ERROR_KEYMASTER_NOT_CONFIGURED;
- UpgradeKeyRequest request;
+ auto& impl_ = convert_device(dev)->impl_;
+ UpgradeKeyRequest request(impl_->message_version());
request.SetKeyMaterial(*key_to_upgrade);
request.upgrade_params.Reinitialize(*upgrade_params);
- UpgradeKeyResponse response;
- convert_device(dev)->impl_->UpgradeKey(request, &response);
- if (response.error != KM_ERROR_OK)
- return response.error;
+ UpgradeKeyResponse response(impl_->message_version());
+ impl_->UpgradeKey(request, &response);
+ if (response.error != KM_ERROR_OK) return response.error;
upgraded_key->key_material_size = response.upgraded_key.key_material_size;
uint8_t* tmp = reinterpret_cast<uint8_t*>(malloc(upgraded_key->key_material_size));
- if (!tmp)
- return KM_ERROR_MEMORY_ALLOCATION_FAILED;
+ if (!tmp) return KM_ERROR_MEMORY_ALLOCATION_FAILED;
memcpy(tmp, response.upgraded_key.key_material, response.upgraded_key.key_material_size);
upgraded_key->key_material = tmp;
@@ -1157,8 +1066,7 @@
/* static */
keymaster_error_t SoftKeymasterDevice::delete_key(const keymaster1_device_t* dev,
const keymaster_key_blob_t* key) {
- if (!dev || !key || !key->key_material)
- return KM_ERROR_UNEXPECTED_NULL_POINTER;
+ if (!dev || !key || !key->key_material) return KM_ERROR_UNEXPECTED_NULL_POINTER;
KeymasterKeyBlob blob(*key);
return convert_device(dev)->context_->DeleteKey(blob);
@@ -1167,11 +1075,9 @@
/* static */
keymaster_error_t SoftKeymasterDevice::delete_key(const keymaster2_device_t* dev,
const keymaster_key_blob_t* key) {
- if (!dev || !key || !key->key_material)
- return KM_ERROR_UNEXPECTED_NULL_POINTER;
+ if (!dev || !key || !key->key_material) return KM_ERROR_UNEXPECTED_NULL_POINTER;
- if (!convert_device(dev)->configured())
- return KM_ERROR_KEYMASTER_NOT_CONFIGURED;
+ if (!convert_device(dev)->configured()) return KM_ERROR_KEYMASTER_NOT_CONFIGURED;
KeymasterKeyBlob blob(*key);
return convert_device(dev)->context_->DeleteKey(blob);
@@ -1179,19 +1085,16 @@
/* static */
keymaster_error_t SoftKeymasterDevice::delete_all_keys(const keymaster1_device_t* dev) {
- if (!dev)
- return KM_ERROR_UNEXPECTED_NULL_POINTER;
+ if (!dev) return KM_ERROR_UNEXPECTED_NULL_POINTER;
return convert_device(dev)->context_->DeleteAllKeys();
}
/* static */
keymaster_error_t SoftKeymasterDevice::delete_all_keys(const keymaster2_device_t* dev) {
- if (!dev)
- return KM_ERROR_UNEXPECTED_NULL_POINTER;
+ if (!dev) return KM_ERROR_UNEXPECTED_NULL_POINTER;
- if (!convert_device(dev)->configured())
- return KM_ERROR_KEYMASTER_NOT_CONFIGURED;
+ if (!convert_device(dev)->configured()) return KM_ERROR_KEYMASTER_NOT_CONFIGURED;
return convert_device(dev)->context_->DeleteAllKeys();
}
@@ -1203,11 +1106,9 @@
const keymaster_key_param_set_t* in_params,
keymaster_key_param_set_t* out_params,
keymaster_operation_handle_t* operation_handle) {
- if (!dev || !key || !key->key_material)
- return KM_ERROR_UNEXPECTED_NULL_POINTER;
+ if (!dev || !key || !key->key_material) return KM_ERROR_UNEXPECTED_NULL_POINTER;
- if (!operation_handle)
- return KM_ERROR_OUTPUT_PARAMETER_NULL;
+ if (!operation_handle) return KM_ERROR_OUTPUT_PARAMETER_NULL;
SoftKeymasterDevice* skdev = convert_device(dev);
const keymaster1_device_t* km1_dev = skdev->wrapped_km1_device_;
@@ -1215,7 +1116,7 @@
if (km1_dev) {
AuthorizationSet in_params_set(*in_params);
- UniquePtr<Key> akmKey; // android keymaster key
+ UniquePtr<Key> akmKey; // android keymaster key
skdev->context_->ParseKeyBlob(KeymasterKeyBlob(*key), in_params_set, &akmKey);
keymaster_algorithm_t algorithm = KM_ALGORITHM_AES;
@@ -1248,15 +1149,15 @@
out_params->length = 0;
}
- BeginOperationRequest request;
+ auto& impl_ = skdev->impl_;
+ BeginOperationRequest request(impl_->message_version());
request.purpose = purpose;
request.SetKeyMaterial(*key);
request.additional_params.Reinitialize(*in_params);
- BeginOperationResponse response;
- skdev->impl_->BeginOperation(request, &response);
- if (response.error != KM_ERROR_OK)
- return response.error;
+ BeginOperationResponse response(impl_->message_version());
+ impl_->BeginOperation(request, &response);
+ if (response.error != KM_ERROR_OK) return response.error;
if (response.output_params.size() > 0) {
if (out_params)
@@ -1276,11 +1177,9 @@
const keymaster_key_param_set_t* in_params,
keymaster_key_param_set_t* out_params,
keymaster_operation_handle_t* operation_handle) {
- if (!dev)
- return KM_ERROR_UNEXPECTED_NULL_POINTER;
+ if (!dev) return KM_ERROR_UNEXPECTED_NULL_POINTER;
- if (!convert_device(dev)->configured())
- return KM_ERROR_KEYMASTER_NOT_CONFIGURED;
+ if (!convert_device(dev)->configured()) return KM_ERROR_KEYMASTER_NOT_CONFIGURED;
SoftKeymasterDevice* sk_dev = convert_device(dev);
return begin(&sk_dev->km1_device_, purpose, key, in_params, out_params, operation_handle);
@@ -1293,11 +1192,9 @@
const keymaster_blob_t* input, size_t* input_consumed,
keymaster_key_param_set_t* out_params,
keymaster_blob_t* output) {
- if (!input)
- return KM_ERROR_UNEXPECTED_NULL_POINTER;
+ if (!input) return KM_ERROR_UNEXPECTED_NULL_POINTER;
- if (!input_consumed)
- return KM_ERROR_OUTPUT_PARAMETER_NULL;
+ if (!input_consumed) 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)) {
@@ -1317,17 +1214,15 @@
output->data_length = 0;
}
- UpdateOperationRequest request;
+ auto& impl_ = convert_device(dev)->impl_;
+ UpdateOperationRequest request(impl_->message_version());
request.op_handle = operation_handle;
- if (input)
- request.input.Reinitialize(input->data, input->data_length);
- if (in_params)
- request.additional_params.Reinitialize(*in_params);
+ if (input) request.input.Reinitialize(input->data, input->data_length);
+ if (in_params) request.additional_params.Reinitialize(*in_params);
- UpdateOperationResponse response;
- convert_device(dev)->impl_->UpdateOperation(request, &response);
- if (response.error != KM_ERROR_OK)
- return response.error;
+ UpdateOperationResponse response(impl_->message_version());
+ impl_->UpdateOperation(request, &response);
+ if (response.error != KM_ERROR_OK) return response.error;
if (response.output_params.size() > 0) {
if (out_params)
@@ -1340,8 +1235,7 @@
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;
+ 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) {
@@ -1357,11 +1251,9 @@
const keymaster_blob_t* input, size_t* input_consumed,
keymaster_key_param_set_t* out_params,
keymaster_blob_t* output) {
- if (!dev)
- return KM_ERROR_UNEXPECTED_NULL_POINTER;
+ if (!dev) return KM_ERROR_UNEXPECTED_NULL_POINTER;
- if (!convert_device(dev)->configured())
- return KM_ERROR_KEYMASTER_NOT_CONFIGURED;
+ if (!convert_device(dev)->configured()) return KM_ERROR_KEYMASTER_NOT_CONFIGURED;
SoftKeymasterDevice* sk_dev = convert_device(dev);
return update(&sk_dev->km1_device_, operation_handle, in_params, input, input_consumed,
@@ -1375,8 +1267,7 @@
const keymaster_blob_t* signature,
keymaster_key_param_set_t* out_params,
keymaster_blob_t* output) {
- if (!dev)
- return KM_ERROR_UNEXPECTED_NULL_POINTER;
+ if (!dev) return KM_ERROR_UNEXPECTED_NULL_POINTER;
const keymaster1_device_t* km1_dev = convert_device(dev)->wrapped_km1_device_;
if (km1_dev && !convert_device(dev)->impl_->has_operation(operation_handle)) {
@@ -1396,16 +1287,16 @@
output->data_length = 0;
}
- FinishOperationRequest request;
+ auto& impl_ = convert_device(dev)->impl_;
+ FinishOperationRequest request(impl_->message_version());
request.op_handle = operation_handle;
if (signature && signature->data_length > 0)
request.signature.Reinitialize(signature->data, signature->data_length);
request.additional_params.Reinitialize(*params);
- FinishOperationResponse response;
- convert_device(dev)->impl_->FinishOperation(request, &response);
- if (response.error != KM_ERROR_OK)
- return response.error;
+ FinishOperationResponse response(impl_->message_version());
+ impl_->FinishOperation(request, &response);
+ if (response.error != KM_ERROR_OK) return response.error;
if (response.output_params.size() > 0) {
if (out_params)
@@ -1416,8 +1307,7 @@
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;
+ 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) {
@@ -1439,17 +1329,13 @@
const keymaster_blob_t* signature,
keymaster_key_param_set_t* out_params,
keymaster_blob_t* output) {
- if (!dev)
- return KM_ERROR_UNEXPECTED_NULL_POINTER;
+ if (!dev) return KM_ERROR_UNEXPECTED_NULL_POINTER;
- if (!convert_device(dev)->configured())
- return KM_ERROR_KEYMASTER_NOT_CONFIGURED;
+ if (!convert_device(dev)->configured()) return KM_ERROR_KEYMASTER_NOT_CONFIGURED;
- if (out_params)
- *out_params = {};
+ if (out_params) *out_params = {};
- if (output)
- *output = {};
+ if (output) *output = {};
const keymaster1_device_t* km1_dev = convert_device(dev)->wrapped_km1_device_;
if (km1_dev && !convert_device(dev)->impl_->has_operation(operation_handle)) {
@@ -1538,21 +1424,17 @@
return KM_ERROR_OUTPUT_PARAMETER_NULL;
}
- if (out_params) {
- *out_params = finish_out_params;
- }
+ *out_params = finish_out_params;
+ *output = finish_output;
- if (output) {
- *output = finish_output;
- }
-
- finish_out_params_deleter.release();
- finish_output_deleter.release();
+ finish_out_params_deleter.release(); // NOLINT(bugprone-unused-return-value)
+ finish_output_deleter.release(); // NOLINT(bugprone-unused-return-value)
return KM_ERROR_OK;
}
- FinishOperationRequest request;
+ auto& impl_ = convert_device(dev)->impl_;
+ FinishOperationRequest request(impl_->message_version());
request.op_handle = operation_handle;
if (signature && signature->data_length > 0)
request.signature.Reinitialize(signature->data, signature->data_length);
@@ -1560,10 +1442,9 @@
request.input.Reinitialize(input->data, input->data_length);
request.additional_params.Reinitialize(*params);
- FinishOperationResponse response;
- convert_device(dev)->impl_->FinishOperation(request, &response);
- if (response.error != KM_ERROR_OK)
- return response.error;
+ FinishOperationResponse response(impl_->message_version());
+ impl_->FinishOperation(request, &response);
+ if (response.error != KM_ERROR_OK) return response.error;
if (response.output_params.size() > 0) {
if (out_params)
@@ -1574,8 +1455,7 @@
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;
+ 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) {
@@ -1596,21 +1476,20 @@
return km1_dev->abort(km1_dev, operation_handle);
}
- AbortOperationRequest request;
+ auto& impl_ = convert_device(dev)->impl_;
+ AbortOperationRequest request(impl_->message_version());
request.op_handle = operation_handle;
- AbortOperationResponse response;
- convert_device(dev)->impl_->AbortOperation(request, &response);
+ AbortOperationResponse response(impl_->message_version());
+ impl_->AbortOperation(request, &response);
return response.error;
}
/* static */
keymaster_error_t SoftKeymasterDevice::abort(const keymaster2_device_t* dev,
keymaster_operation_handle_t operation_handle) {
- if (!dev)
- return KM_ERROR_UNEXPECTED_NULL_POINTER;
+ if (!dev) return KM_ERROR_UNEXPECTED_NULL_POINTER;
- if (!convert_device(dev)->configured())
- return KM_ERROR_KEYMASTER_NOT_CONFIGURED;
+ if (!convert_device(dev)->configured()) return KM_ERROR_KEYMASTER_NOT_CONFIGURED;
SoftKeymasterDevice* sk_dev = convert_device(dev);
return abort(&sk_dev->km1_device_, operation_handle);
diff --git a/cppcose/cppcose.cpp b/cppcose/cppcose.cpp
new file mode 100644
index 0000000..bfe9928
--- /dev/null
+++ b/cppcose/cppcose.cpp
@@ -0,0 +1,463 @@
+/*
+ * Copyright (C) 2020 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 <keymaster/cppcose/cppcose.h>
+
+#include <iostream>
+#include <stdio.h>
+
+#include <cppbor.h>
+#include <cppbor_parse.h>
+
+#include <openssl/err.h>
+
+namespace cppcose {
+
+namespace {
+
+ErrMsgOr<bssl::UniquePtr<EVP_CIPHER_CTX>> aesGcmInitAndProcessAad(const bytevec& key,
+ const bytevec& nonce,
+ const bytevec& aad,
+ bool encrypt) {
+ if (key.size() != kAesGcmKeySize) return "Invalid key size";
+
+ bssl::UniquePtr<EVP_CIPHER_CTX> ctx(EVP_CIPHER_CTX_new());
+ if (!ctx) return "Failed to allocate cipher context";
+
+ if (!EVP_CipherInit_ex(ctx.get(), EVP_aes_256_gcm(), nullptr /* engine */, key.data(),
+ nonce.data(), encrypt ? 1 : 0)) {
+ return "Failed to initialize cipher";
+ }
+
+ int outlen;
+ if (!aad.empty() && !EVP_CipherUpdate(ctx.get(), nullptr /* out; null means AAD */, &outlen,
+ aad.data(), aad.size())) {
+ return "Failed to process AAD";
+ }
+
+ return std::move(ctx);
+}
+
+} // namespace
+
+ErrMsgOr<HmacSha256> generateHmacSha256(const bytevec& key, const bytevec& data) {
+ HmacSha256 digest;
+ unsigned int outLen;
+ uint8_t* out = HMAC(EVP_sha256(), //
+ key.data(), key.size(), //
+ data.data(), data.size(), //
+ digest.data(), &outLen);
+
+ if (out == nullptr || outLen != digest.size()) {
+ return "Error generating HMAC";
+ }
+ return digest;
+}
+
+ErrMsgOr<HmacSha256> generateCoseMac0Mac(HmacSha256Function macFunction, const bytevec& externalAad,
+ const bytevec& payload) {
+ auto macStructure = cppbor::Array()
+ .add("MAC0")
+ .add(cppbor::Map().add(ALGORITHM, HMAC_256).canonicalize().encode())
+ .add(externalAad)
+ .add(payload)
+ .encode();
+
+ auto macTag = macFunction(macStructure);
+ if (!macTag) {
+ return "Error computing public key MAC";
+ }
+
+ return *macTag;
+}
+
+ErrMsgOr<cppbor::Array> constructCoseMac0(HmacSha256Function macFunction,
+ const bytevec& externalAad, const bytevec& payload) {
+ auto tag = generateCoseMac0Mac(macFunction, externalAad, payload);
+ if (!tag) return tag.moveMessage();
+
+ return cppbor::Array()
+ .add(cppbor::Map().add(ALGORITHM, HMAC_256).canonicalize().encode())
+ .add(cppbor::Map() /* unprotected */)
+ .add(payload)
+ .add(std::pair(tag->begin(), tag->end()));
+}
+
+ErrMsgOr<bytevec /* payload */> verifyAndParseCoseMac0(const cppbor::Item* macItem,
+ const bytevec& macKey) {
+ auto mac = macItem ? macItem->asArray() : nullptr;
+ if (!mac || mac->size() != kCoseMac0EntryCount) {
+ return "Invalid COSE_Mac0";
+ }
+
+ auto protectedParms = mac->get(kCoseMac0ProtectedParams)->asBstr();
+ auto unprotectedParms = mac->get(kCoseMac0UnprotectedParams)->asMap();
+ auto payload = mac->get(kCoseMac0Payload)->asBstr();
+ auto tag = mac->get(kCoseMac0Tag)->asBstr();
+ if (!protectedParms || !unprotectedParms || !payload || !tag) {
+ return "Invalid COSE_Mac0 contents";
+ }
+
+ auto [protectedMap, _, errMsg] = cppbor::parse(protectedParms);
+ if (!protectedMap || !protectedMap->asMap()) {
+ return "Invalid Mac0 protected: " + errMsg;
+ }
+ auto& algo = protectedMap->asMap()->get(ALGORITHM);
+ if (!algo || !algo->asInt() || algo->asInt()->value() != HMAC_256) {
+ return "Unsupported Mac0 algorithm";
+ }
+
+ auto macFunction = [&macKey](const bytevec& input) {
+ return generateHmacSha256(macKey, input);
+ };
+ auto macTag = generateCoseMac0Mac(macFunction, {} /* external_aad */, payload->value());
+ if (!macTag) return macTag.moveMessage();
+
+ if (macTag->size() != tag->value().size() ||
+ CRYPTO_memcmp(macTag->data(), tag->value().data(), macTag->size()) != 0) {
+ return "MAC tag mismatch";
+ }
+
+ return payload->value();
+}
+
+ErrMsgOr<bytevec> createCoseSign1Signature(const bytevec& key, const bytevec& protectedParams,
+ const bytevec& payload, const bytevec& aad) {
+ bytevec signatureInput = cppbor::Array()
+ .add("Signature1") //
+ .add(protectedParams)
+ .add(aad)
+ .add(payload)
+ .encode();
+
+ if (key.size() != ED25519_PRIVATE_KEY_LEN) return "Invalid signing key";
+ bytevec signature(ED25519_SIGNATURE_LEN);
+ if (!ED25519_sign(signature.data(), signatureInput.data(), signatureInput.size(), key.data())) {
+ return "Signing failed";
+ }
+
+ return signature;
+}
+
+ErrMsgOr<cppbor::Array> constructCoseSign1(const bytevec& key, cppbor::Map protectedParams,
+ const bytevec& payload, const bytevec& aad) {
+ bytevec protParms = protectedParams.add(ALGORITHM, EDDSA).canonicalize().encode();
+ auto signature = createCoseSign1Signature(key, protParms, payload, aad);
+ if (!signature) return signature.moveMessage();
+
+ return cppbor::Array()
+ .add(std::move(protParms))
+ .add(cppbor::Map() /* unprotected parameters */)
+ .add(std::move(payload))
+ .add(std::move(*signature));
+}
+
+ErrMsgOr<cppbor::Array> constructCoseSign1(const bytevec& key, const bytevec& payload,
+ const bytevec& aad) {
+ return constructCoseSign1(key, {} /* protectedParams */, payload, aad);
+}
+
+ErrMsgOr<bytevec> verifyAndParseCoseSign1(const cppbor::Array* coseSign1,
+ const bytevec& signingCoseKey, const bytevec& aad) {
+ if (!coseSign1 || coseSign1->size() != kCoseSign1EntryCount) {
+ return "Invalid COSE_Sign1";
+ }
+
+ const cppbor::Bstr* protectedParams = coseSign1->get(kCoseSign1ProtectedParams)->asBstr();
+ const cppbor::Map* unprotectedParams = coseSign1->get(kCoseSign1UnprotectedParams)->asMap();
+ const cppbor::Bstr* payload = coseSign1->get(kCoseSign1Payload)->asBstr();
+
+ if (!protectedParams || !unprotectedParams || !payload) {
+ return "Missing input parameters";
+ }
+
+ auto [parsedProtParams, _, errMsg] = cppbor::parse(protectedParams);
+ if (!parsedProtParams) {
+ return errMsg + " when parsing protected params.";
+ }
+ if (!parsedProtParams->asMap()) {
+ return "Protected params must be a map";
+ }
+
+ auto& algorithm = parsedProtParams->asMap()->get(ALGORITHM);
+ if (!algorithm || !algorithm->asInt() || algorithm->asInt()->value() != EDDSA) {
+ return "Unsupported signature algorithm";
+ }
+
+ const cppbor::Bstr* signature = coseSign1->get(kCoseSign1Signature)->asBstr();
+ if (!signature || signature->value().empty()) {
+ return "Missing signature input";
+ }
+
+ bool selfSigned = signingCoseKey.empty();
+ auto key = CoseKey::parseEd25519(selfSigned ? payload->value() : signingCoseKey);
+ if (!key || key->getBstrValue(CoseKey::PUBKEY_X)->empty()) {
+ return "Bad signing key: " + key.moveMessage();
+ }
+
+ bytevec signatureInput =
+ cppbor::Array().add("Signature1").add(*protectedParams).add(aad).add(*payload).encode();
+
+ if (!ED25519_verify(signatureInput.data(), signatureInput.size(), signature->value().data(),
+ key->getBstrValue(CoseKey::PUBKEY_X)->data())) {
+ return "Signature verification failed";
+ }
+
+ return payload->value();
+}
+
+ErrMsgOr<bytevec> createCoseEncryptCiphertext(const bytevec& key, const bytevec& nonce,
+ const bytevec& protectedParams,
+ const bytevec& plaintextPayload, const bytevec& aad) {
+ auto ciphertext = aesGcmEncrypt(key, nonce,
+ cppbor::Array() // Enc strucure as AAD
+ .add("Encrypt") // Context
+ .add(protectedParams) // Protected
+ .add(aad) // External AAD
+ .encode(),
+ plaintextPayload);
+
+ if (!ciphertext) return ciphertext.moveMessage();
+ return ciphertext.moveValue();
+}
+
+ErrMsgOr<cppbor::Array> constructCoseEncrypt(const bytevec& key, const bytevec& nonce,
+ const bytevec& plaintextPayload, const bytevec& aad,
+ cppbor::Array recipients) {
+ auto encryptProtectedHeader = cppbor::Map() //
+ .add(ALGORITHM, AES_GCM_256)
+ .canonicalize()
+ .encode();
+
+ auto ciphertext =
+ createCoseEncryptCiphertext(key, nonce, encryptProtectedHeader, plaintextPayload, aad);
+ if (!ciphertext) return ciphertext.moveMessage();
+
+ return cppbor::Array()
+ .add(encryptProtectedHeader) // Protected
+ .add(cppbor::Map().add(IV, nonce).canonicalize()) // Unprotected
+ .add(*ciphertext) // Payload
+ .add(std::move(recipients));
+}
+
+ErrMsgOr<std::pair<bytevec /* pubkey */, bytevec /* key ID */>>
+getSenderPubKeyFromCoseEncrypt(const cppbor::Item* coseEncrypt) {
+ if (!coseEncrypt || !coseEncrypt->asArray() ||
+ coseEncrypt->asArray()->size() != kCoseEncryptEntryCount) {
+ return "Invalid COSE_Encrypt";
+ }
+
+ auto& recipients = coseEncrypt->asArray()->get(kCoseEncryptRecipients);
+ if (!recipients || !recipients->asArray() || recipients->asArray()->size() != 1) {
+ return "Invalid recipients list";
+ }
+
+ auto& recipient = recipients->asArray()->get(0);
+ if (!recipient || !recipient->asArray() || recipient->asArray()->size() != 3) {
+ return "Invalid COSE_recipient";
+ }
+
+ auto& ciphertext = recipient->asArray()->get(2);
+ if (!ciphertext->asSimple() || !ciphertext->asSimple()->asNull()) {
+ return "Unexpected value in recipients ciphertext field " +
+ cppbor::prettyPrint(ciphertext.get());
+ }
+
+ auto& protParms = recipient->asArray()->get(0);
+ if (!protParms || !protParms->asBstr()) return "Invalid protected params";
+ auto [parsedProtParms, _, errMsg] = cppbor::parse(protParms->asBstr());
+ if (!parsedProtParms) return "Failed to parse protected params: " + errMsg;
+ if (!parsedProtParms->asMap()) return "Invalid protected params";
+
+ auto& algorithm = parsedProtParms->asMap()->get(ALGORITHM);
+ if (!algorithm || !algorithm->asInt() || algorithm->asInt()->value() != ECDH_ES_HKDF_256) {
+ return "Invalid algorithm";
+ }
+
+ auto& unprotParms = recipient->asArray()->get(1);
+ if (!unprotParms || !unprotParms->asMap()) return "Invalid unprotected params";
+
+ auto& senderCoseKey = unprotParms->asMap()->get(COSE_KEY);
+ if (!senderCoseKey || !senderCoseKey->asMap()) return "Invalid sender COSE_Key";
+
+ auto& keyType = senderCoseKey->asMap()->get(CoseKey::KEY_TYPE);
+ if (!keyType || !keyType->asInt() || keyType->asInt()->value() != OCTET_KEY_PAIR) {
+ return "Invalid key type";
+ }
+
+ auto& curve = senderCoseKey->asMap()->get(CoseKey::CURVE);
+ if (!curve || !curve->asInt() || curve->asInt()->value() != X25519) {
+ return "Unsupported curve";
+ }
+
+ auto& pubkey = senderCoseKey->asMap()->get(CoseKey::PUBKEY_X);
+ if (!pubkey || !pubkey->asBstr() ||
+ pubkey->asBstr()->value().size() != X25519_PUBLIC_VALUE_LEN) {
+ return "Invalid X25519 public key";
+ }
+
+ auto& key_id = unprotParms->asMap()->get(KEY_ID);
+ if (key_id && key_id->asBstr()) {
+ return std::make_pair(pubkey->asBstr()->value(), key_id->asBstr()->value());
+ }
+
+ // If no key ID, just return an empty vector.
+ return std::make_pair(pubkey->asBstr()->value(), bytevec{});
+}
+
+ErrMsgOr<bytevec> decryptCoseEncrypt(const bytevec& key, const cppbor::Item* coseEncrypt,
+ const bytevec& external_aad) {
+ if (!coseEncrypt || !coseEncrypt->asArray() ||
+ coseEncrypt->asArray()->size() != kCoseEncryptEntryCount) {
+ return "Invalid COSE_Encrypt";
+ }
+
+ auto& protParms = coseEncrypt->asArray()->get(kCoseEncryptProtectedParams);
+ auto& unprotParms = coseEncrypt->asArray()->get(kCoseEncryptUnprotectedParams);
+ auto& ciphertext = coseEncrypt->asArray()->get(kCoseEncryptPayload);
+ auto& recipients = coseEncrypt->asArray()->get(kCoseEncryptRecipients);
+
+ if (!protParms || !protParms->asBstr() || !unprotParms || !ciphertext || !recipients) {
+ return "Invalid COSE_Encrypt";
+ }
+
+ auto [parsedProtParams, _, errMsg] = cppbor::parse(protParms->asBstr()->value());
+ if (!parsedProtParams) {
+ return errMsg + " when parsing protected params.";
+ }
+ if (!parsedProtParams->asMap()) {
+ return "Protected params must be a map";
+ }
+
+ auto& algorithm = parsedProtParams->asMap()->get(ALGORITHM);
+ if (!algorithm || !algorithm->asInt() || algorithm->asInt()->value() != AES_GCM_256) {
+ return "Unsupported encryption algorithm";
+ }
+
+ if (!unprotParms->asMap() || unprotParms->asMap()->size() != 1) {
+ return "Invalid unprotected params";
+ }
+
+ auto& nonce = unprotParms->asMap()->get(IV);
+ if (!nonce || !nonce->asBstr() || nonce->asBstr()->value().size() != kAesGcmNonceLength) {
+ return "Invalid nonce";
+ }
+
+ if (!ciphertext->asBstr()) return "Invalid ciphertext";
+
+ auto aad = cppbor::Array() // Enc strucure as AAD
+ .add("Encrypt") // Context
+ .add(protParms->asBstr()->value()) // Protected
+ .add(external_aad) // External AAD
+ .encode();
+
+ return aesGcmDecrypt(key, nonce->asBstr()->value(), aad, ciphertext->asBstr()->value());
+}
+
+ErrMsgOr<bytevec> x25519_HKDF_DeriveKey(const bytevec& pubKeyA, const bytevec& privKeyA,
+ const bytevec& pubKeyB, bool senderIsA) {
+ if (privKeyA.empty() || pubKeyA.empty() || pubKeyB.empty()) {
+ return "Missing input key parameters";
+ }
+
+ bytevec rawSharedKey(X25519_SHARED_KEY_LEN);
+ if (!::X25519(rawSharedKey.data(), privKeyA.data(), pubKeyB.data())) {
+ return "ECDH operation failed";
+ }
+
+ bytevec kdfContext = cppbor::Array()
+ .add(AES_GCM_256)
+ .add(cppbor::Array() // Sender Info
+ .add(cppbor::Bstr("client"))
+ .add(bytevec{} /* nonce */)
+ .add(senderIsA ? pubKeyA : pubKeyB))
+ .add(cppbor::Array() // Recipient Info
+ .add(cppbor::Bstr("server"))
+ .add(bytevec{} /* nonce */)
+ .add(senderIsA ? pubKeyB : pubKeyA))
+ .add(cppbor::Array() // SuppPubInfo
+ .add(kAesGcmKeySizeBits) // output key length
+ .add(bytevec{})) // protected
+ .encode();
+
+ bytevec retval(SHA256_DIGEST_LENGTH);
+ bytevec salt{};
+ if (!HKDF(retval.data(), retval.size(), //
+ EVP_sha256(), //
+ rawSharedKey.data(), rawSharedKey.size(), //
+ salt.data(), salt.size(), //
+ kdfContext.data(), kdfContext.size())) {
+ return "ECDH HKDF failed";
+ }
+
+ return retval;
+}
+
+ErrMsgOr<bytevec> aesGcmEncrypt(const bytevec& key, const bytevec& nonce, const bytevec& aad,
+ const bytevec& plaintext) {
+ auto ctx = aesGcmInitAndProcessAad(key, nonce, aad, true /* encrypt */);
+ if (!ctx) return ctx.moveMessage();
+
+ bytevec ciphertext(plaintext.size() + kAesGcmTagSize);
+ int outlen;
+ if (!EVP_CipherUpdate(ctx->get(), ciphertext.data(), &outlen, plaintext.data(),
+ plaintext.size())) {
+ return "Failed to encrypt plaintext";
+ }
+ assert(plaintext.size() == static_cast<uint64_t>(outlen));
+
+ if (!EVP_CipherFinal_ex(ctx->get(), ciphertext.data() + outlen, &outlen)) {
+ return "Failed to finalize encryption";
+ }
+ assert(outlen == 0);
+
+ if (!EVP_CIPHER_CTX_ctrl(ctx->get(), EVP_CTRL_GCM_GET_TAG, kAesGcmTagSize,
+ ciphertext.data() + plaintext.size())) {
+ return "Failed to retrieve tag";
+ }
+
+ return ciphertext;
+}
+
+ErrMsgOr<bytevec> aesGcmDecrypt(const bytevec& key, const bytevec& nonce, const bytevec& aad,
+ const bytevec& ciphertextWithTag) {
+ auto ctx = aesGcmInitAndProcessAad(key, nonce, aad, false /* encrypt */);
+ if (!ctx) return ctx.moveMessage();
+
+ if (ciphertextWithTag.size() < kAesGcmTagSize) return "Missing tag";
+
+ bytevec plaintext(ciphertextWithTag.size() - kAesGcmTagSize);
+ int outlen;
+ if (!EVP_CipherUpdate(ctx->get(), plaintext.data(), &outlen, ciphertextWithTag.data(),
+ ciphertextWithTag.size() - kAesGcmTagSize)) {
+ return "Failed to decrypt plaintext";
+ }
+ assert(plaintext.size() == static_cast<uint64_t>(outlen));
+
+ bytevec tag(ciphertextWithTag.end() - kAesGcmTagSize, ciphertextWithTag.end());
+ if (!EVP_CIPHER_CTX_ctrl(ctx->get(), EVP_CTRL_GCM_SET_TAG, kAesGcmTagSize, tag.data())) {
+ return "Failed to set tag: " + std::to_string(ERR_peek_last_error());
+ }
+
+ if (!EVP_CipherFinal_ex(ctx->get(), nullptr, &outlen)) {
+ return "Failed to finalize encryption";
+ }
+ assert(outlen == 0);
+
+ return plaintext;
+}
+
+} // namespace cppcose
diff --git a/ec_privkey_pk8.der b/ec_privkey_pk8.der
deleted file mode 100644
index a4af673..0000000
--- a/ec_privkey_pk8.der
+++ /dev/null
Binary files differ
diff --git a/include/keymaster/List.h b/include/keymaster/List.h
index 882c6c7..82aded4 100644
--- a/include/keymaster/List.h
+++ b/include/keymaster/List.h
@@ -24,8 +24,8 @@
//
// The only class you want to use from here is "List".
//
-#ifndef _LIBS_UTILS_LIST_H
-#define _LIBS_UTILS_LIST_H
+
+#pragma once
#include <stddef.h>
#include <stdint.h>
@@ -38,15 +38,13 @@
* Objects added to the list are copied using the assignment operator,
* so this must be defined.
*/
-template<typename T>
-class List
-{
-protected:
+template <typename T> class List {
+ protected:
/*
* One element in the list.
*/
class _Node {
- public:
+ public:
explicit _Node(const T& val) : mVal(val) {}
~_Node() {}
inline T& getRef() { return mVal; }
@@ -56,53 +54,46 @@
inline void setVal(const T& val) { mVal = val; }
inline void setPrev(_Node* ptr) { mpPrev = ptr; }
inline void setNext(_Node* ptr) { mpNext = ptr; }
- private:
+
+ private:
friend class List;
friend class _ListIterator;
- T mVal;
- _Node* mpPrev;
- _Node* mpNext;
+ T mVal;
+ _Node* mpPrev;
+ _Node* mpNext;
};
/*
* Iterator for walking through the list.
*/
-
- template <typename TYPE>
- struct CONST_ITERATOR {
- typedef _Node const * NodePtr;
+
+ template <typename TYPE> struct CONST_ITERATOR {
+ typedef _Node const* NodePtr;
typedef const TYPE Type;
};
-
- template <typename TYPE>
- struct NON_CONST_ITERATOR {
+
+ template <typename TYPE> struct NON_CONST_ITERATOR {
typedef _Node* NodePtr;
typedef TYPE Type;
};
-
- template<
- typename U,
- template <class> class Constness
- >
- class _ListIterator {
- typedef _ListIterator<U, Constness> _Iter;
- typedef typename Constness<U>::NodePtr _NodePtr;
- typedef typename Constness<U>::Type _Type;
+
+ template <typename U, template <class> class Constness> class _ListIterator {
+ typedef _ListIterator<U, Constness> _Iter;
+ typedef typename Constness<U>::NodePtr _NodePtr;
+ typedef typename Constness<U>::Type _Type;
explicit _ListIterator(_NodePtr ptr) : mpNode(ptr) {}
- public:
+ public:
_ListIterator() {}
_ListIterator(const _Iter& rhs) : mpNode(rhs.mpNode) {}
~_ListIterator() {}
-
+
// this will handle conversions from iterator to const_iterator
// (and also all convertible iterators)
// Here, in this implementation, the iterators can be converted
// if the nodes can be converted
- template<typename V> explicit
- _ListIterator(const V& rhs) : mpNode(rhs.mpNode) {}
-
+ template <typename V> explicit _ListIterator(const V& rhs) : mpNode(rhs.mpNode) {}
/*
* Dereference operator. Used to get at the juicy insides.
@@ -113,40 +104,38 @@
/*
* Iterator comparison.
*/
- inline bool operator==(const _Iter& right) const {
- return mpNode == right.mpNode; }
-
- inline bool operator!=(const _Iter& right) const {
- return mpNode != right.mpNode; }
+ inline bool operator==(const _Iter& right) const { return mpNode == right.mpNode; }
+
+ inline bool operator!=(const _Iter& right) const { return mpNode != right.mpNode; }
/*
* handle comparisons between iterator and const_iterator
*/
- template<typename OTHER>
- inline bool operator==(const OTHER& right) const {
- return mpNode == right.mpNode; }
-
- template<typename OTHER>
- inline bool operator!=(const OTHER& right) const {
- return mpNode != right.mpNode; }
+ template <typename OTHER> inline bool operator==(const OTHER& right) const {
+ return mpNode == right.mpNode;
+ }
+
+ template <typename OTHER> inline bool operator!=(const OTHER& right) const {
+ return mpNode != right.mpNode;
+ }
/*
* Incr/decr, used to move through the list.
*/
- inline _Iter& operator++() { // pre-increment
+ inline _Iter& operator++() { // pre-increment
mpNode = mpNode->getNext();
return *this;
}
- const _Iter operator++(int) { // post-increment
+ const _Iter operator++(int) { // post-increment
_Iter tmp(*this);
mpNode = mpNode->getNext();
return tmp;
}
- inline _Iter& operator--() { // pre-increment
+ inline _Iter& operator--() { // pre-increment
mpNode = mpNode->getPrev();
return *this;
}
- const _Iter operator--(int) { // post-increment
+ const _Iter operator--(int) { // post-increment
_Iter tmp(*this);
mpNode = mpNode->getPrev();
return tmp;
@@ -154,22 +143,20 @@
inline _NodePtr getNode() const { return mpNode; }
- _NodePtr mpNode; /* should be private, but older gcc fails */
- private:
+ _NodePtr mpNode; /* should be private, but older gcc fails */
+ private:
friend class List;
};
-public:
- List() {
- prep();
- }
- List(const List<T>& src) { // copy-constructor
+ public:
+ List() { prep(); }
+ List(const List<T>& src) { // copy-constructor
prep();
insert(begin(), src.begin(), src.end());
}
virtual ~List() {
clear();
- delete[] (unsigned char*) mpMiddle;
+ delete[](unsigned char*) mpMiddle;
}
typedef _ListIterator<T, NON_CONST_ITERATOR> iterator;
@@ -181,36 +168,27 @@
inline bool empty() const { return mpMiddle->getNext() == mpMiddle; }
/* return #of elements in list */
- size_t size() const {
- return size_t(distance(begin(), end()));
- }
+ size_t size() const { return size_t(distance(begin(), end())); }
/*
* Return the first element or one past the last element. The
* _Node* we're returning is converted to an "iterator" by a
* constructor in _ListIterator.
*/
- inline iterator begin() {
- return iterator(mpMiddle->getNext());
+ inline iterator begin() { return iterator(mpMiddle->getNext()); }
+ inline const_iterator begin() const {
+ return const_iterator(const_cast<_Node const*>(mpMiddle->getNext()));
}
- inline const_iterator begin() const {
- return const_iterator(const_cast<_Node const*>(mpMiddle->getNext()));
- }
- inline iterator end() {
- return iterator(mpMiddle);
- }
- inline const_iterator end() const {
- return const_iterator(const_cast<_Node const*>(mpMiddle));
- }
+ inline iterator end() { return iterator(mpMiddle); }
+ inline const_iterator end() const { return const_iterator(const_cast<_Node const*>(mpMiddle)); }
/* add the object to the head or tail of the list */
void push_front(const T& val) { insert(begin(), val); }
void push_back(const T& val) { insert(end(), val); }
/* insert before the current node; returns iterator at new node */
- iterator insert(iterator posn, const T& val)
- {
- _Node* newNode = new(std::nothrow) _Node(val); // alloc & copy-construct
+ iterator insert(iterator posn, const T& val) {
+ _Node* newNode = new (std::nothrow) _Node(val); // alloc & copy-construct
newNode->setNext(posn.getNode());
newNode->setPrev(posn.getNode()->getPrev());
posn.getNode()->getPrev()->setNext(newNode);
@@ -220,7 +198,7 @@
/* insert a range of elements before the current node */
void insert(iterator posn, const_iterator first, const_iterator last) {
- for ( ; first != last; ++first)
+ for (; first != last; ++first)
insert(posn, *first);
}
@@ -237,7 +215,7 @@
/* remove a range of elements */
iterator erase(iterator first, iterator last) {
while (first != last)
- erase(first++); // don't erase than incr later!
+ erase(first++); // don't erase than incr later!
return iterator(last);
}
@@ -260,19 +238,13 @@
* will be equal to "last". The iterators must refer to the same
* list.
*
- * FIXME: This is actually a generic iterator function. It should be a
+ * FIXME: This is actually a generic iterator function. It should be a
* template function at the top-level with specializations for things like
* vector<>, which can just do pointer math). Here we limit it to
* _ListIterator of the same type but different constness.
*/
- template<
- typename U,
- template <class> class CL,
- template <class> class CR
- >
- ptrdiff_t distance(
- _ListIterator<U, CL> first, _ListIterator<U, CR> last) const
- {
+ template <typename U, template <class> class CL, template <class> class CR>
+ ptrdiff_t distance(_ListIterator<U, CL> first, _ListIterator<U, CR> last) const {
ptrdiff_t count = 0;
while (first != last) {
++first;
@@ -281,7 +253,7 @@
return count;
}
-private:
+ private:
/*
* I want a _Node but don't need it to hold valid data. More
* to the point, I don't want T's constructor to fire, since it
@@ -289,7 +261,7 @@
* slightly uncouth storage alloc.
*/
void prep() {
- mpMiddle = (_Node*) new(std::nothrow) unsigned char[sizeof(_Node)];
+ mpMiddle = (_Node*)new (std::nothrow) unsigned char[sizeof(_Node)];
mpMiddle->setPrev(mpMiddle);
mpMiddle->setNext(mpMiddle);
}
@@ -299,7 +271,7 @@
* It sits in the middle of a circular list of nodes. The iterator
* runs around the circle until it encounters this one.
*/
- _Node* mpMiddle;
+ _Node* mpMiddle;
};
/*
@@ -309,24 +281,19 @@
* fill it with the source. However, we can speed things along by
* re-using existing elements.
*/
-template<class T>
-List<T>& List<T>::operator=(const List<T>& right)
-{
- if (this == &right)
- return *this; // self-assignment
+template <class T> List<T>& List<T>::operator=(const List<T>& right) {
+ if (this == &right) return *this; // self-assignment
iterator firstDst = begin();
iterator lastDst = end();
const_iterator firstSrc = right.begin();
const_iterator lastSrc = right.end();
while (firstSrc != lastSrc && firstDst != lastDst)
*firstDst++ = *firstSrc++;
- if (firstSrc == lastSrc) // ran out of elements in source?
- erase(firstDst, lastDst); // yes, erase any extras
+ if (firstSrc == lastSrc) // ran out of elements in source?
+ erase(firstDst, lastDst); // yes, erase any extras
else
- insert(lastDst, firstSrc, lastSrc); // copy remaining over
+ insert(lastDst, firstSrc, lastSrc); // copy remaining over
return *this;
}
-}; // namespace android
-
-#endif // _LIBS_UTILS_LIST_H
+}; // namespace keymaster
diff --git a/include/keymaster/UniquePtr.h b/include/keymaster/UniquePtr.h
index 20ff446..aecebb2 100644
--- a/include/keymaster/UniquePtr.h
+++ b/include/keymaster/UniquePtr.h
@@ -14,264 +14,28 @@
* limitations under the License.
*/
-#ifndef INCLUDE_KEYMASTER_UNIQUEPTR_H_
-#define INCLUDE_KEYMASTER_UNIQUEPTR_H_
+#pragma once
-#include <stddef.h> // for size_t
+#include <stddef.h> // for size_t
+
+#include <memory>
namespace keymaster {
// Default deleter for pointer types.
-template <typename T>
-struct DefaultDelete {
+template <typename T> struct DefaultDelete {
enum { type_must_be_complete = sizeof(T) };
DefaultDelete() {}
- void operator()(T* p) const {
- delete p;
- }
+ void operator()(T* p) const { delete p; }
};
// Default deleter for array types.
-template <typename T>
-struct DefaultDelete<T[]> {
+template <typename T> struct DefaultDelete<T[]> {
enum { type_must_be_complete = sizeof(T) };
- void operator()(T* p) const {
- delete[] p;
- }
+ void operator()(T* p) const { delete[] p; }
};
-// A smart pointer that deletes the given pointer on destruction.
-// Equivalent to C++0x's std::unique_ptr (a combination of boost::scoped_ptr
-// and boost::scoped_array).
-// Named to be in keeping with Android style but also to avoid
-// collision with any other implementation, until we can switch over
-// to unique_ptr.
-// Use thus:
-// UniquePtr<C> c(new C);
-template <typename T, typename D = DefaultDelete<T> >
-class UniquePtr {
- template<typename U, typename UD>
- friend
- class UniquePtr;
-public:
- UniquePtr() : mPtr(nullptr) {}
- // Construct a new UniquePtr, taking ownership of the given raw pointer.
- explicit UniquePtr(T* ptr) : mPtr(ptr) {
- }
- // NOLINTNEXTLINE(google-explicit-constructor)
- UniquePtr(const decltype(nullptr)&) : mPtr(nullptr) {}
+template <class T, class Deleter = std::default_delete<T>>
+using UniquePtr = std::unique_ptr<T, Deleter>;
- UniquePtr(UniquePtr && other): mPtr(other.mPtr) {
- other.mPtr = nullptr;
- }
-
- template <typename U>
- // NOLINTNEXTLINE(google-explicit-constructor)
- UniquePtr(UniquePtr<U>&& other) : mPtr(other.mPtr) {
- other.mPtr = nullptr;
- }
- UniquePtr& operator=(UniquePtr && other) {
- if (&other != this) {
- reset();
- mPtr = other.release();
- }
- return *this;
- }
-
- ~UniquePtr() {
- reset();
- }
-
- // Accessors.
- T& operator*() const { return *mPtr; }
- T* operator->() const { return mPtr; }
- T* get() const { return mPtr; }
-
- // NOLINTNEXTLINE(google-explicit-constructor)
- operator bool() const { return mPtr != nullptr; }
-
- // Returns the raw pointer and hands over ownership to the caller.
- // The pointer will not be deleted by UniquePtr.
- T* release() __attribute__((warn_unused_result)) {
- T* result = mPtr;
- mPtr = nullptr;
- return result;
- }
-
- // Takes ownership of the given raw pointer.
- // If this smart pointer previously owned a different raw pointer, that
- // raw pointer will be freed.
- void reset(T* ptr = nullptr) {
- if (ptr != mPtr) {
- D()(mPtr);
- mPtr = ptr;
- }
- }
-
-private:
- // The raw pointer.
- T* mPtr;
-
- // Comparing unique pointers is probably a mistake, since they're unique.
- template <typename T2> bool operator==(const UniquePtr<T2>& p) const;
- template <typename T2> bool operator!=(const UniquePtr<T2>& p) const;
-
- UniquePtr(const UniquePtr&) = delete;
- UniquePtr & operator=(const UniquePtr&) = delete;
-};
-
-// Partial specialization for array types. Like std::unique_ptr, this removes
-// operator* and operator-> but adds operator[].
-template <typename T, typename D>
-class UniquePtr<T[], D> {
-public:
- UniquePtr() : mPtr(nullptr) {}
- explicit UniquePtr(T* ptr) : mPtr(ptr) {
- }
- // NOLINTNEXTLINE(google-explicit-constructor)
- UniquePtr(const decltype(nullptr)&) : mPtr(nullptr) {}
-
- UniquePtr(UniquePtr && other): mPtr(other.mPtr) {
- other.mPtr = nullptr;
- }
- UniquePtr& operator=(UniquePtr && other) {
- if (&other != this) {
- reset();
- mPtr = other.release();
- }
- return *this;
- }
-
- ~UniquePtr() {
- reset();
- }
-
- T& operator[](size_t i) const {
- return mPtr[i];
- }
- T* get() const { return mPtr; }
-
- T* release() __attribute__((warn_unused_result)) {
- T* result = mPtr;
- mPtr = nullptr;
- return result;
- }
-
- // NOLINTNEXTLINE(google-explicit-constructor)
- operator bool() const { return mPtr != nullptr; }
-
- void reset(T* ptr = nullptr) {
- if (ptr != mPtr) {
- D()(mPtr);
- mPtr = ptr;
- }
- }
-
-private:
- T* mPtr;
-
- UniquePtr(const UniquePtr&) = delete;
- UniquePtr & operator=(const UniquePtr&) = delete;
-};
-
-} // namespace keymaster
-
-#if UNIQUE_PTR_TESTS
-
-// Run these tests with:
-// g++ -g -DUNIQUE_PTR_TESTS -x c++ UniquePtr.h && ./a.out
-
-#include <stdio.h>
-using namespace keymaster;
-
-static void assert(bool b) {
- if (!b) {
- fprintf(stderr, "FAIL\n");
- abort();
- }
- fprintf(stderr, "OK\n");
-}
-static int cCount = 0;
-struct C {
- C() { ++cCount; }
- ~C() { --cCount; }
-};
-static bool freed = false;
-struct Freer {
- void operator()(int* p) {
- assert(*p == 123);
- free(p);
- freed = true;
- }
-};
-
-int main(int argc, char* argv[]) {
- //
- // UniquePtr<T> tests...
- //
-
- // Can we free a single object?
- {
- UniquePtr<C> c(new C);
- assert(cCount == 1);
- }
- assert(cCount == 0);
- // Does release work?
- C* rawC;
- {
- UniquePtr<C> c(new C);
- assert(cCount == 1);
- rawC = c.release();
- }
- assert(cCount == 1);
- delete rawC;
- // Does reset work?
- {
- UniquePtr<C> c(new C);
- assert(cCount == 1);
- c.reset(new C);
- assert(cCount == 1);
- }
- assert(cCount == 0);
-
- //
- // UniquePtr<T[]> tests...
- //
-
- // Can we free an array?
- {
- UniquePtr<C[]> cs(new C[4]);
- assert(cCount == 4);
- }
- assert(cCount == 0);
- // Does release work?
- {
- UniquePtr<C[]> c(new C[4]);
- assert(cCount == 4);
- rawC = c.release();
- }
- assert(cCount == 4);
- delete[] rawC;
- // Does reset work?
- {
- UniquePtr<C[]> c(new C[4]);
- assert(cCount == 4);
- c.reset(new C[2]);
- assert(cCount == 2);
- }
- assert(cCount == 0);
-
- //
- // Custom deleter tests...
- //
- assert(!freed);
- {
- UniquePtr<int, Freer> i(reinterpret_cast<int*>(malloc(sizeof(int))));
- *i = 123;
- }
- assert(freed);
- return 0;
-}
-#endif
-
-#endif // INCLUDE_KEYMASTER_UNIQUEPTR_H_
+} // namespace keymaster
diff --git a/include/keymaster/android_keymaster.h b/include/keymaster/android_keymaster.h
index 2836464..bbeb81a 100644
--- a/include/keymaster/android_keymaster.h
+++ b/include/keymaster/android_keymaster.h
@@ -14,8 +14,7 @@
* limitations under the License.
*/
-#ifndef SYSTEM_KEYMASTER_ANDROID_KEYMASTER_H_
-#define SYSTEM_KEYMASTER_ANDROID_KEYMASTER_H_
+#pragma once
#include <keymaster/android_keymaster_messages.h>
#include <keymaster/authorization_set.h>
@@ -47,7 +46,8 @@
*/
class AndroidKeymaster {
public:
- AndroidKeymaster(KeymasterContext* context, size_t operation_table_size);
+ AndroidKeymaster(KeymasterContext* context, size_t operation_table_size,
+ uint32_t message_version = kDefaultMessageVersion);
virtual ~AndroidKeymaster();
AndroidKeymaster(AndroidKeymaster&&);
@@ -68,10 +68,13 @@
GetHmacSharingParametersResponse GetHmacSharingParameters();
ComputeSharedHmacResponse ComputeSharedHmac(const ComputeSharedHmacRequest& request);
VerifyAuthorizationResponse VerifyAuthorization(const VerifyAuthorizationRequest& request);
-
+ void GenerateTimestampToken(GenerateTimestampTokenRequest& request,
+ GenerateTimestampTokenResponse* response);
void AddRngEntropy(const AddEntropyRequest& request, AddEntropyResponse* response);
void Configure(const ConfigureRequest& request, ConfigureResponse* response);
void GenerateKey(const GenerateKeyRequest& request, GenerateKeyResponse* response);
+ void GenerateRkpKey(const GenerateRkpKeyRequest& request, GenerateRkpKeyResponse* response);
+ void GenerateCsr(const GenerateCsrRequest& request, GenerateCsrResponse* response);
void GetKeyCharacteristics(const GetKeyCharacteristicsRequest& request,
GetKeyCharacteristicsResponse* response);
void ImportKey(const ImportKeyRequest& request, ImportKeyResponse* response);
@@ -87,17 +90,35 @@
void FinishOperation(const FinishOperationRequest& request, FinishOperationResponse* response);
void AbortOperation(const AbortOperationRequest& request, AbortOperationResponse* response);
+ EarlyBootEndedResponse EarlyBootEnded();
+ DeviceLockedResponse DeviceLocked(const DeviceLockedRequest& request);
+ GetVersion2Response GetVersion2(const GetVersion2Request& request);
+ ConfigureVendorPatchlevelResponse
+ ConfigureVendorPatchlevel(const ConfigureVendorPatchlevelRequest& request);
+ ConfigureBootPatchlevelResponse
+ ConfigureBootPatchlevel(const ConfigureBootPatchlevelRequest& request);
+
bool has_operation(keymaster_operation_handle_t op_handle) const;
+ // Returns the message version negotiated in GetVersion2. All response messages should have
+ // this passed to their constructors. This is done automatically for the methods that return a
+ // response by value. The caller must do it for the methods that take a response pointer.
+ uint32_t message_version() const { return message_version_; }
+
private:
- keymaster_error_t LoadKey(const keymaster_key_blob_t& key_blob,
- const AuthorizationSet& additional_params,
- const KeyFactory** factory, UniquePtr<Key>* key);
+ // Loads the KM key from `key_blob`, getting app ID and app data from `additional_params`, if
+ // needed. If loading the key fails for any reason (including failure of the version binding
+ // check), the returned UniquePtr is null and `*error` is set (`error` must not be null).
+ UniquePtr<Key> LoadKey(const keymaster_key_blob_t& key_blob,
+ const AuthorizationSet& additional_params, keymaster_error_t* error);
UniquePtr<KeymasterContext> context_;
UniquePtr<OperationTable> operation_table_;
+
+ // If the caller doesn't bother to use GetVersion2 or GetVersion to configure the message
+ // version, assume kDefaultVersion, i.e. assume the client and server always support the
+ // latest default, which is the latest, except when experimental features are being added.
+ uint32_t message_version_;
};
} // namespace keymaster
-
-#endif // SYSTEM_KEYMASTER_ANDROID_KEYMASTER_H_
diff --git a/include/keymaster/android_keymaster_messages.h b/include/keymaster/android_keymaster_messages.h
index 116dfc2..2ec473f 100644
--- a/include/keymaster/android_keymaster_messages.h
+++ b/include/keymaster/android_keymaster_messages.h
@@ -14,8 +14,7 @@
* limitations under the License.
*/
-#ifndef SYSTEM_KEYMASTER_ANDROID_KEYMASTER_MESSAGES_H_
-#define SYSTEM_KEYMASTER_ANDROID_KEYMASTER_MESSAGES_H_
+#pragma once
#include <assert.h>
#include <stdint.h>
@@ -24,6 +23,7 @@
#include <keymaster/android_keymaster_utils.h>
#include <keymaster/authorization_set.h>
+#include <keymaster/km_version.h>
namespace keymaster {
@@ -55,63 +55,110 @@
DELETE_ALL_KEYS = 23,
DESTROY_ATTESTATION_IDS = 24,
IMPORT_WRAPPED_KEY = 25,
+ EARLY_BOOT_ENDED = 26,
+ DEVICE_LOCKED = 27,
+ GET_VERSION_2 = 28,
+ GENERATE_RKP_KEY = 29,
+ GENERATE_CSR = 30,
+ GENERATE_TIMESTAMP_TOKEN = 31,
+ CONFIGURE_VENDOR_PATCHLEVEL = 32,
+ CONFIGURE_BOOT_PATCHLEVEL = 33,
};
/**
- * Keymaster message versions are tied to keymaster versions. We map the keymaster
- * major.minor.subminor version to a sequential "message version".
+ * Keymaster message versions are tied to keymaster versions. We map the keymaster version to a
+ * sequential "message version". The actual message formatting differences are implemented in the
+ * message classes. Note that it is not necessary to increase the message version when new messages
+ * are added, only when the serialized format of one or more messages changes. A message version
+ * argument is provided to the message constructor and when the serialization/deserialization
+ * methods are called the implementations of those methods should examine the message version and
+ * generate/parse the byte stream accordingly.
*
- * Rather than encoding a version number into each message we rely on the client -- who initiates
- * all requests -- to check the version of the keymaster implementation with the GET_VERSION command
- * and to send only requests that the implementation can understand. This means that only the
- * client side needs to manage version compatibility; the implementation can always expect/produce
- * messages of its format.
+ * The original design of message versioning uses the GetVersion message, sent from client (e.g. HAL
+ * service) to server (e.g. trusted app), and then relies on the client to identify what messages to
+ * send. This architecture assumes that the client is never older than the server. This assumption
+ * turned out not to be true in general.
*
- * Because message version selection is purely a client-side issue, all messages default to using
- * the latest version (MAX_MESSAGE_VERSION). Client code must take care to check versions and pass
- * correct version values to message constructors. The AndroidKeymaster implementation always uses
- * the default, latest.
+ * The current approach performs a mutual exchange of message version info between client and
+ * server, using the GetVersion2 message. In addition, it defers the specification of the message
+ * ID to the message classes, so a message class can use a different ID when necessary. ID changes
+ * should be rare, in fact the only time they should be required is during the switch from
+ * GetVersion to GetVersion2.
*
- * Note that this approach implies that GetVersionRequest and GetVersionResponse cannot be
- * versioned.
+ * Assuming both client and server support GetVersion2, the approach is as follows:
+ *
+ * 1. Client sends GetVersion2Request, containing its maximum message version, c_max.
+ * 2. Server replies with GetVersion2Response, containing its maximum message version, s_max.
+ * 3. Both sides proceed to create all messages with version min(c_max, s_max).
+ *
+ * To enable this, the client must always send GetVersion2 as its first message. If the server
+ * doesn't support GetVersion2, it will reply with an error of some sort (the details are likely
+ * environment-specific). If the client gets this error, it must respond by sending GetVersion, and
+ * then must configure its message version according to the response. Note that an acceptable
+ * response to a too-old server version is to return an error to the caller of the client, informing
+ * it of the problem.
+ *
+ * On the server side, a server that supports GetVersion2 must also support GetVersion. If it
+ * received GetVersion2 it should proceed as outline above, and expect that the client will not send
+ * GetVersion. If it received GetVersion, it must assume that the client does not support
+ * GetVersion2 and reply that it is version 2.0.0 and use the corresponding message version (3).
*/
-const int32_t MAX_MESSAGE_VERSION = 3;
-inline int32_t MessageVersion(uint8_t major_ver, uint8_t minor_ver, uint8_t /* subminor_ver */) {
- int32_t message_version = -1;
- switch (major_ver) {
- case 0:
- // For the moment we still support version 0, though in general the plan is not to support
- // non-matching major versions.
- message_version = 0;
- break;
- case 1:
- switch (minor_ver) {
- case 0:
- message_version = 1;
- break;
- case 1:
- message_version = 2;
- break;
- }
- break;
- case 2:
- message_version = 3;
- break;
+constexpr int32_t kInvalidMessageVersion = -1;
+constexpr int32_t kMaxMessageVersion = 4;
+constexpr int32_t kDefaultMessageVersion = 3;
+
+/**
+ * MessageVersion returns the message version for a specified KM version and, possibly, KM release
+ * date in YYYYMMDD format (it's not recommended to change message formats within a KM version, but
+ * it could happen).
+ */
+inline constexpr int32_t MessageVersion(KmVersion version, uint32_t /* km_date */ = 0) {
+ switch (version) {
+ case KmVersion::KEYMASTER_1:
+ return 1;
+ case KmVersion::KEYMASTER_1_1:
+ return 2;
+ case KmVersion::KEYMASTER_2:
+ case KmVersion::KEYMASTER_3:
+ case KmVersion::KEYMASTER_4:
+ case KmVersion::KEYMASTER_4_1:
+ return 3;
+ case KmVersion::KEYMINT_1:
+ return 4;
}
- return message_version;
+ return kInvalidMessageVersion;
}
+/**
+ * NegotiateMessageVersion implements the client side of the GetVersion protocol, determining the
+ * appropriate message version from the values returned by the server.
+ */
+struct GetVersionResponse;
+int32_t NegotiateMessageVersion(const GetVersionResponse& response, keymaster_error_t* error);
+
+/**
+ * This MessageVersion overload determines the message version to use given the provided client and
+ * server messages. If the client gets an error when it sends GetVersion2Request, it should send
+ * GetVersionRequest and use the above overload. If the server receives GetVersionRequest, it
+ * should assume it should use message version 3 and return GetVersionResponse(2, 0, 0).
+ */
+struct GetVersion2Request;
+struct GetVersion2Response;
+int32_t NegotiateMessageVersion(const GetVersion2Request& request,
+ const GetVersion2Response& response);
+
struct KeymasterMessage : public Serializable {
explicit KeymasterMessage(int32_t ver) : message_version(ver) { assert(ver >= 0); }
- uint32_t message_version;
+ // The message version that should be used for this message. This indicates how the data is
+ // serialized/deserialized. Commonly, higher message versions serialize/deserialize additional
+ // arguments, though there is no specific rule limiting later version to adding parameters.
+ const int32_t message_version;
};
/**
* All responses include an error value, and if the error is not KM_ERROR_OK, return no additional
- * data. This abstract class factors out the common serialization functionality for all of the
- * responses, so we only have to implement it once. Inheritance for reuse is generally not a great
- * structure, but in this case it's the cleanest option.
+ * data.
*/
struct KeymasterResponse : public KeymasterMessage {
explicit KeymasterResponse(int32_t ver)
@@ -128,9 +175,27 @@
keymaster_error_t error;
};
+// Abstract base for empty requests.
+struct EmptyKeymasterRequest : public KeymasterMessage {
+ explicit EmptyKeymasterRequest(int32_t ver) : KeymasterMessage(ver) {}
+
+ size_t SerializedSize() const override { return 0; }
+ uint8_t* Serialize(uint8_t* buf, const uint8_t*) const override { return buf; }
+ bool Deserialize(const uint8_t**, const uint8_t*) override { return true; };
+};
+
+// Empty response.
+struct EmptyKeymasterResponse : public KeymasterResponse {
+ explicit EmptyKeymasterResponse(int32_t ver) : KeymasterResponse(ver) {}
+
+ size_t NonErrorSerializedSize() const override { return 0; }
+ uint8_t* NonErrorSerialize(uint8_t* buf, const uint8_t*) const override { return buf; }
+ bool NonErrorDeserialize(const uint8_t**, const uint8_t*) override { return true; }
+};
+
+// TODO(swillden): Remove when Keymaster1 is deleted
struct SupportedAlgorithmsRequest : public KeymasterMessage {
- explicit SupportedAlgorithmsRequest(int32_t ver = MAX_MESSAGE_VERSION)
- : KeymasterMessage(ver) {}
+ explicit SupportedAlgorithmsRequest(int32_t ver) : KeymasterMessage(ver) {}
size_t SerializedSize() const override { return 0; };
uint8_t* Serialize(uint8_t* buf, const uint8_t* /* end */) const override { return buf; }
@@ -139,6 +204,7 @@
}
};
+// TODO(swillden): Remove when Keymaster1 is deleted
struct SupportedByAlgorithmRequest : public KeymasterMessage {
explicit SupportedByAlgorithmRequest(int32_t ver) : KeymasterMessage(ver) {}
@@ -153,19 +219,19 @@
keymaster_algorithm_t algorithm;
};
+// TODO(swillden): Remove when Keymaster1 is deleted
struct SupportedImportFormatsRequest : public SupportedByAlgorithmRequest {
- explicit SupportedImportFormatsRequest(int32_t ver = MAX_MESSAGE_VERSION)
- : SupportedByAlgorithmRequest(ver) {}
+ explicit SupportedImportFormatsRequest(int32_t ver) : SupportedByAlgorithmRequest(ver) {}
};
+// TODO(swillden): Remove when Keymaster1 is deleted
struct SupportedExportFormatsRequest : public SupportedByAlgorithmRequest {
- explicit SupportedExportFormatsRequest(int32_t ver = MAX_MESSAGE_VERSION)
- : SupportedByAlgorithmRequest(ver) {}
+ explicit SupportedExportFormatsRequest(int32_t ver) : SupportedByAlgorithmRequest(ver) {}
};
+// TODO(swillden): Remove when Keymaster1 is deleted
struct SupportedByAlgorithmAndPurposeRequest : public KeymasterMessage {
- explicit SupportedByAlgorithmAndPurposeRequest(int32_t ver = MAX_MESSAGE_VERSION)
- : KeymasterMessage(ver) {}
+ explicit SupportedByAlgorithmAndPurposeRequest(int32_t ver) : KeymasterMessage(ver) {}
size_t SerializedSize() const override { return sizeof(uint32_t) * 2; };
uint8_t* Serialize(uint8_t* buf, const uint8_t* end) const override {
@@ -181,21 +247,23 @@
keymaster_purpose_t purpose;
};
+// TODO(swillden): Remove when Keymaster1 is deleted
struct SupportedBlockModesRequest : public SupportedByAlgorithmAndPurposeRequest {
- explicit SupportedBlockModesRequest(int32_t ver = MAX_MESSAGE_VERSION)
- : SupportedByAlgorithmAndPurposeRequest(ver) {}
+ explicit SupportedBlockModesRequest(int32_t ver) : SupportedByAlgorithmAndPurposeRequest(ver) {}
};
+// TODO(swillden): Remove when Keymaster1 is deleted
struct SupportedPaddingModesRequest : public SupportedByAlgorithmAndPurposeRequest {
- explicit SupportedPaddingModesRequest(int32_t ver = MAX_MESSAGE_VERSION)
+ explicit SupportedPaddingModesRequest(int32_t ver)
: SupportedByAlgorithmAndPurposeRequest(ver) {}
};
+// TODO(swillden): Remove when Keymaster1 is deleted
struct SupportedDigestsRequest : public SupportedByAlgorithmAndPurposeRequest {
- explicit SupportedDigestsRequest(int32_t ver = MAX_MESSAGE_VERSION)
- : SupportedByAlgorithmAndPurposeRequest(ver) {}
+ explicit SupportedDigestsRequest(int32_t ver) : SupportedByAlgorithmAndPurposeRequest(ver) {}
};
+// TODO(swillden): Remove when Keymaster1 is deleted
template <typename T> struct SupportedResponse : public KeymasterResponse {
explicit SupportedResponse(int32_t ver)
: KeymasterResponse(ver), results(nullptr), results_length(0) {}
@@ -234,69 +302,126 @@
size_t results_length;
};
+// TODO(swillden): Remove when Keymaster1 is deleted
struct SupportedAlgorithmsResponse : public SupportedResponse<keymaster_algorithm_t> {
- explicit SupportedAlgorithmsResponse(int32_t ver = MAX_MESSAGE_VERSION)
+ explicit SupportedAlgorithmsResponse(int32_t ver)
: SupportedResponse<keymaster_algorithm_t>(ver) {}
};
+// TODO(swillden): Remove when Keymaster1 is deleted
struct SupportedBlockModesResponse : public SupportedResponse<keymaster_block_mode_t> {
- explicit SupportedBlockModesResponse(int32_t ver = MAX_MESSAGE_VERSION)
+ explicit SupportedBlockModesResponse(int32_t ver)
: SupportedResponse<keymaster_block_mode_t>(ver) {}
};
+// TODO(swillden): Remove when Keymaster1 is deleted
struct SupportedPaddingModesResponse : public SupportedResponse<keymaster_padding_t> {
- explicit SupportedPaddingModesResponse(int32_t ver = MAX_MESSAGE_VERSION)
+ explicit SupportedPaddingModesResponse(int32_t ver)
: SupportedResponse<keymaster_padding_t>(ver) {}
};
+// TODO(swillden): Remove when Keymaster1 is deleted
struct SupportedDigestsResponse : public SupportedResponse<keymaster_digest_t> {
- explicit SupportedDigestsResponse(int32_t ver = MAX_MESSAGE_VERSION)
- : SupportedResponse<keymaster_digest_t>(ver) {}
+ explicit SupportedDigestsResponse(int32_t ver) : SupportedResponse<keymaster_digest_t>(ver) {}
};
+// TODO(swillden): Remove when Keymaster1 is deleted
struct SupportedImportFormatsResponse : public SupportedResponse<keymaster_key_format_t> {
- explicit SupportedImportFormatsResponse(int32_t ver = MAX_MESSAGE_VERSION)
+ explicit SupportedImportFormatsResponse(int32_t ver)
: SupportedResponse<keymaster_key_format_t>(ver) {}
};
+// TODO(swillden): Remove when Keymaster1 is deleted
struct SupportedExportFormatsResponse : public SupportedResponse<keymaster_key_format_t> {
- explicit SupportedExportFormatsResponse(int32_t ver = MAX_MESSAGE_VERSION)
+ explicit SupportedExportFormatsResponse(int32_t ver)
: SupportedResponse<keymaster_key_format_t>(ver) {}
};
struct GenerateKeyRequest : public KeymasterMessage {
- explicit GenerateKeyRequest(int32_t ver = MAX_MESSAGE_VERSION) : KeymasterMessage(ver) {}
+ explicit GenerateKeyRequest(int32_t ver) : KeymasterMessage(ver) {}
- size_t SerializedSize() const override { return key_description.SerializedSize(); }
- uint8_t* Serialize(uint8_t* buf, const uint8_t* end) const override {
- return key_description.Serialize(buf, end);
- }
- bool Deserialize(const uint8_t** buf_ptr, const uint8_t* end) override {
- return key_description.Deserialize(buf_ptr, end);
- }
+ size_t SerializedSize() const override;
+ uint8_t* Serialize(uint8_t* buf, const uint8_t* end) const override;
+ bool Deserialize(const uint8_t** buf_ptr, const uint8_t* end) override;
AuthorizationSet key_description;
+ KeymasterKeyBlob attestation_signing_key_blob;
+ AuthorizationSet attest_key_params;
+ KeymasterBlob issuer_subject;
};
struct GenerateKeyResponse : public KeymasterResponse {
- explicit GenerateKeyResponse(int32_t ver = MAX_MESSAGE_VERSION) : KeymasterResponse(ver) {
- key_blob.key_material = nullptr;
- key_blob.key_material_size = 0;
- }
- ~GenerateKeyResponse();
+ explicit GenerateKeyResponse(int32_t ver)
+ : KeymasterResponse(ver), key_blob{}, certificate_chain{} {}
size_t NonErrorSerializedSize() const override;
uint8_t* NonErrorSerialize(uint8_t* buf, const uint8_t* end) const override;
bool NonErrorDeserialize(const uint8_t** buf_ptr, const uint8_t* end) override;
- keymaster_key_blob_t key_blob;
+ KeymasterKeyBlob key_blob;
AuthorizationSet enforced;
AuthorizationSet unenforced;
+ CertificateChain certificate_chain;
+};
+
+struct GenerateRkpKeyRequest : KeymasterMessage {
+ explicit GenerateRkpKeyRequest(int32_t ver) : KeymasterMessage(ver) {}
+
+ size_t SerializedSize() const override { return sizeof(uint8_t); }
+ uint8_t* Serialize(uint8_t* buf, const uint8_t* end) const override {
+ return append_to_buf(buf, end, &test_mode, sizeof(uint8_t));
+ }
+ bool Deserialize(const uint8_t** buf_ptr, const uint8_t* end) override {
+ return copy_from_buf(buf_ptr, end, &test_mode, sizeof(uint8_t));
+ }
+
+ bool test_mode = false;
+};
+
+struct GenerateRkpKeyResponse : public KeymasterResponse {
+ explicit GenerateRkpKeyResponse(int32_t ver) : KeymasterResponse(ver) {}
+
+ size_t NonErrorSerializedSize() const override;
+ uint8_t* NonErrorSerialize(uint8_t* buf, const uint8_t* end) const override;
+ bool NonErrorDeserialize(const uint8_t** buf_ptr, const uint8_t* end) override;
+
+ KeymasterKeyBlob key_blob;
+ KeymasterBlob maced_public_key;
+};
+
+struct GenerateCsrRequest : public KeymasterMessage {
+ explicit GenerateCsrRequest(int32_t ver) : KeymasterMessage(ver) {}
+
+ ~GenerateCsrRequest() override { delete[] keys_to_sign_array; }
+
+ size_t SerializedSize() const override;
+ uint8_t* Serialize(uint8_t* buf, const uint8_t* end) const override;
+ bool Deserialize(const uint8_t** buf_ptr, const uint8_t* end) override;
+ void SetKeyToSign(uint32_t index, const void* data, size_t length);
+ void SetEndpointEncCertChain(const void* data, size_t length);
+ void SetChallenge(const void* data, size_t length);
+
+ bool test_mode = false;
+ size_t num_keys = 0;
+ KeymasterBlob* keys_to_sign_array = nullptr;
+ KeymasterBlob endpoint_enc_cert_chain;
+ KeymasterBlob challenge;
+};
+
+struct GenerateCsrResponse : public KeymasterResponse {
+ explicit GenerateCsrResponse(int32_t ver) : KeymasterResponse(ver) {}
+
+ size_t NonErrorSerializedSize() const override;
+ uint8_t* NonErrorSerialize(uint8_t* buf, const uint8_t* end) const override;
+ bool NonErrorDeserialize(const uint8_t** buf_ptr, const uint8_t* end) override;
+
+ KeymasterBlob keys_to_sign_mac;
+ KeymasterBlob device_info_blob;
+ KeymasterBlob protected_data_blob;
};
struct GetKeyCharacteristicsRequest : public KeymasterMessage {
- explicit GetKeyCharacteristicsRequest(int32_t ver = MAX_MESSAGE_VERSION)
- : KeymasterMessage(ver) {
+ explicit GetKeyCharacteristicsRequest(int32_t ver) : KeymasterMessage(ver) {
key_blob.key_material = nullptr;
key_blob.key_material_size = 0;
}
@@ -316,8 +441,8 @@
};
struct GetKeyCharacteristicsResponse : public KeymasterResponse {
- explicit GetKeyCharacteristicsResponse(int32_t ver = MAX_MESSAGE_VERSION)
- : KeymasterResponse(ver) {}
+ explicit GetKeyCharacteristicsResponse(int32_t ver) : KeymasterResponse(ver) {}
+
size_t NonErrorSerializedSize() const override;
uint8_t* NonErrorSerialize(uint8_t* buf, const uint8_t* end) const override;
bool NonErrorDeserialize(const uint8_t** buf_ptr, const uint8_t* end) override;
@@ -327,7 +452,7 @@
};
struct BeginOperationRequest : public KeymasterMessage {
- explicit BeginOperationRequest(int32_t ver = MAX_MESSAGE_VERSION) : KeymasterMessage(ver) {
+ explicit BeginOperationRequest(int32_t ver) : KeymasterMessage(ver) {
key_blob.key_material = nullptr;
key_blob.key_material_size = 0;
}
@@ -348,7 +473,7 @@
};
struct BeginOperationResponse : public KeymasterResponse {
- explicit BeginOperationResponse(int32_t ver = MAX_MESSAGE_VERSION) : KeymasterResponse(ver) {}
+ explicit BeginOperationResponse(int32_t ver) : KeymasterResponse(ver) {}
size_t NonErrorSerializedSize() const override;
uint8_t* NonErrorSerialize(uint8_t* buf, const uint8_t* end) const override;
@@ -359,7 +484,7 @@
};
struct UpdateOperationRequest : public KeymasterMessage {
- explicit UpdateOperationRequest(int32_t ver = MAX_MESSAGE_VERSION) : KeymasterMessage(ver) {}
+ explicit UpdateOperationRequest(int32_t ver) : KeymasterMessage(ver) {}
size_t SerializedSize() const override;
uint8_t* Serialize(uint8_t* buf, const uint8_t* end) const override;
@@ -371,8 +496,7 @@
};
struct UpdateOperationResponse : public KeymasterResponse {
- explicit UpdateOperationResponse(int32_t ver = MAX_MESSAGE_VERSION)
- : KeymasterResponse(ver), input_consumed(0) {}
+ explicit UpdateOperationResponse(int32_t ver) : KeymasterResponse(ver), input_consumed(0) {}
size_t NonErrorSerializedSize() const override;
uint8_t* NonErrorSerialize(uint8_t* buf, const uint8_t* end) const override;
@@ -384,7 +508,7 @@
};
struct FinishOperationRequest : public KeymasterMessage {
- explicit FinishOperationRequest(int32_t ver = MAX_MESSAGE_VERSION) : KeymasterMessage(ver) {}
+ explicit FinishOperationRequest(int32_t ver) : KeymasterMessage(ver) {}
size_t SerializedSize() const override;
uint8_t* Serialize(uint8_t* buf, const uint8_t* end) const override;
@@ -397,7 +521,7 @@
};
struct FinishOperationResponse : public KeymasterResponse {
- explicit FinishOperationResponse(int32_t ver = MAX_MESSAGE_VERSION) : KeymasterResponse(ver) {}
+ explicit FinishOperationResponse(int32_t ver) : KeymasterResponse(ver) {}
size_t NonErrorSerializedSize() const override;
uint8_t* NonErrorSerialize(uint8_t* buf, const uint8_t* end) const override;
@@ -408,7 +532,7 @@
};
struct AbortOperationRequest : public KeymasterMessage {
- explicit AbortOperationRequest(int32_t ver = MAX_MESSAGE_VERSION) : KeymasterMessage(ver) {}
+ explicit AbortOperationRequest(int32_t ver) : KeymasterMessage(ver) {}
size_t SerializedSize() const override { return sizeof(uint64_t); }
uint8_t* Serialize(uint8_t* buf, const uint8_t* end) const override {
@@ -421,16 +545,10 @@
keymaster_operation_handle_t op_handle;
};
-struct AbortOperationResponse : public KeymasterResponse {
- explicit AbortOperationResponse(int32_t ver = MAX_MESSAGE_VERSION) : KeymasterResponse(ver) {}
-
- size_t NonErrorSerializedSize() const override { return 0; }
- uint8_t* NonErrorSerialize(uint8_t* buf, const uint8_t*) const override { return buf; }
- bool NonErrorDeserialize(const uint8_t**, const uint8_t*) override { return true; }
-};
+using AbortOperationResponse = EmptyKeymasterResponse;
struct AddEntropyRequest : public KeymasterMessage {
- explicit AddEntropyRequest(int32_t ver = MAX_MESSAGE_VERSION) : KeymasterMessage(ver) {}
+ explicit AddEntropyRequest(int32_t ver) : KeymasterMessage(ver) {}
size_t SerializedSize() const override;
uint8_t* Serialize(uint8_t* buf, const uint8_t* end) const override;
@@ -439,27 +557,10 @@
Buffer random_data;
};
-struct AddEntropyResponse : public KeymasterResponse {
- explicit AddEntropyResponse(int32_t ver = MAX_MESSAGE_VERSION) : KeymasterResponse(ver) {}
-
- size_t NonErrorSerializedSize() const override { return 0; }
- uint8_t* NonErrorSerialize(uint8_t* buf, const uint8_t* /* end */) const override {
- return buf;
- }
- bool NonErrorDeserialize(const uint8_t** /* buf_ptr */, const uint8_t* /* end */) override {
- return true;
- }
-};
+using AddEntropyResponse = EmptyKeymasterResponse;
struct ImportKeyRequest : public KeymasterMessage {
- explicit ImportKeyRequest(int32_t ver = MAX_MESSAGE_VERSION)
- : KeymasterMessage(ver), key_data(nullptr) {}
- ~ImportKeyRequest() { delete[] key_data; }
-
- void SetKeyMaterial(const void* key_material, size_t length);
- void SetKeyMaterial(const keymaster_key_blob_t& blob) {
- SetKeyMaterial(blob.key_material, blob.key_material_size);
- }
+ explicit ImportKeyRequest(int32_t ver) : KeymasterMessage(ver) {}
size_t SerializedSize() const override;
uint8_t* Serialize(uint8_t* buf, const uint8_t* end) const override;
@@ -467,17 +568,15 @@
AuthorizationSet key_description;
keymaster_key_format_t key_format;
- uint8_t* key_data;
- size_t key_data_length;
+ KeymasterKeyBlob key_data;
+ KeymasterKeyBlob attestation_signing_key_blob;
+ AuthorizationSet attest_key_params;
+ KeymasterBlob issuer_subject;
};
struct ImportKeyResponse : public KeymasterResponse {
- explicit ImportKeyResponse(int32_t ver = MAX_MESSAGE_VERSION) : KeymasterResponse(ver) {
- key_blob.key_material = nullptr;
- key_blob.key_material_size = 0;
- }
- ~ImportKeyResponse() { delete[] key_blob.key_material; }
-
+ explicit ImportKeyResponse(int32_t ver)
+ : KeymasterResponse(ver), key_blob{}, certificate_chain{} {}
void SetKeyMaterial(const void* key_material, size_t length);
void SetKeyMaterial(const keymaster_key_blob_t& blob) {
SetKeyMaterial(blob.key_material, blob.key_material_size);
@@ -487,13 +586,14 @@
uint8_t* NonErrorSerialize(uint8_t* buf, const uint8_t* end) const override;
bool NonErrorDeserialize(const uint8_t** buf_ptr, const uint8_t* end) override;
- keymaster_key_blob_t key_blob;
+ KeymasterKeyBlob key_blob;
AuthorizationSet enforced;
AuthorizationSet unenforced;
+ CertificateChain certificate_chain;
};
struct ExportKeyRequest : public KeymasterMessage {
- explicit ExportKeyRequest(int32_t ver = MAX_MESSAGE_VERSION) : KeymasterMessage(ver) {
+ explicit ExportKeyRequest(int32_t ver) : KeymasterMessage(ver) {
key_blob.key_material = nullptr;
key_blob.key_material_size = 0;
}
@@ -514,8 +614,7 @@
};
struct ExportKeyResponse : public KeymasterResponse {
- explicit ExportKeyResponse(int32_t ver = MAX_MESSAGE_VERSION)
- : KeymasterResponse(ver), key_data(nullptr) {}
+ explicit ExportKeyResponse(int32_t ver) : KeymasterResponse(ver), key_data(nullptr) {}
~ExportKeyResponse() { delete[] key_data; }
void SetKeyMaterial(const void* key_material, size_t length);
@@ -532,7 +631,7 @@
};
struct DeleteKeyRequest : public KeymasterMessage {
- explicit DeleteKeyRequest(int32_t ver = MAX_MESSAGE_VERSION) : KeymasterMessage(ver) {
+ explicit DeleteKeyRequest(int32_t ver) : KeymasterMessage(ver) {
key_blob.key_material = nullptr;
key_blob.key_material_size = 0;
}
@@ -550,40 +649,25 @@
keymaster_key_blob_t key_blob;
};
-struct DeleteKeyResponse : public KeymasterResponse {
- explicit DeleteKeyResponse(int32_t ver = MAX_MESSAGE_VERSION) : KeymasterResponse(ver) {}
+using DeleteKeyResponse = EmptyKeymasterResponse;
- size_t NonErrorSerializedSize() const override { return 0; }
- uint8_t* NonErrorSerialize(uint8_t* buf, const uint8_t*) const override { return buf; }
- bool NonErrorDeserialize(const uint8_t**, const uint8_t*) override { return true; }
+struct DeleteAllKeysRequest : public EmptyKeymasterRequest {
+ explicit DeleteAllKeysRequest(int32_t ver) : EmptyKeymasterRequest(ver) {}
};
-struct DeleteAllKeysRequest : public KeymasterMessage {
- explicit DeleteAllKeysRequest(int32_t ver = MAX_MESSAGE_VERSION) : KeymasterMessage(ver) {}
+using DeleteAllKeysResponse = EmptyKeymasterResponse;
- size_t SerializedSize() const override { return 0; }
- uint8_t* Serialize(uint8_t* buf, const uint8_t*) const override { return buf; }
- bool Deserialize(const uint8_t**, const uint8_t*) override { return true; };
-};
-
-struct DeleteAllKeysResponse : public KeymasterResponse {
- explicit DeleteAllKeysResponse(int32_t ver = MAX_MESSAGE_VERSION) : KeymasterResponse(ver) {}
-
- size_t NonErrorSerializedSize() const override { return 0; }
- uint8_t* NonErrorSerialize(uint8_t* buf, const uint8_t*) const override { return buf; }
- bool NonErrorDeserialize(const uint8_t**, const uint8_t*) override { return true; }
-};
-
-struct GetVersionRequest : public KeymasterMessage {
- GetVersionRequest() : KeymasterMessage(0 /* not versionable */) {}
-
- size_t SerializedSize() const override { return 0; }
- uint8_t* Serialize(uint8_t* buf, const uint8_t*) const override { return buf; }
- bool Deserialize(const uint8_t**, const uint8_t*) override { return true; };
+struct GetVersionRequest : public EmptyKeymasterRequest {
+ // GetVersionRequest ctor takes a version arg so it has the same signature as others, but the
+ // value is ignored because it is not not versionable.
+ explicit GetVersionRequest(uint32_t /* ver */ = 0)
+ : EmptyKeymasterRequest(0 /* not versionable */) {}
};
struct GetVersionResponse : public KeymasterResponse {
- GetVersionResponse()
+ // GetVersionResponse ctor takes a version arg so it has the same signature as others, but the
+ // value is ignored because it is not not versionable.
+ explicit GetVersionResponse(uint32_t /* ver */ = 0)
: KeymasterResponse(0 /* not versionable */), major_ver(0), minor_ver(0), subminor_ver(0) {}
size_t NonErrorSerializedSize() const override;
@@ -596,7 +680,7 @@
};
struct AttestKeyRequest : public KeymasterMessage {
- explicit AttestKeyRequest(int32_t ver = MAX_MESSAGE_VERSION) : KeymasterMessage(ver) {
+ explicit AttestKeyRequest(int32_t ver) : KeymasterMessage(ver) {
key_blob.key_material = nullptr;
key_blob.key_material_size = 0;
}
@@ -616,25 +700,17 @@
};
struct AttestKeyResponse : public KeymasterResponse {
- explicit AttestKeyResponse(int32_t ver = MAX_MESSAGE_VERSION) : KeymasterResponse(ver) {
- certificate_chain.entry_count = 0;
- certificate_chain.entries = nullptr;
- }
- ~AttestKeyResponse();
-
- bool AllocateChain(size_t entry_count);
+ explicit AttestKeyResponse(int32_t ver) : KeymasterResponse(ver) {}
size_t NonErrorSerializedSize() const override;
uint8_t* NonErrorSerialize(uint8_t* buf, const uint8_t* end) const override;
bool NonErrorDeserialize(const uint8_t** buf_ptr, const uint8_t* end) override;
- keymaster_cert_chain_t certificate_chain;
+ CertificateChain certificate_chain;
};
struct UpgradeKeyRequest : public KeymasterMessage {
- explicit UpgradeKeyRequest(int32_t ver = MAX_MESSAGE_VERSION) : KeymasterMessage(ver) {
- key_blob = {nullptr, 0};
- }
+ explicit UpgradeKeyRequest(int32_t ver) : KeymasterMessage(ver) { key_blob = {nullptr, 0}; }
~UpgradeKeyRequest();
void SetKeyMaterial(const void* key_material, size_t length);
@@ -651,7 +727,7 @@
};
struct UpgradeKeyResponse : public KeymasterResponse {
- explicit UpgradeKeyResponse(int32_t ver = MAX_MESSAGE_VERSION) : KeymasterResponse(ver) {
+ explicit UpgradeKeyResponse(int32_t ver) : KeymasterResponse(ver) {
upgraded_key = {nullptr, 0};
}
~UpgradeKeyResponse();
@@ -664,7 +740,7 @@
};
struct ConfigureRequest : public KeymasterMessage {
- explicit ConfigureRequest(int32_t ver = MAX_MESSAGE_VERSION) : KeymasterMessage(ver) {}
+ explicit ConfigureRequest(int32_t ver) : KeymasterMessage(ver) {}
size_t SerializedSize() const override { return sizeof(os_version) + sizeof(os_patchlevel); }
uint8_t* Serialize(uint8_t* buf, const uint8_t* end) const override {
@@ -677,16 +753,10 @@
}
uint32_t os_version;
- uint32_t os_patchlevel;
+ uint32_t os_patchlevel; // YYYYMM
};
-struct ConfigureResponse : public KeymasterResponse {
- explicit ConfigureResponse(int32_t ver = MAX_MESSAGE_VERSION) : KeymasterResponse(ver) {}
-
- size_t NonErrorSerializedSize() const override { return 0; }
- uint8_t* NonErrorSerialize(uint8_t* buf, const uint8_t*) const override { return buf; }
- bool NonErrorDeserialize(const uint8_t**, const uint8_t*) override { return true; }
-};
+using ConfigureResponse = EmptyKeymasterResponse;
struct HmacSharingParameters : public Serializable {
HmacSharingParameters() : seed({}) { memset(nonce, 0, sizeof(nonce)); }
@@ -724,9 +794,12 @@
size_t num_params;
};
+struct GetHmacSharingParametersRequest : public EmptyKeymasterRequest {
+ explicit GetHmacSharingParametersRequest(int32_t ver) : EmptyKeymasterRequest(ver) {}
+};
+
struct GetHmacSharingParametersResponse : public KeymasterResponse {
- explicit GetHmacSharingParametersResponse(int32_t ver = MAX_MESSAGE_VERSION)
- : KeymasterResponse(ver) {}
+ explicit GetHmacSharingParametersResponse(int32_t ver) : KeymasterResponse(ver) {}
GetHmacSharingParametersResponse(GetHmacSharingParametersResponse&& other)
: KeymasterResponse(other.message_version), params(move(other.params)) {}
@@ -744,7 +817,7 @@
};
struct ComputeSharedHmacRequest : public KeymasterMessage {
- explicit ComputeSharedHmacRequest(int32_t ver = MAX_MESSAGE_VERSION) : KeymasterMessage(ver) {}
+ explicit ComputeSharedHmacRequest(int32_t ver) : KeymasterMessage(ver) {}
size_t SerializedSize() const override { return params_array.SerializedSize(); }
uint8_t* Serialize(uint8_t* buf, const uint8_t* end) const override {
@@ -758,8 +831,7 @@
};
struct ComputeSharedHmacResponse : public KeymasterResponse {
- explicit ComputeSharedHmacResponse(int32_t ver = MAX_MESSAGE_VERSION)
- : KeymasterResponse(ver) {}
+ explicit ComputeSharedHmacResponse(int32_t ver) : KeymasterResponse(ver) {}
ComputeSharedHmacResponse(ComputeSharedHmacResponse&& other) : KeymasterResponse(move(other)) {
sharing_check = move(other.sharing_check);
}
@@ -772,7 +844,7 @@
};
struct ImportWrappedKeyRequest : public KeymasterMessage {
- explicit ImportWrappedKeyRequest(int32_t ver = MAX_MESSAGE_VERSION) : KeymasterMessage(ver) {}
+ explicit ImportWrappedKeyRequest(int32_t ver) : KeymasterMessage(ver) {}
void SetWrappedMaterial(const void* key_material, size_t length);
void SetWrappingMaterial(const void* key_material, size_t length);
@@ -796,8 +868,8 @@
};
struct ImportWrappedKeyResponse : public KeymasterResponse {
- explicit ImportWrappedKeyResponse(int32_t ver = MAX_MESSAGE_VERSION) : KeymasterResponse(ver) {}
-
+ explicit ImportWrappedKeyResponse(int32_t ver = kDefaultMessageVersion)
+ : KeymasterResponse(ver), key_blob{}, certificate_chain{} {}
void SetKeyMaterial(const void* key_material, size_t length);
void SetKeyMaterial(const keymaster_key_blob_t& blob) {
SetKeyMaterial(blob.key_material, blob.key_material_size);
@@ -810,6 +882,7 @@
KeymasterKeyBlob key_blob;
AuthorizationSet enforced;
AuthorizationSet unenforced;
+ CertificateChain certificate_chain;
};
struct HardwareAuthToken : public Serializable {
@@ -857,8 +930,7 @@
};
struct VerifyAuthorizationRequest : public KeymasterMessage {
- explicit VerifyAuthorizationRequest(int32_t ver = MAX_MESSAGE_VERSION)
- : KeymasterMessage(ver) {}
+ explicit VerifyAuthorizationRequest(int32_t ver) : KeymasterMessage(ver) {}
VerifyAuthorizationRequest(VerifyAuthorizationRequest&& other) = default;
size_t SerializedSize() const override {
@@ -884,8 +956,7 @@
};
struct VerifyAuthorizationResponse : public KeymasterResponse {
- explicit VerifyAuthorizationResponse(int32_t ver = MAX_MESSAGE_VERSION)
- : KeymasterResponse(ver) {}
+ explicit VerifyAuthorizationResponse(int32_t ver) : KeymasterResponse(ver) {}
VerifyAuthorizationResponse(VerifyAuthorizationResponse&& other) = default;
size_t NonErrorSerializedSize() const override {
@@ -902,6 +973,208 @@
VerificationToken token;
};
-} // namespace keymaster
+struct EarlyBootEndedRequest : public EmptyKeymasterRequest {
+ explicit EarlyBootEndedRequest(int32_t ver) : EmptyKeymasterRequest(ver) {}
+};
-#endif // SYSTEM_KEYMASTER_ANDROID_KEYMASTER_MESSAGES_H_
+struct EarlyBootEndedResponse : public KeymasterResponse {
+ explicit EarlyBootEndedResponse(int32_t ver) : KeymasterResponse(ver) {}
+
+ size_t NonErrorSerializedSize() const override { return 0; }
+ uint8_t* NonErrorSerialize(uint8_t* buf, const uint8_t*) const override { return buf; }
+ bool NonErrorDeserialize(const uint8_t**, const uint8_t*) override { return true; }
+};
+
+struct DeviceLockedRequest : public KeymasterMessage {
+ explicit DeviceLockedRequest(int32_t ver) : KeymasterMessage(ver) {}
+ explicit DeviceLockedRequest(int32_t ver, bool passwordOnly_, VerificationToken&& token_)
+ : KeymasterMessage(ver), passwordOnly(passwordOnly_), token(move(token_)) {}
+
+ size_t SerializedSize() const override { return 1; }
+ uint8_t* Serialize(uint8_t* buf, const uint8_t* end) const override {
+ if (buf < end) *buf++ = passwordOnly ? 1 : 0;
+ return token.Serialize(buf, end);
+ }
+ bool Deserialize(const uint8_t** buf_ptr, const uint8_t* end) override {
+ if (*buf_ptr >= end) return false;
+ passwordOnly = !!*(*buf_ptr)++;
+ return token.Deserialize(buf_ptr, end);
+ }
+
+ bool passwordOnly;
+ VerificationToken token;
+};
+
+struct DeviceLockedResponse : public KeymasterResponse {
+ explicit DeviceLockedResponse(int32_t ver) : KeymasterResponse(ver) {}
+
+ size_t NonErrorSerializedSize() const override { return 0; }
+ uint8_t* NonErrorSerialize(uint8_t* buf, const uint8_t*) const override { return buf; }
+ bool NonErrorDeserialize(const uint8_t**, const uint8_t*) override { return true; }
+};
+
+struct GetVersion2Request : public KeymasterMessage {
+ // GetVersion2Request ctor takes a version arg so it has the same signature as others, but the
+ // value is ignored because it's not versionable.
+ explicit GetVersion2Request(uint32_t /* ver */ = 0)
+ : KeymasterMessage(0 /* not versionable */) {}
+
+ size_t SerializedSize() const override { return sizeof(uint32_t); /* max message version */ }
+ uint8_t* Serialize(uint8_t* buf, const uint8_t* end) const override {
+ return append_uint32_to_buf(buf, end, max_message_version);
+ }
+ bool Deserialize(const uint8_t** buf_ptr, const uint8_t* end) override {
+ return copy_uint32_from_buf(buf_ptr, end, &max_message_version);
+ }
+
+ uint32_t max_message_version = kDefaultMessageVersion;
+};
+
+struct GetVersion2Response : public KeymasterResponse {
+ // GetVersion2Request ctor takes a version arg so it has the same signature as others, but the
+ // value is ignored because it's not versionable.
+ explicit GetVersion2Response(uint32_t /* ver */ = 0)
+ : KeymasterResponse(0 /* not versionable */) {}
+
+ size_t NonErrorSerializedSize() const override;
+ uint8_t* NonErrorSerialize(uint8_t* buf, const uint8_t*) const override;
+ bool NonErrorDeserialize(const uint8_t** buf_ptr, const uint8_t* end) override;
+
+ uint32_t max_message_version;
+ KmVersion km_version;
+ uint32_t km_date;
+};
+
+struct TimestampToken : public Serializable {
+ explicit TimestampToken() = default;
+ TimestampToken(TimestampToken&& other) {
+ challenge = other.challenge;
+ timestamp = other.timestamp;
+ security_level = other.security_level;
+ mac = move(other.mac);
+ }
+ size_t SerializedSize() const override {
+ return sizeof(challenge) + sizeof(timestamp) + sizeof(security_level) +
+ mac.SerializedSize();
+ }
+ uint8_t* Serialize(uint8_t* buf, const uint8_t* end) const override {
+ buf = append_uint64_to_buf(buf, end, challenge);
+ buf = append_uint64_to_buf(buf, end, timestamp);
+ buf = append_uint32_to_buf(buf, end, security_level);
+ return mac.Serialize(buf, end);
+ }
+ bool Deserialize(const uint8_t** buf_ptr, const uint8_t* end) override {
+ return copy_uint64_from_buf(buf_ptr, end, &challenge) &&
+ copy_uint64_from_buf(buf_ptr, end, ×tamp) &&
+ copy_uint32_from_buf(buf_ptr, end, &security_level) && mac.Deserialize(buf_ptr, end);
+ }
+ uint64_t challenge{};
+ uint64_t timestamp{};
+ keymaster_security_level_t security_level{};
+ KeymasterBlob mac{};
+};
+
+struct GenerateTimestampTokenRequest : public KeymasterMessage {
+ explicit GenerateTimestampTokenRequest(int32_t ver) : KeymasterMessage(ver), challenge{} {}
+ size_t SerializedSize() const override { return sizeof(challenge); }
+ uint8_t* Serialize(uint8_t* buf, const uint8_t* end) const override {
+ return append_uint64_to_buf(buf, end, challenge);
+ }
+ bool Deserialize(const uint8_t** buf_ptr, const uint8_t* end) override {
+ return copy_uint64_from_buf(buf_ptr, end, &challenge);
+ }
+ uint64_t challenge;
+};
+
+struct GenerateTimestampTokenResponse : public KeymasterResponse {
+ explicit GenerateTimestampTokenResponse(int32_t ver) : KeymasterResponse(ver), token{} {}
+ size_t NonErrorSerializedSize() const override { return token.SerializedSize(); }
+ uint8_t* NonErrorSerialize(uint8_t* buf, const uint8_t* end) const override {
+ return token.Serialize(buf, end);
+ }
+ bool NonErrorDeserialize(const uint8_t** buf_ptr, const uint8_t* end) override {
+ return token.Deserialize(buf_ptr, end);
+ }
+ TimestampToken token;
+};
+
+struct SetAttestationIdsRequest : public KeymasterMessage {
+ explicit SetAttestationIdsRequest(int32_t ver) : KeymasterMessage(ver) {}
+ size_t SerializedSize() const override {
+ return brand.SerializedSize() //
+ + device.SerializedSize() //
+ + product.SerializedSize() //
+ + serial.SerializedSize() //
+ + imei.SerializedSize() //
+ + meid.SerializedSize() //
+ + manufacturer.SerializedSize() //
+ + model.SerializedSize();
+ }
+
+ uint8_t* Serialize(uint8_t* buf, const uint8_t* end) const override {
+ buf = brand.Serialize(buf, end);
+ buf = device.Serialize(buf, end);
+ buf = product.Serialize(buf, end);
+ buf = serial.Serialize(buf, end);
+ buf = imei.Serialize(buf, end);
+ buf = meid.Serialize(buf, end);
+ buf = manufacturer.Serialize(buf, end);
+ return model.Serialize(buf, end);
+ }
+
+ bool Deserialize(const uint8_t** buf_ptr, const uint8_t* end) override {
+ return brand.Deserialize(buf_ptr, end) //
+ && device.Deserialize(buf_ptr, end) //
+ && product.Deserialize(buf_ptr, end) //
+ && serial.Deserialize(buf_ptr, end) //
+ && imei.Deserialize(buf_ptr, end) //
+ && meid.Deserialize(buf_ptr, end) //
+ && manufacturer.Deserialize(buf_ptr, end) //
+ && model.Deserialize(buf_ptr, end); //
+ }
+
+ Buffer brand;
+ Buffer device;
+ Buffer product;
+ Buffer serial;
+ Buffer imei;
+ Buffer meid;
+ Buffer manufacturer;
+ Buffer model;
+};
+
+using SetAttestationIdsResponse = EmptyKeymasterResponse;
+
+struct ConfigureVendorPatchlevelRequest : public KeymasterMessage {
+ explicit ConfigureVendorPatchlevelRequest(int32_t ver) : KeymasterMessage(ver) {}
+
+ size_t SerializedSize() const override { return sizeof(vendor_patchlevel); }
+ uint8_t* Serialize(uint8_t* buf, const uint8_t* end) const override {
+ return append_uint32_to_buf(buf, end, vendor_patchlevel);
+ }
+ bool Deserialize(const uint8_t** buf_ptr, const uint8_t* end) override {
+ return copy_uint32_from_buf(buf_ptr, end, &vendor_patchlevel);
+ }
+
+ uint32_t vendor_patchlevel{}; // YYYYMMDD
+};
+
+using ConfigureVendorPatchlevelResponse = EmptyKeymasterResponse;
+
+struct ConfigureBootPatchlevelRequest : public KeymasterMessage {
+ explicit ConfigureBootPatchlevelRequest(int32_t ver) : KeymasterMessage(ver) {}
+
+ size_t SerializedSize() const override { return sizeof(boot_patchlevel); }
+ uint8_t* Serialize(uint8_t* buf, const uint8_t* end) const override {
+ return append_uint32_to_buf(buf, end, boot_patchlevel);
+ }
+ bool Deserialize(const uint8_t** buf_ptr, const uint8_t* end) override {
+ return copy_uint32_from_buf(buf_ptr, end, &boot_patchlevel);
+ }
+
+ uint32_t boot_patchlevel{}; // YYYYMMDD
+};
+
+using ConfigureBootPatchlevelResponse = EmptyKeymasterResponse;
+
+} // namespace keymaster
diff --git a/include/keymaster/android_keymaster_utils.h b/include/keymaster/android_keymaster_utils.h
index 31f86d9..b0a4052 100644
--- a/include/keymaster/android_keymaster_utils.h
+++ b/include/keymaster/android_keymaster_utils.h
@@ -14,27 +14,15 @@
* limitations under the License.
*/
-#ifndef SYSTEM_KEYMASTER_ANDROID_KEYMASTER_UTILS_H_
-#define SYSTEM_KEYMASTER_ANDROID_KEYMASTER_UTILS_H_
+#pragma once
#include <stdint.h>
-#ifndef __clang__
-// We need to diable foritfy level for memset in gcc because we want to use
-// memset unoptimized. This would falsely trigger __warn_memset_zero_len in
-// /usr/include/bits/string3.h. The inline checking function is only supposed to
-// work when the optimization level is at least 1.
-#pragma push_macro("__USE_FORTIFY_LEVEL")
-#undef __USE_FORTIFY_LEVEL
-#endif
-#include <string.h>
-#ifndef __clang__
-#pragma pop_macro("__USE_FORTIFY_LEVEL")
-#endif
#include <time.h> // for time_t.
-#include <keymaster/UniquePtr.h>
-
#include <hardware/keymaster_defs.h>
+
+#include <keymaster/UniquePtr.h>
+#include <keymaster/mem.h>
#include <keymaster/serializable.h>
#ifndef __has_cpp_attribute
@@ -62,151 +50,6 @@
return static_cast<int64_t>(time) * 1000;
}
-/*
- * Array Manipulation functions. This set of templated inline functions provides some nice tools
- * for operating on c-style arrays. C-style arrays actually do have a defined size associated with
- * them, as long as they are not allowed to decay to a pointer. These template methods exploit this
- * to allow size-based array operations without explicitly specifying the size. If passed a pointer
- * rather than an array, they'll fail to compile.
- */
-
-/**
- * Return the size in bytes of the array \p a.
- */
-template <typename T, size_t N> inline size_t array_size(const T (&a)[N]) {
- return sizeof(a);
-}
-
-/**
- * Return the number of elements in array \p a.
- */
-template <typename T, size_t N> inline size_t array_length(const T (&)[N]) {
- return N;
-}
-
-/**
- * Duplicate the array \p a. The memory for the new array is allocated and the caller takes
- * responsibility.
- */
-template <typename T> inline T* dup_array(const T* a, size_t n) {
- T* dup = new (std::nothrow) T[n];
- if (dup)
- for (size_t i = 0; i < n; ++i)
- dup[i] = a[i];
- return dup;
-}
-
-/**
- * Duplicate the array \p a. The memory for the new array is allocated and the caller takes
- * responsibility. Note that the dup is necessarily returned as a pointer, so size is lost. Call
- * array_length() on the original array to discover the size.
- */
-template <typename T, size_t N> inline T* dup_array(const T (&a)[N]) {
- return dup_array(a, N);
-}
-
-/**
- * Duplicate the buffer \p buf. The memory for the new buffer is allocated and the caller takes
- * responsibility.
- */
-uint8_t* dup_buffer(const void* buf, size_t size);
-
-/**
- * Copy the contents of array \p arr to \p dest.
- */
-template <typename T, size_t N> inline void copy_array(const T (&arr)[N], T* dest) {
- for (size_t i = 0; i < N; ++i)
- dest[i] = arr[i];
-}
-
-/**
- * Search array \p a for value \p val, returning true if found. Note that this function is
- * early-exit, meaning that it should not be used in contexts where timing analysis attacks could be
- * a concern.
- */
-template <typename T, size_t N> inline bool array_contains(const T (&a)[N], T val) {
- for (size_t i = 0; i < N; ++i) {
- if (a[i] == val) {
- return true;
- }
- }
- return false;
-}
-
-/**
- * Variant of memset() that uses GCC-specific pragmas to disable optimizations, so effect is not
- * optimized away. This is important because we often need to wipe blocks of sensitive data from
- * memory. As an additional convenience, this implementation avoids writing to NULL pointers.
- */
-#ifdef __clang__
-#define OPTNONE __attribute__((optnone))
-#else // not __clang__
-#define OPTNONE __attribute__((optimize("O0")))
-#endif // not __clang__
-inline OPTNONE void* memset_s(void* s, int c, size_t n) {
- if (!s)
- return s;
- return memset(s, c, n);
-}
-#undef OPTNONE
-
-/**
- * Variant of memcmp that has the same runtime regardless of whether the data matches (i.e. doesn't
- * short-circuit). Not an exact equivalent to memcmp because it doesn't return <0 if p1 < p2, just
- * 0 for match and non-zero for non-match.
- */
-int memcmp_s(const void* p1, const void* p2, size_t length);
-
-/**
- * Eraser clears buffers. Construct it with a buffer or object and the destructor will ensure that
- * it is zeroed.
- */
-class Eraser {
- public:
- /* Not implemented. If this gets used, we want a link error. */
- template <typename T> explicit Eraser(T* t);
-
- template <typename T>
- explicit Eraser(T& t) : buf_(reinterpret_cast<uint8_t*>(&t)), size_(sizeof(t)) {}
-
- template <size_t N> explicit Eraser(uint8_t (&arr)[N]) : buf_(arr), size_(N) {}
-
- Eraser(void* buf, size_t size) : buf_(static_cast<uint8_t*>(buf)), size_(size) {}
- ~Eraser() { memset_s(buf_, 0, size_); }
-
- private:
- Eraser(const Eraser&);
- void operator=(const Eraser&);
-
- uint8_t* buf_;
- size_t size_;
-};
-
-/**
- * ArrayWrapper is a trivial wrapper around a C-style array that provides begin() and end()
- * methods. This is primarily to facilitate range-based iteration on arrays. It does not copy, nor
- * does it take ownership; it just holds pointers.
- */
-template <typename T> class ArrayWrapper {
- public:
- ArrayWrapper(T* array, size_t size) : begin_(array), end_(array + size) {}
-
- T* begin() { return begin_; }
- T* end() { return end_; }
-
- private:
- T* begin_;
- T* end_;
-};
-
-template <typename T> ArrayWrapper<T> array_range(T* begin, size_t length) {
- return ArrayWrapper<T>(begin, length);
-}
-
-template <typename T, size_t n> ArrayWrapper<T> array_range(T (&a)[n]) {
- return ArrayWrapper<T>(a, n);
-}
-
/**
* Convert any unsigned integer from network to host order. We implement this here rather than
* using the functions from arpa/inet.h because the TEE doesn't have inet.h. This isn't the most
@@ -237,37 +80,29 @@
return retval;
}
-inline
-const uint8_t* const & accessBlobData(const keymaster_key_blob_t* blob) {
+inline const uint8_t* const& accessBlobData(const keymaster_key_blob_t* blob) {
return blob->key_material;
}
-inline
-const uint8_t*& accessBlobData(keymaster_key_blob_t* blob) {
+inline const uint8_t*& accessBlobData(keymaster_key_blob_t* blob) {
return blob->key_material;
}
-inline
-const size_t& accessBlobSize(const keymaster_key_blob_t* blob) {
+inline const size_t& accessBlobSize(const keymaster_key_blob_t* blob) {
return blob->key_material_size;
}
-inline
-size_t& accessBlobSize(keymaster_key_blob_t* blob) {
+inline size_t& accessBlobSize(keymaster_key_blob_t* blob) {
return blob->key_material_size;
}
-inline
-const uint8_t* const & accessBlobData(const keymaster_blob_t* blob) {
+inline const uint8_t* const& accessBlobData(const keymaster_blob_t* blob) {
return blob->data;
}
-inline
-const uint8_t*& accessBlobData(keymaster_blob_t* blob) {
+inline const uint8_t*& accessBlobData(keymaster_blob_t* blob) {
return blob->data;
}
-inline
-const size_t & accessBlobSize(const keymaster_blob_t* blob) {
+inline const size_t& accessBlobSize(const keymaster_blob_t* blob) {
return blob->data_length;
}
-inline
-size_t& accessBlobSize(keymaster_blob_t* blob) {
+inline size_t& accessBlobSize(keymaster_blob_t* blob) {
return blob->data_length;
}
@@ -276,8 +111,7 @@
* keymaster_key_blob_t. It manages its own memory, which makes avoiding memory leaks
* much easier.
*/
-template <typename BlobType>
-struct TKeymasterBlob : public BlobType {
+template <typename BlobType> struct TKeymasterBlob : public BlobType {
TKeymasterBlob() {
accessBlobData(this) = nullptr;
accessBlobSize(this) = 0;
@@ -286,37 +120,31 @@
TKeymasterBlob(const uint8_t* data, size_t size) {
accessBlobSize(this) = 0;
accessBlobData(this) = dup_buffer(data, size);
- if (accessBlobData(this))
- accessBlobSize(this) = size;
+ if (accessBlobData(this)) accessBlobSize(this) = size;
}
explicit TKeymasterBlob(size_t size) {
accessBlobSize(this) = 0;
accessBlobData(this) = new (std::nothrow) uint8_t[size];
- if (accessBlobData(this))
- accessBlobSize(this) = size;
+ if (accessBlobData(this)) accessBlobSize(this) = size;
}
explicit TKeymasterBlob(const BlobType& blob) {
accessBlobSize(this) = 0;
accessBlobData(this) = dup_buffer(accessBlobData(&blob), accessBlobSize(&blob));
- if (accessBlobData(this))
- accessBlobSize(this) = accessBlobSize(&blob);
+ if (accessBlobData(this)) accessBlobSize(this) = accessBlobSize(&blob);
}
- template<size_t N>
- explicit TKeymasterBlob(const uint8_t (&data)[N]) {
+ template <size_t N> explicit TKeymasterBlob(const uint8_t (&data)[N]) {
accessBlobSize(this) = 0;
accessBlobData(this) = dup_buffer(data, N);
- if (accessBlobData(this))
- accessBlobSize(this) = N;
+ if (accessBlobData(this)) accessBlobSize(this) = N;
}
TKeymasterBlob(const TKeymasterBlob& blob) {
accessBlobSize(this) = 0;
accessBlobData(this) = dup_buffer(accessBlobData(&blob), accessBlobSize(&blob));
- if (accessBlobData(this))
- accessBlobSize(this) = accessBlobSize(&blob);
+ if (accessBlobData(this)) accessBlobSize(this) = accessBlobSize(&blob);
}
TKeymasterBlob(TKeymasterBlob&& rhs) {
@@ -351,6 +179,8 @@
const uint8_t* begin() const { return accessBlobData(this); }
const uint8_t* end() const { return accessBlobData(this) + accessBlobSize(this); }
+ size_t size() const { return accessBlobSize(this); }
+
void Clear() {
if (accessBlobSize(this)) {
memset_s(const_cast<uint8_t*>(accessBlobData(this)), 0, accessBlobSize(this));
@@ -363,8 +193,7 @@
const uint8_t* Reset(size_t new_size) {
Clear();
accessBlobData(this) = new (std::nothrow) uint8_t[new_size];
- if (accessBlobData(this))
- accessBlobSize(this) = new_size;
+ if (accessBlobData(this)) accessBlobSize(this) = new_size;
return accessBlobData(this);
}
@@ -408,45 +237,9 @@
}
};
-struct Malloc_Delete {
- void operator()(void* p) { free(p); }
-};
-
-struct CertificateChainDelete {
- void operator()(keymaster_cert_chain_t* p) {
- if (!p)
- return;
- for (size_t i = 0; i < p->entry_count; ++i)
- delete[] p->entries[i].data;
- delete[] p->entries;
- delete p;
- }
-};
-
-typedef UniquePtr<keymaster_cert_chain_t, CertificateChainDelete> CertChainPtr;
-
keymaster_error_t EcKeySizeToCurve(uint32_t key_size_bits, keymaster_ec_curve_t* curve);
keymaster_error_t EcCurveToKeySize(keymaster_ec_curve_t curve, uint32_t* key_size_bits);
-template<typename T> struct remove_reference {typedef T type;};
-template<typename T> struct remove_reference<T&> {typedef T type;};
-template<typename T> struct remove_reference<T&&> {typedef T type;};
-template<typename T>
-using remove_reference_t = typename remove_reference<T>::type;
-template<typename T>
-remove_reference_t<T>&& move(T&& x) {
- return static_cast<remove_reference_t<T>&&>(x);
-}
-
-template<typename T>
-constexpr T&& forward(remove_reference_t<T>& x) {
- return static_cast<T&&>(x);
-}
-template<typename T>
-constexpr T&& forward(remove_reference_t<T>&& x) {
- return static_cast<T&&>(x);
-}
-
template <class F> class final_action {
public:
explicit final_action(F f) : f_(move(f)) {}
@@ -460,6 +253,116 @@
return final_action<F>(f);
}
-} // namespace keymaster
+struct CertificateChain : public keymaster_cert_chain_t {
+ CertificateChain() : keymaster_cert_chain_t{} {}
-#endif // SYSTEM_KEYMASTER_ANDROID_KEYMASTER_UTILS_H_
+ /**
+ * Create a chain with space allocated for `length` certificates. If allocation fails,
+ * `entries` will be null.
+ */
+ explicit CertificateChain(size_t length) : keymaster_cert_chain_t{} {
+ entries = new (std::nothrow) keymaster_blob_t[length];
+ if (!entries) return;
+ entry_count = length;
+ for (size_t i = 0; i < entry_count; ++i) {
+ entries[i] = {};
+ }
+ }
+
+ CertificateChain(CertificateChain&& other) : keymaster_cert_chain_t{} { *this = move(other); }
+
+ ~CertificateChain() { Clear(); }
+
+ CertificateChain& operator=(CertificateChain&& other) {
+ Clear();
+ (keymaster_cert_chain_t&)(*this) = (keymaster_cert_chain_t&)(other);
+ (keymaster_cert_chain_t&)(other) = {};
+ return *this;
+ }
+
+ /**
+ * Clone `other`. If anything fails, `entries` will be null.
+ */
+ static CertificateChain clone(const keymaster_cert_chain_t& other) {
+ CertificateChain retval;
+ retval.entry_count = other.entry_count;
+ retval.entries = new (std::nothrow) keymaster_blob_t[retval.entry_count];
+ if (!retval.entries) return {};
+
+ for (auto& entry : retval) {
+ entry = {};
+ }
+
+ for (size_t i = 0; i < retval.entry_count; ++i) {
+ retval.entries[i].data_length = other.entries[i].data_length;
+ retval.entries[i].data = new (std::nothrow) uint8_t[retval.entries[i].data_length];
+ if (!retval.entries[i].data) return {};
+
+ memcpy(const_cast<uint8_t*>(retval.entries[i].data), other.entries[i].data,
+ retval.entries[i].data_length);
+ }
+
+ return retval;
+ }
+
+ explicit operator bool() { return entries; }
+
+ keymaster_blob_t* begin() { return entries; }
+ const keymaster_blob_t* begin() const { return entries; }
+ keymaster_blob_t* end() { return entries + entry_count; }
+ const keymaster_blob_t* end() const { return entries + entry_count; }
+
+ // Insert the provided blob at the front of the chain. CertificateChain takes ownership of the
+ // contents of `new_entry`.
+ bool push_front(const keymaster_blob_t& new_entry) {
+ keymaster_blob_t* new_entries = new keymaster_blob_t[entry_count + 1];
+ if (!new_entries) return false;
+
+ new_entries[0] = new_entry;
+ for (size_t i = 1; i < entry_count + 1; ++i) {
+ new_entries[i] = entries[i - 1];
+ }
+
+ delete[] entries;
+ entries = new_entries;
+ ++entry_count;
+ return true;
+ }
+
+ keymaster_cert_chain_t release() {
+ keymaster_cert_chain_t retval = *this;
+ entries = nullptr;
+ entry_count = 0;
+ return retval;
+ }
+
+ void Clear() {
+ if (entries) {
+ for (size_t i = 0; i < entry_count; ++i) {
+ delete[] entries[i].data;
+ }
+ delete[] entries;
+ }
+ entry_count = 0;
+ entries = nullptr;
+ }
+};
+
+// Per RFC 5280 4.1.2.5, an undefined expiration (not-after) field should be set to GeneralizedTime
+// 999912312359559, which is 253402300799000 ms from Jan 1, 1970.
+constexpr int64_t kUndefinedExpirationDateTime = 253402300799000;
+
+// A confirmation token is the output of HMAC-SHA256. */
+constexpr size_t kConfirmationTokenSize = 32;
+
+// Defined in hardware/interfaces/confirmationui/1.0/IConfirmationResultCallback.hal
+constexpr const char kConfirmationTokenMessageTag[] = "confirmation token";
+
+constexpr size_t kConfirmationTokenMessageTagSize = sizeof(kConfirmationTokenMessageTag) - 1;
+
+// Maximum supported size for CBOR which includes prompt and
+// extra_data as returned by the ConfirmationUI. See
+// https://source.android.com/security/protected-confirmation/implementation
+constexpr size_t kConfirmationMessageMaxSize = 6144;
+
+} // namespace keymaster
diff --git a/include/keymaster/asymmetric_key_factory.h b/include/keymaster/asymmetric_key_factory.h
index eacc9a8..dab7916 100644
--- a/include/keymaster/asymmetric_key_factory.h
+++ b/include/keymaster/asymmetric_key_factory.h
@@ -14,23 +14,25 @@
* limitations under the License.
*/
-#ifndef SYSTEM_KEYMASTER_ASYMMETRIC_KEY_FACTORY_H_
-#define SYSTEM_KEYMASTER_ASYMMETRIC_KEY_FACTORY_H_
+#pragma once
#include <keymaster/key_factory.h>
namespace keymaster {
+class KeymasterContext;
+
/**
* Abstract base for KeyFactories that handle asymmetric keys.
*/
class AsymmetricKey;
class AsymmetricKeyFactory : public KeyFactory {
public:
+ explicit AsymmetricKeyFactory(const KeymasterContext& context) : context_(context) {}
keymaster_error_t LoadKey(KeymasterKeyBlob&& key_material,
const AuthorizationSet& additional_params,
- AuthorizationSet&& hw_enforced,
- AuthorizationSet&& sw_enforced,
+ AuthorizationSet&& hw_enforced, //
+ AuthorizationSet&& sw_enforced, //
UniquePtr<Key>* key) const override;
virtual keymaster_error_t CreateEmptyKey(AuthorizationSet&& hw_enforced,
@@ -40,10 +42,13 @@
virtual keymaster_algorithm_t keymaster_key_type() const = 0;
virtual int evp_key_type() const = 0;
- virtual const keymaster_key_format_t* SupportedImportFormats(size_t* format_count) const override;
- virtual const keymaster_key_format_t* SupportedExportFormats(size_t* format_count) const override;
+ virtual const keymaster_key_format_t*
+ SupportedImportFormats(size_t* format_count) const override;
+ virtual const keymaster_key_format_t*
+ SupportedExportFormats(size_t* format_count) const override;
+
+ protected:
+ const KeymasterContext& context_;
};
} // namespace keymaster
-
-#endif // SYSTEM_KEYMASTER_ASYMMETRIC_KEY_FACTORY_H_
diff --git a/include/keymaster/attestation_context.h b/include/keymaster/attestation_context.h
new file mode 100644
index 0000000..6d2887d
--- /dev/null
+++ b/include/keymaster/attestation_context.h
@@ -0,0 +1,105 @@
+/*
+ * Copyright 2020 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.
+ */
+
+#pragma once
+
+#include <keymaster/authorization_set.h>
+#include <keymaster/km_version.h>
+
+namespace keymaster {
+
+class Key;
+
+/**
+ * AttestationContext provides an abstract interface to the information needed
+ * to generate attestation certificates.
+ */
+class AttestationContext {
+ protected:
+ virtual ~AttestationContext() {}
+
+ public:
+ explicit AttestationContext(KmVersion version) : version_(version) {}
+
+ KmVersion GetKmVersion() const { return version_; }
+
+ /**
+ * Returns the security level (SW or TEE) of this keymaster implementation.
+ */
+ virtual keymaster_security_level_t GetSecurityLevel() const = 0;
+
+ /**
+ * Verify that the device IDs provided in `attestation_params` match the device's actual IDs and
+ * copy the verified IDs into `attestation`. If *any* of the IDs do not match or verification
+ * is not possible, return KM_ERROR_CANNOT_ATTEST_IDS. If device ID attestation is unsupported,
+ * ignore all arguments and return KM_ERROR_UNIMPLEMENTED. If ID attestation is supported and
+ * no ID mismatches are found, return KM_ERROR_OK;
+ */
+ virtual keymaster_error_t
+ VerifyAndCopyDeviceIds(const AuthorizationSet& /* attestation_params */,
+ AuthorizationSet* /* attestation */) const {
+ return KM_ERROR_UNIMPLEMENTED;
+ }
+
+ /**
+ * Generate the current unique ID. If unique IDs are not supported, set `error` to
+ * KM_ERROR_UNIMPLEMENTED.
+ */
+ virtual Buffer GenerateUniqueId(uint64_t /*creation_date_time*/,
+ const keymaster_blob_t& /*application_id*/,
+ bool /*reset_since_rotation*/, keymaster_error_t* error) const {
+ if (error) *error = KM_ERROR_UNIMPLEMENTED;
+ return {};
+ }
+
+ struct VerifiedBootParams {
+ keymaster_blob_t verified_boot_key;
+ keymaster_blob_t verified_boot_hash;
+ keymaster_verified_boot_t verified_boot_state;
+ bool device_locked;
+ };
+
+ /**
+ * Returns verified boot parameters for the Attestation Extension. For hardware-based
+ * implementations, these will be the values reported by the bootloader. By default, verified
+ * boot state is unknown, and KM_ERROR_UNIMPLEMENTED is returned.
+ *
+ * The AttestationContext retains ownership of the VerifiedBootParams.
+ */
+ virtual const VerifiedBootParams* GetVerifiedBootParams(keymaster_error_t* error) const {
+ *error = KM_ERROR_UNIMPLEMENTED;
+ return nullptr;
+ }
+
+ /**
+ * Return the factory attestation signing key. If not available, set `error` to
+ * KM_ERROR_UNIMPLEMENTED.
+ */
+ virtual KeymasterKeyBlob GetAttestationKey(keymaster_algorithm_t algorithm,
+ keymaster_error_t* error) const = 0;
+
+ /**
+ * Return the factory attestation signing key certificate chain. If not available, set `error`
+ * to KM_ERROR_UNIMPLEMENTED.
+ */
+ virtual CertificateChain GetAttestationChain(keymaster_algorithm_t algorithm,
+ keymaster_error_t* error) const = 0;
+
+ protected:
+ KmVersion version_;
+};
+
+} // namespace keymaster
diff --git a/include/keymaster/attestation_record.h b/include/keymaster/attestation_record.h
deleted file mode 100644
index f4857af..0000000
--- a/include/keymaster/attestation_record.h
+++ /dev/null
@@ -1,278 +0,0 @@
-/*
- * Copyright 2016 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_ATTESTATION_RECORD_H_
-#define SYSTEM_KEYMASTER_ATTESTATION_RECORD_H_
-
-#include <hardware/keymaster_defs.h>
-
-#include <keymaster/authorization_set.h>
-
-#include <openssl/asn1t.h>
-
-namespace keymaster {
-
-struct stack_st_ASN1_TYPE_Delete {
- void operator()(stack_st_ASN1_TYPE* p) { sk_ASN1_TYPE_free(p); }
-};
-
-struct ASN1_STRING_Delete {
- void operator()(ASN1_STRING* p) { ASN1_STRING_free(p); }
-};
-
-struct ASN1_TYPE_Delete {
- void operator()(ASN1_TYPE* p) { ASN1_TYPE_free(p); }
-};
-
-#define ASN1_INTEGER_SET STACK_OF(ASN1_INTEGER)
-
-typedef struct km_root_of_trust {
- ASN1_OCTET_STRING* verified_boot_key;
- ASN1_BOOLEAN* device_locked;
- ASN1_ENUMERATED* verified_boot_state;
- ASN1_OCTET_STRING* verified_boot_hash;
-} KM_ROOT_OF_TRUST;
-
-ASN1_SEQUENCE(KM_ROOT_OF_TRUST) = {
- ASN1_SIMPLE(KM_ROOT_OF_TRUST, verified_boot_key, ASN1_OCTET_STRING),
- ASN1_SIMPLE(KM_ROOT_OF_TRUST, device_locked, ASN1_BOOLEAN),
- ASN1_SIMPLE(KM_ROOT_OF_TRUST, verified_boot_state, ASN1_ENUMERATED),
- ASN1_SIMPLE(KM_ROOT_OF_TRUST, verified_boot_hash, ASN1_OCTET_STRING),
-} ASN1_SEQUENCE_END(KM_ROOT_OF_TRUST);
-DECLARE_ASN1_FUNCTIONS(KM_ROOT_OF_TRUST);
-
-typedef struct km_auth_list {
- ASN1_INTEGER_SET* purpose;
- ASN1_INTEGER* algorithm;
- ASN1_INTEGER* key_size;
- ASN1_INTEGER_SET* block_mode;
- ASN1_INTEGER_SET* digest;
- ASN1_INTEGER_SET* padding;
- ASN1_NULL* caller_nonce;
- ASN1_INTEGER* min_mac_length;
- ASN1_INTEGER_SET* kdf;
- ASN1_INTEGER* ec_curve;
- ASN1_INTEGER* rsa_public_exponent;
- ASN1_INTEGER* active_date_time;
- ASN1_INTEGER* origination_expire_date_time;
- ASN1_INTEGER* usage_expire_date_time;
- ASN1_NULL* no_auth_required;
- ASN1_INTEGER* user_auth_type;
- ASN1_INTEGER* auth_timeout;
- ASN1_NULL* allow_while_on_body;
- ASN1_NULL* trusted_confirmation_required;
- ASN1_NULL* unlocked_device_required;
- ASN1_NULL* all_applications;
- ASN1_OCTET_STRING* application_id;
- ASN1_INTEGER* creation_date_time;
- ASN1_INTEGER* origin;
- ASN1_NULL* rollback_resistance;
- ASN1_NULL* rollback_resistant;
- KM_ROOT_OF_TRUST* root_of_trust;
- ASN1_INTEGER* os_version;
- ASN1_INTEGER* os_patchlevel;
- ASN1_OCTET_STRING* attestation_application_id;
- ASN1_OCTET_STRING* attestation_id_brand;
- ASN1_OCTET_STRING* attestation_id_device;
- ASN1_OCTET_STRING* attestation_id_product;
- ASN1_OCTET_STRING* attestation_id_serial;
- ASN1_OCTET_STRING* attestation_id_imei;
- ASN1_OCTET_STRING* attestation_id_meid;
- ASN1_OCTET_STRING* attestation_id_manufacturer;
- ASN1_OCTET_STRING* attestation_id_model;
-} KM_AUTH_LIST;
-
-ASN1_SEQUENCE(KM_AUTH_LIST) = {
- ASN1_EXP_SET_OF_OPT(KM_AUTH_LIST, purpose, ASN1_INTEGER, TAG_PURPOSE.masked_tag()),
- ASN1_EXP_OPT(KM_AUTH_LIST, algorithm, ASN1_INTEGER, TAG_ALGORITHM.masked_tag()),
- ASN1_EXP_OPT(KM_AUTH_LIST, key_size, ASN1_INTEGER, TAG_KEY_SIZE.masked_tag()),
- ASN1_EXP_SET_OF_OPT(KM_AUTH_LIST, block_mode, ASN1_INTEGER, TAG_BLOCK_MODE.masked_tag()),
- ASN1_EXP_SET_OF_OPT(KM_AUTH_LIST, digest, ASN1_INTEGER, TAG_DIGEST.masked_tag()),
- ASN1_EXP_SET_OF_OPT(KM_AUTH_LIST, padding, ASN1_INTEGER, TAG_PADDING.masked_tag()),
- ASN1_EXP_OPT(KM_AUTH_LIST, caller_nonce, ASN1_NULL, TAG_CALLER_NONCE.masked_tag()),
- ASN1_EXP_OPT(KM_AUTH_LIST, min_mac_length, ASN1_INTEGER, TAG_MIN_MAC_LENGTH.masked_tag()),
- ASN1_EXP_SET_OF_OPT(KM_AUTH_LIST, kdf, ASN1_INTEGER, TAG_KDF.masked_tag()),
- ASN1_EXP_OPT(KM_AUTH_LIST, ec_curve, ASN1_INTEGER, TAG_EC_CURVE.masked_tag()),
- ASN1_EXP_OPT(KM_AUTH_LIST, rsa_public_exponent, ASN1_INTEGER,
- TAG_RSA_PUBLIC_EXPONENT.masked_tag()),
- ASN1_EXP_OPT(KM_AUTH_LIST, active_date_time, ASN1_INTEGER, TAG_ACTIVE_DATETIME.masked_tag()),
- ASN1_EXP_OPT(KM_AUTH_LIST, origination_expire_date_time, ASN1_INTEGER,
- TAG_ORIGINATION_EXPIRE_DATETIME.masked_tag()),
- ASN1_EXP_OPT(KM_AUTH_LIST, usage_expire_date_time, ASN1_INTEGER,
- TAG_USAGE_EXPIRE_DATETIME.masked_tag()),
- ASN1_EXP_OPT(KM_AUTH_LIST, no_auth_required, ASN1_NULL, TAG_NO_AUTH_REQUIRED.masked_tag()),
- ASN1_EXP_OPT(KM_AUTH_LIST, user_auth_type, ASN1_INTEGER, TAG_USER_AUTH_TYPE.masked_tag()),
- ASN1_EXP_OPT(KM_AUTH_LIST, auth_timeout, ASN1_INTEGER, TAG_AUTH_TIMEOUT.masked_tag()),
- ASN1_EXP_OPT(KM_AUTH_LIST, allow_while_on_body, ASN1_NULL,
- TAG_ALLOW_WHILE_ON_BODY.masked_tag()),
- ASN1_EXP_OPT(KM_AUTH_LIST, unlocked_device_required, ASN1_NULL,
- TAG_UNLOCKED_DEVICE_REQUIRED.masked_tag()),
- ASN1_EXP_OPT(KM_AUTH_LIST, all_applications, ASN1_NULL, TAG_ALL_APPLICATIONS.masked_tag()),
- ASN1_EXP_OPT(KM_AUTH_LIST, application_id, ASN1_OCTET_STRING, TAG_APPLICATION_ID.masked_tag()),
- ASN1_EXP_OPT(KM_AUTH_LIST, creation_date_time, ASN1_INTEGER,
- TAG_CREATION_DATETIME.masked_tag()),
- ASN1_EXP_OPT(KM_AUTH_LIST, origin, ASN1_INTEGER, TAG_ORIGIN.masked_tag()),
- ASN1_EXP_OPT(KM_AUTH_LIST, rollback_resistance, ASN1_NULL,
- TAG_ROLLBACK_RESISTANCE.masked_tag()),
- ASN1_EXP_OPT(KM_AUTH_LIST, rollback_resistant, ASN1_NULL, TAG_ROLLBACK_RESISTANT.masked_tag()),
- ASN1_EXP_OPT(KM_AUTH_LIST, root_of_trust, KM_ROOT_OF_TRUST, TAG_ROOT_OF_TRUST.masked_tag()),
- ASN1_EXP_OPT(KM_AUTH_LIST, os_version, ASN1_INTEGER, TAG_OS_VERSION.masked_tag()),
- ASN1_EXP_OPT(KM_AUTH_LIST, os_patchlevel, ASN1_INTEGER, TAG_OS_PATCHLEVEL.masked_tag()),
- ASN1_EXP_OPT(KM_AUTH_LIST, attestation_application_id, ASN1_OCTET_STRING,
- TAG_ATTESTATION_APPLICATION_ID.masked_tag()),
- ASN1_EXP_OPT(KM_AUTH_LIST, attestation_id_brand, ASN1_OCTET_STRING,
- TAG_ATTESTATION_ID_BRAND.masked_tag()),
- ASN1_EXP_OPT(KM_AUTH_LIST, attestation_id_device, ASN1_OCTET_STRING,
- TAG_ATTESTATION_ID_DEVICE.masked_tag()),
- ASN1_EXP_OPT(KM_AUTH_LIST, attestation_id_product, ASN1_OCTET_STRING,
- TAG_ATTESTATION_ID_PRODUCT.masked_tag()),
- ASN1_EXP_OPT(KM_AUTH_LIST, attestation_id_serial, ASN1_OCTET_STRING,
- TAG_ATTESTATION_ID_SERIAL.masked_tag()),
- ASN1_EXP_OPT(KM_AUTH_LIST, attestation_id_imei, ASN1_OCTET_STRING,
- TAG_ATTESTATION_ID_IMEI.masked_tag()),
- ASN1_EXP_OPT(KM_AUTH_LIST, attestation_id_meid, ASN1_OCTET_STRING,
- TAG_ATTESTATION_ID_MEID.masked_tag()),
- ASN1_EXP_OPT(KM_AUTH_LIST, attestation_id_manufacturer, ASN1_OCTET_STRING,
- TAG_ATTESTATION_ID_MANUFACTURER.masked_tag()),
- ASN1_EXP_OPT(KM_AUTH_LIST, attestation_id_model, ASN1_OCTET_STRING,
- TAG_ATTESTATION_ID_MODEL.masked_tag()),
-} ASN1_SEQUENCE_END(KM_AUTH_LIST);
-DECLARE_ASN1_FUNCTIONS(KM_AUTH_LIST);
-
-typedef struct km_key_description {
- ASN1_INTEGER* attestation_version;
- ASN1_ENUMERATED* attestation_security_level;
- ASN1_INTEGER* keymaster_version;
- ASN1_ENUMERATED* keymaster_security_level;
- ASN1_OCTET_STRING* attestation_challenge;
- KM_AUTH_LIST* software_enforced;
- KM_AUTH_LIST* tee_enforced;
- ASN1_INTEGER* unique_id;
-} KM_KEY_DESCRIPTION;
-
-ASN1_SEQUENCE(KM_KEY_DESCRIPTION) = {
- ASN1_SIMPLE(KM_KEY_DESCRIPTION, attestation_version, ASN1_INTEGER),
- ASN1_SIMPLE(KM_KEY_DESCRIPTION, attestation_security_level, ASN1_ENUMERATED),
- ASN1_SIMPLE(KM_KEY_DESCRIPTION, keymaster_version, ASN1_INTEGER),
- ASN1_SIMPLE(KM_KEY_DESCRIPTION, keymaster_security_level, ASN1_ENUMERATED),
- ASN1_SIMPLE(KM_KEY_DESCRIPTION, attestation_challenge, ASN1_OCTET_STRING),
- ASN1_SIMPLE(KM_KEY_DESCRIPTION, unique_id, ASN1_OCTET_STRING),
- ASN1_SIMPLE(KM_KEY_DESCRIPTION, software_enforced, KM_AUTH_LIST),
- ASN1_SIMPLE(KM_KEY_DESCRIPTION, tee_enforced, KM_AUTH_LIST),
-} ASN1_SEQUENCE_END(KM_KEY_DESCRIPTION);
-DECLARE_ASN1_FUNCTIONS(KM_KEY_DESCRIPTION);
-
-class AttestationRecordContext {
- protected:
- virtual ~AttestationRecordContext() {}
-
- public:
- /**
- * Returns the security level (SW or TEE) of this keymaster implementation.
- */
- virtual keymaster_security_level_t GetSecurityLevel() const {
- return KM_SECURITY_LEVEL_SOFTWARE;
- }
-
- /**
- * Verify that the device IDs provided in the attestation_params match the device's actual IDs
- * and copy them to attestation. If *any* of the IDs do not match or verification is not
- * possible, return KM_ERROR_CANNOT_ATTEST_IDS. If *all* IDs provided are successfully verified
- * or no IDs were provided, return KM_ERROR_OK.
- *
- * If you do not support device ID attestation, ignore all arguments and return
- * KM_ERROR_UNIMPLEMENTED.
- */
- virtual keymaster_error_t
- VerifyAndCopyDeviceIds(const AuthorizationSet& /* attestation_params */,
- AuthorizationSet* /* attestation */) const {
- return KM_ERROR_UNIMPLEMENTED;
- }
- /**
- * Generate the current unique ID.
- */
- virtual keymaster_error_t GenerateUniqueId(uint64_t /*creation_date_time*/,
- const keymaster_blob_t& /*application_id*/,
- bool /*reset_since_rotation*/,
- Buffer* /*unique_id*/) const {
- return KM_ERROR_UNIMPLEMENTED;
- }
-
- /**
- * Returns verified boot parameters for the Attestation Extension. For hardware-based
- * implementations, these will be the values reported by the bootloader. By default, verified
- * boot state is unknown, and KM_ERROR_UNIMPLEMENTED is returned.
- */
- virtual keymaster_error_t
- GetVerifiedBootParams(keymaster_blob_t* /* verified_boot_key */,
- keymaster_blob_t* /* verified_boot_hash */,
- keymaster_verified_boot_t* /* verified_boot_state */,
- bool* /* device_locked */) const {
- return KM_ERROR_UNIMPLEMENTED;
- }
-};
-
-/**
- * The OID for Android attestation records. For the curious, it breaks down as follows:
- *
- * 1 = ISO
- * 3 = org
- * 6 = DoD (Huh? OIDs are weird.)
- * 1 = IANA
- * 4 = Private
- * 1 = Enterprises
- * 11129 = Google
- * 2 = Google security
- * 1 = certificate extension
- * 17 = Android attestation extension.
- */
-static const char kAttestionRecordOid[] = "1.3.6.1.4.1.11129.2.1.17";
-
-keymaster_error_t build_attestation_record(const AuthorizationSet& attestation_params,
- AuthorizationSet software_enforced,
- AuthorizationSet tee_enforced,
- const AttestationRecordContext& context,
- UniquePtr<uint8_t[]>* asn1_key_desc,
- size_t* asn1_key_desc_len);
-
-/**
- * Helper functions for attestation record tests. Caller takes ownership of
- * |attestation_challenge->data| and |unique_id->data|, deallocate using delete[].
- */
-keymaster_error_t parse_attestation_record(const uint8_t* asn1_key_desc, size_t asn1_key_desc_len,
- uint32_t* attestation_version, //
- keymaster_security_level_t* attestation_security_level,
- uint32_t* keymaster_version,
- keymaster_security_level_t* keymaster_security_level,
- keymaster_blob_t* attestation_challenge,
- AuthorizationSet* software_enforced,
- AuthorizationSet* tee_enforced,
- keymaster_blob_t* unique_id);
-
-/**
- * Caller takes ownership of |verified_boot_key->data|, deallocate using delete[].
- */
-keymaster_error_t parse_root_of_trust(const uint8_t* asn1_key_desc, size_t asn1_key_desc_len,
- keymaster_blob_t* verified_boot_key,
- keymaster_verified_boot_t* verified_boot_state,
- bool* device_locked);
-
-keymaster_error_t build_auth_list(const AuthorizationSet& auth_list, KM_AUTH_LIST* record);
-
-keymaster_error_t extract_auth_list(const KM_AUTH_LIST* record, AuthorizationSet* auth_list);
-} // namespace keymaster
-
-#endif // SYSTEM_KEYMASTER_ATTESTATION_RECORD_H_
diff --git a/include/keymaster/authorization_set.h b/include/keymaster/authorization_set.h
index 11ffc30..5eebadf 100644
--- a/include/keymaster/authorization_set.h
+++ b/include/keymaster/authorization_set.h
@@ -14,8 +14,7 @@
* limitations under the License.
*/
-#ifndef SYSTEM_KEYMASTER_AUTHORIZATION_SET_H_
-#define SYSTEM_KEYMASTER_AUTHORIZATION_SET_H_
+#pragma once
#include <keymaster/UniquePtr.h>
@@ -82,6 +81,9 @@
explicit AuthorizationSet(/* NOT const */ AuthorizationSetBuilder& builder);
// Copy constructor.
+ // A copy constructor normal should call a base class copy constructor,
+ // but Serializable is special without copy constructor.
+ // NOLINTNEXTLINE(bugprone-copy-constructor-init)
AuthorizationSet(const AuthorizationSet& set)
: Serializable(), elems_capacity_(0), indirect_data_(nullptr), indirect_data_size_(0),
indirect_data_capacity_(0), error_(OK) {
@@ -92,12 +94,11 @@
}
// Move constructor.
- AuthorizationSet(AuthorizationSet&& set) : Serializable() {
- MoveFrom(set);
- }
+ AuthorizationSet(AuthorizationSet&& set) : Serializable() { MoveFrom(set); }
// Copy assignment.
AuthorizationSet& operator=(const AuthorizationSet& set) {
+ if (&set == this) return *this;
Reinitialize(set.elems_, set.elems_size_);
error_ = set.error_;
return *this;
@@ -225,9 +226,7 @@
/**
* Returns true if the set contains at least one instance of \p tag
*/
- bool Contains(keymaster_tag_t tag) const {
- return find(tag) != -1;
- }
+ bool Contains(keymaster_tag_t tag) const { return find(tag) != -1; }
/**
* Returns the number of \p tag entries.
@@ -253,8 +252,7 @@
/**
* Returns true if the set contains the specified tag and value.
*/
- template <keymaster_tag_t Tag>
- bool Contains(TypedTag<KM_UINT, Tag> tag, uint32_t val) const {
+ template <keymaster_tag_t Tag> bool Contains(TypedTag<KM_UINT, Tag> tag, uint32_t val) const {
return ContainsIntValue(tag, val);
}
@@ -322,8 +320,7 @@
*/
template <keymaster_tag_t Tag, typename T>
bool GetTagValue(TypedEnumTag<KM_ENUM_REP, Tag, T> tag, T* val) const {
- if (GetTagCount(tag) != 1)
- return false;
+ if (GetTagCount(tag) != 1) return false;
return GetTagValueEnumRep(tag, 0, reinterpret_cast<uint32_t*>(val));
}
@@ -540,6 +537,10 @@
return Authorization(TAG_DIGEST, digest);
}
+ AuthorizationSetBuilder& OaepMgfDigest(keymaster_digest_t digest) {
+ return Authorization(TAG_RSA_OAEP_MGF_DIGEST, digest);
+ }
+
AuthorizationSetBuilder& BlockMode(keymaster_block_mode_t mode) {
return Authorization(TAG_BLOCK_MODE, mode);
}
@@ -638,14 +639,14 @@
class AuthProxyIterator {
constexpr static size_t invalid = ~size_t(0);
-public:
- AuthProxyIterator()
- : pos_(invalid), auth_set1_(nullptr), auth_set2_(nullptr) {}
+
+ public:
+ AuthProxyIterator() : pos_(invalid), auth_set1_(nullptr), auth_set2_(nullptr) {}
AuthProxyIterator(const AuthorizationSet& auth_set1, const AuthorizationSet& auth_set2)
: pos_(0), auth_set1_(&auth_set1), auth_set2_(&auth_set2) {}
AuthProxyIterator(const AuthProxyIterator& rhs)
: pos_(rhs.pos_), auth_set1_(rhs.auth_set1_), auth_set2_(rhs.auth_set2_) {}
- ~AuthProxyIterator() {};
+ ~AuthProxyIterator(){};
AuthProxyIterator& operator=(const AuthProxyIterator& rhs) {
if (this != &rhs) {
pos_ = rhs.pos_;
@@ -669,25 +670,23 @@
return (*auth_set2_)[pos_ - auth_set1_->size()];
}
}
- AuthProxyIterator operator++(int) {
+ const AuthProxyIterator operator++(int) {
AuthProxyIterator dummy(*this);
++(*this);
return dummy;
}
- const keymaster_key_param_t* operator->() const {
- return &(*(*this));
- }
+ const keymaster_key_param_t* operator->() const { return &(*(*this)); }
bool operator==(const AuthProxyIterator& rhs) {
if (pos_ == rhs.pos_) {
return pos_ == invalid ||
- (auth_set1_ == rhs.auth_set1_ && auth_set2_ == rhs.auth_set2_);
- } else return false;
+ (auth_set1_ == rhs.auth_set1_ && auth_set2_ == rhs.auth_set2_);
+ } else
+ return false;
}
- bool operator!=(const AuthProxyIterator& rhs) {
- return !operator==(rhs);
- }
-private:
+ bool operator!=(const AuthProxyIterator& rhs) { return !operator==(rhs); }
+
+ private:
size_t pos_;
const AuthorizationSet* auth_set1_;
const AuthorizationSet* auth_set2_;
@@ -708,10 +707,13 @@
sw_enforced_.GetTagValue(forward<ARGS>(args)...);
}
- AuthProxyIterator begin() const {
- return AuthProxyIterator(hw_enforced_, sw_enforced_);
+ template <typename... ARGS> bool GetTagCount(ARGS&&... args) const {
+ return hw_enforced_.GetTagCount(forward<ARGS>(args)...) ||
+ sw_enforced_.GetTagCount(forward<ARGS>(args)...);
}
+ AuthProxyIterator begin() const { return AuthProxyIterator(hw_enforced_, sw_enforced_); }
+
AuthProxyIterator end() const { return AuthProxyIterator(); }
size_t size() const { return hw_enforced_.size() + sw_enforced_.size(); }
@@ -730,5 +732,3 @@
};
} // namespace keymaster
-
-#endif // SYSTEM_KEYMASTER_KEY_AUTHORIZATION_SET_H_
diff --git a/include/keymaster/contexts/keymaster0_passthrough_context.h b/include/keymaster/contexts/keymaster0_passthrough_context.h
deleted file mode 100644
index cad9df6..0000000
--- a/include/keymaster/contexts/keymaster0_passthrough_context.h
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
-**
-** Copyright 2017, 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 CONTEXTS_KEYMASTER0_PASSTHROUGH_CONTEXT_H_
-#define CONTEXTS_KEYMASTER0_PASSTHROUGH_CONTEXT_H_
-
-#include <hardware/keymaster0.h>
-
-#include <keymaster/contexts/pure_soft_keymaster_context.h>
-#include <keymaster/legacy_support/ec_keymaster0_key.h>
-#include <keymaster/legacy_support/keymaster0_engine.h>
-#include <keymaster/legacy_support/rsa_keymaster0_key.h>
-
-namespace keymaster {
-
-class Keymaster0PassthroughContext : public PureSoftKeymasterContext {
- public:
- explicit Keymaster0PassthroughContext(keymaster0_device_t* dev) : PureSoftKeymasterContext() {
- km0_engine_.reset(new Keymaster0Engine(dev));
- rsa_factory_.reset(new RsaKeymaster0KeyFactory(this, km0_engine_.get()));
- ec_factory_.reset(new EcdsaKeymaster0KeyFactory(this, km0_engine_.get()));
- }
-
- private:
- UniquePtr<Keymaster0Engine> km0_engine_;
-};
-
-} // namespace keymaster
-
-#endif // CONTEXTS_KEYMASTER0_PASSTHROUGH_CONTEXT_H_
diff --git a/include/keymaster/contexts/keymaster1_passthrough_context.h b/include/keymaster/contexts/keymaster1_passthrough_context.h
index 820e01c..e5bd16b 100644
--- a/include/keymaster/contexts/keymaster1_passthrough_context.h
+++ b/include/keymaster/contexts/keymaster1_passthrough_context.h
@@ -23,7 +23,7 @@
#include <hardware/keymaster1.h>
#include <hardware/keymaster_defs.h>
-#include <keymaster/attestation_record.h>
+#include <keymaster/contexts/soft_attestation_context.h>
#include <keymaster/keymaster_context.h>
#include <keymaster/km_openssl/software_random_source.h>
#include <keymaster/legacy_support/keymaster1_engine.h>
@@ -34,11 +34,13 @@
namespace keymaster {
class Keymaster1PassthroughContext : public KeymasterContext,
- AttestationRecordContext,
+ public SoftAttestationContext,
public SoftwareRandomSource,
public SoftwareKeyBlobMaker {
public:
- explicit Keymaster1PassthroughContext(keymaster1_device_t* dev);
+ Keymaster1PassthroughContext(KmVersion version, keymaster1_device_t* dev);
+
+ KmVersion GetKmVersion() const override { return AttestationContext::GetKmVersion(); }
/**
* Sets the system version as reported by the system *itself*. This is used to verify that the
@@ -106,8 +108,18 @@
*/
KeymasterEnforcement* enforcement_policy() override;
- keymaster_error_t GenerateAttestation(const Key& key, const AuthorizationSet& attest_params,
- CertChainPtr* cert_chain) const override;
+ CertificateChain GenerateAttestation(const Key& key, //
+ const AuthorizationSet& attest_params,
+ UniquePtr<Key> attest_key,
+ const KeymasterBlob& issuer_subject,
+ keymaster_error_t* error) const override;
+ CertificateChain GenerateSelfSignedCertificate(const Key& /* key */,
+ const AuthorizationSet& /* cert_params */,
+ bool /* fake_signature */,
+ keymaster_error_t* error) const override {
+ *error = KM_ERROR_UNIMPLEMENTED;
+ return {};
+ }
keymaster_error_t CreateKeyBlob(const AuthorizationSet& key_description,
const keymaster_key_origin_t origin,
diff --git a/include/keymaster/contexts/keymaster2_passthrough_context.h b/include/keymaster/contexts/keymaster2_passthrough_context.h
index 8b889f3..37592f8 100644
--- a/include/keymaster/contexts/keymaster2_passthrough_context.h
+++ b/include/keymaster/contexts/keymaster2_passthrough_context.h
@@ -24,6 +24,7 @@
#include <hardware/keymaster_defs.h>
#include <keymaster/keymaster_context.h>
+#include <keymaster/km_version.h>
#include <keymaster/legacy_support/keymaster_passthrough_engine.h>
#include <keymaster/legacy_support/keymaster_passthrough_key.h>
@@ -31,7 +32,9 @@
class Keymaster2PassthroughContext : public KeymasterContext {
public:
- explicit Keymaster2PassthroughContext(keymaster2_device_t* dev);
+ explicit Keymaster2PassthroughContext(KmVersion version, keymaster2_device_t* dev);
+
+ KmVersion GetKmVersion() const override { return version_; }
/**
* Sets the system version as reported by the system *itself*. This is used to verify that the
@@ -99,8 +102,18 @@
*/
KeymasterEnforcement* enforcement_policy() override;
- keymaster_error_t GenerateAttestation(const Key& key, const AuthorizationSet& attest_params,
- CertChainPtr* cert_chain) const override;
+ CertificateChain GenerateAttestation(const Key& key, //
+ const AuthorizationSet& attest_params,
+ UniquePtr<Key> attest_key,
+ const KeymasterBlob& issuer_subject,
+ keymaster_error_t* error) const override;
+ CertificateChain GenerateSelfSignedCertificate(const Key& /* key */,
+ const AuthorizationSet& /* cert_params */,
+ bool /* fake_signature */,
+ keymaster_error_t* error) const override {
+ *error = KM_ERROR_UNIMPLEMENTED;
+ return {};
+ }
keymaster_error_t
UnwrapKey(const KeymasterKeyBlob& wrapped_key_blob, const KeymasterKeyBlob& wrapping_key_blob,
@@ -115,6 +128,7 @@
UniquePtr<KeymasterPassthroughEngine> engine_;
uint32_t os_version_;
uint32_t os_patchlevel_;
+ const KmVersion version_;
};
} // namespace keymaster
diff --git a/include/keymaster/contexts/pure_soft_keymaster_context.h b/include/keymaster/contexts/pure_soft_keymaster_context.h
index a1951a0..2f7f098 100644
--- a/include/keymaster/contexts/pure_soft_keymaster_context.h
+++ b/include/keymaster/contexts/pure_soft_keymaster_context.h
@@ -14,19 +14,21 @@
* limitations under the License.
*/
-#ifndef SYSTEM_KEYMASTER_PURE_SOFT_KEYMASTER_CONTEXT_H_
-#define SYSTEM_KEYMASTER_PURE_SOFT_KEYMASTER_CONTEXT_H_
-
+#pragma once
#include <memory>
#include <string>
+#include <keymaster/attestation_context.h>
+#include <keymaster/contexts/pure_soft_remote_provisioning_context.h>
+#include <keymaster/contexts/soft_attestation_context.h>
#include <keymaster/keymaster_context.h>
-#include <keymaster/attestation_record.h>
-#include <keymaster/km_openssl/software_random_source.h>
+#include <keymaster/km_openssl/attestation_record.h>
#include <keymaster/km_openssl/soft_keymaster_enforcement.h>
-#include <keymaster/soft_key_factory.h>
+#include <keymaster/km_openssl/software_random_source.h>
+#include <keymaster/pure_soft_secure_key_storage.h>
#include <keymaster/random_source.h>
+#include <keymaster/soft_key_factory.h>
namespace keymaster {
@@ -38,16 +40,18 @@
/**
* SoftKeymasterContext provides the context for a non-secure implementation of AndroidKeymaster.
*/
-class PureSoftKeymasterContext: public KeymasterContext,
- protected SoftwareKeyBlobMaker,
- AttestationRecordContext,
- SoftwareRandomSource {
+class PureSoftKeymasterContext : public KeymasterContext,
+ protected SoftwareKeyBlobMaker,
+ public SoftAttestationContext,
+ SoftwareRandomSource {
public:
// Security level must only be used for testing.
explicit PureSoftKeymasterContext(
- keymaster_security_level_t security_level = KM_SECURITY_LEVEL_SOFTWARE);
+ KmVersion version, keymaster_security_level_t security_level = KM_SECURITY_LEVEL_SOFTWARE);
~PureSoftKeymasterContext() override;
+ KmVersion GetKmVersion() const override { return AttestationContext::GetKmVersion(); }
+
/*********************************************************************************************
* Implement KeymasterContext
*/
@@ -67,17 +71,47 @@
keymaster_error_t DeleteKey(const KeymasterKeyBlob& blob) const override;
keymaster_error_t DeleteAllKeys() const override;
keymaster_error_t AddRngEntropy(const uint8_t* buf, size_t length) const override;
-
- keymaster_error_t GenerateAttestation(const Key& key,
- const AuthorizationSet& attest_params,
- CertChainPtr* cert_chain) const override;
-
-
+ CertificateChain GenerateAttestation(const Key& key, const AuthorizationSet& attest_params,
+ UniquePtr<Key> attest_key,
+ const KeymasterBlob& issuer_subject,
+ keymaster_error_t* error) const override;
+ CertificateChain GenerateSelfSignedCertificate(const Key& key,
+ const AuthorizationSet& cert_params,
+ bool fake_signature,
+ keymaster_error_t* error) const override;
KeymasterEnforcement* enforcement_policy() override {
// SoftKeymaster does no enforcement; it's all done by Keystore.
return &soft_keymaster_enforcement_;
}
+ SecureKeyStorage* secure_key_storage() override { return pure_soft_secure_key_storage_.get(); }
+
+ RemoteProvisioningContext* GetRemoteProvisioningContext() const override {
+ return pure_soft_remote_provisioning_context_.get();
+ }
+
+ keymaster_error_t SetVendorPatchlevel(uint32_t vendor_patchlevel) override {
+ if (vendor_patchlevel_.has_value() && vendor_patchlevel != vendor_patchlevel_.value()) {
+ // Can't set patchlevel to a different value.
+ return KM_ERROR_INVALID_ARGUMENT;
+ }
+ vendor_patchlevel_ = vendor_patchlevel;
+ return KM_ERROR_OK;
+ }
+
+ keymaster_error_t SetBootPatchlevel(uint32_t boot_patchlevel) override {
+ if (boot_patchlevel_.has_value() && boot_patchlevel != boot_patchlevel_.value()) {
+ // Can't set patchlevel to a different value.
+ return KM_ERROR_INVALID_ARGUMENT;
+ }
+ boot_patchlevel_ = boot_patchlevel;
+ return KM_ERROR_OK;
+ }
+
+ std::optional<uint32_t> GetVendorPatchlevel() const override { return vendor_patchlevel_; }
+
+ std::optional<uint32_t> GetBootPatchlevel() const override { return boot_patchlevel_; }
+
/*********************************************************************************************
* Implement SoftwareKeyBlobMaker
*/
@@ -93,13 +127,10 @@
KeymasterKeyBlob* wrapped_key_material) const override;
/*********************************************************************************************
- * Implement AttestationRecordContext
+ * Implement AttestationContext
*/
- keymaster_error_t GetVerifiedBootParams(keymaster_blob_t* verified_boot_key,
- keymaster_blob_t* verified_boot_hash,
- keymaster_verified_boot_t* verified_boot_state,
- bool* device_locked) const override;
+ const VerifiedBootParams* GetVerifiedBootParams(keymaster_error_t* error) const override;
keymaster_security_level_t GetSecurityLevel() const override { return security_level_; }
@@ -111,10 +142,12 @@
std::unique_ptr<KeyFactory> hmac_factory_;
uint32_t os_version_;
uint32_t os_patchlevel_;
+ std::optional<uint32_t> vendor_patchlevel_;
+ std::optional<uint32_t> boot_patchlevel_;
SoftKeymasterEnforcement soft_keymaster_enforcement_;
- keymaster_security_level_t security_level_;
+ const keymaster_security_level_t security_level_;
+ std::unique_ptr<SecureKeyStorage> pure_soft_secure_key_storage_;
+ std::unique_ptr<RemoteProvisioningContext> pure_soft_remote_provisioning_context_;
};
} // namespace keymaster
-
-#endif // SYSTEM_KEYMASTER_PURE_SOFT_KEYMASTER_CONTEXT_H_
diff --git a/include/keymaster/contexts/pure_soft_remote_provisioning_context.h b/include/keymaster/contexts/pure_soft_remote_provisioning_context.h
new file mode 100644
index 0000000..307795b
--- /dev/null
+++ b/include/keymaster/contexts/pure_soft_remote_provisioning_context.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2021 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.
+ */
+
+#pragma once
+
+#include <keymaster/remote_provisioning_context.h>
+
+#include <cppbor.h>
+
+namespace keymaster {
+
+/**
+ * SoftKeymasterContext provides the context for a non-secure implementation of AndroidKeymaster.
+ */
+class PureSoftRemoteProvisioningContext : public RemoteProvisioningContext {
+ public:
+ PureSoftRemoteProvisioningContext();
+ ~PureSoftRemoteProvisioningContext() override;
+ std::vector<uint8_t> DeriveBytesFromHbk(const std::string& context,
+ size_t numBytes) const override;
+ std::unique_ptr<cppbor::Map> CreateDeviceInfo() const override;
+ std::pair<std::vector<uint8_t>, cppbor::Array> GenerateBcc(bool testMode) const override;
+ std::optional<cppcose::HmacSha256>
+ GenerateHmacSha256(const cppcose::bytevec& input) const override;
+};
+
+} // namespace keymaster
diff --git a/contexts/soft_attestation_cert.h b/include/keymaster/contexts/soft_attestation_cert.h
similarity index 85%
rename from contexts/soft_attestation_cert.h
rename to include/keymaster/contexts/soft_attestation_cert.h
index a508ff8..6273c63 100644
--- a/contexts/soft_attestation_cert.h
+++ b/include/keymaster/contexts/soft_attestation_cert.h
@@ -19,13 +19,13 @@
#define SOFTWARE_CONTEXT_SOFT_ATTESTATION_CERT_H_
#include <hardware/keymaster_defs.h>
+#include <keymaster/android_keymaster_utils.h>
namespace keymaster {
const keymaster_key_blob_t* getAttestationKey(keymaster_algorithm_t algorithm,
keymaster_error_t* error);
-const keymaster_cert_chain_t* getAttestationChain(keymaster_algorithm_t algorithm,
- keymaster_error_t* error);
+CertificateChain getAttestationChain(keymaster_algorithm_t algorithm, keymaster_error_t* error);
-}
+} // namespace keymaster
#endif // SOFTWARE_CONTEXT_SOFT_ATTESTATION_CERT_H_
diff --git a/include/keymaster/contexts/soft_attestation_context.h b/include/keymaster/contexts/soft_attestation_context.h
new file mode 100644
index 0000000..5c8db61
--- /dev/null
+++ b/include/keymaster/contexts/soft_attestation_context.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2020 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.
+ */
+
+#pragma once
+
+#include <keymaster/attestation_context.h>
+
+#include <keymaster/contexts/soft_attestation_cert.h>
+
+namespace keymaster {
+
+class SoftAttestationContext : public AttestationContext {
+ public:
+ explicit SoftAttestationContext(KmVersion version) : AttestationContext(version) {}
+
+ keymaster_security_level_t GetSecurityLevel() const override {
+ return KM_SECURITY_LEVEL_SOFTWARE;
+ }
+
+ const VerifiedBootParams* GetVerifiedBootParams(keymaster_error_t* error) const override;
+
+ KeymasterKeyBlob GetAttestationKey(keymaster_algorithm_t algorithm,
+ keymaster_error_t* error) const override {
+ return KeymasterKeyBlob(*getAttestationKey(algorithm, error));
+ }
+
+ CertificateChain GetAttestationChain(keymaster_algorithm_t algorithm,
+ keymaster_error_t* error) const override {
+ return getAttestationChain(algorithm, error);
+ }
+};
+
+} // namespace keymaster
diff --git a/include/keymaster/contexts/soft_keymaster_context.h b/include/keymaster/contexts/soft_keymaster_context.h
index 588e3db..aae0542 100644
--- a/include/keymaster/contexts/soft_keymaster_context.h
+++ b/include/keymaster/contexts/soft_keymaster_context.h
@@ -14,44 +14,42 @@
* limitations under the License.
*/
-#ifndef SYSTEM_KEYMASTER_SOFT_KEYMASTER_CONTEXT_H_
-#define SYSTEM_KEYMASTER_SOFT_KEYMASTER_CONTEXT_H_
+#pragma once
#include <memory>
#include <string>
#include <openssl/evp.h>
-#include <hardware/keymaster0.h>
#include <hardware/keymaster1.h>
-#include <keymaster/attestation_record.h>
+#include <keymaster/attestation_context.h>
+#include <keymaster/contexts/soft_attestation_context.h>
#include <keymaster/keymaster_context.h>
#include <keymaster/km_openssl/software_random_source.h>
-#include <keymaster/soft_key_factory.h>
#include <keymaster/random_source.h>
+#include <keymaster/soft_key_factory.h>
namespace keymaster {
class SoftKeymasterKeyRegistrations;
-class Keymaster0Engine;
class Keymaster1Engine;
class Key;
/**
- * SoftKeymasterContext provides the context for a non-secure implementation of AndroidKeymaster.
+ * SoftKeymasterContext provides the context for a non-secure implementation of AndroidKeymaster
+ * that can wrap a Keymaster0 implementation or an incomplete Keymaster1 implementation (one that
+ * lacks support for all required digests).
*/
-class SoftKeymasterContext: public KeymasterContext, SoftwareKeyBlobMaker, SoftwareRandomSource,
- AttestationRecordContext {
+class SoftKeymasterContext : public KeymasterContext,
+ SoftwareKeyBlobMaker,
+ SoftwareRandomSource,
+ public SoftAttestationContext {
public:
- explicit SoftKeymasterContext(const std::string& root_of_trust = "SW");
+ explicit SoftKeymasterContext(KmVersion version, 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);
+ KmVersion GetKmVersion() const override { return AttestationContext::GetKmVersion(); }
/**
* Use the specified HW keymaster1 device for performing undigested RSA and EC operations after
@@ -80,9 +78,14 @@
keymaster_error_t DeleteAllKeys() const override;
keymaster_error_t AddRngEntropy(const uint8_t* buf, size_t length) const override;
- keymaster_error_t GenerateAttestation(const Key& key,
- const AuthorizationSet& attest_params,
- CertChainPtr* cert_chain) const override;
+ CertificateChain GenerateAttestation(const Key& key, const AuthorizationSet& attest_params,
+ UniquePtr<Key> attest_key,
+ const KeymasterBlob& issuer_subject,
+ keymaster_error_t* error) const override;
+ CertificateChain GenerateSelfSignedCertificate(const Key& key,
+ const AuthorizationSet& cert_params,
+ bool fake_signature,
+ keymaster_error_t* error) const override;
keymaster_error_t
UnwrapKey(const KeymasterKeyBlob& wrapped_key_blob, const KeymasterKeyBlob& wrapping_key_blob,
@@ -110,12 +113,7 @@
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;
- std::unique_ptr<Keymaster0Engine> km0_engine_;
std::unique_ptr<Keymaster1Engine> km1_engine_;
std::unique_ptr<KeyFactory> rsa_factory_;
std::unique_ptr<KeyFactory> ec_factory_;
@@ -129,5 +127,3 @@
};
} // namespace keymaster
-
-#endif // SYSTEM_KEYMASTER_SOFT_KEYMASTER_CONTEXT_H_
diff --git a/include/keymaster/cppcose/cppcose.h b/include/keymaster/cppcose/cppcose.h
new file mode 100644
index 0000000..0f97388
--- /dev/null
+++ b/include/keymaster/cppcose/cppcose.h
@@ -0,0 +1,293 @@
+/*
+ * Copyright (C) 2020 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.
+ */
+
+#pragma once
+
+#include <array>
+#include <memory>
+#include <optional>
+#include <string>
+#include <vector>
+
+#include <cppbor.h>
+#include <cppbor_parse.h>
+
+#include <openssl/cipher.h>
+#include <openssl/curve25519.h>
+#include <openssl/digest.h>
+#include <openssl/hkdf.h>
+#include <openssl/hmac.h>
+#include <openssl/mem.h>
+#include <openssl/sha.h>
+
+namespace cppcose {
+
+template <typename T> class ErrMsgOr;
+using bytevec = std::vector<uint8_t>;
+using HmacSha256 = std::array<uint8_t, SHA256_DIGEST_LENGTH>;
+using HmacSha256Function = std::function<ErrMsgOr<HmacSha256>(const bytevec&)>;
+
+constexpr int kCoseSign1EntryCount = 4;
+constexpr int kCoseSign1ProtectedParams = 0;
+constexpr int kCoseSign1UnprotectedParams = 1;
+constexpr int kCoseSign1Payload = 2;
+constexpr int kCoseSign1Signature = 3;
+
+constexpr int kCoseMac0EntryCount = 4;
+constexpr int kCoseMac0ProtectedParams = 0;
+constexpr int kCoseMac0UnprotectedParams = 1;
+constexpr int kCoseMac0Payload = 2;
+constexpr int kCoseMac0Tag = 3;
+
+constexpr int kCoseEncryptEntryCount = 4;
+constexpr int kCoseEncryptProtectedParams = 0;
+constexpr int kCoseEncryptUnprotectedParams = 1;
+constexpr int kCoseEncryptPayload = 2;
+constexpr int kCoseEncryptRecipients = 3;
+
+enum Label : int {
+ ALGORITHM = 1,
+ KEY_ID = 4,
+ IV = 5,
+ COSE_KEY = -1,
+};
+
+enum CoseKeyAlgorithm : int {
+ AES_GCM_256 = 3,
+ HMAC_256 = 5,
+ ES256 = -7, // ECDSA with SHA-256
+ EDDSA = -8,
+ ECDH_ES_HKDF_256 = -25,
+};
+
+enum CoseKeyCurve : int { P256 = 1, X25519 = 4, ED25519 = 6 };
+enum CoseKeyType : int { OCTET_KEY_PAIR = 1, EC2 = 2, SYMMETRIC_KEY = 4 };
+enum CoseKeyOps : int { SIGN = 1, VERIFY = 2, ENCRYPT = 3, DECRYPT = 4 };
+
+constexpr int kAesGcmNonceLength = 12;
+constexpr int kAesGcmTagSize = 16;
+constexpr int kAesGcmKeySize = 32;
+constexpr int kAesGcmKeySizeBits = 256;
+
+template <typename T> class ErrMsgOr {
+ public:
+ ErrMsgOr(std::string errMsg) // NOLINT(google-explicit-constructor)
+ : errMsg_(std::move(errMsg)) {}
+ ErrMsgOr(const char* errMsg) // NOLINT(google-explicit-constructor)
+ : errMsg_(errMsg) {}
+ ErrMsgOr(T val) // NOLINT(google-explicit-constructor)
+ : value_(std::move(val)) {}
+
+ explicit operator bool() const { return value_.has_value(); }
+
+ T* operator->() & {
+ assert(value_);
+ return &value_.value();
+ }
+ T& operator*() & {
+ assert(value_);
+ return value_.value();
+ };
+ T&& operator*() && {
+ assert(value_);
+ return std::move(value_).value();
+ };
+
+ const std::string& message() { return errMsg_; }
+ std::string moveMessage() { return std::move(errMsg_); }
+
+ T moveValue() {
+ assert(value_);
+ return std::move(value_).value();
+ }
+
+ private:
+ std::string errMsg_;
+ std::optional<T> value_;
+};
+
+class CoseKey {
+ public:
+ CoseKey() {}
+ CoseKey(const CoseKey&) = delete;
+ CoseKey(CoseKey&&) = default;
+
+ enum Label : int {
+ KEY_TYPE = 1,
+ KEY_ID = 2,
+ ALGORITHM = 3,
+ KEY_OPS = 4,
+ CURVE = -1,
+ PUBKEY_X = -2,
+ PUBKEY_Y = -3,
+ PRIVATE_KEY = -4,
+ TEST_KEY = -70000 // Application-defined
+ };
+
+ static ErrMsgOr<CoseKey> parse(const bytevec& coseKey) {
+ auto [parsedKey, _, errMsg] = cppbor::parse(coseKey);
+ if (!parsedKey) return errMsg + " when parsing key";
+ if (!parsedKey->asMap()) return "CoseKey must be a map";
+ return CoseKey(static_cast<cppbor::Map*>(parsedKey.release()));
+ }
+
+ static ErrMsgOr<CoseKey> parse(const bytevec& coseKey, CoseKeyType expectedKeyType,
+ CoseKeyAlgorithm expectedAlgorithm, CoseKeyCurve expectedCurve) {
+ auto key = parse(coseKey);
+ if (!key) return key;
+
+ if (!key->checkIntValue(CoseKey::KEY_TYPE, expectedKeyType) ||
+ !key->checkIntValue(CoseKey::ALGORITHM, expectedAlgorithm) ||
+ !key->checkIntValue(CoseKey::CURVE, expectedCurve)) {
+ return "Unexpected key type:";
+ }
+
+ return key;
+ }
+
+ static ErrMsgOr<CoseKey> parseEd25519(const bytevec& coseKey) {
+ auto key = parse(coseKey, OCTET_KEY_PAIR, EDDSA, ED25519);
+ if (!key) return key;
+
+ auto& pubkey = key->getMap().get(PUBKEY_X);
+ if (!pubkey || !pubkey->asBstr() ||
+ pubkey->asBstr()->value().size() != ED25519_PUBLIC_KEY_LEN) {
+ return "Invalid Ed25519 public key";
+ }
+
+ return key;
+ }
+
+ static ErrMsgOr<CoseKey> parseX25519(const bytevec& coseKey, bool requireKid) {
+ auto key = parse(coseKey, OCTET_KEY_PAIR, ECDH_ES_HKDF_256, X25519);
+ if (!key) return key;
+
+ auto& pubkey = key->getMap().get(PUBKEY_X);
+ if (!pubkey || !pubkey->asBstr() ||
+ pubkey->asBstr()->value().size() != X25519_PUBLIC_VALUE_LEN) {
+ return "Invalid X25519 public key";
+ }
+
+ auto& kid = key->getMap().get(KEY_ID);
+ if (requireKid && (!kid || !kid->asBstr())) {
+ return "Missing KID";
+ }
+
+ return key;
+ }
+
+ static ErrMsgOr<CoseKey> parseP256(const bytevec& coseKey) {
+ auto key = parse(coseKey, EC2, ES256, P256);
+ if (!key) return key;
+
+ auto& pubkey_x = key->getMap().get(PUBKEY_X);
+ auto& pubkey_y = key->getMap().get(PUBKEY_Y);
+ if (!pubkey_x || !pubkey_y || !pubkey_x->asBstr() || !pubkey_y->asBstr() ||
+ pubkey_x->asBstr()->value().size() != 32 || pubkey_y->asBstr()->value().size() != 32) {
+ return "Invalid P256 public key";
+ }
+
+ return key;
+ }
+
+ std::optional<int> getIntValue(Label label) {
+ const auto& value = key_->get(label);
+ if (!value || !value->asInt()) return {};
+ return value->asInt()->value();
+ }
+
+ std::optional<bytevec> getBstrValue(Label label) {
+ const auto& value = key_->get(label);
+ if (!value || !value->asBstr()) return {};
+ return value->asBstr()->value();
+ }
+
+ const cppbor::Map& getMap() const { return *key_; }
+ cppbor::Map&& moveMap() { return std::move(*key_); }
+
+ bool checkIntValue(Label label, int expectedValue) {
+ const auto& value = key_->get(label);
+ return value && value->asInt() && value->asInt()->value() == expectedValue;
+ }
+
+ void add(Label label, int value) { key_->add(label, value); }
+ void add(Label label, bytevec value) { key_->add(label, std::move(value)); }
+
+ bytevec encode() { return key_->canonicalize().encode(); }
+
+ private:
+ explicit CoseKey(cppbor::Map* parsedKey) : key_(parsedKey) {}
+
+ // This is the full parsed key structure.
+ std::unique_ptr<cppbor::Map> key_;
+};
+
+// Utility function for generating an HMAC given a key and some input
+// data. Returns std::nullopt on error
+ErrMsgOr<HmacSha256> generateHmacSha256(const bytevec& key, const bytevec& data);
+
+ErrMsgOr<HmacSha256> generateCoseMac0Mac(HmacSha256Function macFunction, const bytevec& externalAad,
+ const bytevec& payload);
+ErrMsgOr<cppbor::Array> constructCoseMac0(HmacSha256Function macFunction,
+ const bytevec& externalAad, const bytevec& payload);
+ErrMsgOr<bytevec /* payload */> verifyAndParseCoseMac0(const cppbor::Item* macItem,
+ const bytevec& macKey);
+
+ErrMsgOr<bytevec> createCoseSign1Signature(const bytevec& key, const bytevec& protectedParams,
+ const bytevec& payload, const bytevec& aad);
+ErrMsgOr<cppbor::Array> constructCoseSign1(const bytevec& key, const bytevec& payload,
+ const bytevec& aad);
+ErrMsgOr<cppbor::Array> constructCoseSign1(const bytevec& key, cppbor::Map extraProtectedFields,
+ const bytevec& payload, const bytevec& aad);
+/**
+ * Verify and parse a COSE_Sign1 message, returning the payload.
+ *
+ * @param coseSign1 is the COSE_Sign1 to verify and parse.
+ *
+ * @param signingCoseKey is a CBOR-encoded COSE_Key to use to verify the signature. The bytevec may
+ * be empty, in which case the function assumes that coseSign1's payload is the COSE_Key to
+ * use, i.e. that coseSign1 is a self-signed "certificate".
+ */
+ErrMsgOr<bytevec /* payload */> verifyAndParseCoseSign1(const cppbor::Array* coseSign1,
+ const bytevec& signingCoseKey,
+ const bytevec& aad);
+
+ErrMsgOr<bytevec> createCoseEncryptCiphertext(const bytevec& key, const bytevec& nonce,
+ const bytevec& protectedParams, const bytevec& aad);
+ErrMsgOr<cppbor::Array> constructCoseEncrypt(const bytevec& key, const bytevec& nonce,
+ const bytevec& plaintextPayload, const bytevec& aad,
+ cppbor::Array recipients);
+ErrMsgOr<std::pair<bytevec /* pubkey */, bytevec /* key ID */>>
+getSenderPubKeyFromCoseEncrypt(const cppbor::Item* encryptItem);
+inline ErrMsgOr<std::pair<bytevec /* pubkey */, bytevec /* key ID */>>
+getSenderPubKeyFromCoseEncrypt(const std::unique_ptr<cppbor::Item>& encryptItem) {
+ return getSenderPubKeyFromCoseEncrypt(encryptItem.get());
+}
+
+ErrMsgOr<bytevec /* plaintextPayload */>
+decryptCoseEncrypt(const bytevec& key, const cppbor::Item* encryptItem, const bytevec& aad);
+
+ErrMsgOr<bytevec> x25519_HKDF_DeriveKey(const bytevec& senderPubKey, const bytevec& senderPrivKey,
+ const bytevec& recipientPubKey, bool senderIsA);
+
+ErrMsgOr<bytevec /* ciphertextWithTag */> aesGcmEncrypt(const bytevec& key, const bytevec& nonce,
+ const bytevec& aad,
+ const bytevec& plaintext);
+ErrMsgOr<bytevec /* plaintext */> aesGcmDecrypt(const bytevec& key, const bytevec& nonce,
+ const bytevec& aad,
+ const bytevec& ciphertextWithTag);
+
+} // namespace cppcose
diff --git a/include/keymaster/key_blob_utils/auth_encrypted_key_blob.h b/include/keymaster/key_blob_utils/auth_encrypted_key_blob.h
index d69d136..e328818 100644
--- a/include/keymaster/key_blob_utils/auth_encrypted_key_blob.h
+++ b/include/keymaster/key_blob_utils/auth_encrypted_key_blob.h
@@ -14,30 +14,77 @@
* limitations under the License.
*/
-#ifndef SYSTEM_KEYMASTER_AUTH_ENCRYPTED_KEY_BLOB_H_
-#define SYSTEM_KEYMASTER_AUTH_ENCRYPTED_KEY_BLOB_H_
+#pragma once
#include <hardware/keymaster_defs.h>
+#include <keymaster/android_keymaster_utils.h>
+#include <keymaster/authorization_set.h>
+
namespace keymaster {
-class AuthorizationSet;
class Buffer;
-template<typename BlobType> struct TKeymasterBlob;
-typedef TKeymasterBlob<keymaster_key_blob_t> KeymasterKeyBlob;
+class RandomSource;
-keymaster_error_t SerializeAuthEncryptedBlob(const KeymasterKeyBlob& encrypted_key_material,
- const AuthorizationSet& hw_enforced,
- const AuthorizationSet& sw_enforced,
- const Buffer& nonce, const Buffer& tag,
- KeymasterKeyBlob* key_blob);
+// Define the formats this code knows about. Note that "format" here implies both structure and KEK
+// derivation and encryption algorithm, though the KEK derivation and encryption is performed prior
+// to serialization.
+enum AuthEncryptedBlobFormat : uint8_t {
+ AES_OCB = 0,
+ AES_GCM_WITH_SW_ENFORCED = 1,
+};
-keymaster_error_t DeserializeAuthEncryptedBlob(const KeymasterKeyBlob& key_blob,
- KeymasterKeyBlob* encrypted_key_material,
- AuthorizationSet* hw_enforced,
- AuthorizationSet* sw_enforced, Buffer* nonce,
- Buffer* tag);
+struct MoveOnly {
+ MoveOnly() = default;
+ MoveOnly(const MoveOnly&) = delete;
+ MoveOnly(MoveOnly&&) = default;
+
+ MoveOnly& operator=(MoveOnly&&) = default;
+ void operator=(const MoveOnly&) = delete;
+};
+
+struct EncryptedKey : private MoveOnly {
+ AuthEncryptedBlobFormat format;
+ KeymasterKeyBlob ciphertext;
+ Buffer nonce;
+ Buffer tag;
+};
+
+struct DeserializedKey : private MoveOnly {
+ EncryptedKey encrypted_key;
+ AuthorizationSet hw_enforced;
+ AuthorizationSet sw_enforced;
+};
+
+/**
+ * Encrypt the provided plaintext with format `format`, using the provided authorization lists and
+ * master_key to derive the key encryption key.
+ */
+EncryptedKey EncryptKey(const KeymasterKeyBlob& plaintext, AuthEncryptedBlobFormat format,
+ const AuthorizationSet& hw_enforced, const AuthorizationSet& sw_enforced,
+ const AuthorizationSet& hidden, const KeymasterKeyBlob& master_key,
+ const RandomSource& random, keymaster_error_t* error);
+
+/**
+ * Serialize `encrypted_key` (which contains necessary nonce & tag information),
+ * along with the associated authorization data into a blob.
+ */
+KeymasterKeyBlob SerializeAuthEncryptedBlob(const EncryptedKey& encrypted_key,
+ const AuthorizationSet& hw_enforced,
+ const AuthorizationSet& sw_enforced,
+ keymaster_error_t* error);
+
+/**
+ * Deserialize a blob, retrieving the key ciphertext, decryption parameters and associated
+ * authorization lists.
+ */
+DeserializedKey DeserializeAuthEncryptedBlob(const KeymasterKeyBlob& key_blob,
+ keymaster_error_t* error);
+
+/**
+ * Decrypt key material from the Deserialized data in `key'.
+ */
+KeymasterKeyBlob DecryptKey(const DeserializedKey& key, const AuthorizationSet& hidden,
+ const KeymasterKeyBlob& master_key, keymaster_error_t* error);
} // namespace keymaster
-
-#endif // SYSTEM_KEYMASTER_AUTH_ENCRYPTED_KEY_BLOB_H_
diff --git a/include/keymaster/key_blob_utils/integrity_assured_key_blob.h b/include/keymaster/key_blob_utils/integrity_assured_key_blob.h
index 8cc6050..8257195 100644
--- a/include/keymaster/key_blob_utils/integrity_assured_key_blob.h
+++ b/include/keymaster/key_blob_utils/integrity_assured_key_blob.h
@@ -14,8 +14,7 @@
* limitations under the License.
*/
-#ifndef SYSTEM_KEYMASTER_INTEGRITY_ASSURED_KEY_BLOB_
-#define SYSTEM_KEYMASTER_INTEGRITY_ASSURED_KEY_BLOB_
+#pragma once
#include <hardware/keymaster_defs.h>
@@ -23,7 +22,7 @@
class AuthorizationSet;
class Buffer;
-template<typename BlobType> struct TKeymasterBlob;
+template <typename BlobType> struct TKeymasterBlob;
typedef TKeymasterBlob<keymaster_key_blob_t> KeymasterKeyBlob;
keymaster_error_t SerializeIntegrityAssuredBlob(const KeymasterKeyBlob& key_material,
@@ -43,6 +42,4 @@
AuthorizationSet* hw_enforced,
AuthorizationSet* sw_enforced);
-} // namespace keymaster;
-
-#endif // SYSTEM_KEYMASTER_INTEGRITY_ASSURED_KEY_BLOB_
+} // namespace keymaster
diff --git a/include/keymaster/key_blob_utils/ocb_utils.h b/include/keymaster/key_blob_utils/ocb_utils.h
index 5a5b661..7eb555a 100644
--- a/include/keymaster/key_blob_utils/ocb_utils.h
+++ b/include/keymaster/key_blob_utils/ocb_utils.h
@@ -14,8 +14,7 @@
* limitations under the License.
*/
-#ifndef SYSTEM_KEYMASTER_OCB_UTILS_H_
-#define SYSTEM_KEYMASTER_OCB_UTILS_H_
+#pragma once
#include "ae.h"
@@ -26,7 +25,7 @@
namespace keymaster {
class AuthorizationSet;
-template<typename BlobType> struct TKeymasterBlob;
+template <typename BlobType> struct TKeymasterBlob;
typedef TKeymasterBlob<keymaster_key_blob_t> KeymasterKeyBlob;
static const int OCB_NONCE_LENGTH = 12;
@@ -45,5 +44,3 @@
const Buffer& tag, KeymasterKeyBlob* plaintext);
} // namespace keymaster
-
-#endif // SYSTEM_KEYMASTER_OCB_UTILS_H_
diff --git a/include/keymaster/key_blob_utils/software_keyblobs.h b/include/keymaster/key_blob_utils/software_keyblobs.h
index 15dc0a4..962ed5a 100644
--- a/include/keymaster/key_blob_utils/software_keyblobs.h
+++ b/include/keymaster/key_blob_utils/software_keyblobs.h
@@ -15,12 +15,13 @@
** limitations under the License.
*/
-#ifndef KEY_BLOB_UTILS_SOFTWARE_KEYBLOBS_H_
-#define KEY_BLOB_UTILS_SOFTWARE_KEYBLOBS_H_
+#pragma once
+
+#include <optional>
#include <hardware/keymaster_defs.h>
-#include <openssl/base.h>
#include <keymaster/android_keymaster_utils.h>
+#include <openssl/base.h>
namespace keymaster {
@@ -35,8 +36,7 @@
AuthorizationSet* hidden,
const KeymasterBlob& root_of_trust);
-keymaster_error_t FakeKeyAuthorizations(EVP_PKEY* pubkey,
- AuthorizationSet* hw_enforced,
+keymaster_error_t FakeKeyAuthorizations(EVP_PKEY* pubkey, AuthorizationSet* hw_enforced,
AuthorizationSet* sw_enforced);
keymaster_error_t ParseOldSoftkeymasterBlob(const KeymasterKeyBlob& blob,
@@ -44,20 +44,31 @@
AuthorizationSet* hw_enforced,
AuthorizationSet* sw_enforced);
-keymaster_error_t ParseOcbAuthEncryptedBlob(const KeymasterKeyBlob& blob,
- const AuthorizationSet& hidden,
- KeymasterKeyBlob* key_material,
- AuthorizationSet* hw_enforced,
- AuthorizationSet* sw_enforced);
+keymaster_error_t ParseAuthEncryptedBlob(const KeymasterKeyBlob& blob,
+ const AuthorizationSet& hidden,
+ KeymasterKeyBlob* key_material,
+ AuthorizationSet* hw_enforced,
+ AuthorizationSet* sw_enforced);
keymaster_error_t SetKeyBlobAuthorizations(const AuthorizationSet& key_description,
keymaster_key_origin_t origin, uint32_t os_version,
uint32_t os_patchlevel, AuthorizationSet* hw_enforced,
AuthorizationSet* sw_enforced);
-keymaster_error_t UpgradeSoftKeyBlob(const UniquePtr<Key>& key,
- const uint32_t os_version, const uint32_t os_patchlevel,
+
+keymaster_error_t ExtendKeyBlobAuthorizations(AuthorizationSet* hw_enforced,
+ AuthorizationSet* sw_enforced,
+ std::optional<uint32_t> vendor_patchlevel,
+ std::optional<uint32_t> boot_patchlevel);
+
+keymaster_error_t UpgradeSoftKeyBlob(const UniquePtr<Key>& key, const uint32_t os_version,
+ const uint32_t os_patchlevel,
const AuthorizationSet& upgrade_params,
KeymasterKeyBlob* upgraded_key);
-} // namespace keymaster
-#endif // KEY_BLOB_UTILS_SOFTWARE_KEYBLOBS_H_
+keymaster_error_t FullUpgradeSoftKeyBlob(const UniquePtr<Key>& key, const uint32_t os_version,
+ uint32_t os_patchlevel,
+ std::optional<uint32_t> vendor_patchlevel,
+ std::optional<uint32_t> boot_patchlevel,
+ const AuthorizationSet& upgrade_params,
+ KeymasterKeyBlob* upgraded_key);
+} // namespace keymaster
diff --git a/include/keymaster/key_factory.h b/include/keymaster/key_factory.h
index a9fcdac..ad9e161 100644
--- a/include/keymaster/key_factory.h
+++ b/include/keymaster/key_factory.h
@@ -14,8 +14,7 @@
* limitations under the License.
*/
-#ifndef SYSTEM_KEYMASTER_KEY_FACTORY_H_
-#define SYSTEM_KEYMASTER_KEY_FACTORY_H_
+#pragma once
#include <hardware/keymaster_defs.h>
#include <keymaster/authorization_set.h>
@@ -25,7 +24,7 @@
class Key;
class KeymasterContext;
class OperationFactory;
-template<typename BlobType> struct TKeymasterBlob;
+template <typename BlobType> struct TKeymasterBlob;
typedef TKeymasterBlob<keymaster_key_blob_t> KeymasterKeyBlob;
/**
@@ -38,15 +37,22 @@
// Factory methods.
virtual keymaster_error_t GenerateKey(const AuthorizationSet& key_description,
- KeymasterKeyBlob* key_blob, AuthorizationSet* hw_enforced,
- AuthorizationSet* sw_enforced) const = 0;
+ UniquePtr<Key> attestation_signing_key,
+ const KeymasterBlob& issuer_subject,
+ KeymasterKeyBlob* key_blob, //
+ AuthorizationSet* hw_enforced,
+ AuthorizationSet* sw_enforced,
+ CertificateChain* cert_chain) const = 0;
- virtual keymaster_error_t ImportKey(const AuthorizationSet& key_description,
+ virtual keymaster_error_t ImportKey(const AuthorizationSet& key_description, //
keymaster_key_format_t input_key_material_format,
const KeymasterKeyBlob& input_key_material,
+ UniquePtr<Key> attestation_signing_key, //
+ const KeymasterBlob& issuer_subject,
KeymasterKeyBlob* output_key_blob,
AuthorizationSet* hw_enforced,
- AuthorizationSet* sw_enforced) const = 0;
+ AuthorizationSet* sw_enforced,
+ CertificateChain* cert_chain) const = 0;
virtual keymaster_error_t LoadKey(KeymasterKeyBlob&& key_material,
const AuthorizationSet& additional_params,
@@ -62,5 +68,3 @@
};
} // namespace keymaster
-
-#endif // SYSTEM_KEYMASTER_KEY_FACTORY_H_
diff --git a/include/keymaster/keymaster_configuration.h b/include/keymaster/keymaster_configuration.h
index 69738fd..32da101 100644
--- a/include/keymaster/keymaster_configuration.h
+++ b/include/keymaster/keymaster_configuration.h
@@ -48,16 +48,23 @@
/**
* Parses OS patch level string, returning year and month in integer form. For example, "2016-03-25"
* will be returned as 201603. Returns 0 if the string doesn't contain a date in the form
- * YYYY-MM-DD.
+ * YYYY-MM-DD; returns YYYMM on success.
*/
uint32_t GetOsPatchlevel(const char* patchlevel_string);
/**
* Retrieves and parses OS patch level from build properties. Returns 0 if the string doesn't
- * contain a date in the form YYYY-MM-DD.
+ * contain a date in the form YYYY-MM-DD; returns YYYYMM on success.
*/
uint32_t GetOsPatchlevel();
+/**
+ * Retrieves and parses vendor patch level from build properties (which may require SELinux
+ * permission). Returns 0 if the string doesn't contain a date in the form YYYY-MM-DD; returns
+ * YYYYMMDD on success.
+ */
+uint32_t GetVendorPatchlevel();
+
} // namespace keymaster
#endif // SYSTEM_KEYMASTER_KEYMASTER_CONFIGURATION_H_
diff --git a/include/keymaster/keymaster_context.h b/include/keymaster/keymaster_context.h
index c33d20b..65c1b73 100644
--- a/include/keymaster/keymaster_context.h
+++ b/include/keymaster/keymaster_context.h
@@ -17,11 +17,16 @@
#ifndef SYSTEM_KEYMASTER_KEYMASTER_CONTEXT_H_
#define SYSTEM_KEYMASTER_KEYMASTER_CONTEXT_H_
+#include <optional>
+
#include <assert.h>
#include <hardware/keymaster_defs.h>
#include <keymaster/android_keymaster_utils.h>
#include <keymaster/keymaster_enforcement.h>
+#include <keymaster/km_version.h>
+#include <keymaster/remote_provisioning_context.h>
+#include <keymaster/secure_key_storage.h>
namespace keymaster {
@@ -67,6 +72,15 @@
virtual ~KeymasterContext(){};
/**
+ * Returns the Keymaster/KeyMint version we're currently implementing.
+ *
+ * Because AndroidKeymaster supports multiple versions of Keymaster/KeyMint, with slightly
+ * different behavior, we sometimes need to branch based on the version currently being
+ * implemented. This method provides the currently-implemented version.
+ */
+ virtual KmVersion GetKmVersion() const = 0;
+
+ /**
* Sets the system version as reported by the system *itself*. This is used to verify that the
* system believes itself to be running the same version that is reported by the bootloader, in
* hardware implementations. For SoftKeymasterDevice, this sets the version information used.
@@ -134,9 +148,33 @@
*/
virtual KeymasterEnforcement* enforcement_policy() = 0;
- virtual keymaster_error_t GenerateAttestation(const Key& key,
- const AuthorizationSet& attest_params,
- CertChainPtr* cert_chain) const = 0;
+ /**
+ * Generate an attestation certificate, with chain.
+ *
+ * If attest_key is null, the certificate will be signed with the factory attestation key (from
+ * AttestationContext) and have the issuer subject set to the subject name from the signing key
+ * certificate. If attest_key is non-null, it will be used to sign the certificate and the
+ * provided issuer subject will be used (must contain a DER-encoded X.509 NAME).
+ */
+ virtual CertificateChain GenerateAttestation(const Key& key,
+ const AuthorizationSet& attest_params,
+ UniquePtr<Key> attest_key,
+ const KeymasterBlob& issuer_subject,
+ keymaster_error_t* error) const = 0;
+
+ /**
+ * Generate a self-signed certificate. If fake_signature is true, a fake signature is installed
+ * in the certificate, rather than an actual self-signature. The fake signature will not
+ * verify, of course. In this case the certificate is primarily a way to convey the public key.
+ *
+ * Note that although the return type is CertificateChain, this is for convenience and
+ * consistency with GenerateAttestation, the chain never contains more than a single
+ * certificate.
+ */
+ virtual CertificateChain GenerateSelfSignedCertificate(const Key& key,
+ const AuthorizationSet& cert_params,
+ bool fake_signature,
+ keymaster_error_t* error) const = 0;
virtual keymaster_error_t
UnwrapKey(const KeymasterKeyBlob& wrapped_key_blob, const KeymasterKeyBlob& wrapping_key_blob,
@@ -144,6 +182,69 @@
AuthorizationSet* wrapped_key_params, keymaster_key_format_t* wrapped_key_format,
KeymasterKeyBlob* wrapped_key_material) const = 0;
+ /**
+ * Return the secure key storage for this context, or null if there is no available secure key
+ * storage.
+ */
+ virtual SecureKeyStorage* secure_key_storage() { return nullptr; }
+
+ /**
+ * Checks that the data in |input_data| of size |input_data_size| matches the
+ * confirmation token given by |confirmation_token|.
+ *
+ * Note that |input_data| will already contain the prefixed message tag
+ * "confirmation token" (not including NUL byte) so all the implementation
+ * of this method needs to do is to calculate HMAC-SHA256 over |input_data|
+ * and compare it with |confirmation_token|. To do this the implementation
+ * needs access to the secret key shared with the ConfirmationUI TA.
+ *
+ * Returns KM_ERROR_OK if |input_data| matches |confirmation_token|,
+ * KM_ERROR_NO_USER_CONFIRMATION if it doesn't, and if memory allocation
+ * fails KM_ERROR_MEMORY_ALLOCATION_FAILED. If not implemented then
+ * KM_ERROR_UNIMPLEMENTED is returned.
+ */
+ virtual keymaster_error_t
+ CheckConfirmationToken(const uint8_t* /*input_data*/, size_t /*input_data_size*/,
+ const uint8_t /*confirmation_token*/[kConfirmationTokenSize]) const {
+ return KM_ERROR_UNIMPLEMENTED;
+ }
+
+ /**
+ * Return the remote provisioning context object, or null if remote provisioning is not
+ * supported.
+ */
+ virtual RemoteProvisioningContext* GetRemoteProvisioningContext() const { return nullptr; }
+
+ /**
+ * Sets the vendor patchlevel (format YYYYMMDD) for the implementation. This value should
+ * be set by the HAL service at start of day. A subsequent attempt to set a different
+ * value will return KM_ERROR_INVALID_ARGUMENT.
+ */
+ virtual keymaster_error_t SetVendorPatchlevel(uint32_t /* vendor_patchlevel */) {
+ return KM_ERROR_UNIMPLEMENTED;
+ }
+
+ /**
+ * Sets the boot patchlevel (format YYYYMMDD) for the implementation. This value should be set
+ * by the bootloader. A subsequent to set a different value will return
+ * KM_ERROR_INVALID_ARGUMENT;
+ */
+ virtual keymaster_error_t SetBootPatchlevel(uint32_t /* boot_patchlevel */) {
+ return KM_ERROR_UNIMPLEMENTED;
+ }
+
+ /**
+ * Returns the vendor patchlevel, as set by the HAL service using SetVendorPatchlevel.
+ */
+ virtual std::optional<uint32_t> GetVendorPatchlevel() const { return std::nullopt; }
+
+ /**
+ * Returns the boot patchlevel. For hardware-based implementations this will be the value set by
+ * the bootloader. For software implementations this will be the information set by
+ * SetBootPatchLevel.
+ */
+ virtual std::optional<uint32_t> GetBootPatchlevel() const { return std::nullopt; }
+
private:
// Uncopyable.
KeymasterContext(const KeymasterContext&);
diff --git a/include/keymaster/keymaster_enforcement.h b/include/keymaster/keymaster_enforcement.h
index 4e33aff..1d783ba 100644
--- a/include/keymaster/keymaster_enforcement.h
+++ b/include/keymaster/keymaster_enforcement.h
@@ -133,6 +133,11 @@
virtual uint64_t get_current_time_ms() const = 0;
/*
+ * Get whether or not we're in early boot. See early_boot_ended() below.
+ */
+ bool in_early_boot() const { return in_early_boot_; }
+
+ /*
* Get current time in seconds from some starting point. This value is used to compute relative
* times between events. It must be monotonically increasing, and must not skip or lag. It
* need not have any relation to any external time standard (other than the duration of
@@ -171,14 +176,35 @@
VerifyAuthorization(const VerifyAuthorizationRequest& request) = 0;
/**
- * Creates a key ID for use in subsequent calls to AuthorizeOperation. AndroidKeymaster uses
- * this method for creating key IDs. The generated id must be stable in that the same key_blob
- * bits yield the same keyid.
+ * Generate TimestampToken for secure clock instance.
+ */
+ virtual keymaster_error_t GenerateTimestampToken(TimestampToken* token);
+
+ /**
+ * Creates a key ID for use in subsequent calls to AuthorizeOperation. AndroidKeymaster
+ * uses this method for creating key IDs. The generated id must be stable in that the same
+ * key_blob bits yield the same keyid.
*
* Returns false if an error in the crypto library prevents creation of an ID.
*/
virtual bool CreateKeyId(const keymaster_key_blob_t& key_blob, km_id_t* keyid) const = 0;
+ /*
+ * Inform the KeymasterEnforcement object that early boot stage has ended.
+ */
+ void early_boot_ended() { in_early_boot_ = false; }
+
+ /*
+ * Inform the KeymasterEnforcement object that the device is locked, so it knows not to permit
+ * UNLOCKED_DEVICE_REQUIRED keys to be used until a fresh (later than "now") auth token is
+ * provided. If password_only is true, the fresh auth token must additionally be a password
+ * auth token.
+ */
+ void device_locked(bool password_only) {
+ device_locked_at_ = get_current_time_ms();
+ password_unlock_only_ = password_only;
+ }
+
private:
keymaster_error_t AuthorizeUpdateOrFinish(const AuthProxy& auth_set,
const AuthorizationSet& operation_params,
@@ -186,6 +212,8 @@
bool MinTimeBetweenOpsPassed(uint32_t min_time_between, const km_id_t keyid);
bool MaxUsesPerBootNotExceeded(const km_id_t keyid, uint32_t max_uses);
+ bool GetAndValidateAuthToken(const AuthorizationSet& operation_params,
+ const hw_auth_token_t** token, uint32_t* token_auth_type) const;
bool AuthTokenMatches(const AuthProxy& auth_set, const AuthorizationSet& operation_params,
const uint64_t user_secure_id, const int auth_type_index,
const int auth_timeout_index,
@@ -194,6 +222,9 @@
AccessTimeMap* access_time_map_;
AccessCountMap* access_count_map_;
+ bool in_early_boot_ = true;
+ uint64_t device_locked_at_ = 0;
+ bool password_unlock_only_ = false;
};
}; /* namespace keymaster */
diff --git a/include/keymaster/keymaster_tags.h b/include/keymaster/keymaster_tags.h
index 071f0b1..f620dfb 100644
--- a/include/keymaster/keymaster_tags.h
+++ b/include/keymaster/keymaster_tags.h
@@ -107,6 +107,7 @@
}
// NOLINTNEXTLINE(google-explicit-constructor)
inline operator keymaster_tag_t() { return tag; }
+ // NOLINTNEXTLINE(google-runtime-int)
inline long masked_tag() { return static_cast<long>(keymaster_tag_mask_type(tag)); }
};
@@ -124,6 +125,7 @@
}
// NOLINTNEXTLINE(google-explicit-constructor)
inline operator keymaster_tag_t() { return tag; }
+ // NOLINTNEXTLINE(google-runtime-int)
inline long masked_tag() { return static_cast<long>(keymaster_tag_mask_type(tag)); }
};
@@ -147,6 +149,7 @@
DECLARE_KEYMASTER_TAG(KM_DATE, TAG_USAGE_EXPIRE_DATETIME);
DECLARE_KEYMASTER_TAG(KM_UINT, TAG_MIN_SECONDS_BETWEEN_OPS);
DECLARE_KEYMASTER_TAG(KM_UINT, TAG_MAX_USES_PER_BOOT);
+DECLARE_KEYMASTER_TAG(KM_UINT, TAG_USAGE_COUNT_LIMIT);
DECLARE_KEYMASTER_TAG(KM_BOOL, TAG_ALL_USERS);
DECLARE_KEYMASTER_TAG(KM_UINT, TAG_USER_ID);
DECLARE_KEYMASTER_TAG(KM_ULONG_REP, TAG_USER_SECURE_ID);
@@ -180,7 +183,18 @@
DECLARE_KEYMASTER_TAG(KM_BYTES, TAG_ATTESTATION_ID_MEID);
DECLARE_KEYMASTER_TAG(KM_BYTES, TAG_ATTESTATION_ID_MANUFACTURER);
DECLARE_KEYMASTER_TAG(KM_BYTES, TAG_ATTESTATION_ID_MODEL);
-
+DECLARE_KEYMASTER_TAG(KM_BOOL, TAG_EARLY_BOOT_ONLY);
+DECLARE_KEYMASTER_TAG(KM_BOOL, TAG_DEVICE_UNIQUE_ATTESTATION);
+DECLARE_KEYMASTER_TAG(KM_BOOL, TAG_IDENTITY_CREDENTIAL_KEY);
+DECLARE_KEYMASTER_TAG(KM_BOOL, TAG_STORAGE_KEY);
+DECLARE_KEYMASTER_TAG(KM_BOOL, TAG_TRUSTED_USER_PRESENCE_REQUIRED);
+DECLARE_KEYMASTER_TAG(KM_UINT, TAG_BOOT_PATCHLEVEL);
+DECLARE_KEYMASTER_TAG(KM_UINT, TAG_VENDOR_PATCHLEVEL);
+DECLARE_KEYMASTER_TAG(KM_BYTES, TAG_CONFIRMATION_TOKEN);
+DECLARE_KEYMASTER_TAG(KM_BIGNUM, TAG_CERTIFICATE_SERIAL);
+DECLARE_KEYMASTER_TAG(KM_BYTES, TAG_CERTIFICATE_SUBJECT);
+DECLARE_KEYMASTER_TAG(KM_DATE, TAG_CERTIFICATE_NOT_BEFORE);
+DECLARE_KEYMASTER_TAG(KM_DATE, TAG_CERTIFICATE_NOT_AFTER);
// DECLARE_KEYMASTER_ENUM_TAG is used to declare TypedEnumTag instances for each enum keymaster tag.
#define DECLARE_KEYMASTER_ENUM_TAG(type, name, enumtype) \
extern TypedEnumTag<type, KM_##name, enumtype> name
@@ -198,6 +212,7 @@
DECLARE_KEYMASTER_ENUM_TAG(KM_ENUM, TAG_USER_AUTH_TYPE, hw_authenticator_type_t);
DECLARE_KEYMASTER_ENUM_TAG(KM_ENUM_REP, TAG_KDF, keymaster_kdf_t);
DECLARE_KEYMASTER_ENUM_TAG(KM_ENUM, TAG_EC_CURVE, keymaster_ec_curve_t);
+DECLARE_KEYMASTER_ENUM_TAG(KM_ENUM_REP, TAG_RSA_OAEP_MGF_DIGEST, keymaster_digest_t);
//
// Overloaded function "Authorization" to create keymaster_key_param_t objects for all of tags.
diff --git a/include/keymaster/km_date.h b/include/keymaster/km_date.h
new file mode 100644
index 0000000..f3a6c58
--- /dev/null
+++ b/include/keymaster/km_date.h
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2020 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.
+ */
+
+#pragma once
+
+namespace keymaster {
+
+// kKmDate is the date that KM was last modified. Ideally it should be changed every time
+// there's a significant change in the implementation, and it should be set to the date that
+// the change is merged into AOSP.
+//
+// TODO(swillden): Look into how to create a commit hook to update this.
+constexpr uint32_t kKmDate = 20201219;
+
+} // namespace keymaster
diff --git a/include/keymaster/km_openssl/aes_key.h b/include/keymaster/km_openssl/aes_key.h
index 642c502..f00a665 100644
--- a/include/keymaster/km_openssl/aes_key.h
+++ b/include/keymaster/km_openssl/aes_key.h
@@ -14,8 +14,7 @@
* limitations under the License.
*/
-#ifndef SYSTEM_KEYMASTER_AES_KEY_H_
-#define SYSTEM_KEYMASTER_AES_KEY_H_
+#pragma once
#include <openssl/aes.h>
@@ -28,16 +27,15 @@
class AesKeyFactory : public SymmetricKeyFactory {
public:
- explicit AesKeyFactory(const SoftwareKeyBlobMaker* blob_maker,
- const RandomSource* random_source) :
- SymmetricKeyFactory(blob_maker, random_source) {}
+ explicit AesKeyFactory(const SoftwareKeyBlobMaker& blob_maker,
+ const RandomSource& random_source)
+ : SymmetricKeyFactory(blob_maker, random_source) {}
keymaster_algorithm_t registry_key() const { return KM_ALGORITHM_AES; }
keymaster_error_t LoadKey(KeymasterKeyBlob&& key_material,
const AuthorizationSet& additional_params,
- AuthorizationSet&& hw_enforced,
- AuthorizationSet&& sw_enforced,
+ AuthorizationSet&& hw_enforced, AuthorizationSet&& sw_enforced,
UniquePtr<Key>* key) const override;
OperationFactory* GetOperationFactory(keymaster_purpose_t purpose) const override;
@@ -53,11 +51,8 @@
class AesKey : public SymmetricKey {
public:
AesKey(KeymasterKeyBlob&& key_material, AuthorizationSet&& hw_enforced,
- AuthorizationSet&& sw_enforced,
- const KeyFactory* key_factory)
+ AuthorizationSet&& sw_enforced, const KeyFactory* key_factory)
: SymmetricKey(move(key_material), move(hw_enforced), move(sw_enforced), key_factory) {}
};
} // namespace keymaster
-
-#endif // SYSTEM_KEYMASTER_AES_KEY_H_
diff --git a/include/keymaster/km_openssl/attestation_record.h b/include/keymaster/km_openssl/attestation_record.h
new file mode 100644
index 0000000..3ae1a10
--- /dev/null
+++ b/include/keymaster/km_openssl/attestation_record.h
@@ -0,0 +1,431 @@
+/*
+ * Copyright 2016 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.
+ */
+
+#pragma once
+
+#include <hardware/keymaster_defs.h>
+
+#include <keymaster/authorization_set.h>
+#include <keymaster/km_version.h>
+
+#include <cppbor.h>
+#include <openssl/asn1t.h>
+
+#include <vector>
+
+#define remove_type_mask(tag) ((tag)&0x0FFFFFFF)
+
+namespace keymaster {
+
+class AttestationContext;
+
+constexpr KmVersion kCurrentKmVersion = KmVersion::KEYMASTER_4_1;
+
+constexpr int EAT_CLAIM_PRIVATE_BASE = -80000;
+constexpr int EAT_CLAIM_PRIVATE_NON_KM_BASE = EAT_CLAIM_PRIVATE_BASE - 2000;
+
+constexpr int64_t convert_to_eat_claim(keymaster_tag_t tag) {
+ return EAT_CLAIM_PRIVATE_BASE - remove_type_mask(tag);
+}
+
+struct stack_st_ASN1_TYPE_Delete {
+ void operator()(stack_st_ASN1_TYPE* p) { sk_ASN1_TYPE_free(p); }
+};
+
+struct ASN1_STRING_Delete {
+ void operator()(ASN1_STRING* p) { ASN1_STRING_free(p); }
+};
+
+struct ASN1_TYPE_Delete {
+ void operator()(ASN1_TYPE* p) { ASN1_TYPE_free(p); }
+};
+
+#define ASN1_INTEGER_SET STACK_OF(ASN1_INTEGER)
+
+typedef struct km_root_of_trust {
+ ASN1_OCTET_STRING* verified_boot_key;
+ ASN1_BOOLEAN device_locked;
+ ASN1_ENUMERATED* verified_boot_state;
+ ASN1_OCTET_STRING* verified_boot_hash;
+} KM_ROOT_OF_TRUST;
+
+ASN1_SEQUENCE(KM_ROOT_OF_TRUST) = {
+ ASN1_SIMPLE(KM_ROOT_OF_TRUST, verified_boot_key, ASN1_OCTET_STRING),
+ ASN1_SIMPLE(KM_ROOT_OF_TRUST, device_locked, ASN1_BOOLEAN),
+ ASN1_SIMPLE(KM_ROOT_OF_TRUST, verified_boot_state, ASN1_ENUMERATED),
+ ASN1_SIMPLE(KM_ROOT_OF_TRUST, verified_boot_hash, ASN1_OCTET_STRING),
+} ASN1_SEQUENCE_END(KM_ROOT_OF_TRUST);
+DECLARE_ASN1_FUNCTIONS(KM_ROOT_OF_TRUST);
+
+// Fields ordered in tag order.
+typedef struct km_auth_list {
+ ASN1_INTEGER_SET* purpose;
+ ASN1_INTEGER* algorithm;
+ ASN1_INTEGER* key_size;
+ ASN1_INTEGER_SET* block_mode;
+ ASN1_INTEGER_SET* digest;
+ ASN1_INTEGER_SET* padding;
+ ASN1_NULL* caller_nonce;
+ ASN1_INTEGER* min_mac_length;
+ ASN1_INTEGER_SET* kdf;
+ ASN1_INTEGER* ec_curve;
+ ASN1_INTEGER* rsa_public_exponent;
+ ASN1_INTEGER_SET* mgf_digest;
+ ASN1_NULL* rollback_resistance;
+ ASN1_NULL* early_boot_only;
+ ASN1_INTEGER* active_date_time;
+ ASN1_INTEGER* origination_expire_date_time;
+ ASN1_INTEGER* usage_expire_date_time;
+ ASN1_INTEGER* usage_count_limit;
+ ASN1_NULL* no_auth_required;
+ ASN1_INTEGER* user_auth_type;
+ ASN1_INTEGER* auth_timeout;
+ ASN1_NULL* allow_while_on_body;
+ ASN1_NULL* trusted_user_presence_required;
+ ASN1_NULL* trusted_confirmation_required;
+ ASN1_NULL* unlocked_device_required;
+ ASN1_NULL* all_applications;
+ ASN1_OCTET_STRING* application_id;
+ ASN1_INTEGER* creation_date_time;
+ ASN1_INTEGER* origin;
+ ASN1_NULL* rollback_resistant;
+ KM_ROOT_OF_TRUST* root_of_trust;
+ ASN1_INTEGER* os_version;
+ ASN1_INTEGER* os_patchlevel;
+ ASN1_OCTET_STRING* attestation_application_id;
+ ASN1_OCTET_STRING* attestation_id_brand;
+ ASN1_OCTET_STRING* attestation_id_device;
+ ASN1_OCTET_STRING* attestation_id_product;
+ ASN1_OCTET_STRING* attestation_id_serial;
+ ASN1_OCTET_STRING* attestation_id_imei;
+ ASN1_OCTET_STRING* attestation_id_meid;
+ ASN1_OCTET_STRING* attestation_id_manufacturer;
+ ASN1_OCTET_STRING* attestation_id_model;
+ ASN1_INTEGER* vendor_patchlevel;
+ ASN1_INTEGER* boot_patch_level;
+ ASN1_NULL* device_unique_attestation;
+ ASN1_NULL* identity_credential_key;
+} KM_AUTH_LIST;
+
+ASN1_SEQUENCE(KM_AUTH_LIST) = {
+ ASN1_EXP_SET_OF_OPT(KM_AUTH_LIST, purpose, ASN1_INTEGER, TAG_PURPOSE.masked_tag()),
+ ASN1_EXP_OPT(KM_AUTH_LIST, algorithm, ASN1_INTEGER, TAG_ALGORITHM.masked_tag()),
+ ASN1_EXP_OPT(KM_AUTH_LIST, key_size, ASN1_INTEGER, TAG_KEY_SIZE.masked_tag()),
+ ASN1_EXP_SET_OF_OPT(KM_AUTH_LIST, block_mode, ASN1_INTEGER, TAG_BLOCK_MODE.masked_tag()),
+ ASN1_EXP_SET_OF_OPT(KM_AUTH_LIST, digest, ASN1_INTEGER, TAG_DIGEST.masked_tag()),
+ ASN1_EXP_SET_OF_OPT(KM_AUTH_LIST, padding, ASN1_INTEGER, TAG_PADDING.masked_tag()),
+ ASN1_EXP_OPT(KM_AUTH_LIST, caller_nonce, ASN1_NULL, TAG_CALLER_NONCE.masked_tag()),
+ ASN1_EXP_OPT(KM_AUTH_LIST, min_mac_length, ASN1_INTEGER, TAG_MIN_MAC_LENGTH.masked_tag()),
+ ASN1_EXP_SET_OF_OPT(KM_AUTH_LIST, kdf, ASN1_INTEGER, TAG_KDF.masked_tag()),
+ ASN1_EXP_OPT(KM_AUTH_LIST, ec_curve, ASN1_INTEGER, TAG_EC_CURVE.masked_tag()),
+ ASN1_EXP_OPT(KM_AUTH_LIST, rsa_public_exponent, ASN1_INTEGER,
+ TAG_RSA_PUBLIC_EXPONENT.masked_tag()),
+ ASN1_EXP_SET_OF_OPT(KM_AUTH_LIST, mgf_digest, ASN1_INTEGER,
+ TAG_RSA_OAEP_MGF_DIGEST.masked_tag()),
+ ASN1_EXP_OPT(KM_AUTH_LIST, rollback_resistance, ASN1_NULL,
+ TAG_ROLLBACK_RESISTANCE.masked_tag()),
+ ASN1_EXP_OPT(KM_AUTH_LIST, early_boot_only, ASN1_NULL, TAG_EARLY_BOOT_ONLY.masked_tag()),
+ ASN1_EXP_OPT(KM_AUTH_LIST, active_date_time, ASN1_INTEGER, TAG_ACTIVE_DATETIME.masked_tag()),
+ ASN1_EXP_OPT(KM_AUTH_LIST, origination_expire_date_time, ASN1_INTEGER,
+ TAG_ORIGINATION_EXPIRE_DATETIME.masked_tag()),
+ ASN1_EXP_OPT(KM_AUTH_LIST, usage_expire_date_time, ASN1_INTEGER,
+ TAG_USAGE_EXPIRE_DATETIME.masked_tag()),
+ ASN1_EXP_OPT(KM_AUTH_LIST, usage_count_limit, ASN1_INTEGER, TAG_USAGE_COUNT_LIMIT.masked_tag()),
+ ASN1_EXP_OPT(KM_AUTH_LIST, no_auth_required, ASN1_NULL, TAG_NO_AUTH_REQUIRED.masked_tag()),
+ ASN1_EXP_OPT(KM_AUTH_LIST, user_auth_type, ASN1_INTEGER, TAG_USER_AUTH_TYPE.masked_tag()),
+ ASN1_EXP_OPT(KM_AUTH_LIST, auth_timeout, ASN1_INTEGER, TAG_AUTH_TIMEOUT.masked_tag()),
+ ASN1_EXP_OPT(KM_AUTH_LIST, allow_while_on_body, ASN1_NULL,
+ TAG_ALLOW_WHILE_ON_BODY.masked_tag()),
+ ASN1_EXP_OPT(KM_AUTH_LIST, trusted_user_presence_required, ASN1_NULL,
+ TAG_TRUSTED_USER_PRESENCE_REQUIRED.masked_tag()),
+ ASN1_EXP_OPT(KM_AUTH_LIST, trusted_confirmation_required, ASN1_NULL,
+ TAG_TRUSTED_CONFIRMATION_REQUIRED.masked_tag()),
+ ASN1_EXP_OPT(KM_AUTH_LIST, unlocked_device_required, ASN1_NULL,
+ TAG_UNLOCKED_DEVICE_REQUIRED.masked_tag()),
+ ASN1_EXP_OPT(KM_AUTH_LIST, all_applications, ASN1_NULL, TAG_ALL_APPLICATIONS.masked_tag()),
+ ASN1_EXP_OPT(KM_AUTH_LIST, application_id, ASN1_OCTET_STRING, TAG_APPLICATION_ID.masked_tag()),
+ ASN1_EXP_OPT(KM_AUTH_LIST, creation_date_time, ASN1_INTEGER,
+ TAG_CREATION_DATETIME.masked_tag()),
+ ASN1_EXP_OPT(KM_AUTH_LIST, origin, ASN1_INTEGER, TAG_ORIGIN.masked_tag()),
+ ASN1_EXP_OPT(KM_AUTH_LIST, rollback_resistant, ASN1_NULL, TAG_ROLLBACK_RESISTANT.masked_tag()),
+ ASN1_EXP_OPT(KM_AUTH_LIST, root_of_trust, KM_ROOT_OF_TRUST, TAG_ROOT_OF_TRUST.masked_tag()),
+ ASN1_EXP_OPT(KM_AUTH_LIST, os_version, ASN1_INTEGER, TAG_OS_VERSION.masked_tag()),
+ ASN1_EXP_OPT(KM_AUTH_LIST, os_patchlevel, ASN1_INTEGER, TAG_OS_PATCHLEVEL.masked_tag()),
+ ASN1_EXP_OPT(KM_AUTH_LIST, attestation_application_id, ASN1_OCTET_STRING,
+ TAG_ATTESTATION_APPLICATION_ID.masked_tag()),
+ ASN1_EXP_OPT(KM_AUTH_LIST, attestation_id_brand, ASN1_OCTET_STRING,
+ TAG_ATTESTATION_ID_BRAND.masked_tag()),
+ ASN1_EXP_OPT(KM_AUTH_LIST, attestation_id_device, ASN1_OCTET_STRING,
+ TAG_ATTESTATION_ID_DEVICE.masked_tag()),
+ ASN1_EXP_OPT(KM_AUTH_LIST, attestation_id_product, ASN1_OCTET_STRING,
+ TAG_ATTESTATION_ID_PRODUCT.masked_tag()),
+ ASN1_EXP_OPT(KM_AUTH_LIST, attestation_id_serial, ASN1_OCTET_STRING,
+ TAG_ATTESTATION_ID_SERIAL.masked_tag()),
+ ASN1_EXP_OPT(KM_AUTH_LIST, attestation_id_imei, ASN1_OCTET_STRING,
+ TAG_ATTESTATION_ID_IMEI.masked_tag()),
+ ASN1_EXP_OPT(KM_AUTH_LIST, attestation_id_meid, ASN1_OCTET_STRING,
+ TAG_ATTESTATION_ID_MEID.masked_tag()),
+ ASN1_EXP_OPT(KM_AUTH_LIST, attestation_id_manufacturer, ASN1_OCTET_STRING,
+ TAG_ATTESTATION_ID_MANUFACTURER.masked_tag()),
+ ASN1_EXP_OPT(KM_AUTH_LIST, attestation_id_model, ASN1_OCTET_STRING,
+ TAG_ATTESTATION_ID_MODEL.masked_tag()),
+ ASN1_EXP_OPT(KM_AUTH_LIST, vendor_patchlevel, ASN1_INTEGER, TAG_VENDOR_PATCHLEVEL.masked_tag()),
+ ASN1_EXP_OPT(KM_AUTH_LIST, boot_patch_level, ASN1_INTEGER, TAG_BOOT_PATCHLEVEL.masked_tag()),
+ ASN1_EXP_OPT(KM_AUTH_LIST, device_unique_attestation, ASN1_NULL,
+ TAG_DEVICE_UNIQUE_ATTESTATION.masked_tag()),
+ ASN1_EXP_OPT(KM_AUTH_LIST, identity_credential_key, ASN1_NULL,
+ TAG_IDENTITY_CREDENTIAL_KEY.masked_tag()),
+} ASN1_SEQUENCE_END(KM_AUTH_LIST);
+DECLARE_ASN1_FUNCTIONS(KM_AUTH_LIST);
+
+typedef struct km_key_description {
+ ASN1_INTEGER* attestation_version;
+ ASN1_ENUMERATED* attestation_security_level;
+ ASN1_INTEGER* keymaster_version;
+ ASN1_ENUMERATED* keymaster_security_level;
+ ASN1_OCTET_STRING* attestation_challenge;
+ KM_AUTH_LIST* software_enforced;
+ KM_AUTH_LIST* tee_enforced;
+ ASN1_INTEGER* unique_id;
+} KM_KEY_DESCRIPTION;
+
+ASN1_SEQUENCE(KM_KEY_DESCRIPTION) = {
+ ASN1_SIMPLE(KM_KEY_DESCRIPTION, attestation_version, ASN1_INTEGER),
+ ASN1_SIMPLE(KM_KEY_DESCRIPTION, attestation_security_level, ASN1_ENUMERATED),
+ ASN1_SIMPLE(KM_KEY_DESCRIPTION, keymaster_version, ASN1_INTEGER),
+ ASN1_SIMPLE(KM_KEY_DESCRIPTION, keymaster_security_level, ASN1_ENUMERATED),
+ ASN1_SIMPLE(KM_KEY_DESCRIPTION, attestation_challenge, ASN1_OCTET_STRING),
+ ASN1_SIMPLE(KM_KEY_DESCRIPTION, unique_id, ASN1_OCTET_STRING),
+ ASN1_SIMPLE(KM_KEY_DESCRIPTION, software_enforced, KM_AUTH_LIST),
+ ASN1_SIMPLE(KM_KEY_DESCRIPTION, tee_enforced, KM_AUTH_LIST),
+} ASN1_SEQUENCE_END(KM_KEY_DESCRIPTION);
+DECLARE_ASN1_FUNCTIONS(KM_KEY_DESCRIPTION);
+
+enum class EatClaim {
+
+ // Official CWT claims, as defined in https://www.iana.org/assignments/cwt/cwt.xhtml
+
+ IAT = 6,
+ CTI = 7,
+
+ // Claims defined in
+ // https://github.com/laurencelundblade/ctoken/blob/master/inc/ctoken_eat_labels.h, by the
+ // author of the EAT standard, and in the ARM PSA. They should be considered stable at least
+ // until the standard is officially published.
+
+ UEID = -75009,
+ NONCE = -75008,
+ SECURITY_LEVEL = -76002,
+ BOOT_STATE = -76003,
+ SUBMODS = -76000,
+
+ // Claims specific to Android, and not part of the official EAT standard.
+
+ PURPOSE = convert_to_eat_claim(KM_TAG_PURPOSE),
+ ALGORITHM = convert_to_eat_claim(KM_TAG_ALGORITHM),
+ KEY_SIZE = convert_to_eat_claim(KM_TAG_KEY_SIZE),
+ BLOCK_MODE = convert_to_eat_claim(KM_TAG_BLOCK_MODE),
+ DIGEST = convert_to_eat_claim(KM_TAG_DIGEST),
+ PADDING = convert_to_eat_claim(KM_TAG_PADDING),
+ // TODO: Check if CALLER_NONCE is needed (see go/keymint-eat)
+ CALLER_NONCE = convert_to_eat_claim(KM_TAG_CALLER_NONCE),
+ MIN_MAC_LENGTH = convert_to_eat_claim(KM_TAG_MIN_MAC_LENGTH),
+ EC_CURVE = convert_to_eat_claim(KM_TAG_EC_CURVE),
+ RSA_PUBLIC_EXPONENT = convert_to_eat_claim(KM_TAG_RSA_PUBLIC_EXPONENT),
+ EARLY_BOOT_ONLY = convert_to_eat_claim(KM_TAG_EARLY_BOOT_ONLY),
+ ACTIVE_DATETIME = convert_to_eat_claim(KM_TAG_ACTIVE_DATETIME),
+ ORIGINATION_EXPIRE_DATETIME = convert_to_eat_claim(KM_TAG_ORIGINATION_EXPIRE_DATETIME),
+ USAGE_EXPIRE_DATETIME = convert_to_eat_claim(KM_TAG_USAGE_EXPIRE_DATETIME),
+ NO_AUTH_REQUIRED = convert_to_eat_claim(KM_TAG_NO_AUTH_REQUIRED),
+ USER_AUTH_TYPE = convert_to_eat_claim(KM_TAG_USER_AUTH_TYPE),
+ AUTH_TIMEOUT = convert_to_eat_claim(KM_TAG_AUTH_TIMEOUT),
+ ALLOW_WHILE_ON_BODY = convert_to_eat_claim(KM_TAG_ALLOW_WHILE_ON_BODY),
+ TRUSTED_USER_PRESENCE_REQUIRED = convert_to_eat_claim(KM_TAG_TRUSTED_USER_PRESENCE_REQUIRED),
+ TRUSTED_CONFIRMATION_REQUIRED = convert_to_eat_claim(KM_TAG_TRUSTED_CONFIRMATION_REQUIRED),
+ UNLOCKED_DEVICE_REQUIRED = convert_to_eat_claim(KM_TAG_UNLOCKED_DEVICE_REQUIRED),
+ ALL_APPLICATIONS = convert_to_eat_claim(KM_TAG_ALL_APPLICATIONS),
+ APPLICATION_ID = convert_to_eat_claim(KM_TAG_APPLICATION_ID),
+ ORIGIN = convert_to_eat_claim(KM_TAG_ORIGIN),
+ ROLLBACK_RESISTANT = convert_to_eat_claim(KM_TAG_ROLLBACK_RESISTANT),
+ OS_VERSION = convert_to_eat_claim(KM_TAG_OS_VERSION),
+ OS_PATCHLEVEL = convert_to_eat_claim(KM_TAG_OS_PATCHLEVEL),
+ ATTESTATION_APPLICATION_ID = convert_to_eat_claim(KM_TAG_ATTESTATION_APPLICATION_ID),
+ ATTESTATION_ID_BRAND = convert_to_eat_claim(KM_TAG_ATTESTATION_ID_BRAND),
+ ATTESTATION_ID_DEVICE = convert_to_eat_claim(KM_TAG_ATTESTATION_ID_DEVICE),
+ ATTESTATION_ID_PRODUCT = convert_to_eat_claim(KM_TAG_ATTESTATION_ID_PRODUCT),
+ ATTESTATION_ID_SERIAL = convert_to_eat_claim(KM_TAG_ATTESTATION_ID_SERIAL),
+ ATTESTATION_ID_MEID = convert_to_eat_claim(KM_TAG_ATTESTATION_ID_MEID),
+ ATTESTATION_ID_MANUFACTURER = convert_to_eat_claim(KM_TAG_ATTESTATION_ID_MANUFACTURER),
+ VENDOR_PATCHLEVEL = convert_to_eat_claim(KM_TAG_VENDOR_PATCHLEVEL),
+ BOOT_PATCHLEVEL = convert_to_eat_claim(KM_TAG_BOOT_PATCHLEVEL),
+ ATTESTATION_ID_MODEL = convert_to_eat_claim(KM_TAG_ATTESTATION_ID_MODEL),
+ DEVICE_UNIQUE_ATTESTATION = convert_to_eat_claim(KM_TAG_DEVICE_UNIQUE_ATTESTATION),
+ IDENTITY_CREDENTIAL_KEY = convert_to_eat_claim(KM_TAG_IDENTITY_CREDENTIAL_KEY),
+ STORAGE_KEY = convert_to_eat_claim(KM_TAG_STORAGE_KEY),
+ CONFIRMATION_TOKEN = convert_to_eat_claim(KM_TAG_CONFIRMATION_TOKEN),
+
+ // Claims specific to Android that do not exist as Keymint tags.
+
+ VERIFIED_BOOT_KEY = EAT_CLAIM_PRIVATE_NON_KM_BASE - 1,
+ DEVICE_LOCKED = EAT_CLAIM_PRIVATE_NON_KM_BASE - 2,
+ VERIFIED_BOOT_HASH = EAT_CLAIM_PRIVATE_NON_KM_BASE - 3,
+ ATTESTATION_VERSION = EAT_CLAIM_PRIVATE_NON_KM_BASE - 4,
+ KEYMASTER_VERSION = EAT_CLAIM_PRIVATE_NON_KM_BASE - 5,
+ OFFICIAL_BUILD = EAT_CLAIM_PRIVATE_NON_KM_BASE - 6,
+};
+
+enum class EatSecurityLevel {
+ UNRESTRICTED = 1,
+ RESTRICTED = 2,
+ SECURE_RESTRICTED = 3,
+ HARDWARE = 4,
+};
+
+enum class EatEcCurve {
+ P_224 = KM_EC_CURVE_P_224,
+ P_256 = KM_EC_CURVE_P_256,
+ P_384 = KM_EC_CURVE_P_384,
+ P_521 = KM_EC_CURVE_P_521,
+};
+
+static const char kEatSubmodNameSoftware[] = "software";
+static const char kEatSubmodNameTee[] = "tee";
+
+constexpr size_t kImeiBlobLength = 15;
+constexpr size_t kUeidLength = 15;
+constexpr uint8_t kImeiTypeByte = 0x03;
+
+/**
+ * The OID for Android attestation records. For the curious, it breaks down as follows:
+ *
+ * 1 = ISO
+ * 3 = org
+ * 6 = DoD (Huh? OIDs are weird.)
+ * 1 = IANA
+ * 4 = Private
+ * 1 = Enterprises
+ * 11129 = Google
+ * 2 = Google security
+ * 1 = certificate extension
+ * 17 / 25 = ASN.1 attestation extension / EAT attestation extension
+ */
+static const char kAsn1TokenOid[] = "1.3.6.1.4.1.11129.2.1.17";
+static const char kEatTokenOid[] = "1.3.6.1.4.1.11129.2.1.25";
+
+// This build_attestation_record sets the keymaster version to the default
+// value, and chooses the correct attestation extension (ASN.1 or EAT) based
+// on that value.
+keymaster_error_t build_attestation_record(const AuthorizationSet& attestation_params,
+ AuthorizationSet software_enforced,
+ AuthorizationSet tee_enforced,
+ const AttestationContext& context,
+ UniquePtr<uint8_t[]>* asn1_key_desc,
+ size_t* asn1_key_desc_len);
+
+// Builds EAT record, with the same values as the attestation record above,
+// but encoded as a CBOR (EAT) structure rather than an ASN.1 structure.
+keymaster_error_t build_eat_record(const AuthorizationSet& attestation_params,
+ AuthorizationSet software_enforced,
+ AuthorizationSet tee_enforced, //
+ const AttestationContext& context, //
+ std::vector<uint8_t>* eat_token);
+
+/**
+ * Helper functions for attestation record tests. Caller takes ownership of
+ * |attestation_challenge->data| and |unique_id->data|, deallocate using delete[].
+ */
+keymaster_error_t parse_attestation_record(const uint8_t* asn1_key_desc, size_t asn1_key_desc_len,
+ uint32_t* attestation_version, //
+ keymaster_security_level_t* attestation_security_level,
+ uint32_t* keymaster_version,
+ keymaster_security_level_t* keymaster_security_level,
+ keymaster_blob_t* attestation_challenge,
+ AuthorizationSet* software_enforced,
+ AuthorizationSet* tee_enforced,
+ keymaster_blob_t* unique_id);
+
+/**
+ * Caller takes ownership of |verified_boot_key->data|, deallocate using delete[].
+ */
+keymaster_error_t parse_root_of_trust(const uint8_t* asn1_key_desc, size_t asn1_key_desc_len,
+ keymaster_blob_t* verified_boot_key,
+ keymaster_verified_boot_t* verified_boot_state,
+ bool* device_locked);
+
+keymaster_error_t build_eat_submod(const AuthorizationSet& auth_list,
+ EatSecurityLevel security_level, cppbor::Map* submod);
+
+keymaster_error_t build_auth_list(const AuthorizationSet& auth_list, KM_AUTH_LIST* record);
+
+keymaster_error_t parse_eat_record(
+ const uint8_t* eat_key_desc, size_t eat_key_desc_len, uint32_t* attestation_version,
+ keymaster_security_level_t* attestation_security_level, uint32_t* keymaster_version,
+ keymaster_security_level_t* keymaster_security_level, keymaster_blob_t* attestation_challenge,
+ AuthorizationSet* software_enforced, AuthorizationSet* tee_enforced,
+ keymaster_blob_t* unique_id, keymaster_blob_t* verified_boot_key,
+ keymaster_verified_boot_t* verified_boot_state, bool* device_locked,
+ std::vector<int64_t>* unexpected_claims);
+
+keymaster_error_t parse_eat_submod(const cppbor::Map* submod_values,
+ AuthorizationSet* software_enforced,
+ AuthorizationSet* tee_enforced);
+
+keymaster_error_t extract_auth_list(const KM_AUTH_LIST* record, AuthorizationSet* auth_list);
+
+/**
+ * Convert a KeymasterContext::Version to the keymaster version number used in attestations.
+ */
+inline static uint version_to_attestation_km_version(KmVersion version) {
+ switch (version) {
+ default:
+ case KmVersion::KEYMASTER_1:
+ case KmVersion::KEYMASTER_1_1:
+ return 0; // Attestation not actually supported.
+ case KmVersion::KEYMASTER_2:
+ return 2;
+ case KmVersion::KEYMASTER_3:
+ return 3;
+ case KmVersion::KEYMASTER_4:
+ return 4;
+ case KmVersion::KEYMASTER_4_1:
+ return 41;
+ case KmVersion::KEYMINT_1:
+ return 100;
+ }
+}
+
+/**
+ * Convert a KeymasterContext::Version to the corresponding attestation format version number.
+ */
+inline static uint version_to_attestation_version(KmVersion version) {
+ switch (version) {
+ default:
+ case KmVersion::KEYMASTER_1:
+ return 0; // Attestation not actually supported.
+ case KmVersion::KEYMASTER_2:
+ return 1;
+ case KmVersion::KEYMASTER_3:
+ return 2;
+ case KmVersion::KEYMASTER_4:
+ return 3;
+ case KmVersion::KEYMASTER_4_1:
+ return 4;
+ case KmVersion::KEYMINT_1:
+ return 100;
+ }
+}
+
+} // namespace keymaster
diff --git a/include/keymaster/km_openssl/attestation_utils.h b/include/keymaster/km_openssl/attestation_utils.h
index 063fb2c..ab4fa50 100644
--- a/include/keymaster/km_openssl/attestation_utils.h
+++ b/include/keymaster/km_openssl/attestation_utils.h
@@ -20,6 +20,7 @@
#include <hardware/keymaster_defs.h>
#include <keymaster/android_keymaster_utils.h>
+#include <keymaster/attestation_context.h>
#include <openssl/x509v3.h>
@@ -28,15 +29,102 @@
namespace keymaster {
class AuthorizationSet;
-class AttestationRecordContext;
+class AttestationContext;
class AsymmetricKey;
+class Key;
+struct AttestKeyInfo {
+ AttestKeyInfo() = default;
+ AttestKeyInfo(const UniquePtr<Key>& key, const KeymasterBlob* issuer_subject,
+ keymaster_error_t* error);
+ AttestKeyInfo(AttestKeyInfo&&) = default;
+ AttestKeyInfo(const AttestKeyInfo&) = delete;
-keymaster_error_t generate_attestation(const AsymmetricKey& key,
- const AuthorizationSet& attest_params, const keymaster_cert_chain_t& attestation_chain,
- const keymaster_key_blob_t& attestation_signing_key,
- const AttestationRecordContext& context, CertChainPtr* cert_chain_out);
+ void operator=(const AttestKeyInfo&) = delete;
-} // namespace keymaster
+ explicit operator bool() const { return signing_key.get() != nullptr; }
+
+ EVP_PKEY_Ptr signing_key;
+ const KeymasterBlob* issuer_subject;
+};
+
+/**
+ * Generate attestation certificate.
+ *
+ * @param key is an AsymmetricKey object containing the key to be attested. The contained
+ * authorization lists are used for the key description.
+ *
+ * @param attest_params contains parameters for the attestation, including:
+ *
+ * TAG_ATTESTATION_CHALLENGE
+ * TAG_ATTESTATION_APPLICATION_ID
+ * TAG_ATTESTATION_ID_*
+ * TAG_DEVICE_UNIQUE_ATTESTATION
+ * TAG_RESET_SINCE_ROTATION
+ *
+ * @param attest_key optionally contains the attestation key and issuer subject to use. If
+ * attest_key.signing_key is non-null, that key will be used to sign the attestation and the
+ * issuer subject that will be placed in the attestation certificate. This is only used for
+ * KeyMint. If attest_key.signing_key is null, the signing key will be obtained from the
+ * AttestationContext, and the issuer subject will be obtained from the cetificate chain
+ * provided by the AttestationContext.
+ *
+ * @param context is the attestation context, used to generate unique IDs and obtain boot parameters
+ * as well as provide information about the SecurityLevel and KM version.
+ *
+ * @param error must be non-null and will be used to return any errors. In the event of an error
+ * the returned certificate chain will be empty.
+ *
+ * @return Returns the completed certificate chain, ordered from leaf (which is the generated
+ * attestation certificate) to root.
+ */
+CertificateChain generate_attestation(const AsymmetricKey& key,
+ const AuthorizationSet& attest_params,
+ AttestKeyInfo attest_key,
+ const AttestationContext& context, //
+ keymaster_error_t* error);
+
+/**
+ * Generate attestation certificate.
+ *
+ * @param evp_key contains the key to be attested. Must not be null.
+ *
+ * @param sw_enforced contains the software-enforced elements of the key description.
+ *
+ * @param hw_enforced contains the hardware-enforced elements of the key description.
+ *
+ * @param attest_params contains parameters for the attestation, including:
+ *
+ * TAG_ATTESTATION_CHALLENGE
+ * TAG_ATTESTATION_APPLICATION_ID
+ * TAG_ATTESTATION_ID_*
+ * TAG_DEVICE_UNIQUE_ATTESTATION
+ * TAG_RESET_SINCE_ROTATION
+ *
+ * @param attest_key optionally contains the attestation key and issuer subject to use. If
+ * attest_key.signing_key is non-null, that key will be used to sign the attestation and the
+ * issuer subject that will be placed in the attestation certificate. This is only used for
+ * KeyMint. If attest_key.signign_key is null, the signing key will be obtained from the
+ * AttestationContext, and the issuer subject will be obtained from the cetificate chain
+ * provided by the AttestationContext.
+ *
+ * @param context is the attestation context, used to generate unique IDs and obtain boot parameters
+ * as well as provide information about the SecurityLevel and KM version.
+ *
+ * @param error must be non-null and will be used to return any errors. In the event of an error
+ * the returned certificate chain will be empty.
+ *
+ * @return Returns the completed certificate chain, ordered from leaf (which is the generated
+ * attestation certificate) to root.
+ */
+CertificateChain generate_attestation(const EVP_PKEY* evp_key, //
+ const AuthorizationSet& sw_enforced, //
+ const AuthorizationSet& hw_enforced, //
+ const AuthorizationSet& attest_params,
+ AttestKeyInfo attest_key,
+ const AttestationContext& context, //
+ keymaster_error_t* error);
+
+} // namespace keymaster
#endif // KM_OPENSSL_ATTESTATION_UTILS_H_
diff --git a/include/keymaster/km_openssl/certificate_utils.h b/include/keymaster/km_openssl/certificate_utils.h
new file mode 100644
index 0000000..03b9c59
--- /dev/null
+++ b/include/keymaster/km_openssl/certificate_utils.h
@@ -0,0 +1,77 @@
+/*
+ * Copyright 2020, 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.
+ */
+
+#pragma once
+
+#include <openssl/x509v3.h>
+
+#include <hardware/keymaster_defs.h>
+
+#include <keymaster/km_openssl/openssl_utils.h>
+#include <keymaster/km_version.h>
+
+namespace keymaster {
+
+class AsymmetricKey;
+class AuthorizationSet;
+
+keymaster_error_t make_name_from_str(const char name[], X509_NAME_Ptr* name_out);
+
+keymaster_error_t make_name_from_der(const keymaster_blob_t& name, X509_NAME_Ptr* name_out);
+
+keymaster_error_t get_common_name(X509_NAME* name, UniquePtr<const char[]>* name_out);
+
+// CertificateParams encapsulates a set of certificate parameters that may be provided by the
+// caller, or may be defaulted.
+struct CertificateCallerParams {
+ BIGNUM_Ptr serial;
+ X509_NAME_Ptr subject_name;
+ int64_t active_date_time; // Time since epoch in ms
+ int64_t expire_date_time; // Time since epoch in ms
+ bool is_signing_key = false;
+ bool is_encryption_key = false;
+ bool is_agreement_key = false;
+};
+
+keymaster_error_t get_certificate_params(const AuthorizationSet& caller_params,
+ CertificateCallerParams* cert_params, KmVersion kmVersion);
+
+keymaster_error_t make_key_usage_extension(bool is_signing_key, bool is_encryption_key,
+ bool is_key_agreement_key,
+ X509_EXTENSION_Ptr* usage_extension_out);
+
+// Creates a rump certificate structure with serial, subject and issuer names, as well as activation
+// and expiry date. Callers should pass an empty X509_Ptr and check the return value for
+// KM_ERROR_OK (0) before accessing the result.
+keymaster_error_t make_cert_rump(const uint32_t serial, const X509_NAME* issuer,
+ const CertificateCallerParams& cert_params, X509_Ptr* cert_out);
+
+keymaster_error_t make_cert(const EVP_PKEY* evp_pkey, const X509_NAME* issuer,
+ const CertificateCallerParams& cert_params, X509_Ptr* cert_out);
+
+// Sign the certificate with the provided signing key.
+keymaster_error_t sign_cert(X509* certificate, const EVP_PKEY* signing_key);
+
+// Generate a certificate for the provided asymmetric key, with params. The certificate will be
+// self-signed unless `fake_signature` is set, in which case a fake signature will be placed in the
+// certificate. Specifically, the signature algorithm will be set to RSA PKCS#1 v1.5 with digest
+// SHA-256, but the signature field will contain a single zero byte.
+CertificateChain generate_self_signed_cert(const AsymmetricKey& key, const AuthorizationSet& params,
+ bool fake_signature, keymaster_error_t* error);
+
+keymaster_error_t encode_certificate(X509* certificate, keymaster_blob_t* derCert);
+
+} // namespace keymaster
diff --git a/include/keymaster/km_openssl/ec_key.h b/include/keymaster/km_openssl/ec_key.h
index 9bc292e..328ad62 100644
--- a/include/keymaster/km_openssl/ec_key.h
+++ b/include/keymaster/km_openssl/ec_key.h
@@ -14,8 +14,7 @@
* limitations under the License.
*/
-#ifndef SYSTEM_KEYMASTER_EC_KEY_H_
-#define SYSTEM_KEYMASTER_EC_KEY_H_
+#pragma once
#include <openssl/ec.h>
@@ -28,10 +27,11 @@
class EcKey : public AsymmetricKey {
public:
- EcKey(AuthorizationSet&& hw_enforced, AuthorizationSet&& sw_enforced,
- const KeyFactory* key_factory)
- : AsymmetricKey(move(hw_enforced), move(sw_enforced), key_factory) {}
- virtual ~EcKey() {}
+ EcKey(AuthorizationSet hw_enforced, AuthorizationSet sw_enforced, const KeyFactory* factory)
+ : AsymmetricKey(move(hw_enforced), move(sw_enforced), factory) {}
+ EcKey(AuthorizationSet hw_enforced, AuthorizationSet sw_enforced, const KeyFactory* factory,
+ EC_KEY_Ptr ec_key)
+ : AsymmetricKey(move(hw_enforced), move(sw_enforced), factory), ec_key_(move(ec_key)) {}
bool InternalToEvp(EVP_PKEY* pkey) const override;
bool EvpToInternal(const EVP_PKEY* pkey) override;
@@ -39,7 +39,7 @@
EC_KEY* key() const { return ec_key_.get(); }
protected:
- EcKey(EC_KEY* ec_key, AuthorizationSet&& hw_enforced, AuthorizationSet&& sw_enforced,
+ EcKey(EC_KEY* ec_key, AuthorizationSet hw_enforced, AuthorizationSet sw_enforced,
const KeyFactory* key_factory)
: AsymmetricKey(move(hw_enforced), move(sw_enforced), key_factory), ec_key_(ec_key) {}
@@ -48,5 +48,3 @@
};
} // namespace keymaster
-
-#endif // SYSTEM_KEYMASTER_EC_KEY_H_
diff --git a/include/keymaster/km_openssl/ec_key_factory.h b/include/keymaster/km_openssl/ec_key_factory.h
index 1ce2392..ca37d86 100644
--- a/include/keymaster/km_openssl/ec_key_factory.h
+++ b/include/keymaster/km_openssl/ec_key_factory.h
@@ -14,37 +14,42 @@
* limitations under the License.
*/
-#ifndef SYSTEM_KEYMASTER_EC_KEY_FACTORY_H_
-#define SYSTEM_KEYMASTER_EC_KEY_FACTORY_H_
+#pragma once
#include <openssl/ec.h>
#include <openssl/evp.h>
#include <keymaster/asymmetric_key_factory.h>
#include <keymaster/soft_key_factory.h>
-#include <keymaster/attestation_record.h>
namespace keymaster {
class EcKeyFactory : public AsymmetricKeyFactory, public SoftKeyFactoryMixin {
public:
- explicit EcKeyFactory(const SoftwareKeyBlobMaker* blob_maker) :
- SoftKeyFactoryMixin(blob_maker) {}
+ explicit EcKeyFactory(const SoftwareKeyBlobMaker& blob_maker, const KeymasterContext& context)
+ : AsymmetricKeyFactory(context), SoftKeyFactoryMixin(blob_maker) {}
keymaster_algorithm_t keymaster_key_type() const override { return KM_ALGORITHM_EC; }
int evp_key_type() const override { return EVP_PKEY_EC; }
keymaster_error_t GenerateKey(const AuthorizationSet& key_description,
- KeymasterKeyBlob* key_blob, AuthorizationSet* hw_enforced,
- AuthorizationSet* sw_enforced) const override;
+ UniquePtr<Key> attest_key, //
+ const KeymasterBlob& issuer_subject, //
+ KeymasterKeyBlob* key_blob,
+ AuthorizationSet* hw_enforced, //
+ AuthorizationSet* sw_enforced,
+ CertificateChain* cert_chain) 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;
+ UniquePtr<Key> attest_key, //
+ const KeymasterBlob& issuer_subject,
+ KeymasterKeyBlob* output_key_blob, //
+ AuthorizationSet* hw_enforced, //
+ AuthorizationSet* sw_enforced,
+ CertificateChain* cert_chain) const override;
- keymaster_error_t CreateEmptyKey(AuthorizationSet&& hw_enforced,
- AuthorizationSet&& sw_enforced,
+ keymaster_error_t CreateEmptyKey(AuthorizationSet&& hw_enforced, AuthorizationSet&& sw_enforced,
UniquePtr<AsymmetricKey>* key) const override;
keymaster_error_t UpdateImportKeyDescription(const AuthorizationSet& key_description,
@@ -64,5 +69,3 @@
};
} // namespace keymaster
-
-#endif // SYSTEM_KEYMASTER_EC_KEY_FACTORY_H_
diff --git a/include/keymaster/km_openssl/ecdh_operation.h b/include/keymaster/km_openssl/ecdh_operation.h
new file mode 100644
index 0000000..4f85afa
--- /dev/null
+++ b/include/keymaster/km_openssl/ecdh_operation.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2021 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_ECDH_OPERATION_H_
+#define SYSTEM_KEYMASTER_ECDH_OPERATION_H_
+
+#include <openssl/ec.h>
+#include <openssl/evp.h>
+
+#include <keymaster/UniquePtr.h>
+
+#include <keymaster/key.h>
+#include <keymaster/km_openssl/openssl_utils.h>
+#include <keymaster/operation.h>
+
+namespace keymaster {
+
+class EcdhOperation : public Operation {
+ public:
+ EcdhOperation(AuthorizationSet&& hw_enforced, AuthorizationSet&& sw_enforced, EVP_PKEY* key)
+ : Operation(KM_PURPOSE_AGREE_KEY, move(hw_enforced), move(sw_enforced)), ecdh_key_(key) {}
+
+ keymaster_error_t Abort() override { return KM_ERROR_OK; }
+
+ keymaster_error_t Begin(const AuthorizationSet& input_params,
+ AuthorizationSet* output_params) override;
+ keymaster_error_t Update(const AuthorizationSet& additional_params, const Buffer& input,
+ AuthorizationSet* output_params, Buffer* output,
+ size_t* input_consumed) override;
+ keymaster_error_t Finish(const AuthorizationSet& additional_params, const Buffer& input,
+ const Buffer& signature, AuthorizationSet* output_params,
+ Buffer* output) override;
+
+ protected:
+ EVP_PKEY_Ptr ecdh_key_;
+};
+
+class EcdhOperationFactory : public OperationFactory {
+ private:
+ KeyType registry_key() const override { return KeyType(KM_ALGORITHM_EC, KM_PURPOSE_AGREE_KEY); }
+ OperationPtr CreateOperation(Key&& key, const AuthorizationSet& begin_params,
+ keymaster_error_t* error) override;
+};
+
+} // namespace keymaster
+
+#endif // SYSTEM_KEYMASTER_ECDH_OPERATION_H_
diff --git a/include/keymaster/km_openssl/hmac_key.h b/include/keymaster/km_openssl/hmac_key.h
index f32ba4e..55d802a 100644
--- a/include/keymaster/km_openssl/hmac_key.h
+++ b/include/keymaster/km_openssl/hmac_key.h
@@ -14,8 +14,7 @@
* limitations under the License.
*/
-#ifndef SYSTEM_KEYMASTER_HMAC_KEY_H_
-#define SYSTEM_KEYMASTER_HMAC_KEY_H_
+#pragma once
#include "symmetric_key.h"
@@ -27,14 +26,13 @@
class HmacKeyFactory : public SymmetricKeyFactory {
public:
- explicit HmacKeyFactory(const SoftwareKeyBlobMaker* blob_maker,
- const RandomSource* random_source) :
- SymmetricKeyFactory(blob_maker, random_source) {}
+ explicit HmacKeyFactory(const SoftwareKeyBlobMaker& blob_maker,
+ const RandomSource& random_source)
+ : SymmetricKeyFactory(blob_maker, random_source) {}
keymaster_error_t LoadKey(KeymasterKeyBlob&& key_material,
const AuthorizationSet& additional_params,
- AuthorizationSet&& hw_enforced,
- AuthorizationSet&& sw_enforced,
+ AuthorizationSet&& hw_enforced, AuthorizationSet&& sw_enforced,
UniquePtr<Key>* key) const override;
OperationFactory* GetOperationFactory(keymaster_purpose_t purpose) const override;
@@ -56,5 +54,3 @@
};
} // namespace keymaster
-
-#endif // SYSTEM_KEYMASTER_HMAC_KEY_H_
diff --git a/include/keymaster/km_openssl/iso18033kdf.h b/include/keymaster/km_openssl/iso18033kdf.h
index ef96060..8c2952b 100644
--- a/include/keymaster/km_openssl/iso18033kdf.h
+++ b/include/keymaster/km_openssl/iso18033kdf.h
@@ -14,15 +14,14 @@
* limitations under the License.
*/
-#ifndef SYSTEM_KEYMASTER_ISO18033KDF_H_
-#define SYSTEM_KEYMASTER_ISO18033KDF_H_
+#pragma once
#include <keymaster/km_openssl/kdf.h>
#include <hardware/keymaster_defs.h>
-#include <keymaster/serializable.h>
#include <keymaster/UniquePtr.h>
+#include <keymaster/serializable.h>
namespace keymaster {
@@ -63,5 +62,3 @@
};
} // namespace keymaster
-
-#endif // SYSTEM_KEYMASTER_ISO18033KDF_H_
diff --git a/include/keymaster/km_openssl/nist_curve_key_exchange.h b/include/keymaster/km_openssl/nist_curve_key_exchange.h
index 8d2fa84..1c8ee2f 100644
--- a/include/keymaster/km_openssl/nist_curve_key_exchange.h
+++ b/include/keymaster/km_openssl/nist_curve_key_exchange.h
@@ -14,13 +14,12 @@
* limitations under the License.
*/
-#ifndef SYSTEM_KEYMASTER_NIST_CURVE_KEY_EXCHANGE_H_
-#define SYSTEM_KEYMASTER_NIST_CURVE_KEY_EXCHANGE_H_
+#pragma once
#include "key_exchange.h"
-#include <keymaster/authorization_set.h>
#include <hardware/keymaster_defs.h>
+#include <keymaster/authorization_set.h>
#include <keymaster/UniquePtr.h>
@@ -68,5 +67,3 @@
};
} // namespace keymaster
-
-#endif // SYSTEM_KEYMASTER_NIST_CURVE_KEY_EXCHANGE_H_
diff --git a/include/keymaster/km_openssl/openssl_utils.h b/include/keymaster/km_openssl/openssl_utils.h
index 4483045..402c1f9 100644
--- a/include/keymaster/km_openssl/openssl_utils.h
+++ b/include/keymaster/km_openssl/openssl_utils.h
@@ -14,8 +14,7 @@
* limitations under the License.
*/
-#ifndef SYSTEM_KEYMASTER_OPENSSL_UTILS_H_
-#define SYSTEM_KEYMASTER_OPENSSL_UTILS_H_
+#pragma once
#include <openssl/bn.h>
#include <openssl/ec.h>
@@ -30,7 +29,7 @@
namespace keymaster {
-template<typename BlobType> struct TKeymasterBlob;
+template <typename BlobType> struct TKeymasterBlob;
typedef TKeymasterBlob<keymaster_key_blob_t> KeymasterKeyBlob;
class EvpMdCtxCleaner {
@@ -62,6 +61,7 @@
DEFINE_OPENSSL_OBJECT_POINTER(EC_POINT)
DEFINE_OPENSSL_OBJECT_POINTER(ENGINE)
DEFINE_OPENSSL_OBJECT_POINTER(EVP_PKEY)
+DEFINE_OPENSSL_OBJECT_POINTER(EVP_PKEY_CTX)
DEFINE_OPENSSL_OBJECT_POINTER(PKCS8_PRIV_KEY_INFO)
DEFINE_OPENSSL_OBJECT_POINTER(RSA)
DEFINE_OPENSSL_OBJECT_POINTER(X509)
@@ -95,10 +95,30 @@
keymaster_error_t EvpKeyToKeyMaterial(const EVP_PKEY* evp_pkey, KeymasterKeyBlob* key_blob);
+keymaster_error_t GetEcdsa256KeyFromCert(const keymaster_blob_t* km_cert, uint8_t* x_coord,
+ size_t x_length, uint8_t* y_coord, size_t y_length);
+
size_t ec_group_size_bits(EC_KEY* ec_key);
keymaster_error_t GenerateRandom(uint8_t* buf, size_t length);
-} // namespace keymaster
+inline const EVP_MD* KmDigestToEvpDigest(keymaster_digest_t digest) {
+ switch (digest) {
+ case KM_DIGEST_MD5:
+ return EVP_md5();
+ case KM_DIGEST_SHA1:
+ return EVP_sha1();
+ case KM_DIGEST_SHA_2_224:
+ return EVP_sha224();
+ case KM_DIGEST_SHA_2_256:
+ return EVP_sha256();
+ case KM_DIGEST_SHA_2_384:
+ return EVP_sha384();
+ case KM_DIGEST_SHA_2_512:
+ return EVP_sha512();
+ default:
+ return nullptr;
+ }
+}
-#endif // SYSTEM_KEYMASTER_OPENSSL_UTILS_H_
+} // namespace keymaster
diff --git a/include/keymaster/km_openssl/rsa_key.h b/include/keymaster/km_openssl/rsa_key.h
index 4936bc9..3783f9e 100644
--- a/include/keymaster/km_openssl/rsa_key.h
+++ b/include/keymaster/km_openssl/rsa_key.h
@@ -19,15 +19,19 @@
#include <openssl/rsa.h>
+#include <keymaster/km_openssl/openssl_utils.h>
+
#include "asymmetric_key.h"
namespace keymaster {
class RsaKey : public AsymmetricKey {
public:
- RsaKey(AuthorizationSet&& hw_enforced, AuthorizationSet&& sw_enforced,
- const KeyFactory* key_factory)
- : AsymmetricKey(move(hw_enforced), move(sw_enforced), key_factory) {}
+ RsaKey(AuthorizationSet hw_enforced, AuthorizationSet sw_enforced, const KeyFactory* factory)
+ : AsymmetricKey(move(hw_enforced), move(sw_enforced), factory) {}
+ RsaKey(AuthorizationSet hw_enforced, AuthorizationSet sw_enforced, const KeyFactory* factory,
+ RSA_Ptr rsa_key)
+ : AsymmetricKey(move(hw_enforced), move(sw_enforced), factory), rsa_key_(move(rsa_key)) {}
bool InternalToEvp(EVP_PKEY* pkey) const override;
bool EvpToInternal(const EVP_PKEY* pkey) override;
@@ -35,19 +39,15 @@
bool SupportedMode(keymaster_purpose_t purpose, keymaster_padding_t padding);
bool SupportedMode(keymaster_purpose_t purpose, keymaster_digest_t digest);
- struct RSA_Delete {
- void operator()(RSA* p) { RSA_free(p); }
- };
-
RSA* key() const { return rsa_key_.get(); }
protected:
- RsaKey(RSA* rsa, AuthorizationSet&& hw_enforced, AuthorizationSet&& sw_enforced,
+ RsaKey(RSA* rsa, AuthorizationSet hw_enforced, AuthorizationSet sw_enforced,
const KeyFactory* key_factory)
: AsymmetricKey(move(hw_enforced), move(sw_enforced), key_factory), rsa_key_(rsa) {}
private:
- UniquePtr<RSA, RSA_Delete> rsa_key_;
+ RSA_Ptr rsa_key_;
};
} // namespace keymaster
diff --git a/include/keymaster/km_openssl/rsa_key_factory.h b/include/keymaster/km_openssl/rsa_key_factory.h
index ab0b3f5..3aacadc 100644
--- a/include/keymaster/km_openssl/rsa_key_factory.h
+++ b/include/keymaster/km_openssl/rsa_key_factory.h
@@ -14,34 +14,39 @@
* limitations under the License.
*/
-#ifndef SYSTEM_KEYMASTER_RSA_KEY_FACTORY_H_
-#define SYSTEM_KEYMASTER_RSA_KEY_FACTORY_H_
+#pragma once
#include <openssl/evp.h>
#include <openssl/rsa.h>
#include <keymaster/asymmetric_key_factory.h>
#include <keymaster/soft_key_factory.h>
-#include <keymaster/attestation_record.h>
namespace keymaster {
class RsaKeyFactory : public AsymmetricKeyFactory, public SoftKeyFactoryMixin {
public:
- explicit RsaKeyFactory(const SoftwareKeyBlobMaker* blob_maker) :
- SoftKeyFactoryMixin(blob_maker) {}
+ explicit RsaKeyFactory(const SoftwareKeyBlobMaker& blob_maker, const KeymasterContext& context)
+ : AsymmetricKeyFactory(context), SoftKeyFactoryMixin(blob_maker) {}
keymaster_error_t GenerateKey(const AuthorizationSet& key_description,
- KeymasterKeyBlob* key_blob, AuthorizationSet* hw_enforced,
- AuthorizationSet* sw_enforced) const override;
+ UniquePtr<Key> attest_key,
+ const KeymasterBlob& issuer_subject, //
+ KeymasterKeyBlob* key_blob,
+ AuthorizationSet* hw_enforced, //
+ AuthorizationSet* sw_enforced,
+ CertificateChain* cert_chain) 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;
+ UniquePtr<Key> attest_key, //
+ const KeymasterBlob& issuer_subject,
+ KeymasterKeyBlob* output_key_blob,
+ AuthorizationSet* hw_enforced, //
+ AuthorizationSet* sw_enforced,
+ CertificateChain* cert_chain) const override;
- keymaster_error_t CreateEmptyKey(AuthorizationSet&& hw_enforced,
- AuthorizationSet&& sw_enforced,
+ keymaster_error_t CreateEmptyKey(AuthorizationSet&& hw_enforced, AuthorizationSet&& sw_enforced,
UniquePtr<AsymmetricKey>* key) const override;
OperationFactory* GetOperationFactory(keymaster_purpose_t purpose) const override;
@@ -59,5 +64,3 @@
};
} // namespace keymaster
-
-#endif // SYSTEM_KEYMASTER_RSA_KEY_FACTORY_H_
diff --git a/include/keymaster/km_openssl/rsa_operation.h b/include/keymaster/km_openssl/rsa_operation.h
index 578a3d2..99004f2 100644
--- a/include/keymaster/km_openssl/rsa_operation.h
+++ b/include/keymaster/km_openssl/rsa_operation.h
@@ -140,14 +140,22 @@
RsaCryptOperation(AuthorizationSet&& hw_enforced, AuthorizationSet&& sw_enforced,
keymaster_purpose_t purpose, keymaster_digest_t digest,
keymaster_padding_t padding, EVP_PKEY* key)
- : RsaOperation(move(hw_enforced), move(sw_enforced), purpose, digest, padding, key) {}
+ : RsaOperation(move(hw_enforced), move(sw_enforced), purpose, digest, padding, key),
+ mgf_digest_(KM_DIGEST_SHA1), mgf_digest_algorithm_(nullptr) {}
+ keymaster_digest_t oaepMgfDigest() { return mgf_digest_; }
+ void setOaepMgfDigest(keymaster_digest_t mgf_digest) { mgf_digest_ = mgf_digest; }
+ keymaster_error_t Begin(const AuthorizationSet& input_params,
+ AuthorizationSet* output_params) override;
protected:
keymaster_error_t SetOaepDigestIfRequired(EVP_PKEY_CTX* pkey_ctx);
+ keymaster_error_t InitMgfDigest();
private:
int GetOpensslPadding(keymaster_error_t* error) override;
bool require_digest() const override { return padding_ == KM_PAD_RSA_OAEP; }
+ keymaster_digest_t mgf_digest_;
+ const EVP_MD* mgf_digest_algorithm_;
};
/**
@@ -194,7 +202,7 @@
const keymaster_digest_t* SupportedDigests(size_t* digest_count) const override;
protected:
- static EVP_PKEY* GetRsaKey(Key&& key, keymaster_error_t* error);
+ static EVP_PKEY* GetRsaKey(const Key& key, keymaster_error_t* error);
virtual RsaOperation* CreateRsaOperation(Key&& key, const AuthorizationSet& begin_params,
keymaster_error_t* error);
@@ -222,6 +230,10 @@
RsaOperation* CreateRsaOperation(Key&& key, const AuthorizationSet& begin_params,
keymaster_error_t* error) override;
const keymaster_padding_t* SupportedPaddingModes(size_t* padding_mode_count) const override;
+
+ protected:
+ keymaster_error_t GetAndValidateMgfDigest(const AuthorizationSet& begin_params, const Key& key,
+ keymaster_digest_t* digest) const;
};
/**
diff --git a/include/keymaster/km_openssl/soft_keymaster_enforcement.h b/include/keymaster/km_openssl/soft_keymaster_enforcement.h
index 72b11ec..31022e7 100644
--- a/include/keymaster/km_openssl/soft_keymaster_enforcement.h
+++ b/include/keymaster/km_openssl/soft_keymaster_enforcement.h
@@ -44,6 +44,7 @@
KeymasterBlob* sharingCheck) override;
VerifyAuthorizationResponse
VerifyAuthorization(const VerifyAuthorizationRequest& request) override;
+ keymaster_error_t GenerateTimestampToken(TimestampToken* token) override;
private:
bool have_saved_params_ = false;
diff --git a/include/keymaster/km_openssl/software_random_source.h b/include/keymaster/km_openssl/software_random_source.h
index ee472ef..ea8111b 100644
--- a/include/keymaster/km_openssl/software_random_source.h
+++ b/include/keymaster/km_openssl/software_random_source.h
@@ -15,22 +15,18 @@
** limitations under the License.
*/
-#ifndef KM_OPENSSL_SOFTWARE_RANDOM_SOURCE_H_
-#define KM_OPENSSL_SOFTWARE_RANDOM_SOURCE_H_
+#pragma once
#include <keymaster/random_source.h>
namespace keymaster {
class SoftwareRandomSource : public RandomSource {
-public:
+ public:
/**
* Generates \p length random bytes, placing them in \p buf.
*/
keymaster_error_t GenerateRandom(uint8_t* buffer, size_t length) const override;
-
};
-}
-
-#endif // KM_OPENSSL_SOFTWARE_RANDOM_SOURCE_H_
+} // namespace keymaster
diff --git a/include/keymaster/km_openssl/symmetric_key.h b/include/keymaster/km_openssl/symmetric_key.h
index 5a5252d..a57d287 100644
--- a/include/keymaster/km_openssl/symmetric_key.h
+++ b/include/keymaster/km_openssl/symmetric_key.h
@@ -14,8 +14,7 @@
* limitations under the License.
*/
-#ifndef SYSTEM_KEYMASTER_SYMMETRIC_KEY_H_
-#define SYSTEM_KEYMASTER_SYMMETRIC_KEY_H_
+#pragma once
#include <keymaster/key_factory.h>
#include <keymaster/random_source.h>
@@ -29,19 +28,26 @@
class SymmetricKeyFactory : public KeyFactory, public SoftKeyFactoryMixin {
public:
- explicit SymmetricKeyFactory(const SoftwareKeyBlobMaker* blob_maker,
- const RandomSource* random_source) :
- SoftKeyFactoryMixin(blob_maker),
- random_source_(*random_source) {}
+ explicit SymmetricKeyFactory(const SoftwareKeyBlobMaker& blob_maker,
+ const RandomSource& random_source)
+ : SoftKeyFactoryMixin(blob_maker), random_source_(random_source) {}
keymaster_error_t GenerateKey(const AuthorizationSet& key_description,
- KeymasterKeyBlob* key_blob, AuthorizationSet* hw_enforced,
- AuthorizationSet* sw_enforced) const override;
+ UniquePtr<Key> attest_key,
+ const KeymasterBlob& issuer_subject, //
+ KeymasterKeyBlob* key_blob,
+ AuthorizationSet* hw_enforced, //
+ AuthorizationSet* sw_enforced,
+ CertificateChain* cert_chain) 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;
+ UniquePtr<Key> attest_key,
+ const KeymasterBlob& issuer_subject, //
+ KeymasterKeyBlob* output_key_blob,
+ AuthorizationSet* hw_enforced, //
+ AuthorizationSet* sw_enforced,
+ CertificateChain* cert_chain) const override;
virtual const keymaster_key_format_t* SupportedImportFormats(size_t* count) const override;
virtual const keymaster_key_format_t* SupportedExportFormats(size_t* count) const override {
@@ -77,10 +83,7 @@
protected:
SymmetricKey(KeymasterKeyBlob&& key_material, AuthorizationSet&& hw_enforced,
- AuthorizationSet&& sw_enforced,
- const KeyFactory* key_factory);
+ AuthorizationSet&& sw_enforced, const KeyFactory* key_factory);
};
} // namespace keymaster
-
-#endif // SYSTEM_KEYMASTER_AES_KEY_H_
diff --git a/include/keymaster/km_openssl/triple_des_key.h b/include/keymaster/km_openssl/triple_des_key.h
index 0a6810d..a03d595 100644
--- a/include/keymaster/km_openssl/triple_des_key.h
+++ b/include/keymaster/km_openssl/triple_des_key.h
@@ -25,8 +25,8 @@
class TripleDesKeyFactory : public SymmetricKeyFactory {
public:
- explicit TripleDesKeyFactory(const SoftwareKeyBlobMaker* blob_maker,
- const RandomSource* random_source)
+ explicit TripleDesKeyFactory(const SoftwareKeyBlobMaker& blob_maker,
+ const RandomSource& random_source)
: SymmetricKeyFactory(blob_maker, random_source) {}
keymaster_algorithm_t registry_key() const { return KM_ALGORITHM_TRIPLE_DES; }
diff --git a/include/keymaster/km_version.h b/include/keymaster/km_version.h
new file mode 100644
index 0000000..c328a27
--- /dev/null
+++ b/include/keymaster/km_version.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2020 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.
+ */
+
+#pragma once
+
+namespace keymaster {
+
+/**
+ * Version enumerates the list of Keymaster/KeyMint versions that we may support. As old
+ * versions are deprecated and removed they should be removed from this enum, which will make it
+ * possible to easily find the version-dependent code and remove dead branches.
+ */
+enum class KmVersion {
+ KEYMASTER_1 = 10,
+ KEYMASTER_1_1 = 11,
+ KEYMASTER_2 = 20,
+ KEYMASTER_3 = 30,
+ KEYMASTER_4 = 40,
+ KEYMASTER_4_1 = 41,
+ KEYMINT_1 = 100,
+};
+
+}; // namespace keymaster
diff --git a/include/keymaster/legacy_support/ec_keymaster0_key.h b/include/keymaster/legacy_support/ec_keymaster0_key.h
deleted file mode 100644
index ab5ae4f..0000000
--- a/include/keymaster/legacy_support/ec_keymaster0_key.h
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * 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_KEYMASTER0_KEY_H_
-#define SYSTEM_KEYMASTER_EC_KEYMASTER0_KEY_H_
-
-#include <openssl/ec_key.h>
-
-#include <keymaster/km_openssl/ec_key.h>
-#include <keymaster/km_openssl/ec_key_factory.h>
-
-namespace keymaster {
-
-class Keymaster0Engine;
-
-/**
- * An EcdsaKeyFactory which can delegate key generation, importing and loading operations to a
- * keymaster0-backed OpenSSL engine.
- */
-class EcdsaKeymaster0KeyFactory : public EcKeyFactory {
- typedef EcKeyFactory super;
-
- public:
- EcdsaKeymaster0KeyFactory(const SoftwareKeyBlobMaker* blob_maker,
- const Keymaster0Engine* 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(KeymasterKeyBlob&& key_material,
- const AuthorizationSet& additional_params,
- AuthorizationSet&& hw_enforced,
- AuthorizationSet&& sw_enforced,
- UniquePtr<Key>* key) const override;
-
- private:
- const Keymaster0Engine* engine_;
-};
-
-class EcKeymaster0Key : public EcKey {
- public:
- EcKeymaster0Key(EC_KEY* ec_key, AuthorizationSet&& hw_enforced,
- AuthorizationSet&& sw_enforced, const KeyFactory* key_factory)
- : EcKey(ec_key, move(hw_enforced), move(sw_enforced), key_factory) {}
-};
-
-} // namespace keymaster
-
-#endif // SYSTEM_KEYMASTER_EC_KEYMASTER0_KEY_H_
diff --git a/include/keymaster/legacy_support/ec_keymaster1_key.h b/include/keymaster/legacy_support/ec_keymaster1_key.h
index 5a2c1d8..d695c74 100644
--- a/include/keymaster/legacy_support/ec_keymaster1_key.h
+++ b/include/keymaster/legacy_support/ec_keymaster1_key.h
@@ -14,8 +14,7 @@
* limitations under the License.
*/
-#ifndef SYSTEM_KEYMASTER_EC_KEYMASTER1_KEY_H_
-#define SYSTEM_KEYMASTER_EC_KEYMASTER1_KEY_H_
+#pragma once
#include <openssl/ecdsa.h>
@@ -38,23 +37,31 @@
*/
class EcdsaKeymaster1KeyFactory : public EcKeyFactory {
public:
- EcdsaKeymaster1KeyFactory(const SoftwareKeyBlobMaker* blob_maker,
+ EcdsaKeymaster1KeyFactory(const SoftwareKeyBlobMaker& blob_maker,
+ const KeymasterContext& context, //
const Keymaster1Engine* engine);
keymaster_error_t GenerateKey(const AuthorizationSet& key_description,
- KeymasterKeyBlob* key_blob, AuthorizationSet* hw_enforced,
- AuthorizationSet* sw_enforced) const override;
+ UniquePtr<Key> attest_key, //
+ const KeymasterBlob& issuer_subject, //
+ KeymasterKeyBlob* key_blob, //
+ AuthorizationSet* hw_enforced, //
+ AuthorizationSet* sw_enforced,
+ CertificateChain* cert_chain) 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;
+ UniquePtr<Key> attest_key, //
+ const KeymasterBlob& issuer_subject,
+ KeymasterKeyBlob* output_key_blob, //
+ AuthorizationSet* hw_enforced, //
+ AuthorizationSet* sw_enforced,
+ CertificateChain* cert_chain) const override;
keymaster_error_t LoadKey(KeymasterKeyBlob&& key_material,
const AuthorizationSet& additional_params,
- AuthorizationSet&& hw_enforced,
- AuthorizationSet&& sw_enforced,
+ AuthorizationSet&& hw_enforced, AuthorizationSet&& sw_enforced,
UniquePtr<Key>* key) const override;
OperationFactory* GetOperationFactory(keymaster_purpose_t purpose) const override;
@@ -74,5 +81,3 @@
};
} // namespace keymaster
-
-#endif // SYSTEM_KEYMASTER_ECDSA_KEYMASTER1_KEY_H_
diff --git a/include/keymaster/legacy_support/keymaster0_engine.h b/include/keymaster/legacy_support/keymaster0_engine.h
deleted file mode 100644
index ca3908b..0000000
--- a/include/keymaster/legacy_support/keymaster0_engine.h
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
- * 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_KEYMASTER0_ENGINE_H_
-#define SYSTEM_KEYMASTER_KEYMASTER0_ENGINE_H_
-
-#include <memory>
-
-#include <openssl/ec.h>
-#include <openssl/engine.h>
-#include <openssl/ex_data.h>
-#include <openssl/rsa.h>
-
-#include <hardware/keymaster0.h>
-#include <hardware/keymaster_defs.h>
-
-namespace keymaster {
-
-template<typename BlobType> struct TKeymasterBlob;
-typedef TKeymasterBlob<keymaster_key_blob_t> KeymasterKeyBlob;
-
-/* Keymaster0Engine is a BoringSSL ENGINE that implements RSA & EC by forwarding the requested
- * operations to a keymaster0 module. */
-class Keymaster0Engine {
- public:
- /**
- * Create a Keymaster0Engine, wrapping the provided keymaster0_device. The engine takes
- * ownership of the device, and will close it during destruction.
- */
- explicit Keymaster0Engine(const keymaster0_device_t* keymaster0_device);
- ~Keymaster0Engine();
-
- bool supports_ec() const { return supports_ec_; }
-
- bool GenerateRsaKey(uint64_t public_exponent, uint32_t public_modulus,
- KeymasterKeyBlob* key_material) const;
- bool GenerateEcKey(uint32_t key_size, KeymasterKeyBlob* key_material) const;
-
- bool ImportKey(keymaster_key_format_t key_format, const KeymasterKeyBlob& to_import,
- KeymasterKeyBlob* imported_key_material) const;
- bool DeleteKey(const KeymasterKeyBlob& blob) const;
- bool DeleteAllKeys() const;
-
- RSA* BlobToRsaKey(const KeymasterKeyBlob& blob) const;
- EC_KEY* BlobToEcKey(const KeymasterKeyBlob& blob) const;
-
- 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:
- Keymaster0Engine(const Keymaster0Engine&); // Uncopyable
- void operator=(const Keymaster0Engine&); // Unassignable
-
- static int keyblob_dup(CRYPTO_EX_DATA* to, const CRYPTO_EX_DATA* from, void** from_d, int index,
- long argl, void* argp);
- static void keyblob_free(void* parent, void* ptr, CRYPTO_EX_DATA* data, int index, long argl,
- void* argp);
- static int rsa_private_transform(RSA* rsa, uint8_t* out, const uint8_t* in, size_t len);
- static int ecdsa_sign(const uint8_t* digest, size_t digest_len, uint8_t* sig,
- unsigned int* sig_len, EC_KEY* ec_key);
-
- struct Malloc_Delete {
- void operator()(void* p) { free(p); }
- };
-
- bool Keymaster0Sign(const void* signing_params, const keymaster_key_blob_t& key_blob,
- const uint8_t* data, const size_t data_length,
- std::unique_ptr<uint8_t[], Malloc_Delete>* signature,
- size_t* signature_length) const;
-
- int RsaPrivateTransform(RSA* rsa, uint8_t* out, const uint8_t* in, size_t len) const;
- int EcdsaSign(const uint8_t* digest, size_t digest_len, uint8_t* sig, unsigned int* sig_len,
- EC_KEY* ec_key) const;
-
- const keymaster0_device_t* keymaster0_device_;
- ENGINE* const engine_;
- int rsa_index_, ec_key_index_;
- bool supports_ec_;
- RSA_METHOD rsa_method_;
- ECDSA_METHOD ecdsa_method_;
-
- static Keymaster0Engine* instance_;
-};
-
-} // namespace keymaster
-
-#endif // SYSTEM_KEYMASTER_KEYMASTER0_ENGINE_H_
diff --git a/include/keymaster/legacy_support/keymaster1_engine.h b/include/keymaster/legacy_support/keymaster1_engine.h
index 9fe9ee9..004dbe2 100644
--- a/include/keymaster/legacy_support/keymaster1_engine.h
+++ b/include/keymaster/legacy_support/keymaster1_engine.h
@@ -14,8 +14,7 @@
* limitations under the License.
*/
-#ifndef SYSTEM_KEYMASTER_KEYMASTER1_ENGINE_H_
-#define SYSTEM_KEYMASTER_KEYMASTER1_ENGINE_H_
+#pragma once
#include <memory>
@@ -31,7 +30,6 @@
#include <keymaster/authorization_set.h>
#include <keymaster/km_openssl/openssl_utils.h>
-
namespace keymaster {
class Keymaster1Engine {
@@ -96,7 +94,9 @@
keymaster_blob_t* output);
static int duplicate_key_data(CRYPTO_EX_DATA* to, const CRYPTO_EX_DATA* from, void** from_d,
+ // NOLINTNEXTLINE(google-runtime-int)
int index, long argl, void* argp);
+ // NOLINTNEXTLINE(google-runtime-int)
static void free_key_data(void* parent, void* ptr, CRYPTO_EX_DATA* data, int index, long argl,
void* argp);
@@ -119,5 +119,3 @@
};
} // namespace keymaster
-
-#endif // SYSTEM_KEYMASTER_KEYMASTER1_ENGINE_H_
diff --git a/include/keymaster/legacy_support/keymaster1_legacy_support.h b/include/keymaster/legacy_support/keymaster1_legacy_support.h
index 5ecc4b8..a09b5e5 100644
--- a/include/keymaster/legacy_support/keymaster1_legacy_support.h
+++ b/include/keymaster/legacy_support/keymaster1_legacy_support.h
@@ -15,30 +15,29 @@
** limitations under the License.
*/
-#ifndef LEGACY_SUPPORT_KEYMASTER1_LEGACY_SUPPORT_H_
-#define LEGACY_SUPPORT_KEYMASTER1_LEGACY_SUPPORT_H_
+#pragma once
#include <map>
#include <vector>
-#include <hardware/keymaster_defs.h>
#include <hardware/keymaster1.h>
+#include <hardware/keymaster_defs.h>
+#include <keymaster/UniquePtr.h>
#include <keymaster/android_keymaster_utils.h>
#include <keymaster/authorization_set.h>
#include <keymaster/key_factory.h>
-#include <keymaster/UniquePtr.h>
#include "ec_keymaster1_key.h"
+#include "keymaster1_engine.h"
#include "keymaster_passthrough_engine.h"
#include "keymaster_passthrough_key.h"
-#include "keymaster1_engine.h"
#include "rsa_keymaster1_key.h"
namespace keymaster {
class Keymaster1LegacySupport {
-public:
+ public:
typedef std::pair<keymaster_algorithm_t, keymaster_purpose_t> AlgPurposePair;
typedef std::map<AlgPurposePair, std::vector<keymaster_digest_t>> DigestMap;
@@ -49,57 +48,61 @@
bool RequiresSoftwareDigesting(const keymaster_digest_t digest,
const AuthProxy& key_description) const;
-private:
+ private:
DigestMap device_digests_;
bool supports_all_;
-
};
class SoftwareKeyBlobMaker;
-template<typename KM1_SOFTDIGEST_FACTORY>
-class Keymaster1ArbitrationFactory : public KeyFactory {
-public:
- template<typename... SOFT_FACTORY_CONSRUCTOR_ARGS>
+template <typename KM1_SOFTDIGEST_FACTORY> class Keymaster1ArbitrationFactory : public KeyFactory {
+ public:
+ template <typename... SOFT_FACTORY_CONSRUCTOR_ARGS>
Keymaster1ArbitrationFactory(const KeymasterPassthroughEngine* ptengine,
- keymaster_algorithm_t algorithm,
- const keymaster1_device_t* dev,
+ keymaster_algorithm_t algorithm, const keymaster1_device_t* dev,
SOFT_FACTORY_CONSRUCTOR_ARGS&&... args)
- : software_digest_factory_(forward<SOFT_FACTORY_CONSRUCTOR_ARGS>(args)...),
- passthrough_factory_(ptengine, algorithm),
- legacy_support_(dev){}
+ : software_digest_factory_(forward<SOFT_FACTORY_CONSRUCTOR_ARGS>(args)...),
+ passthrough_factory_(ptengine, algorithm), legacy_support_(dev) {}
keymaster_error_t GenerateKey(const AuthorizationSet& key_description,
- KeymasterKeyBlob* key_blob, AuthorizationSet* hw_enforced,
- AuthorizationSet* sw_enforced) const {
+ UniquePtr<Key> attest_key, //
+ const KeymasterBlob& issuer_subject,
+ KeymasterKeyBlob* key_blob, //
+ AuthorizationSet* hw_enforced, //
+ AuthorizationSet* sw_enforced,
+ CertificateChain* cert_chain) const {
if (legacy_support_.RequiresSoftwareDigesting(key_description)) {
- return software_digest_factory_.GenerateKey(key_description, key_blob, hw_enforced,
- sw_enforced);
+ return software_digest_factory_.GenerateKey(key_description, move(attest_key),
+ issuer_subject, key_blob, hw_enforced,
+ sw_enforced, cert_chain);
} else {
- return passthrough_factory_.GenerateKey(key_description, key_blob, hw_enforced,
- sw_enforced);
+ return passthrough_factory_.GenerateKey(key_description, move(attest_key),
+ issuer_subject, key_blob, hw_enforced,
+ sw_enforced, cert_chain);
}
}
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 {
+ UniquePtr<Key> attest_key, //
+ const KeymasterBlob& issuer_subject,
+ KeymasterKeyBlob* output_key_blob, //
+ AuthorizationSet* hw_enforced, //
+ AuthorizationSet* sw_enforced, CertificateChain* cert_chain) const {
if (legacy_support_.RequiresSoftwareDigesting(key_description)) {
- return software_digest_factory_.ImportKey(key_description, input_key_material_format,
- input_key_material, output_key_blob,
- hw_enforced, sw_enforced);
+ return software_digest_factory_.ImportKey(
+ key_description, input_key_material_format, input_key_material, move(attest_key),
+ issuer_subject, output_key_blob, hw_enforced, sw_enforced, cert_chain);
} else {
- return passthrough_factory_.ImportKey(key_description, input_key_material_format,
- input_key_material, output_key_blob,
- hw_enforced, sw_enforced);
+ return passthrough_factory_.ImportKey(
+ key_description, input_key_material_format, input_key_material, move(attest_key),
+ issuer_subject, output_key_blob, hw_enforced, sw_enforced, cert_chain);
}
}
keymaster_error_t LoadKey(KeymasterKeyBlob&& key_material,
const AuthorizationSet& additional_params,
- AuthorizationSet&& hw_enforced,
- AuthorizationSet&& sw_enforced,
+ AuthorizationSet&& hw_enforced, AuthorizationSet&& sw_enforced,
UniquePtr<Key>* key) const override {
keymaster_digest_t digest;
if (!additional_params.GetTagValue(TAG_DIGEST, &digest)) {
@@ -124,7 +127,7 @@
}
// Informational methods.
- const keymaster_key_format_t* SupportedImportFormats(size_t* format_count) const override {
+ const keymaster_key_format_t* SupportedImportFormats(size_t* format_count) const override {
*format_count = 0;
return nullptr;
}
@@ -133,36 +136,30 @@
return nullptr;
}
-private:
+ private:
KM1_SOFTDIGEST_FACTORY software_digest_factory_;
KeymasterPassthroughKeyFactory passthrough_factory_;
Keymaster1LegacySupport legacy_support_;
};
-template<>
-keymaster_error_t
-Keymaster1ArbitrationFactory<EcdsaKeymaster1KeyFactory>::GenerateKey(
- const AuthorizationSet& key_description,
- KeymasterKeyBlob* key_blob, AuthorizationSet* hw_enforced,
- AuthorizationSet* sw_enforced) const;
+template <>
+keymaster_error_t Keymaster1ArbitrationFactory<EcdsaKeymaster1KeyFactory>::GenerateKey(
+ const AuthorizationSet& key_description, //
+ UniquePtr<Key> attest_key, //
+ const KeymasterBlob& issuer_subject, //
+ KeymasterKeyBlob* key_blob, //
+ AuthorizationSet* hw_enforced, //
+ AuthorizationSet* sw_enforced, //
+ CertificateChain* cert_chain) const;
+template <>
+keymaster_error_t Keymaster1ArbitrationFactory<EcdsaKeymaster1KeyFactory>::LoadKey(
+ KeymasterKeyBlob&& key_material, const AuthorizationSet& additional_params,
+ AuthorizationSet&& hw_enforced, AuthorizationSet&& sw_enforced, UniquePtr<Key>* key) const;
-template<>
-keymaster_error_t
-Keymaster1ArbitrationFactory<EcdsaKeymaster1KeyFactory>::LoadKey(KeymasterKeyBlob&& key_material,
- const AuthorizationSet& additional_params,
- AuthorizationSet&& hw_enforced,
- AuthorizationSet&& sw_enforced,
- UniquePtr<Key>* key) const;
+template <>
+keymaster_error_t Keymaster1ArbitrationFactory<RsaKeymaster1KeyFactory>::LoadKey(
+ KeymasterKeyBlob&& key_material, const AuthorizationSet& additional_params,
+ AuthorizationSet&& hw_enforced, AuthorizationSet&& sw_enforced, UniquePtr<Key>* key) const;
-template<>
-keymaster_error_t
-Keymaster1ArbitrationFactory<RsaKeymaster1KeyFactory>::LoadKey(KeymasterKeyBlob&& key_material,
- const AuthorizationSet& additional_params,
- AuthorizationSet&& hw_enforced,
- AuthorizationSet&& sw_enforced,
- UniquePtr<Key>* key) const;
-
-} // namespace keymaster
-
-#endif // LEGACY_SUPPORT_KEYMASTER1_LEGACY_SUPPORT_H_
+} // namespace keymaster
diff --git a/include/keymaster/legacy_support/keymaster_passthrough_engine.h b/include/keymaster/legacy_support/keymaster_passthrough_engine.h
index a986ffe..5d43cbe 100644
--- a/include/keymaster/legacy_support/keymaster_passthrough_engine.h
+++ b/include/keymaster/legacy_support/keymaster_passthrough_engine.h
@@ -15,8 +15,7 @@
** limitations under the License.
*/
-#ifndef SYSTEM_KEYMASTER_KEYMASTER2_ENGINE_H_
-#define SYSTEM_KEYMASTER_KEYMASTER2_ENGINE_H_
+#pragma once
#include <memory>
@@ -41,32 +40,30 @@
public:
virtual ~KeymasterPassthroughEngine() {}
virtual keymaster_error_t GenerateKey(const AuthorizationSet& key_description,
- KeymasterKeyBlob* key_material, AuthorizationSet* hw_enforced,
- AuthorizationSet* sw_enforced) const = 0;
+ KeymasterKeyBlob* key_material,
+ AuthorizationSet* hw_enforced,
+ AuthorizationSet* sw_enforced) const = 0;
virtual 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 = 0;
- virtual keymaster_error_t ExportKey(keymaster_key_format_t format,
- const KeymasterKeyBlob& blob,
- const KeymasterBlob& client_id,
- const KeymasterBlob& app_data,
- KeymasterBlob* export_data) const = 0;
+ keymaster_key_format_t input_key_material_format,
+ const KeymasterKeyBlob& input_key_material,
+ KeymasterKeyBlob* output_key_blob,
+ AuthorizationSet* hw_enforced,
+ AuthorizationSet* sw_enforced) const = 0;
+ virtual keymaster_error_t ExportKey(keymaster_key_format_t format, const KeymasterKeyBlob& blob,
+ const KeymasterBlob& client_id,
+ const KeymasterBlob& app_data,
+ KeymasterBlob* export_data) const = 0;
virtual keymaster_error_t DeleteKey(const KeymasterKeyBlob& blob) const = 0;
virtual keymaster_error_t DeleteAllKeys() const = 0;
virtual OperationFactory* GetOperationFactory(keymaster_purpose_t purpose,
keymaster_algorithm_t algorithm) const = 0;
- static UniquePtr<KeymasterPassthroughEngine>
- createInstance(const keymaster1_device_t* dev);
- static UniquePtr<KeymasterPassthroughEngine>
- createInstance(const keymaster2_device_t* dev);
+ static UniquePtr<KeymasterPassthroughEngine> createInstance(const keymaster1_device_t* dev);
+ static UniquePtr<KeymasterPassthroughEngine> createInstance(const keymaster2_device_t* dev);
+
protected:
KeymasterPassthroughEngine() {}
};
-} // namespace keymaster
-
-#endif // SYSTEM_KEYMASTER_KEYMASTER2_ENGINE_H_
+} // namespace keymaster
diff --git a/include/keymaster/legacy_support/keymaster_passthrough_key.h b/include/keymaster/legacy_support/keymaster_passthrough_key.h
index da51758..e262181 100644
--- a/include/keymaster/legacy_support/keymaster_passthrough_key.h
+++ b/include/keymaster/legacy_support/keymaster_passthrough_key.h
@@ -15,50 +15,55 @@
** limitations under the License.
*/
-#ifndef SYSTEM_KEYMASTER_KEYMASTER_PASSTHROUGH_KEY_H_
-#define SYSTEM_KEYMASTER_KEYMASTER_PASSTHROUGH_KEY_H_
+#pragma once
-#include <keymaster/key.h>
#include <keymaster/android_keymaster_utils.h>
-#include <keymaster/logger.h>
-#include <keymaster/key_factory.h>
#include <keymaster/authorization_set.h>
+#include <keymaster/key.h>
+#include <keymaster/key_factory.h>
+#include <keymaster/logger.h>
#include "keymaster_passthrough_engine.h"
namespace keymaster {
-//class SoftKeymasterContext;
+// class SoftKeymasterContext;
/**
- * KeymasterPassthroughKeyFactory is a KeyFactory that creates and loads keys which are actually backed
- * by a hardware keymaster2 module.
+ * KeymasterPassthroughKeyFactory is a KeyFactory that creates and loads keys which are actually
+ * backed by a hardware keymaster2 module.
*/
class KeymasterPassthroughKeyFactory : public KeyFactory {
using engine_t = KeymasterPassthroughEngine;
+
public:
KeymasterPassthroughKeyFactory(const engine_t* engine, keymaster_algorithm_t algorithm)
- : KeyFactory(), engine_(engine), algorithm_(algorithm) {}
+ : KeyFactory(), engine_(engine), algorithm_(algorithm) {}
keymaster_error_t GenerateKey(const AuthorizationSet& key_description,
+ UniquePtr<Key> /* attest_key */,
+ const KeymasterBlob& /* issuer_subject */,
KeymasterKeyBlob* key_blob, AuthorizationSet* hw_enforced,
- AuthorizationSet* sw_enforced) const override {
+ AuthorizationSet* sw_enforced,
+ CertificateChain* /* cert_chain */) const override {
return engine_->GenerateKey(key_description, key_blob, hw_enforced, sw_enforced);
}
keymaster_error_t ImportKey(const AuthorizationSet& key_description,
keymaster_key_format_t input_key_material_format,
const KeymasterKeyBlob& input_key_material,
+ UniquePtr<Key> /* attest_key */,
+ const KeymasterBlob& /* issuer_subject */,
KeymasterKeyBlob* output_key_blob, AuthorizationSet* hw_enforced,
- AuthorizationSet* sw_enforced) const override {
+ AuthorizationSet* sw_enforced,
+ CertificateChain* /* cert_chain */) const override {
return engine_->ImportKey(key_description, input_key_material_format, input_key_material,
output_key_blob, hw_enforced, sw_enforced);
}
keymaster_error_t LoadKey(KeymasterKeyBlob&& key_material,
const AuthorizationSet& additional_params,
- AuthorizationSet&& hw_enforced,
- AuthorizationSet&& sw_enforced,
+ AuthorizationSet&& hw_enforced, AuthorizationSet&& sw_enforced,
UniquePtr<Key>* key) const override;
OperationFactory* GetOperationFactory(keymaster_purpose_t purpose) const override {
@@ -76,16 +81,15 @@
class KeymasterPassthroughKey : public Key {
public:
KeymasterPassthroughKey(KeymasterKeyBlob&& key_material, AuthorizationSet&& hw_enforced,
- AuthorizationSet&& sw_enforced,
- const KeyFactory* key_factory, keymaster_error_t* error,
- const AuthorizationSet& additional_parameters,
- const KeymasterPassthroughEngine* engine)
+ AuthorizationSet&& sw_enforced, const KeyFactory* key_factory,
+ keymaster_error_t* error, const AuthorizationSet& additional_parameters,
+ const KeymasterPassthroughEngine* engine)
: Key(move(hw_enforced), move(sw_enforced), key_factory),
additional_parameters_(additional_parameters), engine_(engine) {
key_material_ = move(key_material);
if (*error != KM_ERROR_OK) return;
- if (additional_parameters.is_valid() != additional_parameters_.is_valid()
- && additional_parameters_.is_valid() == AuthorizationSet::ALLOCATION_FAILURE) {
+ if (additional_parameters.is_valid() != additional_parameters_.is_valid() &&
+ additional_parameters_.is_valid() == AuthorizationSet::ALLOCATION_FAILURE) {
*error = KM_ERROR_MEMORY_ALLOCATION_FAILED;
}
}
@@ -100,5 +104,3 @@
};
} // namespace keymaster
-
-#endif // SYSTEM_KEYMASTER_KEYMASTER_PASSTHROUGH_KEY_H_
diff --git a/include/keymaster/legacy_support/rsa_keymaster0_key.h b/include/keymaster/legacy_support/rsa_keymaster0_key.h
deleted file mode 100644
index faf13ed..0000000
--- a/include/keymaster/legacy_support/rsa_keymaster0_key.h
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * 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_KEYMASTER0_KEY_H_
-#define SYSTEM_KEYMASTER_RSA_KEYMASTER0_KEY_H_
-
-#include <openssl/rsa.h>
-
-#include <keymaster/km_openssl/rsa_key.h>
-#include <keymaster/km_openssl/rsa_key_factory.h>
-
-namespace keymaster {
-
-class Keymaster0Engine;
-
-/**
- * An RsaKeyFactory which can delegate key generation, importing and loading operations to a
- * keymaster0-backed OpenSSL engine.
- */
-class RsaKeymaster0KeyFactory : public RsaKeyFactory {
- typedef RsaKeyFactory super;
-
- public:
- RsaKeymaster0KeyFactory(const SoftwareKeyBlobMaker* blob_maker,
- const Keymaster0Engine* 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(KeymasterKeyBlob&& key_material,
- const AuthorizationSet& additional_params,
- AuthorizationSet&& hw_enforced,
- AuthorizationSet&& sw_enforced,
- UniquePtr<Key>* key) const override;
-
- private:
- const Keymaster0Engine* engine_;
-};
-
-class RsaKeymaster0Key : public RsaKey {
- public:
- RsaKeymaster0Key(RSA* rsa_key, AuthorizationSet&& hw_enforced,
- AuthorizationSet&& sw_enforced,
- const KeyFactory* key_factory)
- : RsaKey(rsa_key, move(hw_enforced), move(sw_enforced), key_factory) {}
-};
-
-} // namespace keymaster
-
-#endif // SYSTEM_KEYMASTER_RSA_KEYMASTER0_KEY_H_
diff --git a/include/keymaster/legacy_support/rsa_keymaster1_key.h b/include/keymaster/legacy_support/rsa_keymaster1_key.h
index 43c5e10..e114aef 100644
--- a/include/keymaster/legacy_support/rsa_keymaster1_key.h
+++ b/include/keymaster/legacy_support/rsa_keymaster1_key.h
@@ -14,8 +14,7 @@
* limitations under the License.
*/
-#ifndef SYSTEM_KEYMASTER_RSA_KEYMASTER1_KEY_H_
-#define SYSTEM_KEYMASTER_RSA_KEYMASTER1_KEY_H_
+#pragma once
#include <openssl/rsa.h>
@@ -39,23 +38,30 @@
*/
class RsaKeymaster1KeyFactory : public RsaKeyFactory {
public:
- RsaKeymaster1KeyFactory(const SoftwareKeyBlobMaker* blob_maker,
+ RsaKeymaster1KeyFactory(const SoftwareKeyBlobMaker& blob_maker, const KeymasterContext& context,
const Keymaster1Engine* engine);
keymaster_error_t GenerateKey(const AuthorizationSet& key_description,
- KeymasterKeyBlob* key_blob, AuthorizationSet* hw_enforced,
- AuthorizationSet* sw_enforced) const override;
+ UniquePtr<Key> attest_key, //
+ const KeymasterBlob& issuer_subject, //
+ KeymasterKeyBlob* key_blob,
+ AuthorizationSet* hw_enforced, //
+ AuthorizationSet* sw_enforced,
+ CertificateChain* cert_chain) 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;
+ UniquePtr<Key> attest_key, //
+ const KeymasterBlob& issuer_subject,
+ KeymasterKeyBlob* output_key_blob,
+ AuthorizationSet* hw_enforced, //
+ AuthorizationSet* sw_enforced,
+ CertificateChain* cert_chain) const override;
keymaster_error_t LoadKey(KeymasterKeyBlob&& key_material,
const AuthorizationSet& additional_params,
- AuthorizationSet&& hw_enforced,
- AuthorizationSet&& sw_enforced,
+ AuthorizationSet&& hw_enforced, AuthorizationSet&& sw_enforced,
UniquePtr<Key>* key) const override;
OperationFactory* GetOperationFactory(keymaster_purpose_t purpose) const override;
@@ -71,12 +77,9 @@
class RsaKeymaster1Key : public RsaKey {
public:
- RsaKeymaster1Key(RSA* rsa_key, AuthorizationSet&& hw_enforced,
- AuthorizationSet&& sw_enforced,
+ RsaKeymaster1Key(RSA* rsa_key, AuthorizationSet&& hw_enforced, AuthorizationSet&& sw_enforced,
const KeyFactory* key_factory)
: RsaKey(rsa_key, move(hw_enforced), move(sw_enforced), key_factory) {}
};
} // namespace keymaster
-
-#endif // SYSTEM_KEYMASTER_RSA_KEYMASTER1_KEY_H_
diff --git a/include/keymaster/mem.h b/include/keymaster/mem.h
new file mode 100644
index 0000000..6d5de1b
--- /dev/null
+++ b/include/keymaster/mem.h
@@ -0,0 +1,172 @@
+/*
+ * Copyright 2021 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.
+ */
+
+#pragma once
+
+namespace keymaster {
+
+using std::forward;
+using std::move;
+
+/*
+ * Array Manipulation functions. This set of templated inline functions provides some nice tools
+ * for operating on c-style arrays. C-style arrays actually do have a defined size associated with
+ * them, as long as they are not allowed to decay to a pointer. These template methods exploit this
+ * to allow size-based array operations without explicitly specifying the size. If passed a pointer
+ * rather than an array, they'll fail to compile.
+ */
+
+/**
+ * Return the size in bytes of the array \p a.
+ */
+template <typename T, size_t N> inline size_t array_size(const T (&a)[N]) {
+ return sizeof(a);
+}
+
+/**
+ * Return the number of elements in array \p a.
+ */
+template <typename T, size_t N> inline size_t array_length(const T (&)[N]) {
+ return N;
+}
+
+/**
+ * Duplicate the array \p a. The memory for the new array is allocated and the caller takes
+ * responsibility.
+ */
+template <typename T> inline T* dup_array(const T* a, size_t n) {
+ T* dup = new (std::nothrow) T[n];
+ if (dup)
+ for (size_t i = 0; i < n; ++i)
+ dup[i] = a[i];
+ return dup;
+}
+
+/**
+ * Duplicate the array \p a. The memory for the new array is allocated and the caller takes
+ * responsibility. Note that the dup is necessarily returned as a pointer, so size is lost. Call
+ * array_length() on the original array to discover the size.
+ */
+template <typename T, size_t N> inline T* dup_array(const T (&a)[N]) {
+ return dup_array(a, N);
+}
+
+/**
+ * Duplicate the buffer \p buf. The memory for the new buffer is allocated and the caller takes
+ * responsibility.
+ */
+uint8_t* dup_buffer(const void* buf, size_t size);
+
+/**
+ * Copy the contents of array \p arr to \p dest.
+ */
+template <typename T, size_t N> inline void copy_array(const T (&arr)[N], T* dest) {
+ for (size_t i = 0; i < N; ++i)
+ dest[i] = arr[i];
+}
+
+/**
+ * Search array \p a for value \p val, returning true if found. Note that this function is
+ * early-exit, meaning that it should not be used in contexts where timing analysis attacks could be
+ * a concern.
+ */
+template <typename T, size_t N> inline bool array_contains(const T (&a)[N], T val) {
+ for (size_t i = 0; i < N; ++i) {
+ if (a[i] == val) {
+ return true;
+ }
+ }
+ return false;
+}
+
+/**
+ * Variant of memset() that uses GCC-specific pragmas to disable optimizations, so effect is not
+ * optimized away. This is important because we often need to wipe blocks of sensitive data from
+ * memory. As an additional convenience, this implementation avoids writing to NULL pointers.
+ */
+#ifdef __clang__
+#define OPTNONE __attribute__((optnone))
+#else // not __clang__
+#define OPTNONE __attribute__((optimize("O0")))
+#endif // not __clang__
+inline OPTNONE void* memset_s(void* s, int c, size_t n) {
+ if (!s) return s;
+ return memset(s, c, n);
+}
+#undef OPTNONE
+
+/**
+ * Variant of memcmp that has the same runtime regardless of whether the data matches (i.e. doesn't
+ * short-circuit). Not an exact equivalent to memcmp because it doesn't return <0 if p1 < p2, just
+ * 0 for match and non-zero for non-match.
+ */
+int memcmp_s(const void* p1, const void* p2, size_t length);
+
+/**
+ * Eraser clears buffers. Construct it with a buffer or object and the destructor will ensure that
+ * it is zeroed.
+ */
+class Eraser {
+ public:
+ /* Not implemented. If this gets used, we want a link error. */
+ template <typename T> explicit Eraser(T* t);
+
+ template <typename T>
+ explicit Eraser(T& t) : buf_(reinterpret_cast<uint8_t*>(&t)), size_(sizeof(t)) {}
+
+ template <size_t N> explicit Eraser(uint8_t (&arr)[N]) : buf_(arr), size_(N) {}
+
+ Eraser(void* buf, size_t size) : buf_(static_cast<uint8_t*>(buf)), size_(size) {}
+ ~Eraser() { memset_s(buf_, 0, size_); }
+
+ private:
+ Eraser(const Eraser&);
+ void operator=(const Eraser&);
+
+ uint8_t* buf_;
+ size_t size_;
+};
+
+/**
+ * ArrayWrapper is a trivial wrapper around a C-style array that provides begin() and end()
+ * methods. This is primarily to facilitate range-based iteration on arrays. It does not copy, nor
+ * does it take ownership; it just holds pointers.
+ */
+template <typename T> class ArrayWrapper {
+ public:
+ ArrayWrapper(T* array, size_t size) : begin_(array), end_(array + size) {}
+
+ T* begin() { return begin_; }
+ T* end() { return end_; }
+
+ private:
+ T* begin_;
+ T* end_;
+};
+
+template <typename T> ArrayWrapper<T> array_range(T* begin, size_t length) {
+ return ArrayWrapper<T>(begin, length);
+}
+
+template <typename T, size_t n> ArrayWrapper<T> array_range(T (&a)[n]) {
+ return ArrayWrapper<T>(a, n);
+}
+
+struct Malloc_Delete {
+ void operator()(void* p) { free(p); }
+};
+
+} // namespace keymaster
diff --git a/include/keymaster/new.h b/include/keymaster/new.h
deleted file mode 100644
index 17537e0..0000000
--- a/include/keymaster/new.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
-**
-** Copyright 2017, 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 INCLUDE_KEYMASTER_NEW_
-#define INCLUDE_KEYMASTER_NEW_
-
-#include <stddef.h>
-
-namespace std {
-struct nothrow_t;
-extern const nothrow_t nothrow;
-} // namespace std
-
-#ifndef _NOEXCEPT
-#define _NOEXCEPT
-#endif
-
-void* operator new(size_t __sz, const std::nothrow_t&) _NOEXCEPT;
-void* operator new[](size_t __sz, const std::nothrow_t&) _NOEXCEPT;
-void operator delete(void* ptr);
-void operator delete[](void* ptr);
-
-#endif // INCLUDE_KEYMASTER_NEW_
diff --git a/include/keymaster/operation.h b/include/keymaster/operation.h
index 656ba9d..e80e37a 100644
--- a/include/keymaster/operation.h
+++ b/include/keymaster/operation.h
@@ -106,6 +106,28 @@
virtual keymaster_operation_handle_t operation_handle() const { return operation_handle_; }
AuthProxy authorizations() const { return AuthProxy(hw_enforced_, sw_enforced_); }
+ AuthorizationSet hw_enforced() const { return hw_enforced_; }
+ AuthorizationSet sw_enforced() const { return sw_enforced_; }
+
+ // Creates and initializes |confirmation_verifier_buffer_| that can be retrieved with
+ // get_confirmation_verifier_buffer().
+ //
+ // Returns false on allocation failure.
+ bool create_confirmation_verifier_buffer() {
+ if (!confirmation_verifier_buffer_) {
+ Buffer* buffer = new (std::nothrow)
+ Buffer(kConfirmationTokenMessageTag, kConfirmationTokenMessageTagSize);
+ if (buffer == nullptr) {
+ return false;
+ }
+ confirmation_verifier_buffer_.reset(buffer);
+ }
+ return true;
+ }
+
+ // If a Buffer for ConfirmationUI verification was created with
+ // create_confirmation_verifier_buffer(), returns it. If not, returns |nullptr|.
+ Buffer* get_confirmation_verifier_buffer() { return confirmation_verifier_buffer_.get(); }
virtual keymaster_error_t Begin(const AuthorizationSet& input_params,
AuthorizationSet* output_params) = 0;
@@ -128,6 +150,7 @@
AuthorizationSet hw_enforced_;
AuthorizationSet sw_enforced_;
uint64_t key_id_;
+ UniquePtr<Buffer> confirmation_verifier_buffer_;
};
} // namespace keymaster
diff --git a/include/keymaster/operation_table.h b/include/keymaster/operation_table.h
index 5b5c068..0e2bc4b 100644
--- a/include/keymaster/operation_table.h
+++ b/include/keymaster/operation_table.h
@@ -14,8 +14,7 @@
* limitations under the License.
*/
-#ifndef SYSTEM_KEYMASTER_OPERATION_TABLE_H
-#define SYSTEM_KEYMASTER_OPERATION_TABLE_H
+#pragma once
#include <keymaster/UniquePtr.h>
@@ -27,11 +26,9 @@
class Operation;
using OperationPtr = UniquePtr<Operation>;
-
class OperationTable {
public:
- explicit OperationTable(size_t table_size) :
- table_size_(table_size) {}
+ explicit OperationTable(size_t table_size) : table_size_(table_size) {}
keymaster_error_t Add(OperationPtr&& operation);
Operation* Find(keymaster_operation_handle_t op_handle);
@@ -43,5 +40,3 @@
};
} // namespace keymaster
-
-#endif // SYSTEM_KEYMASTER_OPERATION_TABLE_H
diff --git a/include/keymaster/pure_soft_secure_key_storage.h b/include/keymaster/pure_soft_secure_key_storage.h
new file mode 100644
index 0000000..563db61
--- /dev/null
+++ b/include/keymaster/pure_soft_secure_key_storage.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2021, 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.
+ */
+
+#pragma once
+
+#include <keymaster/secure_key_storage.h>
+
+namespace keymaster {
+
+class PureSoftSecureStorageMap;
+
+/**
+ * This is the pure software emulation of secure key storage.
+ */
+class PureSoftSecureKeyStorage : public SecureKeyStorage {
+ public:
+ explicit PureSoftSecureKeyStorage(uint32_t max_slot);
+ ~PureSoftSecureKeyStorage() override;
+
+ /**
+ * Writes the key blob along with the keyid as the index into pure software emulated secure
+ * key storage.
+ */
+ keymaster_error_t WriteKey(const km_id_t keyid, const KeymasterKeyBlob& blob) override;
+
+ /**
+ * Checks if the key blob with key id exists in pure software secure key storage.
+ */
+ keymaster_error_t KeyExists(const km_id_t keyid, bool* exists) override;
+
+ /**
+ * Deletes the key blob with key id from pure software secure key storage.
+ */
+ keymaster_error_t DeleteKey(const km_id_t keyid) override;
+
+ /**
+ * Deletes all the key blob from pure software secure key storage.
+ */
+ keymaster_error_t DeleteAllKeys() override;
+
+ /**
+ * Checks if the pure software secure key storage still has available slot.
+ */
+ keymaster_error_t HasSlot(bool* has_slot) override;
+
+ private:
+ PureSoftSecureStorageMap* pure_soft_secure_storage_map_;
+};
+
+} // namespace keymaster
diff --git a/include/keymaster/random_source.h b/include/keymaster/random_source.h
index a9c45ad..2d0a492 100644
--- a/include/keymaster/random_source.h
+++ b/include/keymaster/random_source.h
@@ -15,25 +15,22 @@
** limitations under the License.
*/
-#ifndef INCLUDE_KEYMASTER_RANDOM_SOURCE_H_
-#define INCLUDE_KEYMASTER_RANDOM_SOURCE_H_
+#pragma once
-#include <stdint.h>
#include <hardware/keymaster_defs.h>
+#include <stdint.h>
namespace keymaster {
class RandomSource {
-protected:
- virtual ~RandomSource () {}
+ protected:
+ virtual ~RandomSource() {}
-public:
+ public:
/**
* Generates \p length random bytes, placing them in \p buf.
*/
virtual keymaster_error_t GenerateRandom(uint8_t* buffer, size_t length) const = 0;
};
-} // namespace keymaster
-
-#endif // INCLUDE_KEYMASTER_RANDOM_SOURCE_H_
+} // namespace keymaster
diff --git a/include/keymaster/remote_provisioning_context.h b/include/keymaster/remote_provisioning_context.h
new file mode 100644
index 0000000..a5c4d1d
--- /dev/null
+++ b/include/keymaster/remote_provisioning_context.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2021 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.
+ */
+
+#pragma once
+
+#include <array>
+#include <optional>
+#include <string>
+#include <tuple>
+#include <vector>
+
+#include <cppbor.h>
+#include <keymaster/cppcose/cppcose.h>
+
+namespace keymaster {
+
+class RemoteProvisioningContext {
+ public:
+ RemoteProvisioningContext() {}
+ virtual ~RemoteProvisioningContext(){};
+ virtual std::vector<uint8_t> DeriveBytesFromHbk(const std::string& context,
+ size_t numBytes) const = 0;
+ virtual std::unique_ptr<cppbor::Map> CreateDeviceInfo() const = 0;
+ virtual std::pair<std::vector<uint8_t>, cppbor::Array> GenerateBcc(bool testMode) const = 0;
+
+ // Generate an HMAC-SHA256 over the given input. This is used to verify a given
+ // input hasn't changed across multiple calls to the remote provisioning HAL.
+ virtual std::optional<cppcose::HmacSha256>
+ GenerateHmacSha256(const cppcose::bytevec& input) const = 0;
+
+ std::vector<uint8_t> devicePrivKey_;
+ cppbor::Array bcc_;
+
+ private:
+ // Uncopyable.
+ RemoteProvisioningContext(const RemoteProvisioningContext&);
+ void operator=(const RemoteProvisioningContext&);
+};
+
+} // namespace keymaster
diff --git a/include/keymaster/remote_provisioning_utils.h b/include/keymaster/remote_provisioning_utils.h
new file mode 100644
index 0000000..e3781de
--- /dev/null
+++ b/include/keymaster/remote_provisioning_utils.h
@@ -0,0 +1,78 @@
+/*
+ * Copyright 2021 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.
+ */
+
+#pragma once
+
+#include <cppbor.h>
+#include <cppbor_parse.h>
+
+#include <keymaster/android_keymaster_utils.h>
+#include <keymaster/cppcose/cppcose.h>
+
+namespace keymaster {
+
+// These are the negations of the actual error codes
+constexpr keymaster_error_t kStatusFailed = static_cast<keymaster_error_t>(-1);
+constexpr keymaster_error_t kStatusInvalidMac = static_cast<keymaster_error_t>(-2);
+constexpr keymaster_error_t kStatusProductionKeyInTestRequest = static_cast<keymaster_error_t>(-3);
+constexpr keymaster_error_t kStatusTestKeyInProductionRequest = static_cast<keymaster_error_t>(-4);
+constexpr keymaster_error_t kStatusInvalidEek = static_cast<keymaster_error_t>(-5);
+
+template <typename T> class StatusOr {
+ public:
+ StatusOr(uint32_t status_code) // NOLINT(google-explicit-constructor)
+ : status_code_(status_code) {}
+ StatusOr(T val)
+ : status_code_(0), value_(std::move(val)) {} // NOLINT(google-explicit-constructor)
+
+ bool isOk() { return status_code_ == 0; }
+
+ T* operator->() & {
+ assert(isOk());
+ return &value_.value();
+ }
+ T& operator*() & {
+ assert(isOk());
+ return value_.value();
+ }
+ T&& operator*() && {
+ assert(isOk());
+ return std::move(value_).value();
+ }
+
+ uint32_t moveError() {
+ assert(!isOk());
+ return status_code_;
+ }
+
+ T moveValue() { return std::move(value_).value(); }
+
+ private:
+ uint32_t status_code_;
+ std::optional<T> value_;
+};
+
+StatusOr<std::pair<std::vector<uint8_t> /* EEK pub */, std::vector<uint8_t> /* EEK ID */>>
+validateAndExtractEekPubAndId(bool testMode, const KeymasterBlob& endpointEncryptionCertChain);
+
+StatusOr<std::vector<uint8_t> /* pubkeys */>
+validateAndExtractPubkeys(bool testMode, uint32_t numKeys, KeymasterBlob* keysToSign,
+ cppcose::HmacSha256Function macFunction);
+
+cppbor::Array buildCertReqRecipients(const std::vector<uint8_t>& pubkey,
+ const std::vector<uint8_t>& kid);
+
+} // namespace keymaster
diff --git a/include/keymaster/secure_key_storage.h b/include/keymaster/secure_key_storage.h
new file mode 100644
index 0000000..d4d3ad6
--- /dev/null
+++ b/include/keymaster/secure_key_storage.h
@@ -0,0 +1,67 @@
+/*
+ * Copyright 2021, 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.
+ */
+
+#pragma once
+
+#include <hardware/keymaster_defs.h>
+
+namespace keymaster {
+
+typedef uint64_t km_id_t;
+template <typename BlobType> struct TKeymasterBlob;
+typedef TKeymasterBlob<keymaster_key_blob_t> KeymasterKeyBlob;
+
+/**
+ * This is the reference implementation of secure key storage of Keymaster. It implements
+ * key storage on top TEE's secure storage service. All data is stored in the secure hardware,
+ * such as RPMB filesystem.
+ */
+class SecureKeyStorage {
+ public:
+ SecureKeyStorage() {}
+ virtual ~SecureKeyStorage(){};
+
+ /**
+ * Writes the key blob into secure key storage and uses the key ID as the index of this
+ * key blob. The key ID must be the same id created by KeymasterEnforcement.CreateKeyId,
+ * which means the generated id must be stable in that the same key blob bits yield the
+ * same keyid.
+ */
+ virtual keymaster_error_t WriteKey(const km_id_t keyid, const KeymasterKeyBlob& blob) = 0;
+
+ /**
+ * Checks if the key blob with key id exists in secure key storage. On success, writes to
+ * exists.
+ */
+ virtual keymaster_error_t KeyExists(const km_id_t keyid, bool* exists) = 0;
+
+ /**
+ * Deletes the key blob with key id from secure key storage.
+ */
+ virtual keymaster_error_t DeleteKey(const km_id_t keyid) = 0;
+
+ /**
+ * Deletes all the key blob from secure key storage.
+ */
+ virtual keymaster_error_t DeleteAllKeys() = 0;
+
+ /**
+ * Checks if the secure key storage still has available slot. On success, writes to has_slot.
+ */
+ virtual keymaster_error_t HasSlot(bool* has_slot) = 0;
+};
+
+} // namespace keymaster
diff --git a/include/keymaster/serializable.h b/include/keymaster/serializable.h
index 575b691..fdc97f1 100644
--- a/include/keymaster/serializable.h
+++ b/include/keymaster/serializable.h
@@ -14,18 +14,15 @@
* limitations under the License.
*/
-#ifndef SYSTEM_KEYMASTER_SERIALIZABLE_H_
-#define SYSTEM_KEYMASTER_SERIALIZABLE_H_
+#pragma once
+#include <stddef.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
-#include <keymaster/new.h>
-#include <stddef.h>
-// #include <new>
-
#include <keymaster/UniquePtr.h>
+#include <keymaster/mem.h>
namespace keymaster {
@@ -69,7 +66,7 @@
* Convert a pointer into a value. This is used to make sure compiler won't optimize away pointer
* overflow checks. (See http://www.kb.cert.org/vuls/id/162289)
*/
-template <typename T> inline uintptr_t __pval(const T *p) {
+template <typename T> inline uintptr_t __pval(const T* p) {
return reinterpret_cast<uintptr_t>(p);
}
@@ -159,8 +156,7 @@
template <typename T>
inline bool copy_uint32_from_buf(const uint8_t** buf_ptr, const uint8_t* end, T* value) {
uint32_t val;
- if (!copy_from_buf(buf_ptr, end, &val, sizeof(val)))
- return false;
+ if (!copy_from_buf(buf_ptr, end, &val, sizeof(val))) return false;
*value = static_cast<T>(val);
return true;
}
@@ -182,20 +178,17 @@
template <typename T>
inline bool copy_uint32_array_from_buf(const uint8_t** buf_ptr, const uint8_t* end,
UniquePtr<T[]>* data, size_t* count) {
- if (!copy_uint32_from_buf(buf_ptr, end, count))
- return false;
+ if (!copy_uint32_from_buf(buf_ptr, end, count)) return false;
uintptr_t array_end = __pval(*buf_ptr) + *count * sizeof(uint32_t);
- if (*count >= UINT32_MAX / sizeof(uint32_t) ||
- array_end < __pval(*buf_ptr) || array_end > __pval(end))
+ if (*count >= UINT32_MAX / sizeof(uint32_t) || array_end < __pval(*buf_ptr) ||
+ array_end > __pval(end))
return false;
data->reset(new (std::nothrow) T[*count]);
- if (!data->get())
- return false;
+ if (!data->get()) return false;
for (size_t i = 0; i < *count; ++i)
- if (!copy_uint32_from_buf(buf_ptr, end, &(*data)[i]))
- return false;
+ if (!copy_uint32_from_buf(buf_ptr, end, &(*data)[i])) return false;
return true;
}
@@ -207,6 +200,24 @@
Buffer() : buffer_(nullptr), buffer_size_(0), read_position_(0), write_position_(0) {}
explicit Buffer(size_t size) : buffer_(nullptr) { Reinitialize(size); }
Buffer(const void* buf, size_t size) : buffer_(nullptr) { Reinitialize(buf, size); }
+ Buffer(Buffer&& b) { *this = move(b); }
+ Buffer(const Buffer&) = delete;
+
+ ~Buffer() { Clear(); }
+
+ Buffer& operator=(Buffer&& other) {
+ if (this == &other) return *this;
+ buffer_ = move(other.buffer_);
+ buffer_size_ = other.buffer_size_;
+ other.buffer_size_ = 0;
+ read_position_ = other.read_position_;
+ other.read_position_ = 0;
+ write_position_ = other.write_position_;
+ other.write_position_ = 0;
+ return *this;
+ }
+
+ void operator=(const Buffer& other) = delete;
// Grow the buffer so that at least \p size bytes can be written.
bool reserve(size_t size);
@@ -252,10 +263,6 @@
bool Deserialize(const uint8_t** buf_ptr, const uint8_t* end);
private:
- // Disallow copy construction and assignment.
- void operator=(const Buffer& other);
- Buffer(const Buffer&);
-
UniquePtr<uint8_t[]> buffer_;
size_t buffer_size_;
size_t read_position_;
@@ -263,5 +270,3 @@
};
} // namespace keymaster
-
-#endif // SYSTEM_KEYMASTER_SERIALIZABLE_H_
diff --git a/include/keymaster/soft_key_factory.h b/include/keymaster/soft_key_factory.h
index ee494cb..f59f4ee 100644
--- a/include/keymaster/soft_key_factory.h
+++ b/include/keymaster/soft_key_factory.h
@@ -14,11 +14,9 @@
* limitations under the License.
*/
-#ifndef SYSTEM_KEYMASTER_SOFTWARE_KEY_FACTORY_H_
-#define SYSTEM_KEYMASTER_SOFTWARE_KEY_FACTORY_H_
+#pragma once
#include "key_factory.h"
-#include <keymaster/attestation_record.h>
namespace keymaster {
@@ -43,8 +41,8 @@
class SoftKeyFactoryMixin {
public:
- explicit SoftKeyFactoryMixin(const SoftwareKeyBlobMaker* blob_maker)
- : blob_maker_(*blob_maker) {}
+ explicit SoftKeyFactoryMixin(const SoftwareKeyBlobMaker& blob_maker)
+ : blob_maker_(blob_maker) {}
virtual ~SoftKeyFactoryMixin() {}
protected:
@@ -52,5 +50,3 @@
};
} // namespace keymaster
-
-#endif // SYSTEM_KEYMASTER_SOFTWARE_KEY_FACTORY_H_
diff --git a/include/keymaster/soft_keymaster_device.h b/include/keymaster/soft_keymaster_device.h
index ad757b5..67a9372 100644
--- a/include/keymaster/soft_keymaster_device.h
+++ b/include/keymaster/soft_keymaster_device.h
@@ -14,20 +14,18 @@
* limitations under the License.
*/
-#ifndef SYSTEM_KEYMASTER_SOFT_KEYMASTER_DEVICE_H_
-#define SYSTEM_KEYMASTER_SOFT_KEYMASTER_DEVICE_H_
+#pragma once
#include <cstdlib>
#include <map>
#include <vector>
-#include <hardware/keymaster0.h>
#include <hardware/keymaster1.h>
#include <hardware/keymaster2.h>
+#include <keymaster/UniquePtr.h>
#include <keymaster/android_keymaster.h>
#include <keymaster/contexts/soft_keymaster_context.h>
-#include <keymaster/UniquePtr.h>
namespace keymaster {
@@ -46,17 +44,11 @@
*/
class SoftKeymasterDevice {
public:
- SoftKeymasterDevice();
+ explicit SoftKeymasterDevice(KmVersion version);
explicit 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);
-
- /**
* Set SoftKeymasterDevice to wrap specified HW keymaster1 device. Takes ownership of the
* specified device (will call keymaster1_device->common.close());
*/
@@ -250,5 +242,3 @@
};
} // namespace keymaster
-
-#endif // EXTERNAL_KEYMASTER_TRUSTY_KEYMASTER_DEVICE_H_
diff --git a/include/keymaster/soft_keymaster_logger.h b/include/keymaster/soft_keymaster_logger.h
index 3be83b8..9d65c00 100644
--- a/include/keymaster/soft_keymaster_logger.h
+++ b/include/keymaster/soft_keymaster_logger.h
@@ -14,21 +14,17 @@
* limitations under the License.
*/
-#ifndef SYSTEM_KEYMASTER_SOFT_KEYMASTER_LOGGER_H_
-#define SYSTEM_KEYMASTER_SOFT_KEYMASTER_LOGGER_H_
+#pragma once
#include <keymaster/logger.h>
namespace keymaster {
-class SoftKeymasterLogger : public Logger
-{
-public:
+class SoftKeymasterLogger : public Logger {
+ public:
SoftKeymasterLogger() { set_instance(this); }
virtual int log_msg(LogLevel level, const char* fmt, va_list args) const;
};
-} // namespace keymaster
-
-#endif // SYSTEM_KEYMASTER_SOFT_KEYMASTER_LOGGER_H_
+} // namespace keymaster
diff --git a/include/keymaster/wrapped_key.h b/include/keymaster/wrapped_key.h
index fe50e86..3331460 100644
--- a/include/keymaster/wrapped_key.h
+++ b/include/keymaster/wrapped_key.h
@@ -19,8 +19,8 @@
#include <hardware/keymaster_defs.h>
-#include <keymaster/attestation_record.h>
#include <keymaster/authorization_set.h>
+#include <keymaster/km_openssl/attestation_record.h>
namespace keymaster {
diff --git a/key_blob_utils/auth_encrypted_key_blob.cpp b/key_blob_utils/auth_encrypted_key_blob.cpp
index f5bf9c8..8d81157 100644
--- a/key_blob_utils/auth_encrypted_key_blob.cpp
+++ b/key_blob_utils/auth_encrypted_key_blob.cpp
@@ -16,122 +16,329 @@
#include <keymaster/key_blob_utils/auth_encrypted_key_blob.h>
+#include <openssl/digest.h>
+#include <openssl/evp.h>
+#include <openssl/hkdf.h>
+
#include <keymaster/android_keymaster_utils.h>
#include <keymaster/authorization_set.h>
#include <keymaster/key_blob_utils/ocb_utils.h>
+#include <keymaster/km_openssl/openssl_err.h>
#include <keymaster/logger.h>
-
+#include <keymaster/random_source.h>
namespace keymaster {
-const uint32_t CURRENT_BLOB_VERSION = 0;
+namespace {
-keymaster_error_t SerializeAuthEncryptedBlob(const KeymasterKeyBlob& encrypted_key_material,
- const AuthorizationSet& hw_enforced,
- const AuthorizationSet& sw_enforced,
+constexpr uint8_t kAesGcmDescriptor[] = "AES-256-GCM-HKDF-SHA-256, version 1";
+constexpr size_t kAesGcmNonceLength = 12;
+constexpr size_t kAesGcmTagLength = 16;
+constexpr size_t kAes256KeyLength = 256 / 8;
- const Buffer& nonce, const Buffer& tag,
- KeymasterKeyBlob* key_blob) {
- size_t size = 1 /* version byte */ + nonce.SerializedSize() +
- encrypted_key_material.SerializedSize() + tag.SerializedSize() +
- hw_enforced.SerializedSize() + sw_enforced.SerializedSize();
+Buffer generate_nonce(const RandomSource& random, size_t size, keymaster_error_t* error) {
+ if (!error) return {};
+ *error = KM_ERROR_OK;
- if (!key_blob->Reset(size))
- return KM_ERROR_MEMORY_ALLOCATION_FAILED;
+ Buffer nonce;
+ if (!nonce.Reinitialize(size)) {
+ *error = KM_ERROR_MEMORY_ALLOCATION_FAILED;
+ return {};
+ }
- uint8_t* buf = key_blob->writable_data();
- const uint8_t* end = key_blob->key_material + key_blob->key_material_size;
+ random.GenerateRandom(nonce.peek_write(), size);
+ nonce.advance_write(size);
+ return nonce;
+}
- *buf++ = CURRENT_BLOB_VERSION;
- buf = nonce.Serialize(buf, end);
- buf = encrypted_key_material.Serialize(buf, end);
- buf = tag.Serialize(buf, end);
+Buffer BuildAesGcmInfo(const AuthorizationSet& hw_enforced, const AuthorizationSet& sw_enforced,
+ const AuthorizationSet& hidden, keymaster_error_t* error) {
+ if (!error) return {};
+ *error = KM_ERROR_OK;
+
+ size_t info_len = sizeof(kAesGcmDescriptor) + hidden.SerializedSize() +
+ hw_enforced.SerializedSize() + sw_enforced.SerializedSize();
+ Buffer info(info_len);
+
+ info.write(kAesGcmDescriptor, sizeof(kAesGcmDescriptor));
+ uint8_t* buf = info.peek_write();
+ const uint8_t* end = info.peek_write() + info.available_write();
+ buf = hidden.Serialize(buf, end);
buf = hw_enforced.Serialize(buf, end);
buf = sw_enforced.Serialize(buf, end);
- if (buf != key_blob->key_material + key_blob->key_material_size)
- return KM_ERROR_UNKNOWN_ERROR;
- return KM_ERROR_OK;
-}
-
-static keymaster_error_t DeserializeUnversionedBlob(const KeymasterKeyBlob& key_blob,
- KeymasterKeyBlob* encrypted_key_material,
- AuthorizationSet* hw_enforced,
- AuthorizationSet* sw_enforced, Buffer* nonce,
- Buffer* tag) {
- const uint8_t* tmp = key_blob.key_material;
- const uint8_t** buf_ptr = &tmp;
- const uint8_t* end = tmp + key_blob.key_material_size;
-
- if (!nonce->reserve(OCB_NONCE_LENGTH) || !tag->reserve(OCB_TAG_LENGTH))
- return KM_ERROR_MEMORY_ALLOCATION_FAILED;
-
- if (!copy_from_buf(buf_ptr, end, nonce->peek_write(), OCB_NONCE_LENGTH) ||
- !encrypted_key_material->Deserialize(buf_ptr, end) ||
- !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_D("Failed to deserialize unversioned blob (may be a HW-backed key)", 0);
- return KM_ERROR_INVALID_KEY_BLOB;
+ if (!buf || buf != end || !info.advance_write(buf - info.peek_write())) {
+ LOG_S("Buffer management error", 0);
+ *error = KM_ERROR_UNKNOWN_ERROR;
+ return {};
}
- if (!nonce->advance_write(OCB_NONCE_LENGTH) || !tag->advance_write(OCB_TAG_LENGTH))
- return KM_ERROR_UNKNOWN_ERROR;
- return KM_ERROR_OK;
+
+ return info;
}
-keymaster_error_t DeserializeAuthEncryptedBlob(const KeymasterKeyBlob& key_blob,
- KeymasterKeyBlob* encrypted_key_material,
- AuthorizationSet* hw_enforced,
- AuthorizationSet* sw_enforced, Buffer* nonce,
- Buffer* tag) {
- if (!key_blob.key_material || key_blob.key_material_size == 0)
- return KM_ERROR_INVALID_KEY_BLOB;
+Buffer DeriveAesGcmKeyEncryptionKey(const AuthorizationSet& hw_enforced,
+ const AuthorizationSet& sw_enforced,
+ const AuthorizationSet& hidden,
+ const KeymasterKeyBlob& master_key, keymaster_error_t* error) {
+ if (!error) return {};
+ *error = KM_ERROR_OK;
+
+ Buffer prk(EVP_MAX_MD_SIZE);
+ size_t out_len = EVP_MAX_MD_SIZE;
+ if (!HKDF_extract(prk.peek_write(), &out_len, EVP_sha256(), master_key.key_material,
+ master_key.key_material_size, nullptr /* salt */, 0 /* salt_len */)) {
+ *error = TranslateLastOpenSslError();
+ return {};
+ }
+
+ Buffer info = BuildAesGcmInfo(hw_enforced, sw_enforced, hidden, error);
+ if (KM_ERROR_OK != *error) return {};
+
+ if (!prk.advance_write(out_len) || !prk.available_read() || !info.available_read()) {
+ *error = KM_ERROR_UNKNOWN_ERROR;
+ return {};
+ }
+
+ Buffer keyEncryptionKey(kAes256KeyLength);
+ if (!HKDF_expand(keyEncryptionKey.peek_write(), keyEncryptionKey.available_write(), //
+ EVP_sha256(), //
+ prk.peek_read(), prk.available_read(), //
+ info.peek_read(), info.available_read())) {
+ *error = TranslateLastOpenSslError();
+ return {};
+ }
+
+ return keyEncryptionKey;
+}
+
+EncryptedKey AesGcmEncryptKey(const AuthorizationSet& hw_enforced, //
+ const AuthorizationSet& sw_enforced, //
+ const AuthorizationSet& hidden, //
+ const KeymasterKeyBlob& master_key, //
+ const KeymasterKeyBlob& plaintext, //
+ AuthEncryptedBlobFormat format, //
+ Buffer nonce, //
+ keymaster_error_t* error) {
+ if (!error) return {};
+ *error = KM_ERROR_OK;
+
+ Buffer kek = DeriveAesGcmKeyEncryptionKey(hw_enforced, sw_enforced, hidden, master_key, error);
+ if (KM_ERROR_OK != *error) return {};
+
+ bssl::UniquePtr<EVP_CIPHER_CTX> ctx(EVP_CIPHER_CTX_new());
+ if (!ctx) {
+ *error = KM_ERROR_MEMORY_ALLOCATION_FAILED;
+ return {};
+ }
+
+ int ciphertext_len = plaintext.size();
+ int unused_len = 0;
+ EncryptedKey retval;
+ retval.format = format;
+ retval.ciphertext = KeymasterKeyBlob(ciphertext_len);
+ retval.nonce = move(nonce);
+ retval.tag = Buffer(kAesGcmTagLength);
+
+ if (!(EVP_EncryptInit_ex(ctx.get(), EVP_aes_256_gcm(), nullptr /* engine */, kek.peek_read(),
+ retval.nonce.peek_read()) &&
+ EVP_EncryptUpdate(ctx.get(), retval.ciphertext.writable_data(), &ciphertext_len,
+ plaintext.key_material, plaintext.size()) &&
+ EVP_EncryptFinal_ex(ctx.get(), retval.ciphertext.writable_data() /* not written to */,
+ &unused_len) &&
+ EVP_CIPHER_CTX_ctrl(ctx.get(), EVP_CTRL_GCM_GET_TAG, kAesGcmTagLength,
+ retval.tag.peek_write()))) {
+ *error = TranslateLastOpenSslError();
+ return {};
+ }
+
+ if (plaintext.size() != static_cast<size_t>(ciphertext_len) || 0 != unused_len ||
+ !retval.tag.advance_write(kAesGcmTagLength)) {
+ *error = KM_ERROR_UNKNOWN_ERROR;
+ }
+
+ return retval;
+}
+
+KeymasterKeyBlob AesGcmDecryptKey(const DeserializedKey& key, const AuthorizationSet& hidden,
+ const KeymasterKeyBlob& master_key, keymaster_error_t* error) {
+ if (!error) return {};
+ *error = KM_ERROR_OK;
+
+ Buffer kek =
+ DeriveAesGcmKeyEncryptionKey(key.hw_enforced, key.sw_enforced, hidden, master_key, error);
+ if (KM_ERROR_OK != *error) return {};
+
+ bssl::UniquePtr<EVP_CIPHER_CTX> ctx(EVP_CIPHER_CTX_new());
+ if (!ctx) {
+ *error = KM_ERROR_MEMORY_ALLOCATION_FAILED;
+ return {};
+ }
+
+ int plaintext_len = key.encrypted_key.ciphertext.size();
+ int unused_len = 0;
+ KeymasterKeyBlob plaintext(plaintext_len);
+ if (!(EVP_DecryptInit_ex(ctx.get(), EVP_aes_256_gcm(), nullptr /* engine */, kek.peek_read(),
+ key.encrypted_key.nonce.peek_read()) &&
+ EVP_DecryptUpdate(ctx.get(), plaintext.writable_data(), &plaintext_len,
+ key.encrypted_key.ciphertext.key_material,
+ key.encrypted_key.ciphertext.size()) &&
+ EVP_CIPHER_CTX_ctrl(ctx.get(), EVP_CTRL_GCM_SET_TAG, kAesGcmTagLength,
+ const_cast<uint8_t*>(key.encrypted_key.tag.peek_read())))) {
+ *error = TranslateLastOpenSslError();
+ return {};
+ }
+
+ if (!EVP_DecryptFinal_ex(ctx.get(), plaintext.writable_data() /* not written to */,
+ &unused_len)) {
+ *error = KM_ERROR_INVALID_KEY_BLOB;
+ return {};
+ }
+
+ if (key.encrypted_key.ciphertext.size() != plaintext.size() || 0 != unused_len) {
+ *error = KM_ERROR_UNKNOWN_ERROR;
+ }
+
+ return plaintext;
+}
+
+} // namespace
+
+KeymasterKeyBlob SerializeAuthEncryptedBlob(const EncryptedKey& encrypted_key,
+ const AuthorizationSet& hw_enforced,
+ const AuthorizationSet& sw_enforced,
+ keymaster_error_t* error) {
+ if (!error) return {};
+ *error = KM_ERROR_OK;
+
+ size_t size = 1 /* version byte */ + encrypted_key.nonce.SerializedSize() +
+ encrypted_key.ciphertext.SerializedSize() + encrypted_key.tag.SerializedSize() +
+ hw_enforced.SerializedSize() + sw_enforced.SerializedSize();
+
+ KeymasterKeyBlob retval;
+ if (!retval.Reset(size)) {
+ *error = KM_ERROR_MEMORY_ALLOCATION_FAILED;
+ return {};
+ }
+
+ uint8_t* buf = retval.writable_data();
+ const uint8_t* end = retval.end();
+
+ *buf++ = encrypted_key.format;
+ buf = encrypted_key.nonce.Serialize(buf, end);
+ buf = encrypted_key.ciphertext.Serialize(buf, end);
+ buf = encrypted_key.tag.Serialize(buf, end);
+ buf = hw_enforced.Serialize(buf, end);
+ buf = sw_enforced.Serialize(buf, end);
+ if (buf != retval.end()) *error = KM_ERROR_UNKNOWN_ERROR;
+
+ return retval;
+}
+
+DeserializedKey DeserializeAuthEncryptedBlob(const KeymasterKeyBlob& key_blob,
+ keymaster_error_t* error) {
+ if (!error) return {};
+ *error = KM_ERROR_OK;
+
+ if (!key_blob.key_material || key_blob.key_material_size == 0) {
+ *error = KM_ERROR_INVALID_KEY_BLOB;
+ return {};
+ }
const uint8_t* tmp = key_blob.key_material;
const uint8_t** buf_ptr = &tmp;
const uint8_t* end = tmp + key_blob.key_material_size;
- if (end <= *buf_ptr)
- return KM_ERROR_INVALID_KEY_BLOB;
-
- uint8_t version = *(*buf_ptr)++;
- if (version != CURRENT_BLOB_VERSION || //
- !nonce->Deserialize(buf_ptr, end) || nonce->available_read() != OCB_NONCE_LENGTH ||
- !encrypted_key_material->Deserialize(buf_ptr, end) || //
- !tag->Deserialize(buf_ptr, end) || tag->available_read() != OCB_TAG_LENGTH ||
- !hw_enforced->Deserialize(buf_ptr, end) || //
- !sw_enforced->Deserialize(buf_ptr, end)) {
- // This blob failed to parse. Either it's corrupted or it's a blob generated by an earlier
- // version of keymaster using a previous blob format which did not include the version byte
- // or the nonce or tag length fields. So we try to parse it as that previous version.
- //
- // Note that it's not really a problem if we erronously parse a corrupted blob, because
- // decryption will fail the authentication check.
- //
- // A bigger potential problem is: What if a valid unversioned blob appears to parse
- // correctly as a versioned blob? It would then be rejected during decryption, causing a
- // valid key to become unusable. If this is a disk encryption key, upgrading to a keymaster
- // version with the new format would destroy the user's data.
- //
- // What is the probability that an unversioned key could be successfully parsed as a version
- // 0 key? The first 12 bytes of an unversioned key are the nonce, which, in the only
- // keymaster version released with unversioned keys, is chosen randomly. In order for an
- // unversioned key to parse as a version 0 key, the following must be true about the first
- // five of those random bytes:
- //
- // 1. The first byte must be zero. This will happen with probability 1/2^8.
- //
- // 2. The second through fifth bytes must contain an unsigned integer value equal to
- // NONCE_LENGTH. This will happen with probability 1/2^32.
- //
- // 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_D("Failed to deserialize versioned key blob. Assuming unversioned.", 0);
- return DeserializeUnversionedBlob(key_blob, encrypted_key_material, hw_enforced,
- sw_enforced, nonce, tag);
+ if (end <= *buf_ptr) {
+ *error = KM_ERROR_INVALID_KEY_BLOB;
+ return {};
}
- return KM_ERROR_OK;
+
+ DeserializedKey retval;
+ retval.encrypted_key.format = static_cast<AuthEncryptedBlobFormat>(*(*buf_ptr)++);
+ if (!retval.encrypted_key.nonce.Deserialize(buf_ptr, end) || //
+ !retval.encrypted_key.ciphertext.Deserialize(buf_ptr, end) || //
+ !retval.encrypted_key.tag.Deserialize(buf_ptr, end) || //
+ !retval.hw_enforced.Deserialize(buf_ptr, end) || //
+ !retval.sw_enforced.Deserialize(buf_ptr, end) || //
+ *buf_ptr != end) {
+ *error = KM_ERROR_INVALID_KEY_BLOB;
+ return {};
+ }
+
+ switch (retval.encrypted_key.format) {
+ case AES_OCB:
+ if (retval.encrypted_key.nonce.available_read() != OCB_NONCE_LENGTH ||
+ retval.encrypted_key.tag.available_read() != OCB_TAG_LENGTH) {
+ *error = KM_ERROR_INVALID_KEY_BLOB;
+ return {};
+ }
+ return retval;
+
+ case AES_GCM_WITH_SW_ENFORCED:
+ if (retval.encrypted_key.nonce.available_read() != kAesGcmNonceLength ||
+ retval.encrypted_key.tag.available_read() != kAesGcmTagLength) {
+ *error = KM_ERROR_INVALID_KEY_BLOB;
+ return {};
+ }
+ return retval;
+ }
+
+ *error = KM_ERROR_INVALID_KEY_BLOB;
+ return {};
+}
+
+EncryptedKey EncryptKey(const KeymasterKeyBlob& plaintext, AuthEncryptedBlobFormat format,
+ const AuthorizationSet& hw_enforced, const AuthorizationSet& sw_enforced,
+ const AuthorizationSet& hidden, const KeymasterKeyBlob& master_key,
+ const RandomSource& random, keymaster_error_t* error) {
+ if (!error) return {};
+ *error = KM_ERROR_OK;
+
+ switch (format) {
+ case AES_OCB: {
+ EncryptedKey retval;
+ retval.format = format;
+ retval.nonce = generate_nonce(random, OCB_NONCE_LENGTH, error);
+ retval.tag.Reinitialize(OCB_TAG_LENGTH);
+ if (KM_ERROR_OK != *error) return {};
+ *error = OcbEncryptKey(hw_enforced, sw_enforced, hidden, master_key, plaintext,
+ retval.nonce, &retval.ciphertext, &retval.tag);
+ return retval;
+ }
+
+ case AES_GCM_WITH_SW_ENFORCED: {
+ auto nonce = generate_nonce(random, kAesGcmNonceLength, error);
+ if (KM_ERROR_OK != *error) return {};
+ return AesGcmEncryptKey(hw_enforced, sw_enforced, hidden, master_key, plaintext, format,
+ move(nonce), error);
+ }
+ }
+
+ *error = KM_ERROR_UNKNOWN_ERROR;
+ LOG_E("Invalid key blob format %d", format);
+ return {};
+}
+
+KeymasterKeyBlob DecryptKey(const DeserializedKey& key, const AuthorizationSet& hidden,
+ const KeymasterKeyBlob& master_key, keymaster_error_t* error) {
+ if (!error) return {};
+ *error = KM_ERROR_OK;
+
+ KeymasterKeyBlob retval;
+
+ switch (key.encrypted_key.format) {
+ case AES_OCB:
+ *error = OcbDecryptKey(key.hw_enforced, key.sw_enforced, hidden, master_key,
+ key.encrypted_key.ciphertext, key.encrypted_key.nonce,
+ key.encrypted_key.tag, &retval);
+ break;
+
+ case AES_GCM_WITH_SW_ENFORCED:
+ retval = AesGcmDecryptKey(key, hidden, master_key, error);
+ break;
+ }
+
+ return retval;
}
} // namespace keymaster
diff --git a/key_blob_utils/integrity_assured_key_blob.cpp b/key_blob_utils/integrity_assured_key_blob.cpp
index 014855e..11d9cf2 100644
--- a/key_blob_utils/integrity_assured_key_blob.cpp
+++ b/key_blob_utils/integrity_assured_key_blob.cpp
@@ -24,7 +24,6 @@
#include <keymaster/android_keymaster_utils.h>
#include <keymaster/authorization_set.h>
#include <keymaster/km_openssl/openssl_err.h>
-#include <keymaster/new.h>
namespace keymaster {
@@ -33,8 +32,7 @@
static const char HMAC_KEY[] = "IntegrityAssuredBlob0";
inline size_t min(size_t a, size_t b) {
- if (a < b)
- return a;
+ if (a < b) return a;
return b;
}
@@ -51,8 +49,7 @@
const AuthorizationSet& hidden, uint8_t hmac[HMAC_SIZE]) {
size_t hidden_bytes_size = hidden.SerializedSize();
UniquePtr<uint8_t[]> hidden_bytes(new (std::nothrow) uint8_t[hidden_bytes_size]);
- if (!hidden_bytes.get())
- return KM_ERROR_MEMORY_ALLOCATION_FAILED;
+ if (!hidden_bytes.get()) return KM_ERROR_MEMORY_ALLOCATION_FAILED;
hidden.Serialize(hidden_bytes.get(), hidden_bytes.get() + hidden_bytes_size);
HMAC_CTX ctx;
@@ -86,8 +83,7 @@
sw_enforced.SerializedSize() + //
HMAC_SIZE;
- if (!key_blob->Reset(size))
- return KM_ERROR_MEMORY_ALLOCATION_FAILED;
+ if (!key_blob->Reset(size)) return KM_ERROR_MEMORY_ALLOCATION_FAILED;
uint8_t* p = key_blob->writable_data();
*p++ = BLOB_VERSION;
@@ -106,14 +102,12 @@
const uint8_t* p = key_blob.begin();
const uint8_t* end = key_blob.end();
- if (p > end || p + HMAC_SIZE > end)
- return KM_ERROR_INVALID_KEY_BLOB;
+ if (p > end || p + HMAC_SIZE > end) return KM_ERROR_INVALID_KEY_BLOB;
uint8_t computed_hmac[HMAC_SIZE];
keymaster_error_t error = ComputeHmac(key_blob.begin(), key_blob.key_material_size - HMAC_SIZE,
hidden, computed_hmac);
- if (error != KM_ERROR_OK)
- return error;
+ if (error != KM_ERROR_OK) return error;
if (CRYPTO_memcmp(key_blob.end() - HMAC_SIZE, computed_hmac, HMAC_SIZE) != 0)
return KM_ERROR_INVALID_KEY_BLOB;
@@ -129,11 +123,9 @@
const uint8_t* p = key_blob.begin();
const uint8_t* end = key_blob.end() - HMAC_SIZE;
- if (p > end)
- return KM_ERROR_INVALID_KEY_BLOB;
+ if (p > end) return KM_ERROR_INVALID_KEY_BLOB;
- if (*p != BLOB_VERSION)
- return KM_ERROR_INVALID_KEY_BLOB;
+ if (*p != BLOB_VERSION) return KM_ERROR_INVALID_KEY_BLOB;
++p;
if (!key_material->Deserialize(&p, end) || //
@@ -144,4 +136,4 @@
return KM_ERROR_OK;
}
-} // namespace keymaster;
+} // namespace keymaster
diff --git a/key_blob_utils/ocb_utils.cpp b/key_blob_utils/ocb_utils.cpp
index d58d2df..1dcb0cb 100644
--- a/key_blob_utils/ocb_utils.cpp
+++ b/key_blob_utils/ocb_utils.cpp
@@ -26,7 +26,6 @@
#include <keymaster/android_keymaster_utils.h>
#include <keymaster/authorization_set.h>
#include <keymaster/km_openssl/openssl_err.h>
-#include <keymaster/new.h>
namespace keymaster {
@@ -52,8 +51,7 @@
*derivation_data_length =
hidden.SerializedSize() + hw_enforced.SerializedSize() + sw_enforced.SerializedSize();
derivation_data->reset(new (std::nothrow) uint8_t[*derivation_data_length]);
- if (!derivation_data->get())
- return KM_ERROR_MEMORY_ALLOCATION_FAILED;
+ if (!derivation_data->get()) return KM_ERROR_MEMORY_ALLOCATION_FAILED;
uint8_t* buf = derivation_data->get();
uint8_t* end = derivation_data->get() + *derivation_data_length;
@@ -73,17 +71,14 @@
UniquePtr<uint8_t[]> derivation_data;
keymaster_error_t error = BuildDerivationData(hw_enforced, sw_enforced, hidden,
&derivation_data, &derivation_data_length);
- if (error != KM_ERROR_OK)
- return error;
+ if (error != KM_ERROR_OK) return error;
SHA256_CTX sha256_ctx;
UniquePtr<uint8_t[]> hash_buf(new (std::nothrow) uint8_t[SHA256_DIGEST_LENGTH]);
- if (!hash_buf.get())
- return KM_ERROR_MEMORY_ALLOCATION_FAILED;
+ if (!hash_buf.get()) return KM_ERROR_MEMORY_ALLOCATION_FAILED;
Eraser hash_eraser(hash_buf.get(), SHA256_DIGEST_LENGTH);
UniquePtr<uint8_t[]> derived_key(new (std::nothrow) uint8_t[AES_BLOCK_SIZE]);
- if (!derived_key.get())
- return KM_ERROR_MEMORY_ALLOCATION_FAILED;
+ if (!derived_key.get()) return KM_ERROR_MEMORY_ALLOCATION_FAILED;
Eraser derived_key_eraser(derived_key.get(), AES_BLOCK_SIZE);
if (!ctx->get() || !hash_buf.get() || !derived_key.get())
@@ -121,20 +116,17 @@
KeymasterKeyBlob* ciphertext, Buffer* tag) {
assert(ciphertext && tag);
- if (nonce.available_read() != OCB_NONCE_LENGTH)
- return KM_ERROR_INVALID_ARGUMENT;
+ if (nonce.available_read() != OCB_NONCE_LENGTH) return KM_ERROR_INVALID_ARGUMENT;
+ if (tag->available_write() != OCB_TAG_LENGTH) return KM_ERROR_INVALID_ARGUMENT;
AeCtx ctx;
- if (!ctx.get())
- return KM_ERROR_MEMORY_ALLOCATION_FAILED;
+ if (!ctx.get()) return KM_ERROR_MEMORY_ALLOCATION_FAILED;
keymaster_error_t error =
InitializeKeyWrappingContext(hw_enforced, sw_enforced, hidden, master_key, &ctx);
- if (error != KM_ERROR_OK)
- return error;
+ if (error != KM_ERROR_OK) return error;
- if (!ciphertext->Reset(plaintext.key_material_size))
- return KM_ERROR_MEMORY_ALLOCATION_FAILED;
+ if (!ciphertext->Reset(plaintext.key_material_size)) return KM_ERROR_MEMORY_ALLOCATION_FAILED;
int ae_err = ae_encrypt(ctx.get(), nonce.peek_read(), plaintext.key_material,
plaintext.key_material_size, nullptr /* additional data */,
@@ -144,8 +136,7 @@
LOG_E("Error %d while encrypting key", ae_err);
return KM_ERROR_UNKNOWN_ERROR;
}
- if (!tag->advance_write(OCB_TAG_LENGTH))
- return KM_ERROR_UNKNOWN_ERROR;
+ if (!tag->advance_write(OCB_TAG_LENGTH)) return KM_ERROR_UNKNOWN_ERROR;
assert(ae_err == static_cast<int>(plaintext.key_material_size));
return KM_ERROR_OK;
}
@@ -161,16 +152,13 @@
return KM_ERROR_INVALID_ARGUMENT;
AeCtx ctx;
- if (!ctx.get())
- return KM_ERROR_MEMORY_ALLOCATION_FAILED;
+ if (!ctx.get()) return KM_ERROR_MEMORY_ALLOCATION_FAILED;
keymaster_error_t error =
InitializeKeyWrappingContext(hw_enforced, sw_enforced, hidden, master_key, &ctx);
- if (error != KM_ERROR_OK)
- return error;
+ if (error != KM_ERROR_OK) return error;
- if (!plaintext->Reset(ciphertext.key_material_size))
- return KM_ERROR_MEMORY_ALLOCATION_FAILED;
+ if (!plaintext->Reset(ciphertext.key_material_size)) return KM_ERROR_MEMORY_ALLOCATION_FAILED;
int ae_err = ae_decrypt(ctx.get(), nonce.peek_read(), ciphertext.key_material,
ciphertext.key_material_size, nullptr /* additional data */,
diff --git a/key_blob_utils/software_keyblobs.cpp b/key_blob_utils/software_keyblobs.cpp
index 60719bb..764ebcb 100644
--- a/key_blob_utils/software_keyblobs.cpp
+++ b/key_blob_utils/software_keyblobs.cpp
@@ -21,16 +21,16 @@
#include <hardware/keymaster_defs.h>
+#include <keymaster/UniquePtr.h>
#include <keymaster/android_keymaster_utils.h>
#include <keymaster/authorization_set.h>
#include <keymaster/key.h>
#include <keymaster/key_blob_utils/auth_encrypted_key_blob.h>
#include <keymaster/key_blob_utils/integrity_assured_key_blob.h>
#include <keymaster/key_blob_utils/ocb_utils.h>
-#include <keymaster/km_openssl/openssl_utils.h>
#include <keymaster/km_openssl/openssl_err.h>
+#include <keymaster/km_openssl/openssl_utils.h>
#include <keymaster/logger.h>
-#include <keymaster/UniquePtr.h>
#include <openssl/aes.h>
@@ -42,7 +42,7 @@
namespace {
bool UpgradeIntegerTag(keymaster_tag_t tag, uint32_t value, AuthorizationSet* set,
- bool* set_changed) {
+ bool* set_changed) {
int index = set->find(tag);
if (index == -1) {
keymaster_key_param_t param;
@@ -53,8 +53,7 @@
return true;
}
- if (set->params[index].integer > value)
- return false;
+ if (set->params[index].integer > value) return false;
if (set->params[index].integer != value) {
set->params[index].integer = value;
@@ -75,7 +74,7 @@
return KM_ERROR_OK;
}
-} // anonymous namespace
+} // anonymous namespace
keymaster_error_t BuildHiddenAuthorizations(const AuthorizationSet& input_set,
AuthorizationSet* hidden,
@@ -91,8 +90,7 @@
return TranslateAuthorizationSetError(hidden->is_valid());
}
-keymaster_error_t FakeKeyAuthorizations(EVP_PKEY* pubkey,
- AuthorizationSet* hw_enforced,
+keymaster_error_t FakeKeyAuthorizations(EVP_PKEY* pubkey, AuthorizationSet* hw_enforced,
AuthorizationSet* sw_enforced) {
hw_enforced->Clear();
sw_enforced->Clear();
@@ -119,12 +117,10 @@
sw_enforced->push_back(TAG_PURPOSE, KM_PURPOSE_DECRYPT);
RSA_Ptr rsa(EVP_PKEY_get1_RSA(pubkey));
- if (!rsa)
- return TranslateLastOpenSslError();
+ if (!rsa) return TranslateLastOpenSslError();
hw_enforced->push_back(TAG_KEY_SIZE, RSA_size(rsa.get()) * 8);
uint64_t public_exponent = BN_get_word(rsa->e);
- if (public_exponent == 0xffffffffL)
- return KM_ERROR_INVALID_KEY_BLOB;
+ if (public_exponent == 0xffffffffL) return KM_ERROR_INVALID_KEY_BLOB;
hw_enforced->push_back(TAG_RSA_PUBLIC_EXPONENT, public_exponent);
break;
}
@@ -143,13 +139,11 @@
sw_enforced->push_back(TAG_PURPOSE, KM_PURPOSE_VERIFY);
UniquePtr<EC_KEY, EC_KEY_Delete> ec_key(EVP_PKEY_get1_EC_KEY(pubkey));
- if (!ec_key.get())
- return TranslateLastOpenSslError();
+ if (!ec_key.get()) return TranslateLastOpenSslError();
size_t key_size_bits;
keymaster_error_t error =
ec_get_group_size(EC_KEY_get0_group(ec_key.get()), &key_size_bits);
- if (error != KM_ERROR_OK)
- return error;
+ if (error != KM_ERROR_OK) return error;
hw_enforced->push_back(TAG_KEY_SIZE, key_size_bits);
break;
}
@@ -164,16 +158,16 @@
return KM_ERROR_OK;
}
-
// Note: This parsing code in below is from system/security/softkeymaster/keymaster_openssl.cpp's
// unwrap_key function, modified for the preferred function signature and formatting. It does some
// odd things, but they have been left unchanged to avoid breaking compatibility.
static const uint8_t SOFT_KEY_MAGIC[] = {'P', 'K', '#', '8'};
-keymaster_error_t ParseOldSoftkeymasterBlob(
- const KeymasterKeyBlob& blob, KeymasterKeyBlob* key_material, AuthorizationSet* hw_enforced,
- AuthorizationSet* sw_enforced) {
- long publicLen = 0;
- long privateLen = 0;
+keymaster_error_t ParseOldSoftkeymasterBlob(const KeymasterKeyBlob& blob,
+ KeymasterKeyBlob* key_material,
+ AuthorizationSet* hw_enforced,
+ AuthorizationSet* sw_enforced) {
+ long publicLen = 0; // NOLINT(google-runtime-int)
+ long privateLen = 0; // NOLINT(google-runtime-int)
const uint8_t* p = blob.key_material;
const uint8_t* end = blob.key_material + blob.key_material_size;
@@ -185,15 +179,16 @@
return KM_ERROR_INVALID_KEY_BLOB;
}
- if (memcmp(p, SOFT_KEY_MAGIC, sizeof(SOFT_KEY_MAGIC)) != 0)
- return KM_ERROR_INVALID_KEY_BLOB;
+ if (memcmp(p, SOFT_KEY_MAGIC, sizeof(SOFT_KEY_MAGIC)) != 0) return KM_ERROR_INVALID_KEY_BLOB;
p += sizeof(SOFT_KEY_MAGIC);
- for (size_t i = 0; i < sizeof(type); i++)
+ for (size_t i = 0; i < sizeof(type); i++) {
type = (type << 8) | *p++;
+ }
- for (size_t i = 0; i < sizeof(type); i++)
+ for (size_t i = 0; i < sizeof(type); i++) {
publicLen = (publicLen << 8) | *p++;
+ }
if (p + publicLen > end) {
LOG_W("public key length encoding error: size=%ld, end=%td", publicLen, end - p);
@@ -227,11 +222,9 @@
// auths for a HW-backed key.
hw_enforced->Clear();
keymaster_error_t error = FakeKeyAuthorizations(pkey.get(), sw_enforced, sw_enforced);
- if (error != KM_ERROR_OK)
- return error;
+ if (error != KM_ERROR_OK) return error;
- if (!key_material->Reset(privateLen))
- return KM_ERROR_MEMORY_ALLOCATION_FAILED;
+ if (!key_material->Reset(privateLen)) return KM_ERROR_MEMORY_ALLOCATION_FAILED;
memcpy(key_material->writable_data(), key_start, privateLen);
return KM_ERROR_OK;
@@ -240,23 +233,19 @@
static uint8_t master_key_bytes[AES_BLOCK_SIZE] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
const KeymasterKeyBlob MASTER_KEY(master_key_bytes, array_length(master_key_bytes));
-keymaster_error_t ParseOcbAuthEncryptedBlob(const KeymasterKeyBlob& blob,
- const AuthorizationSet& hidden,
- KeymasterKeyBlob* key_material,
- AuthorizationSet* hw_enforced,
- AuthorizationSet* sw_enforced) {
- Buffer nonce, tag;
- KeymasterKeyBlob encrypted_key_material;
- keymaster_error_t error = DeserializeAuthEncryptedBlob(blob, &encrypted_key_material,
- hw_enforced, sw_enforced, &nonce, &tag);
- if (error != KM_ERROR_OK)
- return error;
+keymaster_error_t ParseAuthEncryptedBlob(const KeymasterKeyBlob& blob,
+ const AuthorizationSet& hidden,
+ KeymasterKeyBlob* key_material,
+ AuthorizationSet* hw_enforced,
+ AuthorizationSet* sw_enforced) {
+ keymaster_error_t error;
+ DeserializedKey key = DeserializeAuthEncryptedBlob(blob, &error);
+ if (error != KM_ERROR_OK) return error;
- if (nonce.available_read() != OCB_NONCE_LENGTH || tag.available_read() != OCB_TAG_LENGTH)
- return KM_ERROR_INVALID_KEY_BLOB;
-
- return OcbDecryptKey(*hw_enforced, *sw_enforced, hidden, MASTER_KEY, encrypted_key_material,
- nonce, tag, key_material);
+ *key_material = DecryptKey(key, hidden, MASTER_KEY, &error);
+ *hw_enforced = move(key.hw_enforced);
+ *sw_enforced = move(key.sw_enforced);
+ return error;
}
keymaster_error_t SetKeyBlobAuthorizations(const AuthorizationSet& key_description,
@@ -268,26 +257,112 @@
for (auto& entry : key_description) {
switch (entry.tag) {
// These cannot be specified by the client.
- case KM_TAG_ROOT_OF_TRUST:
+ case KM_TAG_BOOT_PATCHLEVEL:
case KM_TAG_ORIGIN:
+ case KM_TAG_OS_PATCHLEVEL:
+ case KM_TAG_OS_VERSION:
+ case KM_TAG_ROOT_OF_TRUST:
+ case KM_TAG_VENDOR_PATCHLEVEL:
LOG_E("Root of trust and origin tags may not be specified", 0);
return KM_ERROR_INVALID_TAG;
- // These don't work.
+ case KM_TAG_ALLOW_WHILE_ON_BODY:
+ // Not supported, but is specified to noop in that case (vs error).
+ LOG_W("No on-body detection supported, skipping tag %d", entry.tag);
+ break;
+
+ // These aren't supported by SoftKeymaster.
+ case KM_TAG_DEVICE_UNIQUE_ATTESTATION:
+ case KM_TAG_ECIES_SINGLE_HASH_MODE:
+ case KM_TAG_EXPORTABLE:
+ case KM_TAG_IDENTITY_CREDENTIAL_KEY:
+ case KM_TAG_KDF:
case KM_TAG_ROLLBACK_RESISTANT:
- LOG_E("KM_TAG_ROLLBACK_RESISTANT not supported", 0);
+ case KM_TAG_STORAGE_KEY:
+ LOG_E("Tag %d not supported by SoftKeymaster", entry.tag);
return KM_ERROR_UNSUPPORTED_TAG;
+ // If the hardware enforce list contains this tag, means we are
+ // pretending to be some secure hardware which has secure storage.
+ case KM_TAG_ROLLBACK_RESISTANCE:
+ if (hw_enforced->GetTagCount(entry.tag) != 0)
+ break;
+ else {
+ LOG_E("Tag %d not supported by SoftKeymaster", entry.tag);
+ return KM_ERROR_UNSUPPORTED_TAG;
+ }
+
// These are hidden.
- case KM_TAG_APPLICATION_ID:
case KM_TAG_APPLICATION_DATA:
+ case KM_TAG_APPLICATION_ID:
+ break;
+
+ // These should not be in key descriptions because they're for operation parameters.
+ case KM_TAG_ASSOCIATED_DATA:
+ case KM_TAG_AUTH_TOKEN:
+ case KM_TAG_CONFIRMATION_TOKEN:
+ case KM_TAG_INVALID:
+ case KM_TAG_MAC_LENGTH:
+ case KM_TAG_NONCE:
+ LOG_E("Tag %d not allowed in key generation/import", entry.tag);
+ break;
+
+ // These are provided to support attesation key generation, but should not be included in
+ // the key characteristics.
+ case KM_TAG_ATTESTATION_APPLICATION_ID:
+ case KM_TAG_ATTESTATION_CHALLENGE:
+ case KM_TAG_ATTESTATION_ID_BRAND:
+ case KM_TAG_ATTESTATION_ID_DEVICE:
+ case KM_TAG_ATTESTATION_ID_IMEI:
+ case KM_TAG_ATTESTATION_ID_MANUFACTURER:
+ case KM_TAG_ATTESTATION_ID_MEID:
+ case KM_TAG_ATTESTATION_ID_MODEL:
+ case KM_TAG_ATTESTATION_ID_PRODUCT:
+ case KM_TAG_ATTESTATION_ID_SERIAL:
+ case KM_TAG_CERTIFICATE_SERIAL:
+ case KM_TAG_CERTIFICATE_SUBJECT:
+ case KM_TAG_CERTIFICATE_NOT_BEFORE:
+ case KM_TAG_CERTIFICATE_NOT_AFTER:
+ case KM_TAG_RESET_SINCE_ID_ROTATION:
break;
// Everything else we just copy into sw_enforced, unless the KeyFactory has placed it in
// hw_enforced, in which case we defer to its decision.
- default:
- if (hw_enforced->GetTagCount(entry.tag) == 0)
- sw_enforced->push_back(entry);
+ case KM_TAG_ACTIVE_DATETIME:
+ case KM_TAG_ALGORITHM:
+ case KM_TAG_ALL_APPLICATIONS:
+ case KM_TAG_ALL_USERS:
+ case KM_TAG_AUTH_TIMEOUT:
+ case KM_TAG_BLOB_USAGE_REQUIREMENTS:
+ case KM_TAG_BLOCK_MODE:
+ case KM_TAG_BOOTLOADER_ONLY:
+ case KM_TAG_CALLER_NONCE:
+ case KM_TAG_CREATION_DATETIME:
+ case KM_TAG_DIGEST:
+ case KM_TAG_EARLY_BOOT_ONLY:
+ case KM_TAG_EC_CURVE:
+ case KM_TAG_INCLUDE_UNIQUE_ID:
+ case KM_TAG_KEY_SIZE:
+ case KM_TAG_MAX_BOOT_LEVEL:
+ case KM_TAG_MAX_USES_PER_BOOT:
+ case KM_TAG_MIN_MAC_LENGTH:
+ case KM_TAG_MIN_SECONDS_BETWEEN_OPS:
+ case KM_TAG_NO_AUTH_REQUIRED:
+ case KM_TAG_ORIGINATION_EXPIRE_DATETIME:
+ case KM_TAG_PADDING:
+ case KM_TAG_PURPOSE:
+ case KM_TAG_RSA_OAEP_MGF_DIGEST:
+ case KM_TAG_RSA_PUBLIC_EXPONENT:
+ case KM_TAG_TRUSTED_CONFIRMATION_REQUIRED:
+ case KM_TAG_TRUSTED_USER_PRESENCE_REQUIRED:
+ case KM_TAG_UNIQUE_ID:
+ case KM_TAG_UNLOCKED_DEVICE_REQUIRED:
+ case KM_TAG_USAGE_COUNT_LIMIT:
+ case KM_TAG_USAGE_EXPIRE_DATETIME:
+ case KM_TAG_USER_AUTH_TYPE:
+ case KM_TAG_USER_ID:
+ case KM_TAG_USER_SECURE_ID:
+ if (hw_enforced->GetTagCount(entry.tag) == 0) sw_enforced->push_back(entry);
break;
}
}
@@ -306,11 +381,37 @@
return TranslateAuthorizationSetError(sw_enforced->is_valid());
}
+keymaster_error_t ExtendKeyBlobAuthorizations(AuthorizationSet* hw_enforced,
+ AuthorizationSet* sw_enforced,
+ std::optional<uint32_t> vendor_patchlevel,
+ std::optional<uint32_t> boot_patchlevel) {
+ // If hw_enforced is non-empty, we're pretending to be some sort of secure hardware.
+ AuthorizationSet* pseudo_hw_enforced = (hw_enforced->empty()) ? sw_enforced : hw_enforced;
+ if (vendor_patchlevel.has_value()) {
+ pseudo_hw_enforced->push_back(TAG_VENDOR_PATCHLEVEL, vendor_patchlevel.value());
+ }
+ if (boot_patchlevel.has_value()) {
+ pseudo_hw_enforced->push_back(TAG_BOOT_PATCHLEVEL, boot_patchlevel.value());
+ }
+ return TranslateAuthorizationSetError(sw_enforced->is_valid());
+}
-keymaster_error_t UpgradeSoftKeyBlob(const UniquePtr<Key>& key,
- const uint32_t os_version, const uint32_t os_patchlevel,
- const AuthorizationSet& upgrade_params,
- KeymasterKeyBlob* upgraded_key) {
+keymaster_error_t UpgradeSoftKeyBlob(const UniquePtr<Key>& key, const uint32_t os_version,
+ const uint32_t os_patchlevel,
+ const AuthorizationSet& upgrade_params,
+ KeymasterKeyBlob* upgraded_key) {
+ return FullUpgradeSoftKeyBlob(key, os_version, os_patchlevel,
+ /* vendor_patchlevel= */ std::nullopt,
+ /* boot_patchlevel= */ std::nullopt, //
+ upgrade_params, upgraded_key);
+}
+
+keymaster_error_t FullUpgradeSoftKeyBlob(const UniquePtr<Key>& key, const uint32_t os_version,
+ uint32_t os_patchlevel,
+ std::optional<uint32_t> vendor_patchlevel,
+ std::optional<uint32_t> boot_patchlevel,
+ const AuthorizationSet& upgrade_params,
+ KeymasterKeyBlob* upgraded_key) {
bool set_changed = false;
if (os_version == 0) {
@@ -328,20 +429,27 @@
}
if (!UpgradeIntegerTag(TAG_OS_VERSION, os_version, &key->sw_enforced(), &set_changed) ||
- !UpgradeIntegerTag(TAG_OS_PATCHLEVEL, os_patchlevel, &key->sw_enforced(), &set_changed))
+ !UpgradeIntegerTag(TAG_OS_PATCHLEVEL, os_patchlevel, &key->sw_enforced(), &set_changed) ||
+ (vendor_patchlevel.has_value() &&
+ !UpgradeIntegerTag(TAG_VENDOR_PATCHLEVEL, vendor_patchlevel.value(), &key->sw_enforced(),
+ &set_changed)) ||
+ (boot_patchlevel.has_value() &&
+ !UpgradeIntegerTag(TAG_BOOT_PATCHLEVEL, boot_patchlevel.value(), &key->sw_enforced(),
+ &set_changed))) {
// One of the version fields would have been a downgrade. Not allowed.
return KM_ERROR_INVALID_ARGUMENT;
+ }
- if (!set_changed)
+ if (!set_changed) {
// Dont' need an upgrade.
return KM_ERROR_OK;
+ }
AuthorizationSet hidden;
auto error = BuildHiddenAuthorizations(upgrade_params, &hidden, softwareRootOfTrust);
- if (error != KM_ERROR_OK)
- return error;
+ if (error != KM_ERROR_OK) return error;
return SerializeIntegrityAssuredBlob(key->key_material(), hidden, key->hw_enforced(),
key->sw_enforced(), upgraded_key);
}
-} // namespace keymaster
+} // namespace keymaster
diff --git a/km_openssl/aes_key.cpp b/km_openssl/aes_key.cpp
index 0e1a756..5df9e9e 100644
--- a/km_openssl/aes_key.cpp
+++ b/km_openssl/aes_key.cpp
@@ -18,8 +18,6 @@
#include <assert.h>
-#include <keymaster/new.h>
-
#include <openssl/err.h>
#include <openssl/rand.h>
@@ -46,8 +44,7 @@
AuthorizationSet&& hw_enforced,
AuthorizationSet&& sw_enforced,
UniquePtr<Key>* key) const {
- if (!key)
- return KM_ERROR_OUTPUT_PARAMETER_NULL;
+ if (!key) return KM_ERROR_OUTPUT_PARAMETER_NULL;
uint32_t min_mac_length = 0;
if (hw_enforced.Contains(TAG_BLOCK_MODE, KM_MODE_GCM) ||
@@ -62,10 +59,9 @@
}
keymaster_error_t error = KM_ERROR_OK;
- key->reset(new (std::nothrow) AesKey(move(key_material), move(hw_enforced), move(sw_enforced),
- this));
- if (!key->get())
- error = KM_ERROR_MEMORY_ALLOCATION_FAILED;
+ key->reset(new (std::nothrow)
+ AesKey(move(key_material), move(hw_enforced), move(sw_enforced), this));
+ if (!key->get()) error = KM_ERROR_MEMORY_ALLOCATION_FAILED;
return error;
}
@@ -76,8 +72,7 @@
if (!key_description.GetTagValue(TAG_MIN_MAC_LENGTH, &min_tag_length))
return KM_ERROR_MISSING_MIN_MAC_LENGTH;
- if (min_tag_length % 8 != 0)
- return KM_ERROR_UNSUPPORTED_MIN_MAC_LENGTH;
+ if (min_tag_length % 8 != 0) return KM_ERROR_UNSUPPORTED_MIN_MAC_LENGTH;
if (min_tag_length < kMinGcmTagLength || min_tag_length > kMaxGcmTagLength)
return KM_ERROR_UNSUPPORTED_MIN_MAC_LENGTH;
diff --git a/km_openssl/asymmetric_key.cpp b/km_openssl/asymmetric_key.cpp
index 511e43a..8516c65 100644
--- a/km_openssl/asymmetric_key.cpp
+++ b/km_openssl/asymmetric_key.cpp
@@ -16,42 +16,33 @@
#include <keymaster/km_openssl/asymmetric_key.h>
-#include <keymaster/new.h>
-
#include <openssl/asn1.h>
#include <openssl/stack.h>
#include <openssl/x509.h>
#include <openssl/x509v3.h>
#include <keymaster/android_keymaster_utils.h>
-#include <keymaster/attestation_record.h>
#include <keymaster/keymaster_context.h>
#include <keymaster/km_openssl/openssl_err.h>
#include <keymaster/km_openssl/openssl_utils.h>
-
namespace keymaster {
keymaster_error_t AsymmetricKey::formatted_key_material(keymaster_key_format_t format,
UniquePtr<uint8_t[]>* material,
size_t* size) const {
- if (format != KM_KEY_FORMAT_X509)
- return KM_ERROR_UNSUPPORTED_KEY_FORMAT;
+ if (format != KM_KEY_FORMAT_X509) return KM_ERROR_UNSUPPORTED_KEY_FORMAT;
- if (material == nullptr || size == nullptr)
- return KM_ERROR_OUTPUT_PARAMETER_NULL;
+ if (material == nullptr || size == nullptr) return KM_ERROR_OUTPUT_PARAMETER_NULL;
EVP_PKEY_Ptr pkey(EVP_PKEY_new());
- if (!InternalToEvp(pkey.get()))
- return TranslateLastOpenSslError();
+ if (!InternalToEvp(pkey.get())) return TranslateLastOpenSslError();
int key_data_length = i2d_PUBKEY(pkey.get(), nullptr);
- if (key_data_length <= 0)
- return TranslateLastOpenSslError();
+ if (key_data_length <= 0) return TranslateLastOpenSslError();
- material->reset(new(std::nothrow) uint8_t[key_data_length]);
- if (material->get() == nullptr)
- return KM_ERROR_MEMORY_ALLOCATION_FAILED;
+ material->reset(new (std::nothrow) uint8_t[key_data_length]);
+ if (material->get() == nullptr) return KM_ERROR_MEMORY_ALLOCATION_FAILED;
uint8_t* tmp = material->get();
if (i2d_PUBKEY(pkey.get(), &tmp) != key_data_length) {
diff --git a/km_openssl/asymmetric_key_factory.cpp b/km_openssl/asymmetric_key_factory.cpp
index b34924a..cf68c68 100644
--- a/km_openssl/asymmetric_key_factory.cpp
+++ b/km_openssl/asymmetric_key_factory.cpp
@@ -45,23 +45,21 @@
UniquePtr<Key>* key) const {
UniquePtr<AsymmetricKey> asym_key;
keymaster_error_t error = CreateEmptyKey(move(hw_enforced), move(sw_enforced), &asym_key);
- if (error != KM_ERROR_OK)
- return error;
+ if (error != KM_ERROR_OK) return error;
const uint8_t* tmp = key_material.key_material;
asym_key->key_material() = move(key_material);
- EVP_PKEY* pkey =
- d2i_PrivateKey(evp_key_type(), nullptr /* pkey */, &tmp,
- asym_key->key_material().key_material_size);
- if (!pkey)
- return TranslateLastOpenSslError();
+ EVP_PKEY* pkey = d2i_PrivateKey(evp_key_type(), nullptr /* pkey */, &tmp,
+ asym_key->key_material().key_material_size);
+ if (!pkey) return TranslateLastOpenSslError();
UniquePtr<EVP_PKEY, EVP_PKEY_Delete> pkey_deleter(pkey);
- if (!asym_key->EvpToInternal(pkey))
+ if (!asym_key->EvpToInternal(pkey)) {
error = TranslateLastOpenSslError();
- else
- key->reset(asym_key.release());
+ } else {
+ *key = std::move(asym_key);
+ }
return error;
}
diff --git a/km_openssl/attestation_record.cpp b/km_openssl/attestation_record.cpp
index 8fcaa03..92aaeae 100644
--- a/km_openssl/attestation_record.cpp
+++ b/km_openssl/attestation_record.cpp
@@ -14,20 +14,31 @@
* limitations under the License.
*/
-#include <keymaster/attestation_record.h>
+#include <keymaster/km_openssl/attestation_record.h>
#include <assert.h>
+#include <math.h>
+#include <unordered_map>
+
+#include <cppbor_parse.h>
#include <openssl/asn1t.h>
#include <keymaster/android_keymaster_utils.h>
+#include <keymaster/attestation_context.h>
#include <keymaster/km_openssl/openssl_err.h>
#include <keymaster/km_openssl/openssl_utils.h>
+#define ASSERT_OR_RETURN_ERROR(stmt, error) \
+ do { \
+ assert(stmt); \
+ if (!(stmt)) { \
+ return error; \
+ } \
+ } while (0)
+
namespace keymaster {
-constexpr uint kCurrentKeymasterVersion = 4;
-constexpr uint kCurrentAttestationVersion = 3;
constexpr size_t kMaximumAttestationChallengeLength = 128;
IMPLEMENT_ASN1_FUNCTIONS(KM_ROOT_OF_TRUST);
@@ -35,14 +46,9 @@
IMPLEMENT_ASN1_FUNCTIONS(KM_KEY_DESCRIPTION);
static const keymaster_tag_t kDeviceAttestationTags[] = {
- KM_TAG_ATTESTATION_ID_BRAND,
- KM_TAG_ATTESTATION_ID_DEVICE,
- KM_TAG_ATTESTATION_ID_PRODUCT,
- KM_TAG_ATTESTATION_ID_SERIAL,
- KM_TAG_ATTESTATION_ID_IMEI,
- KM_TAG_ATTESTATION_ID_MEID,
- KM_TAG_ATTESTATION_ID_MANUFACTURER,
- KM_TAG_ATTESTATION_ID_MODEL,
+ KM_TAG_ATTESTATION_ID_BRAND, KM_TAG_ATTESTATION_ID_DEVICE, KM_TAG_ATTESTATION_ID_PRODUCT,
+ KM_TAG_ATTESTATION_ID_SERIAL, KM_TAG_ATTESTATION_ID_IMEI, KM_TAG_ATTESTATION_ID_MEID,
+ KM_TAG_ATTESTATION_ID_MANUFACTURER, KM_TAG_ATTESTATION_ID_MODEL,
};
struct KM_AUTH_LIST_Delete {
@@ -57,6 +63,25 @@
void operator()(KM_ROOT_OF_TRUST* p) { KM_ROOT_OF_TRUST_free(p); }
};
+static cppbor::Bstr blob_to_bstr(const keymaster_blob_t& blob) {
+ return cppbor::Bstr(std::pair(blob.data, blob.data_length));
+}
+
+static keymaster_error_t bstr_to_blob(const cppbor::Bstr* bstr, keymaster_blob_t* blob) {
+ ASSERT_OR_RETURN_ERROR(bstr, KM_ERROR_INVALID_TAG);
+ const std::vector<uint8_t>& vec = bstr->value();
+ uint8_t* data = (uint8_t*)calloc(vec.size(), sizeof(uint8_t));
+ if (data == nullptr) {
+ return KM_ERROR_MEMORY_ALLOCATION_FAILED;
+ }
+
+ std::copy(vec.begin(), vec.end(), data);
+ blob->data = data;
+ blob->data_length = vec.size();
+
+ return KM_ERROR_OK;
+}
+
static uint32_t get_uint32_value(const keymaster_key_param_t& param) {
switch (keymaster_tag_get_type(param.tag)) {
case KM_ENUM:
@@ -66,44 +91,427 @@
case KM_UINT_REP:
return param.integer;
default:
- assert(false);
- return 0xFFFFFFFF;
+ ASSERT_OR_RETURN_ERROR(false, 0xFFFFFFFF);
}
}
+static int64_t get_uint32_value(EatSecurityLevel level) {
+ return static_cast<int64_t>(level);
+}
+
// Insert value in either the dest_integer or the dest_integer_set, whichever is provided.
static keymaster_error_t insert_integer(ASN1_INTEGER* value, ASN1_INTEGER** dest_integer,
ASN1_INTEGER_SET** dest_integer_set) {
- assert((dest_integer == nullptr) ^ (dest_integer_set == nullptr));
- assert(value);
+ ASSERT_OR_RETURN_ERROR((dest_integer == nullptr) ^ (dest_integer_set == nullptr),
+ KM_ERROR_UNEXPECTED_NULL_POINTER);
+ ASSERT_OR_RETURN_ERROR(value, KM_ERROR_INVALID_ARGUMENT);
if (dest_integer_set) {
- if (!*dest_integer_set)
+ if (!*dest_integer_set) {
*dest_integer_set = sk_ASN1_INTEGER_new_null();
- if (!*dest_integer_set)
+ }
+ if (!*dest_integer_set) {
return KM_ERROR_MEMORY_ALLOCATION_FAILED;
- if (!sk_ASN1_INTEGER_push(*dest_integer_set, value))
+ }
+ if (!sk_ASN1_INTEGER_push(*dest_integer_set, value)) {
return KM_ERROR_MEMORY_ALLOCATION_FAILED;
+ }
return KM_ERROR_OK;
} else if (dest_integer) {
- if (*dest_integer)
+ if (*dest_integer) {
ASN1_INTEGER_free(*dest_integer);
+ }
*dest_integer = value;
return KM_ERROR_OK;
}
- assert(false); // Should never get here.
+ ASSERT_OR_RETURN_ERROR(false, KM_ERROR_UNKNOWN_ERROR); // Should never get here.
+}
+
+// Add a repeating enum to a map going mapping its key to list of values.
+static void add_repeating_enum(EatClaim key, uint32_t value,
+ std::unordered_map<EatClaim, cppbor::Array>* fields_map) {
+ auto field = fields_map->find(key);
+ if (field != fields_map->end()) {
+ field->second.add(value);
+ } else {
+ fields_map->insert({key, cppbor::Array().add(value)});
+ }
+}
+
+static keymaster_error_t
+insert_unknown_tag(const keymaster_key_param_t& param, cppbor::Map* dest_map,
+ std::unordered_map<EatClaim, cppbor::Array>* fields_map) {
+ EatClaim private_eat_tag = static_cast<EatClaim>(convert_to_eat_claim(param.tag));
+ switch (keymaster_tag_get_type(param.tag)) {
+ case KM_ENUM:
+ dest_map->add(private_eat_tag, param.enumerated);
+ break;
+ case KM_ENUM_REP:
+ add_repeating_enum(private_eat_tag, param.enumerated, fields_map);
+ break;
+ case KM_UINT:
+ dest_map->add(private_eat_tag, param.integer);
+ break;
+ case KM_UINT_REP:
+ add_repeating_enum(private_eat_tag, param.integer, fields_map);
+ break;
+ case KM_ULONG:
+ dest_map->add(private_eat_tag, param.long_integer);
+ break;
+ case KM_ULONG_REP:
+ add_repeating_enum(private_eat_tag, param.long_integer, fields_map);
+ break;
+ case KM_DATE:
+ dest_map->add(private_eat_tag, param.date_time);
+ break;
+ case KM_BOOL:
+ dest_map->add(private_eat_tag, true);
+ break;
+ case KM_BIGNUM:
+ case KM_BYTES:
+ dest_map->add(private_eat_tag, blob_to_bstr(param.blob));
+ break;
+ default:
+ ASSERT_OR_RETURN_ERROR(false, KM_ERROR_INVALID_TAG);
+ }
return KM_ERROR_OK;
}
-// Put the contents of the keymaster AuthorizationSet auth_list in to the ASN.1 record structure,
+/**
+ * Convert an IMEI encoded as a string of numbers into the UEID format defined in
+ * https://tools.ietf.org/html/draft-ietf-rats-eat.
+ * The resulting format is a bstr encoded as follows:
+ * - Type byte: 0x03
+ * - IMEI (without check digit), encoded as byte string of length 14 with each byte as the digit's
+ * value. The IMEI value encoded SHALL NOT include Luhn checksum or SVN information.
+ */
+keymaster_error_t imei_to_ueid(const keymaster_blob_t& imei_blob, cppbor::Bstr* out) {
+ ASSERT_OR_RETURN_ERROR(imei_blob.data_length == kImeiBlobLength, KM_ERROR_INVALID_TAG);
+
+ uint8_t ueid[kUeidLength];
+ ueid[0] = kImeiTypeByte;
+ // imei_blob corresponds to android.telephony.TelephonyManager#getDeviceId(), which is the
+ // 15-digit IMEI (including the check digit), encoded as a string.
+ for (size_t i = 1; i < kUeidLength; i++) {
+ // Convert each character to its numeric value.
+ ueid[i] = imei_blob.data[i - 1] - '0'; // Intentionally skip check digit at last position.
+ }
+
+ *out = cppbor::Bstr(std::pair(ueid, sizeof(ueid)));
+ return KM_ERROR_OK;
+}
+
+keymaster_error_t ueid_to_imei_blob(const cppbor::Bstr* ueid, keymaster_blob_t* out) {
+ ASSERT_OR_RETURN_ERROR(ueid, KM_ERROR_INVALID_TAG);
+ const std::vector<uint8_t>& ueid_vec = ueid->value();
+ ASSERT_OR_RETURN_ERROR(ueid_vec.size() == kUeidLength, KM_ERROR_INVALID_TAG);
+ ASSERT_OR_RETURN_ERROR(ueid_vec[0] == kImeiTypeByte, KM_ERROR_INVALID_TAG);
+
+ uint8_t* imei_string = (uint8_t*)calloc(kImeiBlobLength, sizeof(uint8_t));
+ // Fill string from left to right, and calculate Luhn check digit.
+ int luhn_digit_sum = 0;
+ for (size_t i = 0; i < kImeiBlobLength - 1; i++) {
+ uint8_t digit_i = ueid_vec[i + 1];
+ // Convert digit to its string value.
+ imei_string[i] = '0' + digit_i;
+ luhn_digit_sum += i % 2 == 0 ? digit_i : digit_i * 2 / 10 + (digit_i * 2) % 10;
+ }
+ imei_string[kImeiBlobLength - 1] = '0' + (10 - luhn_digit_sum % 10) % 10;
+
+ *out = {.data = imei_string, .data_length = kImeiBlobLength};
+ return KM_ERROR_OK;
+}
+
+keymaster_error_t ec_key_size_to_eat_curve(uint32_t key_size_bits, int* curve) {
+ switch (key_size_bits) {
+ default:
+ return KM_ERROR_UNSUPPORTED_KEY_SIZE;
+
+ case 224:
+ *curve = (int)EatEcCurve::P_224;
+ break;
+
+ case 256:
+ *curve = (int)EatEcCurve::P_256;
+ break;
+
+ case 384:
+ *curve = (int)EatEcCurve::P_384;
+ break;
+
+ case 521:
+ *curve = (int)EatEcCurve::P_521;
+ break;
+ }
+
+ return KM_ERROR_OK;
+}
+
+bool is_valid_attestation_challenge(const keymaster_blob_t& attestation_challenge) {
+ // TODO(171864369): Limit apps targeting >= API 30 to attestations in the range of
+ // [0, 128] bytes.
+ return (attestation_challenge.data_length <= kMaximumAttestationChallengeLength);
+}
+
+Buffer generate_unique_id(const AttestationContext& context, //
+ const AuthorizationSet& sw_enforced,
+ const AuthorizationSet& attestation_params, //
+ keymaster_error_t* error) {
+ uint64_t creation_datetime;
+ // Only check sw_enforced for TAG_CREATION_DATETIME, since it shouldn't be in tee_enforced,
+ // since this implementation has no secure wall clock.
+ if (!sw_enforced.GetTagValue(TAG_CREATION_DATETIME, &creation_datetime)) {
+ LOG_E("Unique ID cannot be created without creation datetime", 0);
+ *error = KM_ERROR_INVALID_KEY_BLOB;
+ return {};
+ }
+
+ keymaster_blob_t application_id = {nullptr, 0};
+ sw_enforced.GetTagValue(TAG_APPLICATION_ID, &application_id);
+
+ return context.GenerateUniqueId(creation_datetime, application_id,
+ attestation_params.GetTagValue(TAG_RESET_SINCE_ID_ROTATION),
+ error);
+}
+
+// Put the contents of the keymaster AuthorizationSet auth_list into the EAT record structure.
+keymaster_error_t build_eat_submod(const AuthorizationSet& auth_list,
+ const EatSecurityLevel security_level, cppbor::Map* submod) {
+ ASSERT_OR_RETURN_ERROR(submod, KM_ERROR_UNEXPECTED_NULL_POINTER);
+
+ if (auth_list.empty()) return KM_ERROR_OK;
+
+ submod->add(EatClaim::SECURITY_LEVEL, get_uint32_value(security_level));
+
+ // Keep repeating fields in a separate map for easy lookup.
+ // Add them to submod map in postprocessing.
+ std::unordered_map<EatClaim, cppbor::Array> repeating_fields =
+ std::unordered_map<EatClaim, cppbor::Array>();
+
+ for (auto entry : auth_list) {
+
+ switch (entry.tag) {
+
+ default:
+ // Unknown tags should only be included if they're software-enforced.
+ if (security_level == EatSecurityLevel::UNRESTRICTED) {
+ keymaster_error_t error = insert_unknown_tag(entry, submod, &repeating_fields);
+ if (error != KM_ERROR_OK) {
+ return error;
+ }
+ }
+ break;
+
+ /* Tags ignored because they should never exist */
+ case KM_TAG_INVALID:
+
+ /* Tags ignored because they're not used. */
+ case KM_TAG_ALL_USERS:
+ case KM_TAG_EXPORTABLE:
+ case KM_TAG_ECIES_SINGLE_HASH_MODE:
+ case KM_TAG_KDF:
+
+ /* Tags ignored because they're used only to provide information to operations */
+ case KM_TAG_ASSOCIATED_DATA:
+ case KM_TAG_NONCE:
+ case KM_TAG_AUTH_TOKEN:
+ case KM_TAG_MAC_LENGTH:
+ case KM_TAG_ATTESTATION_CHALLENGE:
+ case KM_TAG_RESET_SINCE_ID_ROTATION:
+
+ /* Tags ignored because they have no meaning off-device */
+ case KM_TAG_USER_ID:
+ case KM_TAG_USER_SECURE_ID:
+ case KM_TAG_BLOB_USAGE_REQUIREMENTS:
+
+ /* Tags ignored because they're not usable by app keys */
+ case KM_TAG_BOOTLOADER_ONLY:
+ case KM_TAG_INCLUDE_UNIQUE_ID:
+ case KM_TAG_MAX_USES_PER_BOOT:
+ case KM_TAG_MIN_SECONDS_BETWEEN_OPS:
+ case KM_TAG_UNIQUE_ID:
+
+ /* Tags ignored because they contain data that should not be exported */
+ case KM_TAG_APPLICATION_DATA:
+ case KM_TAG_APPLICATION_ID:
+ case KM_TAG_ROOT_OF_TRUST:
+ continue;
+
+ /* Non-repeating enumerations */
+ case KM_TAG_ALGORITHM:
+ submod->add(EatClaim::ALGORITHM, get_uint32_value(entry));
+ break;
+ case KM_TAG_EC_CURVE:
+ submod->add(EatClaim::EC_CURVE, get_uint32_value(entry));
+ break;
+ case KM_TAG_USER_AUTH_TYPE:
+ submod->add(EatClaim::USER_AUTH_TYPE, get_uint32_value(entry));
+ break;
+ case KM_TAG_ORIGIN:
+ submod->add(EatClaim::ORIGIN, get_uint32_value(entry));
+ break;
+
+ /* Repeating enumerations */
+ case KM_TAG_PURPOSE:
+ add_repeating_enum(EatClaim::PURPOSE, get_uint32_value(entry), &repeating_fields);
+ break;
+ case KM_TAG_PADDING:
+ add_repeating_enum(EatClaim::PADDING, get_uint32_value(entry), &repeating_fields);
+ break;
+ case KM_TAG_DIGEST:
+ add_repeating_enum(EatClaim::DIGEST, get_uint32_value(entry), &repeating_fields);
+ break;
+ case KM_TAG_BLOCK_MODE:
+ add_repeating_enum(EatClaim::BLOCK_MODE, get_uint32_value(entry), &repeating_fields);
+ break;
+
+ /* Non-repeating unsigned integers */
+ case KM_TAG_KEY_SIZE:
+ submod->add(EatClaim::KEY_SIZE, get_uint32_value(entry));
+ break;
+ case KM_TAG_AUTH_TIMEOUT:
+ submod->add(EatClaim::AUTH_TIMEOUT, get_uint32_value(entry));
+ break;
+ case KM_TAG_OS_VERSION:
+ submod->add(EatClaim::OS_VERSION, get_uint32_value(entry));
+ break;
+ case KM_TAG_OS_PATCHLEVEL:
+ submod->add(EatClaim::OS_PATCHLEVEL, get_uint32_value(entry));
+ break;
+ case KM_TAG_VENDOR_PATCHLEVEL:
+ submod->add(EatClaim::VENDOR_PATCHLEVEL, get_uint32_value(entry));
+ break;
+ case KM_TAG_BOOT_PATCHLEVEL:
+ submod->add(EatClaim::BOOT_PATCHLEVEL, get_uint32_value(entry));
+ break;
+ case KM_TAG_MIN_MAC_LENGTH:
+ submod->add(EatClaim::MIN_MAC_LENGTH, get_uint32_value(entry));
+ break;
+
+ /* Non-repeating long unsigned integers */
+ case KM_TAG_RSA_PUBLIC_EXPONENT:
+ submod->add(EatClaim::RSA_PUBLIC_EXPONENT, entry.long_integer);
+ break;
+
+ /* Dates */
+ case KM_TAG_ACTIVE_DATETIME:
+ submod->add(EatClaim::ACTIVE_DATETIME, entry.date_time);
+ break;
+ case KM_TAG_ORIGINATION_EXPIRE_DATETIME:
+ submod->add(EatClaim::ORIGINATION_EXPIRE_DATETIME, entry.date_time);
+ break;
+ case KM_TAG_USAGE_EXPIRE_DATETIME:
+ submod->add(EatClaim::USAGE_EXPIRE_DATETIME, entry.date_time);
+ break;
+ case KM_TAG_CREATION_DATETIME:
+ submod->add(EatClaim::IAT, entry.date_time);
+ break;
+
+ /* Booleans */
+ case KM_TAG_NO_AUTH_REQUIRED:
+ submod->add(EatClaim::NO_AUTH_REQUIRED, true);
+ break;
+ case KM_TAG_ALL_APPLICATIONS:
+ submod->add(EatClaim::ALL_APPLICATIONS, true);
+ break;
+ case KM_TAG_ROLLBACK_RESISTANT:
+ submod->add(EatClaim::ROLLBACK_RESISTANT, true);
+ break;
+ case KM_TAG_ALLOW_WHILE_ON_BODY:
+ submod->add(EatClaim::ALLOW_WHILE_ON_BODY, true);
+ break;
+ case KM_TAG_UNLOCKED_DEVICE_REQUIRED:
+ submod->add(EatClaim::UNLOCKED_DEVICE_REQUIRED, true);
+ break;
+ case KM_TAG_CALLER_NONCE:
+ submod->add(EatClaim::CALLER_NONCE, true);
+ break;
+ case KM_TAG_TRUSTED_CONFIRMATION_REQUIRED:
+ submod->add(EatClaim::TRUSTED_CONFIRMATION_REQUIRED, true);
+ break;
+ case KM_TAG_EARLY_BOOT_ONLY:
+ submod->add(EatClaim::EARLY_BOOT_ONLY, true);
+ break;
+ case KM_TAG_DEVICE_UNIQUE_ATTESTATION:
+ submod->add(EatClaim::DEVICE_UNIQUE_ATTESTATION, true);
+ break;
+ case KM_TAG_IDENTITY_CREDENTIAL_KEY:
+ submod->add(EatClaim::IDENTITY_CREDENTIAL_KEY, true);
+ break;
+ case KM_TAG_TRUSTED_USER_PRESENCE_REQUIRED:
+ submod->add(EatClaim::TRUSTED_USER_PRESENCE_REQUIRED, true);
+ break;
+ case KM_TAG_STORAGE_KEY:
+ submod->add(EatClaim::STORAGE_KEY, true);
+ break;
+
+ /* Byte arrays*/
+ case KM_TAG_ATTESTATION_APPLICATION_ID:
+ submod->add(EatClaim::ATTESTATION_APPLICATION_ID, blob_to_bstr(entry.blob));
+ break;
+ case KM_TAG_ATTESTATION_ID_BRAND:
+ submod->add(EatClaim::ATTESTATION_ID_BRAND, blob_to_bstr(entry.blob));
+ break;
+ case KM_TAG_ATTESTATION_ID_DEVICE:
+ submod->add(EatClaim::ATTESTATION_ID_DEVICE, blob_to_bstr(entry.blob));
+ break;
+ case KM_TAG_ATTESTATION_ID_PRODUCT:
+ submod->add(EatClaim::ATTESTATION_ID_PRODUCT, blob_to_bstr(entry.blob));
+ break;
+ case KM_TAG_ATTESTATION_ID_SERIAL:
+ submod->add(EatClaim::ATTESTATION_ID_SERIAL, blob_to_bstr(entry.blob));
+ break;
+ case KM_TAG_ATTESTATION_ID_IMEI: {
+ cppbor::Bstr ueid("");
+ keymaster_error_t error = imei_to_ueid(entry.blob, &ueid);
+ if (error != KM_ERROR_OK) return error;
+ submod->add(EatClaim::UEID, ueid);
+ break;
+ }
+ case KM_TAG_ATTESTATION_ID_MEID:
+ submod->add(EatClaim::ATTESTATION_ID_MEID, blob_to_bstr(entry.blob));
+ break;
+ case KM_TAG_ATTESTATION_ID_MANUFACTURER:
+ submod->add(EatClaim::ATTESTATION_ID_MANUFACTURER, blob_to_bstr(entry.blob));
+ break;
+ case KM_TAG_ATTESTATION_ID_MODEL:
+ submod->add(EatClaim::ATTESTATION_ID_MODEL, blob_to_bstr(entry.blob));
+ break;
+ case KM_TAG_CONFIRMATION_TOKEN:
+ submod->add(EatClaim::CONFIRMATION_TOKEN, blob_to_bstr(entry.blob));
+ break;
+ }
+ }
+
+ // Move values from repeating enums into the submod map.
+ for (auto const& repeating_field : repeating_fields) {
+ EatClaim key = static_cast<EatClaim>(repeating_field.first);
+ submod->add(key, std::move(repeating_fields.at(key)));
+ }
+
+ int ec_curve;
+ uint32_t key_size;
+ if (auth_list.Contains(TAG_ALGORITHM, KM_ALGORITHM_EC) && !auth_list.Contains(TAG_EC_CURVE) &&
+ auth_list.GetTagValue(TAG_KEY_SIZE, &key_size)) {
+ // This must be a keymaster1 key. It's an EC key with no curve. Insert the curve.
+
+ keymaster_error_t error = ec_key_size_to_eat_curve(key_size, &ec_curve);
+ if (error != KM_ERROR_OK) return error;
+
+ submod->add(EatClaim::EC_CURVE, ec_curve);
+ }
+
+ return KM_ERROR_OK;
+}
+
+// Put the contents of the keymaster AuthorizationSet auth_list into the ASN.1 record structure,
// record.
keymaster_error_t build_auth_list(const AuthorizationSet& auth_list, KM_AUTH_LIST* record) {
- assert(record);
+ ASSERT_OR_RETURN_ERROR(record, KM_ERROR_UNEXPECTED_NULL_POINTER);
- if (auth_list.empty())
- return KM_ERROR_OK;
+ if (auth_list.empty()) return KM_ERROR_OK;
for (auto entry : auth_list) {
@@ -129,6 +537,13 @@
case KM_TAG_MAC_LENGTH:
case KM_TAG_ATTESTATION_CHALLENGE:
case KM_TAG_RESET_SINCE_ID_ROTATION:
+ case KM_TAG_KDF:
+
+ /* Tags ignored because they're used only to provide for certificate generation */
+ case KM_TAG_CERTIFICATE_SERIAL:
+ case KM_TAG_CERTIFICATE_SUBJECT:
+ case KM_TAG_CERTIFICATE_NOT_BEFORE:
+ case KM_TAG_CERTIFICATE_NOT_AFTER:
/* Tags ignored because they have no meaning off-device */
case KM_TAG_USER_ID:
@@ -138,12 +553,16 @@
/* Tags ignored because they're not usable by app keys */
case KM_TAG_BOOTLOADER_ONLY:
case KM_TAG_INCLUDE_UNIQUE_ID:
+ case KM_TAG_MAX_BOOT_LEVEL:
case KM_TAG_MAX_USES_PER_BOOT:
case KM_TAG_MIN_SECONDS_BETWEEN_OPS:
+ case KM_TAG_STORAGE_KEY:
case KM_TAG_UNIQUE_ID:
/* Tags ignored because they contain data that should not be exported */
case KM_TAG_APPLICATION_DATA:
+ case KM_TAG_APPLICATION_ID:
+ case KM_TAG_CONFIRMATION_TOKEN:
case KM_TAG_ROOT_OF_TRUST:
continue;
@@ -171,12 +590,12 @@
case KM_TAG_DIGEST:
integer_set = &record->digest;
break;
- case KM_TAG_KDF:
- integer_set = &record->kdf;
- break;
case KM_TAG_BLOCK_MODE:
integer_set = &record->block_mode;
break;
+ case KM_TAG_RSA_OAEP_MGF_DIGEST:
+ integer_set = &record->mgf_digest;
+ break;
/* Non-repeating unsigned integers */
case KM_TAG_KEY_SIZE:
@@ -194,6 +613,15 @@
case KM_TAG_MIN_MAC_LENGTH:
integer_ptr = &record->min_mac_length;
break;
+ case KM_TAG_BOOT_PATCHLEVEL:
+ integer_ptr = &record->boot_patch_level;
+ break;
+ case KM_TAG_VENDOR_PATCHLEVEL:
+ integer_ptr = &record->vendor_patchlevel;
+ break;
+ case KM_TAG_USAGE_COUNT_LIMIT:
+ integer_ptr = &record->usage_count_limit;
+ break;
/* Non-repeating long unsigned integers */
case KM_TAG_RSA_PUBLIC_EXPONENT:
@@ -239,11 +667,20 @@
case KM_TAG_TRUSTED_CONFIRMATION_REQUIRED:
bool_ptr = &record->trusted_confirmation_required;
break;
+ case KM_TAG_EARLY_BOOT_ONLY:
+ bool_ptr = &record->early_boot_only;
+ break;
+ case KM_TAG_DEVICE_UNIQUE_ATTESTATION:
+ bool_ptr = &record->device_unique_attestation;
+ break;
+ case KM_TAG_IDENTITY_CREDENTIAL_KEY:
+ bool_ptr = &record->identity_credential_key;
+ break;
+ case KM_TAG_TRUSTED_USER_PRESENCE_REQUIRED:
+ bool_ptr = &record->trusted_user_presence_required;
+ break;
/* Byte arrays*/
- case KM_TAG_APPLICATION_ID:
- string_ptr = &record->application_id;
- break;
case KM_TAG_ATTESTATION_APPLICATION_ID:
string_ptr = &record->attestation_application_id;
break;
@@ -279,14 +716,17 @@
case KM_ENUM_REP:
case KM_UINT:
case KM_UINT_REP: {
- assert((keymaster_tag_repeatable(entry.tag) && integer_set) ||
- (!keymaster_tag_repeatable(entry.tag) && integer_ptr));
+ ASSERT_OR_RETURN_ERROR((keymaster_tag_repeatable(entry.tag) && integer_set) ||
+ (!keymaster_tag_repeatable(entry.tag) && integer_ptr),
+ KM_ERROR_INVALID_TAG);
UniquePtr<ASN1_INTEGER, ASN1_INTEGER_Delete> value(ASN1_INTEGER_new());
- if (!value.get())
+ if (!value.get()) {
return KM_ERROR_MEMORY_ALLOCATION_FAILED;
- if (!ASN1_INTEGER_set(value.get(), get_uint32_value(entry)))
+ }
+ if (!ASN1_INTEGER_set(value.get(), get_uint32_value(entry))) {
return TranslateLastOpenSslError();
+ }
insert_integer(value.release(), integer_ptr, integer_set);
break;
@@ -295,12 +735,14 @@
case KM_ULONG:
case KM_ULONG_REP:
case KM_DATE: {
- assert((keymaster_tag_repeatable(entry.tag) && integer_set) ||
- (!keymaster_tag_repeatable(entry.tag) && integer_ptr));
+ ASSERT_OR_RETURN_ERROR((keymaster_tag_repeatable(entry.tag) && integer_set) ||
+ (!keymaster_tag_repeatable(entry.tag) && integer_ptr),
+ KM_ERROR_INVALID_TAG);
UniquePtr<BIGNUM, BIGNUM_Delete> bn_value(BN_new());
- if (!bn_value.get())
+ if (!bn_value.get()) {
return KM_ERROR_MEMORY_ALLOCATION_FAILED;
+ }
if (type == KM_DATE) {
if (!BN_set_u64(bn_value.get(), entry.date_time)) {
@@ -314,30 +756,32 @@
UniquePtr<ASN1_INTEGER, ASN1_INTEGER_Delete> value(
BN_to_ASN1_INTEGER(bn_value.get(), nullptr));
- if (!value.get())
+ if (!value.get()) {
return KM_ERROR_MEMORY_ALLOCATION_FAILED;
+ }
insert_integer(value.release(), integer_ptr, integer_set);
break;
}
case KM_BOOL:
- assert(bool_ptr);
- if (!*bool_ptr)
- *bool_ptr = ASN1_NULL_new();
- if (!*bool_ptr)
- return KM_ERROR_MEMORY_ALLOCATION_FAILED;
+ ASSERT_OR_RETURN_ERROR(bool_ptr, KM_ERROR_INVALID_TAG);
+ if (!*bool_ptr) *bool_ptr = ASN1_NULL_new();
+ if (!*bool_ptr) return KM_ERROR_MEMORY_ALLOCATION_FAILED;
break;
/* Byte arrays*/
case KM_BYTES:
- assert(string_ptr);
- if (!*string_ptr)
+ ASSERT_OR_RETURN_ERROR(string_ptr, KM_ERROR_INVALID_TAG);
+ if (!*string_ptr) {
*string_ptr = ASN1_OCTET_STRING_new();
- if (!*string_ptr)
+ }
+ if (!*string_ptr) {
return KM_ERROR_MEMORY_ALLOCATION_FAILED;
- if (!ASN1_OCTET_STRING_set(*string_ptr, entry.blob.data, entry.blob.data_length))
+ }
+ if (!ASN1_OCTET_STRING_set(*string_ptr, entry.blob.data, entry.blob.data_length)) {
return TranslateLastOpenSslError();
+ }
break;
default:
@@ -353,15 +797,16 @@
// This must be a keymaster1 key. It's an EC key with no curve. Insert the curve.
keymaster_error_t error = EcKeySizeToCurve(key_size, &ec_curve);
- if (error != KM_ERROR_OK)
- return error;
+ if (error != KM_ERROR_OK) return error;
UniquePtr<ASN1_INTEGER, ASN1_INTEGER_Delete> value(ASN1_INTEGER_new());
- if (!value.get())
+ if (!value.get()) {
return KM_ERROR_MEMORY_ALLOCATION_FAILED;
+ }
- if (!ASN1_INTEGER_set(value.get(), ec_curve))
+ if (!ASN1_INTEGER_set(value.get(), ec_curve)) {
return TranslateLastOpenSslError();
+ }
insert_integer(value.release(), &record->ec_curve, nullptr);
}
@@ -369,19 +814,164 @@
return KM_ERROR_OK;
}
+// Construct a CBOR-encoded attestation record containing the values from sw_enforced
+// and tee_enforced.
+keymaster_error_t build_eat_record(const AuthorizationSet& attestation_params,
+ AuthorizationSet sw_enforced, AuthorizationSet tee_enforced,
+ const AttestationContext& context,
+ std::vector<uint8_t>* eat_token) {
+ ASSERT_OR_RETURN_ERROR(eat_token, KM_ERROR_UNEXPECTED_NULL_POINTER);
+
+ cppbor::Map eat_record;
+ switch (context.GetSecurityLevel()) {
+ case KM_SECURITY_LEVEL_SOFTWARE:
+ eat_record.add(EatClaim::SECURITY_LEVEL, get_uint32_value(EatSecurityLevel::UNRESTRICTED));
+ break;
+ case KM_SECURITY_LEVEL_TRUSTED_ENVIRONMENT:
+ eat_record.add(EatClaim::SECURITY_LEVEL,
+ get_uint32_value(EatSecurityLevel::SECURE_RESTRICTED));
+ break;
+ case KM_SECURITY_LEVEL_STRONGBOX:
+ eat_record.add(EatClaim::SECURITY_LEVEL, get_uint32_value(EatSecurityLevel::HARDWARE));
+ break;
+ default:
+ return KM_ERROR_UNKNOWN_ERROR;
+ }
+
+ keymaster_error_t error;
+ const AttestationContext::VerifiedBootParams* vb_params = context.GetVerifiedBootParams(&error);
+ if (error != KM_ERROR_OK) return error;
+
+ if (vb_params->verified_boot_key.data_length) {
+ eat_record.add(EatClaim::VERIFIED_BOOT_KEY, blob_to_bstr(vb_params->verified_boot_key));
+ }
+ if (vb_params->verified_boot_hash.data_length) {
+ eat_record.add(EatClaim::VERIFIED_BOOT_HASH, blob_to_bstr(vb_params->verified_boot_hash));
+ }
+ if (vb_params->device_locked) {
+ eat_record.add(EatClaim::DEVICE_LOCKED, vb_params->device_locked);
+ }
+
+ bool verified_or_self_signed = (vb_params->verified_boot_state == KM_VERIFIED_BOOT_VERIFIED ||
+ vb_params->verified_boot_state == KM_VERIFIED_BOOT_SELF_SIGNED);
+ auto eat_boot_state = cppbor::Array()
+ .add(verified_or_self_signed) // secure-boot-enabled
+ .add(verified_or_self_signed) // debug-disabled
+ .add(verified_or_self_signed) // debug-disabled-since-boot
+ .add(verified_or_self_signed) // debug-permanent-disable
+ .add(false); // debug-full-permanent-disable (no way to verify)
+ eat_record.add(EatClaim::BOOT_STATE, std::move(eat_boot_state));
+ eat_record.add(EatClaim::OFFICIAL_BUILD,
+ vb_params->verified_boot_state == KM_VERIFIED_BOOT_VERIFIED);
+
+ eat_record.add(EatClaim::ATTESTATION_VERSION,
+ version_to_attestation_version(context.GetKmVersion()));
+ eat_record.add(EatClaim::KEYMASTER_VERSION,
+ version_to_attestation_km_version(context.GetKmVersion()));
+
+ keymaster_blob_t attestation_challenge = {nullptr, 0};
+ if (!attestation_params.GetTagValue(TAG_ATTESTATION_CHALLENGE, &attestation_challenge)) {
+ return KM_ERROR_ATTESTATION_CHALLENGE_MISSING;
+ }
+
+ if (!is_valid_attestation_challenge(attestation_challenge)) {
+ return KM_ERROR_INVALID_INPUT_LENGTH;
+ }
+
+ eat_record.add(EatClaim::NONCE, blob_to_bstr(attestation_challenge));
+
+ keymaster_blob_t attestation_app_id;
+ if (!attestation_params.GetTagValue(TAG_ATTESTATION_APPLICATION_ID, &attestation_app_id)) {
+ return KM_ERROR_ATTESTATION_APPLICATION_ID_MISSING;
+ }
+ // TODO: what should happen when sw_enforced already contains TAG_ATTESTATION_APPLICATION_ID?
+ // (as is the case in android_keymaster_test.cpp). For now, we will ignore the provided one in
+ // attestation_params if that's the case.
+ keymaster_blob_t existing_app_id;
+ if (!sw_enforced.GetTagValue(TAG_ATTESTATION_APPLICATION_ID, &existing_app_id)) {
+ sw_enforced.push_back(TAG_ATTESTATION_APPLICATION_ID, attestation_app_id);
+ }
+
+ error = context.VerifyAndCopyDeviceIds(
+ attestation_params,
+ context.GetSecurityLevel() == KM_SECURITY_LEVEL_SOFTWARE ? &sw_enforced : &tee_enforced);
+ if (error == KM_ERROR_UNIMPLEMENTED) {
+ // The KeymasterContext implementation does not support device ID attestation. Bail out if
+ // device ID attestation is being attempted.
+ for (const auto& tag : kDeviceAttestationTags) {
+ if (attestation_params.find(tag) != -1) {
+ return KM_ERROR_CANNOT_ATTEST_IDS;
+ }
+ }
+ } else if (error != KM_ERROR_OK) {
+ return error;
+ }
+
+ if (attestation_params.Contains(TAG_DEVICE_UNIQUE_ATTESTATION) &&
+ context.GetSecurityLevel() == KM_SECURITY_LEVEL_STRONGBOX) {
+ eat_record.add(EatClaim::DEVICE_UNIQUE_ATTESTATION, true);
+ }
+
+ cppbor::Map software_submod;
+ error = build_eat_submod(sw_enforced, EatSecurityLevel::UNRESTRICTED, &software_submod);
+ if (error != KM_ERROR_OK) return error;
+
+ cppbor::Map tee_submod;
+ error = build_eat_submod(tee_enforced, EatSecurityLevel::SECURE_RESTRICTED, &tee_submod);
+ if (error != KM_ERROR_OK) return error;
+
+ if (software_submod.size() + tee_submod.size() > 0) {
+ cppbor::Map submods;
+ if (software_submod.size() > 0) {
+ submods.add(kEatSubmodNameSoftware, std::move(software_submod));
+ }
+ if (tee_submod.size() > 0) {
+ submods.add(kEatSubmodNameTee, std::move(tee_submod));
+ }
+
+ eat_record.add(EatClaim::SUBMODS, std::move(submods));
+ }
+
+ // Only check tee_enforced for TAG_INCLUDE_UNIQUE_ID. If we don't have hardware we can't
+ // generate unique IDs.
+ if (tee_enforced.GetTagValue(TAG_INCLUDE_UNIQUE_ID)) {
+ uint64_t creation_datetime;
+ // Only check sw_enforced for TAG_CREATION_DATETIME, since it shouldn't be in tee_enforced,
+ // since this implementation has no secure wall clock.
+ if (!sw_enforced.GetTagValue(TAG_CREATION_DATETIME, &creation_datetime)) {
+ LOG_E("Unique ID cannot be created without creation datetime", 0);
+ return KM_ERROR_INVALID_KEY_BLOB;
+ }
+
+ keymaster_blob_t application_id = {nullptr, 0};
+ sw_enforced.GetTagValue(TAG_APPLICATION_ID, &application_id);
+
+ Buffer unique_id = context.GenerateUniqueId(
+ creation_datetime, application_id,
+ attestation_params.GetTagValue(TAG_RESET_SINCE_ID_ROTATION), &error);
+ if (error != KM_ERROR_OK) return error;
+
+ eat_record.add(EatClaim::CTI,
+ cppbor::Bstr(std::pair(unique_id.begin(), unique_id.available_read())));
+ }
+
+ *eat_token = eat_record.encode();
+
+ return KM_ERROR_OK;
+}
+
// Construct an ASN1.1 DER-encoded attestation record containing the values from sw_enforced and
// tee_enforced.
-keymaster_error_t build_attestation_record(const AuthorizationSet& attestation_params,
+keymaster_error_t build_attestation_record(const AuthorizationSet& attestation_params, //
AuthorizationSet sw_enforced,
AuthorizationSet tee_enforced,
- const AttestationRecordContext& context,
+ const AttestationContext& context,
UniquePtr<uint8_t[]>* asn1_key_desc,
size_t* asn1_key_desc_len) {
- assert(asn1_key_desc && asn1_key_desc_len);
+ ASSERT_OR_RETURN_ERROR(asn1_key_desc && asn1_key_desc_len, KM_ERROR_UNEXPECTED_NULL_POINTER);
UniquePtr<KM_KEY_DESCRIPTION, KM_KEY_DESCRIPTION_Delete> key_desc(KM_KEY_DESCRIPTION_new());
- if (!key_desc.get())
- return KM_ERROR_MEMORY_ALLOCATION_FAILED;
+ if (!key_desc.get()) return KM_ERROR_MEMORY_ALLOCATION_FAILED;
KM_ROOT_OF_TRUST* root_of_trust = nullptr;
if (context.GetSecurityLevel() == KM_SECURITY_LEVEL_SOFTWARE) {
@@ -392,51 +982,53 @@
root_of_trust = key_desc->tee_enforced->root_of_trust;
}
- keymaster_blob_t verified_boot_key;
- keymaster_blob_t verified_boot_hash;
- keymaster_verified_boot_t verified_boot_state;
- bool device_locked;
- keymaster_error_t error = context.GetVerifiedBootParams(&verified_boot_key, &verified_boot_hash,
- &verified_boot_state, &device_locked);
+ keymaster_error_t error;
+ auto vb_params = context.GetVerifiedBootParams(&error);
if (error != KM_ERROR_OK) return error;
- if (verified_boot_key.data_length &&
- !ASN1_OCTET_STRING_set(root_of_trust->verified_boot_key, verified_boot_key.data,
- verified_boot_key.data_length)) {
+ if (vb_params->verified_boot_key.data_length &&
+ !ASN1_OCTET_STRING_set(root_of_trust->verified_boot_key, vb_params->verified_boot_key.data,
+ vb_params->verified_boot_key.data_length)) {
+ return TranslateLastOpenSslError();
+ }
+ if (vb_params->verified_boot_hash.data_length &&
+ !ASN1_OCTET_STRING_set(root_of_trust->verified_boot_hash,
+ vb_params->verified_boot_hash.data,
+ vb_params->verified_boot_hash.data_length)) {
return TranslateLastOpenSslError();
}
- root_of_trust->device_locked = reinterpret_cast<int*>(malloc(sizeof(ASN1_BOOLEAN)));
- *root_of_trust->device_locked = device_locked;
- if (!ASN1_ENUMERATED_set(root_of_trust->verified_boot_state, verified_boot_state)) {
- return TranslateLastOpenSslError();
- }
- if (verified_boot_hash.data_length &&
- !ASN1_OCTET_STRING_set(root_of_trust->verified_boot_hash, verified_boot_hash.data,
- verified_boot_hash.data_length)) {
+ root_of_trust->device_locked = vb_params->device_locked ? 0xFF : 0x00;
+ if (!ASN1_ENUMERATED_set(root_of_trust->verified_boot_state, vb_params->verified_boot_state)) {
return TranslateLastOpenSslError();
}
- if (!ASN1_INTEGER_set(key_desc->attestation_version, kCurrentAttestationVersion) ||
+ if (!ASN1_INTEGER_set(key_desc->attestation_version,
+ version_to_attestation_version(context.GetKmVersion())) ||
!ASN1_ENUMERATED_set(key_desc->attestation_security_level, context.GetSecurityLevel()) ||
- !ASN1_INTEGER_set(key_desc->keymaster_version, kCurrentKeymasterVersion) ||
+ !ASN1_INTEGER_set(key_desc->keymaster_version,
+ version_to_attestation_km_version(context.GetKmVersion())) ||
!ASN1_ENUMERATED_set(key_desc->keymaster_security_level, context.GetSecurityLevel())) {
return TranslateLastOpenSslError();
}
keymaster_blob_t attestation_challenge = {nullptr, 0};
- if (!attestation_params.GetTagValue(TAG_ATTESTATION_CHALLENGE, &attestation_challenge))
+ if (!attestation_params.GetTagValue(TAG_ATTESTATION_CHALLENGE, &attestation_challenge)) {
return KM_ERROR_ATTESTATION_CHALLENGE_MISSING;
+ }
- if (attestation_challenge.data_length > kMaximumAttestationChallengeLength)
+ if (!is_valid_attestation_challenge(attestation_challenge)) {
return KM_ERROR_INVALID_INPUT_LENGTH;
+ }
if (!ASN1_OCTET_STRING_set(key_desc->attestation_challenge, attestation_challenge.data,
- attestation_challenge.data_length))
+ attestation_challenge.data_length)) {
return TranslateLastOpenSslError();
+ }
keymaster_blob_t attestation_app_id;
- if (!attestation_params.GetTagValue(TAG_ATTESTATION_APPLICATION_ID, &attestation_app_id))
+ if (!attestation_params.GetTagValue(TAG_ATTESTATION_APPLICATION_ID, &attestation_app_id)) {
return KM_ERROR_ATTESTATION_APPLICATION_ID_MISSING;
+ }
sw_enforced.push_back(TAG_ATTESTATION_APPLICATION_ID, attestation_app_id);
error = context.VerifyAndCopyDeviceIds(
@@ -454,13 +1046,16 @@
return error;
}
+ if (attestation_params.Contains(TAG_DEVICE_UNIQUE_ATTESTATION) &&
+ context.GetSecurityLevel() == KM_SECURITY_LEVEL_STRONGBOX) {
+ tee_enforced.push_back(TAG_DEVICE_UNIQUE_ATTESTATION);
+ };
+
error = build_auth_list(sw_enforced, key_desc->software_enforced);
- if (error != KM_ERROR_OK)
- return error;
+ if (error != KM_ERROR_OK) return error;
error = build_auth_list(tee_enforced, key_desc->tee_enforced);
- if (error != KM_ERROR_OK)
- return error;
+ if (error != KM_ERROR_OK) return error;
// Only check tee_enforced for TAG_INCLUDE_UNIQUE_ID. If we don't have hardware we can't
// generate unique IDs.
@@ -476,12 +1071,10 @@
keymaster_blob_t application_id = {nullptr, 0};
sw_enforced.GetTagValue(TAG_APPLICATION_ID, &application_id);
- Buffer unique_id;
- error = context.GenerateUniqueId(
+ Buffer unique_id = context.GenerateUniqueId(
creation_datetime, application_id,
- attestation_params.GetTagValue(TAG_RESET_SINCE_ID_ROTATION), &unique_id);
- if (error != KM_ERROR_OK)
- return error;
+ attestation_params.GetTagValue(TAG_RESET_SINCE_ID_ROTATION), &error);
+ if (error != KM_ERROR_OK) return error;
key_desc->unique_id = ASN1_OCTET_STRING_new();
if (!key_desc->unique_id ||
@@ -491,16 +1084,13 @@
}
int len = i2d_KM_KEY_DESCRIPTION(key_desc.get(), nullptr);
- if (len < 0)
- return TranslateLastOpenSslError();
+ if (len < 0) return TranslateLastOpenSslError();
*asn1_key_desc_len = len;
- asn1_key_desc->reset(new(std::nothrow) uint8_t[*asn1_key_desc_len]);
- if (!asn1_key_desc->get())
- return KM_ERROR_MEMORY_ALLOCATION_FAILED;
+ asn1_key_desc->reset(new (std::nothrow) uint8_t[*asn1_key_desc_len]);
+ if (!asn1_key_desc->get()) return KM_ERROR_MEMORY_ALLOCATION_FAILED;
uint8_t* p = asn1_key_desc->get();
len = i2d_KM_KEY_DESCRIPTION(key_desc.get(), &p);
- if (len < 0)
- return TranslateLastOpenSslError();
+ if (len < 0) return TranslateLastOpenSslError();
return KM_ERROR_OK;
}
@@ -508,7 +1098,7 @@
// Copy all enumerated values with the specified tag from stack to auth_list.
static bool get_repeated_enums(const ASN1_INTEGER_SET* stack, keymaster_tag_t tag,
AuthorizationSet* auth_list) {
- assert(keymaster_tag_get_type(tag) == KM_ENUM_REP);
+ ASSERT_OR_RETURN_ERROR(keymaster_tag_get_type(tag) == KM_ENUM_REP, KM_ERROR_INVALID_TAG);
for (size_t i = 0; i < sk_ASN1_INTEGER_num(stack); ++i) {
if (!auth_list->push_back(
keymaster_param_enum(tag, ASN1_INTEGER_get(sk_ASN1_INTEGER_value(stack, i)))))
@@ -521,196 +1111,283 @@
template <keymaster_tag_type_t Type, keymaster_tag_t Tag, typename KeymasterEnum>
static bool get_enum(const ASN1_INTEGER* asn1_int, TypedEnumTag<Type, Tag, KeymasterEnum> tag,
AuthorizationSet* auth_list) {
- if (!asn1_int)
- return true;
+ if (!asn1_int) return true;
return auth_list->push_back(tag, static_cast<KeymasterEnum>(ASN1_INTEGER_get(asn1_int)));
}
// Add the specified ulong tag/value pair to auth_list.
static bool get_ulong(const ASN1_INTEGER* asn1_int, keymaster_tag_t tag,
AuthorizationSet* auth_list) {
- if (!asn1_int)
- return true;
+ if (!asn1_int) return true;
UniquePtr<BIGNUM, BIGNUM_Delete> bn(ASN1_INTEGER_to_BN(asn1_int, nullptr));
- if (!bn.get())
- return false;
- uint64_t ulong = BN_get_word(bn.get());
+ if (!bn.get()) return false;
+ uint64_t ulong = 0;
+ BN_get_u64(bn.get(), &ulong);
return auth_list->push_back(keymaster_param_long(tag, ulong));
}
// Extract the values from the specified ASN.1 record and place them in auth_list.
keymaster_error_t extract_auth_list(const KM_AUTH_LIST* record, AuthorizationSet* auth_list) {
- if (!record)
- return KM_ERROR_OK;
+ if (!record) return KM_ERROR_OK;
// Purpose
- if (!get_repeated_enums(record->purpose, TAG_PURPOSE, auth_list))
+ if (!get_repeated_enums(record->purpose, TAG_PURPOSE, auth_list)) {
return KM_ERROR_MEMORY_ALLOCATION_FAILED;
+ }
// Algorithm
- if (!get_enum(record->algorithm, TAG_ALGORITHM, auth_list))
+ if (!get_enum(record->algorithm, TAG_ALGORITHM, auth_list)) {
return KM_ERROR_MEMORY_ALLOCATION_FAILED;
+ }
// Key size
- if (record->key_size && !auth_list->push_back(TAG_KEY_SIZE, ASN1_INTEGER_get(record->key_size)))
+ if (record->key_size &&
+ !auth_list->push_back(TAG_KEY_SIZE, ASN1_INTEGER_get(record->key_size))) {
return KM_ERROR_MEMORY_ALLOCATION_FAILED;
+ }
// Block mode
- if (!get_repeated_enums(record->block_mode, TAG_BLOCK_MODE, auth_list))
+ if (!get_repeated_enums(record->block_mode, TAG_BLOCK_MODE, auth_list)) {
return KM_ERROR_MEMORY_ALLOCATION_FAILED;
+ }
// Digest
- if (!get_repeated_enums(record->digest, TAG_DIGEST, auth_list))
+ if (!get_repeated_enums(record->digest, TAG_DIGEST, auth_list)) {
return KM_ERROR_MEMORY_ALLOCATION_FAILED;
+ }
// Padding
- if (!get_repeated_enums(record->padding, TAG_PADDING, auth_list))
+ if (!get_repeated_enums(record->padding, TAG_PADDING, auth_list)) {
return KM_ERROR_MEMORY_ALLOCATION_FAILED;
+ }
// Caller nonce
- if (record->caller_nonce && !auth_list->push_back(TAG_CALLER_NONCE))
+ if (record->caller_nonce && !auth_list->push_back(TAG_CALLER_NONCE)) {
return KM_ERROR_MEMORY_ALLOCATION_FAILED;
+ }
// Min mac length
- if (!get_ulong(record->min_mac_length, TAG_MIN_MAC_LENGTH, auth_list))
+ if (!get_ulong(record->min_mac_length, TAG_MIN_MAC_LENGTH, auth_list)) {
return KM_ERROR_MEMORY_ALLOCATION_FAILED;
+ }
// EC curve
- if (!get_enum(record->ec_curve, TAG_EC_CURVE, auth_list))
+ if (!get_enum(record->ec_curve, TAG_EC_CURVE, auth_list)) {
return KM_ERROR_MEMORY_ALLOCATION_FAILED;
+ }
// RSA public exponent
- if (!get_ulong(record->rsa_public_exponent, TAG_RSA_PUBLIC_EXPONENT, auth_list))
+ if (!get_ulong(record->rsa_public_exponent, TAG_RSA_PUBLIC_EXPONENT, auth_list)) {
return KM_ERROR_MEMORY_ALLOCATION_FAILED;
+ }
+
+ // Rsa Oaep Mgf Digest
+ if (!get_repeated_enums(record->mgf_digest, TAG_RSA_OAEP_MGF_DIGEST, auth_list)) {
+ return KM_ERROR_MEMORY_ALLOCATION_FAILED;
+ }
+
+ // Rollback resistance
+ if (record->rollback_resistance && !auth_list->push_back(TAG_ROLLBACK_RESISTANCE)) {
+ return KM_ERROR_MEMORY_ALLOCATION_FAILED;
+ }
+
+ // Early boot only
+ if (record->early_boot_only && !auth_list->push_back(TAG_EARLY_BOOT_ONLY)) {
+ return KM_ERROR_MEMORY_ALLOCATION_FAILED;
+ }
// Active date time
- if (!get_ulong(record->active_date_time, TAG_ACTIVE_DATETIME, auth_list))
+ if (!get_ulong(record->active_date_time, TAG_ACTIVE_DATETIME, auth_list)) {
return KM_ERROR_MEMORY_ALLOCATION_FAILED;
+ }
// Origination expire date time
if (!get_ulong(record->origination_expire_date_time, TAG_ORIGINATION_EXPIRE_DATETIME,
- auth_list))
+ auth_list)) {
return KM_ERROR_MEMORY_ALLOCATION_FAILED;
+ }
// Usage Expire date time
- if (!get_ulong(record->usage_expire_date_time, TAG_USAGE_EXPIRE_DATETIME, auth_list))
+ if (!get_ulong(record->usage_expire_date_time, TAG_USAGE_EXPIRE_DATETIME, auth_list)) {
return KM_ERROR_MEMORY_ALLOCATION_FAILED;
+ }
+
+ // Usage count limit
+ if (record->usage_count_limit &&
+ !auth_list->push_back(TAG_USAGE_COUNT_LIMIT, ASN1_INTEGER_get(record->usage_count_limit))) {
+ return KM_ERROR_MEMORY_ALLOCATION_FAILED;
+ }
// No auth required
- if (record->no_auth_required && !auth_list->push_back(TAG_NO_AUTH_REQUIRED))
+ if (record->no_auth_required && !auth_list->push_back(TAG_NO_AUTH_REQUIRED)) {
return KM_ERROR_MEMORY_ALLOCATION_FAILED;
+ }
// User auth type
- if (!get_enum(record->user_auth_type, TAG_USER_AUTH_TYPE, auth_list))
+ if (!get_enum(record->user_auth_type, TAG_USER_AUTH_TYPE, auth_list)) {
return KM_ERROR_MEMORY_ALLOCATION_FAILED;
+ }
// Auth timeout
if (record->auth_timeout &&
- !auth_list->push_back(TAG_AUTH_TIMEOUT, ASN1_INTEGER_get(record->auth_timeout)))
+ !auth_list->push_back(TAG_AUTH_TIMEOUT, ASN1_INTEGER_get(record->auth_timeout))) {
return KM_ERROR_MEMORY_ALLOCATION_FAILED;
+ }
+
+ // Allow while on body
+ if (record->allow_while_on_body && !auth_list->push_back(TAG_ALLOW_WHILE_ON_BODY)) {
+ return KM_ERROR_MEMORY_ALLOCATION_FAILED;
+ }
+
+ // trusted user presence required
+ if (record->trusted_user_presence_required &&
+ !auth_list->push_back(TAG_TRUSTED_USER_PRESENCE_REQUIRED)) {
+ return KM_ERROR_MEMORY_ALLOCATION_FAILED;
+ }
+
+ // trusted confirmation required
+ if (record->trusted_confirmation_required &&
+ !auth_list->push_back(TAG_TRUSTED_CONFIRMATION_REQUIRED)) {
+ return KM_ERROR_MEMORY_ALLOCATION_FAILED;
+ }
+
+ // Unlocked device required
+ if (record->unlocked_device_required && !auth_list->push_back(TAG_UNLOCKED_DEVICE_REQUIRED)) {
+ return KM_ERROR_MEMORY_ALLOCATION_FAILED;
+ }
// All applications
- if (record->all_applications && !auth_list->push_back(TAG_ALL_APPLICATIONS))
+ if (record->all_applications && !auth_list->push_back(TAG_ALL_APPLICATIONS)) {
return KM_ERROR_MEMORY_ALLOCATION_FAILED;
+ }
// Application ID
if (record->application_id &&
!auth_list->push_back(TAG_APPLICATION_ID, record->application_id->data,
- record->application_id->length))
+ record->application_id->length)) {
return KM_ERROR_MEMORY_ALLOCATION_FAILED;
-
- // Attestation application ID
- if (record->attestation_application_id &&
- !auth_list->push_back(TAG_ATTESTATION_APPLICATION_ID,
- record->attestation_application_id->data,
- record->attestation_application_id->length))
- return KM_ERROR_MEMORY_ALLOCATION_FAILED;
+ }
// Creation date time
- if (!get_ulong(record->creation_date_time, TAG_CREATION_DATETIME, auth_list))
+ if (!get_ulong(record->creation_date_time, TAG_CREATION_DATETIME, auth_list)) {
return KM_ERROR_MEMORY_ALLOCATION_FAILED;
+ }
// Origin
- if (!get_enum(record->origin, TAG_ORIGIN, auth_list))
+ if (!get_enum(record->origin, TAG_ORIGIN, auth_list)) {
return KM_ERROR_MEMORY_ALLOCATION_FAILED;
+ }
// Rollback resistant
- if (record->rollback_resistant && !auth_list->push_back(TAG_ROLLBACK_RESISTANT))
+ if (record->rollback_resistant && !auth_list->push_back(TAG_ROLLBACK_RESISTANT)) {
return KM_ERROR_MEMORY_ALLOCATION_FAILED;
+ }
// Root of trust
if (record->root_of_trust) {
KM_ROOT_OF_TRUST* rot = record->root_of_trust;
- if (!rot->verified_boot_key)
- return KM_ERROR_INVALID_KEY_BLOB;
+ if (!rot->verified_boot_key) return KM_ERROR_INVALID_KEY_BLOB;
// Other root of trust fields are not mapped to auth set entries.
}
// OS Version
if (record->os_version &&
- !auth_list->push_back(TAG_OS_VERSION, ASN1_INTEGER_get(record->os_version)))
+ !auth_list->push_back(TAG_OS_VERSION, ASN1_INTEGER_get(record->os_version))) {
return KM_ERROR_MEMORY_ALLOCATION_FAILED;
+ }
// OS Patch level
if (record->os_patchlevel &&
- !auth_list->push_back(TAG_OS_PATCHLEVEL, ASN1_INTEGER_get(record->os_patchlevel)))
+ !auth_list->push_back(TAG_OS_PATCHLEVEL, ASN1_INTEGER_get(record->os_patchlevel))) {
return KM_ERROR_MEMORY_ALLOCATION_FAILED;
+ }
+
+ // attestation application Id
+ if (record->attestation_application_id &&
+ !auth_list->push_back(TAG_ATTESTATION_APPLICATION_ID,
+ record->attestation_application_id->data,
+ record->attestation_application_id->length)) {
+ return KM_ERROR_MEMORY_ALLOCATION_FAILED;
+ }
// Brand name
if (record->attestation_id_brand &&
!auth_list->push_back(TAG_ATTESTATION_ID_BRAND, record->attestation_id_brand->data,
- record->attestation_id_brand->length))
+ record->attestation_id_brand->length)) {
return KM_ERROR_MEMORY_ALLOCATION_FAILED;
+ }
// Device name
if (record->attestation_id_device &&
!auth_list->push_back(TAG_ATTESTATION_ID_DEVICE, record->attestation_id_device->data,
- record->attestation_id_device->length))
+ record->attestation_id_device->length)) {
return KM_ERROR_MEMORY_ALLOCATION_FAILED;
+ }
// Product name
if (record->attestation_id_product &&
!auth_list->push_back(TAG_ATTESTATION_ID_PRODUCT, record->attestation_id_product->data,
- record->attestation_id_product->length))
+ record->attestation_id_product->length)) {
return KM_ERROR_MEMORY_ALLOCATION_FAILED;
+ }
// Serial number
if (record->attestation_id_serial &&
!auth_list->push_back(TAG_ATTESTATION_ID_SERIAL, record->attestation_id_serial->data,
- record->attestation_id_serial->length))
+ record->attestation_id_serial->length)) {
return KM_ERROR_MEMORY_ALLOCATION_FAILED;
+ }
// IMEI
if (record->attestation_id_imei &&
!auth_list->push_back(TAG_ATTESTATION_ID_IMEI, record->attestation_id_imei->data,
- record->attestation_id_imei->length))
+ record->attestation_id_imei->length)) {
return KM_ERROR_MEMORY_ALLOCATION_FAILED;
+ }
// MEID
if (record->attestation_id_meid &&
!auth_list->push_back(TAG_ATTESTATION_ID_MEID, record->attestation_id_meid->data,
- record->attestation_id_meid->length))
+ record->attestation_id_meid->length)) {
return KM_ERROR_MEMORY_ALLOCATION_FAILED;
+ }
// Manufacturer name
if (record->attestation_id_manufacturer &&
!auth_list->push_back(TAG_ATTESTATION_ID_MANUFACTURER,
record->attestation_id_manufacturer->data,
- record->attestation_id_manufacturer->length))
+ record->attestation_id_manufacturer->length)) {
return KM_ERROR_MEMORY_ALLOCATION_FAILED;
+ }
// Model name
if (record->attestation_id_model &&
!auth_list->push_back(TAG_ATTESTATION_ID_MODEL, record->attestation_id_model->data,
- record->attestation_id_model->length))
+ record->attestation_id_model->length)) {
return KM_ERROR_MEMORY_ALLOCATION_FAILED;
+ }
- // Trusted confirmation required
- if (record->trusted_confirmation_required) {
- if (!auth_list->push_back(TAG_NO_AUTH_REQUIRED)) {
- return KM_ERROR_MEMORY_ALLOCATION_FAILED;
- }
+ // vendor patch level
+ if (record->vendor_patchlevel &&
+ !auth_list->push_back(TAG_VENDOR_PATCHLEVEL, ASN1_INTEGER_get(record->vendor_patchlevel))) {
+ return KM_ERROR_MEMORY_ALLOCATION_FAILED;
+ }
+
+ // boot patch level
+ if (record->boot_patch_level &&
+ !auth_list->push_back(TAG_BOOT_PATCHLEVEL, ASN1_INTEGER_get(record->boot_patch_level))) {
+ return KM_ERROR_MEMORY_ALLOCATION_FAILED;
+ }
+
+ // device unique attestation
+ if (record->device_unique_attestation && !auth_list->push_back(TAG_DEVICE_UNIQUE_ATTESTATION)) {
+ return KM_ERROR_MEMORY_ALLOCATION_FAILED;
+ }
+
+ // identity credential key
+ if (record->identity_credential_key && !auth_list->push_back(TAG_IDENTITY_CREDENTIAL_KEY)) {
+ return KM_ERROR_MEMORY_ALLOCATION_FAILED;
}
return KM_ERROR_OK;
@@ -730,8 +1407,7 @@
const uint8_t* p = asn1_key_desc;
UniquePtr<KM_KEY_DESCRIPTION, KM_KEY_DESCRIPTION_Delete> record(
d2i_KM_KEY_DESCRIPTION(nullptr, &p, asn1_key_desc_len));
- if (!record.get())
- return TranslateLastOpenSslError();
+ if (!record.get()) return TranslateLastOpenSslError();
*attestation_version = ASN1_INTEGER_get(record->attestation_version);
*attestation_security_level = static_cast<keymaster_security_level_t>(
@@ -748,8 +1424,7 @@
unique_id->data_length = record->unique_id->length;
keymaster_error_t error = extract_auth_list(record->software_enforced, software_enforced);
- if (error != KM_ERROR_OK)
- return error;
+ if (error != KM_ERROR_OK) return error;
return extract_auth_list(record->tee_enforced, tee_enforced);
}
@@ -783,4 +1458,408 @@
return KM_ERROR_OK;
}
+// Parse the EAT-encoded attestation record, placing the results in keymaster_version,
+// attestation_challenge, software_enforced, tee_enforced and unique_id.
+keymaster_error_t parse_eat_record(
+ const uint8_t* eat_key_desc, size_t eat_key_desc_len, uint32_t* attestation_version,
+ keymaster_security_level_t* attestation_security_level, uint32_t* keymaster_version,
+ keymaster_security_level_t* keymaster_security_level, keymaster_blob_t* attestation_challenge,
+ AuthorizationSet* software_enforced, AuthorizationSet* tee_enforced,
+ keymaster_blob_t* unique_id, keymaster_blob_t* verified_boot_key,
+ keymaster_verified_boot_t* verified_boot_state, bool* device_locked,
+ std::vector<int64_t>* unexpected_claims) {
+ auto [top_level_item, next_pos, error] = cppbor::parse(eat_key_desc, eat_key_desc_len);
+ ASSERT_OR_RETURN_ERROR(top_level_item, KM_ERROR_INVALID_TAG);
+ const cppbor::Map* eat_map = top_level_item->asMap();
+ ASSERT_OR_RETURN_ERROR(eat_map, KM_ERROR_INVALID_TAG);
+ bool verified_or_self_signed = false;
+
+ for (size_t i = 0; i < eat_map->size(); i++) {
+ auto& [key_item, value_item] = (*eat_map)[i];
+ const cppbor::Int* key = key_item->asInt();
+ ASSERT_OR_RETURN_ERROR(key, (KM_ERROR_INVALID_TAG));
+
+ // The following values will either hold the typed value, or be null (if not the right
+ // type).
+ const cppbor::Int* int_value = value_item->asInt();
+ const cppbor::Bstr* bstr_value = value_item->asBstr();
+ const cppbor::Simple* simple_value = value_item->asSimple();
+ const cppbor::Array* array_value = value_item->asArray();
+ const cppbor::Map* map_value = value_item->asMap();
+
+ keymaster_error_t error;
+ switch ((EatClaim)key->value()) {
+ default:
+ unexpected_claims->push_back(key->value());
+ break;
+ case EatClaim::ATTESTATION_VERSION:
+ ASSERT_OR_RETURN_ERROR(int_value, KM_ERROR_INVALID_TAG);
+ *attestation_version = int_value->value();
+ break;
+ case EatClaim::SECURITY_LEVEL:
+ ASSERT_OR_RETURN_ERROR(int_value, KM_ERROR_INVALID_TAG);
+ switch ((EatSecurityLevel)int_value->value()) {
+ // TODO: Is my assumption correct that the security level of the attestation data should
+ // always be equal to the security level of keymint, as the attestation data always
+ // lives in the top-level module?
+ case EatSecurityLevel::UNRESTRICTED:
+ *keymaster_security_level = *attestation_security_level =
+ KM_SECURITY_LEVEL_SOFTWARE;
+ break;
+ case EatSecurityLevel::SECURE_RESTRICTED:
+ *keymaster_security_level = *attestation_security_level =
+ KM_SECURITY_LEVEL_TRUSTED_ENVIRONMENT;
+ break;
+ case EatSecurityLevel::HARDWARE:
+ *keymaster_security_level = *attestation_security_level =
+ KM_SECURITY_LEVEL_STRONGBOX;
+ break;
+ default:
+ return KM_ERROR_INVALID_TAG;
+ }
+ break;
+ case EatClaim::KEYMASTER_VERSION:
+ ASSERT_OR_RETURN_ERROR(int_value, KM_ERROR_INVALID_TAG);
+ *keymaster_version = int_value->value();
+ break;
+ case EatClaim::SUBMODS:
+ ASSERT_OR_RETURN_ERROR(map_value, KM_ERROR_INVALID_TAG);
+ for (size_t j = 0; j < map_value->size(); j++) {
+ auto& [submod_key, submod_value] = (*map_value)[j];
+ const cppbor::Map* submod_map = submod_value->asMap();
+ ASSERT_OR_RETURN_ERROR(submod_map, KM_ERROR_INVALID_TAG);
+ error = parse_eat_submod(submod_map, software_enforced, tee_enforced);
+ if (error != KM_ERROR_OK) return error;
+ }
+ break;
+ case EatClaim::CTI:
+ error = bstr_to_blob(bstr_value, unique_id);
+ if (error != KM_ERROR_OK) return error;
+ break;
+ case EatClaim::NONCE:
+ error = bstr_to_blob(bstr_value, attestation_challenge);
+ if (error != KM_ERROR_OK) return error;
+ break;
+ case EatClaim::VERIFIED_BOOT_KEY:
+ error = bstr_to_blob(bstr_value, verified_boot_key);
+ if (error != KM_ERROR_OK) return error;
+ break;
+ case EatClaim::VERIFIED_BOOT_HASH:
+ // Not parsing this for now.
+ break;
+ case EatClaim::DEVICE_UNIQUE_ATTESTATION:
+ if (value_item->asSimple() == nullptr || !value_item->asSimple()->asBool()->value()) {
+ return KM_ERROR_INVALID_TAG;
+ }
+ // Not parsing this for now.
+ break;
+ case EatClaim::DEVICE_LOCKED:
+ ASSERT_OR_RETURN_ERROR(simple_value->asBool(), KM_ERROR_INVALID_TAG);
+ *device_locked = simple_value->asBool()->value();
+ break;
+ case EatClaim::BOOT_STATE:
+ ASSERT_OR_RETURN_ERROR(array_value, KM_ERROR_INVALID_TAG);
+ ASSERT_OR_RETURN_ERROR(array_value->size() == 5, KM_ERROR_INVALID_TAG);
+ ASSERT_OR_RETURN_ERROR((*array_value)[4]->asSimple()->asBool()->value() == false,
+ KM_ERROR_INVALID_TAG);
+ verified_or_self_signed = (*array_value)[0]->asSimple()->asBool()->value();
+ ASSERT_OR_RETURN_ERROR(verified_or_self_signed ==
+ (*array_value)[1]->asSimple()->asBool()->value(),
+ KM_ERROR_INVALID_TAG);
+ ASSERT_OR_RETURN_ERROR(verified_or_self_signed ==
+ (*array_value)[2]->asSimple()->asBool()->value(),
+ KM_ERROR_INVALID_TAG);
+ ASSERT_OR_RETURN_ERROR(verified_or_self_signed ==
+ (*array_value)[3]->asSimple()->asBool()->value(),
+ KM_ERROR_INVALID_TAG);
+ break;
+ case EatClaim::OFFICIAL_BUILD:
+ *verified_boot_state = KM_VERIFIED_BOOT_VERIFIED;
+ break;
+ }
+ }
+
+ if (*verified_boot_state == KM_VERIFIED_BOOT_VERIFIED) {
+ (void)(verified_boot_state);
+ // TODO: re-enable this
+ // ASSERT_OR_RETURN_ERROR(verified_or_self_signed, KM_ERROR_INVALID_TAG);
+ } else {
+ *verified_boot_state =
+ verified_or_self_signed ? KM_VERIFIED_BOOT_SELF_SIGNED : KM_VERIFIED_BOOT_UNVERIFIED;
+ }
+
+ return KM_ERROR_OK;
+}
+
+keymaster_error_t parse_submod_values(AuthorizationSetBuilder* set_builder,
+ int* auth_set_security_level, const cppbor::Map* submod_map) {
+ ASSERT_OR_RETURN_ERROR(set_builder, KM_ERROR_UNEXPECTED_NULL_POINTER);
+ for (size_t i = 0; i < submod_map->size(); i++) {
+ auto& [key_item, value_item] = (*submod_map)[i];
+ const cppbor::Int* key_int = key_item->asInt();
+ ASSERT_OR_RETURN_ERROR(key_int, KM_ERROR_INVALID_TAG);
+ int key = key_int->value();
+ keymaster_error_t error;
+ keymaster_blob_t blob;
+
+ switch ((EatClaim)key) {
+ default:
+ return KM_ERROR_INVALID_TAG;
+ case EatClaim::ALGORITHM:
+ ASSERT_OR_RETURN_ERROR(value_item->asInt(), KM_ERROR_INVALID_TAG);
+ set_builder->Authorization(
+ TAG_ALGORITHM, static_cast<keymaster_algorithm_t>(value_item->asInt()->value()));
+ break;
+ case EatClaim::EC_CURVE:
+ ASSERT_OR_RETURN_ERROR(value_item->asInt(), KM_ERROR_INVALID_TAG);
+ set_builder->Authorization(
+ TAG_EC_CURVE, static_cast<keymaster_ec_curve_t>(value_item->asInt()->value()));
+ break;
+ case EatClaim::USER_AUTH_TYPE:
+ ASSERT_OR_RETURN_ERROR(value_item->asInt(), KM_ERROR_INVALID_TAG);
+ set_builder->Authorization(TAG_USER_AUTH_TYPE, static_cast<hw_authenticator_type_t>(
+ value_item->asInt()->value()));
+ break;
+ case EatClaim::ORIGIN:
+ ASSERT_OR_RETURN_ERROR(value_item->asInt(), KM_ERROR_INVALID_TAG);
+ set_builder->Authorization(
+ TAG_ORIGIN, static_cast<keymaster_key_origin_t>(value_item->asInt()->value()));
+ break;
+ case EatClaim::PURPOSE:
+ for (size_t j = 0; j < value_item->asArray()->size(); j++) {
+ set_builder->Authorization(TAG_PURPOSE,
+ static_cast<keymaster_purpose_t>(
+ (*value_item->asArray())[j]->asInt()->value()));
+ }
+ break;
+ case EatClaim::PADDING:
+ for (size_t j = 0; j < value_item->asArray()->size(); j++) {
+ set_builder->Authorization(TAG_PADDING,
+ static_cast<keymaster_padding_t>(
+ (*value_item->asArray())[j]->asInt()->value()));
+ }
+ break;
+ case EatClaim::DIGEST:
+ for (size_t j = 0; j < value_item->asArray()->size(); j++) {
+ set_builder->Authorization(
+ TAG_DIGEST,
+ static_cast<keymaster_digest_t>((*value_item->asArray())[j]->asInt()->value()));
+ }
+ break;
+ case EatClaim::BLOCK_MODE:
+ for (size_t j = 0; j < value_item->asArray()->size(); j++) {
+ set_builder->Authorization(TAG_BLOCK_MODE,
+ static_cast<keymaster_block_mode_t>(
+ (*value_item->asArray())[j]->asInt()->value()));
+ }
+ break;
+ case EatClaim::KEY_SIZE:
+ ASSERT_OR_RETURN_ERROR(value_item->asInt(), KM_ERROR_INVALID_TAG);
+ set_builder->Authorization(TAG_KEY_SIZE, value_item->asInt()->value());
+ break;
+ case EatClaim::AUTH_TIMEOUT:
+ ASSERT_OR_RETURN_ERROR(value_item->asInt(), KM_ERROR_INVALID_TAG);
+ set_builder->Authorization(TAG_AUTH_TIMEOUT, value_item->asInt()->value());
+ break;
+ case EatClaim::OS_VERSION:
+ ASSERT_OR_RETURN_ERROR(value_item->asInt(), KM_ERROR_INVALID_TAG);
+ set_builder->Authorization(TAG_OS_VERSION, value_item->asInt()->value());
+ break;
+ case EatClaim::OS_PATCHLEVEL:
+ ASSERT_OR_RETURN_ERROR(value_item->asInt(), KM_ERROR_INVALID_TAG);
+ set_builder->Authorization(TAG_OS_PATCHLEVEL, value_item->asInt()->value());
+ break;
+ case EatClaim::MIN_MAC_LENGTH:
+ ASSERT_OR_RETURN_ERROR(value_item->asInt(), KM_ERROR_INVALID_TAG);
+ set_builder->Authorization(TAG_MIN_MAC_LENGTH, value_item->asInt()->value());
+ break;
+ case EatClaim::BOOT_PATCHLEVEL:
+ ASSERT_OR_RETURN_ERROR(value_item->asInt(), KM_ERROR_INVALID_TAG);
+ set_builder->Authorization(TAG_BOOT_PATCHLEVEL, value_item->asInt()->value());
+ break;
+ case EatClaim::VENDOR_PATCHLEVEL:
+ ASSERT_OR_RETURN_ERROR(value_item->asInt(), KM_ERROR_INVALID_TAG);
+ set_builder->Authorization(TAG_VENDOR_PATCHLEVEL, value_item->asInt()->value());
+ break;
+ case EatClaim::RSA_PUBLIC_EXPONENT:
+ ASSERT_OR_RETURN_ERROR(value_item->asInt(), KM_ERROR_INVALID_TAG);
+ set_builder->Authorization(TAG_RSA_PUBLIC_EXPONENT, value_item->asInt()->value());
+ break;
+ case EatClaim::ACTIVE_DATETIME:
+ ASSERT_OR_RETURN_ERROR(value_item->asInt(), KM_ERROR_INVALID_TAG);
+ set_builder->Authorization(TAG_ACTIVE_DATETIME, value_item->asInt()->value());
+ break;
+ case EatClaim::ORIGINATION_EXPIRE_DATETIME:
+ ASSERT_OR_RETURN_ERROR(value_item->asInt(), KM_ERROR_INVALID_TAG);
+ set_builder->Authorization(TAG_ORIGINATION_EXPIRE_DATETIME,
+ value_item->asInt()->value());
+ break;
+ case EatClaim::USAGE_EXPIRE_DATETIME:
+ ASSERT_OR_RETURN_ERROR(value_item->asInt(), KM_ERROR_INVALID_TAG);
+ set_builder->Authorization(TAG_USAGE_EXPIRE_DATETIME, value_item->asInt()->value());
+ break;
+ case EatClaim::IAT:
+ ASSERT_OR_RETURN_ERROR(value_item->asInt(), KM_ERROR_INVALID_TAG);
+ set_builder->Authorization(TAG_CREATION_DATETIME, value_item->asInt()->value());
+ break;
+ case EatClaim::NO_AUTH_REQUIRED:
+ if (value_item->asSimple() == nullptr || !value_item->asSimple()->asBool()->value()) {
+ return KM_ERROR_INVALID_TAG;
+ }
+ set_builder->Authorization(TAG_NO_AUTH_REQUIRED);
+ break;
+ case EatClaim::ALL_APPLICATIONS:
+ if (value_item->asSimple() == nullptr || !value_item->asSimple()->asBool()->value()) {
+ return KM_ERROR_INVALID_TAG;
+ }
+ set_builder->Authorization(TAG_ALL_APPLICATIONS);
+ break;
+ case EatClaim::ROLLBACK_RESISTANT:
+ if (value_item->asSimple() == nullptr || !value_item->asSimple()->asBool()->value()) {
+ return KM_ERROR_INVALID_TAG;
+ }
+ set_builder->Authorization(TAG_ROLLBACK_RESISTANT);
+ break;
+ case EatClaim::ALLOW_WHILE_ON_BODY:
+ if (value_item->asSimple() == nullptr || !value_item->asSimple()->asBool()->value()) {
+ return KM_ERROR_INVALID_TAG;
+ }
+ set_builder->Authorization(TAG_ALLOW_WHILE_ON_BODY);
+ break;
+ case EatClaim::UNLOCKED_DEVICE_REQUIRED:
+ if (value_item->asSimple() == nullptr || !value_item->asSimple()->asBool()->value()) {
+ return KM_ERROR_INVALID_TAG;
+ }
+ set_builder->Authorization(TAG_UNLOCKED_DEVICE_REQUIRED);
+ break;
+ case EatClaim::CALLER_NONCE:
+ if (value_item->asSimple() == nullptr || !value_item->asSimple()->asBool()->value()) {
+ return KM_ERROR_INVALID_TAG;
+ }
+ set_builder->Authorization(TAG_CALLER_NONCE);
+ break;
+ case EatClaim::TRUSTED_CONFIRMATION_REQUIRED:
+ if (value_item->asSimple() == nullptr || !value_item->asSimple()->asBool()->value()) {
+ return KM_ERROR_INVALID_TAG;
+ }
+ set_builder->Authorization(TAG_TRUSTED_CONFIRMATION_REQUIRED);
+ break;
+ case EatClaim::EARLY_BOOT_ONLY:
+ if (value_item->asSimple() == nullptr || !value_item->asSimple()->asBool()->value()) {
+ return KM_ERROR_INVALID_TAG;
+ }
+ set_builder->Authorization(TAG_EARLY_BOOT_ONLY);
+ break;
+ case EatClaim::IDENTITY_CREDENTIAL_KEY:
+ if (value_item->asSimple() == nullptr || !value_item->asSimple()->asBool()->value()) {
+ return KM_ERROR_INVALID_TAG;
+ }
+ set_builder->Authorization(TAG_IDENTITY_CREDENTIAL_KEY);
+ break;
+ case EatClaim::STORAGE_KEY:
+ if (value_item->asSimple() == nullptr || !value_item->asSimple()->asBool()->value()) {
+ return KM_ERROR_INVALID_TAG;
+ }
+ set_builder->Authorization(TAG_STORAGE_KEY);
+ break;
+ case EatClaim::TRUSTED_USER_PRESENCE_REQUIRED:
+ if (value_item->asSimple() == nullptr || !value_item->asSimple()->asBool()->value()) {
+ return KM_ERROR_INVALID_TAG;
+ }
+ set_builder->Authorization(TAG_TRUSTED_USER_PRESENCE_REQUIRED);
+ break;
+ case EatClaim::DEVICE_UNIQUE_ATTESTATION:
+ if (value_item->asSimple() == nullptr || !value_item->asSimple()->asBool()->value()) {
+ return KM_ERROR_INVALID_TAG;
+ }
+ set_builder->Authorization(TAG_DEVICE_UNIQUE_ATTESTATION);
+ break;
+ case EatClaim::APPLICATION_ID:
+ error = bstr_to_blob(value_item->asBstr(), &blob);
+ if (error != KM_ERROR_OK) return error;
+ set_builder->Authorization(TAG_APPLICATION_ID, blob);
+ break;
+ case EatClaim::ATTESTATION_APPLICATION_ID:
+ error = bstr_to_blob(value_item->asBstr(), &blob);
+ if (error != KM_ERROR_OK) return error;
+ set_builder->Authorization(TAG_ATTESTATION_APPLICATION_ID, blob);
+ break;
+ case EatClaim::ATTESTATION_ID_BRAND:
+ error = bstr_to_blob(value_item->asBstr(), &blob);
+ if (error != KM_ERROR_OK) return error;
+ set_builder->Authorization(TAG_ATTESTATION_ID_BRAND, blob);
+ break;
+ case EatClaim::ATTESTATION_ID_DEVICE:
+ error = bstr_to_blob(value_item->asBstr(), &blob);
+ if (error != KM_ERROR_OK) return error;
+ set_builder->Authorization(TAG_ATTESTATION_ID_DEVICE, blob);
+ break;
+ case EatClaim::ATTESTATION_ID_PRODUCT:
+ error = bstr_to_blob(value_item->asBstr(), &blob);
+ if (error != KM_ERROR_OK) return error;
+ set_builder->Authorization(TAG_ATTESTATION_ID_PRODUCT, blob);
+ break;
+ case EatClaim::ATTESTATION_ID_SERIAL:
+ error = bstr_to_blob(value_item->asBstr(), &blob);
+ if (error != KM_ERROR_OK) return error;
+ set_builder->Authorization(TAG_ATTESTATION_ID_SERIAL, blob);
+ break;
+ case EatClaim::UEID:
+ error = ueid_to_imei_blob(value_item->asBstr(), &blob);
+ if (error != KM_ERROR_OK) return error;
+ set_builder->Authorization(TAG_ATTESTATION_ID_IMEI, blob);
+ break;
+ case EatClaim::ATTESTATION_ID_MEID:
+ error = bstr_to_blob(value_item->asBstr(), &blob);
+ if (error != KM_ERROR_OK) return error;
+ set_builder->Authorization(TAG_ATTESTATION_ID_MEID, blob);
+ break;
+ case EatClaim::ATTESTATION_ID_MANUFACTURER:
+ error = bstr_to_blob(value_item->asBstr(), &blob);
+ if (error != KM_ERROR_OK) return error;
+ set_builder->Authorization(TAG_ATTESTATION_ID_MANUFACTURER, blob);
+ break;
+ case EatClaim::ATTESTATION_ID_MODEL:
+ error = bstr_to_blob(value_item->asBstr(), &blob);
+ if (error != KM_ERROR_OK) return error;
+ set_builder->Authorization(TAG_ATTESTATION_ID_MODEL, blob);
+ break;
+ case EatClaim::CONFIRMATION_TOKEN:
+ error = bstr_to_blob(value_item->asBstr(), &blob);
+ if (error != KM_ERROR_OK) return error;
+ set_builder->Authorization(TAG_CONFIRMATION_TOKEN, blob);
+ break;
+ case EatClaim::SECURITY_LEVEL:
+ ASSERT_OR_RETURN_ERROR(value_item->asInt(), KM_ERROR_INVALID_TAG);
+ *auth_set_security_level = value_item->asInt()->value();
+ }
+ }
+
+ return KM_ERROR_OK;
+}
+
+keymaster_error_t parse_eat_submod(const cppbor::Map* submod_values,
+ AuthorizationSet* software_enforced,
+ AuthorizationSet* tee_enforced) {
+ AuthorizationSetBuilder auth_set_builder;
+ int auth_set_security_level = 0;
+ keymaster_error_t error =
+ parse_submod_values(&auth_set_builder, &auth_set_security_level, submod_values);
+ if (error) return error;
+ switch ((EatSecurityLevel)auth_set_security_level) {
+ case EatSecurityLevel::HARDWARE:
+ // Hardware attestation should never occur in a submod of another EAT.
+ [[fallthrough]];
+ default:
+ return KM_ERROR_INVALID_TAG;
+ case EatSecurityLevel::UNRESTRICTED:
+ *software_enforced = AuthorizationSet(auth_set_builder);
+ break;
+ case EatSecurityLevel::SECURE_RESTRICTED:
+ *tee_enforced = AuthorizationSet(auth_set_builder);
+ break;
+ }
+
+ return KM_ERROR_OK;
+}
} // namespace keymaster
diff --git a/km_openssl/attestation_utils.cpp b/km_openssl/attestation_utils.cpp
index e6754a2..9a6c7f3 100644
--- a/km_openssl/attestation_utils.cpp
+++ b/km_openssl/attestation_utils.cpp
@@ -15,408 +15,318 @@
** limitations under the License.
*/
-#include <keymaster/km_openssl/attestation_utils.h>
+#include <openssl/evp.h>
+#include <openssl/x509v3.h>
#include <hardware/keymaster_defs.h>
#include <keymaster/authorization_set.h>
-#include <keymaster/attestation_record.h>
#include <keymaster/km_openssl/asymmetric_key.h>
-#include <keymaster/km_openssl/openssl_utils.h>
+#include <keymaster/km_openssl/attestation_record.h>
+#include <keymaster/km_openssl/attestation_utils.h>
+#include <keymaster/km_openssl/certificate_utils.h>
#include <keymaster/km_openssl/openssl_err.h>
-
-#include <openssl/x509v3.h>
-#include <openssl/evp.h>
-
+#include <keymaster/km_openssl/openssl_utils.h>
namespace keymaster {
namespace {
-constexpr int kDigitalSignatureKeyUsageBit = 0;
-constexpr int kKeyEnciphermentKeyUsageBit = 2;
-constexpr int kDataEnciphermentKeyUsageBit = 3;
-constexpr int kMaxKeyUsageBit = 8;
+CertificateChain make_cert_chain(X509* certificate, CertificateChain chain,
+ keymaster_error_t* error) {
+ keymaster_blob_t blob{};
+ *error = encode_certificate(certificate, &blob);
+ if (*error != KM_ERROR_OK) return {};
-template <typename T> T && min(T && a, T && b) {
- return (a < b) ? forward<T>(a) : forward<T>(b);
-}
-
-struct emptyCert {};
-
-__attribute__((__unused__))
-inline keymaster_blob_t certBlobifier(const emptyCert&, bool*){ return {}; }
-template <size_t N>
-inline keymaster_blob_t certBlobifier(const uint8_t (&cert)[N], bool* fail){
- keymaster_blob_t result = { dup_array(cert), N };
- if (!result.data) {
- *fail = true;
+ if (!chain.push_front(blob)) {
+ *error = KM_ERROR_MEMORY_ALLOCATION_FAILED;
return {};
}
- return result;
+ return chain;
}
-inline keymaster_blob_t certBlobifier(const keymaster_blob_t& blob, bool* fail){
- if (blob.data == nullptr || blob.data_length == 0) return {};
- keymaster_blob_t result = { dup_array(blob.data, blob.data_length), blob.data_length };
- if (!result.data) {
- *fail = true;
- return {};
- }
- return result;
-}
-inline keymaster_blob_t certBlobifier(keymaster_blob_t&& blob, bool*){
- if (blob.data == nullptr || blob.data_length == 0) return {};
- keymaster_blob_t result = blob;
- blob = {};
- return result;
-}
-inline keymaster_blob_t certBlobifier(X509* certificate, bool* fail){
- int len = i2d_X509(certificate, nullptr);
- if (len < 0) {
- *fail = true;
- return {};
- }
-
- uint8_t* data = new(std::nothrow) uint8_t[len];
- if (!data) {
- *fail = true;
- return {};
- }
- uint8_t* p = data;
-
- i2d_X509(certificate, &p);
-
- return { data, (size_t)len };
-}
-
-inline bool certCopier(keymaster_blob_t** out, const keymaster_cert_chain_t& chain,
- bool* fail) {
- for (size_t i = 0; i < chain.entry_count; ++i) {
- *(*out)++ = certBlobifier(chain.entries[i], fail);
- }
- return *fail;
-}
-
-__attribute__((__unused__))
-inline bool certCopier(keymaster_blob_t** out, keymaster_cert_chain_t&& chain, bool* fail) {
- for (size_t i = 0; i < chain.entry_count; ++i) {
- *(*out)++ = certBlobifier(move(chain.entries[i]), fail);
- }
- delete[] chain.entries;
- chain.entries = nullptr;
- chain.entry_count = 0;
- return *fail;
-}
-template <typename CERT>
-inline bool certCopier(keymaster_blob_t** out, CERT&& cert, bool* fail) {
- *(*out)++ = certBlobifier(forward<CERT>(cert), fail);
- return *fail;
-}
-
-inline bool certCopyHelper(keymaster_blob_t**, bool* fail) {
- return *fail;
-}
-
-template <typename CERT, typename... CERTS>
-inline bool certCopyHelper(keymaster_blob_t** out, bool* fail, CERT&& cert, CERTS&&... certs) {
- certCopier(out, forward<CERT>(cert), fail);
- return certCopyHelper(out, fail, forward<CERTS>(certs)...);
-}
-
-
-
-template <typename T>
-inline size_t noOfCert(T &&) { return 1; }
-inline size_t noOfCert(const keymaster_cert_chain_t& cert_chain) { return cert_chain.entry_count; }
-
-inline size_t certCount() { return 0; }
-template <typename CERT, typename... CERTS>
-inline size_t certCount(CERT&& cert, CERTS&&... certs) {
- return noOfCert(forward<CERT>(cert)) + certCount(forward<CERTS>(certs)...);
-}
-
-/*
- * makeCertChain creates a new keymaster_cert_chain_t from all the certs that get thrown at it
- * in the given order. A cert may be a X509*, uint8_t[], a keymaster_blob_t, an instance of
- * emptyCert, or another keymater_cert_chain_t in which case the certs of the chain are included
- * in the new chain. emptyCert is a placeholder which results in an empty slot at the given
- * position in the newly created certificate chain. E.g., makeCertChain(emptyCert(), someCertChain)
- * allocates enough slots to accommodate all certificates of someCertChain plus one empty slot and
- * copies in someCertChain starting at index 1 so that the slot with index 0 can be used for a new
- * leaf entry.
- *
- * makeCertChain respects move semantics. E.g., makeCertChain(emptyCert(), std::move(someCertChain))
- * will take possession of secondary resources for the certificate blobs so that someCertChain is
- * empty after the call. Also, because no allocation happens this cannot fail. Note, however, that
- * if another cert is passed to makeCertChain, that needs to be copied and thus requires
- * allocation, and this allocation fails, all resources - allocated or moved - will be reaped.
- */
-template <typename... CERTS>
-CertChainPtr makeCertChain(CERTS&&... certs) {
- CertChainPtr result(new (std::nothrow) keymaster_cert_chain_t);
- if (!result.get()) return {};
- result->entries = new (std::nothrow) keymaster_blob_t[certCount(forward<CERTS>(certs)...)];
- if (!result->entries) return {};
- result->entry_count = certCount(forward<CERTS>(certs)...);
- bool allocation_failed = false;
- keymaster_blob_t* entries = result->entries;
- certCopyHelper(&entries, &allocation_failed, forward<CERTS>(certs)...);
- if (allocation_failed) return {};
- return result;
-}
-
keymaster_error_t build_attestation_extension(const AuthorizationSet& attest_params,
- const AuthorizationSet& tee_enforced,
- const AuthorizationSet& sw_enforced,
- const AttestationRecordContext& context,
- X509_EXTENSION_Ptr* extension) {
+ const AuthorizationSet& tee_enforced,
+ const AuthorizationSet& sw_enforced,
+ const AttestationContext& context,
+ X509_EXTENSION_Ptr* extension) {
ASN1_OBJECT_Ptr oid(
- OBJ_txt2obj(kAttestionRecordOid, 1 /* accept numerical dotted string form only */));
- if (!oid.get())
- return TranslateLastOpenSslError();
+ OBJ_txt2obj(kAsn1TokenOid, 1 /* accept numerical dotted string form only */));
+ if (!oid.get()) return TranslateLastOpenSslError();
UniquePtr<uint8_t[]> attest_bytes;
size_t attest_bytes_len;
keymaster_error_t error = build_attestation_record(attest_params, sw_enforced, tee_enforced,
context, &attest_bytes, &attest_bytes_len);
- if (error != KM_ERROR_OK)
- return error;
+ if (error != KM_ERROR_OK) return error;
ASN1_OCTET_STRING_Ptr attest_str(ASN1_OCTET_STRING_new());
if (!attest_str.get() ||
- !ASN1_OCTET_STRING_set(attest_str.get(), attest_bytes.get(), attest_bytes_len))
+ !ASN1_OCTET_STRING_set(attest_str.get(), attest_bytes.get(), attest_bytes_len)) {
return TranslateLastOpenSslError();
+ }
extension->reset(
X509_EXTENSION_create_by_OBJ(nullptr, oid.get(), 0 /* not critical */, attest_str.get()));
- if (!extension->get())
- return TranslateLastOpenSslError();
-
- return KM_ERROR_OK;
-}
-
-keymaster_error_t add_key_usage_extension(const AuthorizationSet& tee_enforced,
- const AuthorizationSet& sw_enforced,
- X509* certificate) {
- // Build BIT_STRING with correct contents.
- ASN1_BIT_STRING_Ptr key_usage(ASN1_BIT_STRING_new());
- if (!key_usage) return KM_ERROR_MEMORY_ALLOCATION_FAILED;
-
- for (size_t i = 0; i <= kMaxKeyUsageBit; ++i) {
- if (!ASN1_BIT_STRING_set_bit(key_usage.get(), i, 0)) {
- return TranslateLastOpenSslError();
- }
- }
-
- if (tee_enforced.Contains(TAG_PURPOSE, KM_PURPOSE_SIGN) ||
- tee_enforced.Contains(TAG_PURPOSE, KM_PURPOSE_VERIFY) ||
- sw_enforced.Contains(TAG_PURPOSE, KM_PURPOSE_SIGN) ||
- sw_enforced.Contains(TAG_PURPOSE, KM_PURPOSE_VERIFY)) {
- if (!ASN1_BIT_STRING_set_bit(key_usage.get(), kDigitalSignatureKeyUsageBit, 1)) {
- return TranslateLastOpenSslError();
- }
- }
-
- if (tee_enforced.Contains(TAG_PURPOSE, KM_PURPOSE_ENCRYPT) ||
- tee_enforced.Contains(TAG_PURPOSE, KM_PURPOSE_DECRYPT) ||
- sw_enforced.Contains(TAG_PURPOSE, KM_PURPOSE_ENCRYPT) ||
- sw_enforced.Contains(TAG_PURPOSE, KM_PURPOSE_DECRYPT)) {
- if (!ASN1_BIT_STRING_set_bit(key_usage.get(), kKeyEnciphermentKeyUsageBit, 1) ||
- !ASN1_BIT_STRING_set_bit(key_usage.get(), kDataEnciphermentKeyUsageBit, 1)) {
- return TranslateLastOpenSslError();
- }
- }
-
- // Convert to octets
- int len = i2d_ASN1_BIT_STRING(key_usage.get(), nullptr);
- if (len < 0) {
- return TranslateLastOpenSslError();
- }
- UniquePtr<uint8_t[]> asn1_key_usage(new(std::nothrow) uint8_t[len]);
- if (!asn1_key_usage.get()) {
- return KM_ERROR_MEMORY_ALLOCATION_FAILED;
- }
- uint8_t* p = asn1_key_usage.get();
- len = i2d_ASN1_BIT_STRING(key_usage.get(), &p);
- if (len < 0) {
- return TranslateLastOpenSslError();
- }
-
- // Build OCTET_STRING
- ASN1_OCTET_STRING_Ptr key_usage_str(ASN1_OCTET_STRING_new());
- if (!key_usage_str.get() ||
- !ASN1_OCTET_STRING_set(key_usage_str.get(), asn1_key_usage.get(), len)) {
- return TranslateLastOpenSslError();
- }
-
- X509_EXTENSION_Ptr key_usage_extension(X509_EXTENSION_create_by_NID(nullptr, //
- NID_key_usage, //
- false /* critical */,
- key_usage_str.get()));
- if (!key_usage_extension.get()) {
- return TranslateLastOpenSslError();
- }
-
- if (!X509_add_ext(certificate, key_usage_extension.get() /* Don't release; copied */,
- -1 /* insert at end */)) {
+ if (!extension->get()) {
return TranslateLastOpenSslError();
}
return KM_ERROR_OK;
}
-bool add_public_key(EVP_PKEY* key, X509* certificate, keymaster_error_t* error) {
- if (!X509_set_pubkey(certificate, key)) {
- *error = TranslateLastOpenSslError();
- return false;
- }
- return true;
-}
-
-bool add_attestation_extension(const AuthorizationSet& attest_params,
+keymaster_error_t build_eat_extension(const AuthorizationSet& attest_params,
const AuthorizationSet& tee_enforced,
const AuthorizationSet& sw_enforced,
- const AttestationRecordContext& context,
- X509* certificate,
- keymaster_error_t* error) {
+ const AttestationContext& context, //
+ X509_EXTENSION_Ptr* extension) {
+ ASN1_OBJECT_Ptr oid(
+ OBJ_txt2obj(kEatTokenOid, 1 /* accept numerical dotted string form only */));
+ if (!oid.get()) {
+ return TranslateLastOpenSslError();
+ }
+
+ std::vector<uint8_t> eat_bytes;
+ keymaster_error_t error =
+ build_eat_record(attest_params, sw_enforced, tee_enforced, context, &eat_bytes);
+ if (error != KM_ERROR_OK) return error;
+
+ ASN1_OCTET_STRING_Ptr eat_str(ASN1_OCTET_STRING_new());
+ if (!eat_str.get() ||
+ !ASN1_OCTET_STRING_set(eat_str.get(), eat_bytes.data(), eat_bytes.size())) {
+ return TranslateLastOpenSslError();
+ }
+
+ extension->reset(
+ X509_EXTENSION_create_by_OBJ(nullptr, oid.get(), 0 /* not critical */, eat_str.get()));
+ if (!extension->get()) {
+ return TranslateLastOpenSslError();
+ }
+
+ return KM_ERROR_OK;
+}
+
+keymaster_error_t add_attestation_extension(const AuthorizationSet& attest_params,
+ const AuthorizationSet& tee_enforced,
+ const AuthorizationSet& sw_enforced,
+ const AttestationContext& context, //
+ X509* certificate) {
X509_EXTENSION_Ptr attest_extension;
- *error = build_attestation_extension(attest_params, tee_enforced, sw_enforced, context,
- &attest_extension);
- if (*error != KM_ERROR_OK)
- return false;
+ if (context.GetKmVersion() <= KmVersion::KEYMINT_1) {
+ if (auto error = build_attestation_extension(attest_params, tee_enforced, sw_enforced,
+ context, &attest_extension)) {
+ return error;
+ }
+ } else {
+ if (auto error = build_eat_extension(attest_params, tee_enforced, sw_enforced, context,
+ &attest_extension)) {
+ return error;
+ }
+ }
if (!X509_add_ext(certificate, attest_extension.get() /* Don't release; copied */,
-1 /* insert at end */)) {
- *error = TranslateLastOpenSslError();
- return false;
- }
-
- return true;
-}
-
-} // anonymous namespace
-
-keymaster_error_t generate_attestation(const AsymmetricKey& key,
- const AuthorizationSet& attest_params, const keymaster_cert_chain_t& attestation_chain,
- const keymaster_key_blob_t& attestation_signing_key,
- const AttestationRecordContext& context, CertChainPtr* cert_chain_out) {
-
- if (!cert_chain_out)
- return KM_ERROR_UNEXPECTED_NULL_POINTER;
-
- keymaster_algorithm_t sign_algorithm;
- if ((!key.sw_enforced().GetTagValue(TAG_ALGORITHM, &sign_algorithm) &&
- !key.hw_enforced().GetTagValue(TAG_ALGORITHM, &sign_algorithm)))
- return KM_ERROR_UNKNOWN_ERROR;
-
- EVP_PKEY_Ptr pkey(EVP_PKEY_new());
- if (!key.InternalToEvp(pkey.get()))
- return TranslateLastOpenSslError();
-
- X509_Ptr certificate(X509_new());
- if (!certificate.get())
- return TranslateLastOpenSslError();
-
- if (!X509_set_version(certificate.get(), 2 /* version 3, but zero-based */))
- return TranslateLastOpenSslError();
-
- ASN1_INTEGER_Ptr serialNumber(ASN1_INTEGER_new());
- if (!serialNumber.get() || !ASN1_INTEGER_set(serialNumber.get(), 1) ||
- !X509_set_serialNumber(certificate.get(), serialNumber.get() /* Don't release; copied */))
- return TranslateLastOpenSslError();
-
- X509_NAME_Ptr subjectName(X509_NAME_new());
- if (!subjectName.get() ||
- !X509_NAME_add_entry_by_txt(subjectName.get(), "CN", MBSTRING_ASC,
- reinterpret_cast<const uint8_t*>("Android Keystore Key"),
- -1 /* len */, -1 /* loc */, 0 /* set */) ||
- !X509_set_subject_name(certificate.get(), subjectName.get() /* Don't release; copied */))
- return TranslateLastOpenSslError();
-
- ASN1_TIME_Ptr notBefore(ASN1_TIME_new());
- uint64_t activeDateTime = 0;
- key.authorizations().GetTagValue(TAG_ACTIVE_DATETIME, &activeDateTime);
- if (!notBefore.get() || !ASN1_TIME_set(notBefore.get(), activeDateTime / 1000) ||
- !X509_set_notBefore(certificate.get(), notBefore.get() /* Don't release; copied */))
- return TranslateLastOpenSslError();
-
- ASN1_TIME_Ptr notAfter(ASN1_TIME_new());
- uint64_t usageExpireDateTime = UINT64_MAX;
- key.authorizations().GetTagValue(TAG_USAGE_EXPIRE_DATETIME, &usageExpireDateTime);
- // TODO(swillden): When trusty can use the C++ standard library change the calculation of
- // notAfterTime to use std::numeric_limits<time_t>::max(), rather than assuming that time_t is
- // 32 bits.
- time_t notAfterTime =
- (time_t)min(static_cast<uint64_t>(UINT32_MAX), usageExpireDateTime / 1000);
- if (!notAfter.get() || !ASN1_TIME_set(notAfter.get(), notAfterTime) ||
- !X509_set_notAfter(certificate.get(), notAfter.get() /* Don't release; copied */))
- return TranslateLastOpenSslError();
-
- keymaster_error_t error = add_key_usage_extension(key.hw_enforced(), key.sw_enforced(), certificate.get());
- if (error != KM_ERROR_OK) {
- return error;
- }
-
- // We have established above that it is one of the two. So if it is not RSA its EC.
- int evp_key_type = (sign_algorithm == KM_ALGORITHM_RSA) ? EVP_PKEY_RSA : EVP_PKEY_EC;
-
- const uint8_t* key_material = attestation_signing_key.key_material;
- EVP_PKEY_Ptr sign_key(
- d2i_PrivateKey(evp_key_type, nullptr,
- const_cast<const uint8_t**>(&key_material),
- attestation_signing_key.key_material_size));
- if (!sign_key.get()) return TranslateLastOpenSslError();
-
- if (!add_public_key(pkey.get(), certificate.get(), &error) ||
- !add_attestation_extension(attest_params, key.hw_enforced(), key.sw_enforced(),
- context, certificate.get(), &error))
- return error;
-
- if (attestation_chain.entry_count < 1) {
- // the attestation chain must have at least the cert for the key that signs the new cert.
- return KM_ERROR_UNKNOWN_ERROR;
- }
-
- const uint8_t* p = attestation_chain.entries[0].data;
- X509_Ptr signing_cert(d2i_X509(nullptr, &p, attestation_chain.entries[0].data_length));
- if (!signing_cert.get()) {
return TranslateLastOpenSslError();
}
- // Set issuer to subject of batch certificate.
- X509_NAME* issuerSubject = X509_get_subject_name(signing_cert.get());
- if (!issuerSubject) {
- return KM_ERROR_UNKNOWN_ERROR;
- }
- if (!X509_set_issuer_name(certificate.get(), issuerSubject)) {
- return TranslateLastOpenSslError();
- }
-
- UniquePtr<X509V3_CTX> x509v3_ctx(new(std::nothrow) X509V3_CTX);
- if (!x509v3_ctx.get())
- return KM_ERROR_MEMORY_ALLOCATION_FAILED;
- *x509v3_ctx = {};
- X509V3_set_ctx(x509v3_ctx.get(), signing_cert.get(), certificate.get(), nullptr /* req */,
- nullptr /* crl */, 0 /* flags */);
-
- X509_EXTENSION_Ptr auth_key_id(X509V3_EXT_nconf_nid(nullptr /* conf */, x509v3_ctx.get(),
- NID_authority_key_identifier,
- const_cast<char*>("keyid:always")));
- if (!auth_key_id.get() ||
- !X509_add_ext(certificate.get(), auth_key_id.get() /* Don't release; copied */,
- -1 /* insert at end */)) {
- return TranslateLastOpenSslError();
- }
-
- if (!X509_sign(certificate.get(), sign_key.get(), EVP_sha256()))
- return TranslateLastOpenSslError();
-
- *cert_chain_out = makeCertChain(certificate.get(), attestation_chain);
- if (!cert_chain_out->get())
- return KM_ERROR_MEMORY_ALLOCATION_FAILED;
return KM_ERROR_OK;
}
+keymaster_error_t make_attestation_cert(const EVP_PKEY* evp_pkey, const X509_NAME* issuer,
+ const CertificateCallerParams& cert_params,
+ const AuthorizationSet& attest_params,
+ const AuthorizationSet& tee_enforced,
+ const AuthorizationSet& sw_enforced,
+ const AttestationContext& context, X509_Ptr* cert_out) {
-} // namespace keymaster
+ // First make the basic certificate with usage extension.
+ X509_Ptr certificate;
+ if (auto error = make_cert(evp_pkey, issuer, cert_params, &certificate)) {
+ return error;
+ }
+
+ // Add attestation extension.
+ if (auto error = add_attestation_extension(attest_params, tee_enforced, sw_enforced, context,
+ certificate.get())) {
+ return error;
+ }
+
+ *cert_out = move(certificate);
+ return KM_ERROR_OK;
+}
+
+X509_NAME_Ptr get_issuer_subject(const AttestKeyInfo& attest_key, keymaster_error_t* error) {
+ // Use subject from attest_key.
+ const uint8_t* p = attest_key.issuer_subject->data;
+ if (!p || !attest_key.issuer_subject->data_length) {
+ *error = KM_ERROR_MISSING_ISSUER_SUBJECT;
+ return {};
+ }
+ X509_NAME_Ptr retval(d2i_X509_NAME(nullptr /* Allocate X509_NAME */, &p,
+ attest_key.issuer_subject->data_length));
+ if (!retval) *error = KM_ERROR_INVALID_ISSUER_SUBJECT;
+ return retval;
+}
+
+X509_NAME_Ptr get_issuer_subject(const keymaster_blob_t& signing_cert_der,
+ keymaster_error_t* error) {
+ const uint8_t* p = signing_cert_der.data;
+ if (!p) {
+ *error = KM_ERROR_UNEXPECTED_NULL_POINTER;
+ return {};
+ }
+ X509_Ptr signing_cert(d2i_X509(nullptr /* Allocate X509 */, &p, signing_cert_der.data_length));
+ if (!signing_cert) {
+ *error = TranslateLastOpenSslError();
+ return {};
+ }
+
+ X509_NAME* issuer_subject = X509_get_subject_name(signing_cert.get());
+ if (!issuer_subject) {
+ *error = TranslateLastOpenSslError();
+ return {};
+ }
+
+ X509_NAME_Ptr retval(X509_NAME_dup(issuer_subject));
+ if (!retval) *error = TranslateLastOpenSslError();
+
+ return retval;
+}
+
+// Return subject from attest_key, if non-null, otherwise extract from cert_chain.
+X509_NAME_Ptr get_issuer_subject(const AttestKeyInfo& attest_key,
+ const CertificateChain& cert_chain, keymaster_error_t* error) {
+ if (attest_key) {
+ return get_issuer_subject(attest_key, error);
+ }
+
+ // Need to extract issuer from cert chain. First cert in the chain is the signing key cert.
+ if (cert_chain.entry_count >= 1) return get_issuer_subject(cert_chain.entries[0], error);
+
+ *error = KM_ERROR_UNKNOWN_ERROR;
+ return {};
+}
+
+keymaster_error_t check_attest_key_auths(const Key& key) {
+ auto auths = key.authorizations();
+
+ if (!auths.Contains(TAG_ALGORITHM, KM_ALGORITHM_RSA) &&
+ !auths.Contains(TAG_ALGORITHM, KM_ALGORITHM_EC)) {
+ return KM_ERROR_INCOMPATIBLE_ALGORITHM;
+ }
+ if (!auths.Contains(TAG_PURPOSE, KM_PURPOSE_ATTEST_KEY)) {
+ return KM_ERROR_INCOMPATIBLE_PURPOSE;
+ }
+ return KM_ERROR_OK;
+}
+
+EVP_PKEY_Ptr get_attestation_key(keymaster_algorithm_t algorithm, const AttestationContext& context,
+ keymaster_error_t* error) {
+ KeymasterKeyBlob signing_key_blob = context.GetAttestationKey(algorithm, error);
+ if (*error != KM_ERROR_OK) return {};
+
+ const uint8_t* p = signing_key_blob.key_material;
+ EVP_PKEY_Ptr retval(
+ d2i_AutoPrivateKey(nullptr /* Allocate key */, &p, signing_key_blob.key_material_size));
+ if (!retval) *error = TranslateLastOpenSslError();
+ return retval;
+}
+
+} // namespace
+
+AttestKeyInfo::AttestKeyInfo(const UniquePtr<Key>& key, const KeymasterBlob* issuer_subject_,
+ keymaster_error_t* error)
+ : issuer_subject(issuer_subject_) {
+ if (!error) return;
+
+ if (!key) {
+ // No key... so this is just an empty AttestKeyInfo.
+ issuer_subject = nullptr;
+ return;
+ }
+
+ if (!issuer_subject) {
+ *error = KM_ERROR_UNEXPECTED_NULL_POINTER;
+ return;
+ }
+
+ *error = check_attest_key_auths(*key);
+ if (*error != KM_ERROR_OK) return;
+
+ signing_key.reset(EVP_PKEY_new());
+ if (!signing_key) {
+ *error = TranslateLastOpenSslError();
+ return;
+ }
+
+ if (!static_cast<const AsymmetricKey&>(*key).InternalToEvp(signing_key.get())) {
+ *error = KM_ERROR_UNKNOWN_ERROR;
+ }
+}
+
+CertificateChain generate_attestation(const AsymmetricKey& key,
+ const AuthorizationSet& attest_params,
+ AttestKeyInfo attest_key,
+ const AttestationContext& context, //
+ keymaster_error_t* error) {
+ EVP_PKEY_Ptr pkey(EVP_PKEY_new());
+ if (!key.InternalToEvp(pkey.get())) {
+ *error = TranslateLastOpenSslError();
+ return {};
+ }
+
+ return generate_attestation(pkey.get(), key.sw_enforced(), key.hw_enforced(), attest_params,
+ move(attest_key), context, error);
+}
+
+CertificateChain generate_attestation(const EVP_PKEY* evp_key, //
+ const AuthorizationSet& sw_enforced, //
+ const AuthorizationSet& tee_enforced,
+ const AuthorizationSet& attest_params,
+ AttestKeyInfo attest_key,
+ const AttestationContext& context, //
+ keymaster_error_t* error) {
+ if (!error) return {};
+
+ CertificateCallerParams cert_params{};
+ *error = get_certificate_params(attest_params, &cert_params, context.GetKmVersion());
+ if (*error != KM_ERROR_OK) return {};
+
+ AuthProxy proxy(tee_enforced, sw_enforced);
+ cert_params.is_signing_key = proxy.Contains(TAG_PURPOSE, KM_PURPOSE_SIGN);
+ cert_params.is_encryption_key = proxy.Contains(TAG_PURPOSE, KM_PURPOSE_DECRYPT);
+ cert_params.is_agreement_key = proxy.Contains(TAG_PURPOSE, KM_PURPOSE_AGREE_KEY);
+
+ keymaster_algorithm_t algorithm;
+ if (!proxy.GetTagValue(TAG_ALGORITHM, &algorithm)) {
+ *error = KM_ERROR_UNSUPPORTED_PURPOSE;
+ return {};
+ }
+
+ CertificateChain cert_chain =
+ attest_key ? CertificateChain() : context.GetAttestationChain(algorithm, error);
+ if (*error != KM_ERROR_OK) return {};
+
+ X509_NAME_Ptr issuer_subject = get_issuer_subject(attest_key, cert_chain, error);
+ if (*error != KM_ERROR_OK) return {};
+
+ X509_Ptr certificate;
+ *error = make_attestation_cert(evp_key, issuer_subject.get(), cert_params, attest_params,
+ tee_enforced, sw_enforced, context, &certificate);
+ if (*error != KM_ERROR_OK) return {};
+
+ EVP_PKEY_Ptr signing_key;
+ const EVP_PKEY* signing_key_ptr = attest_key.signing_key.get();
+ if (!signing_key_ptr) {
+ signing_key = get_attestation_key(algorithm, context, error);
+ if (*error != KM_ERROR_OK) return {};
+ signing_key_ptr = signing_key.get();
+ }
+
+ *error = sign_cert(certificate.get(), signing_key_ptr);
+ if (*error != KM_ERROR_OK) return {};
+
+ return make_cert_chain(certificate.get(), move(cert_chain), error);
+}
+
+} // namespace keymaster
diff --git a/km_openssl/block_cipher_operation.cpp b/km_openssl/block_cipher_operation.cpp
index 4a34b35..a381e75 100644
--- a/km_openssl/block_cipher_operation.cpp
+++ b/km_openssl/block_cipher_operation.cpp
@@ -18,8 +18,6 @@
#include <stdio.h>
-#include <keymaster/new.h>
-
#include <keymaster/UniquePtr.h>
#include <openssl/aes.h>
@@ -162,7 +160,9 @@
(size_t)sizeof(operation_handle_));
if (rc != KM_ERROR_OK) return rc;
- return InitializeCipher(move(key_));
+ auto retval = InitializeCipher(key_);
+ key_ = {};
+ return retval;
}
keymaster_error_t BlockCipherEvpOperation::Update(const AuthorizationSet& additional_params,
@@ -177,6 +177,7 @@
return KM_ERROR_OK;
}
+// NOLINTNEXTLINE(google-runtime-int)
inline bool is_bad_decrypt(unsigned long error) {
return (ERR_GET_LIB(error) == ERR_LIB_CIPHER && //
ERR_GET_REASON(error) == CIPHER_R_BAD_DECRYPT);
@@ -197,7 +198,9 @@
int output_written = -1;
if (!EVP_CipherFinal_ex(&ctx_, output->peek_write(), &output_written)) {
if (tag_length_ > 0) return KM_ERROR_VERIFICATION_FAILED;
- LOG_E("Error encrypting final block: %s", ERR_error_string(ERR_peek_last_error(), nullptr));
+ char buf[128];
+ ERR_error_string_n(ERR_peek_last_error(), buf, sizeof(buf));
+ LOG_E("Error encrypting final block: %s", buf);
return TranslateLastOpenSslError();
}
@@ -222,7 +225,7 @@
}
}
-keymaster_error_t BlockCipherEvpOperation::InitializeCipher(KeymasterKeyBlob key) {
+keymaster_error_t BlockCipherEvpOperation::InitializeCipher(const KeymasterKeyBlob& key) {
keymaster_error_t error;
const EVP_CIPHER* cipher =
cipher_description_.GetCipherInstance(key.key_material_size, block_mode_, &error);
diff --git a/km_openssl/block_cipher_operation.h b/km_openssl/block_cipher_operation.h
index 1da94eb..9c25bda 100644
--- a/km_openssl/block_cipher_operation.h
+++ b/km_openssl/block_cipher_operation.h
@@ -87,7 +87,7 @@
virtual int evp_encrypt_mode() = 0;
bool need_iv() const;
- keymaster_error_t InitializeCipher(KeymasterKeyBlob key);
+ keymaster_error_t InitializeCipher(const KeymasterKeyBlob& key);
keymaster_error_t GetIv(const AuthorizationSet& input_params);
bool HandleAad(const AuthorizationSet& input_params, const Buffer& input,
keymaster_error_t* error);
diff --git a/km_openssl/certificate_utils.cpp b/km_openssl/certificate_utils.cpp
new file mode 100644
index 0000000..d9419c8
--- /dev/null
+++ b/km_openssl/certificate_utils.cpp
@@ -0,0 +1,401 @@
+/*
+ * Copyright 2020, 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 <openssl/asn1.h>
+#include <openssl/evp.h>
+#include <openssl/x509v3.h>
+
+#include <hardware/keymaster_defs.h>
+#include <keymaster/android_keymaster_utils.h>
+#include <keymaster/authorization_set.h>
+#include <keymaster/km_openssl/asymmetric_key.h>
+#include <keymaster/km_openssl/certificate_utils.h>
+#include <keymaster/km_openssl/openssl_err.h>
+#include <keymaster/logger.h>
+
+namespace keymaster {
+
+namespace {
+
+constexpr const char kDefaultSubject[] = "Android Keystore Key";
+constexpr int kDataEnciphermentKeyUsageBit = 3;
+constexpr int kDigitalSignatureKeyUsageBit = 0;
+constexpr int kKeyEnciphermentKeyUsageBit = 2;
+constexpr int kKeyAgreementKeyUsageBit = 4;
+constexpr int kMaxKeyUsageBit = 8;
+
+template <typename T> T&& min(T&& a, T&& b) {
+ return (a < b) ? forward<T>(a) : forward<T>(b);
+}
+
+keymaster_error_t fake_sign_cert(X509* cert) {
+ // Set algorithm in TBSCertificate
+ X509_ALGOR_set0(cert->cert_info->signature, OBJ_nid2obj(NID_sha256WithRSAEncryption),
+ V_ASN1_NULL, nullptr);
+
+ // Set algorithm in Certificate
+ X509_ALGOR_set0(cert->sig_alg, OBJ_nid2obj(NID_sha256WithRSAEncryption), V_ASN1_NULL, nullptr);
+
+ // Set signature to a bit string containing a single byte, value 0.
+ uint8_t fake_sig = 0;
+ if (!cert->signature) cert->signature = ASN1_BIT_STRING_new();
+ if (!cert->signature) return KM_ERROR_MEMORY_ALLOCATION_FAILED;
+ if (!ASN1_STRING_set(cert->signature, &fake_sig, sizeof(fake_sig))) {
+ return TranslateLastOpenSslError();
+ }
+
+ return KM_ERROR_OK;
+}
+
+} // namespace
+
+keymaster_error_t make_name_from_str(const char name[], X509_NAME_Ptr* name_out) {
+ if (name_out == nullptr) return KM_ERROR_UNEXPECTED_NULL_POINTER;
+ X509_NAME_Ptr x509_name(X509_NAME_new());
+ if (!x509_name.get()) {
+ return TranslateLastOpenSslError();
+ }
+ if (!X509_NAME_add_entry_by_txt(x509_name.get(), //
+ "CN", //
+ MBSTRING_ASC, reinterpret_cast<const uint8_t*>(&name[0]),
+ -1, // len
+ -1, // loc
+ 0 /* set */)) {
+ return TranslateLastOpenSslError();
+ }
+ *name_out = move(x509_name);
+ return KM_ERROR_OK;
+}
+
+keymaster_error_t make_name_from_der(const keymaster_blob_t& name, X509_NAME_Ptr* name_out) {
+ if (!name_out || !name.data) return KM_ERROR_UNEXPECTED_NULL_POINTER;
+
+ const uint8_t* p = name.data;
+ X509_NAME_Ptr x509_name(d2i_X509_NAME(nullptr, &p, name.data_length));
+ if (!x509_name.get()) {
+ return TranslateLastOpenSslError();
+ }
+
+ *name_out = move(x509_name);
+ return KM_ERROR_OK;
+}
+
+keymaster_error_t get_common_name(X509_NAME* name, UniquePtr<const char[]>* name_out) {
+ if (name == nullptr || name_out == nullptr) return KM_ERROR_UNEXPECTED_NULL_POINTER;
+ int len = X509_NAME_get_text_by_NID(name, NID_commonName, nullptr, 0);
+ UniquePtr<char[]> name_ptr(new (std::nothrow) char[len]);
+ if (!name_ptr) {
+ return KM_ERROR_MEMORY_ALLOCATION_FAILED;
+ }
+ X509_NAME_get_text_by_NID(name, NID_commonName, name_ptr.get(), len);
+ *name_out = UniquePtr<const char[]>{name_ptr.release()};
+ return KM_ERROR_OK;
+}
+
+keymaster_error_t get_certificate_params(const AuthorizationSet& caller_params,
+ CertificateCallerParams* cert_params,
+ KmVersion kmVersion) {
+ if (!cert_params) return KM_ERROR_UNEXPECTED_NULL_POINTER;
+
+ BIGNUM_Ptr serial(BN_new());
+ if (!serial) {
+ return KM_ERROR_MEMORY_ALLOCATION_FAILED;
+ }
+
+ keymaster_blob_t serial_blob{.data = nullptr, .data_length = 0};
+ if (caller_params.GetTagValue(TAG_CERTIFICATE_SERIAL, &serial_blob)) {
+ if (BN_bin2bn(serial_blob.data, serial_blob.data_length, serial.get()) == nullptr) {
+ return TranslateLastOpenSslError();
+ }
+ } else {
+ // Default serial is one.
+ BN_one(serial.get());
+ }
+ cert_params->serial = move(serial);
+
+ cert_params->active_date_time = 0;
+ cert_params->expire_date_time = kUndefinedExpirationDateTime;
+
+ uint64_t tmp;
+ switch (kmVersion) {
+ case KmVersion::KEYMASTER_1:
+ case KmVersion::KEYMASTER_1_1:
+ case KmVersion::KEYMASTER_2:
+ case KmVersion::KEYMASTER_3:
+ case KmVersion::KEYMASTER_4:
+ case KmVersion::KEYMASTER_4_1:
+ if (caller_params.GetTagValue(TAG_ACTIVE_DATETIME, &tmp)) {
+ LOG_D("Using TAG_ACTIVE_DATETIME: %lu", tmp);
+ cert_params->active_date_time = static_cast<int64_t>(tmp);
+ }
+ if (caller_params.GetTagValue(TAG_ORIGINATION_EXPIRE_DATETIME, &tmp)) {
+ LOG_D("Using TAG_ORIGINATION_EXPIRE_DATETIME: %lu", tmp);
+ cert_params->expire_date_time = static_cast<int64_t>(tmp);
+ }
+ break;
+
+ case KmVersion::KEYMINT_1:
+ if (!caller_params.GetTagValue(TAG_CERTIFICATE_NOT_BEFORE, &tmp)) {
+ return KM_ERROR_MISSING_NOT_BEFORE;
+ }
+ LOG_D("Using TAG_CERTIFICATE_NOT_BEFORE: %lu", tmp);
+ cert_params->active_date_time = static_cast<int64_t>(tmp);
+
+ if (!caller_params.GetTagValue(TAG_CERTIFICATE_NOT_AFTER, &tmp)) {
+ return KM_ERROR_MISSING_NOT_AFTER;
+ }
+ LOG_D("Using TAG_CERTIFICATE_NOT_AFTER: %lu", tmp);
+ cert_params->expire_date_time = static_cast<int64_t>(tmp);
+ }
+
+ LOG_D("Got certificate date params: NotBefore = %ld, NotAfter = %ld",
+ cert_params->active_date_time, cert_params->expire_date_time);
+
+ keymaster_blob_t subject{};
+ if (caller_params.GetTagValue(TAG_CERTIFICATE_SUBJECT, &subject) && subject.data_length) {
+ return make_name_from_der(subject, &cert_params->subject_name);
+ }
+
+ return make_name_from_str(kDefaultSubject, &cert_params->subject_name);
+}
+
+keymaster_error_t make_key_usage_extension(bool is_signing_key, bool is_encryption_key,
+ bool is_key_agreement_key,
+ X509_EXTENSION_Ptr* usage_extension_out) {
+ if (usage_extension_out == nullptr) return KM_ERROR_UNEXPECTED_NULL_POINTER;
+
+ // Build BIT_STRING with correct contents.
+ ASN1_BIT_STRING_Ptr key_usage(ASN1_BIT_STRING_new());
+ if (!key_usage) return KM_ERROR_MEMORY_ALLOCATION_FAILED;
+
+ for (size_t i = 0; i <= kMaxKeyUsageBit; ++i) {
+ if (!ASN1_BIT_STRING_set_bit(key_usage.get(), i, 0)) {
+ return TranslateLastOpenSslError();
+ }
+ }
+
+ if (is_signing_key) {
+ if (!ASN1_BIT_STRING_set_bit(key_usage.get(), kDigitalSignatureKeyUsageBit, 1)) {
+ return TranslateLastOpenSslError();
+ }
+ }
+
+ if (is_encryption_key) {
+ if (!ASN1_BIT_STRING_set_bit(key_usage.get(), kKeyEnciphermentKeyUsageBit, 1) ||
+ !ASN1_BIT_STRING_set_bit(key_usage.get(), kDataEnciphermentKeyUsageBit, 1)) {
+ return TranslateLastOpenSslError();
+ }
+ }
+
+ if (is_key_agreement_key) {
+ if (!ASN1_BIT_STRING_set_bit(key_usage.get(), kKeyAgreementKeyUsageBit, 1)) {
+ return TranslateLastOpenSslError();
+ }
+ }
+
+ // Convert to octets
+ int len = i2d_ASN1_BIT_STRING(key_usage.get(), nullptr);
+ if (len < 0) {
+ return TranslateLastOpenSslError();
+ }
+ UniquePtr<uint8_t[]> asn1_key_usage(new (std::nothrow) uint8_t[len]);
+ if (!asn1_key_usage.get()) {
+ return KM_ERROR_MEMORY_ALLOCATION_FAILED;
+ }
+ uint8_t* p = asn1_key_usage.get();
+ len = i2d_ASN1_BIT_STRING(key_usage.get(), &p);
+ if (len < 0) {
+ return TranslateLastOpenSslError();
+ }
+
+ // Build OCTET_STRING
+ ASN1_OCTET_STRING_Ptr key_usage_str(ASN1_OCTET_STRING_new());
+ if (!key_usage_str.get() ||
+ !ASN1_OCTET_STRING_set(key_usage_str.get(), asn1_key_usage.get(), len)) {
+ return TranslateLastOpenSslError();
+ }
+
+ X509_EXTENSION_Ptr key_usage_extension(X509_EXTENSION_create_by_NID(nullptr, //
+ NID_key_usage, //
+ true /* critical */,
+ key_usage_str.get()));
+ if (!key_usage_extension.get()) {
+ return TranslateLastOpenSslError();
+ }
+
+ *usage_extension_out = move(key_usage_extension);
+
+ return KM_ERROR_OK;
+}
+
+// Creates a rump certificate structure with serial, subject and issuer names, as well as
+// activation and expiry date.
+// Callers should pass an empty X509_Ptr and check the return value for KM_ERROR_OK (0) before
+// accessing the result.
+keymaster_error_t make_cert_rump(const X509_NAME* issuer,
+ const CertificateCallerParams& cert_params, X509_Ptr* cert_out) {
+ if (!cert_out || !issuer) return KM_ERROR_UNEXPECTED_NULL_POINTER;
+
+ // Create certificate structure.
+ X509_Ptr certificate(X509_new());
+ if (!certificate.get()) return TranslateLastOpenSslError();
+
+ // Set the X509 version.
+ if (!X509_set_version(certificate.get(), 2 /* version 3 */)) return TranslateLastOpenSslError();
+
+ // Set the certificate serialNumber
+ ASN1_INTEGER_Ptr serial_number(ASN1_INTEGER_new());
+ if (!serial_number.get() || //
+ !BN_to_ASN1_INTEGER(cert_params.serial.get(), serial_number.get()) ||
+ !X509_set_serialNumber(certificate.get(),
+ serial_number.get() /* Don't release; copied */)) {
+ return TranslateLastOpenSslError();
+ }
+
+ if (!X509_set_subject_name(certificate.get(),
+ const_cast<X509_NAME*>(cert_params.subject_name.get()))) {
+ return TranslateLastOpenSslError();
+ }
+
+ if (!X509_set_issuer_name(certificate.get(), const_cast<X509_NAME*>(issuer))) {
+ return TranslateLastOpenSslError();
+ }
+
+ // Set activation date.
+ ASN1_TIME_Ptr notBefore(ASN1_TIME_new());
+ LOG_D("Setting notBefore to %ld: ", cert_params.active_date_time / 1000);
+ time_t notBeforeTime = static_cast<time_t>(cert_params.active_date_time / 1000);
+ if (!notBefore.get() || !ASN1_TIME_set(notBefore.get(), notBeforeTime) ||
+ !X509_set_notBefore(certificate.get(), notBefore.get() /* Don't release; copied */)) {
+ return TranslateLastOpenSslError();
+ }
+
+ // Set expiration date.
+ ASN1_TIME_Ptr notAfter(ASN1_TIME_new());
+ LOG_D("Setting notAfter to %ld: ", cert_params.expire_date_time / 1000);
+ time_t notAfterTime = static_cast<time_t>(cert_params.expire_date_time / 1000);
+
+ if (!notAfter.get() || !ASN1_TIME_set(notAfter.get(), notAfterTime) ||
+ !X509_set_notAfter(certificate.get(), notAfter.get() /* Don't release; copied */)) {
+ return TranslateLastOpenSslError();
+ }
+
+ *cert_out = move(certificate);
+ return KM_ERROR_OK;
+}
+
+keymaster_error_t make_cert(const EVP_PKEY* evp_pkey, const X509_NAME* issuer,
+ const CertificateCallerParams& cert_params, X509_Ptr* cert_out) {
+
+ // Make the rump certificate with serial, subject, not before and not after dates.
+ X509_Ptr certificate;
+ if (keymaster_error_t error = make_cert_rump(issuer, cert_params, &certificate)) {
+ return error;
+ }
+
+ // Set the public key.
+ if (!X509_set_pubkey(certificate.get(), (EVP_PKEY*)evp_pkey)) {
+ return TranslateLastOpenSslError();
+ }
+
+ // Make and add the key usage extension.
+ X509_EXTENSION_Ptr key_usage_extension;
+ if (auto error =
+ make_key_usage_extension(cert_params.is_signing_key, cert_params.is_encryption_key,
+ cert_params.is_agreement_key, &key_usage_extension)) {
+ return error;
+ }
+ if (!X509_add_ext(certificate.get(), key_usage_extension.get() /* Don't release; copied */,
+ -1 /* insert at end */)) {
+ return TranslateLastOpenSslError();
+ }
+
+ *cert_out = move(certificate);
+ return KM_ERROR_OK;
+}
+
+keymaster_error_t sign_cert(X509* certificate, const EVP_PKEY* signing_key) {
+ if (!certificate || !signing_key) return KM_ERROR_UNEXPECTED_NULL_POINTER;
+
+ // X509_sign takes the key as non-const, but per the BoringSSL dev team, that's a legacy
+ // mistake that hasn't yet been corrected.
+ auto sk = const_cast<EVP_PKEY*>(signing_key);
+
+ if (!X509_sign(certificate, sk, EVP_sha256())) {
+ return TranslateLastOpenSslError();
+ }
+ return KM_ERROR_OK;
+}
+
+CertificateChain generate_self_signed_cert(const AsymmetricKey& key, const AuthorizationSet& params,
+ bool fake_signature, keymaster_error_t* error) {
+ keymaster_error_t err;
+ if (!error) error = &err;
+
+ EVP_PKEY_Ptr pkey(EVP_PKEY_new());
+ if (!key.InternalToEvp(pkey.get())) {
+ *error = TranslateLastOpenSslError();
+ return {};
+ }
+
+ CertificateCallerParams cert_params{};
+ // Self signed certificates are only generated since Keymint 1.0. To keep the API stable for
+ // now, we pass KEYMINT_1 to get_certificate_params, which has the intended effect. If
+ // get_certificate_params ever has to distinguish between versions of KeyMint this needs to be
+ // changed.
+ *error = get_certificate_params(params, &cert_params, KmVersion::KEYMINT_1);
+ if (*error != KM_ERROR_OK) return {};
+
+ cert_params.is_signing_key = key.authorizations().Contains(TAG_PURPOSE, KM_PURPOSE_SIGN);
+ cert_params.is_encryption_key = key.authorizations().Contains(TAG_PURPOSE, KM_PURPOSE_DECRYPT);
+ cert_params.is_agreement_key = key.authorizations().Contains(TAG_PURPOSE, KM_PURPOSE_AGREE_KEY);
+
+ X509_Ptr cert;
+ *error = make_cert(pkey.get(), cert_params.subject_name.get() /* issuer */, cert_params, &cert);
+ if (*error != KM_ERROR_OK) return {};
+
+ if (fake_signature) {
+ *error = fake_sign_cert(cert.get());
+ } else {
+ *error = sign_cert(cert.get(), pkey.get());
+ }
+ if (*error != KM_ERROR_OK) return {};
+
+ CertificateChain result(1);
+ if (!result) {
+ *error = KM_ERROR_MEMORY_ALLOCATION_FAILED;
+ return {};
+ }
+
+ *error = encode_certificate(cert.get(), &result.entries[0]);
+ if (*error != KM_ERROR_OK) return {};
+
+ return result;
+}
+
+keymaster_error_t encode_certificate(X509* certificate, keymaster_blob_t* blob) {
+ int len = i2d_X509(certificate, nullptr /* ppout */);
+ if (len < 0) return TranslateLastOpenSslError();
+
+ blob->data = new (std::nothrow) uint8_t[len];
+ if (!blob->data) return KM_ERROR_MEMORY_ALLOCATION_FAILED;
+
+ uint8_t* p = const_cast<uint8_t*>(blob->data);
+ blob->data_length = i2d_X509(certificate, &p);
+ return KM_ERROR_OK;
+}
+
+} // namespace keymaster
diff --git a/km_openssl/ec_key_factory.cpp b/km_openssl/ec_key_factory.cpp
index 8dead88..80d761f 100644
--- a/km_openssl/ec_key_factory.cpp
+++ b/km_openssl/ec_key_factory.cpp
@@ -18,7 +18,9 @@
#include <openssl/evp.h>
+#include <keymaster/keymaster_context.h>
#include <keymaster/km_openssl/ec_key.h>
+#include <keymaster/km_openssl/ecdh_operation.h>
#include <keymaster/km_openssl/ecdsa_operation.h>
#include <keymaster/km_openssl/openssl_err.h>
@@ -28,6 +30,7 @@
static EcdsaSignOperationFactory sign_factory;
static EcdsaVerifyOperationFactory verify_factory;
+static EcdhOperationFactory agree_key_factory;
OperationFactory* EcKeyFactory::GetOperationFactory(keymaster_purpose_t purpose) const {
switch (purpose) {
@@ -35,6 +38,8 @@
return &sign_factory;
case KM_PURPOSE_VERIFY:
return &verify_factory;
+ case KM_PURPOSE_AGREE_KEY:
+ return &agree_key_factory;
default:
return nullptr;
}
@@ -72,11 +77,13 @@
}
keymaster_error_t EcKeyFactory::GenerateKey(const AuthorizationSet& key_description,
+ UniquePtr<Key> attest_key, //
+ const KeymasterBlob& issuer_subject,
KeymasterKeyBlob* key_blob,
AuthorizationSet* hw_enforced,
- AuthorizationSet* sw_enforced) const {
- if (!key_blob || !hw_enforced || !sw_enforced)
- return KM_ERROR_OUTPUT_PARAMETER_NULL;
+ AuthorizationSet* sw_enforced,
+ CertificateChain* cert_chain) const {
+ if (!key_blob || !hw_enforced || !sw_enforced) return KM_ERROR_OUTPUT_PARAMETER_NULL;
AuthorizationSet authorizations(key_description);
@@ -93,8 +100,7 @@
UniquePtr<EC_KEY, EC_KEY_Delete> ec_key(EC_KEY_new());
UniquePtr<EVP_PKEY, EVP_PKEY_Delete> pkey(EVP_PKEY_new());
- if (ec_key.get() == nullptr || pkey.get() == nullptr)
- return KM_ERROR_MEMORY_ALLOCATION_FAILED;
+ if (ec_key.get() == nullptr || pkey.get() == nullptr) return KM_ERROR_MEMORY_ALLOCATION_FAILED;
UniquePtr<EC_GROUP, EC_GROUP_Delete> group(ChooseGroup(ec_curve));
if (group.get() == nullptr) {
@@ -112,36 +118,78 @@
return TranslateLastOpenSslError();
}
- if (EVP_PKEY_set1_EC_KEY(pkey.get(), ec_key.get()) != 1)
- return TranslateLastOpenSslError();
+ if (EVP_PKEY_set1_EC_KEY(pkey.get(), ec_key.get()) != 1) return TranslateLastOpenSslError();
KeymasterKeyBlob key_material;
error = EvpKeyToKeyMaterial(pkey.get(), &key_material);
- if (error != KM_ERROR_OK)
- return error;
+ if (error != KM_ERROR_OK) return error;
- return blob_maker_.CreateKeyBlob(authorizations, KM_ORIGIN_GENERATED, key_material, key_blob,
- hw_enforced, sw_enforced);
+ error = blob_maker_.CreateKeyBlob(authorizations, KM_ORIGIN_GENERATED, key_material, key_blob,
+ hw_enforced, sw_enforced);
+ if (error != KM_ERROR_OK) return error;
+
+ if (context_.GetKmVersion() < KmVersion::KEYMINT_1) return KM_ERROR_OK;
+ if (!cert_chain) return KM_ERROR_UNEXPECTED_NULL_POINTER;
+
+ EcKey key(*hw_enforced, *sw_enforced, this, move(ec_key));
+ if (key_description.Contains(TAG_ATTESTATION_CHALLENGE)) {
+ *cert_chain = context_.GenerateAttestation(key, key_description, move(attest_key),
+ issuer_subject, &error);
+ } else if (attest_key.get() != nullptr) {
+ return KM_ERROR_ATTESTATION_CHALLENGE_MISSING;
+ } else {
+ *cert_chain = context_.GenerateSelfSignedCertificate(
+ key, key_description,
+ !key_description.Contains(TAG_PURPOSE, KM_PURPOSE_SIGN) /* fake_signature */, &error);
+ }
+
+ return error;
}
-keymaster_error_t EcKeyFactory::ImportKey(const AuthorizationSet& key_description,
+keymaster_error_t EcKeyFactory::ImportKey(const AuthorizationSet& key_description, //
keymaster_key_format_t input_key_material_format,
const KeymasterKeyBlob& input_key_material,
+ UniquePtr<Key> attest_key, //
+ const KeymasterBlob& issuer_subject,
KeymasterKeyBlob* output_key_blob,
AuthorizationSet* hw_enforced,
- AuthorizationSet* sw_enforced) const {
- if (!output_key_blob || !hw_enforced || !sw_enforced)
- return KM_ERROR_OUTPUT_PARAMETER_NULL;
+ AuthorizationSet* sw_enforced,
+ CertificateChain* cert_chain) const {
+ if (!output_key_blob || !hw_enforced || !sw_enforced) return KM_ERROR_OUTPUT_PARAMETER_NULL;
AuthorizationSet authorizations;
uint32_t key_size;
keymaster_error_t error = UpdateImportKeyDescription(
key_description, input_key_material_format, input_key_material, &authorizations, &key_size);
- if (error != KM_ERROR_OK)
- return error;
+ if (error != KM_ERROR_OK) return error;
- return blob_maker_.CreateKeyBlob(authorizations, KM_ORIGIN_IMPORTED, input_key_material,
- output_key_blob, hw_enforced, sw_enforced);
+ error = blob_maker_.CreateKeyBlob(authorizations, KM_ORIGIN_IMPORTED, input_key_material,
+ output_key_blob, hw_enforced, sw_enforced);
+ if (error != KM_ERROR_OK) return error;
+
+ if (context_.GetKmVersion() < KmVersion::KEYMINT_1) return KM_ERROR_OK;
+ if (!cert_chain) return KM_ERROR_UNEXPECTED_NULL_POINTER;
+
+ EVP_PKEY_Ptr pkey;
+ error = KeyMaterialToEvpKey(KM_KEY_FORMAT_PKCS8, input_key_material, KM_ALGORITHM_EC, &pkey);
+ if (error != KM_ERROR_OK) return error;
+
+ EC_KEY_Ptr ec_key(EVP_PKEY_get1_EC_KEY(pkey.get()));
+ if (!ec_key.get()) return KM_ERROR_INVALID_ARGUMENT;
+
+ EcKey key(*hw_enforced, *sw_enforced, this, move(ec_key));
+ if (key_description.Contains(KM_TAG_ATTESTATION_CHALLENGE)) {
+ *cert_chain = context_.GenerateAttestation(key, key_description, move(attest_key),
+ issuer_subject, &error);
+ } else if (attest_key.get() != nullptr) {
+ return KM_ERROR_ATTESTATION_CHALLENGE_MISSING;
+ } else {
+ *cert_chain = context_.GenerateSelfSignedCertificate(
+ key, key_description,
+ !key_description.Contains(TAG_PURPOSE, KM_PURPOSE_SIGN) /* fake_signature */, &error);
+ }
+
+ return error;
}
keymaster_error_t EcKeyFactory::UpdateImportKeyDescription(const AuthorizationSet& key_description,
@@ -149,25 +197,21 @@
const KeymasterKeyBlob& key_material,
AuthorizationSet* updated_description,
uint32_t* key_size_bits) const {
- if (!updated_description || !key_size_bits)
- return KM_ERROR_OUTPUT_PARAMETER_NULL;
+ if (!updated_description || !key_size_bits) return KM_ERROR_OUTPUT_PARAMETER_NULL;
UniquePtr<EVP_PKEY, EVP_PKEY_Delete> pkey;
keymaster_error_t error =
KeyMaterialToEvpKey(key_format, key_material, keymaster_key_type(), &pkey);
- if (error != KM_ERROR_OK)
- return error;
+ if (error != KM_ERROR_OK) return error;
UniquePtr<EC_KEY, EC_KEY_Delete> ec_key(EVP_PKEY_get1_EC_KEY(pkey.get()));
- if (!ec_key.get())
- return TranslateLastOpenSslError();
+ if (!ec_key.get()) return TranslateLastOpenSslError();
updated_description->Reinitialize(key_description);
size_t extracted_key_size_bits;
error = ec_get_group_size(EC_KEY_get0_group(ec_key.get()), &extracted_key_size_bits);
- if (error != KM_ERROR_OK)
- return error;
+ if (error != KM_ERROR_OK) return error;
*key_size_bits = extracted_key_size_bits;
if (!updated_description->GetTagValue(TAG_KEY_SIZE, key_size_bits)) {
@@ -178,8 +222,7 @@
keymaster_ec_curve_t curve_from_size;
error = EcKeySizeToCurve(*key_size_bits, &curve_from_size);
- if (error != KM_ERROR_OK)
- return error;
+ if (error != KM_ERROR_OK) return error;
keymaster_ec_curve_t curve;
if (!updated_description->GetTagValue(TAG_EC_CURVE, &curve)) {
updated_description->push_back(TAG_EC_CURVE, curve_from_size);
diff --git a/km_openssl/ecdh_operation.cpp b/km_openssl/ecdh_operation.cpp
new file mode 100644
index 0000000..fbc6f3e
--- /dev/null
+++ b/km_openssl/ecdh_operation.cpp
@@ -0,0 +1,112 @@
+/*
+ * Copyright 2021 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 <keymaster/km_openssl/ecdh_operation.h>
+
+#include <keymaster/km_openssl/ec_key.h>
+#include <keymaster/km_openssl/openssl_err.h>
+#include <keymaster/km_openssl/openssl_utils.h>
+#include <keymaster/logger.h>
+#include <openssl/err.h>
+#include <vector>
+
+namespace keymaster {
+
+keymaster_error_t EcdhOperation::Begin(const AuthorizationSet& /*input_params*/,
+ AuthorizationSet* /*output_params*/) {
+ auto rc = GenerateRandom(reinterpret_cast<uint8_t*>(&operation_handle_),
+ (size_t)sizeof(operation_handle_));
+ if (rc != KM_ERROR_OK) {
+ return rc;
+ }
+ return KM_ERROR_OK;
+}
+
+keymaster_error_t EcdhOperation::Update(const AuthorizationSet& /*additional_params*/,
+ const Buffer& /*input*/,
+ AuthorizationSet* /*output_params*/, Buffer* /*output*/,
+ size_t* /*input_consumed*/) {
+ return KM_ERROR_OK;
+}
+
+keymaster_error_t EcdhOperation::Finish(const AuthorizationSet& /*additional_params*/,
+ const Buffer& input, const Buffer& /*signature*/,
+ AuthorizationSet* /*output_params*/, Buffer* output) {
+ const unsigned char* encodedPublicKey = input.begin();
+ EVP_PKEY* pkeyRaw = d2i_PUBKEY(nullptr, &encodedPublicKey, input.available_read());
+ if (pkeyRaw == nullptr) {
+ LOG_E("Error decoding key", 0);
+ return TranslateLastOpenSslError();
+ }
+ auto pkey = EVP_PKEY_Ptr(pkeyRaw);
+
+ auto ctx = EVP_PKEY_CTX_Ptr(EVP_PKEY_CTX_new(ecdh_key_.get(), nullptr));
+ if (ctx.get() == nullptr) {
+ LOG_E("Memory allocation failed", 0);
+ return TranslateLastOpenSslError();
+ }
+ if (EVP_PKEY_derive_init(ctx.get()) != 1) {
+ LOG_E("Context initialization failed", 0);
+ return TranslateLastOpenSslError();
+ }
+ if (EVP_PKEY_derive_set_peer(ctx.get(), pkey.get()) != 1) {
+ LOG_E("Error setting peer key", 0);
+ return TranslateLastOpenSslError();
+ }
+ size_t sharedSecretLen = 0;
+ if (EVP_PKEY_derive(ctx.get(), nullptr, &sharedSecretLen) != 1) {
+ LOG_E("Error deriving key", 0);
+ return TranslateLastOpenSslError();
+ }
+ if (!output->reserve(sharedSecretLen)) {
+ LOG_E("Error reserving data in output buffer", 0);
+ return KM_ERROR_MEMORY_ALLOCATION_FAILED;
+ }
+ if (EVP_PKEY_derive(ctx.get(), output->peek_write(), &sharedSecretLen) != 1) {
+ LOG_E("Error deriving key", 0);
+ return TranslateLastOpenSslError();
+ }
+ output->advance_write(sharedSecretLen);
+
+ return KM_ERROR_OK;
+}
+
+OperationPtr EcdhOperationFactory::CreateOperation(Key&& key,
+ const AuthorizationSet& /*begin_params*/,
+ keymaster_error_t* error) {
+ const EcKey& ecdh_key = static_cast<EcKey&>(key);
+
+ EVP_PKEY_Ptr pkey(EVP_PKEY_new());
+ if (pkey.get() == nullptr) {
+ *error = KM_ERROR_MEMORY_ALLOCATION_FAILED;
+ return nullptr;
+ }
+ if (!ecdh_key.InternalToEvp(pkey.get())) {
+ *error = KM_ERROR_UNKNOWN_ERROR;
+ return nullptr;
+ }
+
+ *error = KM_ERROR_OK;
+ auto op = new (std::nothrow)
+ EcdhOperation(move(key.hw_enforced_move()), move(key.sw_enforced_move()), pkey.release());
+ if (!op) {
+ *error = KM_ERROR_MEMORY_ALLOCATION_FAILED;
+ return nullptr;
+ }
+ return OperationPtr(op);
+}
+
+} // namespace keymaster
diff --git a/km_openssl/ecdsa_operation.cpp b/km_openssl/ecdsa_operation.cpp
index e4cac5a..b840bb0 100644
--- a/km_openssl/ecdsa_operation.cpp
+++ b/km_openssl/ecdsa_operation.cpp
@@ -56,8 +56,7 @@
}
EcdsaOperation::~EcdsaOperation() {
- if (ecdsa_key_ != nullptr)
- EVP_PKEY_free(ecdsa_key_);
+ if (ecdsa_key_ != nullptr) EVP_PKEY_free(ecdsa_key_);
EVP_MD_CTX_cleanup(&digest_ctx_);
}
@@ -109,11 +108,9 @@
if (rc != KM_ERROR_OK) return rc;
keymaster_error_t error = InitDigest();
- if (error != KM_ERROR_OK)
- return error;
+ if (error != KM_ERROR_OK) return error;
- if (digest_ == KM_DIGEST_NONE)
- return KM_ERROR_OK;
+ if (digest_ == KM_DIGEST_NONE) return KM_ERROR_OK;
EVP_PKEY_CTX* pkey_ctx;
if (EVP_DigestSignInit(&digest_ctx_, &pkey_ctx, digest_algorithm_, nullptr /* engine */,
@@ -126,8 +123,7 @@
const Buffer& input,
AuthorizationSet* /* output_params */,
Buffer* /* output */, size_t* input_consumed) {
- if (digest_ == KM_DIGEST_NONE)
- return StoreData(input, input_consumed);
+ if (digest_ == KM_DIGEST_NONE) return StoreData(input, input_consumed);
if (EVP_DigestSignUpdate(&digest_ctx_, input.peek_read(), input.available_read()) != 1)
return TranslateLastOpenSslError();
@@ -139,18 +135,15 @@
const Buffer& input, const Buffer& /* signature */,
AuthorizationSet* /* output_params */,
Buffer* output) {
- if (!output)
- return KM_ERROR_OUTPUT_PARAMETER_NULL;
+ if (!output) return KM_ERROR_OUTPUT_PARAMETER_NULL;
keymaster_error_t error = UpdateForFinish(additional_params, input);
- if (error != KM_ERROR_OK)
- return error;
+ if (error != KM_ERROR_OK) return error;
size_t siglen;
if (digest_ == KM_DIGEST_NONE) {
UniquePtr<EC_KEY, EC_KEY_Delete> ecdsa(EVP_PKEY_get1_EC_KEY(ecdsa_key_));
- if (!ecdsa.get())
- return TranslateLastOpenSslError();
+ if (!ecdsa.get()) return TranslateLastOpenSslError();
output->Reinitialize(ECDSA_size(ecdsa.get()));
unsigned int siglen_tmp;
@@ -161,13 +154,11 @@
} else {
if (EVP_DigestSignFinal(&digest_ctx_, nullptr /* signature */, &siglen) != 1)
return TranslateLastOpenSslError();
- if (!output->Reinitialize(siglen))
- return KM_ERROR_MEMORY_ALLOCATION_FAILED;
+ if (!output->Reinitialize(siglen)) return KM_ERROR_MEMORY_ALLOCATION_FAILED;
if (EVP_DigestSignFinal(&digest_ctx_, output->peek_write(), &siglen) <= 0)
return TranslateLastOpenSslError();
}
- if (!output->advance_write(siglen))
- return KM_ERROR_UNKNOWN_ERROR;
+ if (!output->advance_write(siglen)) return KM_ERROR_UNKNOWN_ERROR;
return KM_ERROR_OK;
}
@@ -178,11 +169,9 @@
if (rc != KM_ERROR_OK) return rc;
keymaster_error_t error = InitDigest();
- if (error != KM_ERROR_OK)
- return error;
+ if (error != KM_ERROR_OK) return error;
- if (digest_ == KM_DIGEST_NONE)
- return KM_ERROR_OK;
+ if (digest_ == KM_DIGEST_NONE) return KM_ERROR_OK;
EVP_PKEY_CTX* pkey_ctx;
if (EVP_DigestVerifyInit(&digest_ctx_, &pkey_ctx, digest_algorithm_, nullptr /* engine */,
@@ -195,8 +184,7 @@
const Buffer& input,
AuthorizationSet* /* output_params */,
Buffer* /* output */, size_t* input_consumed) {
- if (digest_ == KM_DIGEST_NONE)
- return StoreData(input, input_consumed);
+ if (digest_ == KM_DIGEST_NONE) return StoreData(input, input_consumed);
if (EVP_DigestVerifyUpdate(&digest_ctx_, input.peek_read(), input.available_read()) != 1)
return TranslateLastOpenSslError();
@@ -209,13 +197,11 @@
AuthorizationSet* /* output_params */,
Buffer* /* output */) {
keymaster_error_t error = UpdateForFinish(additional_params, input);
- if (error != KM_ERROR_OK)
- return error;
+ if (error != KM_ERROR_OK) return error;
if (digest_ == KM_DIGEST_NONE) {
UniquePtr<EC_KEY, EC_KEY_Delete> ecdsa(EVP_PKEY_get1_EC_KEY(ecdsa_key_));
- if (!ecdsa.get())
- return TranslateLastOpenSslError();
+ if (!ecdsa.get()) return TranslateLastOpenSslError();
int result =
ECDSA_verify(0 /* type -- ignored */, data_.peek_read(), data_.available_read(),
diff --git a/km_openssl/ecies_kem.cpp b/km_openssl/ecies_kem.cpp
index 91f6912..6c5b15d 100644
--- a/km_openssl/ecies_kem.cpp
+++ b/km_openssl/ecies_kem.cpp
@@ -50,7 +50,7 @@
}
switch (kdf) {
case KM_KDF_RFC5869_SHA256:
- kdf_.reset(new(std::nothrow) Rfc5869Sha256Kdf());
+ kdf_.reset(new (std::nothrow) Rfc5869Sha256Kdf());
break;
default:
LOG_E("Kdf %d is unsupported", kdf);
@@ -136,7 +136,7 @@
Buffer* output_key) {
keymaster_error_t error;
- key_exchange_.reset(new(std::nothrow) NistCurveKeyExchange(private_key, &error));
+ key_exchange_.reset(new (std::nothrow) NistCurveKeyExchange(private_key, &error));
if (!key_exchange_.get() || error != KM_ERROR_OK) {
return false;
}
diff --git a/km_openssl/hkdf.cpp b/km_openssl/hkdf.cpp
index 7ac49b9..8bd466a 100644
--- a/km_openssl/hkdf.cpp
+++ b/km_openssl/hkdf.cpp
@@ -18,14 +18,12 @@
#include <keymaster/android_keymaster_utils.h>
#include <keymaster/km_openssl/hmac.h>
-#include <keymaster/new.h>
namespace keymaster {
bool Rfc5869Sha256Kdf::GenerateKey(const uint8_t* info, size_t info_len, uint8_t* output,
size_t output_len) {
- if (!is_initialized_ || output == nullptr)
- return false;
+ if (!is_initialized_ || output == nullptr) return false;
/**
* Step 1. Extract: PRK = HMAC-SHA256(actual_salt, secret)
* https://tools.ietf.org/html/rfc5869#section-2.2
@@ -35,40 +33,33 @@
if (salt_.get() != nullptr && salt_len_ > 0) {
result = prk_hmac.Init(salt_.get(), salt_len_);
} else {
- UniquePtr<uint8_t[]> zeros(new(std::nothrow) uint8_t[digest_size_]);
- if (zeros.get() == nullptr)
- return false;
+ UniquePtr<uint8_t[]> zeros(new (std::nothrow) uint8_t[digest_size_]);
+ if (zeros.get() == nullptr) return false;
/* If salt is not given, digest size of zeros are used. */
memset(zeros.get(), 0, digest_size_);
result = prk_hmac.Init(zeros.get(), digest_size_);
}
- if (!result)
- return false;
+ if (!result) return false;
- UniquePtr<uint8_t[]> pseudo_random_key(new(std::nothrow) uint8_t[digest_size_]);
- if (pseudo_random_key.get() == nullptr || digest_size_ != prk_hmac.DigestLength())
- return false;
+ UniquePtr<uint8_t[]> pseudo_random_key(new (std::nothrow) uint8_t[digest_size_]);
+ if (pseudo_random_key.get() == nullptr || digest_size_ != prk_hmac.DigestLength()) return false;
result =
prk_hmac.Sign(secret_key_.get(), secret_key_len_, pseudo_random_key.get(), digest_size_);
- if (!result)
- return false;
+ if (!result) return false;
/**
* Step 2. Expand: OUTPUT = HKDF-Expand(PRK, info)
* https://tools.ietf.org/html/rfc5869#section-2.3
*/
const size_t num_blocks = (output_len + digest_size_ - 1) / digest_size_;
- if (num_blocks >= 256u)
- return false;
+ if (num_blocks >= 256u) return false;
- UniquePtr<uint8_t[]> buf(new(std::nothrow) uint8_t[digest_size_ + info_len + 1]);
- UniquePtr<uint8_t[]> digest(new(std::nothrow) uint8_t[digest_size_]);
- if (buf.get() == nullptr || digest.get() == nullptr)
- return false;
+ UniquePtr<uint8_t[]> buf(new (std::nothrow) uint8_t[digest_size_ + info_len + 1]);
+ UniquePtr<uint8_t[]> digest(new (std::nothrow) uint8_t[digest_size_]);
+ if (buf.get() == nullptr || digest.get() == nullptr) return false;
HmacSha256 hmac;
result = hmac.Init(pseudo_random_key.get(), digest_size_);
- if (!result)
- return false;
+ if (!result) return false;
for (size_t i = 0; i < num_blocks; i++) {
size_t block_input_len = 0;
@@ -76,13 +67,11 @@
memcpy(buf.get(), digest.get(), digest_size_);
block_input_len = digest_size_;
}
- if (info != nullptr && info_len > 0)
- memcpy(buf.get() + block_input_len, info, info_len);
+ if (info != nullptr && info_len > 0) memcpy(buf.get() + block_input_len, info, info_len);
block_input_len += info_len;
*(buf.get() + block_input_len++) = static_cast<uint8_t>(i + 1);
result = hmac.Sign(buf.get(), block_input_len, digest.get(), digest_size_);
- if (!result)
- return false;
+ if (!result) return false;
size_t block_output_len = digest_size_ < output_len - i * digest_size_
? digest_size_
: output_len - i * digest_size_;
diff --git a/km_openssl/hmac.cpp b/km_openssl/hmac.cpp
index e39f671..cb788d0 100644
--- a/km_openssl/hmac.cpp
+++ b/km_openssl/hmac.cpp
@@ -36,8 +36,7 @@
}
bool HmacSha256::Init(const uint8_t* key, size_t key_len) {
- if (!key)
- return false;
+ if (!key) return false;
key_len_ = key_len;
key_.reset(dup_buffer(key, key_len));
@@ -57,14 +56,12 @@
uint8_t tmp[SHA256_DIGEST_LENGTH];
uint8_t* digest = tmp;
- if (digest_len >= SHA256_DIGEST_LENGTH)
- digest = out_digest;
+ if (digest_len >= SHA256_DIGEST_LENGTH) digest = out_digest;
if (nullptr == ::HMAC(EVP_sha256(), key_.get(), key_len_, data, data_len, digest, nullptr)) {
return false;
}
- if (digest_len < SHA256_DIGEST_LENGTH)
- memcpy(out_digest, tmp, digest_len);
+ if (digest_len < SHA256_DIGEST_LENGTH) memcpy(out_digest, tmp, digest_len);
return true;
}
@@ -76,12 +73,10 @@
bool HmacSha256::Verify(const uint8_t* data, size_t data_len, const uint8_t* digest,
size_t digest_len) const {
- if (digest_len != SHA256_DIGEST_LENGTH)
- return false;
+ if (digest_len != SHA256_DIGEST_LENGTH) return false;
uint8_t computed_digest[SHA256_DIGEST_LENGTH];
- if (!Sign(data, data_len, computed_digest, sizeof(computed_digest)))
- return false;
+ if (!Sign(data, data_len, computed_digest, sizeof(computed_digest))) return false;
return 0 == CRYPTO_memcmp(digest, computed_digest, SHA256_DIGEST_LENGTH);
}
diff --git a/km_openssl/hmac_key.cpp b/km_openssl/hmac_key.cpp
index b2757b6..d74ff37 100644
--- a/km_openssl/hmac_key.cpp
+++ b/km_openssl/hmac_key.cpp
@@ -16,8 +16,6 @@
#include <keymaster/km_openssl/hmac_key.h>
-#include <keymaster/new.h>
-
#include <openssl/err.h>
#include <openssl/rand.h>
@@ -44,8 +42,7 @@
AuthorizationSet&& hw_enforced,
AuthorizationSet&& sw_enforced,
UniquePtr<Key>* key) const {
- if (!key)
- return KM_ERROR_OUTPUT_PARAMETER_NULL;
+ if (!key) return KM_ERROR_OUTPUT_PARAMETER_NULL;
uint32_t min_mac_length;
if (!hw_enforced.GetTagValue(TAG_MIN_MAC_LENGTH, &min_mac_length) &&
@@ -54,10 +51,9 @@
return KM_ERROR_INVALID_KEY_BLOB;
}
- key->reset(new (std::nothrow) HmacKey(move(key_material), move(hw_enforced), move(sw_enforced),
- this));
- if (!key->get())
- return KM_ERROR_MEMORY_ALLOCATION_FAILED;
+ key->reset(new (std::nothrow)
+ HmacKey(move(key_material), move(hw_enforced), move(sw_enforced), this));
+ if (!key->get()) return KM_ERROR_MEMORY_ALLOCATION_FAILED;
return KM_ERROR_OK;
}
@@ -105,8 +101,7 @@
if (min_mac_length_bits % 8 != 0 || min_mac_length_bits > hash_size_bits)
return KM_ERROR_UNSUPPORTED_MIN_MAC_LENGTH;
- if (min_mac_length_bits < kMinHmacLengthBits)
- return KM_ERROR_UNSUPPORTED_MIN_MAC_LENGTH;
+ if (min_mac_length_bits < kMinHmacLengthBits) return KM_ERROR_UNSUPPORTED_MIN_MAC_LENGTH;
return KM_ERROR_OK;
}
diff --git a/km_openssl/hmac_operation.cpp b/km_openssl/hmac_operation.cpp
index ce80cfc..759ca12 100644
--- a/km_openssl/hmac_operation.cpp
+++ b/km_openssl/hmac_operation.cpp
@@ -16,8 +16,6 @@
#include "hmac_operation.h"
-#include <keymaster/new.h>
-
#include <openssl/evp.h>
#include <openssl/hmac.h>
@@ -50,6 +48,11 @@
*error = KM_ERROR_INVALID_ARGUMENT;
return nullptr;
}
+ if ((mac_length_bits % 8) != 0) {
+ LOG_E("MAC length must be a multiple of 8", mac_length_bits);
+ *error = KM_ERROR_UNSUPPORTED_MAC_LENGTH;
+ return nullptr;
+ }
} else {
if (purpose() == KM_PURPOSE_SIGN) {
*error = KM_ERROR_MISSING_MAC_LENGTH;
diff --git a/km_openssl/kdf.cpp b/km_openssl/kdf.cpp
index e4ed135..ad0b68a 100644
--- a/km_openssl/kdf.cpp
+++ b/km_openssl/kdf.cpp
@@ -37,19 +37,16 @@
return false;
}
- if (!secret || secret_len == 0)
- return false;
+ if (!secret || secret_len == 0) return false;
secret_key_len_ = secret_len;
secret_key_.reset(dup_buffer(secret, secret_len));
- if (!secret_key_.get())
- return false;
+ if (!secret_key_.get()) return false;
salt_len_ = salt_len;
if (salt && salt_len > 0) {
salt_.reset(dup_buffer(salt, salt_len));
- if (!salt_.get())
- return false;
+ if (!salt_.get()) return false;
} else {
salt_.reset();
}
@@ -59,8 +56,7 @@
}
bool Kdf::Uint32ToBigEndianByteArray(uint32_t number, uint8_t* output) {
- if (!output)
- return false;
+ if (!output) return false;
output[0] = (number >> 24) & 0xff;
output[1] = (number >> 16) & 0xff;
diff --git a/km_openssl/openssl_err.cpp b/km_openssl/openssl_err.cpp
index 1391f40..73d1ad0 100644
--- a/km_openssl/openssl_err.cpp
+++ b/km_openssl/openssl_err.cpp
@@ -41,10 +41,12 @@
#endif
keymaster_error_t TranslateLastOpenSslError(bool log_message) {
- unsigned long error = ERR_peek_last_error();
+ uint32_t error = ERR_peek_last_error();
if (log_message) {
- LOG_D("%s", ERR_error_string(error, nullptr));
+ char buf[128];
+ ERR_error_string_n(error, buf, sizeof(buf));
+ LOG_D("%s", buf);
}
int reason = ERR_GET_REASON(error);
diff --git a/km_openssl/openssl_utils.cpp b/km_openssl/openssl_utils.cpp
index 06cfafa..a0c0300 100644
--- a/km_openssl/openssl_utils.cpp
+++ b/km_openssl/openssl_utils.cpp
@@ -16,13 +16,15 @@
#include <keymaster/km_openssl/openssl_utils.h>
-#include <openssl/rand.h>
#include <keymaster/android_keymaster_utils.h>
+#include <openssl/rand.h>
#include <keymaster/km_openssl/openssl_err.h>
namespace keymaster {
+constexpr uint32_t kAffinePointLength = 32;
+
keymaster_error_t ec_get_group_size(const EC_GROUP* group, size_t* key_size_bits) {
switch (EC_GROUP_get_curve_name(group)) {
case NID_secp224r1:
@@ -77,17 +79,14 @@
keymaster_error_t convert_pkcs8_blob_to_evp(const uint8_t* key_data, size_t key_length,
keymaster_algorithm_t expected_algorithm,
UniquePtr<EVP_PKEY, EVP_PKEY_Delete>* pkey) {
- if (key_data == nullptr || key_length <= 0)
- return KM_ERROR_INVALID_KEY_BLOB;
+ if (key_data == nullptr || key_length <= 0) return KM_ERROR_INVALID_KEY_BLOB;
UniquePtr<PKCS8_PRIV_KEY_INFO, PKCS8_PRIV_KEY_INFO_Delete> pkcs8(
d2i_PKCS8_PRIV_KEY_INFO(nullptr, &key_data, key_length));
- if (pkcs8.get() == nullptr)
- return TranslateLastOpenSslError(true /* log_message */);
+ if (pkcs8.get() == nullptr) return TranslateLastOpenSslError(true /* log_message */);
pkey->reset(EVP_PKCS82PKEY(pkcs8.get()));
- if (!pkey->get())
- return TranslateLastOpenSslError(true /* log_message */);
+ if (!pkey->get()) return TranslateLastOpenSslError(true /* log_message */);
if (EVP_PKEY_type((*pkey)->type) != convert_to_evp(expected_algorithm)) {
LOG_E("EVP key algorithm was %d, not the expected %d", EVP_PKEY_type((*pkey)->type),
@@ -101,9 +100,8 @@
keymaster_error_t KeyMaterialToEvpKey(keymaster_key_format_t key_format,
const KeymasterKeyBlob& key_material,
keymaster_algorithm_t expected_algorithm,
- UniquePtr<EVP_PKEY, EVP_PKEY_Delete>* pkey) {
- if (key_format != KM_KEY_FORMAT_PKCS8)
- return KM_ERROR_UNSUPPORTED_KEY_FORMAT;
+ EVP_PKEY_Ptr* pkey) {
+ if (key_format != KM_KEY_FORMAT_PKCS8) return KM_ERROR_UNSUPPORTED_KEY_FORMAT;
return convert_pkcs8_blob_to_evp(key_material.key_material, key_material.key_material_size,
expected_algorithm, pkey);
@@ -111,11 +109,9 @@
keymaster_error_t EvpKeyToKeyMaterial(const EVP_PKEY* pkey, KeymasterKeyBlob* key_blob) {
int key_data_size = i2d_PrivateKey(pkey, nullptr /* key_data*/);
- if (key_data_size <= 0)
- return TranslateLastOpenSslError();
+ if (key_data_size <= 0) return TranslateLastOpenSslError();
- if (!key_blob->Reset(key_data_size))
- return KM_ERROR_MEMORY_ALLOCATION_FAILED;
+ if (!key_blob->Reset(key_data_size)) return KM_ERROR_MEMORY_ALLOCATION_FAILED;
uint8_t* tmp = key_blob->writable_data();
i2d_PrivateKey(pkey, &tmp);
@@ -123,6 +119,43 @@
return KM_ERROR_OK;
}
+// Remote provisioning helper function
+keymaster_error_t GetEcdsa256KeyFromCert(const keymaster_blob_t* km_cert, uint8_t* x_coord,
+ size_t x_length, uint8_t* y_coord, size_t y_length) {
+ if (km_cert == nullptr || x_coord == nullptr || y_coord == nullptr) {
+ return KM_ERROR_UNEXPECTED_NULL_POINTER;
+ }
+ if (x_length != kAffinePointLength || y_length != kAffinePointLength) {
+ return KM_ERROR_INVALID_ARGUMENT;
+ }
+ const uint8_t* temp = km_cert->data;
+ X509_Ptr cert(d2i_X509(NULL, &temp, km_cert->data_length));
+ if (!cert.get()) return TranslateLastOpenSslError();
+ EVP_PKEY_Ptr pubKey(X509_get_pubkey(cert.get()));
+ if (!pubKey.get()) return TranslateLastOpenSslError();
+ EC_KEY* ecKey = EVP_PKEY_get0_EC_KEY(pubKey.get());
+ if (!ecKey) return TranslateLastOpenSslError();
+ const EC_POINT* jacobian_coords = EC_KEY_get0_public_key(ecKey);
+ if (!jacobian_coords) return TranslateLastOpenSslError();
+ bssl::UniquePtr<BIGNUM> x(BN_new());
+ bssl::UniquePtr<BIGNUM> y(BN_new());
+ BN_CTX_Ptr ctx(BN_CTX_new());
+ if (!ctx.get()) return TranslateLastOpenSslError();
+ if (!EC_POINT_get_affine_coordinates_GFp(EC_KEY_get0_group(ecKey), jacobian_coords, x.get(),
+ y.get(), ctx.get())) {
+ return TranslateLastOpenSslError();
+ }
+ uint8_t* tmp_x = x_coord;
+ if (BN_bn2binpad(x.get(), tmp_x, kAffinePointLength) != kAffinePointLength) {
+ return TranslateLastOpenSslError();
+ }
+ uint8_t* tmp_y = y_coord;
+ if (BN_bn2binpad(y.get(), tmp_y, kAffinePointLength) != kAffinePointLength) {
+ return TranslateLastOpenSslError();
+ }
+ 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());
@@ -135,8 +168,7 @@
}
keymaster_error_t GenerateRandom(uint8_t* buf, size_t length) {
- if (RAND_bytes(buf, length) != 1)
- return KM_ERROR_UNKNOWN_ERROR;
+ if (RAND_bytes(buf, length) != 1) return KM_ERROR_UNKNOWN_ERROR;
return KM_ERROR_OK;
}
diff --git a/km_openssl/rsa_key.cpp b/km_openssl/rsa_key.cpp
index 8b5b6ae..154fe1b 100644
--- a/km_openssl/rsa_key.cpp
+++ b/km_openssl/rsa_key.cpp
@@ -34,6 +34,9 @@
bool RsaKey::SupportedMode(keymaster_purpose_t purpose, keymaster_padding_t padding) {
switch (purpose) {
+ case KM_PURPOSE_ATTEST_KEY:
+ return true;
+
case KM_PURPOSE_SIGN:
case KM_PURPOSE_VERIFY:
return padding == KM_PAD_NONE || padding == KM_PAD_RSA_PSS ||
@@ -45,6 +48,7 @@
return padding == KM_PAD_RSA_OAEP || padding == KM_PAD_RSA_PKCS1_1_5_ENCRYPT;
case KM_PURPOSE_DERIVE_KEY:
+ case KM_PURPOSE_AGREE_KEY:
return false;
};
return false;
@@ -52,6 +56,9 @@
bool RsaKey::SupportedMode(keymaster_purpose_t purpose, keymaster_digest_t digest) {
switch (purpose) {
+ case KM_PURPOSE_ATTEST_KEY:
+ return true;
+
case KM_PURPOSE_SIGN:
case KM_PURPOSE_VERIFY:
return digest == KM_DIGEST_NONE || digest == KM_DIGEST_SHA_2_256;
@@ -63,6 +70,7 @@
break;
case KM_PURPOSE_DERIVE_KEY:
+ case KM_PURPOSE_AGREE_KEY:
return false;
};
return true;
diff --git a/km_openssl/rsa_key_factory.cpp b/km_openssl/rsa_key_factory.cpp
index 05029bb..114fdab 100644
--- a/km_openssl/rsa_key_factory.cpp
+++ b/km_openssl/rsa_key_factory.cpp
@@ -21,7 +21,6 @@
#include <keymaster/km_openssl/openssl_utils.h>
#include <keymaster/km_openssl/rsa_key.h>
#include <keymaster/km_openssl/rsa_operation.h>
-#include <keymaster/new.h>
namespace keymaster {
@@ -50,16 +49,16 @@
}
keymaster_error_t RsaKeyFactory::GenerateKey(const AuthorizationSet& key_description,
+ UniquePtr<Key> attest_key, //
+ const KeymasterBlob& issuer_subject,
KeymasterKeyBlob* key_blob,
AuthorizationSet* hw_enforced,
- AuthorizationSet* sw_enforced) const {
- if (!key_blob || !hw_enforced || !sw_enforced)
- return KM_ERROR_OUTPUT_PARAMETER_NULL;
-
- const AuthorizationSet& authorizations(key_description);
+ AuthorizationSet* sw_enforced,
+ CertificateChain* cert_chain) const {
+ if (!key_blob || !hw_enforced || !sw_enforced) return KM_ERROR_OUTPUT_PARAMETER_NULL;
uint64_t public_exponent;
- if (!authorizations.GetTagValue(TAG_RSA_PUBLIC_EXPONENT, &public_exponent)) {
+ if (!key_description.GetTagValue(TAG_RSA_PUBLIC_EXPONENT, &public_exponent)) {
LOG_E("No public exponent specified for RSA key generation", 0);
return KM_ERROR_INVALID_ARGUMENT;
}
@@ -69,7 +68,7 @@
}
uint32_t key_size;
- if (!authorizations.GetTagValue(TAG_KEY_SIZE, &key_size)) {
+ if (!key_description.GetTagValue(TAG_KEY_SIZE, &key_size)) {
LOG_E("No key size specified for RSA key generation", 0);
return KM_ERROR_UNSUPPORTED_KEY_SIZE;
}
@@ -78,36 +77,56 @@
return KM_ERROR_UNSUPPORTED_KEY_SIZE;
}
- UniquePtr<BIGNUM, BIGNUM_Delete> exponent(BN_new());
- UniquePtr<RSA, RsaKey::RSA_Delete> rsa_key(RSA_new());
- UniquePtr<EVP_PKEY, EVP_PKEY_Delete> pkey(EVP_PKEY_new());
- if (exponent.get() == nullptr || rsa_key.get() == nullptr || pkey.get() == nullptr)
+ BIGNUM_Ptr exponent(BN_new());
+ RSA_Ptr rsa_key(RSA_new());
+ EVP_PKEY_Ptr pkey(EVP_PKEY_new());
+ if (exponent.get() == nullptr || rsa_key.get() == nullptr || pkey.get() == nullptr) {
return KM_ERROR_MEMORY_ALLOCATION_FAILED;
+ }
if (!BN_set_word(exponent.get(), public_exponent) ||
!RSA_generate_key_ex(rsa_key.get(), key_size, exponent.get(), nullptr /* callback */))
return TranslateLastOpenSslError();
- if (EVP_PKEY_set1_RSA(pkey.get(), rsa_key.get()) != 1)
- return TranslateLastOpenSslError();
+ if (EVP_PKEY_set1_RSA(pkey.get(), rsa_key.get()) != 1) return TranslateLastOpenSslError();
KeymasterKeyBlob key_material;
keymaster_error_t error = EvpKeyToKeyMaterial(pkey.get(), &key_material);
- if (error != KM_ERROR_OK)
- return error;
+ if (error != KM_ERROR_OK) return error;
- return blob_maker_.CreateKeyBlob(authorizations, KM_ORIGIN_GENERATED, key_material, key_blob,
- hw_enforced, sw_enforced);
+ error = blob_maker_.CreateKeyBlob(key_description, KM_ORIGIN_GENERATED, key_material, key_blob,
+ hw_enforced, sw_enforced);
+ if (error != KM_ERROR_OK) return error;
+
+ if (context_.GetKmVersion() < KmVersion::KEYMINT_1) return KM_ERROR_OK;
+ if (!cert_chain) return KM_ERROR_UNEXPECTED_NULL_POINTER;
+
+ RsaKey key(*hw_enforced, *sw_enforced, this, move(rsa_key));
+ if (key_description.Contains(TAG_ATTESTATION_CHALLENGE)) {
+ *cert_chain = context_.GenerateAttestation(key, key_description, move(attest_key),
+ issuer_subject, &error);
+ } else if (attest_key.get() != nullptr) {
+ return KM_ERROR_ATTESTATION_CHALLENGE_MISSING;
+ } else {
+ bool fake_signature =
+ key_size < 1024 || !key_description.Contains(TAG_PURPOSE, KM_PURPOSE_SIGN);
+ *cert_chain =
+ context_.GenerateSelfSignedCertificate(key, key_description, fake_signature, &error);
+ }
+
+ return error;
}
-keymaster_error_t RsaKeyFactory::ImportKey(const AuthorizationSet& key_description,
+keymaster_error_t RsaKeyFactory::ImportKey(const AuthorizationSet& key_description, //
keymaster_key_format_t input_key_material_format,
const KeymasterKeyBlob& input_key_material,
+ UniquePtr<Key> attest_key, //
+ const KeymasterBlob& issuer_subject,
KeymasterKeyBlob* output_key_blob,
AuthorizationSet* hw_enforced,
- AuthorizationSet* sw_enforced) const {
- if (!output_key_blob || !hw_enforced || !sw_enforced)
- return KM_ERROR_OUTPUT_PARAMETER_NULL;
+ AuthorizationSet* sw_enforced,
+ CertificateChain* cert_chain) const {
+ if (!output_key_blob || !hw_enforced || !sw_enforced) return KM_ERROR_OUTPUT_PARAMETER_NULL;
AuthorizationSet authorizations;
uint64_t public_exponent;
@@ -115,10 +134,35 @@
keymaster_error_t error =
UpdateImportKeyDescription(key_description, input_key_material_format, input_key_material,
&authorizations, &public_exponent, &key_size);
- if (error != KM_ERROR_OK)
- return error;
- return blob_maker_.CreateKeyBlob(authorizations, KM_ORIGIN_IMPORTED, input_key_material,
- output_key_blob, hw_enforced, sw_enforced);
+ if (error != KM_ERROR_OK) return error;
+ error = blob_maker_.CreateKeyBlob(authorizations, KM_ORIGIN_IMPORTED, input_key_material,
+ output_key_blob, hw_enforced, sw_enforced);
+ if (error != KM_ERROR_OK) return error;
+
+ if (context_.GetKmVersion() < KmVersion::KEYMINT_1) return KM_ERROR_OK;
+ if (!cert_chain) return KM_ERROR_UNEXPECTED_NULL_POINTER;
+
+ EVP_PKEY_Ptr pkey;
+ error = KeyMaterialToEvpKey(KM_KEY_FORMAT_PKCS8, input_key_material, KM_ALGORITHM_RSA, &pkey);
+ if (error != KM_ERROR_OK) return error;
+
+ RSA_Ptr rsa_key(EVP_PKEY_get1_RSA(pkey.get()));
+ if (!rsa_key.get()) return KM_ERROR_INVALID_ARGUMENT;
+
+ RsaKey key(*hw_enforced, *sw_enforced, this, move(rsa_key));
+ if (key_description.Contains(KM_TAG_ATTESTATION_CHALLENGE)) {
+ *cert_chain = context_.GenerateAttestation(key, key_description, move(attest_key),
+ issuer_subject, &error);
+ } else if (attest_key.get() != nullptr) {
+ return KM_ERROR_ATTESTATION_CHALLENGE_MISSING;
+ } else {
+ bool fake_signature =
+ key_size < 1024 || !key_description.Contains(TAG_PURPOSE, KM_PURPOSE_SIGN);
+ *cert_chain =
+ context_.GenerateSelfSignedCertificate(key, key_description, fake_signature, &error);
+ }
+
+ return error;
}
keymaster_error_t RsaKeyFactory::UpdateImportKeyDescription(const AuthorizationSet& key_description,
@@ -130,21 +174,18 @@
if (!updated_description || !public_exponent || !key_size)
return KM_ERROR_OUTPUT_PARAMETER_NULL;
- UniquePtr<EVP_PKEY, EVP_PKEY_Delete> pkey;
+ EVP_PKEY_Ptr pkey;
keymaster_error_t error =
KeyMaterialToEvpKey(key_format, key_material, keymaster_key_type(), &pkey);
- if (error != KM_ERROR_OK)
- return error;
+ if (error != KM_ERROR_OK) return error;
- UniquePtr<RSA, RsaKey::RSA_Delete> rsa_key(EVP_PKEY_get1_RSA(pkey.get()));
- if (!rsa_key.get())
- return TranslateLastOpenSslError();
+ RSA_Ptr rsa_key(EVP_PKEY_get1_RSA(pkey.get()));
+ if (!rsa_key.get()) return TranslateLastOpenSslError();
updated_description->Reinitialize(key_description);
*public_exponent = BN_get_word(rsa_key->e);
- if (*public_exponent == 0xffffffffL)
- return KM_ERROR_INVALID_KEY_BLOB;
+ if (*public_exponent == 0xffffffffL) return KM_ERROR_INVALID_KEY_BLOB;
if (!updated_description->GetTagValue(TAG_RSA_PUBLIC_EXPONENT, public_exponent))
updated_description->push_back(TAG_RSA_PUBLIC_EXPONENT, *public_exponent);
if (*public_exponent != BN_get_word(rsa_key->e)) {
@@ -165,8 +206,7 @@
keymaster_algorithm_t algorithm = KM_ALGORITHM_RSA;
if (!updated_description->GetTagValue(TAG_ALGORITHM, &algorithm))
updated_description->push_back(TAG_ALGORITHM, KM_ALGORITHM_RSA);
- if (algorithm != KM_ALGORITHM_RSA)
- return KM_ERROR_IMPORT_PARAMETER_MISMATCH;
+ if (algorithm != KM_ALGORITHM_RSA) return KM_ERROR_IMPORT_PARAMETER_MISMATCH;
return KM_ERROR_OK;
}
diff --git a/km_openssl/rsa_operation.cpp b/km_openssl/rsa_operation.cpp
index 3e3e082..313afe9 100644
--- a/km_openssl/rsa_operation.cpp
+++ b/km_openssl/rsa_operation.cpp
@@ -24,7 +24,6 @@
#include <keymaster/km_openssl/openssl_utils.h>
#include <keymaster/km_openssl/rsa_key.h>
#include <keymaster/logger.h>
-#include <keymaster/new.h>
namespace keymaster {
@@ -35,8 +34,8 @@
const size_t kPkcs1UndigestedSignaturePaddingOverhead = 11;
/* static */
-EVP_PKEY* RsaOperationFactory::GetRsaKey(Key&& key, keymaster_error_t* error) {
- const RsaKey& rsa_key = static_cast<RsaKey&>(key);
+EVP_PKEY* RsaOperationFactory::GetRsaKey(const Key& key, keymaster_error_t* error) {
+ const RsaKey& rsa_key = static_cast<const RsaKey&>(key);
if (!rsa_key.key()) {
*error = KM_ERROR_UNKNOWN_ERROR;
return nullptr;
@@ -74,7 +73,7 @@
return nullptr;
}
- UniquePtr<EVP_PKEY, EVP_PKEY_Delete> rsa(GetRsaKey(move(key), error));
+ UniquePtr<EVP_PKEY, EVP_PKEY_Delete> rsa(GetRsaKey(key, error));
if (!rsa.get()) return nullptr;
RsaOperation* op = InstantiateOperation(key.hw_enforced_move(), key.sw_enforced_move(), digest,
@@ -94,6 +93,10 @@
RsaOperation* RsaCryptingOperationFactory::CreateRsaOperation(Key&& key,
const AuthorizationSet& begin_params,
keymaster_error_t* error) {
+ keymaster_digest_t mgf_digest = KM_DIGEST_NONE;
+ key.authorizations().GetTagValue(TAG_RSA_OAEP_MGF_DIGEST, &mgf_digest);
+ *error = GetAndValidateMgfDigest(begin_params, key, &mgf_digest);
+ if (*error != KM_ERROR_OK) return nullptr;
UniquePtr<RsaOperation> op(
RsaOperationFactory::CreateRsaOperation(move(key), begin_params, error));
if (op.get()) {
@@ -111,6 +114,7 @@
*error = KM_ERROR_INCOMPATIBLE_DIGEST;
return nullptr;
}
+ static_cast<RsaCryptOperation*>(op.get())->setOaepMgfDigest(mgf_digest);
break;
default:
@@ -121,6 +125,35 @@
return op.release();
}
+keymaster_error_t RsaCryptingOperationFactory::GetAndValidateMgfDigest(
+ const AuthorizationSet& begin_params, const Key& key, keymaster_digest_t* digest) const {
+ *digest = KM_DIGEST_SHA1;
+ if (!begin_params.Contains(TAG_PADDING, KM_PAD_RSA_OAEP)) {
+ *digest = KM_DIGEST_NONE;
+ return KM_ERROR_OK;
+ }
+ // If begin params does not specify any mgf digest
+ if (!begin_params.GetTagValue(TAG_RSA_OAEP_MGF_DIGEST, digest)) {
+ // And the authorizations has MGF Digest tag specified.
+ if (key.authorizations().GetTagCount(TAG_RSA_OAEP_MGF_DIGEST) > 0) {
+ // And key authorizations does not contain SHA1 for Mgf digest.
+ if (!key.authorizations().Contains(TAG_RSA_OAEP_MGF_DIGEST, KM_DIGEST_SHA1)) {
+ // Then it is an error.
+ LOG_E("%d MGF digests specified in begin params and SHA1 not authorized",
+ begin_params.GetTagCount(TAG_RSA_OAEP_MGF_DIGEST));
+ return KM_ERROR_UNSUPPORTED_MGF_DIGEST;
+ }
+ }
+ } else if (!supported(*digest) || (*digest == KM_DIGEST_NONE)) {
+ LOG_E("MGF Digest %d not supported", *digest);
+ return KM_ERROR_UNSUPPORTED_MGF_DIGEST;
+ } else if (!key.authorizations().Contains(TAG_RSA_OAEP_MGF_DIGEST, *digest)) {
+ LOG_E("MGF Digest %d was specified, but not authorized by key", *digest);
+ return KM_ERROR_INCOMPATIBLE_MGF_DIGEST;
+ }
+ return KM_ERROR_OK;
+}
+
static const keymaster_padding_t supported_crypt_padding[] = {KM_PAD_NONE, KM_PAD_RSA_OAEP,
KM_PAD_RSA_PKCS1_1_5_ENCRYPT};
const keymaster_padding_t*
@@ -130,8 +163,7 @@
}
RsaOperation::~RsaOperation() {
- if (rsa_key_ != nullptr)
- EVP_PKEY_free(rsa_key_);
+ if (rsa_key_ != nullptr) EVP_PKEY_free(rsa_key_);
}
keymaster_error_t RsaOperation::Begin(const AuthorizationSet& /* input_params */,
@@ -161,8 +193,7 @@
keymaster_error_t RsaOperation::StoreData(const Buffer& input, size_t* input_consumed) {
assert(input_consumed);
- if (!data_.reserve(EVP_PKEY_size(rsa_key_)))
- return KM_ERROR_MEMORY_ALLOCATION_FAILED;
+ if (!data_.reserve(EVP_PKEY_size(rsa_key_))) 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 operate on %u bytes of data with %u-byte RSA key",
@@ -177,8 +208,7 @@
keymaster_error_t RsaOperation::SetRsaPaddingInEvpContext(EVP_PKEY_CTX* pkey_ctx, bool signing) {
keymaster_error_t error;
int openssl_padding = GetOpensslPadding(&error);
- if (error != KM_ERROR_OK)
- return error;
+ if (error != KM_ERROR_OK) return error;
if (EVP_PKEY_CTX_set_rsa_padding(pkey_ctx, openssl_padding) <= 0)
return TranslateLastOpenSslError();
@@ -196,35 +226,14 @@
keymaster_error_t RsaOperation::InitDigest() {
if (digest_ == KM_DIGEST_NONE) {
- if (require_digest())
- return KM_ERROR_INCOMPATIBLE_DIGEST;
+ if (require_digest()) return KM_ERROR_INCOMPATIBLE_DIGEST;
return KM_ERROR_OK;
}
-
- switch (digest_) {
- case KM_DIGEST_NONE:
- return KM_ERROR_OK;
- case KM_DIGEST_MD5:
- digest_algorithm_ = EVP_md5();
- return KM_ERROR_OK;
- case KM_DIGEST_SHA1:
- digest_algorithm_ = EVP_sha1();
- return KM_ERROR_OK;
- case KM_DIGEST_SHA_2_224:
- digest_algorithm_ = EVP_sha224();
- return KM_ERROR_OK;
- case KM_DIGEST_SHA_2_256:
- digest_algorithm_ = EVP_sha256();
- return KM_ERROR_OK;
- case KM_DIGEST_SHA_2_384:
- digest_algorithm_ = EVP_sha384();
- return KM_ERROR_OK;
- case KM_DIGEST_SHA_2_512:
- digest_algorithm_ = EVP_sha512();
- return KM_ERROR_OK;
- default:
+ digest_algorithm_ = KmDigestToEvpDigest(digest_);
+ if (digest_algorithm_ == nullptr) {
return KM_ERROR_UNSUPPORTED_DIGEST;
}
+ return KM_ERROR_OK;
}
RsaDigestingOperation::RsaDigestingOperation(AuthorizationSet&& hw_enforced,
@@ -266,11 +275,9 @@
keymaster_error_t RsaSignOperation::Begin(const AuthorizationSet& input_params,
AuthorizationSet* output_params) {
keymaster_error_t error = RsaDigestingOperation::Begin(input_params, output_params);
- if (error != KM_ERROR_OK)
- return error;
+ if (error != KM_ERROR_OK) return error;
- if (digest_ == KM_DIGEST_NONE)
- return KM_ERROR_OK;
+ if (digest_ == KM_DIGEST_NONE) return KM_ERROR_OK;
EVP_PKEY_CTX* pkey_ctx;
if (EVP_DigestSignInit(&digest_ctx_, &pkey_ctx, digest_algorithm_, nullptr /* engine */,
@@ -299,8 +306,7 @@
assert(output);
keymaster_error_t error = UpdateForFinish(additional_params, input);
- if (error != KM_ERROR_OK)
- return error;
+ if (error != KM_ERROR_OK) return error;
if (digest_ == KM_DIGEST_NONE)
return SignUndigested(output);
@@ -311,25 +317,21 @@
static keymaster_error_t zero_pad_left(UniquePtr<uint8_t[]>* dest, size_t padded_len, Buffer& src) {
assert(padded_len > src.available_read());
- dest->reset(new(std::nothrow) uint8_t[padded_len]);
- if (!dest->get())
- return KM_ERROR_MEMORY_ALLOCATION_FAILED;
+ dest->reset(new (std::nothrow) uint8_t[padded_len]);
+ if (!dest->get()) return KM_ERROR_MEMORY_ALLOCATION_FAILED;
size_t padding_len = padded_len - src.available_read();
memset(dest->get(), 0, padding_len);
- if (!src.read(dest->get() + padding_len, src.available_read()))
- return KM_ERROR_UNKNOWN_ERROR;
+ if (!src.read(dest->get() + padding_len, src.available_read())) return KM_ERROR_UNKNOWN_ERROR;
return KM_ERROR_OK;
}
keymaster_error_t RsaSignOperation::SignUndigested(Buffer* output) {
UniquePtr<RSA, RSA_Delete> rsa(EVP_PKEY_get1_RSA(const_cast<EVP_PKEY*>(rsa_key_)));
- if (!rsa.get())
- return TranslateLastOpenSslError();
+ if (!rsa.get()) return TranslateLastOpenSslError();
- if (!output->Reinitialize(RSA_size(rsa.get())))
- return KM_ERROR_MEMORY_ALLOCATION_FAILED;
+ if (!output->Reinitialize(RSA_size(rsa.get()))) return KM_ERROR_MEMORY_ALLOCATION_FAILED;
size_t key_len = EVP_PKEY_size(rsa_key_);
int bytes_encrypted;
@@ -341,8 +343,7 @@
return KM_ERROR_INVALID_INPUT_LENGTH;
} else if (data_.available_read() < key_len) {
keymaster_error_t error = zero_pad_left(&zero_padded, key_len, data_);
- if (error != KM_ERROR_OK)
- return error;
+ if (error != KM_ERROR_OK) return error;
to_encrypt = zero_padded.get();
}
bytes_encrypted = RSA_private_encrypt(key_len, to_encrypt, output->peek_write(), rsa.get(),
@@ -364,10 +365,8 @@
return KM_ERROR_UNSUPPORTED_PADDING_MODE;
}
- if (bytes_encrypted <= 0)
- return TranslateLastOpenSslError();
- if (!output->advance_write(bytes_encrypted))
- return KM_ERROR_UNKNOWN_ERROR;
+ if (bytes_encrypted <= 0) return TranslateLastOpenSslError();
+ if (!output->advance_write(bytes_encrypted)) return KM_ERROR_UNKNOWN_ERROR;
return KM_ERROR_OK;
}
@@ -376,13 +375,11 @@
if (EVP_DigestSignFinal(&digest_ctx_, nullptr /* signature */, &siglen) != 1)
return TranslateLastOpenSslError();
- if (!output->Reinitialize(siglen))
- return KM_ERROR_MEMORY_ALLOCATION_FAILED;
+ if (!output->Reinitialize(siglen)) return KM_ERROR_MEMORY_ALLOCATION_FAILED;
if (EVP_DigestSignFinal(&digest_ctx_, output->peek_write(), &siglen) <= 0)
return TranslateLastOpenSslError();
- if (!output->advance_write(siglen))
- return KM_ERROR_UNKNOWN_ERROR;
+ if (!output->advance_write(siglen)) return KM_ERROR_UNKNOWN_ERROR;
return KM_ERROR_OK;
}
@@ -390,11 +387,9 @@
keymaster_error_t RsaVerifyOperation::Begin(const AuthorizationSet& input_params,
AuthorizationSet* output_params) {
keymaster_error_t error = RsaDigestingOperation::Begin(input_params, output_params);
- if (error != KM_ERROR_OK)
- return error;
+ if (error != KM_ERROR_OK) return error;
- if (digest_ == KM_DIGEST_NONE)
- return KM_ERROR_OK;
+ if (digest_ == KM_DIGEST_NONE) return KM_ERROR_OK;
EVP_PKEY_CTX* pkey_ctx;
if (EVP_DigestVerifyInit(&digest_ctx_, &pkey_ctx, digest_algorithm_, nullptr, rsa_key_) != 1)
@@ -421,8 +416,7 @@
AuthorizationSet* /* output_params */,
Buffer* /* output */) {
keymaster_error_t error = UpdateForFinish(additional_params, input);
- if (error != KM_ERROR_OK)
- return error;
+ if (error != KM_ERROR_OK) return error;
if (digest_ == KM_DIGEST_NONE)
return VerifyUndigested(signature);
@@ -432,17 +426,14 @@
keymaster_error_t RsaVerifyOperation::VerifyUndigested(const Buffer& signature) {
UniquePtr<RSA, RSA_Delete> rsa(EVP_PKEY_get1_RSA(const_cast<EVP_PKEY*>(rsa_key_)));
- if (!rsa.get())
- return KM_ERROR_UNKNOWN_ERROR;
+ if (!rsa.get()) return KM_ERROR_UNKNOWN_ERROR;
size_t key_len = RSA_size(rsa.get());
int openssl_padding;
switch (padding_) {
case KM_PAD_NONE:
- if (data_.available_read() > key_len)
- return KM_ERROR_INVALID_INPUT_LENGTH;
- if (key_len != signature.available_read())
- return KM_ERROR_VERIFICATION_FAILED;
+ if (data_.available_read() > key_len) return KM_ERROR_INVALID_INPUT_LENGTH;
+ if (key_len != signature.available_read()) return KM_ERROR_VERIFICATION_FAILED;
openssl_padding = RSA_NO_PADDING;
break;
case KM_PAD_RSA_PKCS1_1_5_SIGN:
@@ -458,12 +449,10 @@
}
UniquePtr<uint8_t[]> decrypted_data(new (std::nothrow) uint8_t[key_len]);
- if (!decrypted_data.get())
- return KM_ERROR_MEMORY_ALLOCATION_FAILED;
+ if (!decrypted_data.get()) return KM_ERROR_MEMORY_ALLOCATION_FAILED;
int bytes_decrypted = RSA_public_decrypt(signature.available_read(), signature.peek_read(),
decrypted_data.get(), rsa.get(), openssl_padding);
- if (bytes_decrypted < 0)
- return KM_ERROR_VERIFICATION_FAILED;
+ if (bytes_decrypted < 0) return KM_ERROR_VERIFICATION_FAILED;
const uint8_t* compare_pos = decrypted_data.get();
size_t bytes_to_compare = bytes_decrypted;
@@ -489,20 +478,27 @@
}
keymaster_error_t RsaCryptOperation::SetOaepDigestIfRequired(EVP_PKEY_CTX* pkey_ctx) {
- if (padding() != KM_PAD_RSA_OAEP)
- return KM_ERROR_OK;
+ if (padding() != KM_PAD_RSA_OAEP) return KM_ERROR_OK;
assert(digest_algorithm_ != nullptr);
- if (!EVP_PKEY_CTX_set_rsa_oaep_md(pkey_ctx, digest_algorithm_))
+ if (!EVP_PKEY_CTX_set_rsa_oaep_md(pkey_ctx, digest_algorithm_)) {
return TranslateLastOpenSslError();
-
+ }
+ assert(mgf_digest_algorithm_ != nullptr);
// MGF1 MD is always SHA1.
- if (!EVP_PKEY_CTX_set_rsa_mgf1_md(pkey_ctx, EVP_sha1()))
+ if (!EVP_PKEY_CTX_set_rsa_mgf1_md(pkey_ctx, mgf_digest_algorithm_)) {
return TranslateLastOpenSslError();
-
+ }
return KM_ERROR_OK;
}
+keymaster_error_t RsaCryptOperation::Begin(const AuthorizationSet& input_params,
+ AuthorizationSet* output_params) {
+ keymaster_error_t error = RsaOperation::Begin(input_params, output_params);
+ if (error != KM_ERROR_OK) return error;
+ return InitMgfDigest();
+}
+
int RsaCryptOperation::GetOpensslPadding(keymaster_error_t* error) {
*error = KM_ERROR_OK;
switch (padding_) {
@@ -517,59 +513,56 @@
}
}
-struct EVP_PKEY_CTX_Delete {
- void operator()(EVP_PKEY_CTX* p) { EVP_PKEY_CTX_free(p); }
-};
+keymaster_error_t RsaCryptOperation::InitMgfDigest() {
+ if (mgf_digest_ == KM_DIGEST_NONE) {
+ return KM_ERROR_OK;
+ }
+ mgf_digest_algorithm_ = KmDigestToEvpDigest(mgf_digest_);
+ if (mgf_digest_algorithm_ == nullptr) {
+ return KM_ERROR_UNSUPPORTED_DIGEST;
+ }
+ return KM_ERROR_OK;
+}
keymaster_error_t RsaEncryptOperation::Finish(const AuthorizationSet& additional_params,
const Buffer& input, const Buffer& /* signature */,
AuthorizationSet* /* output_params */,
Buffer* output) {
- if (!output)
- return KM_ERROR_OUTPUT_PARAMETER_NULL;
+ if (!output) return KM_ERROR_OUTPUT_PARAMETER_NULL;
keymaster_error_t error = UpdateForFinish(additional_params, input);
- if (error != KM_ERROR_OK)
- return error;
+ if (error != KM_ERROR_OK) return error;
- UniquePtr<EVP_PKEY_CTX, EVP_PKEY_CTX_Delete> ctx(
- EVP_PKEY_CTX_new(rsa_key_, nullptr /* engine */));
- if (!ctx.get())
- return KM_ERROR_MEMORY_ALLOCATION_FAILED;
+ EVP_PKEY_CTX_Ptr ctx(EVP_PKEY_CTX_new(rsa_key_, nullptr /* engine */));
+ if (!ctx.get()) return KM_ERROR_MEMORY_ALLOCATION_FAILED;
- if (EVP_PKEY_encrypt_init(ctx.get()) <= 0)
- return TranslateLastOpenSslError();
+ if (EVP_PKEY_encrypt_init(ctx.get()) <= 0) return TranslateLastOpenSslError();
error = SetRsaPaddingInEvpContext(ctx.get(), false /* signing */);
- if (error != KM_ERROR_OK)
- return error;
+ if (error != KM_ERROR_OK) return error;
error = SetOaepDigestIfRequired(ctx.get());
- if (error != KM_ERROR_OK)
- return error;
+ if (error != KM_ERROR_OK) return error;
size_t outlen;
if (EVP_PKEY_encrypt(ctx.get(), nullptr /* out */, &outlen, data_.peek_read(),
data_.available_read()) <= 0)
return TranslateLastOpenSslError();
- if (!output->Reinitialize(outlen))
- return KM_ERROR_MEMORY_ALLOCATION_FAILED;
+ if (!output->Reinitialize(outlen)) return KM_ERROR_MEMORY_ALLOCATION_FAILED;
const uint8_t* to_encrypt = data_.peek_read();
size_t to_encrypt_len = data_.available_read();
UniquePtr<uint8_t[]> zero_padded;
if (padding_ == KM_PAD_NONE && to_encrypt_len < outlen) {
keymaster_error_t error = zero_pad_left(&zero_padded, outlen, data_);
- if (error != KM_ERROR_OK)
- return error;
+ if (error != KM_ERROR_OK) return error;
to_encrypt = zero_padded.get();
to_encrypt_len = outlen;
}
if (EVP_PKEY_encrypt(ctx.get(), output->peek_write(), &outlen, to_encrypt, to_encrypt_len) <= 0)
return TranslateLastOpenSslError();
- if (!output->advance_write(outlen))
- return KM_ERROR_UNKNOWN_ERROR;
+ if (!output->advance_write(outlen)) return KM_ERROR_UNKNOWN_ERROR;
return KM_ERROR_OK;
}
@@ -578,51 +571,41 @@
const Buffer& input, const Buffer& /* signature */,
AuthorizationSet* /* output_params */,
Buffer* output) {
- if (!output)
- return KM_ERROR_OUTPUT_PARAMETER_NULL;
+ if (!output) return KM_ERROR_OUTPUT_PARAMETER_NULL;
keymaster_error_t error = UpdateForFinish(additional_params, input);
- if (error != KM_ERROR_OK)
- return error;
+ if (error != KM_ERROR_OK) return error;
- UniquePtr<EVP_PKEY_CTX, EVP_PKEY_CTX_Delete> ctx(
- EVP_PKEY_CTX_new(rsa_key_, nullptr /* engine */));
- if (!ctx.get())
- return KM_ERROR_MEMORY_ALLOCATION_FAILED;
+ EVP_PKEY_CTX_Ptr ctx(EVP_PKEY_CTX_new(rsa_key_, nullptr /* engine */));
+ if (!ctx.get()) return KM_ERROR_MEMORY_ALLOCATION_FAILED;
- if (EVP_PKEY_decrypt_init(ctx.get()) <= 0)
- return TranslateLastOpenSslError();
+ if (EVP_PKEY_decrypt_init(ctx.get()) <= 0) return TranslateLastOpenSslError();
error = SetRsaPaddingInEvpContext(ctx.get(), false /* signing */);
- if (error != KM_ERROR_OK)
- return error;
+ if (error != KM_ERROR_OK) return error;
error = SetOaepDigestIfRequired(ctx.get());
- if (error != KM_ERROR_OK)
- return error;
+ if (error != KM_ERROR_OK) return error;
size_t outlen;
if (EVP_PKEY_decrypt(ctx.get(), nullptr /* out */, &outlen, data_.peek_read(),
data_.available_read()) <= 0)
return TranslateLastOpenSslError();
- if (!output->Reinitialize(outlen))
- return KM_ERROR_MEMORY_ALLOCATION_FAILED;
+ if (!output->Reinitialize(outlen)) return KM_ERROR_MEMORY_ALLOCATION_FAILED;
const uint8_t* to_decrypt = data_.peek_read();
size_t to_decrypt_len = data_.available_read();
UniquePtr<uint8_t[]> zero_padded;
if (padding_ == KM_PAD_NONE && to_decrypt_len < outlen) {
keymaster_error_t error = zero_pad_left(&zero_padded, outlen, data_);
- if (error != KM_ERROR_OK)
- return error;
+ if (error != KM_ERROR_OK) return error;
to_decrypt = zero_padded.get();
to_decrypt_len = outlen;
}
if (EVP_PKEY_decrypt(ctx.get(), output->peek_write(), &outlen, to_decrypt, to_decrypt_len) <= 0)
return TranslateLastOpenSslError();
- if (!output->advance_write(outlen))
- return KM_ERROR_UNKNOWN_ERROR;
+ if (!output->advance_write(outlen)) return KM_ERROR_UNKNOWN_ERROR;
return KM_ERROR_OK;
}
diff --git a/km_openssl/soft_keymaster_enforcement.cpp b/km_openssl/soft_keymaster_enforcement.cpp
index cc8bac9..0a3c2f6 100644
--- a/km_openssl/soft_keymaster_enforcement.cpp
+++ b/km_openssl/soft_keymaster_enforcement.cpp
@@ -181,7 +181,7 @@
// is an acceptable implementation strategy for production use as well. Additional verification
// need only be provided by an implementation if it is interoperating with another
// implementation that requires more.
- VerifyAuthorizationResponse response;
+ VerifyAuthorizationResponse response(request.message_version);
response.token.challenge = request.challenge;
response.token.timestamp = get_current_time_ms();
response.token.security_level = SecurityLevel();
@@ -197,4 +197,16 @@
return response;
}
+keymaster_error_t SoftKeymasterEnforcement::GenerateTimestampToken(TimestampToken* token) {
+ token->timestamp = get_current_time_ms();
+ token->security_level = SecurityLevel();
+ keymaster_blob_t data_chunks[] = {
+ toBlob(kAuthVerificationLabel),
+ toBlob(token->challenge),
+ toBlob(token->timestamp),
+ toBlob(token->security_level),
+ };
+ return hmacSha256(hmac_key_, data_chunks, 4, &token->mac);
+}
+
} // namespace keymaster
diff --git a/km_openssl/software_random_source.cpp b/km_openssl/software_random_source.cpp
index fe49cc7..48238b9 100644
--- a/km_openssl/software_random_source.cpp
+++ b/km_openssl/software_random_source.cpp
@@ -21,9 +21,8 @@
namespace keymaster {
keymaster_error_t SoftwareRandomSource::GenerateRandom(uint8_t* buffer, size_t length) const {
- if (RAND_bytes(buffer, length) != 1)
- return KM_ERROR_UNKNOWN_ERROR;
+ if (RAND_bytes(buffer, length) != 1) return KM_ERROR_UNKNOWN_ERROR;
return KM_ERROR_OK;
}
-}
+} // namespace keymaster
diff --git a/km_openssl/symmetric_key.cpp b/km_openssl/symmetric_key.cpp
index 2ef7d9e..1b89d66 100644
--- a/km_openssl/symmetric_key.cpp
+++ b/km_openssl/symmetric_key.cpp
@@ -31,11 +31,13 @@
namespace keymaster {
keymaster_error_t SymmetricKeyFactory::GenerateKey(const AuthorizationSet& key_description,
+ UniquePtr<Key> /* attest_key */,
+ const KeymasterBlob& /* issuer_subject */,
KeymasterKeyBlob* key_blob,
AuthorizationSet* hw_enforced,
- AuthorizationSet* sw_enforced) const {
- if (!key_blob || !hw_enforced || !sw_enforced)
- return KM_ERROR_OUTPUT_PARAMETER_NULL;
+ AuthorizationSet* sw_enforced,
+ CertificateChain* /* cert_chain */) const {
+ if (!key_blob || !hw_enforced || !sw_enforced) return KM_ERROR_OUTPUT_PARAMETER_NULL;
uint32_t key_size_bits;
if (!key_description.GetTagValue(TAG_KEY_SIZE, &key_size_bits) ||
@@ -43,13 +45,11 @@
return KM_ERROR_UNSUPPORTED_KEY_SIZE;
keymaster_error_t error = validate_algorithm_specific_new_key_params(key_description);
- if (error != KM_ERROR_OK)
- return error;
+ if (error != KM_ERROR_OK) return error;
size_t key_data_size = key_size_bytes(key_size_bits);
KeymasterKeyBlob key_material(key_data_size);
- if (!key_material.key_material)
- return KM_ERROR_MEMORY_ALLOCATION_FAILED;
+ if (!key_material.key_material) return KM_ERROR_MEMORY_ALLOCATION_FAILED;
error = random_source_.GenerateRandom(key_material.writable_data(), key_data_size);
if (error != KM_ERROR_OK) {
@@ -61,14 +61,16 @@
hw_enforced, sw_enforced);
}
-keymaster_error_t SymmetricKeyFactory::ImportKey(const AuthorizationSet& key_description,
+keymaster_error_t SymmetricKeyFactory::ImportKey(const AuthorizationSet& key_description, //
keymaster_key_format_t input_key_material_format,
- const KeymasterKeyBlob& input_key_material,
+ const KeymasterKeyBlob& input_key_material, //
+ UniquePtr<Key> /* attest_key */,
+ const KeymasterBlob& /* issuer_subject */,
KeymasterKeyBlob* output_key_blob,
AuthorizationSet* hw_enforced,
- AuthorizationSet* sw_enforced) const {
- if (!output_key_blob || !hw_enforced || !sw_enforced)
- return KM_ERROR_OUTPUT_PARAMETER_NULL;
+ AuthorizationSet* sw_enforced,
+ CertificateChain* /* cert_chain */) const {
+ if (!output_key_blob || !hw_enforced || !sw_enforced) return KM_ERROR_OUTPUT_PARAMETER_NULL;
AuthorizationSet authorizations(key_description);
@@ -91,7 +93,7 @@
}
return blob_maker_.CreateKeyBlob(authorizations, KM_ORIGIN_IMPORTED, input_key_material,
- output_key_blob, hw_enforced, sw_enforced);
+ output_key_blob, hw_enforced, sw_enforced);
}
static const keymaster_key_format_t supported_import_formats[] = {KM_KEY_FORMAT_RAW};
@@ -101,9 +103,8 @@
return supported_import_formats;
}
-SymmetricKey::SymmetricKey(KeymasterKeyBlob&& key_material,
- AuthorizationSet&& hw_enforced, AuthorizationSet&& sw_enforced,
- const KeyFactory* key_factory)
+SymmetricKey::SymmetricKey(KeymasterKeyBlob&& key_material, AuthorizationSet&& hw_enforced,
+ AuthorizationSet&& sw_enforced, const KeyFactory* key_factory)
: Key(move(hw_enforced), move(sw_enforced), key_factory) {
key_material_ = move(key_material);
}
diff --git a/km_openssl/triple_des_key.cpp b/km_openssl/triple_des_key.cpp
index 654e40e..8c267e6 100644
--- a/km_openssl/triple_des_key.cpp
+++ b/km_openssl/triple_des_key.cpp
@@ -18,8 +18,6 @@
#include <assert.h>
-#include <keymaster/new.h>
-
#include <openssl/err.h>
#include <openssl/rand.h>
diff --git a/km_openssl/wrapped_key.cpp b/km_openssl/wrapped_key.cpp
index e619f2a..79cba00 100644
--- a/km_openssl/wrapped_key.cpp
+++ b/km_openssl/wrapped_key.cpp
@@ -14,7 +14,6 @@
* limitations under the License.
*/
-#include <keymaster/attestation_record.h>
#include <keymaster/logger.h>
#include <keymaster/wrapped_key.h>
diff --git a/legacy_support/ec_keymaster0_key.cpp b/legacy_support/ec_keymaster0_key.cpp
deleted file mode 100644
index 9bf8556..0000000
--- a/legacy_support/ec_keymaster0_key.cpp
+++ /dev/null
@@ -1,124 +0,0 @@
-/*
- * 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 <keymaster/legacy_support/ec_keymaster0_key.h>
-
-#include <memory>
-
-#include <keymaster/android_keymaster_utils.h>
-#include <keymaster/contexts/soft_keymaster_context.h>
-#include <keymaster/km_openssl/openssl_utils.h>
-#include <keymaster/legacy_support/keymaster0_engine.h>
-#include <keymaster/logger.h>
-
-
-using std::unique_ptr;
-
-namespace keymaster {
-
-EcdsaKeymaster0KeyFactory::EcdsaKeymaster0KeyFactory(const SoftwareKeyBlobMaker* blob_maker,
- const Keymaster0Engine* engine)
- : EcKeyFactory(blob_maker), engine_(engine) {}
-
-keymaster_error_t EcdsaKeymaster0KeyFactory::GenerateKey(const AuthorizationSet& key_description,
- KeymasterKeyBlob* key_blob,
- AuthorizationSet* hw_enforced,
- AuthorizationSet* sw_enforced) const {
- if (!key_blob || !hw_enforced || !sw_enforced)
- return KM_ERROR_OUTPUT_PARAMETER_NULL;
-
- if (!engine_ || !engine_->supports_ec())
- return super::GenerateKey(key_description, key_blob, hw_enforced, sw_enforced);
-
- keymaster_ec_curve_t ec_curve;
- uint32_t key_size;
- keymaster_error_t error = GetCurveAndSize(key_description, &ec_curve, &key_size);
- if (error != KM_ERROR_OK) {
- return error;
- }
-
- KeymasterKeyBlob key_material;
- if (!engine_->GenerateEcKey(key_size, &key_material))
- return KM_ERROR_UNKNOWN_ERROR;
-
- // These tags are hardware-enforced. Putting them in the hw_enforced set here will ensure that
- // blob_maker_->CreateKeyBlob doesn't put them in sw_enforced.
- hw_enforced->push_back(TAG_ALGORITHM, KM_ALGORITHM_EC);
- hw_enforced->push_back(TAG_KEY_SIZE, key_size);
- hw_enforced->push_back(TAG_EC_CURVE, ec_curve);
- hw_enforced->push_back(TAG_ORIGIN, KM_ORIGIN_UNKNOWN);
-
- return blob_maker_.CreateKeyBlob(key_description, KM_ORIGIN_UNKNOWN, key_material, key_blob,
- hw_enforced, sw_enforced);
-}
-
-keymaster_error_t EcdsaKeymaster0KeyFactory::ImportKey(
- const AuthorizationSet& key_description, keymaster_key_format_t input_key_material_format,
- const KeymasterKeyBlob& input_key_material, KeymasterKeyBlob* output_key_blob,
- AuthorizationSet* hw_enforced, AuthorizationSet* sw_enforced) const {
- if (!output_key_blob || !hw_enforced || !sw_enforced)
- return KM_ERROR_OUTPUT_PARAMETER_NULL;
-
- if (!engine_ || !engine_->supports_ec())
- return super::ImportKey(key_description, input_key_material_format, input_key_material,
- output_key_blob, hw_enforced, sw_enforced);
-
- AuthorizationSet authorizations;
- uint32_t key_size;
- keymaster_error_t error = UpdateImportKeyDescription(
- key_description, input_key_material_format, input_key_material, &authorizations, &key_size);
- if (error != KM_ERROR_OK)
- return error;
-
- KeymasterKeyBlob imported_hw_key;
- if (!engine_->ImportKey(input_key_material_format, input_key_material, &imported_hw_key))
- return KM_ERROR_UNKNOWN_ERROR;
-
- // These tags are hardware-enforced. Putting them in the hw_enforced set here will ensure that
- // blob_maker_->CreateKeyBlob doesn't put them in sw_enforced.
- hw_enforced->push_back(TAG_ALGORITHM, KM_ALGORITHM_EC);
- hw_enforced->push_back(TAG_KEY_SIZE, key_size);
- hw_enforced->push_back(TAG_ORIGIN, KM_ORIGIN_UNKNOWN);
-
- return blob_maker_.CreateKeyBlob(authorizations, KM_ORIGIN_UNKNOWN, imported_hw_key,
- output_key_blob, hw_enforced, sw_enforced);
-}
-
-keymaster_error_t EcdsaKeymaster0KeyFactory::LoadKey(KeymasterKeyBlob&& key_material,
- const AuthorizationSet& additional_params,
- AuthorizationSet&& hw_enforced,
- AuthorizationSet&& sw_enforced,
- UniquePtr<Key>* key) const {
- if (!key)
- return KM_ERROR_OUTPUT_PARAMETER_NULL;
-
- if (sw_enforced.GetTagCount(TAG_ALGORITHM) == 1)
- return super::LoadKey(move(key_material), additional_params, move(hw_enforced), move(sw_enforced), key);
-
- unique_ptr<EC_KEY, EC_KEY_Delete> ec_key(engine_->BlobToEcKey(key_material));
- if (!ec_key)
- return KM_ERROR_UNKNOWN_ERROR;
-
- key->reset(new (std::nothrow)
- EcKeymaster0Key(ec_key.release(), move(hw_enforced), move(sw_enforced), this));
- if (!(*key))
- return KM_ERROR_MEMORY_ALLOCATION_FAILED;
-
- (*key)->key_material() = move(key_material);
- return KM_ERROR_OK;
-}
-
-} // namespace keymaster
diff --git a/legacy_support/ec_keymaster1_key.cpp b/legacy_support/ec_keymaster1_key.cpp
index 8dcc07f..fa4dc07 100644
--- a/legacy_support/ec_keymaster1_key.cpp
+++ b/legacy_support/ec_keymaster1_key.cpp
@@ -27,9 +27,10 @@
namespace keymaster {
-EcdsaKeymaster1KeyFactory::EcdsaKeymaster1KeyFactory(const SoftwareKeyBlobMaker* blob_maker,
+EcdsaKeymaster1KeyFactory::EcdsaKeymaster1KeyFactory(const SoftwareKeyBlobMaker& blob_maker,
+ const KeymasterContext& context,
const Keymaster1Engine* engine)
- : EcKeyFactory(blob_maker), engine_(engine),
+ : EcKeyFactory(blob_maker, 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) {}
@@ -62,9 +63,12 @@
}
keymaster_error_t EcdsaKeymaster1KeyFactory::GenerateKey(const AuthorizationSet& key_description,
+ UniquePtr<Key> /* attest_key */,
+ const KeymasterBlob& /* issuer_subject */,
KeymasterKeyBlob* key_blob,
AuthorizationSet* hw_enforced,
- AuthorizationSet* sw_enforced) const {
+ AuthorizationSet* sw_enforced,
+ CertificateChain* /* cert_chain */) const {
AuthorizationSet key_params_copy;
UpdateToWorkAroundUnsupportedDigests(key_description, &key_params_copy);
@@ -79,10 +83,16 @@
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 {
+keymaster_error_t
+EcdsaKeymaster1KeyFactory::ImportKey(const AuthorizationSet& key_description, //
+ keymaster_key_format_t input_key_material_format, //
+ const KeymasterKeyBlob& input_key_material, //
+ UniquePtr<Key> /* attest_key */, //
+ const KeymasterBlob& /* issuer_subject */,
+ KeymasterKeyBlob* output_key_blob, //
+ AuthorizationSet* hw_enforced, //
+ AuthorizationSet* sw_enforced,
+ CertificateChain* /* cert_chain */) const {
AuthorizationSet key_params_copy;
UpdateToWorkAroundUnsupportedDigests(key_description, &key_params_copy);
return engine_->ImportKey(key_params_copy, input_key_material_format, input_key_material,
@@ -94,19 +104,16 @@
AuthorizationSet&& hw_enforced,
AuthorizationSet&& sw_enforced,
UniquePtr<Key>* key) const {
- if (!key)
- return KM_ERROR_OUTPUT_PARAMETER_NULL;
+ if (!key) return KM_ERROR_OUTPUT_PARAMETER_NULL;
keymaster_error_t error;
unique_ptr<EC_KEY, EC_KEY_Delete> ecdsa(
engine_->BuildEcKey(key_material, additional_params, &error));
- if (!ecdsa)
- return error;
+ if (!ecdsa) return error;
key->reset(new (std::nothrow)
EcdsaKeymaster1Key(ecdsa.release(), move(hw_enforced), move(sw_enforced), this));
- if (!(*key))
- return KM_ERROR_MEMORY_ALLOCATION_FAILED;
+ if (!(*key)) return KM_ERROR_MEMORY_ALLOCATION_FAILED;
(*key)->key_material() = move(key_material);
return KM_ERROR_OK;
diff --git a/legacy_support/ecdsa_keymaster1_operation.cpp b/legacy_support/ecdsa_keymaster1_operation.cpp
index e3d2ace..01b6061 100644
--- a/legacy_support/ecdsa_keymaster1_operation.cpp
+++ b/legacy_support/ecdsa_keymaster1_operation.cpp
@@ -30,8 +30,7 @@
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;
+ 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
@@ -48,8 +47,7 @@
// that layer.
AuthorizationSet begin_params(input_params);
int pos = begin_params.find(TAG_DIGEST);
- if (pos == -1)
- return KM_ERROR_UNSUPPORTED_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,
@@ -76,8 +74,7 @@
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;
+ if (!key_data) return KM_ERROR_UNKNOWN_ERROR;
return key_data->error;
}
diff --git a/legacy_support/ecdsa_keymaster1_operation.h b/legacy_support/ecdsa_keymaster1_operation.h
index a24cc2b..e52deae 100644
--- a/legacy_support/ecdsa_keymaster1_operation.h
+++ b/legacy_support/ecdsa_keymaster1_operation.h
@@ -32,8 +32,7 @@
EcdsaKeymaster1WrappedOperation(keymaster_purpose_t purpose, const Keymaster1Engine* engine)
: purpose_(purpose), operation_handle_(0), engine_(engine) {}
~EcdsaKeymaster1WrappedOperation() {
- if (operation_handle_)
- Abort();
+ if (operation_handle_) Abort();
}
keymaster_error_t Begin(EVP_PKEY* ecdsa_key, const AuthorizationSet& input_params);
@@ -43,6 +42,7 @@
keymaster_error_t GetError(EVP_PKEY* ecdsa_key);
keymaster_operation_handle_t GetOperationHandle() const { return operation_handle_; }
+
protected:
keymaster_purpose_t purpose_;
keymaster_operation_handle_t operation_handle_;
@@ -66,8 +66,7 @@
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;
+ if (error != KM_ERROR_OK) return error;
return super::Begin(input_params, output_params);
}
@@ -75,8 +74,7 @@
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;
+ if (error != KM_ERROR_OK) return error;
error = super::Finish(input_params, input, signature, output_params, output);
if (wrapped_operation_.GetError(super::ecdsa_key_) != KM_ERROR_OK)
error = wrapped_operation_.GetError(super::ecdsa_key_);
@@ -85,14 +83,14 @@
keymaster_error_t Abort() override {
keymaster_error_t error = wrapped_operation_.Abort();
- if (error != KM_ERROR_OK)
- return error;
+ if (error != KM_ERROR_OK) return error;
return super::Abort();
}
keymaster_operation_handle_t operation_handle() const override {
return wrapped_operation_.GetOperationHandle();
}
+
private:
EcdsaKeymaster1WrappedOperation wrapped_operation_;
};
diff --git a/legacy_support/keymaster0_engine.cpp b/legacy_support/keymaster0_engine.cpp
deleted file mode 100644
index e856318..0000000
--- a/legacy_support/keymaster0_engine.cpp
+++ /dev/null
@@ -1,382 +0,0 @@
-/*
- * 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 <keymaster/legacy_support/keymaster0_engine.h>
-
-#include <assert.h>
-#include <string.h>
-
-#include <memory>
-
-#define LOG_TAG "Keymaster0Engine"
-#include <log/log.h>
-
-#include <keymaster/android_keymaster_utils.h>
-#include <keymaster/km_openssl/openssl_utils.h>
-
-#include <openssl/bn.h>
-#include <openssl/ec_key.h>
-#include <openssl/ecdsa.h>
-
-
-using std::shared_ptr;
-using std::unique_ptr;
-
-namespace keymaster {
-
-Keymaster0Engine* Keymaster0Engine::instance_ = nullptr;
-
-Keymaster0Engine::Keymaster0Engine(const keymaster0_device_t* keymaster0_device)
- : keymaster0_device_(keymaster0_device), engine_(ENGINE_new()), supports_ec_(false) {
- assert(!instance_);
- instance_ = this;
-
- rsa_index_ = RSA_get_ex_new_index(0 /* argl */, nullptr /* argp */, nullptr /* new_func */,
- keyblob_dup, keyblob_free);
- ec_key_index_ = EC_KEY_get_ex_new_index(0 /* argl */, nullptr /* argp */, nullptr /* new_func */,
- keyblob_dup, keyblob_free);
-
- memset(&rsa_method_, 0, sizeof(rsa_method_));
- rsa_method_.common.is_static = 1;
- rsa_method_.private_transform = Keymaster0Engine::rsa_private_transform;
- rsa_method_.flags = RSA_FLAG_OPAQUE;
-
- ENGINE_set_RSA_method(engine_, &rsa_method_, sizeof(rsa_method_));
-
- if ((keymaster0_device_->flags & KEYMASTER_SUPPORTS_EC) != 0) {
- supports_ec_ = true;
-
- memset(&ecdsa_method_, 0, sizeof(ecdsa_method_));
- ecdsa_method_.common.is_static = 1;
- ecdsa_method_.sign = Keymaster0Engine::ecdsa_sign;
- ecdsa_method_.flags = ECDSA_FLAG_OPAQUE;
-
- ENGINE_set_ECDSA_method(engine_, &ecdsa_method_, sizeof(ecdsa_method_));
- }
-}
-
-Keymaster0Engine::~Keymaster0Engine() {
- if (keymaster0_device_)
- keymaster0_device_->common.close(
- reinterpret_cast<hw_device_t*>(const_cast<keymaster0_device_t*>(keymaster0_device_)));
- ENGINE_free(engine_);
- instance_ = nullptr;
-}
-
-bool Keymaster0Engine::GenerateRsaKey(uint64_t public_exponent, uint32_t public_modulus,
- KeymasterKeyBlob* key_material) const {
- assert(key_material);
- keymaster_rsa_keygen_params_t params;
- params.public_exponent = public_exponent;
- params.modulus_size = public_modulus;
-
- uint8_t* key_blob = nullptr;
- if (keymaster0_device_->generate_keypair(keymaster0_device_, TYPE_RSA, ¶ms, &key_blob,
- &key_material->key_material_size) < 0) {
- ALOGE("Error generating RSA key pair with keymaster0 device");
- return false;
- }
- unique_ptr<uint8_t, Malloc_Delete> key_blob_deleter(key_blob);
- key_material->key_material = dup_buffer(key_blob, key_material->key_material_size);
- return true;
-}
-
-bool Keymaster0Engine::GenerateEcKey(uint32_t key_size, KeymasterKeyBlob* key_material) const {
- assert(key_material);
- keymaster_ec_keygen_params_t params;
- params.field_size = key_size;
-
- uint8_t* key_blob = nullptr;
- if (keymaster0_device_->generate_keypair(keymaster0_device_, TYPE_EC, ¶ms, &key_blob,
- &key_material->key_material_size) < 0) {
- ALOGE("Error generating EC key pair with keymaster0 device");
- return false;
- }
- unique_ptr<uint8_t, Malloc_Delete> key_blob_deleter(key_blob);
- key_material->key_material = dup_buffer(key_blob, key_material->key_material_size);
- return true;
-}
-
-bool Keymaster0Engine::ImportKey(keymaster_key_format_t key_format,
- const KeymasterKeyBlob& to_import,
- KeymasterKeyBlob* imported_key) const {
- assert(imported_key);
- if (key_format != KM_KEY_FORMAT_PKCS8)
- return false;
-
- uint8_t* key_blob = nullptr;
- if (keymaster0_device_->import_keypair(keymaster0_device_, to_import.key_material,
- to_import.key_material_size, &key_blob,
- &imported_key->key_material_size) < 0) {
- ALOGW("Error importing keypair with keymaster0 device");
- return false;
- }
- unique_ptr<uint8_t, Malloc_Delete> key_blob_deleter(key_blob);
- imported_key->key_material = dup_buffer(key_blob, imported_key->key_material_size);
- return true;
-}
-
-bool Keymaster0Engine::DeleteKey(const KeymasterKeyBlob& blob) const {
- if (!keymaster0_device_->delete_keypair)
- return true;
- return (keymaster0_device_->delete_keypair(keymaster0_device_, blob.key_material,
- blob.key_material_size) == 0);
-}
-
-bool Keymaster0Engine::DeleteAllKeys() const {
- if (!keymaster0_device_->delete_all)
- return true;
- return (keymaster0_device_->delete_all(keymaster0_device_) == 0);
-}
-
-static keymaster_key_blob_t* duplicate_blob(const uint8_t* key_data, size_t key_data_size) {
- unique_ptr<uint8_t[]> key_material_copy(dup_buffer(key_data, key_data_size));
- if (!key_material_copy)
- return nullptr;
-
- unique_ptr<keymaster_key_blob_t> blob_copy(new (std::nothrow) keymaster_key_blob_t);
- if (!blob_copy.get())
- return nullptr;
- blob_copy->key_material_size = key_data_size;
- blob_copy->key_material = key_material_copy.release();
- return blob_copy.release();
-}
-
-inline keymaster_key_blob_t* duplicate_blob(const keymaster_key_blob_t& blob) {
- return duplicate_blob(blob.key_material, blob.key_material_size);
-}
-
-RSA* Keymaster0Engine::BlobToRsaKey(const KeymasterKeyBlob& blob) const {
- // Create new RSA key (with engine methods) and insert blob
- unique_ptr<RSA, RSA_Delete> rsa(RSA_new_method(engine_));
- if (!rsa)
- return nullptr;
-
- keymaster_key_blob_t* blob_copy = duplicate_blob(blob);
- if (!blob_copy->key_material || !RSA_set_ex_data(rsa.get(), rsa_index_, blob_copy))
- return nullptr;
-
- // Copy public key into new RSA key
- unique_ptr<EVP_PKEY, EVP_PKEY_Delete> pkey(GetKeymaster0PublicKey(blob));
- if (!pkey)
- return nullptr;
- unique_ptr<RSA, RSA_Delete> public_rsa(EVP_PKEY_get1_RSA(pkey.get()));
- if (!public_rsa)
- return nullptr;
- rsa->n = BN_dup(public_rsa->n);
- rsa->e = BN_dup(public_rsa->e);
- if (!rsa->n || !rsa->e)
- return nullptr;
-
- return rsa.release();
-}
-
-EC_KEY* Keymaster0Engine::BlobToEcKey(const KeymasterKeyBlob& blob) const {
- // Create new EC key (with engine methods) and insert blob
- unique_ptr<EC_KEY, EC_KEY_Delete> ec_key(EC_KEY_new_method(engine_));
- if (!ec_key)
- return nullptr;
-
- keymaster_key_blob_t* blob_copy = duplicate_blob(blob);
- if (!blob_copy->key_material || !EC_KEY_set_ex_data(ec_key.get(), ec_key_index_, blob_copy))
- return nullptr;
-
- // Copy public key into new EC key
- unique_ptr<EVP_PKEY, EVP_PKEY_Delete> pkey(GetKeymaster0PublicKey(blob));
- if (!pkey)
- return nullptr;
-
- unique_ptr<EC_KEY, EC_KEY_Delete> public_ec_key(EVP_PKEY_get1_EC_KEY(pkey.get()));
- if (!public_ec_key)
- 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())))
- return nullptr;
-
- return ec_key.release();
-}
-
-const keymaster_key_blob_t* Keymaster0Engine::RsaKeyToBlob(const RSA* rsa) const {
- return reinterpret_cast<keymaster_key_blob_t*>(RSA_get_ex_data(rsa, rsa_index_));
-}
-
-const keymaster_key_blob_t* Keymaster0Engine::EcKeyToBlob(const EC_KEY* ec_key) const {
- return reinterpret_cast<keymaster_key_blob_t*>(EC_KEY_get_ex_data(ec_key, ec_key_index_));
-}
-
-/* static */
-int Keymaster0Engine::keyblob_dup(CRYPTO_EX_DATA* /* to */, const CRYPTO_EX_DATA* /* from */,
- void** from_d, int /* index */, long /* argl */,
- void* /* argp */) {
- keymaster_key_blob_t* blob = reinterpret_cast<keymaster_key_blob_t*>(*from_d);
- if (!blob)
- return 1;
- *from_d = duplicate_blob(*blob);
- if (*from_d)
- return 1;
- return 0;
-}
-
-/* static */
-void Keymaster0Engine::keyblob_free(void* /* parent */, void* ptr, CRYPTO_EX_DATA* /* data */,
- int /* index*/, long /* argl */, void* /* argp */) {
- keymaster_key_blob_t* blob = reinterpret_cast<keymaster_key_blob_t*>(ptr);
- if (blob) {
- delete[] blob->key_material;
- delete blob;
- }
-}
-
-/* static */
-int Keymaster0Engine::rsa_private_transform(RSA* rsa, uint8_t* out, const uint8_t* in, size_t len) {
- ALOGV("rsa_private_transform(%p, %p, %p, %u)", rsa, out, in, (unsigned)len);
-
- assert(instance_);
- return instance_->RsaPrivateTransform(rsa, out, in, len);
-}
-
-/* static */
-int Keymaster0Engine::ecdsa_sign(const uint8_t* digest, size_t digest_len, uint8_t* sig,
- unsigned int* sig_len, EC_KEY* ec_key) {
- ALOGV("ecdsa_sign(%p, %u, %p)", digest, (unsigned)digest_len, ec_key);
- assert(instance_);
- return instance_->EcdsaSign(digest, digest_len, sig, sig_len, ec_key);
-}
-
-bool Keymaster0Engine::Keymaster0Sign(const void* signing_params, const keymaster_key_blob_t& blob,
- const uint8_t* data, const size_t data_length,
- unique_ptr<uint8_t[], Malloc_Delete>* signature,
- size_t* signature_length) const {
- uint8_t* signed_data;
- int err = keymaster0_device_->sign_data(keymaster0_device_, signing_params, blob.key_material,
- blob.key_material_size, data, data_length, &signed_data,
- signature_length);
- if (err < 0) {
- ALOGE("Keymaster0 signing failed with error %d", err);
- return false;
- }
-
- signature->reset(signed_data);
- return true;
-}
-
-EVP_PKEY* Keymaster0Engine::GetKeymaster0PublicKey(const KeymasterKeyBlob& blob) const {
- uint8_t* pub_key_data;
- size_t pub_key_data_length;
- int err = keymaster0_device_->get_keypair_public(keymaster0_device_, blob.key_material,
- blob.key_material_size, &pub_key_data,
- &pub_key_data_length);
- if (err < 0) {
- ALOGE("Error %d extracting public key", err);
- return nullptr;
- }
- unique_ptr<uint8_t, Malloc_Delete> pub_key(pub_key_data);
-
- const uint8_t* p = pub_key_data;
- return d2i_PUBKEY(nullptr /* allocate new struct */, &p, pub_key_data_length);
-}
-
-static bool data_too_large_for_public_modulus(const uint8_t* data, size_t len, const RSA* rsa) {
- unique_ptr<BIGNUM, BIGNUM_Delete> input_as_bn(
- BN_bin2bn(data, len, nullptr /* allocate result */));
- return input_as_bn && BN_ucmp(input_as_bn.get(), rsa->n) >= 0;
-}
-
-int Keymaster0Engine::RsaPrivateTransform(RSA* rsa, uint8_t* out, const uint8_t* in,
- size_t len) const {
- const keymaster_key_blob_t* key_blob = RsaKeyToBlob(rsa);
- if (key_blob == nullptr) {
- ALOGE("key had no key_blob!");
- return 0;
- }
-
- keymaster_rsa_sign_params_t sign_params = {DIGEST_NONE, PADDING_NONE};
- unique_ptr<uint8_t[], Malloc_Delete> signature;
- size_t signature_length;
- if (!Keymaster0Sign(&sign_params, *key_blob, in, len, &signature, &signature_length)) {
- if (data_too_large_for_public_modulus(in, len, rsa)) {
- ALOGE("Keymaster0 signing failed because data is too large.");
- OPENSSL_PUT_ERROR(RSA, RSA_R_DATA_TOO_LARGE_FOR_MODULUS);
- } else {
- // We don't know what error code is correct; force an "unknown error" return
- OPENSSL_PUT_ERROR(USER, KM_ERROR_UNKNOWN_ERROR);
- }
- return 0;
- }
- Eraser eraser(signature.get(), signature_length);
-
- if (signature_length > len) {
- /* The result of the RSA operation can never be larger than the size of
- * the modulus so we assume that the result has extra zeros on the
- * left. This provides attackers with an oracle, but there's nothing
- * that we can do about it here. */
- memcpy(out, signature.get() + signature_length - len, len);
- } else if (signature_length < len) {
- /* If the keymaster0 implementation returns a short value we assume that
- * it's because it removed leading zeros from the left side. This is
- * bad because it provides attackers with an oracle but we cannot do
- * anything about a broken keymaster0 implementation here. */
- memset(out, 0, len);
- memcpy(out + len - signature_length, signature.get(), signature_length);
- } else {
- memcpy(out, signature.get(), len);
- }
-
- ALOGV("rsa=%p keystore_rsa_priv_dec successful", rsa);
- return 1;
-}
-
-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);
- if (key_blob == nullptr) {
- ALOGE("key had no key_blob!");
- 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_ec_sign_params_t sign_params = {DIGEST_NONE};
- unique_ptr<uint8_t[], Malloc_Delete> signature;
- size_t signature_length;
- if (!Keymaster0Sign(&sign_params, *key_blob, digest, digest_len, &signature,
- &signature_length)) {
- // We don't know what error code is correct; force an "unknown error" return
- OPENSSL_PUT_ERROR(USER, KM_ERROR_UNKNOWN_ERROR);
- return 0;
- }
- Eraser eraser(signature.get(), signature_length);
-
- if (signature_length == 0) {
- ALOGW("No valid signature returned");
- return 0;
- } else if (signature_length > ECDSA_size(ec_key)) {
- ALOGW("Signature is too large");
- return 0;
- } else {
- memcpy(sig, signature.get(), signature_length);
- *sig_len = signature_length;
- }
-
- ALOGV("ecdsa_sign(%p, %u, %p) => success", digest, (unsigned)digest_len, ec_key);
- return 1;
-}
-
-} // namespace keymaster
diff --git a/legacy_support/keymaster1_engine.cpp b/legacy_support/keymaster1_engine.cpp
index 7dd2c8a..28a64ad 100644
--- a/legacy_support/keymaster1_engine.cpp
+++ b/legacy_support/keymaster1_engine.cpp
@@ -32,7 +32,6 @@
#include <openssl/ec_key.h>
#include <openssl/ecdsa.h>
-using std::shared_ptr;
using std::unique_ptr;
namespace keymaster {
@@ -44,9 +43,9 @@
rsa_index_(RSA_get_ex_new_index(0 /* argl */, nullptr /* argp */, nullptr /* new_func */,
Keymaster1Engine::duplicate_key_data,
Keymaster1Engine::free_key_data)),
- ec_key_index_(EC_KEY_get_ex_new_index(0 /* argl */, nullptr /* argp */, nullptr /* new_func */,
- Keymaster1Engine::duplicate_key_data,
- Keymaster1Engine::free_key_data)),
+ ec_key_index_(EC_KEY_get_ex_new_index(
+ 0 /* argl */, nullptr /* argp */, nullptr /* 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);
@@ -69,10 +68,8 @@
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);
+ 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,
@@ -85,8 +82,7 @@
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;
+ 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;
@@ -110,8 +106,7 @@
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;
+ 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;
@@ -121,14 +116,12 @@
}
keymaster_error_t Keymaster1Engine::DeleteKey(const KeymasterKeyBlob& blob) const {
- if (!keymaster1_device_->delete_key)
- return KM_ERROR_OK;
+ if (!keymaster1_device_->delete_key) return KM_ERROR_OK;
return keymaster1_device_->delete_key(keymaster1_device_, &blob);
}
keymaster_error_t Keymaster1Engine::DeleteAllKeys() const {
- if (!keymaster1_device_->delete_all_keys)
- return KM_ERROR_OK;
+ if (!keymaster1_device_->delete_all_keys) return KM_ERROR_OK;
return keymaster1_device_->delete_all_keys(keymaster1_device_);
}
@@ -152,8 +145,7 @@
// 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 (*error != KM_ERROR_OK)
- return nullptr;
+ if (*error != KM_ERROR_OK) return nullptr;
unique_ptr<RSA, RSA_Delete> public_rsa(EVP_PKEY_get1_RSA(pkey.get()));
if (!public_rsa) {
@@ -192,8 +184,7 @@
// Copy public key into new EC key
unique_ptr<EVP_PKEY, EVP_PKEY_Delete> pkey(
GetKeymaster1PublicKey(blob, additional_params, error));
- if (*error != KM_ERROR_OK)
- return nullptr;
+ if (*error != KM_ERROR_OK) return nullptr;
unique_ptr<EC_KEY, EC_KEY_Delete> public_ec_key(EVP_PKEY_get1_EC_KEY(pkey.get()));
if (!public_ec_key) {
@@ -229,34 +220,32 @@
}
Keymaster1Engine::KeyData* Keymaster1Engine::GetData(const RSA* rsa) const {
- if (!rsa)
- return nullptr;
+ 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;
+ 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 */,
+ // NOLINTNEXTLINE(google-runtime-int)
void** from_d, int /* index */, long /* argl */,
void* /* argp */) {
KeyData* data = reinterpret_cast<KeyData*>(*from_d);
- if (!data)
- return 1;
+ if (!data) return 1;
// Default copy ctor is good.
*from_d = new KeyData(*data);
- if (*from_d)
- return 1;
+ if (*from_d) return 1;
return 0;
}
/* static */
void Keymaster1Engine::free_key_data(void* /* parent */, void* ptr, CRYPTO_EX_DATA* /* data */,
+ // NOLINTNEXTLINE(google-runtime-int)
int /* index*/, long /* argl */, void* /* argp */) {
delete reinterpret_cast<KeyData*>(ptr);
}
@@ -264,8 +253,7 @@
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;
+ 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
@@ -273,8 +261,7 @@
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;
+ 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);
@@ -284,8 +271,7 @@
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 (!key_data) return 0;
if (padding != key_data->expected_openssl_padding) {
LOG_E("Expected sign_raw with padding %d but got padding %d",
@@ -296,8 +282,7 @@
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;
+ 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);
@@ -309,8 +294,7 @@
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 (!key_data) return 0;
if (padding != key_data->expected_openssl_padding) {
LOG_E("Expected sign_raw with padding %d but got padding %d",
@@ -321,8 +305,7 @@
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;
+ 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);
@@ -334,19 +317,16 @@
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;
+ 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;
+ 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;
+ 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));
@@ -361,16 +341,13 @@
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;
+ 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;
+ if (*error != KM_ERROR_OK) return nullptr;
unique_ptr<uint8_t, Malloc_Delete> pub_key(const_cast<uint8_t*>(export_data.data));
diff --git a/legacy_support/keymaster1_legacy_support.cpp b/legacy_support/keymaster1_legacy_support.cpp
index b0fe3f2..3fd5cb4 100644
--- a/legacy_support/keymaster1_legacy_support.cpp
+++ b/legacy_support/keymaster1_legacy_support.cpp
@@ -54,8 +54,8 @@
return counter.count == full_digest_list.size();
}
-static keymaster_error_t add_digests(const keymaster1_device_t* dev, keymaster_algorithm_t algorithm,
- keymaster_purpose_t purpose,
+static keymaster_error_t add_digests(const keymaster1_device_t* dev,
+ keymaster_algorithm_t algorithm, keymaster_purpose_t purpose,
Keymaster1LegacySupport::DigestMap* map, bool* supports_all) {
auto key = std::make_pair(algorithm, purpose);
@@ -76,8 +76,7 @@
}
static keymaster_error_t map_digests(const keymaster1_device_t* dev,
- Keymaster1LegacySupport::DigestMap* map,
- bool* supports_all) {
+ Keymaster1LegacySupport::DigestMap* map, bool* supports_all) {
map->clear();
*supports_all = true;
@@ -88,8 +87,7 @@
bool alg_purpose_supports_all;
keymaster_error_t error =
add_digests(dev, algorithm, purpose, map, &alg_purpose_supports_all);
- if (error != KM_ERROR_OK)
- return error;
+ if (error != KM_ERROR_OK) return error;
*supports_all &= alg_purpose_supports_all;
}
@@ -100,8 +98,7 @@
bool alg_purpose_supports_all;
keymaster_error_t error =
add_digests(dev, algorithm, purpose, map, &alg_purpose_supports_all);
- if (error != KM_ERROR_OK)
- return error;
+ if (error != KM_ERROR_OK) return error;
*supports_all &= alg_purpose_supports_all;
}
@@ -117,10 +114,8 @@
}
template <typename T>
-static bool findUnsupportedDigest(keymaster_algorithm_t algorithm,
- keymaster_purpose_t purpose,
- keymaster_digest_t digest,
- const T& params,
+static bool findUnsupportedDigest(keymaster_algorithm_t algorithm, keymaster_purpose_t purpose,
+ keymaster_digest_t digest, const T& params,
const Keymaster1LegacySupport::DigestMap& digest_map) {
auto supported_digests = digest_map.find(std::make_pair(algorithm, purpose));
if (supported_digests == digest_map.end())
@@ -135,7 +130,8 @@
for (auto& entry : params)
if (entry.tag == TAG_DIGEST)
if (!contains(supported_digests->second, entry.enumerated)) {
- LOG(WARNING) << "Digest " << entry.enumerated << " requested but not supported by KM1 hal";
+ LOG(WARNING) << "Digest " << entry.enumerated
+ << " requested but not supported by KM1 hal";
return true;
}
return false;
@@ -143,8 +139,7 @@
template <typename T>
bool requiresSoftwareDigesting(keymaster_algorithm_t algorithm, keymaster_purpose_t purpose,
- keymaster_digest_t digest,
- const T& params,
+ keymaster_digest_t digest, const T& params,
const Keymaster1LegacySupport::DigestMap& digest_map) {
switch (algorithm) {
case KM_ALGORITHM_AES:
@@ -158,14 +153,15 @@
}
if (!findUnsupportedDigest(algorithm, purpose, digest, params, digest_map)) {
- LOG(DEBUG) << "Requested digest(s) supported for algorithm " << algorithm << " and purpose " << purpose;
+ LOG(DEBUG) << "Requested digest(s) supported for algorithm " << algorithm << " and purpose "
+ << purpose;
return false;
}
return true;
}
bool Keymaster1LegacySupport::RequiresSoftwareDigesting(
- const AuthorizationSet& key_description) const {
+ const AuthorizationSet& key_description) const {
keymaster_algorithm_t algorithm;
if (!key_description.GetTagValue(TAG_ALGORITHM, &algorithm)) {
@@ -189,7 +185,7 @@
}
bool Keymaster1LegacySupport::RequiresSoftwareDigesting(const keymaster_digest_t digest,
- const AuthProxy& key_description) const {
+ const AuthProxy& key_description) const {
keymaster_algorithm_t algorithm;
if (!key_description.GetTagValue(TAG_ALGORITHM, &algorithm)) {
@@ -222,15 +218,19 @@
return !has_purpose;
}
-template<>
-keymaster_error_t
-Keymaster1ArbitrationFactory<EcdsaKeymaster1KeyFactory>::GenerateKey(
- const AuthorizationSet& key_description,
- KeymasterKeyBlob* key_blob, AuthorizationSet* hw_enforced,
- AuthorizationSet* sw_enforced) const {
+template <>
+keymaster_error_t Keymaster1ArbitrationFactory<EcdsaKeymaster1KeyFactory>::GenerateKey(
+ const AuthorizationSet& key_description, //
+ UniquePtr<Key> attest_key, //
+ const KeymasterBlob& issuer_subject, //
+ KeymasterKeyBlob* key_blob, //
+ AuthorizationSet* hw_enforced, //
+ AuthorizationSet* sw_enforced, //
+ CertificateChain* cert_chain) const {
if (legacy_support_.RequiresSoftwareDigesting(key_description)) {
- return software_digest_factory_.GenerateKey(key_description, key_blob, hw_enforced,
- sw_enforced);
+ return software_digest_factory_.GenerateKey(key_description, move(attest_key),
+ issuer_subject, key_blob, hw_enforced,
+ sw_enforced, cert_chain);
} else {
AuthorizationSet mutable_key_description = key_description;
keymaster_ec_curve_t curve;
@@ -252,54 +252,48 @@
}
}
- return passthrough_factory_.GenerateKey(mutable_key_description, key_blob, hw_enforced,
- sw_enforced);
+ return passthrough_factory_.GenerateKey(mutable_key_description, move(attest_key),
+ issuer_subject, key_blob, hw_enforced, sw_enforced,
+ cert_chain);
}
}
-template<>
-keymaster_error_t
-Keymaster1ArbitrationFactory<EcdsaKeymaster1KeyFactory>::LoadKey(KeymasterKeyBlob&& key_material,
- const AuthorizationSet& additional_params,
- AuthorizationSet&& hw_enforced,
- AuthorizationSet&& sw_enforced,
- UniquePtr<Key>* key) const {
+template <>
+keymaster_error_t Keymaster1ArbitrationFactory<EcdsaKeymaster1KeyFactory>::LoadKey(
+ KeymasterKeyBlob&& key_material, const AuthorizationSet& additional_params,
+ AuthorizationSet&& hw_enforced, AuthorizationSet&& sw_enforced, UniquePtr<Key>* key) const {
keymaster_digest_t digest;
if (!additional_params.GetTagValue(TAG_DIGEST, &digest)) {
digest = KM_DIGEST_NONE;
}
- bool requires_software_digesting = legacy_support_.RequiresSoftwareDigesting(digest,
- AuthProxy(hw_enforced, sw_enforced));
+ bool requires_software_digesting =
+ legacy_support_.RequiresSoftwareDigesting(digest, AuthProxy(hw_enforced, sw_enforced));
auto rc = software_digest_factory_.LoadKey(move(key_material), additional_params,
move(hw_enforced), move(sw_enforced), key);
if (rc != KM_ERROR_OK) return rc;
if (!requires_software_digesting) {
- (*key)->key_factory() = & passthrough_factory_;
+ (*key)->key_factory() = &passthrough_factory_;
}
return KM_ERROR_OK;
}
-template<>
-keymaster_error_t
-Keymaster1ArbitrationFactory<RsaKeymaster1KeyFactory>::LoadKey(KeymasterKeyBlob&& key_material,
- const AuthorizationSet& additional_params,
- AuthorizationSet&& hw_enforced,
- AuthorizationSet&& sw_enforced,
- UniquePtr<Key>* key) const {
+template <>
+keymaster_error_t Keymaster1ArbitrationFactory<RsaKeymaster1KeyFactory>::LoadKey(
+ KeymasterKeyBlob&& key_material, const AuthorizationSet& additional_params,
+ AuthorizationSet&& hw_enforced, AuthorizationSet&& sw_enforced, UniquePtr<Key>* key) const {
keymaster_digest_t digest;
if (!additional_params.GetTagValue(TAG_DIGEST, &digest)) {
digest = KM_DIGEST_NONE;
}
- bool requires_software_digesting = legacy_support_.RequiresSoftwareDigesting(digest,
- AuthProxy(hw_enforced, sw_enforced));
+ bool requires_software_digesting =
+ legacy_support_.RequiresSoftwareDigesting(digest, AuthProxy(hw_enforced, sw_enforced));
auto rc = software_digest_factory_.LoadKey(move(key_material), additional_params,
move(hw_enforced), move(sw_enforced), key);
if (rc != KM_ERROR_OK) return rc;
if (!requires_software_digesting) {
- (*key)->key_factory() = & passthrough_factory_;
+ (*key)->key_factory() = &passthrough_factory_;
}
return KM_ERROR_OK;
}
-
-} // namespace keymaster
+} // namespace keymaster
diff --git a/legacy_support/keymaster_passthrough_engine.cpp b/legacy_support/keymaster_passthrough_engine.cpp
index bd8f5b4..ed22320 100644
--- a/legacy_support/keymaster_passthrough_engine.cpp
+++ b/legacy_support/keymaster_passthrough_engine.cpp
@@ -30,7 +30,6 @@
#define LOG_TAG "Keymaster2Engine"
#include <android/log.h>
-using std::shared_ptr;
using std::unique_ptr;
namespace keymaster {
@@ -79,7 +78,7 @@
// For KM1 the Keymaster1Engine takes ownership
if (std::is_same<KeymasterDeviceType, keymaster2_device_t>::value)
km_device_->common.close(
- reinterpret_cast<hw_device_t*>(const_cast<KeymasterDeviceType*>(km_device_)));
+ reinterpret_cast<hw_device_t*>(const_cast<KeymasterDeviceType*>(km_device_)));
}
keymaster_error_t GenerateKey(const AuthorizationSet& key_description,
@@ -91,16 +90,13 @@
const KeymasterKeyBlob& input_key_material,
KeymasterKeyBlob* output_key_blob, AuthorizationSet* hw_enforced,
AuthorizationSet* sw_enforced) const override;
- keymaster_error_t ExportKey(keymaster_key_format_t format,
- const KeymasterKeyBlob& blob,
- const KeymasterBlob& client_id,
- const KeymasterBlob& app_data,
+ keymaster_error_t ExportKey(keymaster_key_format_t format, const KeymasterKeyBlob& blob,
+ const KeymasterBlob& client_id, const KeymasterBlob& app_data,
KeymasterBlob* export_data) const override {
keymaster_blob_t my_export_data = {};
keymaster_error_t error = km_device_->export_key(km_device_, format, &blob, &client_id,
&app_data, &my_export_data);
- if (error != KM_ERROR_OK)
- return error;
+ if (error != KM_ERROR_OK) return error;
*export_data = KeymasterBlob(my_export_data.data, my_export_data.data_length);
free(const_cast<uint8_t*>(my_export_data.data));
if (export_data->data == nullptr) {
@@ -116,9 +112,9 @@
}
OperationFactory* GetOperationFactory(keymaster_purpose_t purpose,
keymaster_algorithm_t algorithm) const override {
- switch(algorithm) {
+ switch (algorithm) {
case KM_ALGORITHM_RSA:
- switch(purpose) {
+ switch (purpose) {
case KM_PURPOSE_ENCRYPT:
return rsa_encrypt_op_factory_.get();
case KM_PURPOSE_DECRYPT:
@@ -131,7 +127,7 @@
return nullptr;
}
case KM_ALGORITHM_EC:
- switch(purpose) {
+ switch (purpose) {
case KM_PURPOSE_ENCRYPT:
return ec_encrypt_op_factory_.get();
case KM_PURPOSE_DECRYPT:
@@ -146,7 +142,7 @@
return nullptr;
}
case KM_ALGORITHM_AES:
- switch(purpose) {
+ switch (purpose) {
case KM_PURPOSE_ENCRYPT:
return aes_encrypt_op_factory_.get();
case KM_PURPOSE_DECRYPT:
@@ -179,7 +175,7 @@
private:
TKeymasterPassthroughEngine(const KeymasterPassthroughEngine&) = delete; // Uncopyable
- void operator=(const KeymasterPassthroughEngine&) = delete; // Unassignable
+ void operator=(const KeymasterPassthroughEngine&) = delete; // Unassignable
const KeymasterDeviceType* const km_device_;
std::unique_ptr<opfactory_t> rsa_encrypt_op_factory_;
@@ -201,49 +197,41 @@
static void ConvertCharacteristics(const keymaster_key_characteristics_t& characteristics,
AuthorizationSet* hw_enforced, AuthorizationSet* sw_enforced) {
- if (hw_enforced)
- hw_enforced->Reinitialize(characteristics.hw_enforced);
- if (sw_enforced)
- sw_enforced->Reinitialize(characteristics.sw_enforced);
+ if (hw_enforced) hw_enforced->Reinitialize(characteristics.hw_enforced);
+ if (sw_enforced) sw_enforced->Reinitialize(characteristics.sw_enforced);
}
-template<>
-keymaster_error_t
-TKeymasterPassthroughEngine<keymaster1_device_t>::GenerateKey(const AuthorizationSet& key_description,
- KeymasterKeyBlob* key_blob,
- AuthorizationSet* hw_enforced,
- AuthorizationSet* sw_enforced) const {
+template <>
+keymaster_error_t TKeymasterPassthroughEngine<keymaster1_device_t>::GenerateKey(
+ const AuthorizationSet& key_description, KeymasterKeyBlob* key_blob,
+ AuthorizationSet* hw_enforced, AuthorizationSet* sw_enforced) const {
assert(key_blob);
keymaster_key_characteristics_t* characteristics = nullptr;
keymaster_key_blob_t blob = {};
- keymaster_error_t error = km_device_->generate_key(km_device_, &key_description,
- &blob, &characteristics);
- if (error != KM_ERROR_OK)
- return error;
+ keymaster_error_t error =
+ km_device_->generate_key(km_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);
keymaster_free_characteristics(characteristics);
- free (characteristics);
+ free(characteristics);
return error;
}
-template<>
-keymaster_error_t
-TKeymasterPassthroughEngine<keymaster2_device_t>::GenerateKey(const AuthorizationSet& key_description,
- KeymasterKeyBlob* key_blob,
- AuthorizationSet* hw_enforced,
- AuthorizationSet* sw_enforced) const {
+template <>
+keymaster_error_t TKeymasterPassthroughEngine<keymaster2_device_t>::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 = km_device_->generate_key(km_device_, &key_description,
- &blob, &characteristics);
- if (error != KM_ERROR_OK)
- return error;
+ keymaster_error_t error =
+ km_device_->generate_key(km_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;
@@ -253,25 +241,21 @@
return error;
}
-template<>
-keymaster_error_t
-TKeymasterPassthroughEngine<keymaster1_device_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 {
+template <>
+keymaster_error_t TKeymasterPassthroughEngine<keymaster1_device_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 {
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 = km_device_->import_key(km_device_, &key_description,
- input_key_material_format, &input_key,
- &blob, &characteristics);
- if (error != KM_ERROR_OK)
- return error;
+ keymaster_error_t error =
+ km_device_->import_key(km_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 = KeymasterKeyBlob(blob);
@@ -282,25 +266,21 @@
return error;
}
-template<>
-keymaster_error_t
-TKeymasterPassthroughEngine<keymaster2_device_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 {
+template <>
+keymaster_error_t TKeymasterPassthroughEngine<keymaster2_device_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 {
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 = km_device_->import_key(km_device_, &key_description,
- input_key_material_format, &input_key,
- &blob, &characteristics);
- if (error != KM_ERROR_OK)
- return error;
+ keymaster_error_t error =
+ km_device_->import_key(km_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));
// TODO why duplicate the blob if we have ownership here anyway?
output_key_blob->key_material = dup_buffer(blob.key_material, blob.key_material_size);
@@ -313,12 +293,10 @@
typedef UniquePtr<KeymasterPassthroughEngine> engine_ptr_t;
-engine_ptr_t
-KeymasterPassthroughEngine::createInstance(const keymaster1_device_t* dev) {
+engine_ptr_t KeymasterPassthroughEngine::createInstance(const keymaster1_device_t* dev) {
return engine_ptr_t(new TKeymasterPassthroughEngine<keymaster1_device_t>(dev));
}
-engine_ptr_t
-KeymasterPassthroughEngine::createInstance(const keymaster2_device_t* dev) {
+engine_ptr_t KeymasterPassthroughEngine::createInstance(const keymaster2_device_t* dev) {
return engine_ptr_t(new TKeymasterPassthroughEngine<keymaster2_device_t>(dev));
}
diff --git a/legacy_support/keymaster_passthrough_key.cpp b/legacy_support/keymaster_passthrough_key.cpp
index f8d8f62..52b56e8 100644
--- a/legacy_support/keymaster_passthrough_key.cpp
+++ b/legacy_support/keymaster_passthrough_key.cpp
@@ -19,21 +19,18 @@
namespace keymaster {
-keymaster_error_t
-KeymasterPassthroughKeyFactory::LoadKey(KeymasterKeyBlob&& key_material,
- const AuthorizationSet& additional_params,
- AuthorizationSet&& hw_enforced,
- AuthorizationSet&& sw_enforced,
- UniquePtr<Key>* key) const {
+keymaster_error_t KeymasterPassthroughKeyFactory::LoadKey(KeymasterKeyBlob&& key_material,
+ const AuthorizationSet& additional_params,
+ AuthorizationSet&& hw_enforced,
+ AuthorizationSet&& sw_enforced,
+ UniquePtr<Key>* key) const {
keymaster_error_t error = KM_ERROR_OK;
- if (!key)
- return KM_ERROR_OUTPUT_PARAMETER_NULL;
+ if (!key) return KM_ERROR_OUTPUT_PARAMETER_NULL;
- key->reset(new (std::nothrow) KeymasterPassthroughKey(move(key_material), move(hw_enforced),
- move(sw_enforced), this, &error,
- additional_params, engine_));
- if (!key->get())
- error = KM_ERROR_MEMORY_ALLOCATION_FAILED;
+ key->reset(new (std::nothrow)
+ KeymasterPassthroughKey(move(key_material), move(hw_enforced), move(sw_enforced),
+ this, &error, additional_params, engine_));
+ if (!key->get()) error = KM_ERROR_MEMORY_ALLOCATION_FAILED;
return error;
}
@@ -49,11 +46,9 @@
return nullptr;
}
-
-keymaster_error_t
-KeymasterPassthroughKey::formatted_key_material(keymaster_key_format_t format,
- UniquePtr<uint8_t[]>* material,
- size_t* size) const {
+keymaster_error_t KeymasterPassthroughKey::formatted_key_material(keymaster_key_format_t format,
+ UniquePtr<uint8_t[]>* material,
+ size_t* size) const {
if (!material || !size) {
return KM_ERROR_OUTPUT_PARAMETER_NULL;
}
@@ -71,8 +66,8 @@
KeymasterBlob export_data;
- keymaster_error_t error = engine_->ExportKey(format, key_material(), client_id, app_data,
- &export_data);
+ keymaster_error_t error =
+ engine_->ExportKey(format, key_material(), client_id, app_data, &export_data);
if (error == KM_ERROR_OK) {
keymaster_blob_t export_blob = export_data.release();
material->reset(const_cast<uint8_t*>(export_blob.data));
diff --git a/legacy_support/keymaster_passthrough_operation.cpp b/legacy_support/keymaster_passthrough_operation.cpp
index 9b21058..7b10722 100644
--- a/legacy_support/keymaster_passthrough_operation.cpp
+++ b/legacy_support/keymaster_passthrough_operation.cpp
@@ -16,19 +16,17 @@
*/
#include "keymaster_passthrough_operation.h"
-#include <vector>
#include <keymaster/android_keymaster_utils.h>
+#include <vector>
namespace keymaster {
-template<>
-keymaster_error_t
-KeymasterPassthroughOperation<keymaster1_device_t>::Finish(const AuthorizationSet& input_params,
- const Buffer& input,
- const Buffer& signature, AuthorizationSet* output_params,
- Buffer* output) {
+template <>
+keymaster_error_t KeymasterPassthroughOperation<keymaster1_device_t>::Finish(
+ const AuthorizationSet& input_params, const Buffer& input, const Buffer& signature,
+ AuthorizationSet* output_params, Buffer* output) {
keymaster_key_param_set_t out_params = {};
- keymaster_blob_t in{ input.peek_read(), input.available_read() };
+ keymaster_blob_t in{input.peek_read(), input.available_read()};
keymaster_blob_t out = {};
keymaster_error_t rc;
std::vector<KeymasterBlob> accumulate_output;
@@ -37,7 +35,8 @@
AuthorizationSet mutable_input_params = input_params;
while (in.data_length != 0) {
size_t consumed = 0;
- rc = km_device_->update(km_device_, operation_handle_, &mutable_input_params, &in, &consumed, &out_params, &out);
+ rc = km_device_->update(km_device_, operation_handle_, &mutable_input_params, &in,
+ &consumed, &out_params, &out);
if (rc == KM_ERROR_OK) {
accumulate_output.push_back(KeymasterBlob(out));
accumulated_output_size += out.data_length;
@@ -64,9 +63,10 @@
}
}
- keymaster_blob_t sig{ signature.peek_read(), signature.available_read() };
+ keymaster_blob_t sig{signature.peek_read(), signature.available_read()};
- rc = km_device_->finish(km_device_, operation_handle_, &mutable_input_params, &sig, &out_params, &out);
+ rc = km_device_->finish(km_device_, operation_handle_, &mutable_input_params, &sig, &out_params,
+ &out);
if (rc != KM_ERROR_OK) return rc;
accumulate_output.push_back(KeymasterBlob(out));
accumulated_output_size += out.data_length;
@@ -79,7 +79,7 @@
if (!output->reserve(accumulated_output_size)) {
return KM_ERROR_MEMORY_ALLOCATION_FAILED;
}
- for (auto& outBlob: accumulate_output) {
+ for (auto& outBlob : accumulate_output) {
output->write(outBlob.data, outBlob.data_length);
}
}
@@ -90,17 +90,17 @@
return KM_ERROR_OK;
}
-template<>
-keymaster_error_t
-KeymasterPassthroughOperation<keymaster2_device_t>::Finish(const AuthorizationSet& input_params, const Buffer& input,
- const Buffer& signature, AuthorizationSet* output_params,
- Buffer* output) {
+template <>
+keymaster_error_t KeymasterPassthroughOperation<keymaster2_device_t>::Finish(
+ const AuthorizationSet& input_params, const Buffer& input, const Buffer& signature,
+ AuthorizationSet* output_params, Buffer* output) {
keymaster_key_param_set_t out_params = {};
- keymaster_blob_t sig{ signature.peek_read(), signature.available_read() };
- keymaster_blob_t in{ input.peek_read(), input.available_read() };
+ keymaster_blob_t sig{signature.peek_read(), signature.available_read()};
+ keymaster_blob_t in{input.peek_read(), input.available_read()};
keymaster_blob_t out = {};
keymaster_error_t rc;
- rc = km_device_->finish(km_device_, operation_handle_, &input_params, &in, &sig, &out_params, &out);
+ rc = km_device_->finish(km_device_, operation_handle_, &input_params, &in, &sig, &out_params,
+ &out);
if (rc == KM_ERROR_OK) {
if (output) output->Reinitialize(out.data, out.data_length);
if (output_params) output_params->Reinitialize(out_params);
diff --git a/legacy_support/rsa_keymaster0_key.cpp b/legacy_support/rsa_keymaster0_key.cpp
deleted file mode 100644
index 0f3bf27..0000000
--- a/legacy_support/rsa_keymaster0_key.cpp
+++ /dev/null
@@ -1,126 +0,0 @@
-/*
- * 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 <keymaster/legacy_support/rsa_keymaster0_key.h>
-
-#include <memory>
-
-#include <keymaster/android_keymaster_utils.h>
-#include <keymaster/contexts/soft_keymaster_context.h>
-#include <keymaster/km_openssl/openssl_utils.h>
-#include <keymaster/legacy_support/keymaster0_engine.h>
-#include <keymaster/logger.h>
-
-
-using std::unique_ptr;
-
-namespace keymaster {
-
-RsaKeymaster0KeyFactory::RsaKeymaster0KeyFactory(const SoftwareKeyBlobMaker* blob_maker,
- const Keymaster0Engine* engine)
- : RsaKeyFactory(blob_maker), engine_(engine) {}
-
-keymaster_error_t RsaKeymaster0KeyFactory::GenerateKey(const AuthorizationSet& key_description,
- KeymasterKeyBlob* key_blob,
- AuthorizationSet* hw_enforced,
- AuthorizationSet* sw_enforced) const {
- if (!key_blob || !hw_enforced || !sw_enforced)
- return KM_ERROR_OUTPUT_PARAMETER_NULL;
-
- 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");
- return KM_ERROR_INVALID_ARGUMENT;
- }
-
- uint32_t key_size;
- if (!key_description.GetTagValue(TAG_KEY_SIZE, &key_size)) {
- LOG_E("%s", "No key size specified for RSA key generation");
- return KM_ERROR_UNSUPPORTED_KEY_SIZE;
- }
-
- KeymasterKeyBlob key_material;
- if (!engine_->GenerateRsaKey(public_exponent, key_size, &key_material))
- return KM_ERROR_UNKNOWN_ERROR;
-
- // These tags are hardware-enforced. Putting them in the hw_enforced set here will ensure that
- // blob_maker_->CreateKeyBlob doesn't put them in sw_enforced.
- hw_enforced->push_back(TAG_ALGORITHM, KM_ALGORITHM_RSA);
- hw_enforced->push_back(TAG_RSA_PUBLIC_EXPONENT, public_exponent);
- hw_enforced->push_back(TAG_KEY_SIZE, key_size);
- hw_enforced->push_back(TAG_ORIGIN, KM_ORIGIN_UNKNOWN);
-
- return blob_maker_.CreateKeyBlob(key_description, KM_ORIGIN_UNKNOWN, key_material, key_blob,
- hw_enforced, sw_enforced);
-}
-
-keymaster_error_t RsaKeymaster0KeyFactory::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 {
- if (!output_key_blob || !hw_enforced || !sw_enforced)
- return KM_ERROR_OUTPUT_PARAMETER_NULL;
-
- AuthorizationSet authorizations;
- uint64_t public_exponent;
- uint32_t key_size;
- keymaster_error_t error =
- UpdateImportKeyDescription(key_description, input_key_material_format, input_key_material,
- &authorizations, &public_exponent, &key_size);
- if (error != KM_ERROR_OK)
- return error;
-
- KeymasterKeyBlob imported_hw_key;
- if (!engine_->ImportKey(input_key_material_format, input_key_material, &imported_hw_key))
- return KM_ERROR_UNKNOWN_ERROR;
-
- // These tags are hardware-enforced. Putting them in the hw_enforced set here will ensure that
- // blob_maker_->CreateKeyBlob doesn't put them in sw_enforced.
- hw_enforced->push_back(TAG_ALGORITHM, KM_ALGORITHM_RSA);
- hw_enforced->push_back(TAG_RSA_PUBLIC_EXPONENT, public_exponent);
- hw_enforced->push_back(TAG_KEY_SIZE, key_size);
- hw_enforced->push_back(TAG_ORIGIN, KM_ORIGIN_UNKNOWN);
-
- return blob_maker_.CreateKeyBlob(authorizations, KM_ORIGIN_UNKNOWN, imported_hw_key,
- output_key_blob, hw_enforced, sw_enforced);
-}
-
-keymaster_error_t RsaKeymaster0KeyFactory::LoadKey(KeymasterKeyBlob&& key_material,
- const AuthorizationSet& additional_params,
- AuthorizationSet&& hw_enforced,
- AuthorizationSet&& sw_enforced,
- UniquePtr<Key>* key) const {
- if (!key)
- return KM_ERROR_OUTPUT_PARAMETER_NULL;
-
- if (sw_enforced.GetTagCount(TAG_ALGORITHM) == 1)
- return super::LoadKey(move(key_material), additional_params, move(hw_enforced),
- move(sw_enforced), key);
-
- unique_ptr<RSA, RSA_Delete> rsa(engine_->BlobToRsaKey(key_material));
- if (!rsa)
- return KM_ERROR_UNKNOWN_ERROR;
-
- key->reset(new (std::nothrow)
- RsaKeymaster0Key(rsa.release(), move(hw_enforced), move(sw_enforced), this));
- if (!(*key))
- return KM_ERROR_MEMORY_ALLOCATION_FAILED;
-
- (*key)->key_material() = move(key_material);
- return KM_ERROR_OK;
-}
-
-} // namespace keymaster
diff --git a/legacy_support/rsa_keymaster1_key.cpp b/legacy_support/rsa_keymaster1_key.cpp
index 1644f3f..5859bde 100644
--- a/legacy_support/rsa_keymaster1_key.cpp
+++ b/legacy_support/rsa_keymaster1_key.cpp
@@ -24,9 +24,10 @@
namespace keymaster {
-RsaKeymaster1KeyFactory::RsaKeymaster1KeyFactory(const SoftwareKeyBlobMaker* blob_maker,
+RsaKeymaster1KeyFactory::RsaKeymaster1KeyFactory(const SoftwareKeyBlobMaker& blob_maker,
+ const KeymasterContext& context,
const Keymaster1Engine* engine)
- : RsaKeyFactory(blob_maker), engine_(engine),
+ : RsaKeyFactory(blob_maker, 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.
@@ -80,18 +81,27 @@
}
keymaster_error_t RsaKeymaster1KeyFactory::GenerateKey(const AuthorizationSet& key_description,
+ UniquePtr<Key> /* attest_key */,
+ const KeymasterBlob& /* issuer_subject */,
KeymasterKeyBlob* key_blob,
AuthorizationSet* hw_enforced,
- AuthorizationSet* sw_enforced) const {
+ AuthorizationSet* sw_enforced,
+ CertificateChain* /* cert_chain */) 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 {
+keymaster_error_t //
+RsaKeymaster1KeyFactory::ImportKey(const AuthorizationSet& key_description,
+ keymaster_key_format_t input_key_material_format,
+ const KeymasterKeyBlob& input_key_material,
+ UniquePtr<Key> /* attest_key */,
+ const KeymasterBlob& /* issuer_subject */,
+ KeymasterKeyBlob* output_key_blob, //
+ AuthorizationSet* hw_enforced, //
+ AuthorizationSet* sw_enforced,
+ CertificateChain* /* cert_chain */) const {
AuthorizationSet key_params_copy;
UpdateToWorkAroundUnsupportedDigests(key_description, &key_params_copy);
return engine_->ImportKey(key_params_copy, input_key_material_format, input_key_material,
@@ -103,18 +113,15 @@
AuthorizationSet&& hw_enforced,
AuthorizationSet&& sw_enforced,
UniquePtr<Key>* key) const {
- if (!key)
- return KM_ERROR_OUTPUT_PARAMETER_NULL;
+ if (!key) return KM_ERROR_OUTPUT_PARAMETER_NULL;
keymaster_error_t error;
RSA_Ptr rsa(engine_->BuildRsaKey(key_material, additional_params, &error));
- if (!rsa.get())
- return error;
+ if (!rsa.get()) return error;
key->reset(new (std::nothrow)
RsaKeymaster1Key(rsa.release(), move(hw_enforced), move(sw_enforced), this));
- if (!(*key))
- return KM_ERROR_MEMORY_ALLOCATION_FAILED;
+ if (!(*key)) return KM_ERROR_MEMORY_ALLOCATION_FAILED;
(*key)->key_material() = move(key_material);
return KM_ERROR_OK;
@@ -132,6 +139,8 @@
return decrypt_factory_.get();
case KM_PURPOSE_DERIVE_KEY:
case KM_PURPOSE_WRAP:
+ case KM_PURPOSE_AGREE_KEY:
+ case KM_PURPOSE_ATTEST_KEY:
break;
}
return nullptr;
diff --git a/legacy_support/rsa_keymaster1_operation.cpp b/legacy_support/rsa_keymaster1_operation.cpp
index dd2c094..cceff47 100644
--- a/legacy_support/rsa_keymaster1_operation.cpp
+++ b/legacy_support/rsa_keymaster1_operation.cpp
@@ -30,8 +30,7 @@
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;
+ 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
@@ -57,8 +56,7 @@
}
pos = begin_params.find(TAG_PADDING);
- if (pos == -1)
- return KM_ERROR_UNSUPPORTED_PADDING_MODE;
+ if (pos == -1) return KM_ERROR_UNSUPPORTED_PADDING_MODE;
switch (begin_params[pos].enumerated) {
case KM_PAD_NONE:
case KM_PAD_RSA_PSS:
@@ -97,8 +95,7 @@
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;
+ if (!key_data) return KM_ERROR_UNKNOWN_ERROR;
return key_data->error;
}
@@ -157,10 +154,14 @@
}
static const keymaster_padding_t supported_sig_padding[] = {
- KM_PAD_NONE, KM_PAD_RSA_PKCS1_1_5_SIGN, KM_PAD_RSA_PSS,
+ 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,
+ KM_PAD_NONE,
+ KM_PAD_RSA_PKCS1_1_5_ENCRYPT,
+ KM_PAD_RSA_OAEP,
};
const keymaster_padding_t*
diff --git a/legacy_support/rsa_keymaster1_operation.h b/legacy_support/rsa_keymaster1_operation.h
index c0219ea..124c4b7 100644
--- a/legacy_support/rsa_keymaster1_operation.h
+++ b/legacy_support/rsa_keymaster1_operation.h
@@ -14,8 +14,7 @@
* limitations under the License.
*/
-#ifndef SYSTEM_KEYMASTER_RSA_KEYMASTER1_OPERATION_H_
-#define SYSTEM_KEYMASTER_RSA_KEYMASTER1_OPERATION_H_
+#pragma once
#include <openssl/evp.h>
@@ -32,8 +31,7 @@
RsaKeymaster1WrappedOperation(keymaster_purpose_t purpose, const Keymaster1Engine* engine)
: purpose_(purpose), operation_handle_(0), engine_(engine) {}
~RsaKeymaster1WrappedOperation() {
- if (operation_handle_)
- Abort();
+ if (operation_handle_) Abort();
}
keymaster_error_t Begin(EVP_PKEY* rsa_key, const AuthorizationSet& input_params);
@@ -43,6 +41,7 @@
keymaster_error_t GetError(EVP_PKEY* rsa_key);
keymaster_operation_handle_t GetOperationHandle() const { return operation_handle_; }
+
protected:
keymaster_purpose_t purpose_;
keymaster_operation_handle_t operation_handle_;
@@ -66,8 +65,7 @@
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;
+ if (error != KM_ERROR_OK) return error;
return super::Begin(input_params, output_params);
}
@@ -75,8 +73,7 @@
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;
+ if (error != KM_ERROR_OK) return error;
error = super::Finish(input_params, input, signature, output_params, output);
if (wrapped_operation_.GetError(super::rsa_key_) != KM_ERROR_OK)
error = wrapped_operation_.GetError(super::rsa_key_);
@@ -85,14 +82,14 @@
keymaster_error_t Abort() override {
keymaster_error_t error = wrapped_operation_.Abort();
- if (error != KM_ERROR_OK)
- return error;
+ if (error != KM_ERROR_OK) return error;
return super::Abort();
}
keymaster_operation_handle_t operation_handle() const override {
return wrapped_operation_.GetOperationHandle();
}
+
private:
RsaKeymaster1WrappedOperation wrapped_operation_;
};
@@ -119,5 +116,3 @@
};
} // namespace keymaster
-
-#endif // SYSTEM_KEYMASTER_RSA_KEYMASTER1_OPERATION_H_
diff --git a/ng/AndroidKeyMintDevice.cpp b/ng/AndroidKeyMintDevice.cpp
new file mode 100644
index 0000000..f511c3f
--- /dev/null
+++ b/ng/AndroidKeyMintDevice.cpp
@@ -0,0 +1,472 @@
+/*
+ * Copyright 2020, 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.
+ */
+
+#define LOG_TAG "android.hardware.security.keymint-impl"
+#include <android-base/logging.h>
+
+#include "AndroidKeyMintDevice.h"
+
+#include <aidl/android/hardware/security/keymint/ErrorCode.h>
+
+#include <keymaster/android_keymaster.h>
+#include <keymaster/contexts/pure_soft_keymaster_context.h>
+#include <keymaster/keymaster_configuration.h>
+
+#include "AndroidKeyMintOperation.h"
+#include "KeyMintUtils.h"
+
+namespace aidl::android::hardware::security::keymint {
+
+using namespace keymaster; // NOLINT(google-build-using-namespace)
+
+using km_utils::authToken2AidlVec;
+using km_utils::kmBlob2vector;
+using km_utils::kmError2ScopedAStatus;
+using km_utils::kmParam2Aidl;
+using km_utils::KmParamSet;
+using km_utils::kmParamSet2Aidl;
+using km_utils::legacy_enum_conversion;
+using secureclock::TimeStampToken;
+
+namespace {
+
+vector<KeyCharacteristics> convertKeyCharacteristics(SecurityLevel keyMintSecurityLevel,
+ const AuthorizationSet& requestParams,
+ const AuthorizationSet& sw_enforced,
+ const AuthorizationSet& hw_enforced,
+ bool include_keystore_enforced = true) {
+ KeyCharacteristics keyMintEnforced{keyMintSecurityLevel, {}};
+
+ if (keyMintSecurityLevel != SecurityLevel::SOFTWARE) {
+ // We're pretending to be TRUSTED_ENVIRONMENT or STRONGBOX.
+ keyMintEnforced.authorizations = kmParamSet2Aidl(hw_enforced);
+ if (include_keystore_enforced) {
+ // Put all the software authorizations in the keystore list.
+ KeyCharacteristics keystoreEnforced{SecurityLevel::KEYSTORE,
+ kmParamSet2Aidl(sw_enforced)};
+ return {std::move(keyMintEnforced), std::move(keystoreEnforced)};
+ } else {
+ return {std::move(keyMintEnforced)};
+ }
+ }
+
+ KeyCharacteristics keystoreEnforced{SecurityLevel::KEYSTORE, {}};
+ CHECK(hw_enforced.empty()) << "Hardware-enforced list is non-empty for pure SW KeyMint";
+
+ // This is a pure software implementation, so all tags are in sw_enforced.
+ // We need to walk through the SW-enforced list and figure out which tags to
+ // return in the software list and which in the keystore list.
+
+ for (auto& entry : sw_enforced) {
+ switch (entry.tag) {
+ /* Invalid and unused */
+ case KM_TAG_ECIES_SINGLE_HASH_MODE:
+ case KM_TAG_INVALID:
+ case KM_TAG_KDF:
+ case KM_TAG_ROLLBACK_RESISTANCE:
+ CHECK(false) << "We shouldn't see tag " << entry.tag;
+ break;
+
+ /* Unimplemented */
+ case KM_TAG_ALLOW_WHILE_ON_BODY:
+ case KM_TAG_BOOTLOADER_ONLY:
+ case KM_TAG_ROLLBACK_RESISTANT:
+ case KM_TAG_STORAGE_KEY:
+ break;
+
+ /* Keystore-enforced if not locally generated. */
+ case KM_TAG_CREATION_DATETIME:
+ // A KeyMaster implementation is required to add this tag to generated/imported keys.
+ // A KeyMint implementation is not required to create this tag, only to echo it back if
+ // it was included in the key generation/import request.
+ if (requestParams.Contains(KM_TAG_CREATION_DATETIME)) {
+ keystoreEnforced.authorizations.push_back(kmParam2Aidl(entry));
+ }
+ break;
+
+ /* Disallowed in KeyCharacteristics */
+ case KM_TAG_APPLICATION_DATA:
+ case KM_TAG_ATTESTATION_APPLICATION_ID:
+ break;
+
+ /* Not key characteristics */
+ case KM_TAG_ASSOCIATED_DATA:
+ case KM_TAG_ATTESTATION_CHALLENGE:
+ case KM_TAG_ATTESTATION_ID_BRAND:
+ case KM_TAG_ATTESTATION_ID_DEVICE:
+ case KM_TAG_ATTESTATION_ID_IMEI:
+ case KM_TAG_ATTESTATION_ID_MANUFACTURER:
+ case KM_TAG_ATTESTATION_ID_MEID:
+ case KM_TAG_ATTESTATION_ID_MODEL:
+ case KM_TAG_ATTESTATION_ID_PRODUCT:
+ case KM_TAG_ATTESTATION_ID_SERIAL:
+ case KM_TAG_AUTH_TOKEN:
+ case KM_TAG_CERTIFICATE_SERIAL:
+ case KM_TAG_CERTIFICATE_SUBJECT:
+ case KM_TAG_CERTIFICATE_NOT_AFTER:
+ case KM_TAG_CERTIFICATE_NOT_BEFORE:
+ case KM_TAG_CONFIRMATION_TOKEN:
+ case KM_TAG_DEVICE_UNIQUE_ATTESTATION:
+ case KM_TAG_IDENTITY_CREDENTIAL_KEY:
+ case KM_TAG_MAC_LENGTH:
+ case KM_TAG_NONCE:
+ case KM_TAG_RESET_SINCE_ID_ROTATION:
+ case KM_TAG_ROOT_OF_TRUST:
+ case KM_TAG_UNIQUE_ID:
+ break;
+
+ /* KeyMint-enforced */
+ case KM_TAG_ALGORITHM:
+ case KM_TAG_APPLICATION_ID:
+ case KM_TAG_AUTH_TIMEOUT:
+ case KM_TAG_BLOB_USAGE_REQUIREMENTS:
+ case KM_TAG_BLOCK_MODE:
+ case KM_TAG_BOOT_PATCHLEVEL:
+ case KM_TAG_CALLER_NONCE:
+ case KM_TAG_DIGEST:
+ case KM_TAG_EARLY_BOOT_ONLY:
+ case KM_TAG_EC_CURVE:
+ case KM_TAG_EXPORTABLE:
+ case KM_TAG_INCLUDE_UNIQUE_ID:
+ case KM_TAG_KEY_SIZE:
+ case KM_TAG_MAX_USES_PER_BOOT:
+ case KM_TAG_MIN_MAC_LENGTH:
+ case KM_TAG_MIN_SECONDS_BETWEEN_OPS:
+ case KM_TAG_NO_AUTH_REQUIRED:
+ case KM_TAG_ORIGIN:
+ case KM_TAG_OS_PATCHLEVEL:
+ case KM_TAG_OS_VERSION:
+ case KM_TAG_PADDING:
+ case KM_TAG_PURPOSE:
+ case KM_TAG_RSA_OAEP_MGF_DIGEST:
+ case KM_TAG_RSA_PUBLIC_EXPONENT:
+ case KM_TAG_TRUSTED_CONFIRMATION_REQUIRED:
+ case KM_TAG_TRUSTED_USER_PRESENCE_REQUIRED:
+ case KM_TAG_UNLOCKED_DEVICE_REQUIRED:
+ case KM_TAG_USER_AUTH_TYPE:
+ case KM_TAG_USER_SECURE_ID:
+ case KM_TAG_VENDOR_PATCHLEVEL:
+ keyMintEnforced.authorizations.push_back(kmParam2Aidl(entry));
+ break;
+
+ /* Keystore-enforced */
+ case KM_TAG_ACTIVE_DATETIME:
+ case KM_TAG_ALL_APPLICATIONS:
+ case KM_TAG_ALL_USERS:
+ case KM_TAG_MAX_BOOT_LEVEL:
+ case KM_TAG_ORIGINATION_EXPIRE_DATETIME:
+ case KM_TAG_USAGE_EXPIRE_DATETIME:
+ case KM_TAG_USER_ID:
+ case KM_TAG_USAGE_COUNT_LIMIT:
+ keystoreEnforced.authorizations.push_back(kmParam2Aidl(entry));
+ break;
+ }
+ }
+
+ vector<KeyCharacteristics> retval;
+ retval.reserve(2);
+ if (!keyMintEnforced.authorizations.empty()) retval.push_back(std::move(keyMintEnforced));
+ if (include_keystore_enforced && !keystoreEnforced.authorizations.empty()) {
+ retval.push_back(std::move(keystoreEnforced));
+ }
+
+ return retval;
+}
+
+Certificate convertCertificate(const keymaster_blob_t& cert) {
+ return {std::vector<uint8_t>(cert.data, cert.data + cert.data_length)};
+}
+
+vector<Certificate> convertCertificateChain(const CertificateChain& chain) {
+ vector<Certificate> retval;
+ retval.reserve(chain.entry_count);
+ std::transform(chain.begin(), chain.end(), std::back_inserter(retval), convertCertificate);
+ return retval;
+}
+
+void addClientAndAppData(const std::vector<uint8_t>& appId, const std::vector<uint8_t>& appData,
+ ::keymaster::AuthorizationSet* params) {
+ params->Clear();
+ if (appId.size()) {
+ params->push_back(::keymaster::TAG_APPLICATION_ID, appId.data(), appId.size());
+ }
+ if (appData.size()) {
+ params->push_back(::keymaster::TAG_APPLICATION_DATA, appData.data(), appData.size());
+ }
+}
+
+} // namespace
+
+constexpr size_t kOperationTableSize = 16;
+
+AndroidKeyMintDevice::AndroidKeyMintDevice(SecurityLevel securityLevel)
+ : impl_(new ::keymaster::AndroidKeymaster(
+ [&]() -> auto {
+ auto context = new PureSoftKeymasterContext(
+ KmVersion::KEYMINT_1, static_cast<keymaster_security_level_t>(securityLevel));
+ context->SetSystemVersion(::keymaster::GetOsVersion(),
+ ::keymaster::GetOsPatchlevel());
+ return context;
+ }(),
+ kOperationTableSize)),
+ securityLevel_(securityLevel) {}
+
+AndroidKeyMintDevice::~AndroidKeyMintDevice() {}
+
+ScopedAStatus AndroidKeyMintDevice::getHardwareInfo(KeyMintHardwareInfo* info) {
+ info->versionNumber = 1;
+ info->securityLevel = securityLevel_;
+ info->keyMintName = "FakeKeyMintDevice";
+ info->keyMintAuthorName = "Google";
+ info->timestampTokenRequired = false;
+ return ScopedAStatus::ok();
+}
+
+ScopedAStatus AndroidKeyMintDevice::addRngEntropy(const vector<uint8_t>& data) {
+ if (data.size() == 0) {
+ return ScopedAStatus::ok();
+ }
+
+ AddEntropyRequest request(impl_->message_version());
+ request.random_data.Reinitialize(data.data(), data.size());
+
+ AddEntropyResponse response(impl_->message_version());
+ impl_->AddRngEntropy(request, &response);
+
+ return kmError2ScopedAStatus(response.error);
+}
+
+ScopedAStatus AndroidKeyMintDevice::generateKey(const vector<KeyParameter>& keyParams,
+ const optional<AttestationKey>& attestationKey,
+ KeyCreationResult* creationResult) {
+
+ GenerateKeyRequest request(impl_->message_version());
+ request.key_description.Reinitialize(KmParamSet(keyParams));
+ if (attestationKey) {
+ request.attestation_signing_key_blob =
+ KeymasterKeyBlob(attestationKey->keyBlob.data(), attestationKey->keyBlob.size());
+ request.attest_key_params.Reinitialize(KmParamSet(attestationKey->attestKeyParams));
+ request.issuer_subject = KeymasterBlob(attestationKey->issuerSubjectName.data(),
+ attestationKey->issuerSubjectName.size());
+ }
+
+ GenerateKeyResponse response(impl_->message_version());
+ impl_->GenerateKey(request, &response);
+
+ if (response.error != KM_ERROR_OK) {
+ // Note a key difference between this current aidl and previous hal, is
+ // that hal returns void where as aidl returns the error status. If
+ // aidl returns error, then aidl will not return any change you may make
+ // to the out parameters. This is quite different from hal where all
+ // output variable can be modified due to hal returning void.
+ //
+ // So the caller need to be aware not to expect aidl functions to clear
+ // the output variables for you in case of error. If you left some
+ // wrong data set in the out parameters, they will stay there.
+ return kmError2ScopedAStatus(response.error);
+ }
+
+ creationResult->keyBlob = kmBlob2vector(response.key_blob);
+ creationResult->keyCharacteristics = convertKeyCharacteristics(
+ securityLevel_, request.key_description, response.unenforced, response.enforced);
+ creationResult->certificateChain = convertCertificateChain(response.certificate_chain);
+ return ScopedAStatus::ok();
+}
+
+ScopedAStatus AndroidKeyMintDevice::importKey(const vector<KeyParameter>& keyParams,
+ KeyFormat keyFormat, const vector<uint8_t>& keyData,
+ const optional<AttestationKey>& attestationKey,
+ KeyCreationResult* creationResult) {
+
+ ImportKeyRequest request(impl_->message_version());
+ request.key_description.Reinitialize(KmParamSet(keyParams));
+ request.key_format = legacy_enum_conversion(keyFormat);
+ request.key_data = KeymasterKeyBlob(keyData.data(), keyData.size());
+ if (attestationKey) {
+ request.attestation_signing_key_blob =
+ KeymasterKeyBlob(attestationKey->keyBlob.data(), attestationKey->keyBlob.size());
+ request.attest_key_params.Reinitialize(KmParamSet(attestationKey->attestKeyParams));
+ request.issuer_subject = KeymasterBlob(attestationKey->issuerSubjectName.data(),
+ attestationKey->issuerSubjectName.size());
+ }
+
+ ImportKeyResponse response(impl_->message_version());
+ impl_->ImportKey(request, &response);
+
+ if (response.error != KM_ERROR_OK) {
+ return kmError2ScopedAStatus(response.error);
+ }
+
+ creationResult->keyBlob = kmBlob2vector(response.key_blob);
+ creationResult->keyCharacteristics = convertKeyCharacteristics(
+ securityLevel_, request.key_description, response.unenforced, response.enforced);
+ creationResult->certificateChain = convertCertificateChain(response.certificate_chain);
+
+ return ScopedAStatus::ok();
+}
+
+ScopedAStatus
+AndroidKeyMintDevice::importWrappedKey(const vector<uint8_t>& wrappedKeyData, //
+ const vector<uint8_t>& wrappingKeyBlob, //
+ const vector<uint8_t>& maskingKey, //
+ const vector<KeyParameter>& unwrappingParams, //
+ int64_t passwordSid, int64_t biometricSid, //
+ KeyCreationResult* creationResult) {
+
+ ImportWrappedKeyRequest request(impl_->message_version());
+ request.SetWrappedMaterial(wrappedKeyData.data(), wrappedKeyData.size());
+ request.SetWrappingMaterial(wrappingKeyBlob.data(), wrappingKeyBlob.size());
+ request.SetMaskingKeyMaterial(maskingKey.data(), maskingKey.size());
+ request.additional_params.Reinitialize(KmParamSet(unwrappingParams));
+ request.password_sid = static_cast<uint64_t>(passwordSid);
+ request.biometric_sid = static_cast<uint64_t>(biometricSid);
+
+ ImportWrappedKeyResponse response(impl_->message_version());
+ impl_->ImportWrappedKey(request, &response);
+
+ if (response.error != KM_ERROR_OK) {
+ return kmError2ScopedAStatus(response.error);
+ }
+
+ creationResult->keyBlob = kmBlob2vector(response.key_blob);
+ creationResult->keyCharacteristics = convertKeyCharacteristics(
+ securityLevel_, request.additional_params, response.unenforced, response.enforced);
+ creationResult->certificateChain = convertCertificateChain(response.certificate_chain);
+
+ return ScopedAStatus::ok();
+}
+
+ScopedAStatus AndroidKeyMintDevice::upgradeKey(const vector<uint8_t>& keyBlobToUpgrade,
+ const vector<KeyParameter>& upgradeParams,
+ vector<uint8_t>* keyBlob) {
+
+ UpgradeKeyRequest request(impl_->message_version());
+ request.SetKeyMaterial(keyBlobToUpgrade.data(), keyBlobToUpgrade.size());
+ request.upgrade_params.Reinitialize(KmParamSet(upgradeParams));
+
+ UpgradeKeyResponse response(impl_->message_version());
+ impl_->UpgradeKey(request, &response);
+
+ if (response.error != KM_ERROR_OK) {
+ return kmError2ScopedAStatus(response.error);
+ }
+
+ *keyBlob = kmBlob2vector(response.upgraded_key);
+ return ScopedAStatus::ok();
+}
+
+ScopedAStatus AndroidKeyMintDevice::deleteKey(const vector<uint8_t>& keyBlob) {
+ DeleteKeyRequest request(impl_->message_version());
+ request.SetKeyMaterial(keyBlob.data(), keyBlob.size());
+
+ DeleteKeyResponse response(impl_->message_version());
+ impl_->DeleteKey(request, &response);
+
+ return kmError2ScopedAStatus(response.error);
+}
+
+ScopedAStatus AndroidKeyMintDevice::deleteAllKeys() {
+ // There's nothing to be done to delete software key blobs.
+ DeleteAllKeysRequest request(impl_->message_version());
+ DeleteAllKeysResponse response(impl_->message_version());
+ impl_->DeleteAllKeys(request, &response);
+
+ return kmError2ScopedAStatus(response.error);
+}
+
+ScopedAStatus AndroidKeyMintDevice::destroyAttestationIds() {
+ return kmError2ScopedAStatus(KM_ERROR_UNIMPLEMENTED);
+}
+
+ScopedAStatus AndroidKeyMintDevice::begin(KeyPurpose purpose, const vector<uint8_t>& keyBlob,
+ const vector<KeyParameter>& params,
+ const optional<HardwareAuthToken>& authToken,
+ BeginResult* result) {
+
+ BeginOperationRequest request(impl_->message_version());
+ request.purpose = legacy_enum_conversion(purpose);
+ request.SetKeyMaterial(keyBlob.data(), keyBlob.size());
+ request.additional_params.Reinitialize(KmParamSet(params));
+
+ vector<uint8_t> vector_token = authToken2AidlVec(authToken);
+ request.additional_params.push_back(
+ TAG_AUTH_TOKEN, reinterpret_cast<uint8_t*>(vector_token.data()), vector_token.size());
+
+ BeginOperationResponse response(impl_->message_version());
+ impl_->BeginOperation(request, &response);
+
+ if (response.error != KM_ERROR_OK) {
+ return kmError2ScopedAStatus(response.error);
+ }
+
+ result->params = kmParamSet2Aidl(response.output_params);
+ result->challenge = response.op_handle;
+ result->operation =
+ ndk::SharedRefBase::make<AndroidKeyMintOperation>(impl_, response.op_handle);
+ return ScopedAStatus::ok();
+}
+
+ScopedAStatus AndroidKeyMintDevice::deviceLocked(
+ bool passwordOnly, const std::optional<secureclock::TimeStampToken>& timestampToken) {
+ DeviceLockedRequest request(impl_->message_version());
+ request.passwordOnly = passwordOnly;
+ if (timestampToken.has_value()) {
+ request.token.challenge = timestampToken->challenge;
+ request.token.mac = {timestampToken->mac.data(), timestampToken->mac.size()};
+ request.token.timestamp = timestampToken->timestamp.milliSeconds;
+ }
+ DeviceLockedResponse response = impl_->DeviceLocked(request);
+ return kmError2ScopedAStatus(response.error);
+}
+
+ScopedAStatus AndroidKeyMintDevice::earlyBootEnded() {
+ EarlyBootEndedResponse response = impl_->EarlyBootEnded();
+ return kmError2ScopedAStatus(response.error);
+}
+
+ScopedAStatus
+AndroidKeyMintDevice::convertStorageKeyToEphemeral(const std::vector<uint8_t>& /* storageKeyBlob */,
+ std::vector<uint8_t>* /* ephemeralKeyBlob */) {
+ return kmError2ScopedAStatus(KM_ERROR_UNIMPLEMENTED);
+}
+
+ScopedAStatus AndroidKeyMintDevice::getKeyCharacteristics(
+ const std::vector<uint8_t>& keyBlob, const std::vector<uint8_t>& appId,
+ const std::vector<uint8_t>& appData, std::vector<KeyCharacteristics>* keyCharacteristics) {
+ GetKeyCharacteristicsRequest request(impl_->message_version());
+ request.SetKeyMaterial(keyBlob.data(), keyBlob.size());
+ addClientAndAppData(appId, appData, &request.additional_params);
+
+ GetKeyCharacteristicsResponse response(impl_->message_version());
+ impl_->GetKeyCharacteristics(request, &response);
+
+ if (response.error != KM_ERROR_OK) {
+ return kmError2ScopedAStatus(response.error);
+ }
+
+ AuthorizationSet emptySet;
+ *keyCharacteristics =
+ convertKeyCharacteristics(securityLevel_, emptySet, response.unenforced, response.enforced,
+ /* include_keystore_enforced = */ false);
+
+ return ScopedAStatus::ok();
+}
+
+IKeyMintDevice* CreateKeyMintDevice(SecurityLevel securityLevel) {
+ return ::new AndroidKeyMintDevice(securityLevel);
+}
+
+} // namespace aidl::android::hardware::security::keymint
diff --git a/ng/AndroidKeyMintOperation.cpp b/ng/AndroidKeyMintOperation.cpp
new file mode 100644
index 0000000..17f6b33
--- /dev/null
+++ b/ng/AndroidKeyMintOperation.cpp
@@ -0,0 +1,127 @@
+/*
+ * Copyright 2020, 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.
+ */
+
+#define LOG_TAG "android.hardware.security.keymint-impl"
+#include <log/log.h>
+
+#include "AndroidKeyMintOperation.h"
+
+#include <aidl/android/hardware/security/keymint/ErrorCode.h>
+#include <aidl/android/hardware/security/secureclock/ISecureClock.h>
+
+#include <keymaster/android_keymaster.h>
+
+#include "KeyMintUtils.h"
+
+namespace aidl::android::hardware::security::keymint {
+
+using ::keymaster::AbortOperationRequest;
+using ::keymaster::AbortOperationResponse;
+using ::keymaster::FinishOperationRequest;
+using ::keymaster::FinishOperationResponse;
+using ::keymaster::TAG_ASSOCIATED_DATA;
+using ::keymaster::UpdateOperationRequest;
+using ::keymaster::UpdateOperationResponse;
+using secureclock::TimeStampToken;
+using namespace km_utils; // NOLINT(google-build-using-namespace)
+
+AndroidKeyMintOperation::AndroidKeyMintOperation(
+ shared_ptr<::keymaster::AndroidKeymaster> implementation, keymaster_operation_handle_t opHandle)
+ : impl_(std::move(implementation)), opHandle_(opHandle) {}
+
+AndroidKeyMintOperation::~AndroidKeyMintOperation() {
+ if (opHandle_ != 0) {
+ abort();
+ }
+}
+
+ScopedAStatus
+AndroidKeyMintOperation::updateAad(const vector<uint8_t>& input,
+ const optional<HardwareAuthToken>& /* authToken */,
+ const optional<TimeStampToken>& /* timestampToken */) {
+ UpdateOperationRequest request(impl_->message_version());
+ request.op_handle = opHandle_;
+ request.additional_params.push_back(TAG_ASSOCIATED_DATA, input.data(), input.size());
+
+ UpdateOperationResponse response(impl_->message_version());
+ impl_->UpdateOperation(request, &response);
+
+ return kmError2ScopedAStatus(response.error);
+}
+
+ScopedAStatus AndroidKeyMintOperation::update(const vector<uint8_t>& input,
+ const optional<HardwareAuthToken>& /* authToken */,
+ const optional<TimeStampToken>&
+ /* timestampToken */,
+ vector<uint8_t>* output) {
+ if (!output) return kmError2ScopedAStatus(KM_ERROR_OUTPUT_PARAMETER_NULL);
+
+ UpdateOperationRequest request(impl_->message_version());
+ request.op_handle = opHandle_;
+ request.input.Reinitialize(input.data(), input.size());
+
+ UpdateOperationResponse response(impl_->message_version());
+ impl_->UpdateOperation(request, &response);
+
+ if (response.error != KM_ERROR_OK) return kmError2ScopedAStatus(response.error);
+ if (response.input_consumed != request.input.buffer_size()) {
+ return kmError2ScopedAStatus(KM_ERROR_UNKNOWN_ERROR);
+ }
+
+ *output = kmBuffer2vector(response.output);
+ return ScopedAStatus::ok();
+}
+
+ScopedAStatus
+AndroidKeyMintOperation::finish(const optional<vector<uint8_t>>& input, //
+ const optional<vector<uint8_t>>& signature, //
+ const optional<HardwareAuthToken>& /* authToken */,
+ const optional<TimeStampToken>& /* timestampToken */,
+ const optional<vector<uint8_t>>& /* confirmationToken */,
+ vector<uint8_t>* output) {
+
+ if (!output) {
+ return ScopedAStatus(AStatus_fromServiceSpecificError(
+ static_cast<int32_t>(ErrorCode::OUTPUT_PARAMETER_NULL)));
+ }
+
+ FinishOperationRequest request(impl_->message_version());
+ request.op_handle = opHandle_;
+ if (input) request.input.Reinitialize(input->data(), input->size());
+ if (signature) request.signature.Reinitialize(signature->data(), signature->size());
+
+ FinishOperationResponse response(impl_->message_version());
+ impl_->FinishOperation(request, &response);
+ opHandle_ = 0;
+
+ if (response.error != KM_ERROR_OK) return kmError2ScopedAStatus(response.error);
+
+ *output = kmBuffer2vector(response.output);
+ return ScopedAStatus::ok();
+}
+
+ScopedAStatus AndroidKeyMintOperation::abort() {
+ AbortOperationRequest request(impl_->message_version());
+ request.op_handle = opHandle_;
+
+ AbortOperationResponse response(impl_->message_version());
+ impl_->AbortOperation(request, &response);
+ opHandle_ = 0;
+
+ return kmError2ScopedAStatus(response.error);
+}
+
+} // namespace aidl::android::hardware::security::keymint
diff --git a/ng/AndroidKeymaster3Device.cpp b/ng/AndroidKeymaster3Device.cpp
index da00d96..4539cc2 100644
--- a/ng/AndroidKeymaster3Device.cpp
+++ b/ng/AndroidKeymaster3Device.cpp
@@ -25,36 +25,35 @@
#include <keymaster/android_keymaster.h>
#include <keymaster/android_keymaster_messages.h>
-#include <keymaster/contexts/soft_keymaster_context.h>
-#include <keymaster/contexts/keymaster0_passthrough_context.h>
#include <keymaster/contexts/keymaster1_passthrough_context.h>
#include <keymaster/contexts/keymaster2_passthrough_context.h>
#include <keymaster/contexts/pure_soft_keymaster_context.h>
+#include <keymaster/contexts/soft_keymaster_context.h>
#include <keymaster/keymaster_configuration.h>
#include <keymaster/keymaster_enforcement.h>
#include <keymaster/km_openssl/soft_keymaster_enforcement.h>
+using ::keymaster::AbortOperationRequest;
+using ::keymaster::AbortOperationResponse;
using ::keymaster::AddEntropyRequest;
using ::keymaster::AddEntropyResponse;
using ::keymaster::AttestKeyRequest;
using ::keymaster::AttestKeyResponse;
using ::keymaster::AuthorizationSet;
+using ::keymaster::BeginOperationRequest;
+using ::keymaster::BeginOperationResponse;
using ::keymaster::ExportKeyRequest;
using ::keymaster::ExportKeyResponse;
+using ::keymaster::FinishOperationRequest;
+using ::keymaster::FinishOperationResponse;
using ::keymaster::GenerateKeyRequest;
using ::keymaster::GenerateKeyResponse;
using ::keymaster::GetKeyCharacteristicsRequest;
using ::keymaster::GetKeyCharacteristicsResponse;
using ::keymaster::ImportKeyRequest;
using ::keymaster::ImportKeyResponse;
-using ::keymaster::BeginOperationRequest;
-using ::keymaster::BeginOperationResponse;
using ::keymaster::UpdateOperationRequest;
using ::keymaster::UpdateOperationResponse;
-using ::keymaster::FinishOperationRequest;
-using ::keymaster::FinishOperationResponse;
-using ::keymaster::AbortOperationRequest;
-using ::keymaster::AbortOperationResponse;
namespace keymaster {
namespace ng {
@@ -222,21 +221,23 @@
AndroidKeymaster3Device::AndroidKeymaster3Device()
: impl_(new ::keymaster::AndroidKeymaster(
- [] () -> auto {
- auto context = new PureSoftKeymasterContext();
- context->SetSystemVersion(GetOsVersion(), GetOsPatchlevel());
- return context;
- } (), kOperationTableSize)), profile_(KeymasterHardwareProfile::SW) {}
+ []() -> auto {
+ auto context = new PureSoftKeymasterContext(KmVersion::KEYMASTER_3);
+ context->SetSystemVersion(GetOsVersion(), GetOsPatchlevel());
+ return context;
+ }(),
+ kOperationTableSize)),
+ profile_(KeymasterHardwareProfile::SW) {}
-
-AndroidKeymaster3Device::AndroidKeymaster3Device(KeymasterContext* context, KeymasterHardwareProfile profile)
+AndroidKeymaster3Device::AndroidKeymaster3Device(KeymasterContext* context,
+ KeymasterHardwareProfile profile)
: impl_(new ::keymaster::AndroidKeymaster(context, kOperationTableSize)), profile_(profile) {}
AndroidKeymaster3Device::~AndroidKeymaster3Device() {}
// Methods from ::android::hardware::keymaster::V3_0::IKeymasterDevice follow.
Return<void> AndroidKeymaster3Device::getHardwareFeatures(getHardwareFeatures_cb _hidl_cb) {
- switch(profile_) {
+ switch (profile_) {
case KeymasterHardwareProfile::KM0:
_hidl_cb(true /* is_secure */, false /* supports_ec */,
false /* supports_symmetric_cryptography */, false /* supports_attestation */,
@@ -264,21 +265,21 @@
Return<ErrorCode> AndroidKeymaster3Device::addRngEntropy(const hidl_vec<uint8_t>& data) {
if (data.size() == 0) return ErrorCode::OK;
- AddEntropyRequest request;
+ AddEntropyRequest request(impl_->message_version());
request.random_data.Reinitialize(data.data(), data.size());
- AddEntropyResponse response;
+ AddEntropyResponse response(impl_->message_version());
impl_->AddRngEntropy(request, &response);
return legacy_enum_conversion(response.error);
}
Return<void> AndroidKeymaster3Device::generateKey(const hidl_vec<KeyParameter>& keyParams,
- generateKey_cb _hidl_cb) {
- GenerateKeyRequest request;
+ generateKey_cb _hidl_cb) {
+ GenerateKeyRequest request(impl_->message_version());
request.key_description.Reinitialize(KmParamSet(keyParams));
- GenerateKeyResponse response;
+ GenerateKeyResponse response(impl_->message_version());
impl_->GenerateKey(request, &response);
KeyCharacteristics resultCharacteristics;
@@ -293,14 +294,14 @@
}
Return<void> AndroidKeymaster3Device::getKeyCharacteristics(const hidl_vec<uint8_t>& keyBlob,
- const hidl_vec<uint8_t>& clientId,
- const hidl_vec<uint8_t>& appData,
- getKeyCharacteristics_cb _hidl_cb) {
- GetKeyCharacteristicsRequest request;
+ const hidl_vec<uint8_t>& clientId,
+ const hidl_vec<uint8_t>& appData,
+ getKeyCharacteristics_cb _hidl_cb) {
+ GetKeyCharacteristicsRequest request(impl_->message_version());
request.SetKeyMaterial(keyBlob.data(), keyBlob.size());
addClientAndAppData(clientId, appData, &request.additional_params);
- GetKeyCharacteristicsResponse response;
+ GetKeyCharacteristicsResponse response(impl_->message_version());
impl_->GetKeyCharacteristics(request, &response);
KeyCharacteristics resultCharacteristics;
@@ -313,14 +314,15 @@
}
Return<void> AndroidKeymaster3Device::importKey(const hidl_vec<KeyParameter>& params,
- KeyFormat keyFormat, const hidl_vec<uint8_t>& keyData,
- importKey_cb _hidl_cb) {
- ImportKeyRequest request;
+ KeyFormat keyFormat,
+ const hidl_vec<uint8_t>& keyData,
+ importKey_cb _hidl_cb) {
+ ImportKeyRequest request(impl_->message_version());
request.key_description.Reinitialize(KmParamSet(params));
request.key_format = legacy_enum_conversion(keyFormat);
- request.SetKeyMaterial(keyData.data(), keyData.size());
+ request.key_data = KeymasterKeyBlob(keyData.data(), keyData.size());
- ImportKeyResponse response;
+ ImportKeyResponse response(impl_->message_version());
impl_->ImportKey(request, &response);
KeyCharacteristics resultCharacteristics;
@@ -335,16 +337,16 @@
}
Return<void> AndroidKeymaster3Device::exportKey(KeyFormat exportFormat,
- const hidl_vec<uint8_t>& keyBlob,
- const hidl_vec<uint8_t>& clientId,
- const hidl_vec<uint8_t>& appData,
- exportKey_cb _hidl_cb) {
- ExportKeyRequest request;
+ const hidl_vec<uint8_t>& keyBlob,
+ const hidl_vec<uint8_t>& clientId,
+ const hidl_vec<uint8_t>& appData,
+ exportKey_cb _hidl_cb) {
+ ExportKeyRequest request(impl_->message_version());
request.key_format = legacy_enum_conversion(exportFormat);
request.SetKeyMaterial(keyBlob.data(), keyBlob.size());
addClientAndAppData(clientId, appData, &request.additional_params);
- ExportKeyResponse response;
+ ExportKeyResponse response(impl_->message_version());
impl_->ExportKey(request, &response);
hidl_vec<uint8_t> resultKeyBlob;
@@ -356,13 +358,13 @@
}
Return<void> AndroidKeymaster3Device::attestKey(const hidl_vec<uint8_t>& keyToAttest,
- const hidl_vec<KeyParameter>& attestParams,
- attestKey_cb _hidl_cb) {
- AttestKeyRequest request;
+ const hidl_vec<KeyParameter>& attestParams,
+ attestKey_cb _hidl_cb) {
+ AttestKeyRequest request(impl_->message_version());
request.SetKeyMaterial(keyToAttest.data(), keyToAttest.size());
request.attest_params.Reinitialize(KmParamSet(attestParams));
- AttestKeyResponse response;
+ AttestKeyResponse response(impl_->message_version());
impl_->AttestKey(request, &response);
hidl_vec<hidl_vec<uint8_t>> resultCertChain;
@@ -374,18 +376,18 @@
}
Return<void> AndroidKeymaster3Device::upgradeKey(const hidl_vec<uint8_t>& keyBlobToUpgrade,
- const hidl_vec<KeyParameter>& upgradeParams,
- upgradeKey_cb _hidl_cb) {
+ const hidl_vec<KeyParameter>& upgradeParams,
+ upgradeKey_cb _hidl_cb) {
// There's nothing to be done to upgrade software key blobs. Further, the software
// implementation never returns ErrorCode::KEY_REQUIRES_UPGRADE, so this should never be called.
- UpgradeKeyRequest request;
+ UpgradeKeyRequest request(impl_->message_version());
request.SetKeyMaterial(keyBlobToUpgrade.data(), keyBlobToUpgrade.size());
request.upgrade_params.Reinitialize(KmParamSet(upgradeParams));
- UpgradeKeyResponse response;
+ UpgradeKeyResponse response(impl_->message_version());
impl_->UpgradeKey(request, &response);
- if (response.error == KM_ERROR_OK){
+ if (response.error == KM_ERROR_OK) {
_hidl_cb(ErrorCode::OK, kmBlob2hidlVec(response.upgraded_key));
} else {
_hidl_cb(legacy_enum_conversion(response.error), hidl_vec<uint8_t>());
@@ -395,10 +397,10 @@
Return<ErrorCode> AndroidKeymaster3Device::deleteKey(const hidl_vec<uint8_t>& keyBlob) {
// There's nothing to be done to delete software key blobs.
- DeleteKeyRequest request;
+ DeleteKeyRequest request(impl_->message_version());
request.SetKeyMaterial(keyBlob.data(), keyBlob.size());
- DeleteKeyResponse response;
+ DeleteKeyResponse response(impl_->message_version());
impl_->DeleteKey(request, &response);
return legacy_enum_conversion(response.error);
@@ -406,8 +408,8 @@
Return<ErrorCode> AndroidKeymaster3Device::deleteAllKeys() {
// There's nothing to be done to delete software key blobs.
- DeleteAllKeysRequest request;
- DeleteAllKeysResponse response;
+ DeleteAllKeysRequest request(impl_->message_version());
+ DeleteAllKeysResponse response(impl_->message_version());
impl_->DeleteAllKeys(request, &response);
return legacy_enum_conversion(response.error);
@@ -418,14 +420,15 @@
}
Return<void> AndroidKeymaster3Device::begin(KeyPurpose purpose, const hidl_vec<uint8_t>& key,
- const hidl_vec<KeyParameter>& inParams, begin_cb _hidl_cb) {
+ const hidl_vec<KeyParameter>& inParams,
+ begin_cb _hidl_cb) {
- BeginOperationRequest request;
+ BeginOperationRequest request(impl_->message_version());
request.purpose = legacy_enum_conversion(purpose);
request.SetKeyMaterial(key.data(), key.size());
request.additional_params.Reinitialize(KmParamSet(inParams));
- BeginOperationResponse response;
+ BeginOperationResponse response(impl_->message_version());
impl_->BeginOperation(request, &response);
hidl_vec<KeyParameter> resultParams;
@@ -438,14 +441,14 @@
}
Return<void> AndroidKeymaster3Device::update(uint64_t operationHandle,
- const hidl_vec<KeyParameter>& inParams,
- const hidl_vec<uint8_t>& input, update_cb _hidl_cb) {
- UpdateOperationRequest request;
+ const hidl_vec<KeyParameter>& inParams,
+ const hidl_vec<uint8_t>& input, update_cb _hidl_cb) {
+ UpdateOperationRequest request(impl_->message_version());
request.op_handle = operationHandle;
request.input.Reinitialize(input.data(), input.size());
request.additional_params.Reinitialize(KmParamSet(inParams));
- UpdateOperationResponse response;
+ UpdateOperationResponse response(impl_->message_version());
impl_->UpdateOperation(request, &response);
uint32_t resultConsumed = 0;
@@ -461,16 +464,17 @@
}
Return<void> AndroidKeymaster3Device::finish(uint64_t operationHandle,
- const hidl_vec<KeyParameter>& inParams,
- const hidl_vec<uint8_t>& input,
- const hidl_vec<uint8_t>& signature, finish_cb _hidl_cb) {
- FinishOperationRequest request;
+ const hidl_vec<KeyParameter>& inParams,
+ const hidl_vec<uint8_t>& input,
+ const hidl_vec<uint8_t>& signature,
+ finish_cb _hidl_cb) {
+ FinishOperationRequest request(impl_->message_version());
request.op_handle = operationHandle;
request.input.Reinitialize(input.data(), input.size());
request.signature.Reinitialize(signature.data(), signature.size());
request.additional_params.Reinitialize(KmParamSet(inParams));
- FinishOperationResponse response;
+ FinishOperationResponse response(impl_->message_version());
impl_->FinishOperation(request, &response);
hidl_vec<KeyParameter> resultParams;
@@ -484,10 +488,10 @@
}
Return<ErrorCode> AndroidKeymaster3Device::abort(uint64_t operationHandle) {
- AbortOperationRequest request;
+ AbortOperationRequest request(impl_->message_version());
request.op_handle = operationHandle;
- AbortOperationResponse response;
+ AbortOperationResponse response(impl_->message_version());
impl_->AbortOperation(request, &response);
return legacy_enum_conversion(response.error);
@@ -496,22 +500,19 @@
IKeymasterDevice* CreateKeymasterDevice() {
return new AndroidKeymaster3Device();
}
+
IKeymasterDevice* CreateKeymasterDevice(keymaster2_device_t* km2_device) {
if (ConfigureDevice(km2_device) != KM_ERROR_OK) return nullptr;
- auto context = new Keymaster2PassthroughContext(km2_device);
+ auto context = new Keymaster2PassthroughContext(KmVersion::KEYMASTER_3, km2_device);
context->SetSystemVersion(GetOsVersion(), GetOsPatchlevel());
return new AndroidKeymaster3Device(context, KeymasterHardwareProfile::KM2);
}
+
IKeymasterDevice* CreateKeymasterDevice(keymaster1_device_t* km1_device) {
- auto context = new Keymaster1PassthroughContext(km1_device);
+ auto context = new Keymaster1PassthroughContext(KmVersion::KEYMASTER_3, km1_device);
context->SetSystemVersion(GetOsVersion(), GetOsPatchlevel());
return new AndroidKeymaster3Device(context, KeymasterHardwareProfile::KM1);
}
-IKeymasterDevice* CreateKeymasterDevice(keymaster0_device_t* km0_device) {
- auto context = new Keymaster0PassthroughContext(km0_device);
- context->SetSystemVersion(GetOsVersion(), GetOsPatchlevel());
- return new AndroidKeymaster3Device(context, KeymasterHardwareProfile::KM0);
-}
} // namespace ng
} // namespace keymaster
diff --git a/ng/AndroidKeymaster41Device.cpp b/ng/AndroidKeymaster41Device.cpp
index 295d3f5..c360ff2 100644
--- a/ng/AndroidKeymaster41Device.cpp
+++ b/ng/AndroidKeymaster41Device.cpp
@@ -15,12 +15,50 @@
** limitations under the License.
*/
+#define LOG_TAG "android.hardware.keymaster@4.1 ref impl"
+#include <log/log.h>
+
#include "include/AndroidKeymaster41Device.h"
+#include <keymaster/android_keymaster.h>
+
namespace keymaster::V4_1 {
+using V4_0::ng::hidlKeyParams2Km;
+
+namespace {
+
+inline V41ErrorCode legacy_enum_conversion(const keymaster_error_t value) {
+ return static_cast<V41ErrorCode>(value);
+}
+
+} // namespace
+
IKeymasterDevice* CreateKeymasterDevice(SecurityLevel securityLevel) {
return new AndroidKeymaster41Device(securityLevel);
}
+Return<V41ErrorCode>
+AndroidKeymaster41Device::deviceLocked(bool passwordOnly,
+ const VerificationToken& verificationToken) {
+ keymaster::VerificationToken serializableToken;
+ serializableToken.challenge = verificationToken.challenge;
+ serializableToken.timestamp = verificationToken.timestamp;
+ serializableToken.parameters_verified.Reinitialize(
+ hidlKeyParams2Km(verificationToken.parametersVerified));
+ serializableToken.security_level =
+ static_cast<keymaster_security_level_t>(verificationToken.securityLevel);
+ serializableToken.mac =
+ KeymasterBlob(verificationToken.mac.data(), verificationToken.mac.size());
+ return legacy_enum_conversion(
+ impl_
+ ->DeviceLocked(DeviceLockedRequest(impl_->message_version(), passwordOnly,
+ std::move(serializableToken)))
+ .error);
+}
+
+Return<V41ErrorCode> AndroidKeymaster41Device::earlyBootEnded() {
+ return legacy_enum_conversion(impl_->EarlyBootEnded().error);
+}
+
} // namespace keymaster::V4_1
diff --git a/ng/AndroidKeymaster4Device.cpp b/ng/AndroidKeymaster4Device.cpp
index b42a19b..18d7fb4 100644
--- a/ng/AndroidKeymaster4Device.cpp
+++ b/ng/AndroidKeymaster4Device.cpp
@@ -21,6 +21,7 @@
#include "include/AndroidKeymaster4Device.h"
#include <keymasterV4_0/authorization_set.h>
+#include <keymasterV4_0/keymaster_utils.h>
#include <keymaster/android_keymaster.h>
#include <keymaster/android_keymaster_messages.h>
@@ -30,6 +31,8 @@
#include <keymaster/keymaster_enforcement.h>
#include <keymaster/km_openssl/soft_keymaster_enforcement.h>
+using android::hardware::keymaster::V4_0::support::authToken2HidlVec;
+
namespace keymaster {
namespace V4_0 {
namespace ng {
@@ -72,46 +75,8 @@
class KmParamSet : public keymaster_key_param_set_t {
public:
- explicit KmParamSet(const hidl_vec<KeyParameter>& keyParams) {
- params = new keymaster_key_param_t[keyParams.size()];
- length = keyParams.size();
- for (size_t i = 0; i < keyParams.size(); ++i) {
- auto tag = legacy_enum_conversion(keyParams[i].tag);
- switch (typeFromTag(tag)) {
- case KM_ENUM:
- case KM_ENUM_REP:
- params[i] = keymaster_param_enum(tag, keyParams[i].f.integer);
- break;
- case KM_UINT:
- case KM_UINT_REP:
- params[i] = keymaster_param_int(tag, keyParams[i].f.integer);
- break;
- case KM_ULONG:
- case KM_ULONG_REP:
- params[i] = keymaster_param_long(tag, keyParams[i].f.longInteger);
- break;
- case KM_DATE:
- params[i] = keymaster_param_date(tag, keyParams[i].f.dateTime);
- break;
- case KM_BOOL:
- if (keyParams[i].f.boolValue)
- params[i] = keymaster_param_bool(tag);
- else
- params[i].tag = KM_TAG_INVALID;
- break;
- case KM_BIGNUM:
- case KM_BYTES:
- params[i] =
- keymaster_param_blob(tag, &keyParams[i].blob[0], keyParams[i].blob.size());
- break;
- case KM_INVALID:
- default:
- params[i].tag = KM_TAG_INVALID;
- /* just skip */
- break;
- }
- }
- }
+ explicit KmParamSet(const hidl_vec<KeyParameter>& keyParams)
+ : keymaster_key_param_set_t(hidlKeyParams2Km(keyParams)) {}
KmParamSet(KmParamSet&& other) : keymaster_key_param_set_t{other.params, other.length} {
other.length = 0;
other.params = nullptr;
@@ -141,8 +106,7 @@
inline static hidl_vec<hidl_vec<uint8_t>>
kmCertChain2Hidl(const keymaster_cert_chain_t& cert_chain) {
hidl_vec<hidl_vec<uint8_t>> result;
- if (!cert_chain.entry_count || !cert_chain.entries)
- return result;
+ if (!cert_chain.entry_count || !cert_chain.entries) return result;
result.resize(cert_chain.entry_count);
for (size_t i = 0; i < cert_chain.entry_count; ++i) {
@@ -154,8 +118,7 @@
static inline hidl_vec<KeyParameter> kmParamSet2Hidl(const keymaster_key_param_set_t& set) {
hidl_vec<KeyParameter> result;
- if (set.length == 0 || set.params == nullptr)
- return result;
+ if (set.length == 0 || set.params == nullptr) return result;
result.resize(set.length);
keymaster_key_param_t* params = set.params;
@@ -209,11 +172,57 @@
} // anonymous namespace
-AndroidKeymaster4Device::AndroidKeymaster4Device(SecurityLevel securityLevel)
+keymaster_key_param_set_t hidlKeyParams2Km(const hidl_vec<KeyParameter>& keyParams) {
+ keymaster_key_param_set_t set;
+
+ set.params = new keymaster_key_param_t[keyParams.size()];
+ set.length = keyParams.size();
+
+ for (size_t i = 0; i < keyParams.size(); ++i) {
+ auto tag = legacy_enum_conversion(keyParams[i].tag);
+ switch (typeFromTag(tag)) {
+ case KM_ENUM:
+ case KM_ENUM_REP:
+ set.params[i] = keymaster_param_enum(tag, keyParams[i].f.integer);
+ break;
+ case KM_UINT:
+ case KM_UINT_REP:
+ set.params[i] = keymaster_param_int(tag, keyParams[i].f.integer);
+ break;
+ case KM_ULONG:
+ case KM_ULONG_REP:
+ set.params[i] = keymaster_param_long(tag, keyParams[i].f.longInteger);
+ break;
+ case KM_DATE:
+ set.params[i] = keymaster_param_date(tag, keyParams[i].f.dateTime);
+ break;
+ case KM_BOOL:
+ if (keyParams[i].f.boolValue)
+ set.params[i] = keymaster_param_bool(tag);
+ else
+ set.params[i].tag = KM_TAG_INVALID;
+ break;
+ case KM_BIGNUM:
+ case KM_BYTES:
+ set.params[i] =
+ keymaster_param_blob(tag, &keyParams[i].blob[0], keyParams[i].blob.size());
+ break;
+ case KM_INVALID:
+ default:
+ set.params[i].tag = KM_TAG_INVALID;
+ /* just skip */
+ break;
+ }
+ }
+
+ return set;
+}
+
+AndroidKeymaster4Device::AndroidKeymaster4Device(KmVersion version, SecurityLevel securityLevel)
: impl_(new ::keymaster::AndroidKeymaster(
[&]() -> auto {
auto context = new PureSoftKeymasterContext(
- static_cast<keymaster_security_level_t>(securityLevel));
+ version, static_cast<keymaster_security_level_t>(securityLevel));
context->SetSystemVersion(GetOsVersion(), GetOsPatchlevel());
return context;
}(),
@@ -223,8 +232,7 @@
AndroidKeymaster4Device::~AndroidKeymaster4Device() {}
Return<void> AndroidKeymaster4Device::getHardwareInfo(getHardwareInfo_cb _hidl_cb) {
- _hidl_cb(securityLevel_,
- "SoftwareKeymasterDevice", "Google");
+ _hidl_cb(securityLevel_, "SoftwareKeymasterDevice", "Google");
return Void();
}
@@ -244,7 +252,7 @@
Return<void> AndroidKeymaster4Device::computeSharedHmac(
const hidl_vec<::android::hardware::keymaster::V4_0::HmacSharingParameters>& params,
computeSharedHmac_cb _hidl_cb) {
- ComputeSharedHmacRequest request;
+ ComputeSharedHmacRequest request(impl_->message_version());
request.params_array.params_array = new keymaster::HmacSharingParameters[params.size()];
request.params_array.num_params = params.size();
for (size_t i = 0; i < params.size(); ++i) {
@@ -269,7 +277,7 @@
const ::android::hardware::keymaster::V4_0::HardwareAuthToken& authToken,
verifyAuthorization_cb _hidl_cb) {
- VerifyAuthorizationRequest request;
+ VerifyAuthorizationRequest request(impl_->message_version());
request.challenge = challenge;
request.parameters_to_verify.Reinitialize(KmParamSet(parametersToVerify));
request.auth_token.challenge = authToken.challenge;
@@ -295,12 +303,11 @@
}
Return<ErrorCode> AndroidKeymaster4Device::addRngEntropy(const hidl_vec<uint8_t>& data) {
- if (data.size() == 0)
- return ErrorCode::OK;
- AddEntropyRequest request;
+ if (data.size() == 0) return ErrorCode::OK;
+ AddEntropyRequest request(impl_->message_version());
request.random_data.Reinitialize(data.data(), data.size());
- AddEntropyResponse response;
+ AddEntropyResponse response(impl_->message_version());
impl_->AddRngEntropy(request, &response);
return legacy_enum_conversion(response.error);
@@ -308,10 +315,10 @@
Return<void> AndroidKeymaster4Device::generateKey(const hidl_vec<KeyParameter>& keyParams,
generateKey_cb _hidl_cb) {
- GenerateKeyRequest request;
+ GenerateKeyRequest request(impl_->message_version());
request.key_description.Reinitialize(KmParamSet(keyParams));
- GenerateKeyResponse response;
+ GenerateKeyResponse response(impl_->message_version());
impl_->GenerateKey(request, &response);
KeyCharacteristics resultCharacteristics;
@@ -329,11 +336,11 @@
const hidl_vec<uint8_t>& clientId,
const hidl_vec<uint8_t>& appData,
getKeyCharacteristics_cb _hidl_cb) {
- GetKeyCharacteristicsRequest request;
+ GetKeyCharacteristicsRequest request(impl_->message_version());
request.SetKeyMaterial(keyBlob.data(), keyBlob.size());
addClientAndAppData(clientId, appData, &request.additional_params);
- GetKeyCharacteristicsResponse response;
+ GetKeyCharacteristicsResponse response(impl_->message_version());
impl_->GetKeyCharacteristics(request, &response);
KeyCharacteristics resultCharacteristics;
@@ -349,12 +356,12 @@
KeyFormat keyFormat,
const hidl_vec<uint8_t>& keyData,
importKey_cb _hidl_cb) {
- ImportKeyRequest request;
+ ImportKeyRequest request(impl_->message_version());
request.key_description.Reinitialize(KmParamSet(params));
request.key_format = legacy_enum_conversion(keyFormat);
- request.SetKeyMaterial(keyData.data(), keyData.size());
+ request.key_data = KeymasterKeyBlob(keyData.data(), keyData.size());
- ImportKeyResponse response;
+ ImportKeyResponse response(impl_->message_version());
impl_->ImportKey(request, &response);
KeyCharacteristics resultCharacteristics;
@@ -373,7 +380,7 @@
const hidl_vec<uint8_t>& maskingKey, const hidl_vec<KeyParameter>& unwrappingParams,
uint64_t passwordSid, uint64_t biometricSid, importWrappedKey_cb _hidl_cb) {
- ImportWrappedKeyRequest request;
+ ImportWrappedKeyRequest request(impl_->message_version());
request.SetWrappedMaterial(wrappedKeyData.data(), wrappedKeyData.size());
request.SetWrappingMaterial(wrappingKeyBlob.data(), wrappingKeyBlob.size());
request.SetMaskingKeyMaterial(maskingKey.data(), maskingKey.size());
@@ -381,7 +388,7 @@
request.password_sid = passwordSid;
request.biometric_sid = biometricSid;
- ImportWrappedKeyResponse response;
+ ImportWrappedKeyResponse response(impl_->message_version());
impl_->ImportWrappedKey(request, &response);
KeyCharacteristics resultCharacteristics;
@@ -400,12 +407,12 @@
const hidl_vec<uint8_t>& clientId,
const hidl_vec<uint8_t>& appData,
exportKey_cb _hidl_cb) {
- ExportKeyRequest request;
+ ExportKeyRequest request(impl_->message_version());
request.key_format = legacy_enum_conversion(exportFormat);
request.SetKeyMaterial(keyBlob.data(), keyBlob.size());
addClientAndAppData(clientId, appData, &request.additional_params);
- ExportKeyResponse response;
+ ExportKeyResponse response(impl_->message_version());
impl_->ExportKey(request, &response);
hidl_vec<uint8_t> resultKeyBlob;
@@ -419,11 +426,11 @@
Return<void> AndroidKeymaster4Device::attestKey(const hidl_vec<uint8_t>& keyToAttest,
const hidl_vec<KeyParameter>& attestParams,
attestKey_cb _hidl_cb) {
- AttestKeyRequest request;
+ AttestKeyRequest request(impl_->message_version());
request.SetKeyMaterial(keyToAttest.data(), keyToAttest.size());
request.attest_params.Reinitialize(KmParamSet(attestParams));
- AttestKeyResponse response;
+ AttestKeyResponse response(impl_->message_version());
impl_->AttestKey(request, &response);
hidl_vec<hidl_vec<uint8_t>> resultCertChain;
@@ -439,11 +446,11 @@
upgradeKey_cb _hidl_cb) {
// There's nothing to be done to upgrade software key blobs. Further, the software
// implementation never returns ErrorCode::KEY_REQUIRES_UPGRADE, so this should never be called.
- UpgradeKeyRequest request;
+ UpgradeKeyRequest request(impl_->message_version());
request.SetKeyMaterial(keyBlobToUpgrade.data(), keyBlobToUpgrade.size());
request.upgrade_params.Reinitialize(KmParamSet(upgradeParams));
- UpgradeKeyResponse response;
+ UpgradeKeyResponse response(impl_->message_version());
impl_->UpgradeKey(request, &response);
if (response.error == KM_ERROR_OK) {
@@ -456,10 +463,10 @@
Return<ErrorCode> AndroidKeymaster4Device::deleteKey(const hidl_vec<uint8_t>& keyBlob) {
// There's nothing to be done to delete software key blobs.
- DeleteKeyRequest request;
+ DeleteKeyRequest request(impl_->message_version());
request.SetKeyMaterial(keyBlob.data(), keyBlob.size());
- DeleteKeyResponse response;
+ DeleteKeyResponse response(impl_->message_version());
impl_->DeleteKey(request, &response);
return legacy_enum_conversion(response.error);
@@ -467,8 +474,8 @@
Return<ErrorCode> AndroidKeymaster4Device::deleteAllKeys() {
// There's nothing to be done to delete software key blobs.
- DeleteAllKeysRequest request;
- DeleteAllKeysResponse response;
+ DeleteAllKeysRequest request(impl_->message_version());
+ DeleteAllKeysResponse response(impl_->message_version());
impl_->DeleteAllKeys(request, &response);
return legacy_enum_conversion(response.error);
@@ -480,21 +487,22 @@
Return<void> AndroidKeymaster4Device::begin(KeyPurpose purpose, const hidl_vec<uint8_t>& key,
const hidl_vec<KeyParameter>& inParams,
- const HardwareAuthToken& /* authToken */,
- begin_cb _hidl_cb) {
+ const HardwareAuthToken& authToken, begin_cb _hidl_cb) {
- BeginOperationRequest request;
+ BeginOperationRequest request(impl_->message_version());
request.purpose = legacy_enum_conversion(purpose);
request.SetKeyMaterial(key.data(), key.size());
request.additional_params.Reinitialize(KmParamSet(inParams));
- BeginOperationResponse response;
+ hidl_vec<uint8_t> hidl_vec_token = authToken2HidlVec(authToken);
+ request.additional_params.push_back(
+ TAG_AUTH_TOKEN, reinterpret_cast<uint8_t*>(hidl_vec_token.data()), hidl_vec_token.size());
+
+ BeginOperationResponse response(impl_->message_version());
impl_->BeginOperation(request, &response);
hidl_vec<KeyParameter> resultParams;
- if (response.error == KM_ERROR_OK) {
- resultParams = kmParamSet2Hidl(response.output_params);
- }
+ if (response.error == KM_ERROR_OK) resultParams = kmParamSet2Hidl(response.output_params);
_hidl_cb(legacy_enum_conversion(response.error), resultParams, response.op_handle);
return Void();
@@ -503,15 +511,19 @@
Return<void> AndroidKeymaster4Device::update(uint64_t operationHandle,
const hidl_vec<KeyParameter>& inParams,
const hidl_vec<uint8_t>& input,
- const HardwareAuthToken& /* authToken */,
+ const HardwareAuthToken& authToken ,
const VerificationToken& /* verificationToken */,
update_cb _hidl_cb) {
- UpdateOperationRequest request;
+ UpdateOperationRequest request(impl_->message_version());
request.op_handle = operationHandle;
request.input.Reinitialize(input.data(), input.size());
request.additional_params.Reinitialize(KmParamSet(inParams));
- UpdateOperationResponse response;
+ hidl_vec<uint8_t> hidl_vec_token = authToken2HidlVec(authToken);
+ request.additional_params.push_back(
+ TAG_AUTH_TOKEN, reinterpret_cast<uint8_t*>(hidl_vec_token.data()), hidl_vec_token.size());
+
+ UpdateOperationResponse response(impl_->message_version());
impl_->UpdateOperation(request, &response);
uint32_t resultConsumed = 0;
@@ -530,16 +542,21 @@
const hidl_vec<KeyParameter>& inParams,
const hidl_vec<uint8_t>& input,
const hidl_vec<uint8_t>& signature,
- const HardwareAuthToken& /* authToken */,
+ const HardwareAuthToken& authToken ,
const VerificationToken& /* verificationToken */,
finish_cb _hidl_cb) {
- FinishOperationRequest request;
+ FinishOperationRequest request(impl_->message_version());
request.op_handle = operationHandle;
request.input.Reinitialize(input.data(), input.size());
request.signature.Reinitialize(signature.data(), signature.size());
request.additional_params.Reinitialize(KmParamSet(inParams));
- FinishOperationResponse response;
+ hidl_vec<uint8_t> hidl_vec_token = authToken2HidlVec(authToken);
+ request.additional_params.push_back(
+ TAG_AUTH_TOKEN, reinterpret_cast<uint8_t*>(hidl_vec_token.data()), hidl_vec_token.size());
+
+
+ FinishOperationResponse response(impl_->message_version());
impl_->FinishOperation(request, &response);
hidl_vec<KeyParameter> resultParams;
@@ -553,10 +570,10 @@
}
Return<ErrorCode> AndroidKeymaster4Device::abort(uint64_t operationHandle) {
- AbortOperationRequest request;
+ AbortOperationRequest request(impl_->message_version());
request.op_handle = operationHandle;
- AbortOperationResponse response;
+ AbortOperationResponse response(impl_->message_version());
impl_->AbortOperation(request, &response);
return legacy_enum_conversion(response.error);
diff --git a/ng/AndroidRemotelyProvisionedComponentDevice.cpp b/ng/AndroidRemotelyProvisionedComponentDevice.cpp
new file mode 100644
index 0000000..ccd13d5
--- /dev/null
+++ b/ng/AndroidRemotelyProvisionedComponentDevice.cpp
@@ -0,0 +1,132 @@
+/*
+ * Copyright (C) 2021 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 "AndroidRemotelyProvisionedComponentDevice.h"
+
+#include <assert.h>
+#include <variant>
+
+#include <cppbor.h>
+#include <cppbor_parse.h>
+
+#include <KeyMintUtils.h>
+#include <keymaster/cppcose/cppcose.h>
+#include <keymaster/keymaster_configuration.h>
+
+#include <openssl/bn.h>
+#include <openssl/ec.h>
+#include <openssl/rand.h>
+#include <openssl/x509.h>
+
+namespace aidl::android::hardware::security::keymint {
+
+using keymaster::GenerateCsrRequest;
+using keymaster::GenerateCsrResponse;
+using keymaster::GenerateRkpKeyRequest;
+using keymaster::GenerateRkpKeyResponse;
+using keymaster::KeymasterBlob;
+using ::std::string;
+using ::std::unique_ptr;
+using ::std::vector;
+using bytevec = ::std::vector<uint8_t>;
+
+namespace {
+
+constexpr auto STATUS_FAILED = IRemotelyProvisionedComponent::STATUS_FAILED;
+
+struct AStatusDeleter {
+ void operator()(AStatus* p) { AStatus_delete(p); }
+};
+
+class Status {
+ public:
+ Status() : status_(AStatus_newOk()) {}
+ Status(int32_t errCode, const std::string& errMsg)
+ : status_(AStatus_fromServiceSpecificErrorWithMessage(errCode, errMsg.c_str())) {}
+ explicit Status(const std::string& errMsg)
+ : status_(AStatus_fromServiceSpecificErrorWithMessage(STATUS_FAILED, errMsg.c_str())) {}
+ explicit Status(AStatus* status) : status_(status ? status : AStatus_newOk()) {}
+
+ Status(Status&&) = default;
+ Status(const Status&) = delete;
+
+ operator ::ndk::ScopedAStatus() && { // NOLINT(google-explicit-constructor)
+ return ndk::ScopedAStatus(status_.release());
+ }
+
+ bool isOk() const { return AStatus_isOk(status_.get()); }
+
+ const char* getMessage() const { return AStatus_getMessage(status_.get()); }
+
+ private:
+ std::unique_ptr<AStatus, AStatusDeleter> status_;
+};
+
+} // namespace
+
+AndroidRemotelyProvisionedComponentDevice::AndroidRemotelyProvisionedComponentDevice(
+ const std::shared_ptr<AndroidKeyMintDevice>& keymint) {
+ impl_ = keymint->getKeymasterImpl();
+}
+
+ScopedAStatus AndroidRemotelyProvisionedComponentDevice::getHardwareInfo(RpcHardwareInfo* info) {
+ info->versionNumber = 1;
+ info->rpcAuthorName = "Google";
+ info->supportedEekCurve = RpcHardwareInfo::CURVE_25519;
+ return ScopedAStatus::ok();
+}
+
+ScopedAStatus AndroidRemotelyProvisionedComponentDevice::generateEcdsaP256KeyPair(
+ bool testMode, MacedPublicKey* macedPublicKey, bytevec* privateKeyHandle) {
+ GenerateRkpKeyRequest request(impl_->message_version());
+ request.test_mode = testMode;
+ GenerateRkpKeyResponse response(impl_->message_version());
+ impl_->GenerateRkpKey(request, &response);
+ if (response.error != KM_ERROR_OK) {
+ return Status(-static_cast<int32_t>(response.error), "Failure in key generation.");
+ }
+
+ macedPublicKey->macedKey = km_utils::kmBlob2vector(response.maced_public_key);
+ *privateKeyHandle = km_utils::kmBlob2vector(response.key_blob);
+ return ScopedAStatus::ok();
+}
+
+ScopedAStatus AndroidRemotelyProvisionedComponentDevice::generateCertificateRequest(
+ bool testMode, const vector<MacedPublicKey>& keysToSign, const bytevec& endpointEncCertChain,
+ const bytevec& challenge, DeviceInfo* deviceInfo, ProtectedData* protectedData,
+ bytevec* keysToSignMac) {
+ GenerateCsrRequest request(impl_->message_version());
+ request.test_mode = testMode;
+ request.num_keys = keysToSign.size();
+ request.keys_to_sign_array = new KeymasterBlob[keysToSign.size()];
+ for (size_t i = 0; i < keysToSign.size(); i++) {
+ request.SetKeyToSign(i, keysToSign[i].macedKey.data(), keysToSign[i].macedKey.size());
+ }
+ request.SetEndpointEncCertChain(endpointEncCertChain.data(), endpointEncCertChain.size());
+ request.SetChallenge(challenge.data(), challenge.size());
+ GenerateCsrResponse response(impl_->message_version());
+ impl_->GenerateCsr(request, &response);
+
+ if (response.error != KM_ERROR_OK) {
+ return Status(-static_cast<int32_t>(response.error), "Failure in CSR Generation.");
+ }
+ deviceInfo->deviceInfo = km_utils::kmBlob2vector(response.device_info_blob);
+ protectedData->protectedData = km_utils::kmBlob2vector(response.protected_data_blob);
+ *keysToSignMac = km_utils::kmBlob2vector(response.keys_to_sign_mac);
+ return ScopedAStatus::ok();
+}
+
+} // namespace aidl::android::hardware::security::keymint
diff --git a/ng/AndroidSecureClock.cpp b/ng/AndroidSecureClock.cpp
new file mode 100644
index 0000000..4c69621
--- /dev/null
+++ b/ng/AndroidSecureClock.cpp
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2020, 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.
+ */
+
+#define LOG_TAG "android.hardware.security.secureclock-impl"
+#include <log/log.h>
+
+#include "AndroidSecureClock.h"
+
+#include <aidl/android/hardware/security/keymint/ErrorCode.h>
+
+#include "KeyMintUtils.h"
+#include <keymaster/android_keymaster.h>
+#include <keymaster/keymaster_configuration.h>
+
+namespace aidl::android::hardware::security::secureclock {
+
+using keymaster::GenerateTimestampTokenRequest;
+using keymaster::GenerateTimestampTokenResponse;
+using keymint::km_utils::kmBlob2vector;
+using keymint::km_utils::kmError2ScopedAStatus;
+
+AndroidSecureClock::AndroidSecureClock(
+ const std::shared_ptr<keymint::AndroidKeyMintDevice>& keymint)
+ : impl_(keymint->getKeymasterImpl()) {}
+
+AndroidSecureClock::~AndroidSecureClock() {}
+
+ScopedAStatus AndroidSecureClock::generateTimeStamp(int64_t challenge, TimeStampToken* token) {
+ GenerateTimestampTokenRequest request(impl_->message_version());
+ request.challenge = challenge;
+ GenerateTimestampTokenResponse response(request.message_version);
+ impl_->GenerateTimestampToken(request, &response);
+ if (response.error != KM_ERROR_OK) {
+ return kmError2ScopedAStatus(response.error);
+ }
+ token->challenge = response.token.challenge;
+ token->timestamp.milliSeconds = static_cast<int64_t>(response.token.timestamp);
+ token->mac = kmBlob2vector(response.token.mac);
+ return ScopedAStatus::ok();
+}
+
+} // namespace aidl::android::hardware::security::secureclock
diff --git a/ng/AndroidSharedSecret.cpp b/ng/AndroidSharedSecret.cpp
new file mode 100644
index 0000000..0ae3d2d
--- /dev/null
+++ b/ng/AndroidSharedSecret.cpp
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2020, 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.
+ */
+
+#define LOG_TAG "android.hardware.security.sharedsecret-impl"
+#include <log/log.h>
+
+#include "AndroidSharedSecret.h"
+#include "KeyMintUtils.h"
+#include <aidl/android/hardware/security/keymint/ErrorCode.h>
+#include <keymaster/android_keymaster.h>
+
+namespace aidl::android::hardware::security::sharedsecret {
+
+using keymaster::ComputeSharedHmacRequest;
+using keymint::km_utils::kmBlob2vector;
+using keymint::km_utils::kmError2ScopedAStatus;
+
+AndroidSharedSecret::AndroidSharedSecret(
+ const std::shared_ptr<keymint::AndroidKeyMintDevice>& keymint)
+ : impl_(keymint->getKeymasterImpl()) {}
+
+AndroidSharedSecret::~AndroidSharedSecret() {}
+
+ScopedAStatus AndroidSharedSecret::getSharedSecretParameters(SharedSecretParameters* params) {
+ auto response = impl_->GetHmacSharingParameters();
+ params->seed = kmBlob2vector(response.params.seed);
+ params->nonce = {std::begin(response.params.nonce), std::end(response.params.nonce)};
+ return kmError2ScopedAStatus(response.error);
+}
+
+ScopedAStatus AndroidSharedSecret::computeSharedSecret(const vector<SharedSecretParameters>& params,
+ vector<uint8_t>* sharingCheck) {
+ ComputeSharedHmacRequest request(impl_->message_version());
+ request.params_array.params_array = new keymaster::HmacSharingParameters[params.size()];
+ request.params_array.num_params = params.size();
+ for (size_t i = 0; i < params.size(); ++i) {
+ request.params_array.params_array[i].seed = {params[i].seed.data(), params[i].seed.size()};
+ if (sizeof(request.params_array.params_array[i].nonce) != params[i].nonce.size()) {
+ return kmError2ScopedAStatus(KM_ERROR_INVALID_ARGUMENT);
+ }
+ memcpy(request.params_array.params_array[i].nonce, params[i].nonce.data(),
+ params[i].nonce.size());
+ }
+ auto response = impl_->ComputeSharedHmac(request);
+ if (response.error == KM_ERROR_OK) *sharingCheck = kmBlob2vector(response.sharing_check);
+ return kmError2ScopedAStatus(response.error);
+}
+
+} // namespace aidl::android::hardware::security::sharedsecret
diff --git a/ng/KeyMintAidlUtils.cpp b/ng/KeyMintAidlUtils.cpp
new file mode 100644
index 0000000..17a53a5
--- /dev/null
+++ b/ng/KeyMintAidlUtils.cpp
@@ -0,0 +1,147 @@
+/*
+ *
+ * Copyright 2020, 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 "include/KeyMintAidlUtils.h"
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace keymint {
+
+using namespace ::keymaster;
+
+vector<uint8_t> authToken2AidlVec(const HardwareAuthToken& token) {
+ static_assert(1 /* version size */ + sizeof(token.challenge) + sizeof(token.userId) +
+ sizeof(token.authenticatorId) + sizeof(token.authenticatorType) +
+ sizeof(token.timestamp) + 32 /* HMAC size */
+ == sizeof(hw_auth_token_t),
+ "HardwareAuthToken content size does not match hw_auth_token_t size");
+
+ vector<uint8_t> result;
+
+ if (token.mac.size() <= 32) return result;
+
+ result.resize(sizeof(hw_auth_token_t));
+ auto pos = result.begin();
+ *pos++ = 0; // Version byte
+ pos = copy_bytes_to_iterator(token.challenge, pos);
+ pos = copy_bytes_to_iterator(token.userId, pos);
+ pos = copy_bytes_to_iterator(token.authenticatorId, pos);
+ pos = copy_bytes_to_iterator(token.authenticatorType, pos);
+ pos = copy_bytes_to_iterator(token.timestamp, pos);
+ pos = std::copy(token.mac.data(), token.mac.data() + token.mac.size(), pos);
+
+ return result;
+}
+
+// TODO(seleneh): This needs to be modified depends on how aidl support for union came out to
+// be.
+vector<KeyParameter> kmParamSet2Aidl(const keymaster_key_param_set_t& set) {
+ vector<KeyParameter> result;
+ if (set.length == 0 || set.params == nullptr) return result;
+
+ result.resize(set.length);
+ keymaster_key_param_t* params = set.params;
+ for (size_t i = 0; i < set.length; ++i) {
+ auto tag = params[i].tag;
+ result[i].tag = legacy_enum_conversion(tag);
+ switch (typeFromTag(tag)) {
+ case KM_ENUM:
+ case KM_ENUM_REP:
+ result[i].integer = params[i].enumerated;
+ break;
+ case KM_UINT:
+ case KM_UINT_REP:
+ result[i].integer = params[i].integer;
+ break;
+ case KM_ULONG:
+ case KM_ULONG_REP:
+ result[i].longInteger = params[i].long_integer;
+ break;
+ case KM_DATE:
+ result[i].longInteger = params[i].date_time;
+ break;
+ case KM_BOOL:
+ result[i].boolValue = params[i].boolean;
+ break;
+ case KM_BIGNUM:
+ case KM_BYTES:
+ result[i].blob.assign(params[i].blob.data,
+ params[i].blob.data + params[i].blob.data_length);
+ break;
+ case KM_INVALID:
+ default:
+ params[i].tag = KM_TAG_INVALID;
+ /* just skip */
+ break;
+ }
+ }
+ return result;
+}
+
+// TODO(seleneh): This needs to be modified depends on how aidl support for union came out to
+// be.
+keymaster_key_param_set_t aidlKeyParams2Km(const vector<KeyParameter>& keyParams) {
+ keymaster_key_param_set_t set;
+
+ set.params = new keymaster_key_param_t[keyParams.size()];
+ set.length = keyParams.size();
+
+ for (size_t i = 0; i < keyParams.size(); ++i) {
+ auto tag = legacy_enum_conversion(keyParams[i].tag);
+ switch (typeFromTag(tag)) {
+ case KM_ENUM:
+ case KM_ENUM_REP:
+ set.params[i] = keymaster_param_enum(tag, keyParams[i].integer);
+ break;
+ case KM_UINT:
+ case KM_UINT_REP:
+ set.params[i] = keymaster_param_int(tag, keyParams[i].integer);
+ break;
+ case KM_ULONG:
+ case KM_ULONG_REP:
+ set.params[i] = keymaster_param_long(tag, keyParams[i].longInteger);
+ break;
+ case KM_DATE:
+ set.params[i] = keymaster_param_date(tag, keyParams[i].longInteger);
+ break;
+ case KM_BOOL:
+ if (keyParams[i].boolValue)
+ set.params[i] = keymaster_param_bool(tag);
+ else
+ set.params[i].tag = KM_TAG_INVALID;
+ break;
+ case KM_BIGNUM:
+ case KM_BYTES:
+ set.params[i] =
+ keymaster_param_blob(tag, keyParams[i].blob.data(), keyParams[i].blob.size());
+ break;
+ case KM_INVALID:
+ default:
+ set.params[i].tag = KM_TAG_INVALID;
+ /* just skip */
+ break;
+ }
+ }
+
+ return set;
+}
+
+} // namespace keymint
+} // namespace hardware
+} // namespace android
+} // namespace aidl
diff --git a/ng/KeyMintUtils.cpp b/ng/KeyMintUtils.cpp
new file mode 100644
index 0000000..45967fd
--- /dev/null
+++ b/ng/KeyMintUtils.cpp
@@ -0,0 +1,247 @@
+/*
+ * Copyright 2020, 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.
+ */
+
+#define LOG_TAG "android.hardware.security.keymint-impl"
+#include <android-base/logging.h>
+
+#include "KeyMintUtils.h"
+
+namespace aidl::android::hardware::security::keymint::km_utils {
+
+namespace {
+
+using keymaster::hton;
+
+KeyParameter kmEnumParam2Aidl(const keymaster_key_param_t& param) {
+ switch (param.tag) {
+ case KM_TAG_PURPOSE:
+ return KeyParameter{Tag::PURPOSE, KeyParameterValue::make<KeyParameterValue::keyPurpose>(
+ static_cast<KeyPurpose>(param.enumerated))};
+ case KM_TAG_ALGORITHM:
+ return KeyParameter{Tag::ALGORITHM, KeyParameterValue::make<KeyParameterValue::algorithm>(
+ static_cast<Algorithm>(param.enumerated))};
+ case KM_TAG_BLOCK_MODE:
+ return KeyParameter{Tag::BLOCK_MODE, KeyParameterValue::make<KeyParameterValue::blockMode>(
+ static_cast<BlockMode>(param.enumerated))};
+ case KM_TAG_DIGEST:
+ return KeyParameter{Tag::DIGEST, KeyParameterValue::make<KeyParameterValue::digest>(
+ static_cast<Digest>(param.enumerated))};
+ case KM_TAG_PADDING:
+ return KeyParameter{Tag::PADDING, KeyParameterValue::make<KeyParameterValue::paddingMode>(
+ static_cast<PaddingMode>(param.enumerated))};
+ case KM_TAG_EC_CURVE:
+ return KeyParameter{Tag::EC_CURVE, KeyParameterValue::make<KeyParameterValue::ecCurve>(
+ static_cast<EcCurve>(param.enumerated))};
+ case KM_TAG_USER_AUTH_TYPE:
+ return KeyParameter{Tag::USER_AUTH_TYPE,
+ KeyParameterValue::make<KeyParameterValue::hardwareAuthenticatorType>(
+ static_cast<HardwareAuthenticatorType>(param.enumerated))};
+ case KM_TAG_ORIGIN:
+ return KeyParameter{Tag::ORIGIN, KeyParameterValue::make<KeyParameterValue::origin>(
+ static_cast<KeyOrigin>(param.enumerated))};
+ case KM_TAG_BLOB_USAGE_REQUIREMENTS:
+ case KM_TAG_KDF:
+ default:
+ return KeyParameter{Tag::INVALID, false};
+ }
+}
+
+keymaster_key_param_t kInvalidTag{.tag = KM_TAG_INVALID, .integer = 0};
+
+template <KeyParameterValue::Tag aidl_tag>
+keymaster_key_param_t aidlEnumVal2Km(keymaster_tag_t km_tag, const KeyParameterValue& value) {
+ return value.getTag() == aidl_tag
+ ? keymaster_param_enum(km_tag, static_cast<uint32_t>(value.get<aidl_tag>()))
+ : kInvalidTag;
+}
+
+keymaster_key_param_t aidlEnumParam2Km(const KeyParameter& param) {
+ auto tag = km_utils::legacy_enum_conversion(param.tag);
+ switch (tag) {
+ case KM_TAG_PURPOSE:
+ return aidlEnumVal2Km<KeyParameterValue::keyPurpose>(tag, param.value);
+ case KM_TAG_ALGORITHM:
+ return aidlEnumVal2Km<KeyParameterValue::algorithm>(tag, param.value);
+ case KM_TAG_BLOCK_MODE:
+ return aidlEnumVal2Km<KeyParameterValue::blockMode>(tag, param.value);
+ case KM_TAG_DIGEST:
+ case KM_TAG_RSA_OAEP_MGF_DIGEST:
+ return aidlEnumVal2Km<KeyParameterValue::digest>(tag, param.value);
+ case KM_TAG_PADDING:
+ return aidlEnumVal2Km<KeyParameterValue::paddingMode>(tag, param.value);
+ case KM_TAG_EC_CURVE:
+ return aidlEnumVal2Km<KeyParameterValue::ecCurve>(tag, param.value);
+ case KM_TAG_USER_AUTH_TYPE:
+ return aidlEnumVal2Km<KeyParameterValue::hardwareAuthenticatorType>(tag, param.value);
+ case KM_TAG_ORIGIN:
+ return aidlEnumVal2Km<KeyParameterValue::origin>(tag, param.value);
+ case KM_TAG_BLOB_USAGE_REQUIREMENTS:
+ case KM_TAG_KDF:
+ default:
+ CHECK(false) << "Unknown or unused enum tag: Something is broken";
+ return keymaster_param_enum(tag, false);
+ }
+}
+
+} // namespace
+
+vector<uint8_t> authToken2AidlVec(const std::optional<HardwareAuthToken>& token) {
+ static_assert(1 /* version size */ + sizeof(token->challenge) + sizeof(token->userId) +
+ sizeof(token->authenticatorId) + sizeof(token->authenticatorType) +
+ sizeof(token->timestamp) + 32 /* HMAC size */
+ == sizeof(hw_auth_token_t),
+ "HardwareAuthToken content size does not match hw_auth_token_t size");
+
+ vector<uint8_t> result;
+
+ if (!token.has_value()) return result;
+ if (token->mac.size() < 32) return result;
+
+ result.resize(sizeof(hw_auth_token_t));
+ auto pos = result.begin();
+ *pos++ = 0; // Version byte
+ pos = copy_bytes_to_iterator(token->challenge, pos);
+ pos = copy_bytes_to_iterator(token->userId, pos);
+ pos = copy_bytes_to_iterator(token->authenticatorId, pos);
+ pos = copy_bytes_to_iterator(hton(static_cast<uint32_t>(token->authenticatorType)), pos);
+ pos = copy_bytes_to_iterator(hton(token->timestamp.milliSeconds), pos);
+ pos = std::copy(token->mac.data(), token->mac.data() + token->mac.size(), pos);
+
+ return result;
+}
+
+KeyParameter kmParam2Aidl(const keymaster_key_param_t& param) {
+ auto tag = legacy_enum_conversion(param.tag);
+ switch (typeFromTag(param.tag)) {
+ case KM_ENUM:
+ case KM_ENUM_REP:
+ return kmEnumParam2Aidl(param);
+ break;
+
+ case KM_UINT:
+ case KM_UINT_REP:
+ return KeyParameter{tag,
+ KeyParameterValue::make<KeyParameterValue::integer>(param.integer)};
+
+ case KM_ULONG:
+ case KM_ULONG_REP:
+ return KeyParameter{
+ tag, KeyParameterValue::make<KeyParameterValue::longInteger>(param.long_integer)};
+ break;
+
+ case KM_DATE:
+ return KeyParameter{tag,
+ KeyParameterValue::make<KeyParameterValue::dateTime>(param.date_time)};
+ break;
+
+ case KM_BOOL:
+ return KeyParameter{tag, param.boolean};
+ break;
+
+ case KM_BIGNUM:
+ case KM_BYTES:
+ return {tag, KeyParameterValue::make<KeyParameterValue::blob>(
+ std::vector(param.blob.data, param.blob.data + param.blob.data_length))};
+ break;
+
+ case KM_INVALID:
+ default:
+ CHECK(false) << "Unknown or unused tag type: Something is broken";
+ return KeyParameter{Tag::INVALID, false};
+ break;
+ }
+}
+
+vector<KeyParameter> kmParamSet2Aidl(const keymaster_key_param_set_t& set) {
+ vector<KeyParameter> result;
+ if (set.length == 0 || set.params == nullptr) return result;
+
+ result.reserve(set.length);
+ for (size_t i = 0; i < set.length; ++i) {
+ result.push_back(kmParam2Aidl(set.params[i]));
+ }
+ return result;
+}
+
+keymaster_key_param_set_t aidlKeyParams2Km(const vector<KeyParameter>& keyParams) {
+ keymaster_key_param_set_t set;
+
+ set.params = static_cast<keymaster_key_param_t*>(
+ malloc(keyParams.size() * sizeof(keymaster_key_param_t)));
+ set.length = keyParams.size();
+
+ for (size_t i = 0; i < keyParams.size(); ++i) {
+ const auto& param = keyParams[i];
+ auto tag = legacy_enum_conversion(param.tag);
+ switch (typeFromTag(tag)) {
+
+ case KM_ENUM:
+ case KM_ENUM_REP:
+ set.params[i] = aidlEnumParam2Km(param);
+ break;
+
+ case KM_UINT:
+ case KM_UINT_REP:
+ set.params[i] =
+ param.value.getTag() == KeyParameterValue::integer
+ ? keymaster_param_int(tag, param.value.get<KeyParameterValue::integer>())
+ : kInvalidTag;
+ break;
+
+ case KM_ULONG:
+ case KM_ULONG_REP:
+ set.params[i] =
+ param.value.getTag() == KeyParameterValue::longInteger
+ ? keymaster_param_long(tag, param.value.get<KeyParameterValue::longInteger>())
+ : kInvalidTag;
+ break;
+
+ case KM_DATE:
+ set.params[i] =
+ param.value.getTag() == KeyParameterValue::dateTime
+ ? keymaster_param_date(tag, param.value.get<KeyParameterValue::dateTime>())
+ : kInvalidTag;
+ break;
+
+ case KM_BOOL:
+ set.params[i] = keymaster_param_bool(tag);
+ break;
+
+ case KM_BIGNUM:
+ case KM_BYTES:
+ if (param.value.getTag() == KeyParameterValue::blob) {
+ const auto& value = param.value.get<KeyParameterValue::blob>();
+ uint8_t* copy = static_cast<uint8_t*>(malloc(value.size()));
+ std::copy(value.begin(), value.end(), copy);
+ set.params[i] = keymaster_param_blob(tag, copy, value.size());
+ } else {
+ set.params[i] = kInvalidTag;
+ }
+ break;
+
+ case KM_INVALID:
+ default:
+ CHECK(false) << "Invalid tag: Something is broken";
+ set.params[i].tag = KM_TAG_INVALID;
+ /* just skip */
+ break;
+ }
+ }
+
+ return set;
+}
+
+} // namespace aidl::android::hardware::security::keymint::km_utils
diff --git a/ng/include/AndroidKeyMintDevice.h b/ng/include/AndroidKeyMintDevice.h
new file mode 100644
index 0000000..e4ea976
--- /dev/null
+++ b/ng/include/AndroidKeyMintDevice.h
@@ -0,0 +1,93 @@
+/*
+ * Copyright 2020, 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.
+ */
+
+#pragma once
+
+#include <aidl/android/hardware/security/keymint/BnKeyMintDevice.h>
+#include <aidl/android/hardware/security/keymint/BnKeyMintOperation.h>
+#include <aidl/android/hardware/security/keymint/HardwareAuthToken.h>
+
+namespace keymaster {
+class AndroidKeymaster;
+}
+
+namespace aidl::android::hardware::security::keymint {
+using ::ndk::ScopedAStatus;
+using std::optional;
+using std::shared_ptr;
+using std::vector;
+
+using secureclock::TimeStampToken;
+
+class AndroidKeyMintDevice : public BnKeyMintDevice {
+ public:
+ explicit AndroidKeyMintDevice(SecurityLevel securityLevel);
+ virtual ~AndroidKeyMintDevice();
+
+ ScopedAStatus getHardwareInfo(KeyMintHardwareInfo* info) override;
+
+ ScopedAStatus addRngEntropy(const vector<uint8_t>& data) override;
+
+ ScopedAStatus generateKey(const vector<KeyParameter>& keyParams,
+ const optional<AttestationKey>& attestationKey,
+ KeyCreationResult* creationResult) override;
+
+ ScopedAStatus importKey(const vector<KeyParameter>& keyParams, KeyFormat keyFormat,
+ const vector<uint8_t>& keyData,
+ const optional<AttestationKey>& attestationKey,
+ KeyCreationResult* creationResult) override;
+
+ ScopedAStatus importWrappedKey(const vector<uint8_t>& wrappedKeyData,
+ const vector<uint8_t>& wrappingKeyBlob,
+ const vector<uint8_t>& maskingKey,
+ const vector<KeyParameter>& unwrappingParams,
+ int64_t passwordSid, int64_t biometricSid,
+ KeyCreationResult* creationResult) override;
+
+ ScopedAStatus upgradeKey(const vector<uint8_t>& keyBlobToUpgrade,
+ const vector<KeyParameter>& upgradeParams,
+ vector<uint8_t>* keyBlob) override;
+
+ ScopedAStatus deleteKey(const vector<uint8_t>& keyBlob) override;
+ ScopedAStatus deleteAllKeys() override;
+ ScopedAStatus destroyAttestationIds() override;
+
+ ScopedAStatus begin(KeyPurpose purpose, const vector<uint8_t>& keyBlob,
+ const vector<KeyParameter>& params,
+ const optional<HardwareAuthToken>& authToken, BeginResult* result) override;
+
+ ScopedAStatus deviceLocked(bool passwordOnly,
+ const optional<TimeStampToken>& timestampToken) override;
+ ScopedAStatus earlyBootEnded() override;
+
+ ScopedAStatus convertStorageKeyToEphemeral(const std::vector<uint8_t>& storageKeyBlob,
+ std::vector<uint8_t>* ephemeralKeyBlob) override;
+
+ ScopedAStatus
+ getKeyCharacteristics(const std::vector<uint8_t>& keyBlob, const std::vector<uint8_t>& appId,
+ const std::vector<uint8_t>& appData,
+ std::vector<KeyCharacteristics>* keyCharacteristics) override;
+
+ shared_ptr<::keymaster::AndroidKeymaster>& getKeymasterImpl() { return impl_; }
+
+ protected:
+ std::shared_ptr<::keymaster::AndroidKeymaster> impl_;
+ SecurityLevel securityLevel_;
+};
+
+IKeyMintDevice* CreateKeyMintDevice(SecurityLevel securityLevel);
+
+} // namespace aidl::android::hardware::security::keymint
diff --git a/ng/include/AndroidKeyMintOperation.h b/ng/include/AndroidKeyMintOperation.h
new file mode 100644
index 0000000..064d05d
--- /dev/null
+++ b/ng/include/AndroidKeyMintOperation.h
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2020, 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.
+ */
+
+#pragma once
+
+#include <aidl/android/hardware/security/keymint/BnKeyMintOperation.h>
+#include <aidl/android/hardware/security/secureclock/ISecureClock.h>
+
+#include <hardware/keymaster_defs.h>
+
+namespace keymaster {
+class AndroidKeymaster;
+}
+
+namespace aidl::android::hardware::security::keymint {
+
+using ::ndk::ScopedAStatus;
+using secureclock::TimeStampToken;
+using std::optional;
+using std::shared_ptr;
+using std::string;
+using std::vector;
+
+class AndroidKeyMintOperation : public BnKeyMintOperation {
+ public:
+ explicit AndroidKeyMintOperation(const shared_ptr<::keymaster::AndroidKeymaster> implementation,
+ keymaster_operation_handle_t opHandle);
+ virtual ~AndroidKeyMintOperation();
+
+ ScopedAStatus updateAad(const vector<uint8_t>& input,
+ const optional<HardwareAuthToken>& authToken,
+ const optional<TimeStampToken>& timestampToken) override;
+
+ ScopedAStatus update(const vector<uint8_t>& input, const optional<HardwareAuthToken>& authToken,
+ const optional<TimeStampToken>& timestampToken,
+ vector<uint8_t>* output) override;
+
+ ScopedAStatus finish(const optional<vector<uint8_t>>& input, //
+ const optional<vector<uint8_t>>& signature, //
+ const optional<HardwareAuthToken>& authToken, //
+ const optional<TimeStampToken>& timestampToken,
+ const optional<vector<uint8_t>>& confirmationToken,
+ vector<uint8_t>* output) override;
+
+ ScopedAStatus abort() override;
+
+ protected:
+ std::shared_ptr<::keymaster::AndroidKeymaster> impl_;
+ keymaster_operation_handle_t opHandle_;
+};
+
+} // namespace aidl::android::hardware::security::keymint
diff --git a/ng/include/AndroidKeymaster3Device.h b/ng/include/AndroidKeymaster3Device.h
index 700fd1c..17f472a 100644
--- a/ng/include/AndroidKeymaster3Device.h
+++ b/ng/include/AndroidKeymaster3Device.h
@@ -15,8 +15,7 @@
** limitations under the License.
*/
-#ifndef HIDL_android_hardware_keymaster_V3_0_AndroidKeymaster3Device_H_
-#define HIDL_android_hardware_keymaster_V3_0_AndroidKeymaster3Device_H_
+#pragma once
#include <android/hardware/keymaster/3.0/IKeymasterDevice.h>
@@ -33,17 +32,17 @@
namespace ng {
+using ::android::sp;
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
using ::android::hardware::keymaster::V3_0::ErrorCode;
using ::android::hardware::keymaster::V3_0::IKeymasterDevice;
using ::android::hardware::keymaster::V3_0::KeyCharacteristics;
using ::android::hardware::keymaster::V3_0::KeyFormat;
using ::android::hardware::keymaster::V3_0::KeyParameter;
using ::android::hardware::keymaster::V3_0::KeyPurpose;
-using ::android::hardware::Return;
-using ::android::hardware::Void;
-using ::android::hardware::hidl_vec;
-using ::android::hardware::hidl_string;
-using ::android::sp;
enum class KeymasterHardwareProfile : uint32_t {
SW,
@@ -103,5 +102,3 @@
} // namespace ng
} // namespace keymaster
-
-#endif // HIDL_android_hardware_keymaster_V3_0_AndroidKeymaster3Device_H_
diff --git a/ng/include/AndroidKeymaster41Device.h b/ng/include/AndroidKeymaster41Device.h
index 2b3d0db..3a4b512 100644
--- a/ng/include/AndroidKeymaster41Device.h
+++ b/ng/include/AndroidKeymaster41Device.h
@@ -21,7 +21,6 @@
#include <android/hardware/keymaster/4.1/IKeymasterDevice.h>
#include <android/hardware/keymaster/4.1/types.h>
#include <hidl/Status.h>
-#include <keymasterV4_1/Operation.h>
#include "AndroidKeymaster4Device.h"
@@ -47,16 +46,15 @@
using ::android::hardware::keymaster::V4_0::SecurityLevel;
using ::android::hardware::keymaster::V4_0::VerificationToken;
using ::android::hardware::keymaster::V4_1::IKeymasterDevice;
-using ::android::hardware::keymaster::V4_1::IOperation;
using ::android::hardware::keymaster::V4_1::Tag;
using V41ErrorCode = ::android::hardware::keymaster::V4_1::ErrorCode;
-V41ErrorCode convert(ErrorCode error_code) {
+inline V41ErrorCode convert(ErrorCode error_code) {
return static_cast<V41ErrorCode>(error_code);
}
-ErrorCode convert(V41ErrorCode error_code) {
+inline ErrorCode convert(V41ErrorCode error_code) {
return static_cast<ErrorCode>(error_code);
}
@@ -64,29 +62,13 @@
using super = V4_0::ng::AndroidKeymaster4Device;
public:
- explicit AndroidKeymaster41Device(SecurityLevel securityLevel) : super(securityLevel) {}
+ explicit AndroidKeymaster41Device(SecurityLevel securityLevel)
+ : super(KmVersion::KEYMASTER_4_1, securityLevel) {}
virtual ~AndroidKeymaster41Device() {}
Return<V41ErrorCode> deviceLocked(bool /* passwordOnly */,
- const VerificationToken& /* verificationToken */) override {
- // TODO(swillden): Add feature to AndroidKeymaster and call from here.
- return convert(ErrorCode::UNIMPLEMENTED);
- }
- Return<V41ErrorCode> earlyBootEnded() override {
- // TODO(swillden): Add feature to AndroidKeymaster and call from here.
- return convert(ErrorCode::UNIMPLEMENTED);
- }
-
- Return<void> beginOp(KeyPurpose purpose, const hidl_vec<uint8_t>& key,
- const hidl_vec<KeyParameter>& inParams, const HardwareAuthToken& authToken,
- beginOp_cb _hidl_cb) override {
- return super::begin(
- purpose, key, inParams, authToken,
- [&](auto hidl_err, auto hidl_params, auto hidl_handle) {
- _hidl_cb(convert(hidl_err), hidl_params,
- new ::android::hardware::keymaster::V4_1::support::Operation(hidl_handle));
- });
- }
+ const VerificationToken& /* verificationToken */) override;
+ Return<V41ErrorCode> earlyBootEnded() override;
Return<void> getHardwareInfo(super::getHardwareInfo_cb _hidl_cb) override {
return super::getHardwareInfo(_hidl_cb);
diff --git a/ng/include/AndroidKeymaster4Device.h b/ng/include/AndroidKeymaster4Device.h
index 688d08a..54b263e 100644
--- a/ng/include/AndroidKeymaster4Device.h
+++ b/ng/include/AndroidKeymaster4Device.h
@@ -20,7 +20,9 @@
#include <android/hardware/keymaster/4.0/IKeymasterDevice.h>
+#include <hardware/keymaster_defs.h>
#include <hidl/Status.h>
+#include <keymaster/km_version.h>
namespace keymaster {
class AndroidKeymaster;
@@ -48,7 +50,8 @@
class AndroidKeymaster4Device : public IKeymasterDevice {
public:
- explicit AndroidKeymaster4Device(SecurityLevel securityLevel);
+ explicit AndroidKeymaster4Device(SecurityLevel securityLevel)
+ : AndroidKeymaster4Device(KmVersion::KEYMASTER_4, securityLevel) {}
virtual ~AndroidKeymaster4Device();
Return<void> getHardwareInfo(getHardwareInfo_cb _hidl_cb) override;
@@ -98,11 +101,18 @@
const VerificationToken& verificationToken, finish_cb _hidl_cb) override;
Return<ErrorCode> abort(uint64_t operationHandle) override;
- private:
+ protected:
+ AndroidKeymaster4Device(::keymaster::KmVersion version, SecurityLevel securityLevel);
+
std::unique_ptr<::keymaster::AndroidKeymaster> impl_;
SecurityLevel securityLevel_;
};
+// Convert HIDL key parametes to old keymaster param set. Note that this does *not* copy the blobs
+// from keyParams, only pointers to them. The keyParams instance retains ownership and must
+// continue to exist.
+keymaster_key_param_set_t hidlKeyParams2Km(const hidl_vec<KeyParameter>& keyParams);
+
IKeymasterDevice* CreateKeymasterDevice(SecurityLevel securityLevel);
} // namespace ng
diff --git a/ng/include/AndroidRemotelyProvisionedComponentDevice.h b/ng/include/AndroidRemotelyProvisionedComponentDevice.h
new file mode 100644
index 0000000..eef81f3
--- /dev/null
+++ b/ng/include/AndroidRemotelyProvisionedComponentDevice.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2021, 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.
+ */
+
+#pragma once
+
+#include <AndroidKeyMintDevice.h>
+#include <aidl/android/hardware/security/keymint/BnRemotelyProvisionedComponent.h>
+#include <aidl/android/hardware/security/keymint/RpcHardwareInfo.h>
+#include <aidl/android/hardware/security/keymint/SecurityLevel.h>
+#include <cppbor.h>
+#include <keymaster/UniquePtr.h>
+#include <keymaster/android_keymaster.h>
+
+namespace aidl::android::hardware::security::keymint {
+
+class AndroidRemotelyProvisionedComponentDevice : public BnRemotelyProvisionedComponent {
+ using ScopedAStatus = ::ndk::ScopedAStatus;
+
+ public:
+ explicit AndroidRemotelyProvisionedComponentDevice(
+ const std::shared_ptr<AndroidKeyMintDevice>& keymint);
+ virtual ~AndroidRemotelyProvisionedComponentDevice() = default;
+
+ ScopedAStatus getHardwareInfo(RpcHardwareInfo* info) override;
+
+ ScopedAStatus generateEcdsaP256KeyPair(bool testMode, MacedPublicKey* macedPublicKey,
+ std::vector<uint8_t>* privateKeyHandle) override;
+
+ ScopedAStatus generateCertificateRequest(bool testMode,
+ const std::vector<MacedPublicKey>& keysToSign,
+ const std::vector<uint8_t>& endpointEncCertChain,
+ const std::vector<uint8_t>& challenge,
+ DeviceInfo* deviceInfo, ProtectedData* protectedData,
+ std::vector<uint8_t>* keysToSignMac) override;
+
+ private:
+ std::shared_ptr<::keymaster::AndroidKeymaster> impl_;
+};
+
+} // namespace aidl::android::hardware::security::keymint
diff --git a/ng/include/AndroidSecureClock.h b/ng/include/AndroidSecureClock.h
new file mode 100644
index 0000000..e7564ca
--- /dev/null
+++ b/ng/include/AndroidSecureClock.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2020, 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.
+ */
+
+#pragma once
+
+#include "AndroidKeyMintDevice.h"
+#include <aidl/android/hardware/security/secureclock/BnSecureClock.h>
+#include <aidl/android/hardware/security/secureclock/TimeStampToken.h>
+#include <aidl/android/hardware/security/secureclock/Timestamp.h>
+
+namespace keymaster {
+class AndroidKeymaster;
+}
+
+namespace aidl::android::hardware::security::secureclock {
+using ::ndk::ScopedAStatus;
+using std::shared_ptr;
+using std::vector;
+
+class AndroidSecureClock : public BnSecureClock {
+ public:
+ explicit AndroidSecureClock(const std::shared_ptr<keymint::AndroidKeyMintDevice>& keymint);
+ virtual ~AndroidSecureClock();
+ ScopedAStatus generateTimeStamp(int64_t challenge, TimeStampToken* token) override;
+
+ private:
+ shared_ptr<::keymaster::AndroidKeymaster>& impl_;
+};
+} // namespace aidl::android::hardware::security::secureclock
diff --git a/ng/include/AndroidSharedSecret.h b/ng/include/AndroidSharedSecret.h
new file mode 100644
index 0000000..503fd0a
--- /dev/null
+++ b/ng/include/AndroidSharedSecret.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2020, 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.
+ */
+
+#pragma once
+
+#include "AndroidKeyMintDevice.h"
+#include <aidl/android/hardware/security/sharedsecret/BnSharedSecret.h>
+#include <aidl/android/hardware/security/sharedsecret/SharedSecretParameters.h>
+
+namespace keymaster {
+class AndroidKeymaster;
+}
+namespace aidl::android::hardware::security::sharedsecret {
+using ::ndk::ScopedAStatus;
+using std::shared_ptr;
+using std::vector;
+
+class AndroidSharedSecret : public BnSharedSecret {
+ public:
+ explicit AndroidSharedSecret(const std::shared_ptr<keymint::AndroidKeyMintDevice>& keymint);
+ virtual ~AndroidSharedSecret();
+ ScopedAStatus getSharedSecretParameters(SharedSecretParameters* params) override;
+ ScopedAStatus computeSharedSecret(const vector<SharedSecretParameters>& params,
+ vector<uint8_t>* sharingCheck) override;
+
+ private:
+ shared_ptr<::keymaster::AndroidKeymaster>& impl_;
+};
+} // namespace aidl::android::hardware::security::sharedsecret
diff --git a/ng/include/KeyMintUtils.h b/ng/include/KeyMintUtils.h
new file mode 100644
index 0000000..6e232e1
--- /dev/null
+++ b/ng/include/KeyMintUtils.h
@@ -0,0 +1,133 @@
+/*
+ * Copyright 2020, 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.
+ */
+
+#pragma once
+
+#include <aidl/android/hardware/security/keymint/Certificate.h>
+#include <aidl/android/hardware/security/keymint/HardwareAuthToken.h>
+#include <aidl/android/hardware/security/keymint/HardwareAuthenticatorType.h>
+#include <aidl/android/hardware/security/keymint/KeyFormat.h>
+#include <aidl/android/hardware/security/keymint/KeyParameter.h>
+#include <aidl/android/hardware/security/keymint/KeyPurpose.h>
+#include <aidl/android/hardware/security/keymint/SecurityLevel.h>
+#include <aidl/android/hardware/security/keymint/Tag.h>
+
+#include <keymaster/keymaster_enforcement.h>
+
+namespace aidl::android::hardware::security::keymint::km_utils {
+
+using ::ndk::ScopedAStatus;
+using std::vector;
+
+inline keymaster_tag_t legacy_enum_conversion(const Tag value) {
+ return static_cast<keymaster_tag_t>(value);
+}
+
+inline Tag legacy_enum_conversion(const keymaster_tag_t value) {
+ return static_cast<Tag>(value);
+}
+
+inline keymaster_purpose_t legacy_enum_conversion(const KeyPurpose value) {
+ return static_cast<keymaster_purpose_t>(value);
+}
+
+inline keymaster_key_format_t legacy_enum_conversion(const KeyFormat value) {
+ return static_cast<keymaster_key_format_t>(value);
+}
+
+inline SecurityLevel legacy_enum_conversion(const keymaster_security_level_t value) {
+ return static_cast<SecurityLevel>(value);
+}
+
+inline hw_authenticator_type_t legacy_enum_conversion(const HardwareAuthenticatorType value) {
+ return static_cast<hw_authenticator_type_t>(value);
+}
+
+inline ScopedAStatus kmError2ScopedAStatus(const keymaster_error_t value) {
+ return (value == KM_ERROR_OK
+ ? ScopedAStatus::ok()
+ : ScopedAStatus(AStatus_fromServiceSpecificError(static_cast<int32_t>(value))));
+}
+
+inline keymaster_tag_type_t typeFromTag(const keymaster_tag_t tag) {
+ return keymaster_tag_get_type(tag);
+}
+
+KeyParameter kmParam2Aidl(const keymaster_key_param_t& param);
+vector<KeyParameter> kmParamSet2Aidl(const keymaster_key_param_set_t& set);
+keymaster_key_param_set_t aidlKeyParams2Km(const vector<KeyParameter>& keyParams);
+
+class KmParamSet : public keymaster_key_param_set_t {
+ public:
+ explicit KmParamSet(const vector<KeyParameter>& keyParams)
+ : keymaster_key_param_set_t(aidlKeyParams2Km(keyParams)) {}
+
+ KmParamSet(KmParamSet&& other) : keymaster_key_param_set_t{other.params, other.length} {
+ other.length = 0;
+ other.params = nullptr;
+ }
+
+ KmParamSet(const KmParamSet&) = delete;
+ ~KmParamSet() { keymaster_free_param_set(this); }
+};
+
+inline vector<uint8_t> kmBlob2vector(const keymaster_key_blob_t& blob) {
+ vector<uint8_t> result(blob.key_material, blob.key_material + blob.key_material_size);
+ return result;
+}
+
+inline vector<uint8_t> kmBlob2vector(const keymaster_blob_t& blob) {
+ vector<uint8_t> result(blob.data, blob.data + blob.data_length);
+ return result;
+}
+
+inline vector<uint8_t> kmBuffer2vector(const ::keymaster::Buffer& buf) {
+ vector<uint8_t> result(buf.peek_read(), buf.peek_read() + buf.available_read());
+ return result;
+}
+
+inline vector<Certificate> kmCertChain2Aidl(const keymaster_cert_chain_t& cert_chain) {
+ vector<Certificate> result;
+ if (!cert_chain.entry_count || !cert_chain.entries) return result;
+
+ result.resize(cert_chain.entry_count);
+ for (size_t i = 0; i < cert_chain.entry_count; ++i) {
+ result[i].encodedCertificate = kmBlob2vector(cert_chain.entries[i]);
+ }
+
+ return result;
+}
+
+template <typename T, typename OutIter>
+inline OutIter copy_bytes_to_iterator(const T& value, OutIter dest) {
+ const uint8_t* value_ptr = reinterpret_cast<const uint8_t*>(&value);
+ return std::copy(value_ptr, value_ptr + sizeof(value), dest);
+}
+
+vector<uint8_t> authToken2AidlVec(const std::optional<HardwareAuthToken>& token);
+
+inline void addClientAndAppData(const vector<uint8_t>& clientId, const vector<uint8_t>& appData,
+ ::keymaster::AuthorizationSet* params) {
+ params->Clear();
+ if (clientId.size()) {
+ params->push_back(::keymaster::TAG_APPLICATION_ID, clientId.data(), clientId.size());
+ }
+ if (appData.size()) {
+ params->push_back(::keymaster::TAG_APPLICATION_DATA, appData.data(), appData.size());
+ }
+}
+
+} // namespace aidl::android::hardware::security::keymint::km_utils
diff --git a/ng/include/authorization_set.h b/ng/include/authorization_set.h
index 5367696..895f6cc 100644
--- a/ng/include/authorization_set.h
+++ b/ng/include/authorization_set.h
@@ -14,14 +14,12 @@
* limitations under the License.
*/
-#ifndef SYSTEM_SECURITY_KEYSTORE_AUTHORIZATION_SET_H_
-#define SYSTEM_SECURITY_KEYSTORE_AUTHORIZATION_SET_H_
+#pragma once
#include "keymaster_tags.h"
#include <vector>
-namespace keymaster {
-namespace ng {
+namespace keymaster::ng {
class AuthorizationSetBuilder;
@@ -35,7 +33,7 @@
/**
* Construct an empty, dynamically-allocated, growable AuthorizationSet.
*/
- AuthorizationSet() {};
+ AuthorizationSet(){};
// Copy constructor.
AuthorizationSet(const AuthorizationSet& other) : data_(other.data_) {}
@@ -48,6 +46,7 @@
// Copy assignment.
AuthorizationSet& operator=(const AuthorizationSet& other) {
+ if (this == &other) return *this;
data_ = other.data_;
return *this;
}
@@ -153,13 +152,11 @@
/**
* Returns true if the set contains at least one instance of \p tag
*/
- bool Contains(Tag tag) const {
- return find(tag) != -1;
- }
+ bool Contains(Tag tag) const { return find(tag) != -1; }
template <TagType tag_type, Tag tag, typename ValueT>
bool Contains(TypedTag<tag_type, tag> ttag, const ValueT& value) const {
- for (const auto& param: data_) {
+ for (const auto& param : data_) {
auto entry = authorizationValue(ttag, param);
if (entry.isOk() && entry.value() == value) return true;
}
@@ -177,25 +174,19 @@
return {};
}
- void push_back(const KeyParameter& param) {
- data_.push_back(param);
- }
- void push_back(KeyParameter&& param) {
- data_.push_back(std::move(param));
- }
+ void push_back(const KeyParameter& param) { data_.push_back(param); }
+ void push_back(KeyParameter&& param) { data_.push_back(std::move(param)); }
/**
* Append the tag and enumerated value to the set.
* "val" may be exactly one parameter unless a boolean parameter is added.
* In this case "val" is omitted. This condition is checked at compile time by Authorization()
*/
- template <typename TypedTagT, typename... Value>
- void push_back(TypedTagT tag, Value&&... val) {
+ template <typename TypedTagT, typename... Value> void push_back(TypedTagT tag, Value&&... val) {
push_back(Authorization(tag, std::forward<Value>(val)...));
}
- template <typename Iterator>
- void append(Iterator begin, Iterator end) {
+ template <typename Iterator> void append(Iterator begin, Iterator end) {
while (begin != end) {
push_back(*begin);
++begin;
@@ -217,7 +208,7 @@
std::vector<KeyParameter> data_;
};
-class AuthorizationSetBuilder: public AuthorizationSet {
+class AuthorizationSetBuilder : public AuthorizationSet {
public:
template <typename TagType, typename... ValueType>
AuthorizationSetBuilder& Authorization(TagType ttag, ValueType&&... value) {
@@ -255,9 +246,7 @@
AuthorizationSetBuilder& NoDigestOrPadding();
AuthorizationSetBuilder& EcbMode();
- AuthorizationSetBuilder& Digest(Digest digest) {
- return Authorization(TAG_DIGEST, digest);
- }
+ AuthorizationSetBuilder& Digest(Digest digest) { return Authorization(TAG_DIGEST, digest); }
AuthorizationSetBuilder& Padding(PaddingMode padding) {
return Authorization(TAG_PADDING, padding);
@@ -330,7 +319,4 @@
return Authorization(TAG_BLOCK_MODE, BlockMode::ECB);
}
-} // namespace ng
-} // namespace keymaster
-
-#endif // SYSTEM_SECURITY_KEYSTORE_AUTHORIZATION_SET_H_
+} // namespace keymaster::ng
diff --git a/ng/include/keymaster_tags.h b/ng/include/keymaster_tags.h
index be6c11c..57e7cc1 100644
--- a/ng/include/keymaster_tags.h
+++ b/ng/include/keymaster_tags.h
@@ -14,8 +14,7 @@
* limitations under the License.
*/
-#ifndef SYSTEM_SECURITY_KEYSTORE_KEYMASTER_TAGS_H_
-#define SYSTEM_SECURITY_KEYSTORE_KEYMASTER_TAGS_H_
+#pragma once
/**
* This header contains various definitions that make working with keymaster tags safer and easier.
@@ -63,16 +62,15 @@
#include <hardware/hw_auth_token.h>
#include <type_traits>
-namespace keymaster {
-namespace ng {
+namespace keymaster::ng {
using ::android::hardware::keymaster::V3_0::Algorithm;
using ::android::hardware::keymaster::V3_0::BlockMode;
using ::android::hardware::keymaster::V3_0::Digest;
using ::android::hardware::keymaster::V3_0::EcCurve;
using ::android::hardware::keymaster::V3_0::ErrorCode;
-using ::android::hardware::keymaster::V3_0::HardwareAuthToken;
using ::android::hardware::keymaster::V3_0::HardwareAuthenticatorType;
+using ::android::hardware::keymaster::V3_0::HardwareAuthToken;
using ::android::hardware::keymaster::V3_0::IKeymasterDevice;
using ::android::hardware::keymaster::V3_0::KeyBlobUsageRequirements;
using ::android::hardware::keymaster::V3_0::KeyCharacteristics;
@@ -314,7 +312,7 @@
bool isOk() const { return !null_; }
- const ValueT& value() const & { return value_; }
+ const ValueT& value() const& { return value_; }
ValueT& value() & { return value_; }
ValueT&& value() && { return std::move(value_); }
@@ -350,7 +348,4 @@
return accessTagValue(ttag, param);
}
-} // namespace ng
-} // namespace keymaster
-
-#endif // SYSTEM_SECURITY_KEYSTORE_KEYMASTER_TAGS_H_
+} // namespace keymaster::ng
diff --git a/ng/include/keystore_hidl_support.h b/ng/include/keystore_hidl_support.h
index cfb3c2d..b7d7221 100644
--- a/ng/include/keystore_hidl_support.h
+++ b/ng/include/keystore_hidl_support.h
@@ -15,20 +15,18 @@
** limitations under the License.
*/
-#ifndef KEYSTORE_KEYSTORE_HIDL_SUPPORT_H_
-#define KEYSTORE_KEYSTORE_HIDL_SUPPORT_H_
+#pragma once
+#include "keymaster_tags.h"
#include <android/hardware/keymaster/3.0/IKeymasterDevice.h>
#include <hidl/Status.h>
-#include "keymaster_tags.h"
#include <ostream>
#include <sstream>
#include <string>
#include <android-base/logging.h>
-namespace keymaster {
-namespace ng {
+namespace keymaster::ng {
inline static std::ostream& formatArgs(std::ostream& out) {
return out;
@@ -50,7 +48,7 @@
inline static ErrorCode ksHandleHidlError(const Return<ErrorCode>& error, Msgs&&... msgs) {
if (!error.isOk()) {
LOG(ERROR) << "HIDL call failed with " << error.description() << " @ "
- << argsToString(msgs...);
+ << argsToString(msgs...);
return ErrorCode::UNKNOWN_ERROR;
}
return ErrorCode(error);
@@ -59,7 +57,7 @@
inline static ErrorCode ksHandleHidlError(const Return<void>& error, Msgs&&... msgs) {
if (!error.isOk()) {
LOG(ERROR) << "HIDL call failed with " << error.description() << " @ "
- << argsToString(msgs...);
+ << argsToString(msgs...);
return ErrorCode::UNKNOWN_ERROR;
}
return ErrorCode::OK;
@@ -128,7 +126,4 @@
return std::string(reinterpret_cast<const std::string::value_type*>(&value[0]), value.size());
}
-}
-} // namespace keystore
-
-#endif // KEYSTORE_KEYSTORE_HIDL_SUPPORT_H_
+} // namespace keymaster::ng
diff --git a/rsa_privkey_pk8.der b/rsa_privkey_pk8.der
deleted file mode 100644
index 0336f80..0000000
--- a/rsa_privkey_pk8.der
+++ /dev/null
Binary files differ
diff --git a/tests/Android.bp b/tests/Android.bp
new file mode 100644
index 0000000..3ee650e
--- /dev/null
+++ b/tests/Android.bp
@@ -0,0 +1,62 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "system_keymaster_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["system_keymaster_license"],
+}
+
+shared_test_libs = [
+ "libbase",
+ "libcppbor_external",
+ "libcrypto",
+ "libcutils",
+ "libhidlbase",
+ "libkeymaster_messages",
+ "libkeymaster_portable",
+ "liblog",
+ "libsoft_attestation_cert",
+ "libutils",
+]
+
+static_test_libs = [
+ "libsoftkeymasterdevice",
+ "libcppcose_rkp",
+]
+
+test_cflags = [
+ "-DKEYMASTER_NAME_TAGS",
+ "-Wall",
+ "-Werror",
+ "-Wextra",
+ "-Wunused-variable",
+]
+
+cc_test {
+ name: "keymaster_tests",
+ cflags: test_cflags,
+ srcs: [
+ "gtest_main.cpp",
+ "keymaster_configuration_test.cpp",
+ "hmac_test.cpp",
+ "android_keymaster_test_utils.cpp",
+ "ckdf_test.cpp",
+ "hkdf_test.cpp",
+ "kdf_test.cpp",
+ "kdf1_test.cpp",
+ "kdf2_test.cpp",
+ "ecies_kem_test.cpp",
+ "nist_curve_key_exchange_test.cpp",
+ "authorization_set_test.cpp",
+ "key_blob_test.cpp",
+ "android_keymaster_messages_test.cpp",
+ "android_keymaster_test.cpp",
+ "keymaster_enforcement_test.cpp",
+ "attestation_record_test.cpp",
+ "wrapped_key_test.cpp",
+ ],
+ shared_libs: shared_test_libs,
+ static_libs: static_test_libs,
+ test_suites: ["general-tests"],
+}
diff --git a/tests/TEST_MAPPING b/tests/TEST_MAPPING
new file mode 100644
index 0000000..5ec0f38
--- /dev/null
+++ b/tests/TEST_MAPPING
@@ -0,0 +1,7 @@
+{
+ "presubmit": [
+ {
+ "name": "keymaster_tests"
+ }
+ ]
+}
diff --git a/tests/android_keymaster_messages_test.cpp b/tests/android_keymaster_messages_test.cpp
index 7dcffbe..7b523a8 100644
--- a/tests/android_keymaster_messages_test.cpp
+++ b/tests/android_keymaster_messages_test.cpp
@@ -34,8 +34,7 @@
Message* round_trip(int32_t ver, const Message& message, size_t expected_size) {
size_t size = message.SerializedSize();
EXPECT_EQ(expected_size, size);
- if (size == 0)
- return nullptr;
+ if (size == 0) return nullptr;
UniquePtr<uint8_t[]> buf(new uint8_t[size]);
EXPECT_EQ(buf.get() + size, message.Serialize(buf.get(), buf.get() + size));
@@ -47,72 +46,21 @@
return deserialized;
}
-struct EmptyKeymasterResponse : public KeymasterResponse {
- explicit EmptyKeymasterResponse(int32_t ver) : KeymasterResponse(ver) {}
- size_t NonErrorSerializedSize() const { return 1; }
- uint8_t* NonErrorSerialize(uint8_t* buf, const uint8_t* /* end */) const {
- *buf++ = 0;
- return buf;
- }
- bool NonErrorDeserialize(const uint8_t** buf_ptr, const uint8_t* end) {
- if (*buf_ptr >= end)
- return false;
- EXPECT_EQ(0, **buf_ptr);
- (*buf_ptr)++;
- return true;
- }
-};
-
TEST(RoundTrip, EmptyKeymasterResponse) {
- for (int ver = 0; ver <= MAX_MESSAGE_VERSION; ++ver) {
+ for (int ver = 0; ver <= kMaxMessageVersion; ++ver) {
EmptyKeymasterResponse msg(ver);
msg.error = KM_ERROR_OK;
- UniquePtr<EmptyKeymasterResponse> deserialized(round_trip(ver, msg, 5));
- }
-}
-
-TEST(RoundTrip, EmptyKeymasterResponseError) {
- for (int ver = 0; ver <= MAX_MESSAGE_VERSION; ++ver) {
- EmptyKeymasterResponse msg(ver);
- msg.error = KM_ERROR_MEMORY_ALLOCATION_FAILED;
-
UniquePtr<EmptyKeymasterResponse> deserialized(round_trip(ver, msg, 4));
}
}
-TEST(RoundTrip, SupportedByAlgorithmRequest) {
- for (int ver = 0; ver <= MAX_MESSAGE_VERSION; ++ver) {
- SupportedByAlgorithmRequest req(ver);
- req.algorithm = KM_ALGORITHM_EC;
+TEST(RoundTrip, EmptyKeymasterResponseError) {
+ for (int ver = 0; ver <= kMaxMessageVersion; ++ver) {
+ EmptyKeymasterResponse msg(ver);
+ msg.error = KM_ERROR_MEMORY_ALLOCATION_FAILED;
- UniquePtr<SupportedByAlgorithmRequest> deserialized(round_trip(ver, req, 4));
- EXPECT_EQ(KM_ALGORITHM_EC, deserialized->algorithm);
- }
-}
-
-TEST(RoundTrip, SupportedByAlgorithmAndPurposeRequest) {
- for (int ver = 0; ver <= MAX_MESSAGE_VERSION; ++ver) {
- SupportedByAlgorithmAndPurposeRequest req(ver);
- req.algorithm = KM_ALGORITHM_EC;
- req.purpose = KM_PURPOSE_DECRYPT;
-
- UniquePtr<SupportedByAlgorithmAndPurposeRequest> deserialized(round_trip(ver, req, 8));
- EXPECT_EQ(KM_ALGORITHM_EC, deserialized->algorithm);
- EXPECT_EQ(KM_PURPOSE_DECRYPT, deserialized->purpose);
- }
-}
-
-TEST(RoundTrip, SupportedResponse) {
- for (int ver = 0; ver <= MAX_MESSAGE_VERSION; ++ver) {
- SupportedResponse<keymaster_digest_t> rsp(ver);
- keymaster_digest_t digests[] = {KM_DIGEST_NONE, KM_DIGEST_MD5, KM_DIGEST_SHA1};
- rsp.error = KM_ERROR_OK;
- rsp.SetResults(digests);
-
- UniquePtr<SupportedResponse<keymaster_digest_t>> deserialized(round_trip(ver, rsp, 20));
- EXPECT_EQ(array_length(digests), deserialized->results_length);
- EXPECT_EQ(0, memcmp(deserialized->results, digests, array_size(digests)));
+ UniquePtr<EmptyKeymasterResponse> deserialized(round_trip(ver, msg, 4));
}
}
@@ -128,31 +76,72 @@
uint8_t TEST_DATA[] = "a key blob";
TEST(RoundTrip, GenerateKeyRequest) {
- for (int ver = 0; ver <= MAX_MESSAGE_VERSION; ++ver) {
+ for (int ver = 0; ver <= kMaxMessageVersion; ++ver) {
GenerateKeyRequest req(ver);
req.key_description.Reinitialize(params, array_length(params));
- UniquePtr<GenerateKeyRequest> deserialized(round_trip(ver, req, 78));
+ req.attestation_signing_key_blob =
+ KeymasterKeyBlob(reinterpret_cast<const uint8_t*>("foo"), 3);
+ req.attest_key_params.Reinitialize(params, array_length(params));
+ req.issuer_subject = KeymasterBlob(reinterpret_cast<const uint8_t*>("bar"), 3);
+
+ UniquePtr<GenerateKeyRequest> deserialized(round_trip(ver, req, ver < 4 ? 78 : 170));
EXPECT_EQ(deserialized->key_description, req.key_description);
+ if (ver < 4) {
+ EXPECT_EQ(0U, deserialized->attestation_signing_key_blob.key_material_size);
+ } else {
+ EXPECT_EQ(3U, deserialized->attestation_signing_key_blob.key_material_size);
+ EXPECT_EQ(0, memcmp(req.attestation_signing_key_blob.key_material,
+ deserialized->attestation_signing_key_blob.key_material,
+ deserialized->attestation_signing_key_blob.key_material_size));
+ EXPECT_EQ(deserialized->attest_key_params, req.attest_key_params);
+ EXPECT_EQ(0, memcmp(req.issuer_subject.data, deserialized->issuer_subject.data,
+ deserialized->issuer_subject.data_length));
+ }
}
}
TEST(RoundTrip, GenerateKeyResponse) {
- for (int ver = 0; ver <= MAX_MESSAGE_VERSION; ++ver) {
+ for (int ver = 0; ver <= kMaxMessageVersion; ++ver) {
GenerateKeyResponse rsp(ver);
rsp.error = KM_ERROR_OK;
rsp.key_blob.key_material = dup_array(TEST_DATA);
rsp.key_blob.key_material_size = array_length(TEST_DATA);
rsp.enforced.Reinitialize(params, array_length(params));
- UniquePtr<GenerateKeyResponse> deserialized(round_trip(ver, rsp, 109));
+ rsp.certificate_chain = CertificateChain(3);
+ rsp.certificate_chain.entries[0] = {dup_buffer("foo", 3), 3};
+ rsp.certificate_chain.entries[1] = {dup_buffer("bar", 3), 3};
+ rsp.certificate_chain.entries[2] = {dup_buffer("baz", 3), 3};
+
+ UniquePtr<GenerateKeyResponse> deserialized;
+ if (ver < 4) {
+ deserialized.reset(round_trip(ver, rsp, 109));
+ } else {
+ deserialized.reset(round_trip(ver, rsp, 134));
+ }
+
EXPECT_EQ(KM_ERROR_OK, deserialized->error);
EXPECT_EQ(deserialized->enforced, rsp.enforced);
EXPECT_EQ(deserialized->unenforced, rsp.unenforced);
+
+ keymaster_cert_chain_t* chain = &deserialized->certificate_chain;
+ if (ver < 4) {
+ EXPECT_EQ(nullptr, chain->entries);
+ } else {
+ EXPECT_NE(nullptr, chain->entries);
+ EXPECT_EQ(3U, chain->entry_count);
+ EXPECT_EQ(3U, chain->entries[0].data_length);
+ EXPECT_EQ(0, memcmp("foo", chain->entries[0].data, 3));
+ EXPECT_EQ(3U, chain->entries[1].data_length);
+ EXPECT_EQ(0, memcmp("bar", chain->entries[1].data, 3));
+ EXPECT_EQ(3U, chain->entries[2].data_length);
+ EXPECT_EQ(0, memcmp("baz", chain->entries[2].data, 3));
+ }
}
}
TEST(RoundTrip, GenerateKeyResponseTestError) {
- for (int ver = 0; ver <= MAX_MESSAGE_VERSION; ++ver) {
+ for (int ver = 0; ver <= kMaxMessageVersion; ++ver) {
GenerateKeyResponse rsp(ver);
rsp.error = KM_ERROR_UNSUPPORTED_ALGORITHM;
rsp.key_blob.key_material = dup_array(TEST_DATA);
@@ -167,8 +156,101 @@
}
}
+TEST(RoundTrip, GenerateRkpKeyRequest) {
+ for (int ver = 0; ver <= kMaxMessageVersion; ++ver) {
+ GenerateRkpKeyRequest req(ver);
+ req.test_mode = true;
+
+ UniquePtr<GenerateRkpKeyRequest> deserialized(round_trip(ver, req, 1));
+ EXPECT_EQ(deserialized->test_mode, req.test_mode);
+ }
+}
+
+TEST(RoundTrip, GenerateRkpKeyResponse) {
+ for (int ver = 0; ver <= kMaxMessageVersion; ++ver) {
+ GenerateRkpKeyResponse rsp(ver);
+ rsp.error = KM_ERROR_OK;
+ rsp.key_blob.key_material = dup_array(TEST_DATA);
+ rsp.key_blob.key_material_size = array_length(TEST_DATA);
+ rsp.maced_public_key.data = dup_array(TEST_DATA);
+ rsp.maced_public_key.data_length = array_length(TEST_DATA);
+
+ UniquePtr<GenerateRkpKeyResponse> deserialized;
+ deserialized.reset(round_trip(ver, rsp, 34));
+
+ EXPECT_EQ(KM_ERROR_OK, deserialized->error);
+ EXPECT_EQ(deserialized->key_blob.key_material_size, rsp.key_blob.key_material_size);
+ EXPECT_EQ(0, std::memcmp(deserialized->key_blob.key_material, rsp.key_blob.key_material,
+ deserialized->key_blob.key_material_size));
+ EXPECT_EQ(deserialized->maced_public_key.data_length, rsp.maced_public_key.data_length);
+ EXPECT_EQ(0, std::memcmp(deserialized->maced_public_key.data, rsp.maced_public_key.data,
+ deserialized->maced_public_key.data_length));
+ }
+}
+
+TEST(RoundTrip, GenerateCsrRequest) {
+ for (int ver = 0; ver <= kMaxMessageVersion; ++ver) {
+ GenerateCsrRequest req(ver);
+ req.test_mode = true;
+ req.num_keys = 2;
+ req.keys_to_sign_array = new KeymasterBlob[req.num_keys];
+ for (size_t i = 0; i < req.num_keys; i++) {
+ req.SetKeyToSign(i, dup_array(TEST_DATA), array_length(TEST_DATA));
+ }
+ req.SetEndpointEncCertChain(dup_array(TEST_DATA), array_length(TEST_DATA));
+ req.SetChallenge(dup_array(TEST_DATA), array_length(TEST_DATA));
+ UniquePtr<GenerateCsrRequest> deserialized(round_trip(ver, req, 65));
+ EXPECT_EQ(deserialized->test_mode, req.test_mode);
+ EXPECT_EQ(deserialized->num_keys, req.num_keys);
+ for (int i = 0; i < (int)req.num_keys; i++) {
+ EXPECT_EQ(deserialized->keys_to_sign_array[i].data_length,
+ req.keys_to_sign_array[i].data_length);
+ EXPECT_EQ(0, std::memcmp(deserialized->keys_to_sign_array[i].data,
+ req.keys_to_sign_array[i].data,
+ req.keys_to_sign_array[i].data_length));
+ }
+ EXPECT_EQ(deserialized->endpoint_enc_cert_chain.data_length,
+ req.endpoint_enc_cert_chain.data_length);
+ EXPECT_EQ(0, std::memcmp(deserialized->endpoint_enc_cert_chain.data,
+ req.endpoint_enc_cert_chain.data,
+ req.endpoint_enc_cert_chain.data_length));
+ EXPECT_EQ(deserialized->challenge.data_length, req.challenge.data_length);
+ EXPECT_EQ(0, std::memcmp(deserialized->challenge.data, req.challenge.data,
+ req.challenge.data_length));
+ }
+}
+
+TEST(RoundTrip, GenerateCsrResponse) {
+ for (int ver = 0; ver <= kMaxMessageVersion; ++ver) {
+ GenerateCsrResponse rsp(ver);
+ rsp.error = KM_ERROR_OK;
+ rsp.keys_to_sign_mac.data = dup_array(TEST_DATA);
+ rsp.keys_to_sign_mac.data_length = array_length(TEST_DATA);
+ rsp.device_info_blob.data = dup_array(TEST_DATA);
+ rsp.device_info_blob.data_length = array_length(TEST_DATA);
+ rsp.protected_data_blob.data = dup_array(TEST_DATA);
+ rsp.protected_data_blob.data_length = array_length(TEST_DATA);
+
+ UniquePtr<GenerateCsrResponse> deserialized;
+ deserialized.reset(round_trip(ver, rsp, 49));
+
+ EXPECT_EQ(KM_ERROR_OK, deserialized->error);
+ EXPECT_EQ(deserialized->keys_to_sign_mac.data_length, rsp.keys_to_sign_mac.data_length);
+ EXPECT_EQ(0, std::memcmp(deserialized->keys_to_sign_mac.data, rsp.keys_to_sign_mac.data,
+ deserialized->keys_to_sign_mac.data_length));
+ EXPECT_EQ(deserialized->device_info_blob.data_length, rsp.device_info_blob.data_length);
+ EXPECT_EQ(0, std::memcmp(deserialized->device_info_blob.data, rsp.device_info_blob.data,
+ deserialized->device_info_blob.data_length));
+ EXPECT_EQ(deserialized->protected_data_blob.data_length,
+ rsp.protected_data_blob.data_length);
+ EXPECT_EQ(0,
+ std::memcmp(deserialized->protected_data_blob.data, rsp.protected_data_blob.data,
+ deserialized->protected_data_blob.data_length));
+ }
+}
+
TEST(RoundTrip, GetKeyCharacteristicsRequest) {
- for (int ver = 0; ver <= MAX_MESSAGE_VERSION; ++ver) {
+ for (int ver = 0; ver <= kMaxMessageVersion; ++ver) {
GetKeyCharacteristicsRequest req(ver);
req.additional_params.Reinitialize(params, array_length(params));
req.SetKeyMaterial("foo", 3);
@@ -181,7 +263,7 @@
}
TEST(RoundTrip, GetKeyCharacteristicsResponse) {
- for (int ver = 0; ver <= MAX_MESSAGE_VERSION; ++ver) {
+ for (int ver = 0; ver <= kMaxMessageVersion; ++ver) {
GetKeyCharacteristicsResponse msg(ver);
msg.error = KM_ERROR_OK;
msg.enforced.Reinitialize(params, array_length(params));
@@ -194,7 +276,7 @@
}
TEST(RoundTrip, BeginOperationRequest) {
- for (int ver = 0; ver <= MAX_MESSAGE_VERSION; ++ver) {
+ for (int ver = 0; ver <= kMaxMessageVersion; ++ver) {
BeginOperationRequest msg(ver);
msg.purpose = KM_PURPOSE_SIGN;
msg.SetKeyMaterial("foo", 3);
@@ -209,7 +291,7 @@
}
TEST(RoundTrip, BeginOperationResponse) {
- for (int ver = 0; ver <= MAX_MESSAGE_VERSION; ++ver) {
+ for (int ver = 0; ver <= kMaxMessageVersion; ++ver) {
BeginOperationResponse msg(ver);
msg.error = KM_ERROR_OK;
msg.op_handle = 0xDEADBEEF;
@@ -223,6 +305,7 @@
case 1:
case 2:
case 3:
+ case 4:
deserialized.reset(round_trip(ver, msg, 39));
break;
default:
@@ -239,6 +322,7 @@
case 1:
case 2:
case 3:
+ case 4:
EXPECT_EQ(msg.output_params, deserialized->output_params);
break;
default:
@@ -248,7 +332,7 @@
}
TEST(RoundTrip, BeginOperationResponseError) {
- for (int ver = 0; ver <= MAX_MESSAGE_VERSION; ++ver) {
+ for (int ver = 0; ver <= kMaxMessageVersion; ++ver) {
BeginOperationResponse msg(ver);
msg.error = KM_ERROR_INVALID_OPERATION_HANDLE;
msg.op_handle = 0xDEADBEEF;
@@ -259,7 +343,7 @@
}
TEST(RoundTrip, UpdateOperationRequest) {
- for (int ver = 0; ver <= MAX_MESSAGE_VERSION; ++ver) {
+ for (int ver = 0; ver <= kMaxMessageVersion; ++ver) {
UpdateOperationRequest msg(ver);
msg.op_handle = 0xDEADBEEF;
msg.input.Reinitialize("foo", 3);
@@ -272,6 +356,7 @@
case 1:
case 2:
case 3:
+ case 4:
deserialized.reset(round_trip(ver, msg, 27));
break;
default:
@@ -283,7 +368,7 @@
}
TEST(RoundTrip, UpdateOperationResponse) {
- for (int ver = 0; ver <= MAX_MESSAGE_VERSION; ++ver) {
+ for (int ver = 0; ver <= kMaxMessageVersion; ++ver) {
UpdateOperationResponse msg(ver);
msg.error = KM_ERROR_OK;
msg.output.Reinitialize("foo", 3);
@@ -300,6 +385,7 @@
break;
case 2:
case 3:
+ case 4:
deserialized.reset(round_trip(ver, msg, 42));
break;
default:
@@ -318,6 +404,7 @@
break;
case 2:
case 3:
+ case 4:
EXPECT_EQ(99U, deserialized->input_consumed);
EXPECT_EQ(1U, deserialized->output_params.size());
break;
@@ -328,7 +415,7 @@
}
TEST(RoundTrip, FinishOperationRequest) {
- for (int ver = 0; ver <= MAX_MESSAGE_VERSION; ++ver) {
+ for (int ver = 0; ver <= kMaxMessageVersion; ++ver) {
FinishOperationRequest msg(ver);
msg.op_handle = 0xDEADBEEF;
msg.signature.Reinitialize("bar", 3);
@@ -344,6 +431,7 @@
deserialized.reset(round_trip(ver, msg, 27));
break;
case 3:
+ case 4:
deserialized.reset(round_trip(ver, msg, 34));
break;
default:
@@ -356,7 +444,7 @@
}
TEST(Round_Trip, FinishOperationResponse) {
- for (int ver = 0; ver <= MAX_MESSAGE_VERSION; ++ver) {
+ for (int ver = 0; ver <= kMaxMessageVersion; ++ver) {
FinishOperationResponse msg(ver);
msg.error = KM_ERROR_OK;
msg.output.Reinitialize("foo", 3);
@@ -369,6 +457,7 @@
break;
case 2:
case 3:
+ case 4:
deserialized.reset(round_trip(ver, msg, 23));
break;
default:
@@ -382,40 +471,81 @@
}
TEST(RoundTrip, ImportKeyRequest) {
- for (int ver = 0; ver <= MAX_MESSAGE_VERSION; ++ver) {
+ for (int ver = 0; ver <= kMaxMessageVersion; ++ver) {
ImportKeyRequest msg(ver);
msg.key_description.Reinitialize(params, array_length(params));
msg.key_format = KM_KEY_FORMAT_X509;
- msg.SetKeyMaterial("foo", 3);
+ msg.key_data = KeymasterKeyBlob(reinterpret_cast<const uint8_t*>("foo"), 3);
+ msg.attestation_signing_key_blob =
+ KeymasterKeyBlob(reinterpret_cast<const uint8_t*>("bar"), 3);
+ msg.attest_key_params.Reinitialize(params, array_length(params));
+ msg.issuer_subject = KeymasterBlob(reinterpret_cast<const uint8_t*>("bar"), 3);
- UniquePtr<ImportKeyRequest> deserialized(round_trip(ver, msg, 89));
+ UniquePtr<ImportKeyRequest> deserialized(round_trip(ver, msg, ver < 4 ? 89 : 181));
EXPECT_EQ(msg.key_description, deserialized->key_description);
EXPECT_EQ(msg.key_format, deserialized->key_format);
- EXPECT_EQ(msg.key_data_length, deserialized->key_data_length);
- EXPECT_EQ(0, memcmp(msg.key_data, deserialized->key_data, msg.key_data_length));
+ EXPECT_EQ(msg.key_data.key_material_size, deserialized->key_data.key_material_size);
+ EXPECT_EQ(0, memcmp(msg.key_data.key_material, deserialized->key_data.key_material,
+ msg.key_data.key_material_size));
+ if (ver < 4) {
+ EXPECT_EQ(0U, deserialized->attestation_signing_key_blob.key_material_size);
+ } else {
+ EXPECT_EQ(3U, deserialized->attestation_signing_key_blob.key_material_size);
+ EXPECT_EQ(0, memcmp(msg.attestation_signing_key_blob.key_material,
+ deserialized->attestation_signing_key_blob.key_material,
+ msg.attestation_signing_key_blob.key_material_size));
+ EXPECT_EQ(deserialized->attest_key_params, msg.attest_key_params);
+ EXPECT_EQ(0, memcmp(msg.issuer_subject.data, deserialized->issuer_subject.data,
+ deserialized->issuer_subject.data_length));
+ }
}
}
TEST(RoundTrip, ImportKeyResponse) {
- for (int ver = 0; ver <= MAX_MESSAGE_VERSION; ++ver) {
+ for (int ver = 0; ver <= kMaxMessageVersion; ++ver) {
ImportKeyResponse msg(ver);
msg.error = KM_ERROR_OK;
msg.SetKeyMaterial("foo", 3);
msg.enforced.Reinitialize(params, array_length(params));
msg.unenforced.Reinitialize(params, array_length(params));
- UniquePtr<ImportKeyResponse> deserialized(round_trip(ver, msg, 167));
+ msg.certificate_chain = CertificateChain(3);
+ msg.certificate_chain.entries[0] = {dup_buffer("foo", 3), 3};
+ msg.certificate_chain.entries[1] = {dup_buffer("bar", 3), 3};
+ msg.certificate_chain.entries[2] = {dup_buffer("baz", 3), 3};
+
+ UniquePtr<ImportKeyResponse> deserialized;
+ if (ver < 4) {
+ deserialized.reset(round_trip(ver, msg, 167));
+ } else {
+ deserialized.reset(round_trip(ver, msg, 192));
+ }
+
EXPECT_EQ(msg.error, deserialized->error);
EXPECT_EQ(msg.key_blob.key_material_size, deserialized->key_blob.key_material_size);
EXPECT_EQ(0, memcmp(msg.key_blob.key_material, deserialized->key_blob.key_material,
msg.key_blob.key_material_size));
EXPECT_EQ(msg.enforced, deserialized->enforced);
EXPECT_EQ(msg.unenforced, deserialized->unenforced);
+
+ keymaster_cert_chain_t* chain = &deserialized->certificate_chain;
+ if (ver < 4) {
+ EXPECT_EQ(nullptr, chain->entries);
+ } else {
+ EXPECT_NE(nullptr, chain->entries);
+ EXPECT_EQ(3U, chain->entry_count);
+ EXPECT_EQ(3U, chain->entries[0].data_length);
+ EXPECT_EQ(0, memcmp("foo", chain->entries[0].data, 3));
+ EXPECT_EQ(3U, chain->entries[1].data_length);
+ EXPECT_EQ(0, memcmp("bar", chain->entries[1].data, 3));
+ EXPECT_EQ(3U, chain->entries[2].data_length);
+ EXPECT_EQ(0, memcmp("baz", chain->entries[2].data, 3));
+ }
}
}
TEST(RoundTrip, ExportKeyRequest) {
- for (int ver = 0; ver <= MAX_MESSAGE_VERSION; ++ver) {
+ for (int ver = 0; ver <= kMaxMessageVersion; ++ver) {
ExportKeyRequest msg(ver);
msg.additional_params.Reinitialize(params, array_length(params));
msg.key_format = KM_KEY_FORMAT_X509;
@@ -430,7 +560,7 @@
}
TEST(RoundTrip, ExportKeyResponse) {
- for (int ver = 0; ver <= MAX_MESSAGE_VERSION; ++ver) {
+ for (int ver = 0; ver <= kMaxMessageVersion; ++ver) {
ExportKeyResponse msg(ver);
msg.error = KM_ERROR_OK;
msg.SetKeyMaterial("foo", 3);
@@ -442,7 +572,7 @@
}
TEST(RoundTrip, DeleteKeyRequest) {
- for (int ver = 0; ver <= MAX_MESSAGE_VERSION; ++ver) {
+ for (int ver = 0; ver <= kMaxMessageVersion; ++ver) {
DeleteKeyRequest msg(ver);
msg.SetKeyMaterial("foo", 3);
@@ -452,29 +582,15 @@
}
}
-TEST(RoundTrip, DeleteKeyResponse) {
- for (int ver = 0; ver <= MAX_MESSAGE_VERSION; ++ver) {
- DeleteKeyResponse msg(ver);
- UniquePtr<DeleteKeyResponse> deserialized(round_trip(ver, msg, 4));
- }
-}
-
TEST(RoundTrip, DeleteAllKeysRequest) {
- for (int ver = 0; ver <= MAX_MESSAGE_VERSION; ++ver) {
+ for (int ver = 0; ver <= kMaxMessageVersion; ++ver) {
DeleteAllKeysRequest msg(ver);
UniquePtr<DeleteAllKeysRequest> deserialized(round_trip(ver, msg, 0));
}
}
-TEST(RoundTrip, DeleteAllKeysResponse) {
- for (int ver = 0; ver <= MAX_MESSAGE_VERSION; ++ver) {
- DeleteAllKeysResponse msg(ver);
- UniquePtr<DeleteAllKeysResponse> deserialized(round_trip(ver, msg, 4));
- }
-}
-
TEST(RoundTrip, GetVersionRequest) {
- GetVersionRequest msg;
+ GetVersionRequest msg(0);
size_t size = msg.SerializedSize();
ASSERT_EQ(0U, size);
@@ -489,7 +605,7 @@
}
TEST(RoundTrip, GetVersionResponse) {
- GetVersionResponse msg;
+ GetVersionResponse msg(0);
msg.error = KM_ERROR_OK;
msg.major_ver = 9;
msg.minor_ver = 98;
@@ -510,8 +626,45 @@
EXPECT_EQ(38U, msg.subminor_ver);
}
+TEST(RoundTrip, GetVersion2Request) {
+ GetVersion2Request msg;
+
+ msg.max_message_version = 0xDEADBEEF;
+ size_t size = msg.SerializedSize();
+ ASSERT_EQ(4U, size);
+
+ UniquePtr<uint8_t[]> buf(new uint8_t[size]);
+ EXPECT_EQ(buf.get() + size, msg.Serialize(buf.get(), buf.get() + size));
+
+ GetVersion2Request deserialized;
+ const uint8_t* p = buf.get();
+ EXPECT_TRUE(deserialized.Deserialize(&p, p + size));
+ EXPECT_EQ((ptrdiff_t)size, p - buf.get());
+ EXPECT_EQ(0xDEADBEEF, msg.max_message_version);
+}
+
+TEST(RoundTrip, GetVersion2Response) {
+ GetVersion2Response msg;
+ msg.error = KM_ERROR_OK;
+ msg.km_version = KmVersion::KEYMINT_1;
+ msg.km_date = 20121900;
+
+ size_t size = msg.SerializedSize();
+ ASSERT_EQ(16U, size);
+
+ UniquePtr<uint8_t[]> buf(new uint8_t[size]);
+ EXPECT_EQ(buf.get() + size, msg.Serialize(buf.get(), buf.get() + size));
+
+ GetVersion2Response deserialized;
+ const uint8_t* p = buf.get();
+ EXPECT_TRUE(deserialized.Deserialize(&p, p + size));
+ EXPECT_EQ((ptrdiff_t)size, p - buf.get());
+ EXPECT_EQ(KmVersion::KEYMINT_1, msg.km_version);
+ EXPECT_EQ(20121900U, msg.km_date);
+}
+
TEST(RoundTrip, ConfigureRequest) {
- for (int ver = 0; ver <= MAX_MESSAGE_VERSION; ++ver) {
+ for (int ver = 0; ver <= kMaxMessageVersion; ++ver) {
ConfigureRequest req(ver);
req.os_version = 1;
req.os_patchlevel = 1;
@@ -523,14 +676,48 @@
}
TEST(RoundTrip, ConfigureResponse) {
- for (int ver = 0; ver <= MAX_MESSAGE_VERSION; ++ver) {
+ for (int ver = 0; ver <= kMaxMessageVersion; ++ver) {
ConfigureResponse rsp(ver);
UniquePtr<ConfigureResponse> deserialized(round_trip(ver, rsp, 4));
}
}
+TEST(RoundTrip, ConfigureVendorPatchlevelRequest) {
+ for (int ver = 0; ver <= kMaxMessageVersion; ++ver) {
+ ConfigureVendorPatchlevelRequest req(ver);
+ req.vendor_patchlevel = 2;
+
+ UniquePtr<ConfigureVendorPatchlevelRequest> deserialized(round_trip(ver, req, 4));
+ EXPECT_EQ(deserialized->vendor_patchlevel, req.vendor_patchlevel);
+ }
+}
+
+TEST(RoundTrip, ConfigureVendorPatchlevelResponse) {
+ for (int ver = 0; ver <= kMaxMessageVersion; ++ver) {
+ ConfigureVendorPatchlevelResponse rsp(ver);
+ UniquePtr<ConfigureVendorPatchlevelResponse> deserialized(round_trip(ver, rsp, 4));
+ }
+}
+
+TEST(RoundTrip, ConfigureBootPatchlevelRequest) {
+ for (int ver = 0; ver <= kMaxMessageVersion; ++ver) {
+ ConfigureBootPatchlevelRequest req(ver);
+ req.boot_patchlevel = 2;
+
+ UniquePtr<ConfigureBootPatchlevelRequest> deserialized(round_trip(ver, req, 4));
+ EXPECT_EQ(deserialized->boot_patchlevel, req.boot_patchlevel);
+ }
+}
+
+TEST(RoundTrip, ConfigureBootPatchlevelResponse) {
+ for (int ver = 0; ver <= kMaxMessageVersion; ++ver) {
+ ConfigureBootPatchlevelResponse rsp(ver);
+ UniquePtr<ConfigureBootPatchlevelResponse> deserialized(round_trip(ver, rsp, 4));
+ }
+}
+
TEST(RoundTrip, AddEntropyRequest) {
- for (int ver = 0; ver <= MAX_MESSAGE_VERSION; ++ver) {
+ for (int ver = 0; ver <= kMaxMessageVersion; ++ver) {
AddEntropyRequest msg(ver);
msg.random_data.Reinitialize("foo", 3);
@@ -540,29 +727,15 @@
}
}
-TEST(RoundTrip, AddEntropyResponse) {
- for (int ver = 0; ver <= MAX_MESSAGE_VERSION; ++ver) {
- AddEntropyResponse msg(ver);
- UniquePtr<AddEntropyResponse> deserialized(round_trip(ver, msg, 4));
- }
-}
-
TEST(RoundTrip, AbortOperationRequest) {
- for (int ver = 0; ver <= MAX_MESSAGE_VERSION; ++ver) {
+ for (int ver = 0; ver <= kMaxMessageVersion; ++ver) {
AbortOperationRequest msg(ver);
UniquePtr<AbortOperationRequest> deserialized(round_trip(ver, msg, 8));
}
}
-TEST(RoundTrip, AbortOperationResponse) {
- for (int ver = 0; ver <= MAX_MESSAGE_VERSION; ++ver) {
- AbortOperationResponse msg(ver);
- UniquePtr<AbortOperationResponse> deserialized(round_trip(ver, msg, 4));
- }
-}
-
TEST(RoundTrip, AttestKeyRequest) {
- for (int ver = 0; ver <= MAX_MESSAGE_VERSION; ++ver) {
+ for (int ver = 0; ver <= kMaxMessageVersion; ++ver) {
AttestKeyRequest msg(ver);
msg.SetKeyMaterial("foo", 3);
msg.attest_params.Reinitialize(params, array_length(params));
@@ -575,10 +748,11 @@
}
TEST(RoundTrip, AttestKeyResponse) {
- for (int ver = 0; ver <= MAX_MESSAGE_VERSION; ++ver) {
+ for (int ver = 0; ver <= kMaxMessageVersion; ++ver) {
AttestKeyResponse msg(ver);
msg.error = KM_ERROR_OK;
- EXPECT_TRUE(msg.AllocateChain(3));
+ msg.certificate_chain = CertificateChain(3);
+ EXPECT_TRUE(!!msg.certificate_chain.entries);
msg.certificate_chain.entries[0] = {dup_buffer("foo", 3), 3};
msg.certificate_chain.entries[1] = {dup_buffer("bar", 3), 3};
msg.certificate_chain.entries[2] = {dup_buffer("baz", 3), 3};
@@ -598,7 +772,7 @@
}
TEST(RoundTrip, UpgradeKeyRequest) {
- for (int ver = 0; ver <= MAX_MESSAGE_VERSION; ++ver) {
+ for (int ver = 0; ver <= kMaxMessageVersion; ++ver) {
UpgradeKeyRequest msg(ver);
msg.SetKeyMaterial("foo", 3);
msg.upgrade_params.Reinitialize(params, array_length(params));
@@ -611,7 +785,7 @@
}
TEST(RoundTrip, UpgradeKeyResponse) {
- for (int ver = 0; ver <= MAX_MESSAGE_VERSION; ++ver) {
+ for (int ver = 0; ver <= kMaxMessageVersion; ++ver) {
UpgradeKeyResponse req(ver);
req.error = KM_ERROR_OK;
req.upgraded_key.key_material = dup_array(TEST_DATA);
@@ -625,6 +799,67 @@
}
}
+TEST(RoundTrip, GenerateTimestampTokenRequest) {
+ for (int ver = 0; ver <= kMaxMessageVersion; ++ver) {
+ GenerateTimestampTokenRequest msg(ver);
+ msg.challenge = 1;
+ UniquePtr<GenerateTimestampTokenRequest> deserialized(round_trip(ver, msg, 8));
+ EXPECT_EQ(1U, deserialized->challenge);
+ }
+}
+
+TEST(RoundTrip, GenerateTimestampTokenResponse) {
+ for (int ver = 0; ver <= kMaxMessageVersion; ++ver) {
+ GenerateTimestampTokenResponse msg(ver);
+ msg.error = KM_ERROR_OK;
+ msg.token.challenge = 1;
+ msg.token.timestamp = 2;
+ msg.token.security_level = KM_SECURITY_LEVEL_SOFTWARE;
+ msg.token.mac.data = dup_array(TEST_DATA);
+ msg.token.mac.data_length = array_length(TEST_DATA);
+ UniquePtr<GenerateTimestampTokenResponse> deserialized(round_trip(ver, msg, 39));
+ EXPECT_EQ(1U, deserialized->token.challenge);
+ EXPECT_EQ(2U, deserialized->token.timestamp);
+ EXPECT_EQ(KM_SECURITY_LEVEL_SOFTWARE, deserialized->token.security_level);
+ EXPECT_EQ(msg.token.mac.data_length, deserialized->token.mac.data_length);
+ EXPECT_EQ(
+ 0, memcmp(msg.token.mac.data, deserialized->token.mac.data, msg.token.mac.data_length));
+ }
+}
+
+#define SET_ATTESTATION_ID(x) msg.x.Reinitialize(#x, strlen(#x))
+
+void check_id(const Buffer& id, const char* value) {
+ auto len = strlen(value);
+ EXPECT_EQ(id.available_read(), len) << "On " << value;
+ EXPECT_TRUE(memcmp(id.peek_read(), value, len) == 0) << "On " << value;
+}
+
+#define CHECK_ID(x) check_id(deserialized->x, #x);
+
+TEST(RoundTrip, SetAttestationIdsRequest) {
+ for (int ver = 0; ver <= kMaxMessageVersion; ++ver) {
+ SetAttestationIdsRequest msg(ver);
+ SET_ATTESTATION_ID(brand);
+ SET_ATTESTATION_ID(device);
+ SET_ATTESTATION_ID(product);
+ SET_ATTESTATION_ID(serial);
+ SET_ATTESTATION_ID(imei);
+ SET_ATTESTATION_ID(meid);
+ SET_ATTESTATION_ID(manufacturer);
+ SET_ATTESTATION_ID(model);
+
+ UniquePtr<SetAttestationIdsRequest> deserialized(round_trip(ver, msg, 81));
+ ASSERT_TRUE(deserialized);
+ CHECK_ID(brand);
+ CHECK_ID(device);
+ CHECK_ID(product);
+ CHECK_ID(serial);
+ CHECK_ID(imei);
+ CHECK_ID(model);
+ }
+}
+
uint8_t msgbuf[] = {
220, 88, 183, 255, 71, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 173, 0, 0, 0, 228, 174, 98, 187, 191, 135, 253, 200, 51, 230, 114, 247, 151, 109,
@@ -659,7 +894,7 @@
*/
template <typename Message> void parse_garbage() {
- for (int32_t ver = 0; ver <= MAX_MESSAGE_VERSION; ++ver) {
+ for (int32_t ver = 0; ver <= kMaxMessageVersion; ++ver) {
Message msg(ver);
const uint8_t* end = msgbuf + array_length(msgbuf);
for (size_t i = 0; i < array_length(msgbuf); ++i) {
@@ -679,7 +914,7 @@
for (size_t i = 0; i < kBufSize; ++i)
buf[i] = static_cast<uint8_t>(rand());
- for (uint32_t ver = 0; ver < MAX_MESSAGE_VERSION; ++ver) {
+ for (uint32_t ver = 0; ver < kMaxMessageVersion; ++ver) {
Message msg(ver);
const uint8_t* end = buf.get() + kBufSize;
for (size_t i = 0; i < kBufSize; ++i) {
@@ -694,15 +929,12 @@
TEST(GarbageTest, Message) { parse_garbage<Message>(); }
GARBAGE_TEST(AbortOperationRequest);
-GARBAGE_TEST(AbortOperationResponse);
+GARBAGE_TEST(EmptyKeymasterResponse);
GARBAGE_TEST(AddEntropyRequest);
-GARBAGE_TEST(AddEntropyResponse);
GARBAGE_TEST(BeginOperationRequest);
GARBAGE_TEST(BeginOperationResponse);
GARBAGE_TEST(DeleteAllKeysRequest);
-GARBAGE_TEST(DeleteAllKeysResponse);
GARBAGE_TEST(DeleteKeyRequest);
-GARBAGE_TEST(DeleteKeyResponse);
GARBAGE_TEST(ExportKeyRequest);
GARBAGE_TEST(ExportKeyResponse);
GARBAGE_TEST(FinishOperationRequest);
@@ -713,19 +945,15 @@
GARBAGE_TEST(GetKeyCharacteristicsResponse);
GARBAGE_TEST(ImportKeyRequest);
GARBAGE_TEST(ImportKeyResponse);
-GARBAGE_TEST(SupportedByAlgorithmAndPurposeRequest)
-GARBAGE_TEST(SupportedByAlgorithmRequest)
GARBAGE_TEST(UpdateOperationRequest);
GARBAGE_TEST(UpdateOperationResponse);
GARBAGE_TEST(AttestKeyRequest);
GARBAGE_TEST(AttestKeyResponse);
GARBAGE_TEST(UpgradeKeyRequest);
GARBAGE_TEST(UpgradeKeyResponse);
-
-// The macro doesn't work on this one.
-TEST(GarbageTest, SupportedResponse) {
- parse_garbage<SupportedResponse<keymaster_digest_t>>();
-}
+GARBAGE_TEST(GenerateTimestampTokenRequest);
+GARBAGE_TEST(GenerateTimestampTokenResponse);
+GARBAGE_TEST(SetAttestationIdsRequest);
} // namespace test
diff --git a/tests/android_keymaster_test.cpp b/tests/android_keymaster_test.cpp
index 253ee92..7c06ce3 100644
--- a/tests/android_keymaster_test.cpp
+++ b/tests/android_keymaster_test.cpp
@@ -22,20 +22,18 @@
#include <openssl/evp.h>
#include <openssl/x509.h>
-#include <hardware/keymaster0.h>
-
#include <keymaster/android_keymaster.h>
-#include <keymaster/attestation_record.h>
#include <keymaster/contexts/pure_soft_keymaster_context.h>
#include <keymaster/contexts/soft_keymaster_context.h>
#include <keymaster/key_factory.h>
+#include <keymaster/km_openssl/attestation_record.h>
#include <keymaster/km_openssl/hmac_key.h>
#include <keymaster/km_openssl/openssl_utils.h>
#include <keymaster/km_openssl/soft_keymaster_enforcement.h>
-#include <keymaster/legacy_support/keymaster0_engine.h>
#include <keymaster/soft_keymaster_device.h>
#include "android_keymaster_test_utils.h"
+#include "test_keys.h"
using std::ifstream;
using std::istreambuf_iterator;
@@ -97,9 +95,12 @@
*/
class TestKeymasterContext : public SoftKeymasterContext {
public:
- TestKeymasterContext() {}
+ TestKeymasterContext() : SoftKeymasterContext(kCurrentKmVersion) {}
+ TestKeymasterContext(KmVersion version) : SoftKeymasterContext(version) {}
explicit TestKeymasterContext(const string& root_of_trust)
- : SoftKeymasterContext(root_of_trust) {}
+ : SoftKeymasterContext(kCurrentKmVersion, root_of_trust) {}
+ explicit TestKeymasterContext(KmVersion version, const string& root_of_trust)
+ : SoftKeymasterContext(version, root_of_trust) {}
KeymasterEnforcement* enforcement_policy() override { return &test_policy_; }
@@ -114,7 +115,7 @@
public:
keymaster2_device_t* CreateDevice() const override {
std::cerr << "Creating software-only device" << std::endl;
- context_ = new TestKeymasterContext;
+ context_ = new TestKeymasterContext(KmVersion::KEYMASTER_4_1);
SoftKeymasterDevice* device = new SoftKeymasterDevice(context_);
AuthorizationSet version_info(AuthorizationSetBuilder()
.Authorization(TAG_OS_VERSION, kOsVersion)
@@ -123,11 +124,10 @@
return device->keymaster2_device();
}
- bool algorithm_in_km0_hardware(keymaster_algorithm_t) const override { return false; }
- int keymaster0_calls() const override { return 0; }
bool is_keymaster1_hw() const override { return false; }
KeymasterContext* keymaster_context() const override { return context_; }
string name() const override { return "Soft Keymaster2"; }
+ KmVersion km_version() const override { return KmVersion::KEYMASTER_4_1; }
private:
mutable TestKeymasterContext* context_;
@@ -142,11 +142,13 @@
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());
+ keymaster1_device_t* fake_device =
+ make_device_sha256_only((new SoftKeymasterDevice(new TestKeymasterContext(
+ KmVersion::KEYMASTER_4_1, "PseudoHW")))
+ ->keymaster_device());
// device doesn't leak; it's cleaned up by device->keymaster_device()->common.close().
- context_ = new TestKeymasterContext;
+ context_ = new TestKeymasterContext(KmVersion::KEYMASTER_4_1);
SoftKeymasterDevice* device = new SoftKeymasterDevice(context_);
device->SetHardwareDevice(fake_device);
@@ -157,12 +159,11 @@
return device->keymaster2_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; }
bool is_keymaster1_hw() const override { return true; }
KeymasterContext* keymaster_context() const override { return context_; }
string name() const override { return "Wrapped fake keymaster1 w/minimal digests"; }
+ KmVersion km_version() const override { return KmVersion::KEYMASTER_4_1; }
private:
mutable TestKeymasterContext* context_;
@@ -177,11 +178,12 @@
std::cerr << "Creating keymaster1-backed device";
// fake_device doesn't leak because device (below) takes ownership of it.
- keymaster1_device_t* fake_device =
- (new SoftKeymasterDevice(new TestKeymasterContext("PseudoHW")))->keymaster_device();
+ keymaster1_device_t* fake_device = (new SoftKeymasterDevice(new TestKeymasterContext(
+ KmVersion::KEYMASTER_4_1, "PseudoHW")))
+ ->keymaster_device();
// device doesn't leak; it's cleaned up by device->keymaster_device()->common.close().
- context_ = new TestKeymasterContext;
+ context_ = new TestKeymasterContext(KmVersion::KEYMASTER_4_1);
SoftKeymasterDevice* device = new SoftKeymasterDevice(context_);
device->SetHardwareDevice(fake_device);
@@ -192,21 +194,20 @@
return device->keymaster2_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 false; }
bool is_keymaster1_hw() const override { return true; }
KeymasterContext* keymaster_context() const override { return context_; }
string name() const override { return "Wrapped fake keymaster1 w/full digests"; }
+ KmVersion km_version() const override { return KmVersion::KEYMASTER_4_1; }
private:
mutable TestKeymasterContext* context_;
};
-static auto test_params = testing::Values(
- InstanceCreatorPtr(new SoftKeymasterTestInstanceCreator),
- InstanceCreatorPtr(new Keymaster1TestInstanceCreator),
- InstanceCreatorPtr(new Sha256OnlyKeymaster1TestInstanceCreator));
+static auto test_params =
+ testing::Values(InstanceCreatorPtr(new SoftKeymasterTestInstanceCreator),
+ InstanceCreatorPtr(new Keymaster1TestInstanceCreator),
+ InstanceCreatorPtr(new Sha256OnlyKeymaster1TestInstanceCreator));
class NewKeyGeneration : public Keymaster2Test {
protected:
@@ -256,16 +257,9 @@
// Check specified tags are all present, and in the right set.
AuthorizationSet crypto_params;
AuthorizationSet non_crypto_params;
- 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());
- non_crypto_params.push_back(sw_enforced());
- } else {
- EXPECT_EQ(0U, hw_enforced().size());
- EXPECT_NE(0U, sw_enforced().size());
- crypto_params.push_back(sw_enforced());
- }
+ EXPECT_EQ(0U, hw_enforced().size());
+ EXPECT_NE(0U, sw_enforced().size());
+ crypto_params.push_back(sw_enforced());
EXPECT_TRUE(contains(crypto_params, TAG_ALGORITHM, KM_ALGORITHM_RSA));
EXPECT_FALSE(contains(non_crypto_params, TAG_ALGORITHM, KM_ALGORITHM_RSA));
@@ -275,9 +269,6 @@
EXPECT_FALSE(contains(non_crypto_params, TAG_RSA_PUBLIC_EXPONENT, 3));
EXPECT_EQ(KM_ERROR_OK, DeleteKey());
-
- if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA))
- EXPECT_EQ(2, GetParam()->keymaster0_calls());
}
TEST_P(NewKeyGeneration, RsaDefaultSize) {
@@ -286,8 +277,6 @@
.Authorization(TAG_ALGORITHM, KM_ALGORITHM_RSA)
.Authorization(TAG_RSA_PUBLIC_EXPONENT, 3)
.SigningKey()));
-
- EXPECT_EQ(0, GetParam()->keymaster0_calls());
}
TEST_P(NewKeyGeneration, Ecdsa) {
@@ -298,24 +287,14 @@
// Check specified tags are all present, and in the right set.
AuthorizationSet crypto_params;
AuthorizationSet non_crypto_params;
- 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());
- non_crypto_params.push_back(sw_enforced());
- } else {
- EXPECT_EQ(0U, hw_enforced().size());
- EXPECT_NE(0U, sw_enforced().size());
- crypto_params.push_back(sw_enforced());
- }
+ EXPECT_EQ(0U, hw_enforced().size());
+ EXPECT_NE(0U, sw_enforced().size());
+ crypto_params.push_back(sw_enforced());
EXPECT_TRUE(contains(crypto_params, TAG_ALGORITHM, KM_ALGORITHM_EC));
EXPECT_FALSE(contains(non_crypto_params, TAG_ALGORITHM, KM_ALGORITHM_EC));
EXPECT_TRUE(contains(crypto_params, TAG_KEY_SIZE, 224));
EXPECT_FALSE(contains(non_crypto_params, TAG_KEY_SIZE, 224));
-
- if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_EC))
- EXPECT_EQ(1, GetParam()->keymaster0_calls());
}
TEST_P(NewKeyGeneration, EcdsaDefaultSize) {
@@ -324,14 +303,11 @@
.Authorization(TAG_ALGORITHM, KM_ALGORITHM_EC)
.SigningKey()
.Digest(KM_DIGEST_NONE)));
-
- EXPECT_EQ(0, GetParam()->keymaster0_calls());
}
TEST_P(NewKeyGeneration, EcdsaInvalidSize) {
ASSERT_EQ(KM_ERROR_UNSUPPORTED_KEY_SIZE,
GenerateKey(AuthorizationSetBuilder().EcdsaSigningKey(190).Digest(KM_DIGEST_NONE)));
- EXPECT_EQ(0, GetParam()->keymaster0_calls());
}
TEST_P(NewKeyGeneration, EcdsaMismatchKeySize) {
@@ -349,9 +325,6 @@
KM_DIGEST_NONE)))
<< "Failed to generate size: " << size;
}
-
- if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_EC))
- EXPECT_EQ(4, GetParam()->keymaster0_calls());
}
TEST_P(NewKeyGeneration, HmacSha256) {
@@ -359,8 +332,6 @@
.HmacKey(128)
.Digest(KM_DIGEST_SHA_2_256)
.Authorization(TAG_MIN_MAC_LENGTH, 256)));
-
- EXPECT_EQ(0, GetParam()->keymaster0_calls());
}
TEST_P(NewKeyGeneration, CheckKeySizes) {
@@ -380,7 +351,6 @@
.Authorization(TAG_MIN_MAC_LENGTH, 256)));
}
}
- EXPECT_EQ(0, GetParam()->keymaster0_calls());
}
TEST_P(NewKeyGeneration, HmacMultipleDigests) {
@@ -390,8 +360,6 @@
.Digest(KM_DIGEST_SHA1)
.Digest(KM_DIGEST_SHA_2_256)
.Authorization(TAG_MIN_MAC_LENGTH, 128)));
-
- EXPECT_EQ(0, GetParam()->keymaster0_calls());
}
TEST_P(NewKeyGeneration, HmacDigestNone) {
@@ -400,8 +368,6 @@
.HmacKey(128)
.Digest(KM_DIGEST_NONE)
.Authorization(TAG_MIN_MAC_LENGTH, 128)));
-
- EXPECT_EQ(0, GetParam()->keymaster0_calls());
}
TEST_P(NewKeyGeneration, HmacSha256TooShortMacLength) {
@@ -410,8 +376,6 @@
.HmacKey(128)
.Digest(KM_DIGEST_SHA_2_256)
.Authorization(TAG_MIN_MAC_LENGTH, 48)));
-
- EXPECT_EQ(0, GetParam()->keymaster0_calls());
}
TEST_P(NewKeyGeneration, HmacSha256NonIntegralOctetMacLength) {
@@ -420,8 +384,6 @@
.HmacKey(128)
.Digest(KM_DIGEST_SHA_2_256)
.Authorization(TAG_MIN_MAC_LENGTH, 130)));
-
- EXPECT_EQ(0, GetParam()->keymaster0_calls());
}
TEST_P(NewKeyGeneration, HmacSha256TooLongMacLength) {
@@ -430,8 +392,6 @@
.HmacKey(128)
.Digest(KM_DIGEST_SHA_2_256)
.Authorization(TAG_MIN_MAC_LENGTH, 384)));
-
- EXPECT_EQ(0, GetParam()->keymaster0_calls());
}
typedef Keymaster2Test GetKeyCharacteristics;
@@ -446,9 +406,6 @@
ASSERT_EQ(KM_ERROR_OK, GetCharacteristics());
EXPECT_EQ(original, sw_enforced());
-
- if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA))
- EXPECT_EQ(1, GetParam()->keymaster0_calls());
}
typedef Keymaster2Test SigningOperationsTest;
@@ -462,9 +419,6 @@
string message = "12345678901234567890123456789012";
string signature;
SignMessage(message, &signature, KM_DIGEST_NONE, KM_PAD_NONE);
-
- if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA))
- EXPECT_EQ(3, GetParam()->keymaster0_calls());
}
TEST_P(SigningOperationsTest, RsaPssSha256Success) {
@@ -476,9 +430,6 @@
string message(1024, 'a');
string signature;
SignMessage(message, &signature, KM_DIGEST_SHA_2_256, KM_PAD_RSA_PSS);
-
- if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA))
- EXPECT_EQ(3, GetParam()->keymaster0_calls());
}
TEST_P(SigningOperationsTest, RsaPaddingNoneDoesNotAllowOther) {
@@ -493,9 +444,6 @@
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) {
@@ -506,9 +454,6 @@
string message(1024, 'a');
string signature;
SignMessage(message, &signature, KM_DIGEST_SHA_2_256, KM_PAD_RSA_PKCS1_1_5_SIGN);
-
- if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA))
- EXPECT_EQ(3, GetParam()->keymaster0_calls());
}
TEST_P(SigningOperationsTest, RsaPkcs1NoDigestSuccess) {
@@ -519,9 +464,6 @@
string message(53, 'a');
string signature;
SignMessage(message, &signature, KM_DIGEST_NONE, KM_PAD_RSA_PKCS1_1_5_SIGN);
-
- if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA))
- EXPECT_EQ(3, GetParam()->keymaster0_calls());
}
TEST_P(SigningOperationsTest, RsaPkcs1NoDigestTooLarge) {
@@ -538,9 +480,6 @@
string result;
string signature;
EXPECT_EQ(KM_ERROR_INVALID_INPUT_LENGTH, FinishOperation(message, "", &signature));
-
- if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA))
- EXPECT_EQ(2, GetParam()->keymaster0_calls());
}
TEST_P(SigningOperationsTest, RsaPssSha256TooSmallKey) {
@@ -573,9 +512,6 @@
string result;
size_t input_consumed;
EXPECT_EQ(KM_ERROR_INVALID_INPUT_LENGTH, UpdateOperation(message, &result, &input_consumed));
-
- if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA))
- EXPECT_EQ(2, GetParam()->keymaster0_calls());
}
TEST_P(SigningOperationsTest, RsaAbort) {
@@ -590,9 +526,6 @@
EXPECT_EQ(KM_ERROR_OK, AbortOperation());
// Another abort should fail
EXPECT_EQ(KM_ERROR_INVALID_OPERATION_HANDLE, AbortOperation());
-
- if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA))
- EXPECT_EQ(2, GetParam()->keymaster0_calls());
}
TEST_P(SigningOperationsTest, RsaUnsupportedPadding) {
@@ -603,9 +536,6 @@
AuthorizationSet begin_params(client_params());
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_km0_hardware(KM_ALGORITHM_RSA))
- EXPECT_EQ(2, GetParam()->keymaster0_calls());
}
TEST_P(SigningOperationsTest, RsaNoDigest) {
@@ -618,9 +548,6 @@
begin_params.push_back(TAG_DIGEST, KM_DIGEST_NONE);
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_km0_hardware(KM_ALGORITHM_RSA))
- EXPECT_EQ(2, GetParam()->keymaster0_calls());
}
TEST_P(SigningOperationsTest, RsaNoPadding) {
@@ -630,9 +557,6 @@
AuthorizationSet begin_params(client_params());
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_km0_hardware(KM_ALGORITHM_RSA))
- EXPECT_EQ(2, GetParam()->keymaster0_calls());
}
TEST_P(SigningOperationsTest, RsaTooShortMessage) {
@@ -643,9 +567,6 @@
string message = "1234567890123456789012345678901";
string signature;
SignMessage(message, &signature, KM_DIGEST_NONE, KM_PAD_NONE);
-
- if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA))
- EXPECT_EQ(3, GetParam()->keymaster0_calls());
}
TEST_P(SigningOperationsTest, RsaSignWithEncryptionKey) {
@@ -657,9 +578,6 @@
begin_params.push_back(TAG_PADDING, KM_PAD_NONE);
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_km0_hardware(KM_ALGORITHM_RSA))
- EXPECT_EQ(2, GetParam()->keymaster0_calls());
}
TEST_P(SigningOperationsTest, RsaSignTooLargeMessage) {
@@ -679,9 +597,6 @@
ASSERT_EQ(message.size(), input_consumed);
string output;
ASSERT_EQ(KM_ERROR_INVALID_ARGUMENT, FinishOperation(&output));
-
- if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA))
- EXPECT_EQ(3, GetParam()->keymaster0_calls());
}
TEST_P(SigningOperationsTest, EcdsaSuccess) {
@@ -690,9 +605,6 @@
string message(224 / 8, 'a');
string signature;
SignMessage(message, &signature, KM_DIGEST_NONE);
-
- if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_EC))
- EXPECT_EQ(3, GetParam()->keymaster0_calls());
}
TEST_P(SigningOperationsTest, EcdsaSha256Success) {
@@ -701,9 +613,6 @@
string message(1024, 'a');
string signature;
SignMessage(message, &signature, KM_DIGEST_SHA_2_256);
-
- if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_EC))
- EXPECT_EQ(3, GetParam()->keymaster0_calls());
}
TEST_P(SigningOperationsTest, EcdsaSha384Success) {
@@ -712,9 +621,6 @@
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());
}
TEST_P(SigningOperationsTest, EcdsaNoPaddingHugeData) {
@@ -728,9 +634,6 @@
string result;
size_t input_consumed;
EXPECT_EQ(KM_ERROR_OK, UpdateOperation(message, &result, &input_consumed));
-
- if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_EC))
- EXPECT_EQ(2, GetParam()->keymaster0_calls());
}
TEST_P(SigningOperationsTest, EcdsaAllSizesAndHashes) {
@@ -748,15 +651,10 @@
string message(1024, 'a');
string signature;
- if (digest == KM_DIGEST_NONE)
- message.resize(key_size / 8);
+ if (digest == KM_DIGEST_NONE) message.resize(key_size / 8);
SignMessage(message, &signature, digest);
}
}
-
- if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_EC))
- EXPECT_EQ(digests.size() * key_sizes.size() * 3,
- static_cast<size_t>(GetParam()->keymaster0_calls()));
}
TEST_P(SigningOperationsTest, AesEcbSign) {
@@ -765,8 +663,6 @@
TAG_BLOCK_MODE, KM_MODE_ECB)));
ASSERT_EQ(KM_ERROR_UNSUPPORTED_PURPOSE, BeginOperation(KM_PURPOSE_SIGN));
ASSERT_EQ(KM_ERROR_UNSUPPORTED_PURPOSE, BeginOperation(KM_PURPOSE_VERIFY));
-
- EXPECT_EQ(0, GetParam()->keymaster0_calls());
}
TEST_P(SigningOperationsTest, HmacSha1Success) {
@@ -778,8 +674,6 @@
string signature;
MacMessage(message, &signature, 160);
ASSERT_EQ(20U, signature.size());
-
- EXPECT_EQ(0, GetParam()->keymaster0_calls());
}
TEST_P(SigningOperationsTest, HmacSha224Success) {
@@ -791,8 +685,6 @@
string signature;
MacMessage(message, &signature, 224);
ASSERT_EQ(28U, signature.size());
-
- EXPECT_EQ(0, GetParam()->keymaster0_calls());
}
TEST_P(SigningOperationsTest, HmacSha256Success) {
@@ -804,8 +696,6 @@
string signature;
MacMessage(message, &signature, 256);
ASSERT_EQ(32U, signature.size());
-
- EXPECT_EQ(0, GetParam()->keymaster0_calls());
}
TEST_P(SigningOperationsTest, HmacSha384Success) {
@@ -818,8 +708,6 @@
string signature;
MacMessage(message, &signature, 384);
ASSERT_EQ(48U, signature.size());
-
- EXPECT_EQ(0, GetParam()->keymaster0_calls());
}
TEST_P(SigningOperationsTest, HmacSha512Success) {
@@ -831,8 +719,6 @@
string signature;
MacMessage(message, &signature, 512);
ASSERT_EQ(64U, signature.size());
-
- EXPECT_EQ(0, GetParam()->keymaster0_calls());
}
TEST_P(SigningOperationsTest, HmacLengthInKey) {
@@ -845,8 +731,6 @@
string signature;
MacMessage(message, &signature, 160);
ASSERT_EQ(20U, signature.size());
-
- EXPECT_EQ(0, GetParam()->keymaster0_calls());
}
TEST_P(SigningOperationsTest, HmacRfc4231TestCase3) {
@@ -879,8 +763,6 @@
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());
}
TEST_P(SigningOperationsTest, HmacRfc4231TestCase4) {
@@ -917,8 +799,6 @@
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());
}
TEST_P(SigningOperationsTest, HmacRfc4231TestCase5) {
@@ -946,8 +826,6 @@
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());
}
TEST_P(SigningOperationsTest, HmacRfc4231TestCase6) {
@@ -981,8 +859,6 @@
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());
}
TEST_P(SigningOperationsTest, HmacRfc4231TestCase7) {
@@ -1018,8 +894,6 @@
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());
}
TEST_P(SigningOperationsTest, HmacSha256TooLargeMacLength) {
@@ -1032,8 +906,6 @@
begin_params.push_back(TAG_DIGEST, KM_DIGEST_SHA_2_256);
ASSERT_EQ(KM_ERROR_UNSUPPORTED_MAC_LENGTH,
BeginOperation(KM_PURPOSE_SIGN, begin_params, nullptr /* output_params */));
-
- EXPECT_EQ(0, GetParam()->keymaster0_calls());
}
TEST_P(SigningOperationsTest, HmacSha256TooSmallMacLength) {
@@ -1046,8 +918,6 @@
begin_params.push_back(TAG_DIGEST, KM_DIGEST_SHA_2_256);
ASSERT_EQ(KM_ERROR_INVALID_MAC_LENGTH,
BeginOperation(KM_PURPOSE_SIGN, begin_params, nullptr /* output_params */));
-
- EXPECT_EQ(0, GetParam()->keymaster0_calls());
}
// TODO(swillden): Add more verification failure tests.
@@ -1064,9 +934,6 @@
string signature;
SignMessage(message, &signature, KM_DIGEST_NONE, KM_PAD_NONE);
VerifyMessage(message, signature, KM_DIGEST_NONE, KM_PAD_NONE);
-
- if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA))
- EXPECT_EQ(4, GetParam()->keymaster0_calls());
}
TEST_P(VerificationOperationsTest, RsaPssSha256Success) {
@@ -1079,9 +946,6 @@
string signature;
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_km0_hardware(KM_ALGORITHM_RSA))
- EXPECT_EQ(4, GetParam()->keymaster0_calls());
}
TEST_P(VerificationOperationsTest, RsaPssSha224Success) {
@@ -1095,9 +959,6 @@
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));
@@ -1137,9 +998,6 @@
string result;
EXPECT_EQ(KM_ERROR_VERIFICATION_FAILED, FinishOperation(message, signature, &result));
-
- if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA))
- EXPECT_EQ(4, GetParam()->keymaster0_calls());
}
TEST_P(VerificationOperationsTest, RsaPssSha256CorruptInput) {
@@ -1160,9 +1018,6 @@
string result;
EXPECT_EQ(KM_ERROR_VERIFICATION_FAILED, FinishOperation(message, signature, &result));
-
- if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA))
- EXPECT_EQ(4, GetParam()->keymaster0_calls());
}
TEST_P(VerificationOperationsTest, RsaPkcs1Sha256Success) {
@@ -1174,9 +1029,6 @@
string signature;
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_km0_hardware(KM_ALGORITHM_RSA))
- EXPECT_EQ(4, GetParam()->keymaster0_calls());
}
TEST_P(VerificationOperationsTest, RsaPks1Sha224Success) {
@@ -1190,9 +1042,6 @@
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));
@@ -1231,9 +1080,6 @@
string result;
EXPECT_EQ(KM_ERROR_VERIFICATION_FAILED, FinishOperation(message, signature, &result));
-
- if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA))
- EXPECT_EQ(4, GetParam()->keymaster0_calls());
}
TEST_P(VerificationOperationsTest, RsaPkcs1Sha256CorruptInput) {
@@ -1254,9 +1100,6 @@
string result;
EXPECT_EQ(KM_ERROR_VERIFICATION_FAILED, FinishOperation(message, signature, &result));
-
- if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA))
- EXPECT_EQ(4, GetParam()->keymaster0_calls());
}
TEST_P(VerificationOperationsTest, RsaAllDigestAndPadCombinations) {
@@ -1266,7 +1109,9 @@
};
vector<keymaster_padding_t> padding_modes{
- KM_PAD_NONE, KM_PAD_RSA_PKCS1_1_5_SIGN, KM_PAD_RSA_PSS,
+ KM_PAD_NONE,
+ KM_PAD_RSA_PKCS1_1_5_SIGN,
+ KM_PAD_RSA_PSS,
};
int trial_count = 0;
@@ -1349,9 +1194,6 @@
++trial_count;
}
}
-
- if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA))
- EXPECT_EQ(trial_count * 4, GetParam()->keymaster0_calls());
}
TEST_P(VerificationOperationsTest, EcdsaSuccess) {
@@ -1361,9 +1203,6 @@
string signature;
SignMessage(message, &signature, KM_DIGEST_NONE);
VerifyMessage(message, signature, KM_DIGEST_NONE);
-
- if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_EC))
- EXPECT_EQ(4, GetParam()->keymaster0_calls());
}
TEST_P(VerificationOperationsTest, EcdsaTooShort) {
@@ -1373,9 +1212,6 @@
string signature;
SignMessage(message, &signature, KM_DIGEST_NONE);
VerifyMessage(message, signature, KM_DIGEST_NONE);
-
- if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_EC))
- EXPECT_EQ(4, GetParam()->keymaster0_calls());
}
TEST_P(VerificationOperationsTest, EcdsaSlightlyTooLong) {
@@ -1390,9 +1226,6 @@
// Modifying low-order bits doesn't matter, because they didn't get signed. Ugh.
message[65] ^= 7;
VerifyMessage(message, signature, KM_DIGEST_NONE);
-
- if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_EC))
- EXPECT_EQ(5, GetParam()->keymaster0_calls());
}
TEST_P(VerificationOperationsTest, EcdsaSha256Success) {
@@ -1405,9 +1238,6 @@
SignMessage(message, &signature, KM_DIGEST_SHA_2_256);
VerifyMessage(message, signature, KM_DIGEST_SHA_2_256);
- 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);
@@ -1426,9 +1256,6 @@
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);
@@ -1462,10 +1289,6 @@
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) {
@@ -1477,8 +1300,6 @@
string signature;
MacMessage(message, &signature, 160);
VerifyMac(message, signature);
-
- EXPECT_EQ(0, GetParam()->keymaster0_calls());
}
TEST_P(VerificationOperationsTest, HmacSha224Success) {
@@ -1490,8 +1311,6 @@
string signature;
MacMessage(message, &signature, 224);
VerifyMac(message, signature);
-
- EXPECT_EQ(0, GetParam()->keymaster0_calls());
}
TEST_P(VerificationOperationsTest, HmacSha256Success) {
@@ -1503,8 +1322,6 @@
string signature;
MacMessage(message, &signature, 256);
VerifyMac(message, signature);
-
- EXPECT_EQ(0, GetParam()->keymaster0_calls());
}
TEST_P(VerificationOperationsTest, HmacSha256TooShortMac) {
@@ -1527,8 +1344,6 @@
EXPECT_EQ(KM_ERROR_OK, BeginOperation(KM_PURPOSE_VERIFY, begin_params));
string result;
EXPECT_EQ(KM_ERROR_INVALID_MAC_LENGTH, FinishOperation(message, signature, &result));
-
- EXPECT_EQ(0, GetParam()->keymaster0_calls());
}
TEST_P(VerificationOperationsTest, HmacSha384Success) {
@@ -1540,8 +1355,6 @@
string signature;
MacMessage(message, &signature, 384);
VerifyMac(message, signature);
-
- EXPECT_EQ(0, GetParam()->keymaster0_calls());
}
TEST_P(VerificationOperationsTest, HmacSha512Success) {
@@ -1553,8 +1366,6 @@
string signature;
MacMessage(message, &signature, 512);
VerifyMac(message, signature);
-
- EXPECT_EQ(0, GetParam()->keymaster0_calls());
}
typedef Keymaster2Test ExportKeyTest;
@@ -1570,9 +1381,6 @@
EXPECT_GT(export_data.length(), 0U);
// TODO(swillden): Verify that the exported key is actually usable to verify signatures.
-
- if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA))
- EXPECT_EQ(2, GetParam()->keymaster0_calls());
}
TEST_P(ExportKeyTest, EcdsaSuccess) {
@@ -1583,9 +1391,6 @@
EXPECT_GT(export_data.length(), 0U);
// TODO(swillden): Verify that the exported key is actually usable to verify signatures.
-
- if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_EC))
- EXPECT_EQ(2, GetParam()->keymaster0_calls());
}
TEST_P(ExportKeyTest, RsaUnsupportedKeyFormat) {
@@ -1595,9 +1400,6 @@
.Padding(KM_PAD_NONE)));
string export_data;
ASSERT_EQ(KM_ERROR_UNSUPPORTED_KEY_FORMAT, ExportKey(KM_KEY_FORMAT_PKCS8, &export_data));
-
- if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA))
- EXPECT_EQ(2, GetParam()->keymaster0_calls());
}
TEST_P(ExportKeyTest, RsaCorruptedKeyBlob) {
@@ -1608,9 +1410,6 @@
corrupt_key_blob();
string export_data;
ASSERT_EQ(KM_ERROR_INVALID_KEY_BLOB, ExportKey(KM_KEY_FORMAT_X509, &export_data));
-
- if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA))
- EXPECT_EQ(2, GetParam()->keymaster0_calls());
}
TEST_P(ExportKeyTest, AesKeyExportFails) {
@@ -1620,22 +1419,13 @@
EXPECT_EQ(KM_ERROR_UNSUPPORTED_KEY_FORMAT, ExportKey(KM_KEY_FORMAT_X509, &export_data));
EXPECT_EQ(KM_ERROR_UNSUPPORTED_KEY_FORMAT, ExportKey(KM_KEY_FORMAT_PKCS8, &export_data));
EXPECT_EQ(KM_ERROR_UNSUPPORTED_KEY_FORMAT, ExportKey(KM_KEY_FORMAT_RAW, &export_data));
-
- EXPECT_EQ(0, GetParam()->keymaster0_calls());
-}
-
-static string read_file(const string& file_name) {
- ifstream file_stream(file_name, std::ios::binary);
- istreambuf_iterator<char> file_begin(file_stream);
- istreambuf_iterator<char> file_end;
- return string(file_begin, file_end);
}
typedef Keymaster2Test ImportKeyTest;
INSTANTIATE_TEST_CASE_P(AndroidKeymasterTest, ImportKeyTest, test_params);
TEST_P(ImportKeyTest, RsaSuccess) {
- string pk8_key = read_file("rsa_privkey_pk8.der");
+ string pk8_key(reinterpret_cast<char*>(&rsa_privkey_pk8_der[0]), rsa_privkey_pk8_der_len);
ASSERT_EQ(633U, pk8_key.size());
ASSERT_EQ(KM_ERROR_OK, ImportKey(AuthorizationSetBuilder()
@@ -1645,34 +1435,22 @@
KM_KEY_FORMAT_PKCS8, pk8_key));
// Check values derived from the key.
- 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_km0_hardware(KM_ALGORITHM_RSA) ? hw_enforced()
- : sw_enforced(),
- TAG_KEY_SIZE, 1024));
- EXPECT_TRUE(contains(GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA) ? hw_enforced()
- : sw_enforced(),
- TAG_RSA_PUBLIC_EXPONENT, 65537U));
+ EXPECT_TRUE(contains(sw_enforced(), TAG_ALGORITHM, KM_ALGORITHM_RSA));
+ EXPECT_TRUE(contains(sw_enforced(), TAG_KEY_SIZE, 1024));
+ EXPECT_TRUE(contains(sw_enforced(), TAG_RSA_PUBLIC_EXPONENT, 65537U));
// And values provided by AndroidKeymaster
- 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));
+ EXPECT_TRUE(contains(sw_enforced(), TAG_ORIGIN, KM_ORIGIN_IMPORTED));
EXPECT_TRUE(contains(sw_enforced(), KM_TAG_CREATION_DATETIME));
string message(1024 / 8, 'a');
string signature;
SignMessage(message, &signature, KM_DIGEST_NONE, KM_PAD_NONE);
VerifyMessage(message, signature, KM_DIGEST_NONE, KM_PAD_NONE);
-
- if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA))
- EXPECT_EQ(4, GetParam()->keymaster0_calls());
}
TEST_P(ImportKeyTest, RsaKeySizeMismatch) {
- string pk8_key = read_file("rsa_privkey_pk8.der");
+ string pk8_key(reinterpret_cast<char*>(&rsa_privkey_pk8_der[0]), rsa_privkey_pk8_der_len);
ASSERT_EQ(633U, pk8_key.size());
ASSERT_EQ(KM_ERROR_IMPORT_PARAMETER_MISMATCH,
ImportKey(AuthorizationSetBuilder()
@@ -1680,12 +1458,10 @@
.Digest(KM_DIGEST_NONE)
.Padding(KM_PAD_NONE),
KM_KEY_FORMAT_PKCS8, pk8_key));
-
- EXPECT_EQ(0, GetParam()->keymaster0_calls());
}
TEST_P(ImportKeyTest, RsaPublicExponenMismatch) {
- string pk8_key = read_file("rsa_privkey_pk8.der");
+ string pk8_key(reinterpret_cast<char*>(&rsa_privkey_pk8_der[0]), rsa_privkey_pk8_der_len);
ASSERT_EQ(633U, pk8_key.size());
ASSERT_EQ(KM_ERROR_IMPORT_PARAMETER_MISMATCH,
ImportKey(AuthorizationSetBuilder()
@@ -1693,12 +1469,10 @@
.Digest(KM_DIGEST_NONE)
.Padding(KM_PAD_NONE),
KM_KEY_FORMAT_PKCS8, pk8_key));
-
- EXPECT_EQ(0, GetParam()->keymaster0_calls());
}
TEST_P(ImportKeyTest, EcdsaSuccess) {
- string pk8_key = read_file("ec_privkey_pk8.der");
+ string pk8_key(reinterpret_cast<char*>(&ec_privkey_pk8_der[0]), ec_privkey_pk8_der_len);
ASSERT_EQ(138U, pk8_key.size());
ASSERT_EQ(KM_ERROR_OK,
@@ -1706,31 +1480,21 @@
KM_KEY_FORMAT_PKCS8, pk8_key));
// Check values derived from the key.
- 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));
+ EXPECT_TRUE(contains(sw_enforced(), TAG_ALGORITHM, KM_ALGORITHM_EC));
+ EXPECT_TRUE(contains(sw_enforced(), TAG_KEY_SIZE, 256));
// And values provided by AndroidKeymaster
- 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));
+ EXPECT_TRUE(contains(sw_enforced(), TAG_ORIGIN, KM_ORIGIN_IMPORTED));
EXPECT_TRUE(contains(sw_enforced(), KM_TAG_CREATION_DATETIME));
string message(32, 'a');
string signature;
SignMessage(message, &signature, KM_DIGEST_NONE);
VerifyMessage(message, signature, KM_DIGEST_NONE);
-
- if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_EC))
- EXPECT_EQ(4, GetParam()->keymaster0_calls());
}
TEST_P(ImportKeyTest, EcdsaSizeSpecified) {
- string pk8_key = read_file("ec_privkey_pk8.der");
+ string pk8_key(reinterpret_cast<char*>(&ec_privkey_pk8_der[0]), ec_privkey_pk8_der_len);
ASSERT_EQ(138U, pk8_key.size());
ASSERT_EQ(KM_ERROR_OK,
@@ -1738,39 +1502,27 @@
KM_KEY_FORMAT_PKCS8, pk8_key));
// Check values derived from the key.
- 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));
+ EXPECT_TRUE(contains(sw_enforced(), TAG_ALGORITHM, KM_ALGORITHM_EC));
+ EXPECT_TRUE(contains(sw_enforced(), TAG_KEY_SIZE, 256));
// And values provided by AndroidKeymaster
- 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));
+ EXPECT_TRUE(contains(sw_enforced(), TAG_ORIGIN, KM_ORIGIN_IMPORTED));
EXPECT_TRUE(contains(sw_enforced(), KM_TAG_CREATION_DATETIME));
string message(32, 'a');
string signature;
SignMessage(message, &signature, KM_DIGEST_NONE);
VerifyMessage(message, signature, KM_DIGEST_NONE);
-
- if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_EC))
- EXPECT_EQ(4, GetParam()->keymaster0_calls());
}
TEST_P(ImportKeyTest, EcdsaSizeMismatch) {
- string pk8_key = read_file("ec_privkey_pk8.der");
+ string pk8_key(reinterpret_cast<char*>(&ec_privkey_pk8_der[0]), ec_privkey_pk8_der_len);
ASSERT_EQ(138U, pk8_key.size());
ASSERT_EQ(KM_ERROR_IMPORT_PARAMETER_MISMATCH,
ImportKey(AuthorizationSetBuilder()
.EcdsaSigningKey(224 /* Doesn't match key */)
.Digest(KM_DIGEST_NONE),
KM_KEY_FORMAT_PKCS8, pk8_key));
-
- EXPECT_EQ(0, GetParam()->keymaster0_calls());
}
TEST_P(ImportKeyTest, AesKeySuccess) {
@@ -1788,8 +1540,6 @@
string ciphertext = EncryptMessage(message, KM_MODE_ECB, KM_PAD_PKCS7);
string plaintext = DecryptMessage(ciphertext, KM_MODE_ECB, KM_PAD_PKCS7);
EXPECT_EQ(message, plaintext);
-
- EXPECT_EQ(0, GetParam()->keymaster0_calls());
}
TEST_P(ImportKeyTest, HmacSha256KeySuccess) {
@@ -1808,31 +1558,31 @@
string signature;
MacMessage(message, &signature, 256);
VerifyMac(message, signature);
-
- EXPECT_EQ(0, GetParam()->keymaster0_calls());
}
-string wrapped_key = hex2str(
- "3082017302010004820100A2B7988012A043CE83E762A4E4D3C86D578B2E1EA5E04138353114A816951308E3222AFA"
- "D86CA141C581198E65BC56D9EEDC5B555713BE2C20948DD076AB4980305871317F89DD3A7A67FBBB7AACF6941C06B2"
- "65396D894A6DCC7B9FB152FFA8CBF44FF8063748795F3FB506DF8718535289E759075A13A5DDC83EF8470549AA7794"
- "3AFBACF6CF82DCE3751E05BFE05F30B998D73E23611E6EAEFC2A497E097A895C4242607B472AE8F19DA77A9A5A4786"
- "75541FC813C9213B5CE8C2E598BFBBCD1B369E3D7AEC0274F9B79118D8AA5FBB7634EBD3C4C2AF3B5DA483DF2CFDF1"
- "E68A3BFC7B6C0D503AF88E82C9EE841A278B144FF8D39F2DB2ACE9415C120190040CD796B02C370F1FA4CC0124F130"
- "280201033023A1083106020100020101A203020120A30402020100A4053103020101A60531030201400420CCD54085"
- "5F833A5E1480BFD2D36FAF3AEEE15DF5BEABE2691BC82DDE2A7AA91004107CB81BDDCD09E8F4DF575726279F3229");
+auto wrapped_key = hex2str(
+ "3082017902010004820100934bf94e2aa28a3f83c9f79297250262fbe3276b5a1c91159bbfa3ef8957aac84b59b30b"
+ "455a79c2973480823d8b3863c3deef4a8e243590268d80e18751a0e130f67ce6a1ace9f79b95e097474febc981195b"
+ "1d13a69086c0863f66a7b7fdb48792227b1ac5e2489febdf087ab5486483033a6f001ca5d1ec1e27f5c30f4cec2642"
+ "074a39ae68aee552e196627a8e3d867e67a8c01b11e75f13cca0a97ab668b50cda07a8ecb7cd8e3dd7009c9636534f"
+ "6f239cffe1fc8daa466f78b676c7119efb96bce4e69ca2a25d0b34ed9c3ff999b801597d5220e307eaa5bee507fb94"
+ "d1fa69f9e519b2de315bac92c36f2ea1fa1df4478c0ddedeae8c70e0233cd098040cd796b02c370f1fa4cc0124f130"
+ "2e0201033029a1083106020100020101a203020120a30402020100a4053103020101a6053103020140bf8377020500"
+ "0420ccd540855f833a5e1480bfd2d36faf3aeee15df5beabe2691bc82dde2a7aa910041064c9f689c60ff6223ab6e6"
+ "999e0eb6e5");
-string wrapped_key_masked = hex2str(
- "30820173020100048201008CBEE0DC600215FFC85FC26B57DD2331DDF5D3E106C0A68BFEF167AFD428041D9B7C3316"
- "110BBB914A86FC24D4EF5C6A4673C9B3CC914C7806453650753B5130C4FE72264A52C1A270286032513F24EB3E033A"
- "BCC26A9D6AEFD0D0AD3E922E4E737ECDAD3C4DF2ABDB416378E67381BE0391175EC8F05FDFBC3794B7D0D88298010F"
- "E9B6F788BC049D874575D2D4C33DB582B113694738A9151BBC7603D3556B26FEC0279EE1C1CA44D6F7F91F4C424912"
- "7F9CC3232DE8B0AEFFD5AFAD4C3D5B846FD26873315606F6457BC19447FD7C6431550D6E6592A0555E61C7A021D149"
- "BCEE7A858DD6D4A8E230C6015EEDF0A58F4CAA8A6D0E3A1E3794CAEE7854CE92040C6D9721D08589581AB49204A330"
- "280201033023A1083106020100020101A203020120A30402020100A4053103020101A60531030201400420A61C6E24"
- "7E25B3E6E69AA78EB03C2D4AC20D1F99A9A024A76F35C8E2CAB9B68D04101FF7A0E793B9EE4AECEBB9AC4C545254");
+auto wrapped_key_masked = hex2str(
+ "3082017902010004820100aad93ed5924f283b4bb5526fbe7a1412f9d9749ec30db9062b29e574a8546f33c8873245"
+ "2f5b8e6a391ee76c39ed1712c61d8df6213dec1cffbc17a8c6d04c7b30893d8daa9b2015213e21946821553207f8f9"
+ "931c4caba23ed3bee28b36947e47f10e0a5c3dc51c988a628daad3e5e1f4005e79c2d5a96c284b4b8d7e4948f331e5"
+ "b85dd5a236f85579f3ea1d1b848487470bdb0ab4f81a12bee42c99fe0df4bee3759453e69ad1d68a809ce06b949f76"
+ "94a990429b2fe81e066ff43e56a21602db70757922a4bcc23ab89f1e35da77586775f423e519c2ea394caf48a28d0c"
+ "8020f1dcf6b3a68ec246f615ae96dae9a079b1f6eb959033c1af5c125fd94168040c6d9721d08589581ab49204a330"
+ "2e0201033029a1083106020100020101a203020120a30402020100a4053103020101a6053103020140bf8377020500"
+ "0420a61c6e247e25b3e6e69aa78eb03c2d4ac20d1f99a9a024a76f35c8e2cab9b68d04102560c70109ae67c030f00b"
+ "98b512a670");
-string wrapping_key = hex2str(
+auto wrapping_key = hex2str(
"308204be020100300d06092a864886f70d0101010500048204a8308204a40201000282010100aec367931d8900ce56"
"b0067f7d70e1fc653f3f34d194c1fed50018fb43db937b06e673a837313d56b1c725150a3fef86acbddc41bb759c28"
"54eae32d35841efb5c18d82bc90a1cb5c1d55adf245b02911f0b7cda88c421ff0ebafe7c0d23be312d7bd5921ffaea"
@@ -1866,26 +1616,26 @@
class ImportWrappedKeyTest : public testing::Test {
public:
- ImportWrappedKeyTest() : keymaster_(new PureSoftKeymasterContext(), 16) {}
+ ImportWrappedKeyTest() : keymaster_(new PureSoftKeymasterContext(kCurrentKmVersion), 16) {}
protected:
void SetUp() override {
- ConfigureRequest configReq;
+ ConfigureRequest configReq(kMaxMessageVersion);
configReq.os_version = kOsVersion;
configReq.os_patchlevel = kOsPatchLevel;
- ConfigureResponse configRsp;
+ ConfigureResponse configRsp(kMaxMessageVersion);
keymaster_.Configure(configReq, &configRsp);
EXPECT_EQ(KM_ERROR_OK, configRsp.error);
}
keymaster_error_t BeginOperation(keymaster_purpose_t purpose,
const AuthorizationSet& input_set) {
- BeginOperationRequest req;
+ BeginOperationRequest req(kMaxMessageVersion);
req.purpose = purpose;
req.SetKeyMaterial(blob_);
req.additional_params = input_set;
- BeginOperationResponse rsp;
+ BeginOperationResponse rsp(kMaxMessageVersion);
keymaster_.BeginOperation(req, &rsp);
op_handle_ = rsp.op_handle;
@@ -1893,11 +1643,11 @@
}
keymaster_error_t FinishOperation(const string& input, string* output) {
- FinishOperationRequest req;
+ FinishOperationRequest req(kMaxMessageVersion);
req.op_handle = op_handle_;
req.input.Reinitialize(input.data(), input.size());
- FinishOperationResponse rsp;
+ FinishOperationResponse rsp(kMaxMessageVersion);
keymaster_.FinishOperation(req, &rsp);
if (output) {
@@ -1923,29 +1673,29 @@
};
TEST_F(ImportWrappedKeyTest, GoldenKeySuccess) {
- ImportKeyRequest import_request;
+ ImportKeyRequest import_request(kMaxMessageVersion);
auto import_params = AuthorizationSetBuilder()
.RsaEncryptionKey(2048, 65537)
- .Digest(KM_DIGEST_SHA1)
+ .Digest(KM_DIGEST_SHA_2_256)
.Padding(KM_PAD_RSA_OAEP)
.Authorization(TAG_PURPOSE, KM_PURPOSE_WRAP)
.build();
import_request.key_description.Reinitialize(import_params);
- import_request.SetKeyMaterial(reinterpret_cast<const uint8_t*>(wrapping_key.c_str()),
- wrapping_key.size());
+ import_request.key_data = KeymasterKeyBlob(
+ reinterpret_cast<const uint8_t*>(wrapping_key.c_str()), wrapping_key.size());
import_request.key_format = KM_KEY_FORMAT_PKCS8;
- ImportKeyResponse import_response;
+ ImportKeyResponse import_response(kMaxMessageVersion);
keymaster_.ImportKey(import_request, &import_response);
ASSERT_EQ(import_response.error, KM_ERROR_OK);
- ImportWrappedKeyRequest request;
+ ImportWrappedKeyRequest request(kMaxMessageVersion);
KeymasterKeyBlob wrapped_key_blob(reinterpret_cast<const uint8_t*>(wrapped_key.c_str()),
wrapped_key.size());
request.SetKeyMaterial(wrapped_key_blob, import_response.key_blob);
request.SetMaskingKeyMaterial(reinterpret_cast<const uint8_t*>(zero_masking_key.c_str()),
zero_masking_key.size());
- ImportWrappedKeyResponse response;
+ ImportWrappedKeyResponse response(kMaxMessageVersion);
keymaster_.ImportWrappedKey(request, &response);
@@ -1968,71 +1718,71 @@
}
TEST_F(ImportWrappedKeyTest, SuccessMaskingKey) {
- ImportKeyRequest import_request;
+ ImportKeyRequest import_request(kMaxMessageVersion);
auto import_params = AuthorizationSetBuilder()
.RsaEncryptionKey(2048, 65537)
- .Digest(KM_DIGEST_SHA1)
+ .Digest(KM_DIGEST_SHA_2_256)
.Padding(KM_PAD_RSA_OAEP)
.Authorization(TAG_PURPOSE, KM_PURPOSE_WRAP)
.build();
import_request.key_description.Reinitialize(import_params);
- import_request.SetKeyMaterial(reinterpret_cast<const uint8_t*>(wrapping_key.c_str()),
- wrapping_key.size());
+ import_request.key_data = KeymasterKeyBlob(
+ reinterpret_cast<const uint8_t*>(wrapping_key.c_str()), wrapping_key.size());
import_request.key_format = KM_KEY_FORMAT_PKCS8;
- ImportKeyResponse import_response;
+ ImportKeyResponse import_response(kMaxMessageVersion);
keymaster_.ImportKey(import_request, &import_response);
EXPECT_EQ(import_response.error, KM_ERROR_OK);
if (import_response.error != KM_ERROR_OK) return;
- ImportWrappedKeyRequest request;
+ ImportWrappedKeyRequest request(kMaxMessageVersion);
KeymasterKeyBlob wrapped_key_blob(reinterpret_cast<const uint8_t*>(wrapped_key_masked.c_str()),
wrapped_key_masked.size());
request.SetKeyMaterial(wrapped_key_blob, import_response.key_blob);
request.SetMaskingKeyMaterial(reinterpret_cast<const uint8_t*>(masking_key.c_str()),
masking_key.size());
- ImportWrappedKeyResponse response;
+ ImportWrappedKeyResponse response(kMaxMessageVersion);
keymaster_.ImportWrappedKey(request, &response);
EXPECT_EQ(response.error, KM_ERROR_OK);
}
TEST_F(ImportWrappedKeyTest, WrongMaskingKey) {
- ImportKeyRequest import_request;
+ ImportKeyRequest import_request(kMaxMessageVersion);
auto import_params = AuthorizationSetBuilder()
.RsaEncryptionKey(2048, 65537)
- .Digest(KM_DIGEST_SHA1)
+ .Digest(KM_DIGEST_SHA_2_256)
.Padding(KM_PAD_RSA_OAEP)
.Authorization(TAG_PURPOSE, KM_PURPOSE_WRAP)
.build();
import_request.key_description.Reinitialize(import_params);
- import_request.SetKeyMaterial(reinterpret_cast<const uint8_t*>(wrapping_key.c_str()),
- wrapping_key.size());
+ import_request.key_data = KeymasterKeyBlob(
+ reinterpret_cast<const uint8_t*>(wrapping_key.c_str()), wrapping_key.size());
import_request.key_format = KM_KEY_FORMAT_PKCS8;
- ImportKeyResponse import_response;
+ ImportKeyResponse import_response(kMaxMessageVersion);
keymaster_.ImportKey(import_request, &import_response);
EXPECT_EQ(import_response.error, KM_ERROR_OK);
if (import_response.error != KM_ERROR_OK) return;
- ImportWrappedKeyRequest request;
+ ImportWrappedKeyRequest request(kMaxMessageVersion);
KeymasterKeyBlob wrapped_key_blob(reinterpret_cast<const uint8_t*>(wrapped_key_masked.c_str()),
wrapped_key_masked.size());
request.SetKeyMaterial(wrapped_key_blob, import_response.key_blob);
request.SetMaskingKeyMaterial(reinterpret_cast<const uint8_t*>(zero_masking_key.c_str()),
zero_masking_key.size());
- ImportWrappedKeyResponse response;
+ ImportWrappedKeyResponse response(kMaxMessageVersion);
keymaster_.ImportWrappedKey(request, &response);
EXPECT_EQ(response.error, KM_ERROR_VERIFICATION_FAILED);
}
TEST_F(ImportWrappedKeyTest, WrongPurpose) {
- ImportKeyRequest import_request;
+ ImportKeyRequest import_request(kMaxMessageVersion);
auto import_params = AuthorizationSetBuilder()
.RsaEncryptionKey(2048, 65537)
@@ -2040,20 +1790,20 @@
.Padding(KM_PAD_RSA_OAEP)
.build();
import_request.key_description.Reinitialize(import_params);
- import_request.SetKeyMaterial(reinterpret_cast<const uint8_t*>(wrapping_key.c_str()),
- wrapping_key.size());
+ import_request.key_data = KeymasterKeyBlob(
+ reinterpret_cast<const uint8_t*>(wrapping_key.c_str()), wrapping_key.size());
import_request.key_format = KM_KEY_FORMAT_PKCS8;
- ImportKeyResponse import_response;
+ ImportKeyResponse import_response(kMaxMessageVersion);
keymaster_.ImportKey(import_request, &import_response);
EXPECT_EQ(import_response.error, KM_ERROR_OK);
if (import_response.error != KM_ERROR_OK) return;
- ImportWrappedKeyRequest request;
+ ImportWrappedKeyRequest request(kMaxMessageVersion);
KeymasterKeyBlob wrapped_key_blob(reinterpret_cast<const uint8_t*>(wrapped_key.c_str()),
wrapped_key.size());
request.SetKeyMaterial(wrapped_key_blob, import_response.key_blob);
- ImportWrappedKeyResponse response;
+ ImportWrappedKeyResponse response(kMaxMessageVersion);
keymaster_.ImportWrappedKey(request, &response);
EXPECT_EQ(response.error, KM_ERROR_INCOMPATIBLE_PURPOSE);
@@ -2075,9 +1825,6 @@
// Unpadded RSA is deterministic
EXPECT_EQ(ciphertext1, ciphertext2);
-
- if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA))
- EXPECT_EQ(3, GetParam()->keymaster0_calls());
}
TEST_P(EncryptionOperationsTest, RsaNoPaddingTooShort) {
@@ -2093,9 +1840,6 @@
string plaintext = DecryptMessage(ciphertext, KM_PAD_NONE);
EXPECT_EQ(expected_plaintext, plaintext);
-
- if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA))
- EXPECT_EQ(4, GetParam()->keymaster0_calls());
}
TEST_P(EncryptionOperationsTest, RsaNoPaddingTooLong) {
@@ -2111,9 +1855,6 @@
string result;
size_t input_consumed;
EXPECT_EQ(KM_ERROR_INVALID_INPUT_LENGTH, UpdateOperation(message, &result, &input_consumed));
-
- if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA))
- EXPECT_EQ(2, GetParam()->keymaster0_calls());
}
TEST_P(EncryptionOperationsTest, RsaNoPaddingLargerThanModulus) {
@@ -2153,9 +1894,6 @@
message = string(reinterpret_cast<const char*>(modulus_buf.get()), modulus_len);
EXPECT_EQ(KM_ERROR_OK, BeginOperation(KM_PURPOSE_ENCRYPT, begin_params));
EXPECT_EQ(KM_ERROR_OK, FinishOperation(message, "", &result));
-
- if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA))
- EXPECT_EQ(4, GetParam()->keymaster0_calls());
}
TEST_P(EncryptionOperationsTest, RsaOaepSuccess) {
@@ -2174,9 +1912,48 @@
// 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());
+TEST_P(EncryptionOperationsTest, RsaOaepWithMgf224Success) {
+ 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_256)
+ .OaepMgfDigest(KM_DIGEST_SHA_2_224)));
+
+ string message = "Hello";
+ string ciphertext1 =
+ EncryptMessage(string(message), KM_DIGEST_SHA_2_256, 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_256, 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);
+}
+
+TEST_P(EncryptionOperationsTest, RsaOaepWithMgfMD5Success) {
+ 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_256)
+ .OaepMgfDigest(KM_DIGEST_MD5)));
+
+ string message = "Hello";
+ string ciphertext1 =
+ EncryptMessage(string(message), KM_DIGEST_SHA_2_256, KM_DIGEST_MD5, KM_PAD_RSA_OAEP);
+ EXPECT_EQ(key_size / 8, ciphertext1.size());
+
+ string ciphertext2 =
+ EncryptMessage(string(message), KM_DIGEST_SHA_2_256, KM_DIGEST_MD5, KM_PAD_RSA_OAEP);
+ EXPECT_EQ(key_size / 8, ciphertext2.size());
+
+ // OAEP randomizes padding so every result should be different.
+ EXPECT_NE(ciphertext1, ciphertext2);
}
TEST_P(EncryptionOperationsTest, RsaOaepSha224Success) {
@@ -2195,9 +1972,6 @@
// 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());
}
TEST_P(EncryptionOperationsTest, RsaOaepRoundTrip) {
@@ -2212,9 +1986,23 @@
string plaintext = DecryptMessage(ciphertext, KM_DIGEST_SHA_2_256, KM_PAD_RSA_OAEP);
EXPECT_EQ(message, plaintext);
+}
- if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA))
- EXPECT_EQ(4, GetParam()->keymaster0_calls());
+TEST_P(EncryptionOperationsTest, RsaOaepWithMgfSha256RoundTrip) {
+ 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_256)
+ .OaepMgfDigest(KM_DIGEST_SHA_2_256)));
+ string message = "Hello World!";
+ string ciphertext =
+ EncryptMessage(string(message), KM_DIGEST_SHA_2_256, KM_DIGEST_SHA_2_256, KM_PAD_RSA_OAEP);
+ EXPECT_EQ(key_size / 8, ciphertext.size());
+
+ string plaintext =
+ DecryptMessage(ciphertext, KM_DIGEST_SHA_2_256, KM_DIGEST_SHA_2_256, KM_PAD_RSA_OAEP);
+ EXPECT_EQ(message, plaintext);
}
TEST_P(EncryptionOperationsTest, RsaOaepSha224RoundTrip) {
@@ -2229,9 +2017,6 @@
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());
}
TEST_P(EncryptionOperationsTest, RsaOaepInvalidDigest) {
@@ -2245,9 +2030,21 @@
begin_params.push_back(TAG_PADDING, KM_PAD_RSA_OAEP);
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_km0_hardware(KM_ALGORITHM_RSA))
- EXPECT_EQ(2, GetParam()->keymaster0_calls());
+TEST_P(EncryptionOperationsTest, RsaOaepWithMgfInvalidDigest) {
+ ASSERT_EQ(KM_ERROR_OK, GenerateKey(AuthorizationSetBuilder()
+ .RsaEncryptionKey(512, 3)
+ .Padding(KM_PAD_RSA_OAEP)
+ .Digest(KM_DIGEST_SHA_2_256)
+ .OaepMgfDigest(KM_DIGEST_SHA_2_256)));
+ string message = "Hello World!";
+
+ AuthorizationSet begin_params(client_params());
+ begin_params.push_back(TAG_PADDING, KM_PAD_RSA_OAEP);
+ begin_params.push_back(TAG_DIGEST, KM_DIGEST_SHA_2_256);
+ begin_params.push_back(TAG_RSA_OAEP_MGF_DIGEST, KM_DIGEST_SHA_2_224);
+ EXPECT_EQ(KM_ERROR_INCOMPATIBLE_MGF_DIGEST, BeginOperation(KM_PURPOSE_ENCRYPT, begin_params));
}
TEST_P(EncryptionOperationsTest, RsaOaepUnauthorizedDigest) {
@@ -2267,9 +2064,6 @@
begin_params.push_back(TAG_PADDING, KM_PAD_RSA_OAEP);
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_km0_hardware(KM_ALGORITHM_RSA))
- EXPECT_EQ(3, GetParam()->keymaster0_calls());
}
TEST_P(EncryptionOperationsTest, RsaOaepDecryptWithWrongDigest) {
@@ -2295,9 +2089,6 @@
EXPECT_EQ(KM_ERROR_OK, UpdateOperation(ciphertext, &result, &input_consumed));
EXPECT_EQ(KM_ERROR_UNKNOWN_ERROR, FinishOperation(&result));
EXPECT_EQ(0U, result.size());
-
- if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA))
- EXPECT_EQ(4, GetParam()->keymaster0_calls());
}
TEST_P(EncryptionOperationsTest, RsaOaepTooLarge) {
@@ -2316,9 +2107,6 @@
EXPECT_EQ(KM_ERROR_OK, UpdateOperation(message, &result, &input_consumed));
EXPECT_EQ(KM_ERROR_INVALID_INPUT_LENGTH, FinishOperation(&result));
EXPECT_EQ(0U, result.size());
-
- if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA))
- EXPECT_EQ(2, GetParam()->keymaster0_calls());
}
TEST_P(EncryptionOperationsTest, RsaOaepCorruptedDecrypt) {
@@ -2343,9 +2131,6 @@
EXPECT_EQ(KM_ERROR_OK, UpdateOperation(ciphertext, &result, &input_consumed));
EXPECT_EQ(KM_ERROR_UNKNOWN_ERROR, FinishOperation(&result));
EXPECT_EQ(0U, result.size());
-
- if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA))
- EXPECT_EQ(4, GetParam()->keymaster0_calls());
}
TEST_P(EncryptionOperationsTest, RsaPkcs1Success) {
@@ -2360,9 +2145,6 @@
// PKCS1 v1.5 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());
}
TEST_P(EncryptionOperationsTest, RsaPkcs1RoundTrip) {
@@ -2374,9 +2156,6 @@
string plaintext = DecryptMessage(ciphertext, KM_PAD_RSA_PKCS1_1_5_ENCRYPT);
EXPECT_EQ(message, plaintext);
-
- if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA))
- EXPECT_EQ(4, GetParam()->keymaster0_calls());
}
TEST_P(EncryptionOperationsTest, RsaRoundTripAllCombinations) {
@@ -2413,9 +2192,6 @@
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) {
@@ -2431,9 +2207,6 @@
EXPECT_EQ(KM_ERROR_OK, UpdateOperation(message, &result, &input_consumed));
EXPECT_EQ(KM_ERROR_INVALID_INPUT_LENGTH, FinishOperation(&result));
EXPECT_EQ(0U, result.size());
-
- if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA))
- EXPECT_EQ(2, GetParam()->keymaster0_calls());
}
TEST_P(EncryptionOperationsTest, RsaPkcs1CorruptedDecrypt) {
@@ -2454,9 +2227,6 @@
EXPECT_EQ(KM_ERROR_OK, UpdateOperation(ciphertext, &result, &input_consumed));
EXPECT_EQ(KM_ERROR_UNKNOWN_ERROR, FinishOperation(&result));
EXPECT_EQ(0U, result.size());
-
- if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA))
- EXPECT_EQ(4, GetParam()->keymaster0_calls());
}
TEST_P(EncryptionOperationsTest, RsaEncryptWithSigningKey) {
@@ -2466,9 +2236,6 @@
AuthorizationSet begin_params(client_params());
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_km0_hardware(KM_ALGORITHM_RSA))
- EXPECT_EQ(2, GetParam()->keymaster0_calls());
}
TEST_P(EncryptionOperationsTest, EcdsaEncrypt) {
@@ -2476,9 +2243,6 @@
GenerateKey(AuthorizationSetBuilder().EcdsaSigningKey(224).Digest(KM_DIGEST_NONE)));
ASSERT_EQ(KM_ERROR_UNSUPPORTED_PURPOSE, BeginOperation(KM_PURPOSE_ENCRYPT));
ASSERT_EQ(KM_ERROR_UNSUPPORTED_PURPOSE, BeginOperation(KM_PURPOSE_DECRYPT));
-
- if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_EC))
- EXPECT_EQ(3, GetParam()->keymaster0_calls());
}
TEST_P(EncryptionOperationsTest, HmacEncrypt) {
@@ -2489,8 +2253,6 @@
.Authorization(TAG_MIN_MAC_LENGTH, 128)));
ASSERT_EQ(KM_ERROR_UNSUPPORTED_PURPOSE, BeginOperation(KM_PURPOSE_ENCRYPT));
ASSERT_EQ(KM_ERROR_UNSUPPORTED_PURPOSE, BeginOperation(KM_PURPOSE_DECRYPT));
-
- EXPECT_EQ(0, GetParam()->keymaster0_calls());
}
TEST_P(EncryptionOperationsTest, AesEcbRoundTripSuccess) {
@@ -2511,8 +2273,6 @@
string plaintext = DecryptMessage(ciphertext1, KM_MODE_ECB, KM_PAD_NONE);
EXPECT_EQ(message, plaintext);
-
- EXPECT_EQ(0, GetParam()->keymaster0_calls());
}
TEST_P(EncryptionOperationsTest, AesEcbNotAuthorized) {
@@ -2526,8 +2286,6 @@
begin_params.push_back(TAG_BLOCK_MODE, KM_MODE_ECB);
begin_params.push_back(TAG_PADDING, KM_PAD_NONE);
EXPECT_EQ(KM_ERROR_INCOMPATIBLE_BLOCK_MODE, BeginOperation(KM_PURPOSE_ENCRYPT, begin_params));
-
- EXPECT_EQ(0, GetParam()->keymaster0_calls());
}
TEST_P(EncryptionOperationsTest, AesEcbNoPaddingWrongInputSize) {
@@ -2544,8 +2302,6 @@
EXPECT_EQ(KM_ERROR_OK, BeginOperation(KM_PURPOSE_ENCRYPT, begin_params));
string ciphertext;
EXPECT_EQ(KM_ERROR_INVALID_INPUT_LENGTH, FinishOperation(message, "", &ciphertext));
-
- EXPECT_EQ(0, GetParam()->keymaster0_calls());
}
TEST_P(EncryptionOperationsTest, AesEcbPkcs7Padding) {
@@ -2562,8 +2318,6 @@
string plaintext = DecryptMessage(ciphertext, KM_MODE_ECB, KM_PAD_PKCS7);
EXPECT_EQ(message, plaintext);
}
-
- EXPECT_EQ(0, GetParam()->keymaster0_calls());
}
TEST_P(EncryptionOperationsTest, AesEcbNoPaddingKeyWithPkcs7Padding) {
@@ -2580,8 +2334,6 @@
EXPECT_EQ(KM_ERROR_INCOMPATIBLE_PADDING_MODE,
BeginOperation(KM_PURPOSE_ENCRYPT, begin_params));
}
-
- EXPECT_EQ(0, GetParam()->keymaster0_calls());
}
TEST_P(EncryptionOperationsTest, AesEcbPkcs7PaddingCorrupted) {
@@ -2605,8 +2357,6 @@
EXPECT_EQ(KM_ERROR_OK, UpdateOperation(ciphertext, &plaintext, &input_consumed));
EXPECT_EQ(ciphertext.size(), input_consumed);
EXPECT_EQ(KM_ERROR_INVALID_ARGUMENT, FinishOperation(&plaintext));
-
- EXPECT_EQ(0, GetParam()->keymaster0_calls());
}
TEST_P(EncryptionOperationsTest, AesCtrRoundTripSuccess) {
@@ -2631,8 +2381,6 @@
string plaintext = DecryptMessage(ciphertext1, KM_MODE_CTR, KM_PAD_NONE, iv1);
EXPECT_EQ(message, plaintext);
-
- EXPECT_EQ(0, GetParam()->keymaster0_calls());
}
TEST_P(EncryptionOperationsTest, AesCtrIncremental) {
@@ -2672,8 +2420,6 @@
EXPECT_EQ(KM_ERROR_OK, FinishOperation(&plaintext));
EXPECT_EQ(ciphertext.size(), plaintext.size());
EXPECT_EQ(message, plaintext);
-
- EXPECT_EQ(0, GetParam()->keymaster0_calls());
}
struct AesCtrSp80038aTestVector {
@@ -2688,7 +2434,8 @@
static const AesCtrSp80038aTestVector kAesCtrSp80038aTestVectors[] = {
// AES-128
{
- "2b7e151628aed2a6abf7158809cf4f3c", "f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff",
+ "2b7e151628aed2a6abf7158809cf4f3c",
+ "f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff",
"6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e51"
"30c81c46a35ce411e5fbc1191a0a52eff69f2445df4f9b17ad2b417be66c3710",
"874d6191b620e3261bef6864990db6ce9806f66b7970fdff8617187bb9fffdff"
@@ -2696,7 +2443,8 @@
},
// AES-192
{
- "8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b", "f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff",
+ "8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b",
+ "f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff",
"6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e51"
"30c81c46a35ce411e5fbc1191a0a52eff69f2445df4f9b17ad2b417be66c3710",
"1abc932417521ca24f2b0459fe7e6e0b090339ec0aa6faefd5ccc2c6f4ce8e94"
@@ -2722,8 +2470,6 @@
const string ciphertext = hex2str(test.ciphertext);
CheckAesCtrTestVector(key, nonce, plaintext, ciphertext);
}
-
- EXPECT_EQ(0, GetParam()->keymaster0_calls());
}
TEST_P(EncryptionOperationsTest, AesCtrInvalidPaddingMode) {
@@ -2735,8 +2481,6 @@
begin_params.push_back(TAG_BLOCK_MODE, KM_MODE_CTR);
begin_params.push_back(TAG_PADDING, KM_PAD_NONE);
EXPECT_EQ(KM_ERROR_INCOMPATIBLE_PADDING_MODE, BeginOperation(KM_PURPOSE_ENCRYPT, begin_params));
-
- EXPECT_EQ(0, GetParam()->keymaster0_calls());
}
TEST_P(EncryptionOperationsTest, AesCtrInvalidCallerNonce) {
@@ -2751,8 +2495,6 @@
input_params.push_back(TAG_PADDING, KM_PAD_NONE);
input_params.push_back(TAG_NONCE, "123", 3);
EXPECT_EQ(KM_ERROR_INVALID_NONCE, BeginOperation(KM_PURPOSE_ENCRYPT, input_params));
-
- EXPECT_EQ(0, GetParam()->keymaster0_calls());
}
TEST_P(EncryptionOperationsTest, AesCbcRoundTripSuccess) {
@@ -2776,8 +2518,6 @@
string plaintext = DecryptMessage(ciphertext1, KM_MODE_CBC, KM_PAD_NONE, iv1);
EXPECT_EQ(message, plaintext);
-
- EXPECT_EQ(0, GetParam()->keymaster0_calls());
}
TEST_P(EncryptionOperationsTest, AesCallerNonce) {
@@ -2819,8 +2559,6 @@
plaintext = ProcessMessage(KM_PURPOSE_DECRYPT, ciphertext2, input_params, update_params,
&output_params);
EXPECT_NE(message, plaintext);
-
- EXPECT_EQ(0, GetParam()->keymaster0_calls());
}
TEST_P(EncryptionOperationsTest, AesCallerNonceProhibited) {
@@ -2849,8 +2587,6 @@
EXPECT_EQ(KM_ERROR_CALLER_NONCE_PROHIBITED,
BeginOperation(KM_PURPOSE_ENCRYPT, input_params, &output_params));
-
- EXPECT_EQ(0, GetParam()->keymaster0_calls());
}
TEST_P(EncryptionOperationsTest, AesCbcIncrementalNoPadding) {
@@ -2890,8 +2626,6 @@
EXPECT_EQ(KM_ERROR_OK, FinishOperation(&plaintext));
EXPECT_EQ(ciphertext.size(), plaintext.size());
EXPECT_EQ(message, plaintext);
-
- EXPECT_EQ(0, GetParam()->keymaster0_calls());
}
TEST_P(EncryptionOperationsTest, AesCbcPkcs7Padding) {
@@ -2909,8 +2643,6 @@
string plaintext = DecryptMessage(ciphertext, KM_MODE_CBC, KM_PAD_PKCS7, iv);
EXPECT_EQ(message, plaintext);
}
-
- EXPECT_EQ(0, GetParam()->keymaster0_calls());
}
TEST_P(EncryptionOperationsTest, AesGcmRoundTripSuccess) {
@@ -2953,7 +2685,6 @@
EXPECT_EQ(KM_ERROR_OK, FinishOperation(&plaintext));
EXPECT_EQ(message, plaintext);
- EXPECT_EQ(0, GetParam()->keymaster0_calls());
}
TEST_P(EncryptionOperationsTest, AesGcmTooShortTag) {
@@ -2975,8 +2706,6 @@
AuthorizationSet begin_out_params;
EXPECT_EQ(KM_ERROR_INVALID_MAC_LENGTH,
BeginOperation(KM_PURPOSE_ENCRYPT, begin_params, &begin_out_params));
-
- EXPECT_EQ(0, GetParam()->keymaster0_calls());
}
TEST_P(EncryptionOperationsTest, AesGcmTooShortTagOnDecrypt) {
@@ -3016,8 +2745,6 @@
// Decrypt.
EXPECT_EQ(KM_ERROR_INVALID_MAC_LENGTH, BeginOperation(KM_PURPOSE_DECRYPT, begin_params));
-
- EXPECT_EQ(0, GetParam()->keymaster0_calls());
}
TEST_P(EncryptionOperationsTest, AesGcmCorruptKey) {
@@ -3074,8 +2801,6 @@
EXPECT_EQ(KM_ERROR_OK, BeginOperation(KM_PURPOSE_DECRYPT, begin_params));
EXPECT_EQ(KM_ERROR_OK, UpdateOperation(ciphertext_str, &plaintext, &input_consumed));
EXPECT_EQ(KM_ERROR_VERIFICATION_FAILED, FinishOperation(&plaintext));
-
- EXPECT_EQ(0, GetParam()->keymaster0_calls());
}
TEST_P(EncryptionOperationsTest, AesGcmAadNoData) {
@@ -3118,7 +2843,6 @@
EXPECT_EQ(KM_ERROR_OK, FinishOperation(&plaintext));
EXPECT_EQ(empty_message, plaintext);
- EXPECT_EQ(0, GetParam()->keymaster0_calls());
}
TEST_P(EncryptionOperationsTest, AesGcmIncremental) {
@@ -3187,8 +2911,6 @@
}
EXPECT_EQ(1000U, plaintext.size());
EXPECT_EQ(KM_ERROR_OK, FinishOperation(&plaintext));
-
- EXPECT_EQ(0, GetParam()->keymaster0_calls());
}
TEST_P(EncryptionOperationsTest, AesGcmMultiPartAad) {
@@ -3239,7 +2961,6 @@
EXPECT_EQ(KM_ERROR_OK, FinishOperation(&plaintext));
EXPECT_EQ(message, plaintext);
- EXPECT_EQ(0, GetParam()->keymaster0_calls());
}
TEST_P(EncryptionOperationsTest, AesGcmBadAad) {
@@ -3285,8 +3006,6 @@
&plaintext, &input_consumed));
EXPECT_EQ(ciphertext.size(), input_consumed);
EXPECT_EQ(KM_ERROR_VERIFICATION_FAILED, FinishOperation(&plaintext));
-
- EXPECT_EQ(0, GetParam()->keymaster0_calls());
}
TEST_P(EncryptionOperationsTest, AesGcmWrongNonce) {
@@ -3327,7 +3046,6 @@
// With wrong nonce, should have gotten garbage plaintext.
EXPECT_NE(message, plaintext);
- EXPECT_EQ(0, GetParam()->keymaster0_calls());
}
TEST_P(EncryptionOperationsTest, AesGcmCorruptTag) {
@@ -3373,7 +3091,6 @@
EXPECT_EQ(KM_ERROR_VERIFICATION_FAILED, FinishOperation(&plaintext));
EXPECT_EQ(message, plaintext);
- EXPECT_EQ(0, GetParam()->keymaster0_calls());
}
TEST_P(EncryptionOperationsTest, TripleDesEcbRoundTripSuccess) {
@@ -3668,8 +3385,6 @@
string plaintext = DecryptMessage(ciphertext1, KM_MODE_CBC, KM_PAD_NONE, iv1);
EXPECT_EQ(message, plaintext);
-
- EXPECT_EQ(0, GetParam()->keymaster0_calls());
}
TEST_P(EncryptionOperationsTest, TripleDesCallerIv) {
@@ -3866,8 +3581,6 @@
EXPECT_EQ(KM_ERROR_OK, FinishOperation(&plaintext));
EXPECT_EQ(ciphertext.size(), plaintext.size());
EXPECT_EQ(message, plaintext);
-
- EXPECT_EQ(0, GetParam()->keymaster0_calls());
}
typedef Keymaster2Test MaxOperationsTest;
@@ -3890,8 +3603,6 @@
begin_params.push_back(TAG_BLOCK_MODE, KM_MODE_ECB);
begin_params.push_back(TAG_PADDING, KM_PAD_NONE);
EXPECT_EQ(KM_ERROR_KEY_MAX_OPS_EXCEEDED, BeginOperation(KM_PURPOSE_ENCRYPT, begin_params));
-
- EXPECT_EQ(0, GetParam()->keymaster0_calls());
}
TEST_P(MaxOperationsTest, TestAbort) {
@@ -3911,8 +3622,6 @@
begin_params.push_back(TAG_BLOCK_MODE, KM_MODE_ECB);
begin_params.push_back(TAG_PADDING, KM_PAD_NONE);
EXPECT_EQ(KM_ERROR_KEY_MAX_OPS_EXCEEDED, BeginOperation(KM_PURPOSE_ENCRYPT, begin_params));
-
- EXPECT_EQ(0, GetParam()->keymaster0_calls());
}
typedef Keymaster2Test AddEntropyTest;
@@ -3923,8 +3632,6 @@
// doesn't blow up or return an error.
EXPECT_EQ(KM_ERROR_OK,
device()->add_rng_entropy(device(), reinterpret_cast<const uint8_t*>("foo"), 3));
-
- EXPECT_EQ(0, GetParam()->keymaster0_calls());
}
typedef Keymaster2Test AttestationTest;
@@ -3943,13 +3650,11 @@
X509_Ptr key_cert(parse_cert_blob(key_cert_blob));
X509_Ptr signing_cert(parse_cert_blob(signing_cert_blob));
EXPECT_TRUE(!!key_cert.get() && !!signing_cert.get());
- if (!key_cert.get() || !signing_cert.get())
- return false;
+ if (!key_cert.get() || !signing_cert.get()) return false;
EVP_PKEY_Ptr signing_pubkey(X509_get_pubkey(signing_cert.get()));
EXPECT_TRUE(!!signing_pubkey.get());
- if (!signing_pubkey.get())
- return false;
+ if (!signing_pubkey.get()) return false;
EXPECT_EQ(1, X509_verify(key_cert.get(), signing_pubkey.get()))
<< "Verification of certificate " << i << " failed";
@@ -3960,21 +3665,18 @@
// Extract attestation record from cert. Returned object is still part of cert; don't free it
// separately.
-static ASN1_OCTET_STRING* get_attestation_record(X509* certificate) {
- ASN1_OBJECT_Ptr oid(OBJ_txt2obj(kAttestionRecordOid, 1 /* dotted string format */));
+static ASN1_OCTET_STRING* get_attestation_record(X509* certificate, const char* oid_string) {
+ ASN1_OBJECT_Ptr oid(OBJ_txt2obj(oid_string, 1 /* dotted string format */));
EXPECT_TRUE(!!oid.get());
- if (!oid.get())
- return nullptr;
+ if (!oid.get()) return nullptr;
int location = X509_get_ext_by_OBJ(certificate, oid.get(), -1 /* search from beginning */);
EXPECT_NE(-1, location);
- if (location == -1)
- return nullptr;
+ if (location == -1) return nullptr;
X509_EXTENSION* attest_rec_ext = X509_get_ext(certificate, location);
EXPECT_TRUE(!!attest_rec_ext);
- if (!attest_rec_ext)
- return nullptr;
+ if (!attest_rec_ext) return nullptr;
ASN1_OCTET_STRING* attest_rec = X509_EXTENSION_get_data(attest_rec_ext);
EXPECT_TRUE(!!attest_rec);
@@ -3990,13 +3692,15 @@
X509_Ptr cert(parse_cert_blob(attestation_cert));
EXPECT_TRUE(!!cert.get());
- if (!cert.get())
- return false;
+ if (!cert.get()) return false;
- ASN1_OCTET_STRING* attest_rec = get_attestation_record(cert.get());
+ const char* oid =
+ expected_keymaster_version >= (uint32_t)KmVersion::KEYMINT_1 ? kEatTokenOid : kAsn1TokenOid;
+ uint32_t expected_attestation_version =
+ expected_keymaster_version >= (uint32_t)KmVersion::KEYMINT_1 ? 5u : 4u;
+ ASN1_OCTET_STRING* attest_rec = get_attestation_record(cert.get(), oid);
EXPECT_TRUE(!!attest_rec);
- if (!attest_rec)
- return false;
+ if (!attest_rec) return false;
AuthorizationSet att_sw_enforced;
AuthorizationSet att_tee_enforced;
@@ -4006,13 +3710,27 @@
keymaster_security_level_t att_keymaster_security_level;
keymaster_blob_t att_challenge = {};
keymaster_blob_t att_unique_id = {};
- EXPECT_EQ(KM_ERROR_OK, parse_attestation_record(
- attest_rec->data, attest_rec->length, &att_attestation_version,
- &att_attestation_security_level, &att_keymaster_version,
- &att_keymaster_security_level, &att_challenge, &att_sw_enforced,
- &att_tee_enforced, &att_unique_id));
+ keymaster_blob_t att_boot_key = {};
+ keymaster_verified_boot_t att_boot_state;
+ bool att_dev_locked;
+ std::vector<int64_t> unexpected_eat_claims;
+ if (expected_keymaster_version >= (uint32_t)KmVersion::KEYMINT_1) {
+ EXPECT_EQ(KM_ERROR_OK,
+ parse_eat_record(attest_rec->data, attest_rec->length, &att_attestation_version,
+ &att_attestation_security_level, &att_keymaster_version,
+ &att_keymaster_security_level, &att_challenge, &att_sw_enforced,
+ &att_tee_enforced, &att_unique_id, &att_boot_key,
+ &att_boot_state, &att_dev_locked, &unexpected_eat_claims));
+ } else {
+ EXPECT_EQ(KM_ERROR_OK, parse_attestation_record(
+ attest_rec->data, attest_rec->length, &att_attestation_version,
+ &att_attestation_security_level, &att_keymaster_version,
+ &att_keymaster_security_level, &att_challenge, &att_sw_enforced,
+ &att_tee_enforced, &att_unique_id));
+ }
- EXPECT_EQ(2U, att_attestation_version);
+ EXPECT_EQ(std::vector<int64_t>(), unexpected_eat_claims);
+ EXPECT_EQ(expected_attestation_version, att_attestation_version);
EXPECT_EQ(KM_SECURITY_LEVEL_SOFTWARE, att_attestation_security_level);
EXPECT_EQ(expected_keymaster_version, att_keymaster_version);
EXPECT_EQ(expected_keymaster_security_level, att_keymaster_security_level);
@@ -4053,7 +3771,14 @@
return true;
}
-TEST_P(AttestationTest, RsaAttestation) {
+TEST_P(AttestationTest, RsaAttestationKeymaster) {
+ // We can't test KeyMint attestation here because these tests are architected to use the
+ // Keymaster2 API (an old-style C-struct HAL, pre-HIDL), which doesn't have a way to return the
+ // certificates. For now, we'll have to rely on the KeyMint VTS tests to validate KeyMint
+ // attestation.
+ //
+ // TODO: Refactor this test suite to use the HIDL/AIDL interfaces.
+ if (GetParam()->is_keymint()) return;
ASSERT_EQ(KM_ERROR_OK, GenerateKey(AuthorizationSetBuilder()
.RsaSigningKey(256, 3)
.Digest(KM_DIGEST_NONE)
@@ -4068,13 +3793,8 @@
uint32_t expected_keymaster_version;
keymaster_security_level_t expected_keymaster_security_level;
// TODO(swillden): Add a test KM1 that claims to be hardware.
- if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA)) {
- expected_keymaster_version = 0;
- expected_keymaster_security_level = KM_SECURITY_LEVEL_TRUSTED_ENVIRONMENT;
- } else {
- expected_keymaster_version = 3;
- expected_keymaster_security_level = KM_SECURITY_LEVEL_SOFTWARE;
- }
+ expected_keymaster_version = (uint32_t)GetParam()->km_version();
+ expected_keymaster_security_level = KM_SECURITY_LEVEL_SOFTWARE;
EXPECT_TRUE(verify_attestation_record(
"challenge", "attest_app_id", sw_enforced(), hw_enforced(), expected_keymaster_version,
@@ -4084,19 +3804,21 @@
}
TEST_P(AttestationTest, EcAttestation) {
+ // We can't test KeyMint attestation here because these tests are architected to use the
+ // Keymaster2 API (an old-style C-struct HAL, pre-HIDL), which doesn't have a way to return the
+ // certificates. For now, we'll have to rely on the KeyMint VTS tests to validate KeyMint
+ // attestation.
+ //
+ // TODO: Refactor this test suite to use the HIDL/AIDL interfaces.
+ if (GetParam()->is_keymint()) return;
ASSERT_EQ(KM_ERROR_OK, GenerateKey(AuthorizationSetBuilder().EcdsaSigningKey(256).Digest(
KM_DIGEST_SHA_2_256)));
uint32_t expected_keymaster_version;
keymaster_security_level_t expected_keymaster_security_level;
// TODO(swillden): Add a test KM1 that claims to be hardware.
- if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_EC)) {
- expected_keymaster_version = 0;
- expected_keymaster_security_level = KM_SECURITY_LEVEL_TRUSTED_ENVIRONMENT;
- } else {
- expected_keymaster_version = 3;
- expected_keymaster_security_level = KM_SECURITY_LEVEL_SOFTWARE;
- }
+ expected_keymaster_version = (uint32_t)GetParam()->km_version();
+ expected_keymaster_security_level = KM_SECURITY_LEVEL_SOFTWARE;
keymaster_cert_chain_t cert_chain;
EXPECT_EQ(KM_ERROR_OK, AttestKey("challenge", "attest_app_id", &cert_chain));
@@ -4156,8 +3878,6 @@
// Upgrade should fail
EXPECT_EQ(KM_ERROR_INVALID_ARGUMENT, UpgradeKey(client_params()));
-
- EXPECT_EQ(0, GetParam()->keymaster0_calls());
}
TEST_P(KeyUpgradeTest, RsaVersionUpgrade) {
@@ -4201,9 +3921,6 @@
// Upgrade should fail
EXPECT_EQ(KM_ERROR_INVALID_ARGUMENT, UpgradeKey(client_params()));
-
- if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA))
- EXPECT_EQ(7, GetParam()->keymaster0_calls());
}
TEST_P(KeyUpgradeTest, EcVersionUpgrade) {
@@ -4248,17 +3965,16 @@
// Upgrade should fail
EXPECT_EQ(KM_ERROR_INVALID_ARGUMENT, UpgradeKey(client_params()));
-
- if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_EC))
- EXPECT_EQ(7, GetParam()->keymaster0_calls());
}
TEST(SoftKeymasterWrapperTest, CheckKeymaster2Device) {
// Make a good fake device, and wrap it.
- SoftKeymasterDevice* good_fake(new SoftKeymasterDevice(new TestKeymasterContext));
+ SoftKeymasterDevice* good_fake(
+ new SoftKeymasterDevice(new TestKeymasterContext(KmVersion::KEYMASTER_4_1)));
// Wrap it and check it.
- SoftKeymasterDevice* good_fake_wrapper(new SoftKeymasterDevice(new TestKeymasterContext));
+ SoftKeymasterDevice* good_fake_wrapper(
+ new SoftKeymasterDevice(new TestKeymasterContext(KmVersion::KEYMASTER_4_1)));
good_fake_wrapper->SetHardwareDevice(good_fake->keymaster_device());
EXPECT_TRUE(good_fake_wrapper->Keymaster1DeviceIsGood());
@@ -4267,11 +3983,12 @@
// 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());
+ (new SoftKeymasterDevice(new TestKeymasterContext(KmVersion::KEYMASTER_4_1, "256")))
+ ->keymaster_device());
// Wrap it and check it.
SoftKeymasterDevice* sha256_only_fake_wrapper(
- (new SoftKeymasterDevice(new TestKeymasterContext)));
+ (new SoftKeymasterDevice(new TestKeymasterContext(KmVersion::KEYMASTER_4_1))));
sha256_only_fake_wrapper->SetHardwareDevice(sha256_only_fake);
EXPECT_FALSE(sha256_only_fake_wrapper->Keymaster1DeviceIsGood());
@@ -4319,7 +4036,7 @@
}
ResponseVec ComputeSharedHmac(const KeymasterVec& keymasters, const ParamsVec& paramsVec) {
- ComputeSharedHmacRequest req;
+ ComputeSharedHmacRequest req(kMaxMessageVersion);
req.params_array.params_array = const_cast<HmacSharingParameters*>(paramsVec.data());
auto prevent_deletion_of_paramsVec_data =
finally([&]() { req.params_array.params_array = nullptr; });
@@ -4462,7 +4179,7 @@
ASSERT_TRUE(VerifyResponses(sharing_check_value, responses));
// Pick a random param and modify the seed.
- auto param_to_tweak = rand() & params.size();
+ auto param_to_tweak = rand() % params.size();
constexpr uint8_t wrong_seed_value[] = {0xF, 0x0, 0x0};
params[param_to_tweak].SetSeed({wrong_seed_value, sizeof(wrong_seed_value)});
auto prevent_deletion_of_wrong_seed =
diff --git a/tests/android_keymaster_test_utils.cpp b/tests/android_keymaster_test_utils.cpp
index b031d26..7b70601 100644
--- a/tests/android_keymaster_test_utils.cpp
+++ b/tests/android_keymaster_test_utils.cpp
@@ -42,19 +42,22 @@
break;
case KM_UINT_REP:
os << " (Rep)";
- /* Falls through */
+ /* Falls through */
+ [[fallthrough]];
case KM_UINT:
os << " Int: " << param.integer;
break;
case KM_ENUM_REP:
os << " (Rep)";
- /* Falls through */
+ /* Falls through */
+ [[fallthrough]];
case KM_ENUM:
os << " Enum: " << param.enumerated;
break;
case KM_ULONG_REP:
os << " (Rep)";
- /* Falls through */
+ /* Falls through */
+ [[fallthrough]];
case KM_ULONG:
os << " Long: " << param.long_integer;
break;
@@ -143,12 +146,10 @@
namespace keymaster {
bool operator==(const AuthorizationSet& a, const AuthorizationSet& b) {
- if (a.size() != b.size())
- return false;
+ if (a.size() != b.size()) return false;
for (size_t i = 0; i < a.size(); ++i)
- if (!(a[i] == b[i]))
- return false;
+ if (!(a[i] == b[i])) return false;
return true;
}
@@ -288,8 +289,7 @@
if (error == KM_ERROR_OK && out_tmp.data)
output->append(reinterpret_cast<const char*>(out_tmp.data), out_tmp.data_length);
free((void*)out_tmp.data);
- if (output_params)
- output_params->Reinitialize(out_params);
+ if (output_params) output_params->Reinitialize(out_params);
keymaster_free_param_set(&out_params);
return error;
}
@@ -324,8 +324,7 @@
if (out_tmp.data)
output->append(reinterpret_cast<const char*>(out_tmp.data), out_tmp.data_length);
free((void*)out_tmp.data);
- if (output_params)
- output_params->Reinitialize(out_params);
+ if (output_params) output_params->Reinitialize(out_params);
keymaster_free_param_set(&out_params);
return error;
}
@@ -485,6 +484,13 @@
return EncryptMessage(update_params, message, digest, padding, generated_nonce);
}
+string Keymaster2Test::EncryptMessage(const string& message, keymaster_digest_t digest,
+ keymaster_digest_t mgf_digest, keymaster_padding_t padding,
+ string* generated_nonce) {
+ AuthorizationSet update_params;
+ return EncryptMessage(update_params, message, digest, mgf_digest, padding, generated_nonce);
+}
+
string Keymaster2Test::EncryptMessage(const string& message, keymaster_block_mode_t block_mode,
keymaster_padding_t padding, string* generated_nonce) {
AuthorizationSet update_params;
@@ -492,6 +498,26 @@
}
string Keymaster2Test::EncryptMessage(const AuthorizationSet& update_params, const string& message,
+ keymaster_digest_t digest, keymaster_digest_t mgf_digest,
+ keymaster_padding_t padding, string* generated_nonce) {
+ SCOPED_TRACE("EncryptMessage");
+ AuthorizationSet begin_params(client_params()), output_params;
+ begin_params.push_back(TAG_PADDING, padding);
+ begin_params.push_back(TAG_DIGEST, digest);
+ begin_params.push_back(TAG_RSA_OAEP_MGF_DIGEST, mgf_digest);
+ string ciphertext =
+ ProcessMessage(KM_PURPOSE_ENCRYPT, message, begin_params, update_params, &output_params);
+ if (generated_nonce) {
+ keymaster_blob_t nonce_blob;
+ EXPECT_TRUE(output_params.GetTagValue(TAG_NONCE, &nonce_blob));
+ *generated_nonce = make_string(nonce_blob.data, nonce_blob.data_length);
+ } else {
+ EXPECT_EQ(-1, output_params.find(TAG_NONCE));
+ }
+ return ciphertext;
+}
+
+string Keymaster2Test::EncryptMessage(const AuthorizationSet& update_params, const string& message,
keymaster_digest_t digest, keymaster_padding_t padding,
string* generated_nonce) {
SCOPED_TRACE("EncryptMessage");
@@ -587,6 +613,17 @@
return ProcessMessage(KM_PURPOSE_DECRYPT, ciphertext, begin_params, update_params);
}
+string Keymaster2Test::DecryptMessage(const string& ciphertext, keymaster_digest_t digest,
+ keymaster_digest_t mgf_digest, keymaster_padding_t padding) {
+ SCOPED_TRACE("DecryptMessage");
+ AuthorizationSet begin_params(client_params());
+ begin_params.push_back(TAG_PADDING, padding);
+ begin_params.push_back(TAG_DIGEST, digest);
+ begin_params.push_back(TAG_RSA_OAEP_MGF_DIGEST, mgf_digest);
+ AuthorizationSet update_params;
+ return ProcessMessage(KM_PURPOSE_DECRYPT, ciphertext, begin_params, update_params);
+}
+
string Keymaster2Test::DecryptMessage(const AuthorizationSet& update_params,
const string& ciphertext, keymaster_digest_t digest,
keymaster_padding_t padding, const string& nonce) {
@@ -617,8 +654,7 @@
keymaster_error_t error = device()->export_key(device(), format, &blob_, &client_id_,
nullptr /* app_data */, &export_tmp);
- if (error != KM_ERROR_OK)
- return error;
+ if (error != KM_ERROR_OK) return error;
*export_data = string(reinterpret_cast<const char*>(export_tmp.data), export_tmp.data_length);
free((void*)export_tmp.data);
@@ -750,8 +786,7 @@
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;
+ if (alg_ptr == end) return nullptr;
return alg_ptr;
}
@@ -795,8 +830,7 @@
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;
+ 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),
@@ -835,8 +869,7 @@
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) return KM_ERROR_UNSUPPORTED_ALGORITHM;
if (alg_ptr->enumerated == KM_ALGORITHM_HMAC && !all_digests_supported(params))
return KM_ERROR_UNSUPPORTED_DIGEST;
@@ -857,8 +890,7 @@
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) return KM_ERROR_UNSUPPORTED_ALGORITHM;
if (alg_ptr->enumerated == KM_ALGORITHM_HMAC && !all_digests_supported(params))
return KM_ERROR_UNSUPPORTED_DIGEST;
@@ -881,8 +913,7 @@
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;
+ 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);
}
diff --git a/tests/android_keymaster_test_utils.h b/tests/android_keymaster_test_utils.h
index a1965be..06eefab 100644
--- a/tests/android_keymaster_test_utils.h
+++ b/tests/android_keymaster_test_utils.h
@@ -14,8 +14,7 @@
* limitations under the License.
*/
-#ifndef SYSTEM_KEYMASTER_ANDROID_KEYMASTER_TEST_UTILS_H_
-#define SYSTEM_KEYMASTER_ANDROID_KEYMASTER_TEST_UTILS_H_
+#pragma once
/*
* Utilities used to help with testing. Not used in production code.
@@ -31,7 +30,6 @@
#include <gtest/gtest.h>
-#include <hardware/keymaster0.h>
#include <hardware/keymaster1.h>
#include <hardware/keymaster2.h>
#include <hardware/keymaster_defs.h>
@@ -39,6 +37,7 @@
#include <keymaster/android_keymaster_utils.h>
#include <keymaster/authorization_set.h>
#include <keymaster/keymaster_context.h>
+#include <keymaster/km_version.h>
#include <keymaster/logger.h>
std::ostream& operator<<(std::ostream& os, const keymaster_key_param_t& param);
@@ -66,8 +65,7 @@
KeymasterEnum val) {
int pos = -1;
while ((pos = set.find(tag, pos)) != -1)
- if (static_cast<KeymasterEnum>(set[pos].enumerated) == val)
- return true;
+ if (static_cast<KeymasterEnum>(set[pos].enumerated) == val) return true;
return false;
}
@@ -81,8 +79,7 @@
bool contains(const AuthorizationSet& set, TypedTag<KM_UINT_REP, Tag> tag, uint32_t val) {
int pos = -1;
while ((pos = set.find(tag, pos)) != -1)
- if (set[pos].integer == val)
- return true;
+ if (set[pos].integer == val) return true;
return false;
}
@@ -95,17 +92,15 @@
template <keymaster_tag_t Tag>
bool contains(const AuthorizationSet& set, TypedTag<KM_BYTES, Tag> tag, const std::string& val) {
int pos = set.find(tag);
- return pos != -1 &&
- std::string(reinterpret_cast<const char*>(set[pos].blob.data),
- set[pos].blob.data_length) == val;
+ return pos != -1 && std::string(reinterpret_cast<const char*>(set[pos].blob.data),
+ set[pos].blob.data_length) == val;
}
template <keymaster_tag_t Tag>
bool contains(const AuthorizationSet& set, TypedTag<KM_BIGNUM, Tag> tag, const std::string& val) {
int pos = set.find(tag);
- return pos != -1 &&
- std::string(reinterpret_cast<const char*>(set[pos].blob.data),
- set[pos].blob.data_length) == val;
+ return pos != -1 && std::string(reinterpret_cast<const char*>(set[pos].blob.data),
+ set[pos].blob.data_length) == val;
}
inline bool contains(const AuthorizationSet& set, keymaster_tag_t tag) {
@@ -161,11 +156,11 @@
virtual ~Keymaster2TestInstanceCreator(){};
virtual keymaster2_device_t* CreateDevice() 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; }
virtual bool is_keymaster1_hw() const = 0;
+ virtual bool is_keymint() const { return false; }
virtual KeymasterContext* keymaster_context() const = 0;
+ virtual KmVersion km_version() const = 0;
virtual std::string name() const = 0;
};
@@ -251,10 +246,16 @@
std::string EncryptMessage(const std::string& message, keymaster_padding_t padding,
std::string* generated_nonce = nullptr);
std::string EncryptMessage(const std::string& message, keymaster_digest_t digest,
+ keymaster_digest_t mgf_digest, keymaster_padding_t padding,
+ std::string* generated_nonce = nullptr);
+ std::string EncryptMessage(const std::string& message, keymaster_digest_t digest,
keymaster_padding_t padding, std::string* generated_nonce = nullptr);
std::string EncryptMessage(const std::string& message, keymaster_block_mode_t block_mode,
keymaster_padding_t padding, std::string* generated_nonce = nullptr);
std::string EncryptMessage(const AuthorizationSet& update_params, const std::string& message,
+ keymaster_digest_t digest, keymaster_digest_t mgf_digest,
+ keymaster_padding_t padding, std::string* generated_nonce = nullptr);
+ std::string EncryptMessage(const AuthorizationSet& update_params, const std::string& message,
keymaster_digest_t digest, keymaster_padding_t padding,
std::string* generated_nonce = nullptr);
std::string EncryptMessage(const AuthorizationSet& update_params, const std::string& message,
@@ -272,6 +273,8 @@
keymaster_padding_t padding);
std::string DecryptMessage(const std::string& ciphertext, keymaster_digest_t digest,
keymaster_padding_t padding, const std::string& nonce);
+ std::string DecryptMessage(const std::string& ciphertext, keymaster_digest_t digest,
+ keymaster_digest_t mgf_digest, keymaster_padding_t padding);
std::string DecryptMessage(const std::string& ciphertext, keymaster_block_mode_t block_mode,
keymaster_padding_t padding, const std::string& nonce);
std::string DecryptMessage(const AuthorizationSet& update_params, const std::string& ciphertext,
@@ -348,139 +351,6 @@
keymaster_key_characteristics_t characteristics_;
};
-struct Keymaster0CountingWrapper : public keymaster0_device_t {
- explicit Keymaster0CountingWrapper(keymaster0_device_t* device) : device_(device), counter_(0) {
- common = device_->common;
- common.close = counting_close_device;
- client_version = device_->client_version;
- flags = device_->flags;
- context = this;
-
- generate_keypair = counting_generate_keypair;
- import_keypair = counting_import_keypair;
- get_keypair_public = counting_get_keypair_public;
- delete_keypair = counting_delete_keypair;
- delete_all = counting_delete_all;
- sign_data = counting_sign_data;
- verify_data = counting_verify_data;
- }
-
- int count() { return counter_; }
-
- // The blobs generated by the underlying softkeymaster start with "PK#8". Tweak the prefix so
- // they don't get identified as softkeymaster blobs.
- static void munge_blob(uint8_t* blob, size_t blob_length) {
- if (blob && blob_length > 0 && *blob == 'P')
- *blob = 'Q'; // Mind your Ps and Qs!
- }
-
- // Copy and un-modfy the blob. The caller must clean up the return value.
- static uint8_t* unmunge_blob(const uint8_t* blob, size_t blob_length) {
- uint8_t* dup_blob = dup_buffer(blob, blob_length);
- if (dup_blob && blob_length > 0 && *dup_blob == 'Q')
- *dup_blob = 'P';
- return dup_blob;
- }
-
- static keymaster0_device_t* device(const keymaster0_device_t* dev) {
- Keymaster0CountingWrapper* wrapper =
- reinterpret_cast<Keymaster0CountingWrapper*>(dev->context);
- return wrapper->device_;
- }
-
- static void increment(const keymaster0_device_t* dev) {
- Keymaster0CountingWrapper* wrapper =
- reinterpret_cast<Keymaster0CountingWrapper*>(dev->context);
- wrapper->counter_++;
- }
-
- static int counting_close_device(hw_device_t* dev) {
- keymaster0_device_t* k0_dev = reinterpret_cast<keymaster0_device_t*>(dev);
- increment(k0_dev);
- Keymaster0CountingWrapper* wrapper =
- reinterpret_cast<Keymaster0CountingWrapper*>(k0_dev->context);
- int retval =
- wrapper->device_->common.close(reinterpret_cast<hw_device_t*>(wrapper->device_));
- delete wrapper;
- return retval;
- }
-
- static int counting_generate_keypair(const struct keymaster0_device* dev,
- const keymaster_keypair_t key_type, const void* key_params,
- uint8_t** key_blob, size_t* key_blob_length) {
- increment(dev);
- int result = device(dev)->generate_keypair(device(dev), key_type, key_params, key_blob,
- key_blob_length);
- if (result == 0)
- munge_blob(*key_blob, *key_blob_length);
- return result;
- }
-
- static int counting_import_keypair(const struct keymaster0_device* dev, const uint8_t* key,
- const size_t key_length, uint8_t** key_blob,
- size_t* key_blob_length) {
- increment(dev);
- int result =
- device(dev)->import_keypair(device(dev), key, key_length, key_blob, key_blob_length);
- if (result == 0)
- munge_blob(*key_blob, *key_blob_length);
- return result;
- }
-
- static int counting_get_keypair_public(const struct keymaster0_device* dev,
- const uint8_t* key_blob, const size_t key_blob_length,
- uint8_t** x509_data, size_t* x509_data_length) {
- increment(dev);
- std::unique_ptr<uint8_t[]> dup_blob(unmunge_blob(key_blob, key_blob_length));
- return device(dev)->get_keypair_public(device(dev), dup_blob.get(), key_blob_length,
- x509_data, x509_data_length);
- }
-
- static int counting_delete_keypair(const struct keymaster0_device* dev, const uint8_t* key_blob,
- const size_t key_blob_length) {
- increment(dev);
- if (key_blob && key_blob_length > 0)
- EXPECT_EQ('Q', *key_blob);
- if (device(dev)->delete_keypair) {
- std::unique_ptr<uint8_t[]> dup_blob(unmunge_blob(key_blob, key_blob_length));
- return device(dev)->delete_keypair(device(dev), dup_blob.get(), key_blob_length);
- }
- return 0;
- }
-
- static int counting_delete_all(const struct keymaster0_device* dev) {
- increment(dev);
- if (device(dev)->delete_all)
- return device(dev)->delete_all(device(dev));
- return 0;
- }
-
- static int counting_sign_data(const struct keymaster0_device* 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) {
- increment(dev);
- std::unique_ptr<uint8_t[]> dup_blob(unmunge_blob(key_blob, key_blob_length));
- return device(dev)->sign_data(device(dev), signing_params, dup_blob.get(), key_blob_length,
- data, data_length, signed_data, signed_data_length);
- }
-
- static int counting_verify_data(const struct keymaster0_device* 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) {
- increment(dev);
- std::unique_ptr<uint8_t[]> dup_blob(unmunge_blob(key_blob, key_blob_length));
- return device(dev)->verify_data(device(dev), signing_params, dup_blob.get(),
- key_blob_length, signed_data, signed_data_length, signature,
- signature_length);
- }
-
- private:
- keymaster0_device_t* device_;
- int counter_;
-};
-
/**
* This function takes a keymaster1_device_t and wraps it in an adapter that supports only
* KM_DIGEST_SHA_2_256.
@@ -489,5 +359,3 @@
} // namespace test
} // namespace keymaster
-
-#endif // SYSTEM_KEYMASTER_ANDROID_KEYMASTER_TEST_UTILS_H_
diff --git a/tests/attestation_record_test.cpp b/tests/attestation_record_test.cpp
index 02b99f7..92cd77d 100644
--- a/tests/attestation_record_test.cpp
+++ b/tests/attestation_record_test.cpp
@@ -16,37 +16,46 @@
#include <fstream>
+#include <cppbor_parse.h>
#include <gtest/gtest.h>
+#include <keymaster/contexts/soft_attestation_context.h>
#include <keymaster/keymaster_context.h>
+#include <keymaster/km_openssl/attestation_record.h>
#include "android_keymaster_test_utils.h"
-#include <keymaster/attestation_record.h>
+
+// Use TAG_KDF as an 'unknown tag', as it is not deliberately thrown out
+// in attestation_record.cpp, but still among the keymaster tag types.
+#define UNKNOWN_TAG static_cast<keymaster_tag_t>(KM_ULONG_REP | 50)
+#define UNKNOWN_TAG_VALUE 0
namespace keymaster {
namespace test {
-class TestContext : public AttestationRecordContext {
+TypedTag<KM_ULONG_REP, UNKNOWN_TAG> UNKNOWN_TAG_T;
+
+class TestContext : public SoftAttestationContext {
public:
+ TestContext(KmVersion version) : SoftAttestationContext(version) {}
+
keymaster_security_level_t GetSecurityLevel() const override {
return KM_SECURITY_LEVEL_TRUSTED_ENVIRONMENT;
}
- keymaster_error_t GenerateUniqueId(uint64_t /* creation_date_time */,
- const keymaster_blob_t& application_id,
- bool /* reset_since_rotation */,
- Buffer* unique_id) const override {
+ Buffer GenerateUniqueId(uint64_t /* creation_date_time */,
+ const keymaster_blob_t& application_id, bool /* reset_since_rotation */,
+ keymaster_error_t* error) const override {
// Use the application ID directly as the unique ID.
- unique_id->Reinitialize(application_id.data, application_id.data_length);
- return KM_ERROR_OK;
+ *error = KM_ERROR_OK;
+ return {application_id.data, application_id.data_length};
}
- keymaster_error_t GetVerifiedBootParams(keymaster_blob_t* verified_boot_key,
- keymaster_verified_boot_t* verified_boot_state,
- bool* device_locked) const override {
- verified_boot_key->data = vboot_key_;
- verified_boot_key->data_length = sizeof(vboot_key_);
- *verified_boot_state = KM_VERIFIED_BOOT_VERIFIED;
- *device_locked = true;
- return KM_ERROR_OK;
+ const VerifiedBootParams* GetVerifiedBootParams(keymaster_error_t* error) const override {
+ static VerifiedBootParams params{};
+ params.verified_boot_key = {vboot_key_, sizeof(vboot_key_)};
+ params.verified_boot_state = KM_VERIFIED_BOOT_VERIFIED;
+ params.device_locked = true;
+ *error = KM_ERROR_OK;
+ return ¶ms;
}
void VerifyRootOfTrust(const keymaster_blob_t& verified_boot_key,
@@ -63,8 +72,18 @@
uint8_t vboot_key_[32]{"test_vboot_key"};
};
-TEST(AttestTest, Simple) {
- TestContext context;
+class KeymintTestContext : public TestContext {
+ public:
+ KeymintTestContext() : TestContext(KmVersion::KEYMINT_1) {}
+};
+
+class KeymasterTestContext : public TestContext {
+ public:
+ KeymasterTestContext() : TestContext(KmVersion::KEYMASTER_4_1) {} // Last Keymaster version
+};
+
+TEST(AttestAsn1Test, Simple) {
+ KeymasterTestContext context;
AuthorizationSet hw_set(AuthorizationSetBuilder()
.RsaSigningKey(512, 3)
.Digest(KM_DIGEST_SHA_2_256)
@@ -75,7 +94,8 @@
AuthorizationSet sw_set(AuthorizationSetBuilder()
.Authorization(TAG_ACTIVE_DATETIME, 10)
.Authorization(TAG_CREATION_DATETIME, 10)
- .Authorization(TAG_APPLICATION_ID, "fake_app_id", 11));
+ .Authorization(TAG_APPLICATION_ID, "fake_app_id", 19)
+ .Authorization(TAG_APPLICATION_DATA, "fake_app_data", 12));
UniquePtr<uint8_t[]> asn1;
size_t asn1_len = 0;
@@ -89,8 +109,7 @@
std::ofstream output("attest.der",
std::ofstream::out | std::ofstream::binary | std::ofstream::trunc);
- if (output)
- output.write(reinterpret_cast<const char*>(asn1.get()), asn1_len);
+ if (output) output.write(reinterpret_cast<const char*>(asn1.get()), asn1_len);
output.close();
AuthorizationSet parsed_hw_set;
@@ -122,6 +141,10 @@
// The TAG_INCLUDE_UNIQUE_ID tag is not expected to appear in parsed_hw_set.
hw_set.erase(hw_set.find(TAG_INCLUDE_UNIQUE_ID));
+ // Application data is not expected to appear in parsed_sw_set.
+ sw_set.erase(sw_set.find(TAG_APPLICATION_ID));
+ sw_set.erase(sw_set.find(TAG_APPLICATION_DATA));
+
// Check that the list of tags is consistent across build and parse.
hw_set.Sort();
sw_set.Sort();
@@ -140,5 +163,190 @@
delete[] verified_boot_key.data;
}
+TEST(EatTest, Simple) {
+ KeymintTestContext context;
+ AuthorizationSet hw_set(AuthorizationSetBuilder()
+ .RsaSigningKey(512, 3)
+ .Digest(KM_DIGEST_SHA_2_256)
+ .Digest(KM_DIGEST_SHA_2_384)
+ .Authorization(TAG_OS_VERSION, 60000)
+ .Authorization(TAG_OS_PATCHLEVEL, 201512)
+ .Authorization(TAG_INCLUDE_UNIQUE_ID)
+ .Authorization(TAG_ATTESTATION_ID_IMEI, "490154203237518", 15));
+ AuthorizationSet sw_set(AuthorizationSetBuilder()
+ .Authorization(TAG_ACTIVE_DATETIME, 10)
+ .Authorization(TAG_CREATION_DATETIME, 10)
+ .Authorization(TAG_APPLICATION_ID, "fake_app_id", 19)
+ .Authorization(TAG_APPLICATION_DATA, "fake_app_data", 12));
+
+ std::vector<uint8_t> eat;
+ AuthorizationSet attest_params(
+ AuthorizationSetBuilder()
+ .Authorization(TAG_ATTESTATION_CHALLENGE, "fake_challenge", 14)
+ .Authorization(TAG_ATTESTATION_APPLICATION_ID, "fake_attest_app_id", 18));
+ ASSERT_EQ(KM_ERROR_OK, build_eat_record(attest_params, sw_set, hw_set, context, &eat));
+ EXPECT_GT(eat.size(), 0U);
+
+ std::ofstream output("eat.der",
+ std::ofstream::out | std::ofstream::binary | std::ofstream::trunc);
+ if (output) output.write(reinterpret_cast<const char*>(&eat[0]), eat.size() * sizeof(uint8_t));
+ output.close();
+
+ AuthorizationSet parsed_hw_set;
+ AuthorizationSet parsed_sw_set;
+ uint32_t attestation_version;
+ uint32_t keymaster_version;
+ keymaster_security_level_t attestation_security_level;
+ keymaster_security_level_t keymaster_security_level;
+ keymaster_blob_t attestation_challenge = {};
+ keymaster_blob_t unique_id = {};
+ keymaster_blob_t verified_boot_key = {};
+ keymaster_verified_boot_t verified_boot_state;
+ bool device_locked;
+ std::vector<int64_t> unexpected_claims;
+ EXPECT_EQ(KM_ERROR_OK,
+ parse_eat_record(eat.data(), eat.size(), &attestation_version,
+ &attestation_security_level, &keymaster_version,
+ &keymaster_security_level, &attestation_challenge, &parsed_sw_set,
+ &parsed_hw_set, &unique_id, &verified_boot_key, &verified_boot_state,
+ &device_locked, &unexpected_claims));
+
+ // Check that there were no unexpected claims when parsing.
+ EXPECT_EQ(std::vector<int64_t>(), unexpected_claims);
+
+ // Check that the challenge is consistent across build and parse.
+ EXPECT_EQ("fake_challenge",
+ std::string(reinterpret_cast<const char*>(attestation_challenge.data), 14));
+ delete[] attestation_challenge.data;
+
+ // Check that the unique id was populated as expected.
+ EXPECT_EQ("fake_app_id", std::string(reinterpret_cast<const char*>(unique_id.data), 11));
+ delete[] unique_id.data;
+
+ // The attestation ID is expected to appear in parsed_sw_set.
+ sw_set.push_back(TAG_ATTESTATION_APPLICATION_ID, "fake_attest_app_id", 18);
+
+ // The TAG_INCLUDE_UNIQUE_ID tag is not expected to appear in parsed_hw_set.
+ hw_set.erase(hw_set.find(TAG_INCLUDE_UNIQUE_ID));
+
+ // Application data is not expected to appear in parsed_sw_set.
+ sw_set.erase(sw_set.find(TAG_APPLICATION_ID));
+ sw_set.erase(sw_set.find(TAG_APPLICATION_DATA));
+
+ // Check that the list of tags is consistent across build and parse.
+ hw_set.Sort();
+ sw_set.Sort();
+ parsed_hw_set.Sort();
+ parsed_sw_set.Sort();
+ EXPECT_EQ(hw_set, parsed_hw_set);
+ EXPECT_EQ(sw_set, parsed_sw_set);
+
+ // Check the root of trust values.
+ context.VerifyRootOfTrust(verified_boot_key, verified_boot_state, device_locked);
+ delete[] verified_boot_key.data;
+}
+
+TEST(BadImeiTest, Simple) {
+ KeymintTestContext context;
+ AuthorizationSet hw_set(
+ AuthorizationSetBuilder().Authorization(TAG_ATTESTATION_ID_IMEI, "1234567890123456", 16));
+ AuthorizationSet attest_params(
+ AuthorizationSetBuilder()
+ .Authorization(TAG_ATTESTATION_CHALLENGE, "fake_challenge", 14)
+ .Authorization(TAG_ATTESTATION_APPLICATION_ID, "fake_attest_app_id", 18));
+ AuthorizationSet sw_set;
+
+ std::vector<uint8_t> eat;
+ ASSERT_EQ(KM_ERROR_INVALID_TAG, build_eat_record(attest_params, sw_set, hw_set, context, &eat));
+}
+
+TEST(MissingAuthChallengeTest, Simple) {
+ KeymintTestContext context;
+ AuthorizationSet hw_set(AuthorizationSetBuilder().Authorization(TAG_OS_PATCHLEVEL, 201512));
+ AuthorizationSet attest_params(AuthorizationSetBuilder().Authorization(
+ TAG_ATTESTATION_APPLICATION_ID, "fake_attest_app_id", 18));
+ AuthorizationSet sw_set;
+
+ std::vector<uint8_t> eat;
+ ASSERT_EQ(KM_ERROR_ATTESTATION_CHALLENGE_MISSING,
+ build_eat_record(attest_params, sw_set, hw_set, context, &eat));
+}
+
+TEST(UnknownTagTest, Simple) {
+ KeymintTestContext context;
+ AuthorizationSet unknown_tag_set(
+ AuthorizationSetBuilder().Authorization(UNKNOWN_TAG_T, UNKNOWN_TAG_VALUE));
+
+ // Test adding an unknown tag to both sets. The tag should be retained only in the software
+ // submod.
+ std::vector<uint8_t> eat;
+ AuthorizationSet attest_params(
+ AuthorizationSetBuilder()
+ .Authorization(TAG_ATTESTATION_CHALLENGE, "fake_challenge", 14)
+ .Authorization(TAG_ATTESTATION_APPLICATION_ID, "fake_attest_app_id", 18));
+ ASSERT_EQ(KM_ERROR_OK,
+ build_eat_record(attest_params, unknown_tag_set, unknown_tag_set, context, &eat));
+ EXPECT_GT(eat.size(), 0U);
+
+ AuthorizationSet parsed_hw_set;
+ AuthorizationSet parsed_sw_set;
+ uint32_t attestation_version;
+ uint32_t keymaster_version;
+ keymaster_security_level_t attestation_security_level;
+ keymaster_security_level_t keymaster_security_level;
+ keymaster_blob_t attestation_challenge = {};
+ keymaster_blob_t unique_id = {};
+ keymaster_blob_t verified_boot_key = {};
+ keymaster_verified_boot_t verified_boot_state;
+ bool device_locked;
+ std::vector<int64_t> unexpected_claims;
+ // Parsing should fail, because the software submod retains the unknown tag.
+ EXPECT_EQ(KM_ERROR_INVALID_TAG,
+ parse_eat_record(eat.data(), eat.size(), &attestation_version,
+ &attestation_security_level, &keymaster_version,
+ &keymaster_security_level, &attestation_challenge, &parsed_sw_set,
+ &parsed_hw_set, &unique_id, &verified_boot_key, &verified_boot_state,
+ &device_locked, &unexpected_claims));
+
+ // Perform a manual inspection of the EAT token, checking that the tag is retained in the
+ // software submod, but not in the hardware submod.
+ auto [top_level_item, next_pos, error] = cppbor::parse(eat.data(), eat.size());
+ ASSERT_NE(top_level_item, nullptr);
+ const cppbor::Map* eat_map = top_level_item->asMap();
+ ASSERT_NE(eat_map, nullptr);
+ bool found_in_software_submod = false;
+ bool found_in_hardware_submod = false;
+ for (size_t i = 0; i < eat_map->size(); i++) {
+ auto& [eat_key, eat_value] = (*eat_map)[i];
+ const cppbor::Int* root_key = eat_key->asInt();
+ if ((EatClaim)root_key->value() == EatClaim::SUBMODS) {
+ const cppbor::Map* submods_map = eat_value->asMap();
+ // Check for each submod whether it contains the expected value.
+ for (size_t j = 0; j < submods_map->size(); j++) {
+ auto& [submod_key, submod_value] = (*submods_map)[j];
+ const cppbor::Map* submod_map = submod_value->asMap();
+ bool found_in_submod = false;
+ EatSecurityLevel submod_security_level;
+ for (size_t k = 0; k < submod_map->size(); k++) {
+ auto& [key_item, value_item] = (*submod_map)[k];
+ const cppbor::Int* key_int = key_item->asInt();
+ if (key_int->value() == convert_to_eat_claim(UNKNOWN_TAG_T)) {
+ found_in_submod = true;
+ } else if ((EatClaim)key_int->value() == EatClaim::SECURITY_LEVEL) {
+ submod_security_level = (EatSecurityLevel)value_item->asInt()->value();
+ }
+ }
+ if (submod_security_level == EatSecurityLevel::UNRESTRICTED) {
+ found_in_software_submod = found_in_submod;
+ } else if (submod_security_level == EatSecurityLevel::SECURE_RESTRICTED) {
+ found_in_hardware_submod = found_in_submod;
+ }
+ }
+ }
+ }
+ EXPECT_FALSE(found_in_hardware_submod);
+ EXPECT_TRUE(found_in_software_submod);
+}
+
} // namespace test
} // namespace keymaster
diff --git a/tests/authorization_set_test.cpp b/tests/authorization_set_test.cpp
index 8c908c3..ecbe2c0 100644
--- a/tests/authorization_set_test.cpp
+++ b/tests/authorization_set_test.cpp
@@ -16,8 +16,8 @@
#include <gtest/gtest.h>
-#include <keymaster/authorization_set.h>
#include <keymaster/android_keymaster_utils.h>
+#include <keymaster/authorization_set.h>
#include "android_keymaster_test_utils.h"
@@ -27,10 +27,13 @@
TEST(Construction, ListProvided) {
keymaster_key_param_t params[] = {
- Authorization(TAG_PURPOSE, KM_PURPOSE_SIGN), Authorization(TAG_PURPOSE, KM_PURPOSE_VERIFY),
- Authorization(TAG_ALGORITHM, KM_ALGORITHM_RSA), Authorization(TAG_USER_ID, 7),
+ Authorization(TAG_PURPOSE, KM_PURPOSE_SIGN),
+ Authorization(TAG_PURPOSE, KM_PURPOSE_VERIFY),
+ Authorization(TAG_ALGORITHM, KM_ALGORITHM_RSA),
+ Authorization(TAG_USER_ID, 7),
Authorization(TAG_USER_AUTH_TYPE, HW_AUTH_PASSWORD),
- Authorization(TAG_APPLICATION_ID, "my_app", 6), Authorization(TAG_KEY_SIZE, 256),
+ Authorization(TAG_APPLICATION_ID, "my_app", 6),
+ Authorization(TAG_KEY_SIZE, 256),
Authorization(TAG_AUTH_TIMEOUT, 300),
};
AuthorizationSet set(params, array_length(params));
@@ -39,10 +42,13 @@
TEST(Construction, Copy) {
keymaster_key_param_t params[] = {
- Authorization(TAG_PURPOSE, KM_PURPOSE_SIGN), Authorization(TAG_PURPOSE, KM_PURPOSE_VERIFY),
- Authorization(TAG_ALGORITHM, KM_ALGORITHM_RSA), Authorization(TAG_USER_ID, 7),
+ Authorization(TAG_PURPOSE, KM_PURPOSE_SIGN),
+ Authorization(TAG_PURPOSE, KM_PURPOSE_VERIFY),
+ Authorization(TAG_ALGORITHM, KM_ALGORITHM_RSA),
+ Authorization(TAG_USER_ID, 7),
Authorization(TAG_USER_AUTH_TYPE, HW_AUTH_PASSWORD),
- Authorization(TAG_APPLICATION_ID, "my_app", 6), Authorization(TAG_KEY_SIZE, 256),
+ Authorization(TAG_APPLICATION_ID, "my_app", 6),
+ Authorization(TAG_KEY_SIZE, 256),
Authorization(TAG_AUTH_TIMEOUT, 300),
};
AuthorizationSet set(params, array_length(params));
@@ -52,7 +58,8 @@
TEST(Construction, NullProvided) {
keymaster_key_param_t params[] = {
- Authorization(TAG_PURPOSE, KM_PURPOSE_SIGN), Authorization(TAG_PURPOSE, KM_PURPOSE_VERIFY),
+ Authorization(TAG_PURPOSE, KM_PURPOSE_SIGN),
+ Authorization(TAG_PURPOSE, KM_PURPOSE_VERIFY),
};
AuthorizationSet set1(params, 0);
@@ -637,22 +644,22 @@
TEST(Union, Disjoint) {
AuthorizationSet set1(AuthorizationSetBuilder()
- .Authorization(TAG_PURPOSE, KM_PURPOSE_VERIFY)
- .Authorization(TAG_ACTIVE_DATETIME, 10)
- .Authorization(TAG_APPLICATION_DATA, "data", 4));
+ .Authorization(TAG_PURPOSE, KM_PURPOSE_VERIFY)
+ .Authorization(TAG_ACTIVE_DATETIME, 10)
+ .Authorization(TAG_APPLICATION_DATA, "data", 4));
AuthorizationSet set2(AuthorizationSetBuilder()
- .Authorization(TAG_USER_ID, 7)
- .Authorization(TAG_APPLICATION_DATA, "foo", 3)
- .Authorization(TAG_USER_AUTH_TYPE, HW_AUTH_PASSWORD));
+ .Authorization(TAG_USER_ID, 7)
+ .Authorization(TAG_APPLICATION_DATA, "foo", 3)
+ .Authorization(TAG_USER_AUTH_TYPE, HW_AUTH_PASSWORD));
AuthorizationSet expected(AuthorizationSetBuilder()
- .Authorization(TAG_USER_AUTH_TYPE, HW_AUTH_PASSWORD)
- .Authorization(TAG_PURPOSE, KM_PURPOSE_VERIFY)
- .Authorization(TAG_USER_ID, 7)
- .Authorization(TAG_ACTIVE_DATETIME, 10)
- .Authorization(TAG_APPLICATION_DATA, "data", 4)
- .Authorization(TAG_APPLICATION_DATA, "foo", 3));
+ .Authorization(TAG_USER_AUTH_TYPE, HW_AUTH_PASSWORD)
+ .Authorization(TAG_PURPOSE, KM_PURPOSE_VERIFY)
+ .Authorization(TAG_USER_ID, 7)
+ .Authorization(TAG_ACTIVE_DATETIME, 10)
+ .Authorization(TAG_APPLICATION_DATA, "data", 4)
+ .Authorization(TAG_APPLICATION_DATA, "foo", 3));
set1.Union(set2);
EXPECT_EQ(expected, set1);
@@ -660,19 +667,19 @@
TEST(Union, Overlap) {
AuthorizationSet set1(AuthorizationSetBuilder()
- .Authorization(TAG_PURPOSE, KM_PURPOSE_VERIFY)
- .Authorization(TAG_ACTIVE_DATETIME, 10)
- .Authorization(TAG_APPLICATION_DATA, "data", 4));
+ .Authorization(TAG_PURPOSE, KM_PURPOSE_VERIFY)
+ .Authorization(TAG_ACTIVE_DATETIME, 10)
+ .Authorization(TAG_APPLICATION_DATA, "data", 4));
AuthorizationSet set2(AuthorizationSetBuilder()
- .Authorization(TAG_PURPOSE, KM_PURPOSE_VERIFY)
- .Authorization(TAG_ACTIVE_DATETIME, 10)
- .Authorization(TAG_APPLICATION_DATA, "data", 4));
+ .Authorization(TAG_PURPOSE, KM_PURPOSE_VERIFY)
+ .Authorization(TAG_ACTIVE_DATETIME, 10)
+ .Authorization(TAG_APPLICATION_DATA, "data", 4));
AuthorizationSet expected(AuthorizationSetBuilder()
- .Authorization(TAG_PURPOSE, KM_PURPOSE_VERIFY)
- .Authorization(TAG_ACTIVE_DATETIME, 10)
- .Authorization(TAG_APPLICATION_DATA, "data", 4));
+ .Authorization(TAG_PURPOSE, KM_PURPOSE_VERIFY)
+ .Authorization(TAG_ACTIVE_DATETIME, 10)
+ .Authorization(TAG_APPLICATION_DATA, "data", 4));
set1.Union(set2);
EXPECT_EQ(expected, set1);
@@ -680,16 +687,16 @@
TEST(Union, Empty) {
AuthorizationSet set1(AuthorizationSetBuilder()
- .Authorization(TAG_PURPOSE, KM_PURPOSE_VERIFY)
- .Authorization(TAG_ACTIVE_DATETIME, 10)
- .Authorization(TAG_APPLICATION_DATA, "data", 4));
+ .Authorization(TAG_PURPOSE, KM_PURPOSE_VERIFY)
+ .Authorization(TAG_ACTIVE_DATETIME, 10)
+ .Authorization(TAG_APPLICATION_DATA, "data", 4));
AuthorizationSet set2;
AuthorizationSet expected(AuthorizationSetBuilder()
- .Authorization(TAG_PURPOSE, KM_PURPOSE_VERIFY)
- .Authorization(TAG_ACTIVE_DATETIME, 10)
- .Authorization(TAG_APPLICATION_DATA, "data", 4));
+ .Authorization(TAG_PURPOSE, KM_PURPOSE_VERIFY)
+ .Authorization(TAG_ACTIVE_DATETIME, 10)
+ .Authorization(TAG_APPLICATION_DATA, "data", 4));
set1.Union(set2);
EXPECT_EQ(expected, set1);
@@ -697,20 +704,20 @@
TEST(Difference, Disjoint) {
AuthorizationSet set1(AuthorizationSetBuilder()
- .Authorization(TAG_APPLICATION_DATA, "data", 4)
- .Authorization(TAG_PURPOSE, KM_PURPOSE_VERIFY)
- .Authorization(TAG_ACTIVE_DATETIME, 10));
+ .Authorization(TAG_APPLICATION_DATA, "data", 4)
+ .Authorization(TAG_PURPOSE, KM_PURPOSE_VERIFY)
+ .Authorization(TAG_ACTIVE_DATETIME, 10));
AuthorizationSet set2(AuthorizationSetBuilder()
- .Authorization(TAG_USER_ID, 7)
- .Authorization(TAG_APPLICATION_DATA, "foo", 3)
- .Authorization(TAG_USER_AUTH_TYPE, HW_AUTH_PASSWORD));
+ .Authorization(TAG_USER_ID, 7)
+ .Authorization(TAG_APPLICATION_DATA, "foo", 3)
+ .Authorization(TAG_USER_AUTH_TYPE, HW_AUTH_PASSWORD));
// Elements are the same as set1, but happen to be in a different order
AuthorizationSet expected(AuthorizationSetBuilder()
- .Authorization(TAG_PURPOSE, KM_PURPOSE_VERIFY)
- .Authorization(TAG_ACTIVE_DATETIME, 10)
- .Authorization(TAG_APPLICATION_DATA, "data", 4));
+ .Authorization(TAG_PURPOSE, KM_PURPOSE_VERIFY)
+ .Authorization(TAG_ACTIVE_DATETIME, 10)
+ .Authorization(TAG_APPLICATION_DATA, "data", 4));
set1.Difference(set2);
EXPECT_EQ(expected, set1);
@@ -718,14 +725,14 @@
TEST(Difference, Overlap) {
AuthorizationSet set1(AuthorizationSetBuilder()
- .Authorization(TAG_PURPOSE, KM_PURPOSE_VERIFY)
- .Authorization(TAG_ACTIVE_DATETIME, 10)
- .Authorization(TAG_APPLICATION_DATA, "data", 4));
+ .Authorization(TAG_PURPOSE, KM_PURPOSE_VERIFY)
+ .Authorization(TAG_ACTIVE_DATETIME, 10)
+ .Authorization(TAG_APPLICATION_DATA, "data", 4));
AuthorizationSet set2(AuthorizationSetBuilder()
- .Authorization(TAG_PURPOSE, KM_PURPOSE_VERIFY)
- .Authorization(TAG_ACTIVE_DATETIME, 10)
- .Authorization(TAG_APPLICATION_DATA, "data", 4));
+ .Authorization(TAG_PURPOSE, KM_PURPOSE_VERIFY)
+ .Authorization(TAG_ACTIVE_DATETIME, 10)
+ .Authorization(TAG_APPLICATION_DATA, "data", 4));
AuthorizationSet empty;
set1.Difference(set2);
@@ -735,16 +742,16 @@
TEST(Difference, NullSet) {
AuthorizationSet set1(AuthorizationSetBuilder()
- .Authorization(TAG_PURPOSE, KM_PURPOSE_VERIFY)
- .Authorization(TAG_ACTIVE_DATETIME, 10)
- .Authorization(TAG_APPLICATION_DATA, "data", 4));
+ .Authorization(TAG_PURPOSE, KM_PURPOSE_VERIFY)
+ .Authorization(TAG_ACTIVE_DATETIME, 10)
+ .Authorization(TAG_APPLICATION_DATA, "data", 4));
AuthorizationSet set2;
AuthorizationSet expected(AuthorizationSetBuilder()
- .Authorization(TAG_PURPOSE, KM_PURPOSE_VERIFY)
- .Authorization(TAG_ACTIVE_DATETIME, 10)
- .Authorization(TAG_APPLICATION_DATA, "data", 4));
+ .Authorization(TAG_PURPOSE, KM_PURPOSE_VERIFY)
+ .Authorization(TAG_ACTIVE_DATETIME, 10)
+ .Authorization(TAG_APPLICATION_DATA, "data", 4));
set1.Difference(set2);
EXPECT_EQ(expected, set1);
diff --git a/tests/ecies_kem_test.cpp b/tests/ecies_kem_test.cpp
index 06e26c3..1910579 100644
--- a/tests/ecies_kem_test.cpp
+++ b/tests/ecies_kem_test.cpp
@@ -31,8 +31,6 @@
namespace keymaster {
namespace test {
-StdoutLogger logger;
-
static const keymaster_ec_curve_t kEcCurves[] = {KM_EC_CURVE_P_224, KM_EC_CURVE_P_256,
KM_EC_CURVE_P_384, KM_EC_CURVE_P_521};
diff --git a/tests/fuzzers/buffer_fuzz.cpp b/tests/fuzzers/buffer_fuzz.cpp
new file mode 100644
index 0000000..0b02b3f
--- /dev/null
+++ b/tests/fuzzers/buffer_fuzz.cpp
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2020 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 <functional>
+#include <memory>
+
+#include "fuzzer/FuzzedDataProvider.h"
+#include "keymaster/serializable.h"
+
+static constexpr uint16_t kMinBufferSize = 1;
+static constexpr uint16_t kMaxBufferSize = 2048;
+static constexpr uint16_t kMaxOperations = 1000;
+
+std::vector<std::function<void(keymaster::Buffer*, FuzzedDataProvider*)>> operations = {
+
+ [](keymaster::Buffer* buf, FuzzedDataProvider*) -> void {
+ // Just reading values, but there's some interesting
+ // integer manipulation here.
+ buf->begin();
+ buf->end();
+ },
+ [](keymaster::Buffer* buf, FuzzedDataProvider*) -> void { buf->Clear(); },
+ [](keymaster::Buffer* buf, FuzzedDataProvider* fdp) -> void {
+ buf->reserve(fdp->ConsumeIntegralInRange<int>(kMinBufferSize, kMaxBufferSize));
+ },
+ [](keymaster::Buffer* buf, FuzzedDataProvider* fdp) -> void {
+ buf->advance_read(fdp->ConsumeIntegral<int>());
+ },
+ [](keymaster::Buffer* buf, FuzzedDataProvider* fdp) -> void {
+ buf->advance_write(fdp->ConsumeIntegral<int>());
+ },
+ [](keymaster::Buffer* buf, FuzzedDataProvider* fdp) -> void {
+ buf->Reinitialize(fdp->ConsumeIntegralInRange<size_t>(kMinBufferSize, kMaxBufferSize));
+ },
+ [](keymaster::Buffer* buf, FuzzedDataProvider* fdp) -> void {
+ size_t buf_size = fdp->ConsumeIntegralInRange<size_t>(kMinBufferSize, kMaxBufferSize);
+ std::unique_ptr<uint8_t[]> in_buf = std::unique_ptr<uint8_t[]>(new uint8_t[buf_size]);
+ buf->Reinitialize(in_buf.get(), buf_size);
+ },
+ [](keymaster::Buffer* buf, FuzzedDataProvider* fdp) -> void {
+ uint16_t buf_size = fdp->ConsumeIntegralInRange<uint16_t>(kMinBufferSize, kMaxBufferSize);
+ std::unique_ptr<uint8_t[]> in_buf = std::unique_ptr<uint8_t[]>(new uint8_t[buf_size]);
+ const uint8_t* data_ptr = in_buf.get();
+ int32_t end = fdp->ConsumeIntegralInRange<int32_t>(0, buf_size);
+ buf->Deserialize(&data_ptr, data_ptr + end);
+ },
+ [](keymaster::Buffer* buf, FuzzedDataProvider* fdp) -> void {
+ uint16_t buf_size = buf->SerializedSize();
+ std::unique_ptr<uint8_t[]> out_buf = std::unique_ptr<uint8_t[]>(new uint8_t[buf_size]);
+ int32_t end = fdp->ConsumeIntegralInRange<int32_t>(0, buf_size);
+ buf->Serialize(out_buf.get(), out_buf.get() + end);
+ },
+ [](keymaster::Buffer* buf, FuzzedDataProvider* fdp) -> void {
+ uint16_t buf_size = fdp->ConsumeIntegralInRange<uint16_t>(kMinBufferSize, kMaxBufferSize);
+ std::vector<uint8_t> in_buf = fdp->ConsumeBytes<uint8_t>(buf_size);
+ buf->write(in_buf.data(), fdp->ConsumeIntegralInRange<int16_t>(0, buf_size));
+ },
+ [](keymaster::Buffer* buf, FuzzedDataProvider* fdp) -> void {
+ uint16_t buf_size = fdp->ConsumeIntegralInRange<uint16_t>(kMinBufferSize, kMaxBufferSize);
+ std::unique_ptr<uint8_t[]> out = std::unique_ptr<uint8_t[]>(new uint8_t[buf_size]);
+ buf->read(out.get(), fdp->ConsumeIntegralInRange<int16_t>(0, buf_size));
+ }};
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+ FuzzedDataProvider fdp(data, size);
+ uint16_t buf_size = fdp.ConsumeIntegralInRange<uint16_t>(kMinBufferSize, kMaxBufferSize);
+ keymaster::Buffer fuzzBuffer(buf_size);
+ for (size_t i = 0; i < kMaxOperations && fdp.remaining_bytes() > 0; i++) {
+ uint8_t op = fdp.ConsumeIntegralInRange<uint8_t>(0, operations.size() - 1);
+ operations[op](&fuzzBuffer, &fdp);
+ }
+ return 0;
+}
diff --git a/tests/fuzzers/message_serializable_fuzz.cpp b/tests/fuzzers/message_serializable_fuzz.cpp
new file mode 100644
index 0000000..11c3ff3
--- /dev/null
+++ b/tests/fuzzers/message_serializable_fuzz.cpp
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2020 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 <functional>
+#include <memory>
+
+#include <keymaster/serializable.h>
+
+#include "fuzzer/FuzzedDataProvider.h"
+#include "serializable_types.h"
+
+static constexpr uint16_t kMinBufferSize = 1;
+static constexpr uint16_t kMaxBufferSize = 2048;
+
+void RunDeserialize(keymaster::Serializable* ser, FuzzedDataProvider* fdp) {
+ uint16_t buf_size = fdp->ConsumeIntegralInRange<uint16_t>(kMinBufferSize, kMaxBufferSize);
+ std::unique_ptr<uint8_t[]> in_buf = std::unique_ptr<uint8_t[]>(new uint8_t[buf_size]);
+ const uint8_t* data_ptr = in_buf.get();
+ // memset((void*) data_ptr, 0x41, buf_size);
+ int32_t end = fdp->ConsumeIntegralInRange<int32_t>(0, buf_size);
+ ser->Deserialize(&data_ptr, data_ptr + end);
+}
+
+void RunSerialize(keymaster::Serializable* ser, FuzzedDataProvider* fdp) {
+ uint16_t buf_size = ser->SerializedSize();
+ std::unique_ptr<uint8_t[]> out_buf = std::unique_ptr<uint8_t[]>(new uint8_t[buf_size]);
+ // memset((void*) out_buf.get(), 0x41, buf_size);
+ int32_t end = fdp->ConsumeIntegralInRange<int32_t>(0, buf_size);
+ ser->Serialize(out_buf.get(), out_buf.get() + end);
+}
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+ FuzzedDataProvider fdp(data, size);
+ std::unique_ptr<keymaster::Serializable> serializable =
+ keymaster::getSerializable(fdp.ConsumeEnum<keymaster::SerializableType>());
+ /*if(fdp.remaining_bytes() > 1) {
+ RunDeserialize(serializable.get(), &fdp);
+ }*/
+ for (size_t i = 0; fdp.remaining_bytes() > 0; i++) {
+ if (fdp.ConsumeBool()) {
+ RunSerialize(serializable.get(), &fdp);
+ } else {
+ RunDeserialize(serializable.get(), &fdp);
+ }
+ }
+ return 0;
+}
diff --git a/tests/fuzzers/serializable_types.h b/tests/fuzzers/serializable_types.h
new file mode 100644
index 0000000..96dc4b3
--- /dev/null
+++ b/tests/fuzzers/serializable_types.h
@@ -0,0 +1,206 @@
+/*
+ * Copyright (C) 2020 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.
+ */
+
+#pragma once
+
+#include <keymaster/android_keymaster_messages.h>
+#include <keymaster/serializable.h>
+
+namespace keymaster {
+enum class SerializableType : uint32_t {
+ SUPPORTED_IMPORT_FORMATS_REQUEST,
+ SUPPORTED_EXPORT_FORMATS_REQUEST,
+ SUPPORTED_BLOCK_MODES_REQUEST,
+ SUPPORTED_PADDING_MODES_REQUEST,
+ SUPPORTED_DIGESTS_REQUEST,
+ SUPPORTED_ALGORITHMS_RESPONSE,
+ SUPPORTED_BLOCK_MODES_RESPONSE,
+ SUPPORTED_PADDING_MODES_RESPONSE,
+ SUPPORTED_DIGESTS_RESPONSE,
+ SUPPORTED_IMPORT_FORMATS_RESPONSE,
+ SUPPORTED_EXPORT_FORMATS_RESPONSE,
+ GENERATE_KEY_REQUEST,
+ GENERATE_KEY_RESPONSE,
+ GET_KEY_CHARACTERISTICS_REQUEST,
+ GET_KEY_CHARACTERISTICS_RESPONSE,
+ BEGIN_OPERATION_REQUEST,
+ BEGIN_OPERATION_RESPONSE,
+ UPDATE_OPERATION_REQUEST,
+ UPDATE_OPERATION_RESPONSE,
+ FINISH_OPERATION_REQUEST,
+ FINISH_OPERATION_RESPONSE,
+ ABORT_OPERATION_REQUEST,
+ ABORT_OPERATION_RESPONSE,
+ ADD_ENTROPY_REQUEST,
+ ADD_ENTROPY_RESPONSE,
+ IMPORT_KEY_REQUEST,
+ IMPORT_KEY_RESPONSE,
+ EXPORT_KEY_REQUEST,
+ EXPORT_KEY_RESPONSE,
+ DELETE_KEY_REQUEST,
+ DELETE_KEY_RESPONSE,
+ DELETE_ALL_KEYS_REQUEST,
+ DELETE_ALL_KEYS_RESPONSE,
+ GET_VERSION_REQUEST,
+ GET_VERSION_RESPONSE,
+ GET_VERSION2_REQUEST,
+ GET_VERSION2_RESPONSE,
+ ATTEST_KEY_REQUEST,
+ ATTEST_KEY_RESPONSE,
+ UPGRADE_KEY_REQUEST,
+ UPGRADE_KEY_RESPONSE,
+ CONFIGURE_REQUEST,
+ CONFIGURE_RESPONSE,
+ HMAC_SHARING_PARAMETERS,
+ HMAC_SHARING_PARAMETERS_ARRAY,
+ GET_HMAC_SHARING_PARAMETERS_RESPONSE,
+ COMPUTE_SHARED_HMAC_REQUEST,
+ COMPUTE_SHARED_HMAC_RESPONSE,
+ IMPORT_WRAPPED_KEY_REQUEST,
+ IMPORT_WRAPPED_KEY_RESPONSE,
+ HARDWARE_AUTH_TOKEN,
+ VERIFICATION_TOKEN,
+ VERIFY_AUTHORIZATION_REQUEST,
+ VERIFY_AUTHORIZATION_RESPONSE,
+ DEVICE_LOCKED_REQUEST,
+ BUFFER,
+ // Libfuzzer needs this to always be the last value
+ kMaxValue = BUFFER
+};
+
+std::unique_ptr<Serializable> getSerializable(SerializableType serType) {
+ switch (serType) {
+ case SerializableType::SUPPORTED_IMPORT_FORMATS_REQUEST:
+ return std::make_unique<SupportedImportFormatsRequest>(kMaxMessageVersion);
+ case SerializableType::SUPPORTED_EXPORT_FORMATS_REQUEST:
+ return std::make_unique<SupportedExportFormatsRequest>(kMaxMessageVersion);
+ case SerializableType::SUPPORTED_BLOCK_MODES_REQUEST:
+ return std::make_unique<SupportedBlockModesRequest>(kMaxMessageVersion);
+ case SerializableType::SUPPORTED_PADDING_MODES_REQUEST:
+ return std::make_unique<SupportedPaddingModesRequest>(kMaxMessageVersion);
+ case SerializableType::SUPPORTED_DIGESTS_REQUEST:
+ return std::make_unique<SupportedDigestsRequest>(kMaxMessageVersion);
+ case SerializableType::SUPPORTED_ALGORITHMS_RESPONSE:
+ return std::make_unique<SupportedAlgorithmsResponse>(kMaxMessageVersion);
+ case SerializableType::SUPPORTED_BLOCK_MODES_RESPONSE:
+ return std::make_unique<SupportedBlockModesResponse>(kMaxMessageVersion);
+ case SerializableType::SUPPORTED_PADDING_MODES_RESPONSE:
+ return std::make_unique<SupportedPaddingModesResponse>(kMaxMessageVersion);
+ case SerializableType::SUPPORTED_DIGESTS_RESPONSE:
+ return std::make_unique<SupportedDigestsResponse>(kMaxMessageVersion);
+ case SerializableType::SUPPORTED_IMPORT_FORMATS_RESPONSE:
+ return std::make_unique<SupportedImportFormatsResponse>(kMaxMessageVersion);
+ case SerializableType::SUPPORTED_EXPORT_FORMATS_RESPONSE:
+ return std::make_unique<SupportedExportFormatsResponse>(kMaxMessageVersion);
+ case SerializableType::GENERATE_KEY_REQUEST:
+ return std::make_unique<GenerateKeyRequest>(kMaxMessageVersion);
+ case SerializableType::GENERATE_KEY_RESPONSE:
+ return std::make_unique<GenerateKeyResponse>(kMaxMessageVersion);
+ case SerializableType::GET_KEY_CHARACTERISTICS_REQUEST:
+ return std::make_unique<GetKeyCharacteristicsRequest>(kMaxMessageVersion);
+ case SerializableType::GET_KEY_CHARACTERISTICS_RESPONSE:
+ return std::make_unique<GetKeyCharacteristicsResponse>(kMaxMessageVersion);
+ case SerializableType::BEGIN_OPERATION_REQUEST:
+ return std::make_unique<BeginOperationRequest>(kMaxMessageVersion);
+ case SerializableType::BEGIN_OPERATION_RESPONSE:
+ return std::make_unique<BeginOperationResponse>(kMaxMessageVersion);
+ case SerializableType::UPDATE_OPERATION_REQUEST:
+ return std::make_unique<UpdateOperationRequest>(kMaxMessageVersion);
+ case SerializableType::UPDATE_OPERATION_RESPONSE:
+ return std::make_unique<UpdateOperationResponse>(kMaxMessageVersion);
+ case SerializableType::FINISH_OPERATION_REQUEST:
+ return std::make_unique<FinishOperationRequest>(kMaxMessageVersion);
+ case SerializableType::FINISH_OPERATION_RESPONSE:
+ return std::make_unique<FinishOperationResponse>(kMaxMessageVersion);
+ case SerializableType::ABORT_OPERATION_REQUEST:
+ return std::make_unique<AbortOperationRequest>(kMaxMessageVersion);
+ case SerializableType::ABORT_OPERATION_RESPONSE:
+ return std::make_unique<AbortOperationResponse>(kMaxMessageVersion);
+ case SerializableType::ADD_ENTROPY_REQUEST:
+ return std::make_unique<AddEntropyRequest>(kMaxMessageVersion);
+ case SerializableType::ADD_ENTROPY_RESPONSE:
+ return std::make_unique<AddEntropyResponse>(kMaxMessageVersion);
+ case SerializableType::IMPORT_KEY_REQUEST:
+ return std::make_unique<ImportKeyRequest>(kMaxMessageVersion);
+ case SerializableType::IMPORT_KEY_RESPONSE:
+ return std::make_unique<ImportKeyResponse>(kMaxMessageVersion);
+ case SerializableType::EXPORT_KEY_REQUEST:
+ return std::make_unique<ExportKeyRequest>(kMaxMessageVersion);
+ case SerializableType::EXPORT_KEY_RESPONSE:
+ return std::make_unique<ExportKeyResponse>(kMaxMessageVersion);
+ case SerializableType::DELETE_KEY_REQUEST:
+ return std::make_unique<DeleteKeyRequest>(kMaxMessageVersion);
+ case SerializableType::DELETE_KEY_RESPONSE:
+ return std::make_unique<DeleteKeyResponse>(kMaxMessageVersion);
+ case SerializableType::DELETE_ALL_KEYS_REQUEST:
+ return std::make_unique<DeleteAllKeysRequest>(kMaxMessageVersion);
+ case SerializableType::DELETE_ALL_KEYS_RESPONSE:
+ return std::make_unique<DeleteAllKeysResponse>(kMaxMessageVersion);
+ case SerializableType::GET_VERSION_REQUEST:
+ // Not versionable
+ return std::make_unique<GetVersionRequest>();
+ case SerializableType::GET_VERSION_RESPONSE:
+ // Not versionable
+ return std::make_unique<GetVersionResponse>();
+ case SerializableType::GET_VERSION2_REQUEST:
+ // Not versionable
+ return std::make_unique<GetVersion2Request>();
+ case SerializableType::GET_VERSION2_RESPONSE:
+ // Not versionable
+ return std::make_unique<GetVersion2Response>();
+ case SerializableType::ATTEST_KEY_REQUEST:
+ return std::make_unique<AttestKeyRequest>(kMaxMessageVersion);
+ case SerializableType::ATTEST_KEY_RESPONSE:
+ return std::make_unique<AttestKeyResponse>(kMaxMessageVersion);
+ case SerializableType::UPGRADE_KEY_REQUEST:
+ return std::make_unique<UpgradeKeyRequest>(kMaxMessageVersion);
+ case SerializableType::UPGRADE_KEY_RESPONSE:
+ return std::make_unique<UpgradeKeyResponse>(kMaxMessageVersion);
+ case SerializableType::CONFIGURE_REQUEST:
+ return std::make_unique<ConfigureRequest>(kMaxMessageVersion);
+ case SerializableType::CONFIGURE_RESPONSE:
+ return std::make_unique<ConfigureResponse>(kMaxMessageVersion);
+ case SerializableType::DEVICE_LOCKED_REQUEST:
+ return std::make_unique<DeviceLockedRequest>(kMaxMessageVersion);
+ case SerializableType::GET_HMAC_SHARING_PARAMETERS_RESPONSE:
+ return std::make_unique<GetHmacSharingParametersResponse>(kMaxMessageVersion);
+ case SerializableType::COMPUTE_SHARED_HMAC_REQUEST:
+ return std::make_unique<ComputeSharedHmacRequest>(kMaxMessageVersion);
+ case SerializableType::COMPUTE_SHARED_HMAC_RESPONSE:
+ return std::make_unique<ComputeSharedHmacResponse>(kMaxMessageVersion);
+ case SerializableType::IMPORT_WRAPPED_KEY_REQUEST:
+ return std::make_unique<ImportWrappedKeyRequest>(kMaxMessageVersion);
+ case SerializableType::IMPORT_WRAPPED_KEY_RESPONSE:
+ return std::make_unique<ImportWrappedKeyResponse>(kMaxMessageVersion);
+ case SerializableType::VERIFY_AUTHORIZATION_REQUEST:
+ return std::make_unique<VerifyAuthorizationRequest>(kMaxMessageVersion);
+ case SerializableType::VERIFY_AUTHORIZATION_RESPONSE:
+ return std::make_unique<VerifyAuthorizationResponse>(kMaxMessageVersion);
+
+ // These are not messages, and expect an empty constructor.
+ case SerializableType::HMAC_SHARING_PARAMETERS:
+ return std::make_unique<HmacSharingParameters>();
+ case SerializableType::HMAC_SHARING_PARAMETERS_ARRAY:
+ return std::make_unique<HmacSharingParametersArray>();
+ case SerializableType::HARDWARE_AUTH_TOKEN:
+ return std::make_unique<HardwareAuthToken>();
+ case SerializableType::VERIFICATION_TOKEN:
+ return std::make_unique<VerificationToken>();
+ case SerializableType::BUFFER:
+ return std::make_unique<Buffer>();
+ }
+}
+} // namespace keymaster
diff --git a/tests/gtest_main.cpp b/tests/gtest_main.cpp
index 6072749..dfa9357 100644
--- a/tests/gtest_main.cpp
+++ b/tests/gtest_main.cpp
@@ -21,7 +21,7 @@
int main(int argc, char** argv) {
#if !defined(OPENSSL_IS_BORINGSSL)
ERR_load_crypto_strings();
-#endif // not OPENSSL_IS_BORINGSSL
+#endif // not OPENSSL_IS_BORINGSSL
::testing::InitGoogleTest(&argc, argv);
int result = RUN_ALL_TESTS();
#if !defined(OPENSSL_IS_BORINGSSL)
@@ -29,6 +29,6 @@
CRYPTO_cleanup_all_ex_data();
ERR_remove_thread_state(NULL);
ERR_free_strings();
-#endif // not OPENSSL_IS_BORINGSSL
+#endif // not OPENSSL_IS_BORINGSSL
return result;
}
diff --git a/tests/hkdf_test.cpp b/tests/hkdf_test.cpp
index 69ddd08..fb210eb 100644
--- a/tests/hkdf_test.cpp
+++ b/tests/hkdf_test.cpp
@@ -37,7 +37,8 @@
// https://tools.ietf.org/html/rfc5869#appendix-A.
static const HkdfTest kHkdfTests[] = {
{
- "0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b", "000102030405060708090a0b0c",
+ "0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b",
+ "000102030405060708090a0b0c",
"f0f1f2f3f4f5f6f7f8f9",
"3cb25f25faacd57a90434f64d0362f2a2d2d0a90cf1a5a4c5db02d56ecc4c5bf34007208d5b887185865",
},
@@ -52,7 +53,9 @@
"590e09da3275600c2f09b8367793a9aca3db71cc30c58179ec3e87c14c01d5c1f3434f1d87",
},
{
- "0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b", "", "",
+ "0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b",
+ "",
+ "",
"8da4e775a563c18f715f802a063c5a31b8a11f5c5ee1879ec3454e5f3c738d2d9d201395faa4b61a96c8",
},
};
diff --git a/tests/hmac_test.cpp b/tests/hmac_test.cpp
index 9802e00..2413380 100644
--- a/tests/hmac_test.cpp
+++ b/tests/hmac_test.cpp
@@ -41,9 +41,9 @@
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
{
- 0x60, 0xe4, 0x31, 0x59, 0x1e, 0xe0, 0xb6, 0x7f, 0x0d, 0x8a, 0x26, 0xaa, 0xcb, 0xf5,
- 0xb7, 0x7f, 0x8e, 0x0b, 0xc6, 0x21, 0x37, 0x28, 0xc5, 0x14, 0x05, 0x46, 0x04, 0x0f,
- 0x0e, 0xe3, 0x7f, 0x54,
+ 0x60, 0xe4, 0x31, 0x59, 0x1e, 0xe0, 0xb6, 0x7f, 0x0d, 0x8a, 0x26,
+ 0xaa, 0xcb, 0xf5, 0xb7, 0x7f, 0x8e, 0x0b, 0xc6, 0x21, 0x37, 0x28,
+ 0xc5, 0x14, 0x05, 0x46, 0x04, 0x0f, 0x0e, 0xe3, 0x7f, 0x54,
},
},
{
@@ -51,9 +51,9 @@
"46697265666f7820616e64205468756e64657242697264206172652061776573"
"6f6d652100",
{
- 0x05, 0x75, 0x9a, 0x9e, 0x70, 0x5e, 0xe7, 0x44, 0xe2, 0x46, 0x4b, 0x92, 0x22, 0x14,
- 0x22, 0xe0, 0x1b, 0x92, 0x8a, 0x0c, 0xfe, 0xf5, 0x49, 0xe9, 0xa7, 0x1b, 0x56, 0x7d,
- 0x1d, 0x29, 0x40, 0x48,
+ 0x05, 0x75, 0x9a, 0x9e, 0x70, 0x5e, 0xe7, 0x44, 0xe2, 0x46, 0x4b,
+ 0x92, 0x22, 0x14, 0x22, 0xe0, 0x1b, 0x92, 0x8a, 0x0c, 0xfe, 0xf5,
+ 0x49, 0xe9, 0xa7, 0x1b, 0x56, 0x7d, 0x1d, 0x29, 0x40, 0x48,
},
},
};
diff --git a/tests/kdf1_test.cpp b/tests/kdf1_test.cpp
index b01143d..5881529 100644
--- a/tests/kdf1_test.cpp
+++ b/tests/kdf1_test.cpp
@@ -14,8 +14,8 @@
* limitations under the License.
*/
-#include <keymaster/km_openssl/kdf1.h>
#include <gtest/gtest.h>
+#include <keymaster/km_openssl/kdf1.h>
#include <string.h>
#include "android_keymaster_test_utils.h"
diff --git a/tests/kdf2_test.cpp b/tests/kdf2_test.cpp
index c300186..d022c10 100644
--- a/tests/kdf2_test.cpp
+++ b/tests/kdf2_test.cpp
@@ -14,8 +14,8 @@
* limitations under the License.
*/
-#include <keymaster/km_openssl/kdf2.h>
#include <gtest/gtest.h>
+#include <keymaster/km_openssl/kdf2.h>
#include <string.h>
#include "android_keymaster_test_utils.h"
diff --git a/tests/kdf_test.cpp b/tests/kdf_test.cpp
index 19c96ef..2c5a43f 100644
--- a/tests/kdf_test.cpp
+++ b/tests/kdf_test.cpp
@@ -14,8 +14,8 @@
* limitations under the License.
*/
-#include <keymaster/km_openssl/kdf.h>
#include <gtest/gtest.h>
+#include <keymaster/km_openssl/kdf.h>
namespace keymaster {
diff --git a/tests/key_blob_test.cpp b/tests/key_blob_test.cpp
index 5c1458b..35d3aa6 100644
--- a/tests/key_blob_test.cpp
+++ b/tests/key_blob_test.cpp
@@ -21,12 +21,12 @@
#include <openssl/engine.h>
#include <openssl/rand.h>
-#include <keymaster/authorization_set.h>
#include <keymaster/android_keymaster_utils.h>
-#include <keymaster/keymaster_tags.h>
+#include <keymaster/authorization_set.h>
#include <keymaster/key_blob_utils/auth_encrypted_key_blob.h>
#include <keymaster/key_blob_utils/integrity_assured_key_blob.h>
-#include <keymaster/key_blob_utils/ocb_utils.h>
+#include <keymaster/keymaster_tags.h>
+#include <keymaster/km_openssl/software_random_source.h>
#include "android_keymaster_test_utils.h"
@@ -34,14 +34,18 @@
namespace test {
-const uint8_t master_key_data[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+namespace {
+
+const uint8_t master_key_data[16] = {};
const uint8_t key_data[5] = {21, 22, 23, 24, 25};
-class KeyBlobTest : public testing::Test {
+} // namespace
+
+class KeyBlobTest : public testing::Test, public SoftwareRandomSource {
protected:
KeyBlobTest()
- : master_key_(master_key_data, array_length(master_key_data)),
- key_material_(key_data, array_length(key_data)) {
+ : key_material_(key_data, array_length(key_data)),
+ master_key_(master_key_data, array_length(master_key_data)) {
hw_enforced_.push_back(TAG_ALGORITHM, KM_ALGORITHM_RSA);
hw_enforced_.push_back(TAG_KEY_SIZE, 256);
hw_enforced_.push_back(TAG_BLOB_USAGE_REQUIREMENTS, KM_BLOB_STANDALONE);
@@ -56,72 +60,83 @@
hidden_.push_back(TAG_ROOT_OF_TRUST, "foo", 3);
hidden_.push_back(TAG_APPLICATION_ID, "my_app", 6);
-
- nonce_.reserve(OCB_NONCE_LENGTH);
- EXPECT_EQ(1, RAND_bytes(nonce_.peek_write(), OCB_NONCE_LENGTH));
- nonce_.advance_write(OCB_NONCE_LENGTH);
-
- tag_.reserve(OCB_TAG_LENGTH);
}
- keymaster_error_t Encrypt() {
- return OcbEncryptKey(hw_enforced_, sw_enforced_, hidden_, master_key_, key_material_,
- nonce_, &ciphertext_, &tag_);
+ keymaster_error_t Encrypt(AuthEncryptedBlobFormat format = AES_GCM_WITH_SW_ENFORCED) {
+ keymaster_error_t error;
+ encrypted_key_ = EncryptKey(key_material_, format, hw_enforced_, sw_enforced_, hidden_,
+ master_key_, *this, &error);
+ return error;
}
keymaster_error_t Decrypt() {
- return OcbDecryptKey(hw_enforced_, sw_enforced_, hidden_, master_key_, ciphertext_, nonce_,
- tag_, &decrypted_plaintext_);
+ keymaster_error_t error;
+ decrypted_plaintext_ = DecryptKey(move(deserialized_key_), hidden_, master_key_, &error);
+ return error;
}
keymaster_error_t Serialize() {
- return SerializeAuthEncryptedBlob(ciphertext_, hw_enforced_, sw_enforced_, nonce_, tag_,
- &serialized_blob_);
+ keymaster_error_t error;
+ serialized_blob_ =
+ SerializeAuthEncryptedBlob(encrypted_key_, hw_enforced_, sw_enforced_, &error);
+ return error;
}
keymaster_error_t Deserialize() {
- return DeserializeAuthEncryptedBlob(serialized_blob_, &ciphertext_, &hw_enforced_,
- &sw_enforced_, &nonce_, &tag_);
+ keymaster_error_t error;
+ deserialized_key_ = DeserializeAuthEncryptedBlob(serialized_blob_, &error);
+ return error;
}
+ // Encryption inputs
AuthorizationSet hw_enforced_;
AuthorizationSet sw_enforced_;
AuthorizationSet hidden_;
- Buffer nonce_, tag_;
-
- KeymasterKeyBlob master_key_;
KeymasterKeyBlob key_material_;
- KeymasterKeyBlob ciphertext_;
- KeymasterKeyBlob decrypted_plaintext_;
+ KeymasterKeyBlob master_key_;
+
+ // Encryption output
+ EncryptedKey encrypted_key_;
+
+ // Serialization output
KeymasterKeyBlob serialized_blob_;
+
+ // Deserialization output
+ DeserializedKey deserialized_key_;
+
+ // Decryption output.
+ KeymasterKeyBlob decrypted_plaintext_;
};
TEST_F(KeyBlobTest, EncryptDecrypt) {
- ASSERT_EQ(KM_ERROR_OK, Encrypt());
- ASSERT_EQ(KM_ERROR_OK, Serialize());
+ for (auto format : {AES_OCB, AES_GCM_WITH_SW_ENFORCED}) {
+ ASSERT_EQ(KM_ERROR_OK, Encrypt(format));
+ ASSERT_EQ(KM_ERROR_OK, Serialize());
- // key_data shouldn't be anywhere in the blob, ciphertext should.
- EXPECT_EQ(serialized_blob_.end(), std::search(serialized_blob_.begin(), serialized_blob_.end(),
- key_material_.begin(), key_material_.end()));
- EXPECT_NE(serialized_blob_.end(), std::search(serialized_blob_.begin(), serialized_blob_.end(),
- ciphertext_.begin(), ciphertext_.end()));
+ // key_data shouldn't be anywhere in the blob, ciphertext should.
+ EXPECT_EQ(serialized_blob_.end(),
+ std::search(serialized_blob_.begin(), serialized_blob_.end(),
+ key_material_.begin(), key_material_.end()));
+ EXPECT_NE(serialized_blob_.end(),
+ std::search(serialized_blob_.begin(), serialized_blob_.end(),
+ encrypted_key_.ciphertext.begin(), encrypted_key_.ciphertext.end()));
- ciphertext_.Clear();
- nonce_.Clear();
- tag_.Clear();
- AuthorizationSet hw2;
- AuthorizationSet sw2;
+ keymaster_error_t error;
+ DeserializedKey deserialized = DeserializeAuthEncryptedBlob(serialized_blob_, &error);
+ ASSERT_EQ(KM_ERROR_OK, error);
+ EXPECT_EQ(hw_enforced_, deserialized.hw_enforced);
+ switch (format) {
+ case AES_OCB:
+ case AES_GCM_WITH_SW_ENFORCED:
+ EXPECT_EQ(sw_enforced_, deserialized.sw_enforced);
+ break;
+ }
- ASSERT_EQ(KM_ERROR_OK, DeserializeAuthEncryptedBlob(serialized_blob_, &ciphertext_, &hw2, &sw2,
- &nonce_, &tag_));
- KeymasterKeyBlob plaintext;
- OcbDecryptKey(hw2, sw2, hidden_, master_key_, ciphertext_, nonce_, tag_, &plaintext);
+ KeymasterKeyBlob plaintext = DecryptKey(move(deserialized), hidden_, master_key_, &error);
- EXPECT_EQ(hw_enforced_, hw2);
- EXPECT_EQ(sw_enforced_, sw2);
-
- ASSERT_EQ(key_material_.key_material_size, plaintext.key_material_size);
- EXPECT_EQ(0, memcmp(plaintext.begin(), key_material_.begin(), plaintext.key_material_size));
+ ASSERT_EQ(key_material_.size(), plaintext.size());
+ EXPECT_TRUE(std::equal(key_material_.begin(), key_material_.end(), plaintext.begin()));
+ }
}
TEST_F(KeyBlobTest, WrongKeyLength) {
@@ -139,11 +154,9 @@
ASSERT_EQ(KM_ERROR_OK, Serialize());
// Find the nonce, then modify it.
- auto nonce_ptr =
- std::search(serialized_blob_.begin(), serialized_blob_.end(), nonce_.begin(), nonce_.end());
+ auto nonce_ptr = std::search(serialized_blob_.begin(), serialized_blob_.end(),
+ encrypted_key_.nonce.begin(), encrypted_key_.nonce.end());
ASSERT_NE(nonce_ptr, serialized_blob_.end());
- EXPECT_EQ(serialized_blob_.end(),
- std::search(nonce_ptr + 1, serialized_blob_.end(), nonce_.begin(), nonce_.end()));
(*const_cast<uint8_t*>(nonce_ptr))++;
// Deserialization shouldn't be affected, but decryption should fail.
@@ -155,12 +168,10 @@
ASSERT_EQ(KM_ERROR_OK, Encrypt());
ASSERT_EQ(KM_ERROR_OK, Serialize());
- // Find the tag, them modify it.
- auto tag_ptr =
- std::search(serialized_blob_.begin(), serialized_blob_.end(), tag_.begin(), tag_.end());
+ // Find the tag, then modify it.
+ auto tag_ptr = std::search(serialized_blob_.begin(), serialized_blob_.end(),
+ encrypted_key_.tag.begin(), encrypted_key_.tag.end());
ASSERT_NE(tag_ptr, serialized_blob_.end());
- EXPECT_EQ(serialized_blob_.end(),
- std::search(tag_ptr + 1, serialized_blob_.end(), tag_.begin(), tag_.end()));
(*const_cast<uint8_t*>(tag_ptr))++;
// Deserialization shouldn't be affected, but decryption should fail.
@@ -172,12 +183,11 @@
ASSERT_EQ(KM_ERROR_OK, Encrypt());
ASSERT_EQ(KM_ERROR_OK, Serialize());
- // Find the ciphertext, them modify it.
- auto ciphertext_ptr = std::search(serialized_blob_.begin(), serialized_blob_.end(),
- ciphertext_.begin(), ciphertext_.end());
+ // Find the ciphertext, then modify it.
+ auto ciphertext_ptr =
+ std::search(serialized_blob_.begin(), serialized_blob_.end(),
+ encrypted_key_.ciphertext.begin(), encrypted_key_.ciphertext.end());
ASSERT_NE(ciphertext_ptr, serialized_blob_.end());
- EXPECT_EQ(serialized_blob_.end(), std::search(ciphertext_ptr + 1, serialized_blob_.end(),
- ciphertext_.begin(), ciphertext_.end()));
(*const_cast<uint8_t*>(ciphertext_ptr))++;
// Deserialization shouldn't be affected, but decryption should fail.
@@ -194,9 +204,10 @@
// Decrypting with wrong master key should fail.
ASSERT_EQ(KM_ERROR_OK, Deserialize());
- ASSERT_EQ(KM_ERROR_INVALID_KEY_BLOB,
- OcbDecryptKey(hw_enforced_, sw_enforced_, hidden_, wrong_master, ciphertext_, nonce_,
- tag_, &decrypted_plaintext_));
+ keymaster_error_t error;
+ DecryptKey(move(deserialized_key_), hidden_, wrong_master, &error);
+
+ ASSERT_EQ(KM_ERROR_INVALID_KEY_BLOB, error);
}
TEST_F(KeyBlobTest, WrongHwEnforced) {
@@ -212,9 +223,6 @@
std::search(serialized_blob_.begin(), serialized_blob_.end(), hw_enforced_data.get(),
hw_enforced_data.get() + hw_enforced_size);
ASSERT_NE(serialized_blob_.end(), hw_enforced_ptr);
- EXPECT_EQ(serialized_blob_.end(),
- std::search(hw_enforced_ptr + 1, serialized_blob_.end(), hw_enforced_data.get(),
- hw_enforced_data.get() + hw_enforced_size));
(*(const_cast<uint8_t*>(hw_enforced_ptr) + hw_enforced_size - 1))++;
// Deserialization shouldn't be affected, but decryption should fail.
@@ -223,26 +231,25 @@
}
TEST_F(KeyBlobTest, WrongSwEnforced) {
- ASSERT_EQ(KM_ERROR_OK, Encrypt());
- ASSERT_EQ(KM_ERROR_OK, Serialize());
+ for (auto format : {AES_OCB, AES_GCM_WITH_SW_ENFORCED}) {
+ ASSERT_EQ(KM_ERROR_OK, Encrypt(format));
+ ASSERT_EQ(KM_ERROR_OK, Serialize());
- // Find enforced serialization data and modify it.
- size_t sw_enforced_size = sw_enforced_.SerializedSize();
- UniquePtr<uint8_t[]> sw_enforced_data(new uint8_t[sw_enforced_size]);
- sw_enforced_.Serialize(sw_enforced_data.get(), sw_enforced_data.get() + sw_enforced_size);
+ // Find enforced serialization data and modify it.
+ size_t sw_enforced_size = sw_enforced_.SerializedSize();
+ UniquePtr<uint8_t[]> sw_enforced_data(new uint8_t[sw_enforced_size]);
+ sw_enforced_.Serialize(sw_enforced_data.get(), sw_enforced_data.get() + sw_enforced_size);
- auto sw_enforced_ptr =
- std::search(serialized_blob_.begin(), serialized_blob_.end(), sw_enforced_data.get(),
- sw_enforced_data.get() + sw_enforced_size);
- ASSERT_NE(serialized_blob_.end(), sw_enforced_ptr);
- EXPECT_EQ(serialized_blob_.end(),
- std::search(sw_enforced_ptr + 1, serialized_blob_.end(), sw_enforced_data.get(),
- sw_enforced_data.get() + sw_enforced_size));
- (*(const_cast<uint8_t*>(sw_enforced_ptr) + sw_enforced_size - 1))++;
+ auto sw_enforced_ptr =
+ std::search(serialized_blob_.begin(), serialized_blob_.end(), sw_enforced_data.get(),
+ sw_enforced_data.get() + sw_enforced_size);
+ ASSERT_NE(serialized_blob_.end(), sw_enforced_ptr);
+ (*(const_cast<uint8_t*>(sw_enforced_ptr) + sw_enforced_size - 1))++;
- // Deserialization shouldn't be affected, but decryption should fail.
- ASSERT_EQ(KM_ERROR_OK, Deserialize());
- ASSERT_EQ(KM_ERROR_INVALID_KEY_BLOB, Decrypt());
+ // Deserialization shouldn't be affected, but decryption should fail.
+ ASSERT_EQ(KM_ERROR_OK, Deserialize());
+ ASSERT_EQ(KM_ERROR_INVALID_KEY_BLOB, Decrypt());
+ }
}
TEST_F(KeyBlobTest, EmptyHidden) {
@@ -253,9 +260,9 @@
// Deserialization shouldn't be affected, but decryption should fail.
ASSERT_EQ(KM_ERROR_OK, Deserialize());
- EXPECT_EQ(KM_ERROR_INVALID_KEY_BLOB,
- OcbDecryptKey(hw_enforced_, sw_enforced_, wrong_hidden, master_key_, ciphertext_,
- nonce_, tag_, &decrypted_plaintext_));
+ keymaster_error_t error;
+ DecryptKey(move(deserialized_key_), wrong_hidden, master_key_, &error);
+ EXPECT_EQ(KM_ERROR_INVALID_KEY_BLOB, error);
}
TEST_F(KeyBlobTest, WrongRootOfTrust) {
@@ -268,9 +275,9 @@
// Deserialization shouldn't be affected, but decryption should fail.
ASSERT_EQ(KM_ERROR_OK, Deserialize());
- EXPECT_EQ(KM_ERROR_INVALID_KEY_BLOB,
- OcbDecryptKey(hw_enforced_, sw_enforced_, wrong_hidden, master_key_, ciphertext_,
- nonce_, tag_, &decrypted_plaintext_));
+ keymaster_error_t error;
+ DecryptKey(move(deserialized_key_), wrong_hidden, master_key_, &error);
+ EXPECT_EQ(KM_ERROR_INVALID_KEY_BLOB, error);
}
TEST_F(KeyBlobTest, WrongAppId) {
@@ -283,9 +290,9 @@
// Deserialization shouldn't be affected, but decryption should fail.
ASSERT_EQ(KM_ERROR_OK, Deserialize());
- EXPECT_EQ(KM_ERROR_INVALID_KEY_BLOB,
- OcbDecryptKey(hw_enforced_, sw_enforced_, wrong_hidden, master_key_, ciphertext_,
- nonce_, tag_, &decrypted_plaintext_));
+ keymaster_error_t error;
+ DecryptKey(move(deserialized_key_), wrong_hidden, master_key_, &error);
+ EXPECT_EQ(KM_ERROR_INVALID_KEY_BLOB, error);
}
// This test is especially useful when compiled for 32-bit mode and run under valgrind.
@@ -311,14 +318,13 @@
DeserializeIntegrityAssuredBlob(key_blob, hidden_, &key_material_, &hw_enforced_,
&sw_enforced_));
- // Auth-encrypted OCB blob.
- keymaster_error_t error = DeserializeAuthEncryptedBlob(
- key_blob, &ciphertext_, &hw_enforced_, &sw_enforced_, &nonce_, &tag_);
+ // Auth-encrypted blob.
+ keymaster_error_t error;
+ auto deserialized = DeserializeAuthEncryptedBlob(key_blob, &error);
if (error == KM_ERROR_OK) {
// It's possible to deserialize successfully. Decryption should always fail.
++deserialize_auth_encrypted_success;
- error = OcbDecryptKey(hw_enforced_, sw_enforced_, hidden_, master_key_, ciphertext_,
- nonce_, tag_, &decrypted_plaintext_);
+ DecryptKey(move(deserialized), hidden_, master_key_, &error);
}
ASSERT_EQ(KM_ERROR_INVALID_KEY_BLOB, error)
<< "Somehow sucessfully parsed a blob with seed " << now << " at offset " << i;
@@ -336,9 +342,9 @@
DeserializeIntegrityAssuredBlob(key_blob, hidden_, &key_material_, &hw_enforced_,
&sw_enforced_));
- EXPECT_EQ(KM_ERROR_INVALID_KEY_BLOB,
- DeserializeAuthEncryptedBlob(key_blob, &ciphertext_, &hw_enforced_, &sw_enforced_,
- &nonce_, &tag_));
+ keymaster_error_t error;
+ DeserializeAuthEncryptedBlob(key_blob, &error);
+ EXPECT_EQ(KM_ERROR_INVALID_KEY_BLOB, error);
}
TEST_F(KeyBlobTest, DupBufferToolarge) {
@@ -353,9 +359,9 @@
DeserializeIntegrityAssuredBlob(key_blob, hidden_, &key_material_, &hw_enforced_,
&sw_enforced_));
- EXPECT_EQ(KM_ERROR_INVALID_KEY_BLOB,
- DeserializeAuthEncryptedBlob(key_blob, &ciphertext_, &hw_enforced_, &sw_enforced_,
- &nonce_, &tag_));
+ keymaster_error_t error;
+ DeserializeAuthEncryptedBlob(key_blob, &error);
+ EXPECT_EQ(KM_ERROR_INVALID_KEY_BLOB, error);
}
} // namespace test
diff --git a/tests/keymaster_enforcement_test.cpp b/tests/keymaster_enforcement_test.cpp
index d446b32..341f0d7 100644
--- a/tests/keymaster_enforcement_test.cpp
+++ b/tests/keymaster_enforcement_test.cpp
@@ -27,9 +27,9 @@
namespace keymaster {
namespace test {
-class TestKeymasterEnforcement : public SoftKeymasterEnforcement {
+class EnforcementTestKeymasterEnforcement : public SoftKeymasterEnforcement {
public:
- TestKeymasterEnforcement()
+ EnforcementTestKeymasterEnforcement()
: SoftKeymasterEnforcement(3, 3), current_time_(10000), report_token_valid_(true) {}
keymaster_error_t AuthorizeOperation(const keymaster_purpose_t purpose, const km_id_t keyid,
@@ -82,7 +82,7 @@
}
virtual ~KeymasterBaseTest() {}
- TestKeymasterEnforcement kmen;
+ EnforcementTestKeymasterEnforcement kmen;
tm past_tm;
tm* future_tm;
@@ -107,8 +107,10 @@
TEST_F(KeymasterBaseTest, TestInvalidActiveTime) {
keymaster_key_param_t params[] = {
- Authorization(TAG_ALGORITHM, KM_ALGORITHM_RSA), Authorization(TAG_PURPOSE, KM_PURPOSE_SIGN),
- Authorization(TAG_NO_AUTH_REQUIRED), Authorization(TAG_ACTIVE_DATETIME, future_time),
+ Authorization(TAG_ALGORITHM, KM_ALGORITHM_RSA),
+ Authorization(TAG_PURPOSE, KM_PURPOSE_SIGN),
+ Authorization(TAG_NO_AUTH_REQUIRED),
+ Authorization(TAG_ACTIVE_DATETIME, future_time),
};
AuthorizationSet auth_set(params, array_length(params));
@@ -123,7 +125,8 @@
TEST_F(KeymasterBaseTest, TestValidActiveTime) {
keymaster_key_param_t params[] = {
- Authorization(TAG_PURPOSE, KM_PURPOSE_SIGN), Authorization(TAG_ACTIVE_DATETIME, past_time),
+ Authorization(TAG_PURPOSE, KM_PURPOSE_SIGN),
+ Authorization(TAG_ACTIVE_DATETIME, past_time),
};
AuthorizationSet auth_set(params, array_length(params));
@@ -135,7 +138,8 @@
TEST_F(KeymasterBaseTest, TestInvalidOriginationExpireTime) {
keymaster_key_param_t params[] = {
- Authorization(TAG_ALGORITHM, KM_ALGORITHM_RSA), Authorization(TAG_PURPOSE, KM_PURPOSE_SIGN),
+ Authorization(TAG_ALGORITHM, KM_ALGORITHM_RSA),
+ Authorization(TAG_PURPOSE, KM_PURPOSE_SIGN),
Authorization(TAG_ORIGINATION_EXPIRE_DATETIME, past_time),
};
@@ -248,7 +252,8 @@
TEST_F(KeymasterBaseTest, TestInvalidMaxOps) {
keymaster_key_param_t params[] = {
- Authorization(TAG_PURPOSE, KM_PURPOSE_SIGN), Authorization(TAG_ALGORITHM, KM_ALGORITHM_RSA),
+ Authorization(TAG_PURPOSE, KM_PURPOSE_SIGN),
+ Authorization(TAG_ALGORITHM, KM_ALGORITHM_RSA),
Authorization(TAG_MAX_USES_PER_BOOT, 4),
};
@@ -271,7 +276,8 @@
TEST_F(KeymasterBaseTest, TestOverFlowMaxOpsTable) {
keymaster_key_param_t params[] = {
- Authorization(TAG_ALGORITHM, KM_ALGORITHM_RSA), Authorization(TAG_PURPOSE, KM_PURPOSE_SIGN),
+ Authorization(TAG_ALGORITHM, KM_ALGORITHM_RSA),
+ Authorization(TAG_PURPOSE, KM_PURPOSE_SIGN),
Authorization(TAG_MAX_USES_PER_BOOT, 2),
};
@@ -311,7 +317,8 @@
TEST_F(KeymasterBaseTest, TestInvalidTimeBetweenOps) {
keymaster_key_param_t params[] = {
- Authorization(TAG_ALGORITHM, KM_ALGORITHM_RSA), Authorization(TAG_PURPOSE, KM_PURPOSE_SIGN),
+ Authorization(TAG_ALGORITHM, KM_ALGORITHM_RSA),
+ Authorization(TAG_PURPOSE, KM_PURPOSE_SIGN),
Authorization(TAG_MIN_SECONDS_BETWEEN_OPS, 10),
};
@@ -334,7 +341,8 @@
TEST_F(KeymasterBaseTest, TestValidTimeBetweenOps) {
keymaster_key_param_t params[] = {
- Authorization(TAG_PURPOSE, KM_PURPOSE_SIGN), Authorization(TAG_PURPOSE, KM_PURPOSE_VERIFY),
+ Authorization(TAG_PURPOSE, KM_PURPOSE_SIGN),
+ Authorization(TAG_PURPOSE, KM_PURPOSE_VERIFY),
Authorization(TAG_MIN_SECONDS_BETWEEN_OPS, 2),
};
@@ -455,7 +463,8 @@
TEST_F(KeymasterBaseTest, TestPubkeyOptTimeoutTableOverflow) {
keymaster_key_param_t params[] = {
Authorization(TAG_ALGORITHM, KM_ALGORITHM_RSA),
- Authorization(TAG_MIN_SECONDS_BETWEEN_OPS, 4), Authorization(TAG_PURPOSE, KM_PURPOSE_SIGN),
+ Authorization(TAG_MIN_SECONDS_BETWEEN_OPS, 4),
+ Authorization(TAG_PURPOSE, KM_PURPOSE_SIGN),
};
AuthorizationSet auth_set(params, array_length(params));
diff --git a/tests/nist_curve_key_exchange_test.cpp b/tests/nist_curve_key_exchange_test.cpp
index 270f231..798c91c 100644
--- a/tests/nist_curve_key_exchange_test.cpp
+++ b/tests/nist_curve_key_exchange_test.cpp
@@ -29,8 +29,6 @@
namespace keymaster {
namespace test {
-StdoutLogger logger;
-
static const keymaster_ec_curve_t kEcCurves[] = {KM_EC_CURVE_P_224, KM_EC_CURVE_P_256,
KM_EC_CURVE_P_384, KM_EC_CURVE_P_521};
@@ -69,7 +67,7 @@
* a point not on the curve.)
* The expected result of such a protocol should be that the
* key agreement fails and returns an error.
-*/
+ */
static const char* kInvalidPublicKeys[] = {
"04" // uncompressed public key
"deadbeef7f56584c5cc632ca65640db91b6bacce3a4df6b42ce7cc838833d287"
@@ -151,9 +149,10 @@
"46fc62106420ff012e54a434fbdd2d25ccc5852060561e68040dd7778997bd7b",
},
{
- KM_EC_CURVE_P_256, "04"
- "809f04289c64348c01515eb03d5ce7ac1a8cb9498f5caa50197e58d43a86a7ae"
- "b29d84e811197f25eba8f5194092cb6ff440e26d4421011372461f579271cda3",
+ KM_EC_CURVE_P_256,
+ "04"
+ "809f04289c64348c01515eb03d5ce7ac1a8cb9498f5caa50197e58d43a86a7ae"
+ "b29d84e811197f25eba8f5194092cb6ff440e26d4421011372461f579271cda3",
// https://tools.ietf.org/html/rfc5915
"30770201010420" // DER-encodeded EC private key header
"38f65d6dce47676044d58ce5139582d568f64bb16098d179dbab07741dd5caf5" // private key
@@ -164,9 +163,10 @@
"057d636096cb80b67a8c038c890e887d1adfa4195e9b3ce241c8a778c59cda67",
},
{
- KM_EC_CURVE_P_256, "04"
- "df3989b9fa55495719b3cf46dccd28b5153f7808191dd518eff0c3cff2b705ed"
- "422294ff46003429d739a33206c8752552c8ba54a270defc06e221e0feaf6ac4",
+ KM_EC_CURVE_P_256,
+ "04"
+ "df3989b9fa55495719b3cf46dccd28b5153f7808191dd518eff0c3cff2b705ed"
+ "422294ff46003429d739a33206c8752552c8ba54a270defc06e221e0feaf6ac4",
// https://tools.ietf.org/html/rfc5915
"30770201010420" // DER-encodeded EC private key header
"207c43a79bfee03db6f4b944f53d2fb76cc49ef1c9c4d34d51b6c65c4db6932d" // private key
diff --git a/tests/test_keys.h b/tests/test_keys.h
new file mode 100644
index 0000000..015b3ba
--- /dev/null
+++ b/tests/test_keys.h
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2020 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.
+ */
+
+unsigned char rsa_privkey_pk8_der[] = {
+ 0x30, 0x82, 0x02, 0x75, 0x02, 0x01, 0x00, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
+ 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x04, 0x82, 0x02, 0x5f, 0x30, 0x82, 0x02, 0x5b, 0x02, 0x01,
+ 0x00, 0x02, 0x81, 0x81, 0x00, 0xc6, 0x09, 0x54, 0x09, 0x04, 0x7d, 0x86, 0x34, 0x81, 0x2d, 0x5a,
+ 0x21, 0x81, 0x76, 0xe4, 0x5c, 0x41, 0xd6, 0x0a, 0x75, 0xb1, 0x39, 0x01, 0xf2, 0x34, 0x22, 0x6c,
+ 0xff, 0xe7, 0x76, 0x52, 0x1c, 0x5a, 0x77, 0xb9, 0xe3, 0x89, 0x41, 0x7b, 0x71, 0xc0, 0xb6, 0xa4,
+ 0x4d, 0x13, 0xaf, 0xe4, 0xe4, 0xa2, 0x80, 0x5d, 0x46, 0xc9, 0xda, 0x29, 0x35, 0xad, 0xb1, 0xff,
+ 0x0c, 0x1f, 0x24, 0xea, 0x06, 0xe6, 0x2b, 0x20, 0xd7, 0x76, 0x43, 0x0a, 0x4d, 0x43, 0x51, 0x57,
+ 0x23, 0x3c, 0x6f, 0x91, 0x67, 0x83, 0xc3, 0x0e, 0x31, 0x0f, 0xcb, 0xd8, 0x9b, 0x85, 0xc2, 0xd5,
+ 0x67, 0x71, 0x16, 0x97, 0x85, 0xac, 0x12, 0xbc, 0xa2, 0x44, 0xab, 0xda, 0x72, 0xbf, 0xb1, 0x9f,
+ 0xc4, 0x4d, 0x27, 0xc8, 0x1e, 0x1d, 0x92, 0xde, 0x28, 0x4f, 0x40, 0x61, 0xed, 0xfd, 0x99, 0x28,
+ 0x07, 0x45, 0xea, 0x6d, 0x25, 0x02, 0x03, 0x01, 0x00, 0x01, 0x02, 0x81, 0x80, 0x1b, 0xe0, 0xf0,
+ 0x4d, 0x9c, 0xae, 0x37, 0x18, 0x69, 0x1f, 0x03, 0x53, 0x38, 0x30, 0x8e, 0x91, 0x56, 0x4b, 0x55,
+ 0x89, 0x9f, 0xfb, 0x50, 0x84, 0xd2, 0x46, 0x0e, 0x66, 0x30, 0x25, 0x7e, 0x05, 0xb3, 0xce, 0xab,
+ 0x02, 0x97, 0x2d, 0xfa, 0xbc, 0xd6, 0xce, 0x5f, 0x6e, 0xe2, 0x58, 0x9e, 0xb6, 0x79, 0x11, 0xed,
+ 0x0f, 0xac, 0x16, 0xe4, 0x3a, 0x44, 0x4b, 0x8c, 0x86, 0x1e, 0x54, 0x4a, 0x05, 0x93, 0x36, 0x57,
+ 0x72, 0xf8, 0xba, 0xf6, 0xb2, 0x2f, 0xc9, 0xe3, 0xc5, 0xf1, 0x02, 0x4b, 0x06, 0x3a, 0xc0, 0x80,
+ 0xa7, 0xb2, 0x23, 0x4c, 0xf8, 0xae, 0xe8, 0xf6, 0xc4, 0x7b, 0xbf, 0x4f, 0xd3, 0xac, 0xe7, 0x24,
+ 0x02, 0x90, 0xbe, 0xf1, 0x6c, 0x0b, 0x3f, 0x7f, 0x3c, 0xdd, 0x64, 0xce, 0x3a, 0xb5, 0x91, 0x2c,
+ 0xf6, 0xe3, 0x2f, 0x39, 0xab, 0x18, 0x83, 0x58, 0xaf, 0xcc, 0xcd, 0x80, 0x81, 0x02, 0x41, 0x00,
+ 0xe4, 0xb4, 0x9e, 0xf5, 0x0f, 0x76, 0x5d, 0x3b, 0x24, 0xdd, 0xe0, 0x1a, 0xce, 0xaa, 0xf1, 0x30,
+ 0xf2, 0xc7, 0x66, 0x70, 0xa9, 0x1a, 0x61, 0xae, 0x08, 0xaf, 0x49, 0x7b, 0x4a, 0x82, 0xbe, 0x6d,
+ 0xee, 0x8f, 0xcd, 0xd5, 0xe3, 0xf7, 0xba, 0x1c, 0xfb, 0x1f, 0x0c, 0x92, 0x6b, 0x88, 0xf8, 0x8c,
+ 0x92, 0xbf, 0xab, 0x13, 0x7f, 0xba, 0x22, 0x85, 0x22, 0x7b, 0x83, 0xc3, 0x42, 0xff, 0x7c, 0x55,
+ 0x02, 0x41, 0x00, 0xdd, 0xab, 0xb5, 0x83, 0x9c, 0x4c, 0x7f, 0x6b, 0xf3, 0xd4, 0x18, 0x32, 0x31,
+ 0xf0, 0x05, 0xb3, 0x1a, 0xa5, 0x8a, 0xff, 0xdd, 0xa5, 0xc7, 0x9e, 0x4c, 0xce, 0x21, 0x7f, 0x6b,
+ 0xc9, 0x30, 0xdb, 0xe5, 0x63, 0xd4, 0x80, 0x70, 0x6c, 0x24, 0xe9, 0xeb, 0xfc, 0xab, 0x28, 0xa6,
+ 0xcd, 0xef, 0xd3, 0x24, 0xb7, 0x7e, 0x1b, 0xf7, 0x25, 0x1b, 0x70, 0x90, 0x92, 0xc2, 0x4f, 0xf5,
+ 0x01, 0xfd, 0x91, 0x02, 0x40, 0x23, 0xd4, 0x34, 0x0e, 0xda, 0x34, 0x45, 0xd8, 0xcd, 0x26, 0xc1,
+ 0x44, 0x11, 0xda, 0x6f, 0xdc, 0xa6, 0x3c, 0x1c, 0xcd, 0x4b, 0x80, 0xa9, 0x8a, 0xd5, 0x2b, 0x78,
+ 0xcc, 0x8a, 0xd8, 0xbe, 0xb2, 0x84, 0x2c, 0x1d, 0x28, 0x04, 0x05, 0xbc, 0x2f, 0x6c, 0x1b, 0xea,
+ 0x21, 0x4a, 0x1d, 0x74, 0x2a, 0xb9, 0x96, 0xb3, 0x5b, 0x63, 0xa8, 0x2a, 0x5e, 0x47, 0x0f, 0xa8,
+ 0x8d, 0xbf, 0x82, 0x3c, 0xdd, 0x02, 0x40, 0x1b, 0x7b, 0x57, 0x44, 0x9a, 0xd3, 0x0d, 0x15, 0x18,
+ 0x24, 0x9a, 0x5f, 0x56, 0xbb, 0x98, 0x29, 0x4d, 0x4b, 0x6a, 0xc1, 0x2f, 0xfc, 0x86, 0x94, 0x04,
+ 0x97, 0xa5, 0xa5, 0x83, 0x7a, 0x6c, 0xf9, 0x46, 0x26, 0x2b, 0x49, 0x45, 0x26, 0xd3, 0x28, 0xc1,
+ 0x1e, 0x11, 0x26, 0x38, 0x0f, 0xde, 0x04, 0xc2, 0x4f, 0x91, 0x6d, 0xec, 0x25, 0x08, 0x92, 0xdb,
+ 0x09, 0xa6, 0xd7, 0x7c, 0xdb, 0xa3, 0x51, 0x02, 0x40, 0x77, 0x62, 0xcd, 0x8f, 0x4d, 0x05, 0x0d,
+ 0xa5, 0x6b, 0xd5, 0x91, 0xad, 0xb5, 0x15, 0xd2, 0x4d, 0x7c, 0xcd, 0x32, 0xcc, 0xa0, 0xd0, 0x5f,
+ 0x86, 0x6d, 0x58, 0x35, 0x14, 0xbd, 0x73, 0x24, 0xd5, 0xf3, 0x36, 0x45, 0xe8, 0xed, 0x8b, 0x4a,
+ 0x1c, 0xb3, 0xcc, 0x4a, 0x1d, 0x67, 0x98, 0x73, 0x99, 0xf2, 0xa0, 0x9f, 0x5b, 0x3f, 0xb6, 0x8c,
+ 0x88, 0xd5, 0xe5, 0xd9, 0x0a, 0xc3, 0x34, 0x92, 0xd6};
+unsigned int rsa_privkey_pk8_der_len = 633;
+
+unsigned char ec_privkey_pk8_der[] = {
+ 0x30, 0x81, 0x87, 0x02, 0x01, 0x00, 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02,
+ 0x01, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0x04, 0x6d, 0x30, 0x6b, 0x02,
+ 0x01, 0x01, 0x04, 0x20, 0x73, 0x7c, 0x2e, 0xcd, 0x7b, 0x8d, 0x19, 0x40, 0xbf, 0x29, 0x30, 0xaa,
+ 0x9b, 0x4e, 0xd3, 0xff, 0x94, 0x1e, 0xed, 0x09, 0x36, 0x6b, 0xc0, 0x32, 0x99, 0x98, 0x64, 0x81,
+ 0xf3, 0xa4, 0xd8, 0x59, 0xa1, 0x44, 0x03, 0x42, 0x00, 0x04, 0xbf, 0x85, 0xd7, 0x72, 0x0d, 0x07,
+ 0xc2, 0x54, 0x61, 0x68, 0x3b, 0xc6, 0x48, 0xb4, 0x77, 0x8a, 0x9a, 0x14, 0xdd, 0x8a, 0x02, 0x4e,
+ 0x3b, 0xdd, 0x8c, 0x7d, 0xdd, 0x9a, 0xb2, 0xb5, 0x28, 0xbb, 0xc7, 0xaa, 0x1b, 0x51, 0xf1, 0x4e,
+ 0xbb, 0xbb, 0x0b, 0xd0, 0xce, 0x21, 0xbc, 0xc4, 0x1c, 0x6e, 0xb0, 0x00, 0x83, 0xcf, 0x33, 0x76,
+ 0xd1, 0x1f, 0xd4, 0x49, 0x49, 0xe0, 0xb2, 0x18, 0x3b, 0xfe};
+unsigned int ec_privkey_pk8_der_len = 138;
diff --git a/tests/wrapped_key_test.cpp b/tests/wrapped_key_test.cpp
index 271b2cc..cb9e7d2 100644
--- a/tests/wrapped_key_test.cpp
+++ b/tests/wrapped_key_test.cpp
@@ -66,7 +66,6 @@
TEST(WrappedKeyTest, Simple) {
KeymasterKeyBlob asn1;
- size_t asn1_len;
KeymasterBlob iv = {reinterpret_cast<const uint8_t*>(test_iv.c_str()), test_iv.size()};
KeymasterKeyBlob tk = {reinterpret_cast<const uint8_t*>(test_transit_key.c_str()),