Merge commit '5c0e13490a6035296333e942623b40e23bebc110' into HEAD
diff --git a/MODULE_LICENSE_APACHE2 b/MODULE_LICENSE_APACHE2
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/MODULE_LICENSE_APACHE2
diff --git a/NOTICE b/NOTICE
new file mode 100644
index 0000000..89ae7c4
--- /dev/null
+++ b/NOTICE
@@ -0,0 +1,190 @@
+
+ Copyright (c) 2008-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.
+
+ 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.
+
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
diff --git a/keystore/Android.mk b/keystore/Android.mk
index 3babd1d..d1f45ca 100644
--- a/keystore/Android.mk
+++ b/keystore/Android.mk
@@ -16,6 +16,12 @@
LOCAL_PATH := $(call my-dir)
+# This has to be lazy-resolved because it depends on the LOCAL_MODULE_CLASS
+# which varies depending on what is being built.
+define keystore_proto_include
+$(call local-generated-sources-dir)/proto/$(LOCAL_PATH)
+endef
+
include $(CLEAR_VARS)
ifeq ($(USE_32_BIT_KEYSTORE), true)
LOCAL_MULTILIB := 32
@@ -38,7 +44,6 @@
LOCAL_MODULE := keystore
LOCAL_MODULE_TAGS := optional
LOCAL_INIT_RC := keystore.rc
-LOCAL_C_INCLUES := system/keymaster/
LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
include $(BUILD_EXECUTABLE)
@@ -54,17 +59,45 @@
LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
include $(BUILD_EXECUTABLE)
+include $(CLEAR_VARS)
+ifeq ($(USE_32_BIT_KEYSTORE), true)
+LOCAL_MULTILIB := 32
+endif
+LOCAL_CFLAGS := -Wall -Wextra -Werror -Wno-unused-parameter
+LOCAL_SRC_FILES := keystore_cli_v2.cpp
+LOCAL_SHARED_LIBRARIES := \
+ libchrome \
+ libkeymaster_messages \
+ libkeystore_binder
+LOCAL_MODULE := keystore_cli_v2
+LOCAL_MODULE_TAGS := debug
+LOCAL_C_INCLUDES := $(LOCAL_PATH)/include external/gtest/include
+LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
+include $(BUILD_EXECUTABLE)
+
# Library for keystore clients
include $(CLEAR_VARS)
ifeq ($(USE_32_BIT_KEYSTORE), true)
LOCAL_MULTILIB := 32
endif
LOCAL_CFLAGS := -Wall -Wextra -Werror
-LOCAL_SRC_FILES := IKeystoreService.cpp keystore_get.cpp keyblob_utils.cpp
-LOCAL_SHARED_LIBRARIES := libbinder libutils liblog libsoftkeymasterdevice
+LOCAL_SRC_FILES := \
+ IKeystoreService.cpp \
+ keyblob_utils.cpp \
+ keystore_client.proto \
+ keystore_client_impl.cpp \
+ keystore_get.cpp
+LOCAL_SHARED_LIBRARIES := \
+ libbinder \
+ libkeymaster_messages \
+ liblog \
+ libprotobuf-cpp-lite \
+ libsoftkeymasterdevice \
+ libutils
+LOCAL_MODULE_CLASS := SHARED_LIBRARIES
LOCAL_MODULE := libkeystore_binder
LOCAL_MODULE_TAGS := optional
-LOCAL_C_INCLUDES := $(LOCAL_PATH)/include
+LOCAL_C_INCLUDES := $(LOCAL_PATH)/include $(call keystore_proto_include)
LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
include $(BUILD_SHARED_LIBRARY)
diff --git a/keystore/include/keystore/keystore_client.h b/keystore/include/keystore/keystore_client.h
new file mode 100644
index 0000000..cec29f7
--- /dev/null
+++ b/keystore/include/keystore/keystore_client.h
@@ -0,0 +1,180 @@
+// Copyright 2015 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef KEYSTORE_KEYSTORE_CLIENT_H_
+#define KEYSTORE_KEYSTORE_CLIENT_H_
+
+#include <set>
+#include <string>
+#include <vector>
+
+#include "hardware/keymaster_defs.h"
+#include "keymaster/authorization_set.h"
+
+namespace keystore {
+
+// An abstract class providing a convenient interface to keystore services. This
+// interface is designed to:
+// - hide details of the IPC mechanism (e.g. binder)
+// - use std data types
+// - encourage the use of keymaster::AuthorizationSet[Builder]
+// - be convenient for native services integrating with keystore
+// - be safely mocked for unit testing (e.g. pure virtual methods)
+//
+// Example usage:
+// KeystoreClient* keystore = new KeyStoreClientImpl();
+// keystore->AddRandomNumberGeneratorEntropy("unpredictable");
+//
+// Notes on error codes:
+// Keystore binder methods return a variety of values including ResponseCode
+// values defined in keystore.h, keymaster_error_t values defined in
+// keymaster_defs.h, or just 0 or -1 (both of which conflict with
+// keymaster_error_t). The methods in this class converge on a single success
+// indicator for convenience. KM_ERROR_OK was chosen over ::NO_ERROR for two
+// reasons:
+// 1) KM_ERROR_OK is 0, which is a common convention for success, is the gmock
+// default, and allows error checks like 'if (error) {...'.
+// 2) Although both pollute the global namespace, KM_ERROR_OK has a prefix per
+// C convention and hopefully clients can use this interface without
+// needing to include 'keystore.h' directly.
+class KeystoreClient {
+ public:
+ KeystoreClient() = default;
+ virtual ~KeystoreClient() = default;
+
+ // Encrypts and authenticates |data| with minimal configuration for local
+ // decryption. If a key identified by |key_name| does not already exist it
+ // will be generated. On success returns true and populates |encrypted_data|.
+ // Note: implementations may generate more than one key but they will always
+ // have |key_name| as a prefix.
+ virtual bool encryptWithAuthentication(const std::string& key_name, const std::string& data,
+ std::string* encrypted_data) = 0;
+
+ // Decrypts and authenticates |encrypted_data| as output by
+ // EncryptWithAuthentication using the key(s) identified by |key_name|. On
+ // success returns true and populates |data|.
+ virtual bool decryptWithAuthentication(const std::string& key_name,
+ const std::string& encrypted_data,
+ std::string* data) = 0;
+
+ // Performs a Begin/Update/Finish sequence for an operation. The |purpose|,
+ // |key_name|, |input_parameters|, and |output_parameters| are as in
+ // BeginOperation. The |input_data| is as in UpdateOperation. The
+ // |signature_to_verify| and |output_data| are as in FinishOperation. On
+ // success returns true.
+ virtual bool oneShotOperation(keymaster_purpose_t purpose, const std::string& key_name,
+ const keymaster::AuthorizationSet& input_parameters,
+ const std::string& input_data,
+ const std::string& signature_to_verify,
+ keymaster::AuthorizationSet* output_parameters,
+ std::string* output_data) = 0;
+
+ // Adds |entropy| to the random number generator. Returns KM_ERROR_OK on
+ // success and a Keystore ResponseCode or keymaster_error_t on failure.
+ virtual int32_t addRandomNumberGeneratorEntropy(const std::string& entropy) = 0;
+
+ // Generates a key according to the given |key_parameters| and stores it with
+ // the given |key_name|. The [hardware|software]_enforced_characteristics of
+ // the key are provided on success. Returns KM_ERROR_OK on success. Returns
+ // KM_ERROR_OK on success and a Keystore ResponseCode or keymaster_error_t on
+ // failure.
+ virtual int32_t generateKey(const std::string& key_name,
+ const keymaster::AuthorizationSet& key_parameters,
+ keymaster::AuthorizationSet* hardware_enforced_characteristics,
+ keymaster::AuthorizationSet* software_enforced_characteristics) = 0;
+
+ // Provides the [hardware|software]_enforced_characteristics of a key
+ // identified by |key_name|. Returns KM_ERROR_OK on success and a Keystore
+ // ResponseCode or keymaster_error_t on failure.
+ virtual int32_t
+ getKeyCharacteristics(const std::string& key_name,
+ keymaster::AuthorizationSet* hardware_enforced_characteristics,
+ keymaster::AuthorizationSet* software_enforced_characteristics) = 0;
+
+ // Imports |key_data| in the given |key_format|, applies the given
+ // |key_parameters|, and stores it with the given |key_name|. The
+ // [hardware|software]_enforced_characteristics of the key are provided on
+ // success. Returns KM_ERROR_OK on success and a Keystore ResponseCode or
+ // keymaster_error_t on failure.
+ virtual int32_t importKey(const std::string& key_name,
+ const keymaster::AuthorizationSet& key_parameters,
+ keymaster_key_format_t key_format, const std::string& key_data,
+ keymaster::AuthorizationSet* hardware_enforced_characteristics,
+ keymaster::AuthorizationSet* software_enforced_characteristics) = 0;
+
+ // Exports the public key identified by |key_name| to |export_data| using
+ // |export_format|. Returns KM_ERROR_OK on success and a Keystore ResponseCode
+ // or keymaster_error_t on failure.
+ virtual int32_t exportKey(keymaster_key_format_t export_format, const std::string& key_name,
+ std::string* export_data) = 0;
+
+ // Deletes the key identified by |key_name|. Returns KM_ERROR_OK on success
+ // and a Keystore ResponseCode or keymaster_error_t on failure.
+ virtual int32_t deleteKey(const std::string& key_name) = 0;
+
+ // Deletes all keys owned by the caller. Returns KM_ERROR_OK on success and a
+ // Keystore ResponseCode or keymaster_error_t on failure.
+ virtual int32_t deleteAllKeys() = 0;
+
+ // Begins a cryptographic operation (e.g. encrypt, sign) identified by
+ // |purpose| using the key identified by |key_name| and the given
+ // |input_parameters|. On success, any |output_parameters| and an operation
+ // |handle| are populated. Returns KM_ERROR_OK on success and a Keystore
+ // ResponseCode or keymaster_error_t on failure.
+ virtual int32_t beginOperation(keymaster_purpose_t purpose, const std::string& key_name,
+ const keymaster::AuthorizationSet& input_parameters,
+ keymaster::AuthorizationSet* output_parameters,
+ keymaster_operation_handle_t* handle) = 0;
+
+ // Continues the operation associated with |handle| using the given
+ // |input_parameters| and |input_data|. On success, the
+ // |num_input_bytes_consumed| and any |output_parameters| are populated. Any
+ // |output_data| will be appended. Returns KM_ERROR_OK on success and a
+ // Keystore ResponseCode or keymaster_error_t on failure.
+ virtual int32_t updateOperation(keymaster_operation_handle_t handle,
+ const keymaster::AuthorizationSet& input_parameters,
+ const std::string& input_data, size_t* num_input_bytes_consumed,
+ keymaster::AuthorizationSet* output_parameters,
+ std::string* output_data) = 0;
+
+ // Finishes the operation associated with |handle| using the given
+ // |input_parameters| and, if necessary, a |signature_to_verify|. On success,
+ // any |output_parameters| are populated and |output_data| is appended.
+ // Returns KM_ERROR_OK on success and a Keystore ResponseCode or
+ // keymaster_error_t on failure.
+ virtual int32_t finishOperation(keymaster_operation_handle_t handle,
+ const keymaster::AuthorizationSet& input_parameters,
+ const std::string& signature_to_verify,
+ keymaster::AuthorizationSet* output_parameters,
+ std::string* output_data) = 0;
+
+ // Aborts the operation associated with |handle|. Returns KM_ERROR_OK on
+ // success and a Keystore ResponseCode or keymaster_error_t on failure.
+ virtual int32_t abortOperation(keymaster_operation_handle_t handle) = 0;
+
+ // Returns true if a key identified by |key_name| exists in the caller's
+ // key store. Returns false if an error occurs.
+ virtual bool doesKeyExist(const std::string& key_name) = 0;
+
+ // Provides a |key_name_list| containing all existing key names in the
+ // caller's key store starting with |prefix|. Returns true on success.
+ virtual bool listKeys(const std::string& prefix, std::vector<std::string>* key_name_list) = 0;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(KeystoreClient);
+};
+
+} // namespace keystore
+
+#endif // KEYSTORE_KEYSTORE_CLIENT_H_
diff --git a/keystore/include/keystore/keystore_client_impl.h b/keystore/include/keystore/keystore_client_impl.h
new file mode 100644
index 0000000..21f68f9
--- /dev/null
+++ b/keystore/include/keystore/keystore_client_impl.h
@@ -0,0 +1,119 @@
+// Copyright 2015 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef KEYSTORE_KEYSTORE_CLIENT_IMPL_H_
+#define KEYSTORE_KEYSTORE_CLIENT_IMPL_H_
+
+#include "keystore/keystore_client.h"
+
+#include <string>
+#include <map>
+#include <vector>
+
+#include "binder/IBinder.h"
+#include "binder/IServiceManager.h"
+#include "keystore/IKeystoreService.h"
+#include "utils/StrongPointer.h"
+
+namespace keystore {
+
+class KeystoreClientImpl : public KeystoreClient {
+ public:
+ KeystoreClientImpl();
+ ~KeystoreClientImpl() override = default;
+
+ // KeystoreClient methods.
+ bool encryptWithAuthentication(const std::string& key_name, const std::string& data,
+ std::string* encrypted_data) override;
+ bool decryptWithAuthentication(const std::string& key_name, const std::string& encrypted_data,
+ std::string* data) override;
+ bool oneShotOperation(keymaster_purpose_t purpose, const std::string& key_name,
+ const keymaster::AuthorizationSet& input_parameters,
+ const std::string& input_data, const std::string& signature_to_verify,
+ keymaster::AuthorizationSet* output_parameters,
+ std::string* output_data) override;
+ int32_t addRandomNumberGeneratorEntropy(const std::string& entropy) override;
+ int32_t generateKey(const std::string& key_name,
+ const keymaster::AuthorizationSet& key_parameters,
+ keymaster::AuthorizationSet* hardware_enforced_characteristics,
+ keymaster::AuthorizationSet* software_enforced_characteristics) override;
+ int32_t
+ getKeyCharacteristics(const std::string& key_name,
+ keymaster::AuthorizationSet* hardware_enforced_characteristics,
+ keymaster::AuthorizationSet* software_enforced_characteristics) override;
+ int32_t importKey(const std::string& key_name,
+ const keymaster::AuthorizationSet& key_parameters,
+ keymaster_key_format_t key_format, const std::string& key_data,
+ keymaster::AuthorizationSet* hardware_enforced_characteristics,
+ keymaster::AuthorizationSet* software_enforced_characteristics) override;
+ int32_t exportKey(keymaster_key_format_t export_format, const std::string& key_name,
+ std::string* export_data) override;
+ int32_t deleteKey(const std::string& key_name) override;
+ int32_t deleteAllKeys() override;
+ int32_t beginOperation(keymaster_purpose_t purpose, const std::string& key_name,
+ const keymaster::AuthorizationSet& input_parameters,
+ keymaster::AuthorizationSet* output_parameters,
+ keymaster_operation_handle_t* handle) override;
+ int32_t updateOperation(keymaster_operation_handle_t handle,
+ const keymaster::AuthorizationSet& input_parameters,
+ const std::string& input_data, size_t* num_input_bytes_consumed,
+ keymaster::AuthorizationSet* output_parameters,
+ std::string* output_data) override;
+ int32_t finishOperation(keymaster_operation_handle_t handle,
+ const keymaster::AuthorizationSet& input_parameters,
+ const std::string& signature_to_verify,
+ keymaster::AuthorizationSet* output_parameters,
+ std::string* output_data) override;
+ int32_t abortOperation(keymaster_operation_handle_t handle) override;
+ bool doesKeyExist(const std::string& key_name) override;
+ bool listKeys(const std::string& prefix, std::vector<std::string>* key_name_list) override;
+
+ private:
+ // Returns an available virtual operation handle.
+ keymaster_operation_handle_t getNextVirtualHandle();
+
+ // Maps a keystore error code to a code where all success cases use
+ // KM_ERROR_OK (not keystore's NO_ERROR).
+ int32_t mapKeystoreError(int32_t keystore_error);
+
+ // Creates an encryption key suitable for EncryptWithAuthentication or
+ // verifies attributes if the key already exists. Returns true on success.
+ bool createOrVerifyEncryptionKey(const std::string& key_name);
+
+ // Creates an authentication key suitable for EncryptWithAuthentication or
+ // verifies attributes if the key already exists. Returns true on success.
+ bool createOrVerifyAuthenticationKey(const std::string& key_name);
+
+ // Verifies attributes of an encryption key suitable for
+ // EncryptWithAuthentication. Returns true on success and populates |verified|
+ // with the result of the verification.
+ bool verifyEncryptionKeyAttributes(const std::string& key_name, bool* verified);
+
+ // Verifies attributes of an authentication key suitable for
+ // EncryptWithAuthentication. Returns true on success and populates |verified|
+ // with the result of the verification.
+ bool verifyAuthenticationKeyAttributes(const std::string& key_name, bool* verified);
+
+ android::sp<android::IServiceManager> service_manager_;
+ android::sp<android::IBinder> keystore_binder_;
+ android::sp<android::IKeystoreService> keystore_;
+ keymaster_operation_handle_t next_virtual_handle_ = 1;
+ std::map<keymaster_operation_handle_t, android::sp<android::IBinder>> active_operations_;
+
+ DISALLOW_COPY_AND_ASSIGN(KeystoreClientImpl);
+};
+
+} // namespace keystore
+
+#endif // KEYSTORE_KEYSTORE_CLIENT_IMPL_H_
diff --git a/keystore/include/keystore/keystore_client_mock.h b/keystore/include/keystore/keystore_client_mock.h
new file mode 100644
index 0000000..2d1f499
--- /dev/null
+++ b/keystore/include/keystore/keystore_client_mock.h
@@ -0,0 +1,88 @@
+// 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 KEYSTORE_KEYSTORE_CLIENT_MOCK_H_
+#define KEYSTORE_KEYSTORE_CLIENT_MOCK_H_
+
+#include "gmock/gmock.h"
+#include "keystore/keystore_client.h"
+
+using testing::_;
+
+namespace keystore {
+
+// A mock implementation of KeystoreClient. By default all methods do nothing
+// and return KM_ERROR_OK (or false).
+class KeystoreClientMock : public KeystoreClient {
+ public:
+ KeystoreClientMock() = default;
+ ~KeystoreClientMock() = default;
+
+ MOCK_METHOD3(encryptWithAuthentication,
+ bool(const std::string& key_name, const std::string& data,
+ std::string* encrypted_data));
+ MOCK_METHOD3(decryptWithAuthentication,
+ bool(const std::string& key_name, const std::string& encrypted_data,
+ std::string* data));
+ MOCK_METHOD7(oneShotOperation,
+ bool(keymaster_purpose_t purpose, const std::string& key_name,
+ const keymaster::AuthorizationSet& input_parameters,
+ const std::string& input_data, const std::string& signature_to_verify,
+ keymaster::AuthorizationSet* output_parameters, std::string* output_data));
+ MOCK_METHOD1(addRandomNumberGeneratorEntropy, int32_t(const std::string& entropy));
+ MOCK_METHOD4(generateKey,
+ int32_t(const std::string& key_name,
+ const keymaster::AuthorizationSet& key_parameters,
+ keymaster::AuthorizationSet* hardware_enforced_characteristics,
+ keymaster::AuthorizationSet* software_enforced_characteristics));
+ MOCK_METHOD3(getKeyCharacteristics,
+ int32_t(const std::string& key_name,
+ keymaster::AuthorizationSet* hardware_enforced_characteristics,
+ keymaster::AuthorizationSet* software_enforced_characteristics));
+ MOCK_METHOD6(importKey,
+ int32_t(const std::string& key_name,
+ const keymaster::AuthorizationSet& key_parameters,
+ keymaster_key_format_t key_format, const std::string& key_data,
+ keymaster::AuthorizationSet* hardware_enforced_characteristics,
+ keymaster::AuthorizationSet* software_enforced_characteristics));
+ MOCK_METHOD3(exportKey, int32_t(keymaster_key_format_t export_format,
+ const std::string& key_name, std::string* export_data));
+ MOCK_METHOD1(deleteKey, int32_t(const std::string& key_name));
+ MOCK_METHOD0(deleteAllKeys, int32_t());
+ MOCK_METHOD5(beginOperation, int32_t(keymaster_purpose_t purpose, const std::string& key_name,
+ const keymaster::AuthorizationSet& input_parameters,
+ keymaster::AuthorizationSet* output_parameters,
+ keymaster_operation_handle_t* handle));
+ MOCK_METHOD6(updateOperation,
+ int32_t(keymaster_operation_handle_t handle,
+ const keymaster::AuthorizationSet& input_parameters,
+ const std::string& input_data, size_t* num_input_bytes_consumed,
+ keymaster::AuthorizationSet* output_parameters, std::string* output_data));
+ MOCK_METHOD5(finishOperation,
+ int32_t(keymaster_operation_handle_t handle,
+ const keymaster::AuthorizationSet& input_parameters,
+ const std::string& signature_to_verify,
+ keymaster::AuthorizationSet* output_parameters, std::string* output_data));
+ MOCK_METHOD1(abortOperation, int32_t(keymaster_operation_handle_t handle));
+ MOCK_METHOD1(doesKeyExist, bool(const std::string& key_name));
+ MOCK_METHOD2(listKeys,
+ bool(const std::string& prefix, std::vector<std::string>* key_name_list));
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(KeystoreClientMock);
+};
+
+} // namespace keystore
+
+#endif // KEYSTORE_KEYSTORE_CLIENT_MOCK_H_
diff --git a/keystore/keystore_cli_v2.cpp b/keystore/keystore_cli_v2.cpp
new file mode 100644
index 0000000..4f4040d
--- /dev/null
+++ b/keystore/keystore_cli_v2.cpp
@@ -0,0 +1,273 @@
+// 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 <cstdio>
+#include <memory>
+#include <string>
+#include <vector>
+
+#include "base/command_line.h"
+#include "base/files/file_util.h"
+#include "keymaster/authorization_set.h"
+#include "keystore/keystore_client_impl.h"
+
+using base::CommandLine;
+using keymaster::AuthorizationSet;
+using keymaster::AuthorizationSetBuilder;
+using keystore::KeystoreClient;
+
+namespace {
+
+void PrintUsageAndExit() {
+ printf("Usage: keystore_client_v2 <command> [options]\n");
+ printf("Commands: add-entropy --input=<entropy>\n"
+ " generate --name=<key_name>\n"
+ " get-chars --name=<key_name>\n"
+ " export --name=<key_name>\n"
+ " delete --name=<key_name>\n"
+ " delete-all\n"
+ " exists --name=<key_name>\n"
+ " list [--prefix=<key_name_prefix>]\n"
+ " sign-verify --name=<key_name>\n"
+ " [en|de]crypt --name=<key_name> --in=<file> --out=<file>\n");
+ exit(1);
+}
+
+std::unique_ptr<KeystoreClient> CreateKeystoreInstance() {
+ return std::unique_ptr<KeystoreClient>(new keystore::KeystoreClientImpl);
+}
+
+std::string ReadFile(const std::string& filename) {
+ std::string content;
+ base::FilePath path(filename);
+ if (!base::ReadFileToString(path, &content)) {
+ printf("Failed to read file: %s\n", filename.c_str());
+ exit(1);
+ }
+ return content;
+}
+
+void WriteFile(const std::string& filename, const std::string& content) {
+ base::FilePath path(filename);
+ int size = content.size();
+ if (base::WriteFile(path, content.data(), size) != size) {
+ printf("Failed to write file: %s\n", filename.c_str());
+ exit(1);
+ }
+}
+
+int AddEntropy(const std::string& input) {
+ std::unique_ptr<KeystoreClient> keystore = CreateKeystoreInstance();
+ int32_t result = keystore->addRandomNumberGeneratorEntropy(input);
+ printf("AddEntropy: %d\n", result);
+ return result;
+}
+
+int GenerateKey(const std::string& name) {
+ std::unique_ptr<KeystoreClient> keystore = CreateKeystoreInstance();
+ AuthorizationSetBuilder params;
+ params.RsaSigningKey(2048, 65537)
+ .Digest(KM_DIGEST_SHA_2_224)
+ .Digest(KM_DIGEST_SHA_2_256)
+ .Digest(KM_DIGEST_SHA_2_384)
+ .Digest(KM_DIGEST_SHA_2_512)
+ .Padding(KM_PAD_RSA_PKCS1_1_5_SIGN)
+ .Padding(KM_PAD_RSA_PSS)
+ .Authorization(keymaster::TAG_NO_AUTH_REQUIRED);
+ AuthorizationSet hardware_enforced_characteristics;
+ AuthorizationSet software_enforced_characteristics;
+ int32_t result = keystore->generateKey(name, params.build(), &hardware_enforced_characteristics,
+ &software_enforced_characteristics);
+ printf("GenerateKey: %d (%zu, %zu)\n", result, hardware_enforced_characteristics.size(),
+ software_enforced_characteristics.size());
+ return result;
+}
+
+int GetCharacteristics(const std::string& name) {
+ std::unique_ptr<KeystoreClient> keystore = CreateKeystoreInstance();
+ AuthorizationSet hardware_enforced_characteristics;
+ AuthorizationSet software_enforced_characteristics;
+ int32_t result = keystore->getKeyCharacteristics(name, &hardware_enforced_characteristics,
+ &software_enforced_characteristics);
+ printf("GetCharacteristics: %d (%zu, %zu)\n", result, hardware_enforced_characteristics.size(),
+ software_enforced_characteristics.size());
+ return result;
+}
+
+int ExportKey(const std::string& name) {
+ std::unique_ptr<KeystoreClient> keystore = CreateKeystoreInstance();
+ std::string data;
+ int32_t result = keystore->exportKey(KM_KEY_FORMAT_X509, name, &data);
+ printf("ExportKey: %d (%zu)\n", result, data.size());
+ return result;
+}
+
+int DeleteKey(const std::string& name) {
+ std::unique_ptr<KeystoreClient> keystore = CreateKeystoreInstance();
+ int32_t result = keystore->deleteKey(name);
+ printf("DeleteKey: %d\n", result);
+ return result;
+}
+
+int DeleteAllKeys() {
+ std::unique_ptr<KeystoreClient> keystore = CreateKeystoreInstance();
+ int32_t result = keystore->deleteAllKeys();
+ printf("DeleteAllKeys: %d\n", result);
+ return result;
+}
+
+int DoesKeyExist(const std::string& name) {
+ std::unique_ptr<KeystoreClient> keystore = CreateKeystoreInstance();
+ printf("DoesKeyExist: %s\n", keystore->doesKeyExist(name) ? "yes" : "no");
+ return 0;
+}
+
+int List(const std::string& prefix) {
+ std::unique_ptr<KeystoreClient> keystore = CreateKeystoreInstance();
+ std::vector<std::string> key_list;
+ if (!keystore->listKeys(prefix, &key_list)) {
+ printf("ListKeys failed.\n");
+ return 1;
+ }
+ printf("Keys:\n");
+ for (const auto& key_name : key_list) {
+ printf(" %s\n", key_name.c_str());
+ }
+ return 0;
+}
+
+int SignAndVerify(const std::string& name) {
+ std::unique_ptr<KeystoreClient> keystore = CreateKeystoreInstance();
+ AuthorizationSetBuilder sign_params;
+ sign_params.Padding(KM_PAD_RSA_PKCS1_1_5_SIGN);
+ sign_params.Digest(KM_DIGEST_SHA_2_256);
+ AuthorizationSet output_params;
+ keymaster_operation_handle_t handle;
+ int32_t result = keystore->beginOperation(KM_PURPOSE_SIGN, name, sign_params.build(),
+ &output_params, &handle);
+ if (result != KM_ERROR_OK) {
+ printf("Sign: BeginOperation failed: %d\n", result);
+ return result;
+ }
+ AuthorizationSet empty_params;
+ size_t num_input_bytes_consumed;
+ std::string output_data;
+ result = keystore->updateOperation(handle, empty_params, "data_to_sign",
+ &num_input_bytes_consumed, &output_params, &output_data);
+ if (result != KM_ERROR_OK) {
+ printf("Sign: UpdateOperation failed: %d\n", result);
+ return result;
+ }
+ result = keystore->finishOperation(handle, empty_params, std::string() /*signature_to_verify*/,
+ &output_params, &output_data);
+ if (result != KM_ERROR_OK) {
+ printf("Sign: FinishOperation failed: %d\n", result);
+ return result;
+ }
+ printf("Sign: %zu bytes.\n", output_data.size());
+ // We have a signature, now verify it.
+ std::string signature_to_verify = output_data;
+ output_data.clear();
+ result = keystore->beginOperation(KM_PURPOSE_VERIFY, name, sign_params.build(), &output_params,
+ &handle);
+ if (result != KM_ERROR_OK) {
+ printf("Verify: BeginOperation failed: %d\n", result);
+ return result;
+ }
+ result = keystore->updateOperation(handle, empty_params, "data_to_sign",
+ &num_input_bytes_consumed, &output_params, &output_data);
+ if (result != KM_ERROR_OK) {
+ printf("Verify: UpdateOperation failed: %d\n", result);
+ return result;
+ }
+ result = keystore->finishOperation(handle, empty_params, signature_to_verify, &output_params,
+ &output_data);
+ if (result == KM_ERROR_VERIFICATION_FAILED) {
+ printf("Verify: Failed to verify signature.\n");
+ return result;
+ }
+ if (result != KM_ERROR_OK) {
+ printf("Verify: FinishOperation failed: %d\n", result);
+ return result;
+ }
+ printf("Verify: OK\n");
+ return 0;
+}
+
+int Encrypt(const std::string& key_name, const std::string& input_filename,
+ const std::string& output_filename) {
+ std::unique_ptr<KeystoreClient> keystore = CreateKeystoreInstance();
+ std::string input = ReadFile(input_filename);
+ std::string output;
+ if (!keystore->encryptWithAuthentication(key_name, input, &output)) {
+ printf("EncryptWithAuthentication failed.\n");
+ return 1;
+ }
+ WriteFile(output_filename, output);
+ return 0;
+}
+
+int Decrypt(const std::string& key_name, const std::string& input_filename,
+ const std::string& output_filename) {
+ std::unique_ptr<KeystoreClient> keystore = CreateKeystoreInstance();
+ std::string input = ReadFile(input_filename);
+ std::string output;
+ if (!keystore->decryptWithAuthentication(key_name, input, &output)) {
+ printf("DecryptWithAuthentication failed.\n");
+ return 1;
+ }
+ WriteFile(output_filename, output);
+ return 0;
+}
+
+} // namespace
+
+int main(int argc, char** argv) {
+ CommandLine::Init(argc, argv);
+ CommandLine* command_line = CommandLine::ForCurrentProcess();
+ CommandLine::StringVector args = command_line->GetArgs();
+ if (args.empty()) {
+ PrintUsageAndExit();
+ }
+ if (args[0] == "add-entropy") {
+ return AddEntropy(command_line->GetSwitchValueASCII("input"));
+ } else if (args[0] == "generate") {
+ return GenerateKey(command_line->GetSwitchValueASCII("name"));
+ } else if (args[0] == "get-chars") {
+ return GetCharacteristics(command_line->GetSwitchValueASCII("name"));
+ } else if (args[0] == "export") {
+ return ExportKey(command_line->GetSwitchValueASCII("name"));
+ } else if (args[0] == "delete") {
+ return DeleteKey(command_line->GetSwitchValueASCII("name"));
+ } else if (args[0] == "delete-all") {
+ return DeleteAllKeys();
+ } else if (args[0] == "exists") {
+ return DoesKeyExist(command_line->GetSwitchValueASCII("name"));
+ } else if (args[0] == "list") {
+ return List(command_line->GetSwitchValueASCII("prefix"));
+ } else if (args[0] == "sign-verify") {
+ return SignAndVerify(command_line->GetSwitchValueASCII("name"));
+ } else if (args[0] == "encrypt") {
+ return Encrypt(command_line->GetSwitchValueASCII("name"),
+ command_line->GetSwitchValueASCII("in"),
+ command_line->GetSwitchValueASCII("out"));
+ } else if (args[0] == "decrypt") {
+ return Decrypt(command_line->GetSwitchValueASCII("name"),
+ command_line->GetSwitchValueASCII("in"),
+ command_line->GetSwitchValueASCII("out"));
+ } else {
+ PrintUsageAndExit();
+ }
+ return 0;
+}
diff --git a/keystore/keystore_client.proto b/keystore/keystore_client.proto
new file mode 100644
index 0000000..cd520dc
--- /dev/null
+++ b/keystore/keystore_client.proto
@@ -0,0 +1,26 @@
+// 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.
+
+package keystore;
+
+option optimize_for = LITE_RUNTIME;
+
+// Holds encrypted, authenticated data.
+message EncryptedData {
+ // The initialization vector used during encryption.
+ optional bytes init_vector = 1;
+ // MAC of (init_vector + encrypted_data).
+ optional bytes authentication_data = 2;
+ optional bytes encrypted_data = 3;
+}
diff --git a/keystore/keystore_client_impl.cpp b/keystore/keystore_client_impl.cpp
new file mode 100644
index 0000000..a46dfc7
--- /dev/null
+++ b/keystore/keystore_client_impl.cpp
@@ -0,0 +1,556 @@
+// 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.
+
+#define LOG_TAG "keystore_client"
+
+#include "keystore/keystore_client_impl.h"
+
+#include <string>
+#include <vector>
+
+#include "binder/IBinder.h"
+#include "binder/IInterface.h"
+#include "binder/IServiceManager.h"
+#include "keystore/IKeystoreService.h"
+#include "keystore/keystore.h"
+#include "log/log.h"
+#include "utils/String16.h"
+#include "utils/String8.h"
+
+#include "keystore_client.pb.h"
+
+using android::ExportResult;
+using android::KeyCharacteristics;
+using android::KeymasterArguments;
+using android::OperationResult;
+using android::String16;
+using keymaster::AuthorizationSet;
+using keymaster::AuthorizationSetBuilder;
+
+namespace {
+
+// Use the UID of the current process.
+const int kDefaultUID = -1;
+const char kEncryptSuffix[] = "_ENC";
+const char kAuthenticateSuffix[] = "_AUTH";
+const uint32_t kAESKeySize = 256; // bits
+const uint32_t kHMACKeySize = 256; // bits
+const uint32_t kHMACOutputSize = 256; // bits
+
+const uint8_t* StringAsByteArray(const std::string& s) {
+ return reinterpret_cast<const uint8_t*>(s.data());
+}
+
+std::string ByteArrayAsString(const uint8_t* data, size_t data_size) {
+ return std::string(reinterpret_cast<const char*>(data), data_size);
+}
+
+void CopyParameters(const AuthorizationSet& in, std::vector<keymaster_key_param_t>* out) {
+ keymaster_key_param_set_t tmp;
+ in.CopyToParamSet(&tmp);
+ out->assign(&tmp.params[0], &tmp.params[tmp.length]);
+ free(tmp.params);
+}
+
+} // namespace
+
+namespace keystore {
+
+KeystoreClientImpl::KeystoreClientImpl() {
+ service_manager_ = android::defaultServiceManager();
+ keystore_binder_ = service_manager_->getService(String16("android.security.keystore"));
+ keystore_ = android::interface_cast<android::IKeystoreService>(keystore_binder_);
+}
+
+bool KeystoreClientImpl::encryptWithAuthentication(const std::string& key_name,
+ const std::string& data,
+ std::string* encrypted_data) {
+ // The encryption algorithm is AES-256-CBC with PKCS #7 padding and a random
+ // IV. The authentication algorithm is HMAC-SHA256 and is computed over the
+ // cipher-text (i.e. Encrypt-then-MAC approach). This was chosen over AES-GCM
+ // because hardware support for GCM is not mandatory for all Brillo devices.
+ std::string encryption_key_name = key_name + kEncryptSuffix;
+ if (!createOrVerifyEncryptionKey(encryption_key_name)) {
+ return false;
+ }
+ std::string authentication_key_name = key_name + kAuthenticateSuffix;
+ if (!createOrVerifyAuthenticationKey(authentication_key_name)) {
+ return false;
+ }
+ AuthorizationSetBuilder encrypt_params;
+ encrypt_params.Padding(KM_PAD_PKCS7);
+ encrypt_params.Authorization(keymaster::TAG_BLOCK_MODE, KM_MODE_CBC);
+ AuthorizationSet output_params;
+ std::string raw_encrypted_data;
+ if (!oneShotOperation(KM_PURPOSE_ENCRYPT, encryption_key_name, encrypt_params.build(), data,
+ std::string(), /* signature_to_verify */
+ &output_params, &raw_encrypted_data)) {
+ ALOGE("Encrypt: AES operation failed.");
+ return false;
+ }
+ keymaster_blob_t init_vector_blob;
+ if (!output_params.GetTagValue(keymaster::TAG_NONCE, &init_vector_blob)) {
+ ALOGE("Encrypt: Missing initialization vector.");
+ return false;
+ }
+ std::string init_vector =
+ ByteArrayAsString(init_vector_blob.data, init_vector_blob.data_length);
+
+ AuthorizationSetBuilder authenticate_params;
+ authenticate_params.Digest(KM_DIGEST_SHA_2_256);
+ authenticate_params.Authorization(keymaster::TAG_MAC_LENGTH, kHMACOutputSize);
+ std::string raw_authentication_data;
+ if (!oneShotOperation(KM_PURPOSE_SIGN, authentication_key_name, authenticate_params.build(),
+ init_vector + raw_encrypted_data, std::string(), /* signature_to_verify */
+ &output_params, &raw_authentication_data)) {
+ ALOGE("Encrypt: HMAC operation failed.");
+ return false;
+ }
+ EncryptedData protobuf;
+ protobuf.set_init_vector(init_vector);
+ protobuf.set_authentication_data(raw_authentication_data);
+ protobuf.set_encrypted_data(raw_encrypted_data);
+ if (!protobuf.SerializeToString(encrypted_data)) {
+ ALOGE("Encrypt: Failed to serialize EncryptedData protobuf.");
+ return false;
+ }
+ return true;
+}
+
+bool KeystoreClientImpl::decryptWithAuthentication(const std::string& key_name,
+ const std::string& encrypted_data,
+ std::string* data) {
+ EncryptedData protobuf;
+ if (!protobuf.ParseFromString(encrypted_data)) {
+ ALOGE("Decrypt: Failed to parse EncryptedData protobuf.");
+ }
+ // Verify authentication before attempting decryption.
+ std::string authentication_key_name = key_name + kAuthenticateSuffix;
+ AuthorizationSetBuilder authenticate_params;
+ authenticate_params.Digest(KM_DIGEST_SHA_2_256);
+ AuthorizationSet output_params;
+ std::string output_data;
+ if (!oneShotOperation(KM_PURPOSE_VERIFY, authentication_key_name, authenticate_params.build(),
+ protobuf.init_vector() + protobuf.encrypted_data(),
+ protobuf.authentication_data(), &output_params, &output_data)) {
+ ALOGE("Decrypt: HMAC operation failed.");
+ return false;
+ }
+ std::string encryption_key_name = key_name + kEncryptSuffix;
+ AuthorizationSetBuilder encrypt_params;
+ encrypt_params.Padding(KM_PAD_PKCS7);
+ encrypt_params.Authorization(keymaster::TAG_BLOCK_MODE, KM_MODE_CBC);
+ encrypt_params.Authorization(keymaster::TAG_NONCE, protobuf.init_vector().data(),
+ protobuf.init_vector().size());
+ if (!oneShotOperation(KM_PURPOSE_DECRYPT, encryption_key_name, encrypt_params.build(),
+ protobuf.encrypted_data(), std::string(), /* signature_to_verify */
+ &output_params, data)) {
+ ALOGE("Decrypt: AES operation failed.");
+ return false;
+ }
+ return true;
+}
+
+bool KeystoreClientImpl::oneShotOperation(keymaster_purpose_t purpose, const std::string& key_name,
+ const keymaster::AuthorizationSet& input_parameters,
+ const std::string& input_data,
+ const std::string& signature_to_verify,
+ keymaster::AuthorizationSet* output_parameters,
+ std::string* output_data) {
+ keymaster_operation_handle_t handle;
+ int32_t result =
+ beginOperation(purpose, key_name, input_parameters, output_parameters, &handle);
+ if (result != KM_ERROR_OK) {
+ ALOGE("BeginOperation failed: %d", result);
+ return false;
+ }
+ AuthorizationSet empty_params;
+ size_t num_input_bytes_consumed;
+ AuthorizationSet ignored_params;
+ result = updateOperation(handle, empty_params, input_data, &num_input_bytes_consumed,
+ &ignored_params, output_data);
+ if (result != KM_ERROR_OK) {
+ ALOGE("UpdateOperation failed: %d", result);
+ return false;
+ }
+ result =
+ finishOperation(handle, empty_params, signature_to_verify, &ignored_params, output_data);
+ if (result != KM_ERROR_OK) {
+ ALOGE("FinishOperation failed: %d", result);
+ return false;
+ }
+ return true;
+}
+
+int32_t KeystoreClientImpl::addRandomNumberGeneratorEntropy(const std::string& entropy) {
+ return mapKeystoreError(keystore_->addRngEntropy(StringAsByteArray(entropy), entropy.size()));
+}
+
+int32_t KeystoreClientImpl::generateKey(const std::string& key_name,
+ const AuthorizationSet& key_parameters,
+ AuthorizationSet* hardware_enforced_characteristics,
+ AuthorizationSet* software_enforced_characteristics) {
+ String16 key_name16(key_name.data(), key_name.size());
+ KeymasterArguments key_arguments;
+ CopyParameters(key_parameters, &key_arguments.params);
+ KeyCharacteristics characteristics;
+ int32_t result =
+ keystore_->generateKey(key_name16, key_arguments, NULL /*entropy*/, 0 /*entropyLength*/,
+ kDefaultUID, KEYSTORE_FLAG_NONE, &characteristics);
+ hardware_enforced_characteristics->Reinitialize(characteristics.characteristics.hw_enforced);
+ software_enforced_characteristics->Reinitialize(characteristics.characteristics.sw_enforced);
+ return mapKeystoreError(result);
+}
+
+int32_t
+KeystoreClientImpl::getKeyCharacteristics(const std::string& key_name,
+ AuthorizationSet* hardware_enforced_characteristics,
+ AuthorizationSet* software_enforced_characteristics) {
+ String16 key_name16(key_name.data(), key_name.size());
+ keymaster_blob_t client_id_blob = {nullptr, 0};
+ keymaster_blob_t app_data_blob = {nullptr, 0};
+ KeyCharacteristics characteristics;
+ int32_t result = keystore_->getKeyCharacteristics(key_name16, &client_id_blob, &app_data_blob,
+ &characteristics);
+ hardware_enforced_characteristics->Reinitialize(characteristics.characteristics.hw_enforced);
+ software_enforced_characteristics->Reinitialize(characteristics.characteristics.sw_enforced);
+ return mapKeystoreError(result);
+}
+
+int32_t KeystoreClientImpl::importKey(const std::string& key_name,
+ const AuthorizationSet& key_parameters,
+ keymaster_key_format_t key_format,
+ const std::string& key_data,
+ AuthorizationSet* hardware_enforced_characteristics,
+ AuthorizationSet* software_enforced_characteristics) {
+ String16 key_name16(key_name.data(), key_name.size());
+ KeymasterArguments key_arguments;
+ CopyParameters(key_parameters, &key_arguments.params);
+ KeyCharacteristics characteristics;
+ int32_t result =
+ keystore_->importKey(key_name16, key_arguments, key_format, StringAsByteArray(key_data),
+ key_data.size(), kDefaultUID, KEYSTORE_FLAG_NONE, &characteristics);
+ hardware_enforced_characteristics->Reinitialize(characteristics.characteristics.hw_enforced);
+ software_enforced_characteristics->Reinitialize(characteristics.characteristics.sw_enforced);
+ return mapKeystoreError(result);
+}
+
+int32_t KeystoreClientImpl::exportKey(keymaster_key_format_t export_format,
+ const std::string& key_name, std::string* export_data) {
+ String16 key_name16(key_name.data(), key_name.size());
+ keymaster_blob_t client_id_blob = {nullptr, 0};
+ keymaster_blob_t app_data_blob = {nullptr, 0};
+ ExportResult export_result;
+ keystore_->exportKey(key_name16, export_format, &client_id_blob, &app_data_blob,
+ &export_result);
+ *export_data = ByteArrayAsString(export_result.exportData.get(), export_result.dataLength);
+ return mapKeystoreError(export_result.resultCode);
+}
+
+int32_t KeystoreClientImpl::deleteKey(const std::string& key_name) {
+ String16 key_name16(key_name.data(), key_name.size());
+ return mapKeystoreError(keystore_->del(key_name16, kDefaultUID));
+}
+
+int32_t KeystoreClientImpl::deleteAllKeys() {
+ return mapKeystoreError(keystore_->clear_uid(kDefaultUID));
+}
+
+int32_t KeystoreClientImpl::beginOperation(keymaster_purpose_t purpose, const std::string& key_name,
+ const AuthorizationSet& input_parameters,
+ AuthorizationSet* output_parameters,
+ keymaster_operation_handle_t* handle) {
+ android::sp<android::IBinder> token(new android::BBinder);
+ String16 key_name16(key_name.data(), key_name.size());
+ KeymasterArguments input_arguments;
+ CopyParameters(input_parameters, &input_arguments.params);
+ OperationResult result;
+ keystore_->begin(token, key_name16, purpose, true /*pruneable*/, input_arguments,
+ NULL /*entropy*/, 0 /*entropyLength*/, &result);
+ int32_t error_code = mapKeystoreError(result.resultCode);
+ if (error_code == KM_ERROR_OK) {
+ *handle = getNextVirtualHandle();
+ active_operations_[*handle] = result.token;
+ if (!result.outParams.params.empty()) {
+ output_parameters->Reinitialize(&*result.outParams.params.begin(),
+ result.outParams.params.size());
+ }
+ }
+ return error_code;
+}
+
+int32_t KeystoreClientImpl::updateOperation(keymaster_operation_handle_t handle,
+ const AuthorizationSet& input_parameters,
+ const std::string& input_data,
+ size_t* num_input_bytes_consumed,
+ AuthorizationSet* output_parameters,
+ std::string* output_data) {
+ if (active_operations_.count(handle) == 0) {
+ return KM_ERROR_INVALID_OPERATION_HANDLE;
+ }
+ KeymasterArguments input_arguments;
+ CopyParameters(input_parameters, &input_arguments.params);
+ OperationResult result;
+ keystore_->update(active_operations_[handle], input_arguments, StringAsByteArray(input_data),
+ input_data.size(), &result);
+ int32_t error_code = mapKeystoreError(result.resultCode);
+ if (error_code == KM_ERROR_OK) {
+ *num_input_bytes_consumed = result.inputConsumed;
+ if (!result.outParams.params.empty()) {
+ output_parameters->Reinitialize(&*result.outParams.params.begin(),
+ result.outParams.params.size());
+ }
+ output_data->append(ByteArrayAsString(result.data.get(), result.dataLength));
+ }
+ return error_code;
+}
+
+int32_t KeystoreClientImpl::finishOperation(keymaster_operation_handle_t handle,
+ const AuthorizationSet& input_parameters,
+ const std::string& signature_to_verify,
+ AuthorizationSet* output_parameters,
+ std::string* output_data) {
+ if (active_operations_.count(handle) == 0) {
+ return KM_ERROR_INVALID_OPERATION_HANDLE;
+ }
+ KeymasterArguments input_arguments;
+ CopyParameters(input_parameters, &input_arguments.params);
+ OperationResult result;
+ keystore_->finish(active_operations_[handle], input_arguments,
+ StringAsByteArray(signature_to_verify), signature_to_verify.size(),
+ NULL /*entropy*/, 0 /*entropyLength*/, &result);
+ int32_t error_code = mapKeystoreError(result.resultCode);
+ if (error_code == KM_ERROR_OK) {
+ if (!result.outParams.params.empty()) {
+ output_parameters->Reinitialize(&*result.outParams.params.begin(),
+ result.outParams.params.size());
+ }
+ output_data->append(ByteArrayAsString(result.data.get(), result.dataLength));
+ active_operations_.erase(handle);
+ }
+ return error_code;
+}
+
+int32_t KeystoreClientImpl::abortOperation(keymaster_operation_handle_t handle) {
+ if (active_operations_.count(handle) == 0) {
+ return KM_ERROR_INVALID_OPERATION_HANDLE;
+ }
+ int32_t error_code = mapKeystoreError(keystore_->abort(active_operations_[handle]));
+ if (error_code == KM_ERROR_OK) {
+ active_operations_.erase(handle);
+ }
+ return error_code;
+}
+
+bool KeystoreClientImpl::doesKeyExist(const std::string& key_name) {
+ String16 key_name16(key_name.data(), key_name.size());
+ int32_t error_code = mapKeystoreError(keystore_->exist(key_name16, kDefaultUID));
+ return (error_code == KM_ERROR_OK);
+}
+
+bool KeystoreClientImpl::listKeys(const std::string& prefix,
+ std::vector<std::string>* key_name_list) {
+ String16 prefix16(prefix.data(), prefix.size());
+ android::Vector<String16> matches;
+ int32_t error_code = mapKeystoreError(keystore_->list(prefix16, kDefaultUID, &matches));
+ if (error_code == KM_ERROR_OK) {
+ for (const auto& match : matches) {
+ android::String8 key_name(match);
+ key_name_list->push_back(prefix + std::string(key_name.string(), key_name.size()));
+ }
+ return true;
+ }
+ return false;
+}
+
+keymaster_operation_handle_t KeystoreClientImpl::getNextVirtualHandle() {
+ return next_virtual_handle_++;
+}
+
+int32_t KeystoreClientImpl::mapKeystoreError(int32_t keystore_error) {
+ // See notes in keystore_client.h for rationale.
+ if (keystore_error == ::NO_ERROR) {
+ return KM_ERROR_OK;
+ }
+ return keystore_error;
+}
+
+bool KeystoreClientImpl::createOrVerifyEncryptionKey(const std::string& key_name) {
+ bool key_exists = doesKeyExist(key_name);
+ if (key_exists) {
+ bool verified = false;
+ if (!verifyEncryptionKeyAttributes(key_name, &verified)) {
+ return false;
+ }
+ if (!verified) {
+ int32_t result = deleteKey(key_name);
+ if (result != KM_ERROR_OK) {
+ ALOGE("Failed to delete invalid encryption key: %d", result);
+ return false;
+ }
+ key_exists = false;
+ }
+ }
+ if (!key_exists) {
+ AuthorizationSetBuilder key_parameters;
+ key_parameters.AesEncryptionKey(kAESKeySize)
+ .Padding(KM_PAD_PKCS7)
+ .Authorization(keymaster::TAG_BLOCK_MODE, KM_MODE_CBC)
+ .Authorization(keymaster::TAG_NO_AUTH_REQUIRED);
+ AuthorizationSet hardware_enforced_characteristics;
+ AuthorizationSet software_enforced_characteristics;
+ int32_t result =
+ generateKey(key_name, key_parameters.build(), &hardware_enforced_characteristics,
+ &software_enforced_characteristics);
+ if (result != KM_ERROR_OK) {
+ ALOGE("Failed to generate encryption key: %d", result);
+ return false;
+ }
+ if (hardware_enforced_characteristics.size() == 0) {
+ ALOGW("WARNING: Encryption key is not hardware-backed.");
+ }
+ }
+ return true;
+}
+
+bool KeystoreClientImpl::createOrVerifyAuthenticationKey(const std::string& key_name) {
+ bool key_exists = doesKeyExist(key_name);
+ if (key_exists) {
+ bool verified = false;
+ if (!verifyAuthenticationKeyAttributes(key_name, &verified)) {
+ return false;
+ }
+ if (!verified) {
+ int32_t result = deleteKey(key_name);
+ if (result != KM_ERROR_OK) {
+ ALOGE("Failed to delete invalid authentication key: %d", result);
+ return false;
+ }
+ key_exists = false;
+ }
+ }
+ if (!key_exists) {
+ AuthorizationSetBuilder key_parameters;
+ key_parameters.HmacKey(kHMACKeySize)
+ .Digest(KM_DIGEST_SHA_2_256)
+ .Authorization(keymaster::TAG_MIN_MAC_LENGTH, kHMACOutputSize)
+ .Authorization(keymaster::TAG_NO_AUTH_REQUIRED);
+ AuthorizationSet hardware_enforced_characteristics;
+ AuthorizationSet software_enforced_characteristics;
+ int32_t result =
+ generateKey(key_name, key_parameters.build(), &hardware_enforced_characteristics,
+ &software_enforced_characteristics);
+ if (result != KM_ERROR_OK) {
+ ALOGE("Failed to generate authentication key: %d", result);
+ return false;
+ }
+ if (hardware_enforced_characteristics.size() == 0) {
+ ALOGW("WARNING: Authentication key is not hardware-backed.");
+ }
+ }
+ return true;
+}
+
+bool KeystoreClientImpl::verifyEncryptionKeyAttributes(const std::string& key_name,
+ bool* verified) {
+ AuthorizationSet hardware_enforced_characteristics;
+ AuthorizationSet software_enforced_characteristics;
+ int32_t result = getKeyCharacteristics(key_name, &hardware_enforced_characteristics,
+ &software_enforced_characteristics);
+ if (result != KM_ERROR_OK) {
+ ALOGE("Failed to query encryption key: %d", result);
+ return false;
+ }
+ *verified = true;
+ keymaster_algorithm_t algorithm = KM_ALGORITHM_RSA;
+ if ((!hardware_enforced_characteristics.GetTagValue(keymaster::TAG_ALGORITHM, &algorithm) &&
+ !software_enforced_characteristics.GetTagValue(keymaster::TAG_ALGORITHM, &algorithm)) ||
+ algorithm != KM_ALGORITHM_AES) {
+ ALOGW("Found encryption key with invalid algorithm.");
+ *verified = false;
+ }
+ uint32_t key_size = 0;
+ if ((!hardware_enforced_characteristics.GetTagValue(keymaster::TAG_KEY_SIZE, &key_size) &&
+ !software_enforced_characteristics.GetTagValue(keymaster::TAG_KEY_SIZE, &key_size)) ||
+ key_size != kAESKeySize) {
+ ALOGW("Found encryption key with invalid size.");
+ *verified = false;
+ }
+ keymaster_block_mode_t block_mode = KM_MODE_ECB;
+ if ((!hardware_enforced_characteristics.GetTagValue(keymaster::TAG_BLOCK_MODE, &block_mode) &&
+ !software_enforced_characteristics.GetTagValue(keymaster::TAG_BLOCK_MODE, &block_mode)) ||
+ block_mode != KM_MODE_CBC) {
+ ALOGW("Found encryption key with invalid block mode.");
+ *verified = false;
+ }
+ keymaster_padding_t padding_mode = KM_PAD_NONE;
+ if ((!hardware_enforced_characteristics.GetTagValue(keymaster::TAG_PADDING, &padding_mode) &&
+ !software_enforced_characteristics.GetTagValue(keymaster::TAG_PADDING, &padding_mode)) ||
+ padding_mode != KM_PAD_PKCS7) {
+ ALOGW("Found encryption key with invalid padding mode.");
+ *verified = false;
+ }
+ if (hardware_enforced_characteristics.size() == 0) {
+ ALOGW("WARNING: Encryption key is not hardware-backed.");
+ }
+ return true;
+}
+
+bool KeystoreClientImpl::verifyAuthenticationKeyAttributes(const std::string& key_name,
+ bool* verified) {
+ AuthorizationSet hardware_enforced_characteristics;
+ AuthorizationSet software_enforced_characteristics;
+ int32_t result = getKeyCharacteristics(key_name, &hardware_enforced_characteristics,
+ &software_enforced_characteristics);
+ if (result != KM_ERROR_OK) {
+ ALOGE("Failed to query authentication key: %d", result);
+ return false;
+ }
+ *verified = true;
+ keymaster_algorithm_t algorithm = KM_ALGORITHM_RSA;
+ if ((!hardware_enforced_characteristics.GetTagValue(keymaster::TAG_ALGORITHM, &algorithm) &&
+ !software_enforced_characteristics.GetTagValue(keymaster::TAG_ALGORITHM, &algorithm)) ||
+ algorithm != KM_ALGORITHM_HMAC) {
+ ALOGW("Found authentication key with invalid algorithm.");
+ *verified = false;
+ }
+ uint32_t key_size = 0;
+ if ((!hardware_enforced_characteristics.GetTagValue(keymaster::TAG_KEY_SIZE, &key_size) &&
+ !software_enforced_characteristics.GetTagValue(keymaster::TAG_KEY_SIZE, &key_size)) ||
+ key_size != kHMACKeySize) {
+ ALOGW("Found authentication key with invalid size.");
+ *verified = false;
+ }
+ uint32_t mac_size = 0;
+ if ((!hardware_enforced_characteristics.GetTagValue(keymaster::TAG_MIN_MAC_LENGTH, &mac_size) &&
+ !software_enforced_characteristics.GetTagValue(keymaster::TAG_MIN_MAC_LENGTH,
+ &mac_size)) ||
+ mac_size != kHMACOutputSize) {
+ ALOGW("Found authentication key with invalid minimum mac size.");
+ *verified = false;
+ }
+ keymaster_digest_t digest = KM_DIGEST_NONE;
+ if ((!hardware_enforced_characteristics.GetTagValue(keymaster::TAG_DIGEST, &digest) &&
+ !software_enforced_characteristics.GetTagValue(keymaster::TAG_DIGEST, &digest)) ||
+ digest != KM_DIGEST_SHA_2_256) {
+ ALOGW("Found authentication key with invalid digest list.");
+ *verified = false;
+ }
+ if (hardware_enforced_characteristics.size() == 0) {
+ ALOGW("WARNING: Authentication key is not hardware-backed.");
+ }
+ return true;
+}
+
+} // namespace keystore