Limit maximum number of concurrent keystore operations. am: ddab0bb513
am: 7335397765

* commit '733539776541fa51bddf2d38fb57e556d563d9af':
  Limit maximum number of concurrent keystore operations.
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-engine/android_engine.cpp b/keystore-engine/android_engine.cpp
index bb23823..d23f169 100644
--- a/keystore-engine/android_engine.cpp
+++ b/keystore-engine/android_engine.cpp
@@ -220,9 +220,7 @@
   RSA_FLAG_CACHE_PUBLIC | RSA_FLAG_OPAQUE | RSA_FLAG_EXT_PKEY,
 
   NULL /* keygen */,
-#if defined(BORINGSSL_201509)
   NULL /* multi_prime_keygen */,
-#endif
   NULL /* supports_digest */,
 };
 
diff --git a/keystore/Android.mk b/keystore/Android.mk
index e18b2d8..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
@@ -37,7 +43,7 @@
 	libkeymaster1
 LOCAL_MODULE := keystore
 LOCAL_MODULE_TAGS := optional
-LOCAL_C_INCLUES := system/keymaster/
+LOCAL_INIT_RC := keystore.rc
 LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
 include $(BUILD_EXECUTABLE)
 
@@ -53,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.cpp b/keystore/keystore.cpp
index e466466..77b3039 100644
--- a/keystore/keystore.cpp
+++ b/keystore/keystore.cpp
@@ -331,6 +331,11 @@
 static const perm_t DEFAULT_PERMS = static_cast<perm_t>(P_GET_STATE | P_GET | P_INSERT | P_DELETE
                                                         | P_EXIST | P_LIST | P_SIGN | P_VERIFY);
 
+struct audit_data {
+    pid_t pid;
+    uid_t uid;
+};
+
 static char *tctx;
 static int ks_is_selinux_enabled;
 
@@ -360,11 +365,24 @@
     return uid / AID_USER;
 }
 
-static bool keystore_selinux_check_access(uid_t /*uid*/, perm_t perm, pid_t spid) {
+static int audit_callback(void *data, security_class_t /* cls */, char *buf, size_t len)
+{
+    struct audit_data *ad = reinterpret_cast<struct audit_data *>(data);
+    if (!ad) {
+        ALOGE("No keystore audit data");
+        return 0;
+    }
+
+    snprintf(buf, len, "pid=%d uid=%d", ad->pid, ad->uid);
+    return 0;
+}
+
+static bool keystore_selinux_check_access(uid_t uid, perm_t perm, pid_t spid) {
     if (!ks_is_selinux_enabled) {
         return true;
     }
 
+    audit_data ad;
     char *sctx = NULL;
     const char *selinux_class = "keystore_key";
     const char *str_perm = get_perm_label(perm);
@@ -378,8 +396,11 @@
         return false;
     }
 
+    ad.pid = spid;
+    ad.uid = uid;
+
     bool allowed = selinux_check_access(sctx, tctx, selinux_class, str_perm,
-            NULL) == 0;
+            reinterpret_cast<void *>(&ad)) == 0;
     freecon(sctx);
     return allowed;
 }
@@ -3327,6 +3348,8 @@
     ks_is_selinux_enabled = is_selinux_enabled();
     if (ks_is_selinux_enabled) {
         union selinux_callback cb;
+        cb.func_audit = audit_callback;
+        selinux_set_callback(SELINUX_CB_AUDIT, cb);
         cb.func_log = selinux_log_callback;
         selinux_set_callback(SELINUX_CB_LOG, cb);
         if (getcon(&tctx) != 0) {
diff --git a/keystore/keystore.rc b/keystore/keystore.rc
new file mode 100644
index 0000000..df48412
--- /dev/null
+++ b/keystore/keystore.rc
@@ -0,0 +1,4 @@
+service keystore /system/bin/keystore /data/misc/keystore
+    class main
+    user keystore
+    group keystore drmrpc
diff --git a/keystore/keystore_cli.cpp b/keystore/keystore_cli.cpp
index a3088e4..34f1d9c 100644
--- a/keystore/keystore_cli.cpp
+++ b/keystore/keystore_cli.cpp
@@ -104,7 +104,7 @@
             int uid = -1; \
             if (argc > 3) { \
                 uid = atoi(argv[3]); \
-                fprintf(stderr, "Running as uid %d\n", uid); \
+                fprintf(stderr, "Working with uid %d\n", uid); \
             } \
             int32_t ret = service->cmd(String16(argv[2]), uid); \
             if (ret < 0) { \
@@ -117,17 +117,28 @@
         } \
     } while (0)
 
-#define STING_ARG_DATA_STDIN_INT_RETURN(cmd) \
+#define STING_ARG_DATA_STDIN_PLUS_UID_PLUS_FLAGS_INT_RETURN(cmd) \
     do { \
         if (strcmp(argv[1], #cmd) == 0) { \
             if (argc < 3) { \
-                fprintf(stderr, "Usage: %s " #cmd " <name>\n", argv[0]); \
+                fprintf(stderr, "Usage: %s " #cmd " <name> [<uid>, <flags>]\n", argv[0]); \
                 return 1; \
             } \
             uint8_t* data; \
             size_t dataSize; \
             read_input(&data, &dataSize); \
-            int32_t ret = service->cmd(String16(argv[2]), data, dataSize); \
+            int uid = -1; \
+            if (argc > 3) { \
+                uid = atoi(argv[3]); \
+                fprintf(stderr, "Working with uid %d\n", uid); \
+            } \
+            int32_t flags = 0; \
+            if (argc > 4) { \
+                flags = int32_t(atoi(argv[4])); \
+                fprintf(stderr, "Using flags %04x\n", flags); \
+            } \
+            int32_t ret = service->cmd(String16(argv[2]), data, dataSize, uid, flags); \
+            free(data); \
             if (ret < 0) { \
                 fprintf(stderr, "%s: could not connect: %d\n", argv[0], ret); \
                 return 1; \
@@ -151,14 +162,16 @@
             if (ret < 0) { \
                 fprintf(stderr, "%s: could not connect: %d\n", argv[0], ret); \
                 return 1; \
-            } else if (ret != ::NO_ERROR) { \
+            } else if (ret) { \
                 fprintf(stderr, "%s: " #cmd ": %s (%d)\n", argv[0], responses[ret], ret); \
                 return 1; \
-            } else { \
+            } else if (dataSize) { \
                 fwrite(data, dataSize, 1, stdout); \
                 fflush(stdout); \
                 free(data); \
                 return 0; \
+            } else { \
+                return 1; \
             } \
         } \
     } while (0)
@@ -181,6 +194,39 @@
     }
 }
 
+#define BUF_SIZE 1024
+static void read_input(uint8_t** data, size_t* dataSize) {
+    char buffer[BUF_SIZE];
+    size_t contentSize = 0;
+    char *content = (char *) malloc(sizeof(char) * BUF_SIZE);
+
+    if (content == NULL) {
+        fprintf(stderr, "read_input: failed to allocate content");
+        exit(1);
+    }
+    content[0] = '\0';
+    while (fgets(buffer, BUF_SIZE, stdin)) {
+        char *old = content;
+        contentSize += strlen(buffer);
+        content = (char *) realloc(content, contentSize);
+        if (content == NULL) {
+            fprintf(stderr, "read_input: failed to reallocate content.");
+            free(old);
+            exit(1);
+        }
+        strcat(content, buffer);
+    }
+
+    if (ferror(stdin)) {
+        free(content);
+        fprintf(stderr, "read_input: error reading from stdin.");
+        exit(1);
+    }
+
+    *data = (uint8_t*) content;
+    *dataSize = contentSize;
+}
+
 int main(int argc, char* argv[])
 {
     if (argc < 2) {
@@ -205,7 +251,7 @@
 
     SINGLE_ARG_DATA_RETURN(get);
 
-    // TODO: insert
+    STING_ARG_DATA_STDIN_PLUS_UID_PLUS_FLAGS_INT_RETURN(insert);
 
     SINGLE_ARG_PLUS_UID_INT_RETURN(del);
 
@@ -230,7 +276,7 @@
 
     SINGLE_ARG_DATA_RETURN(get_pubkey);
 
-    // TODO: grant
+    SINGLE_ARG_PLUS_UID_INT_RETURN(grant);
 
     // TODO: ungrant
 
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
diff --git a/keystore/operation.cpp b/keystore/operation.cpp
index 4a71922..3b381c4 100644
--- a/keystore/operation.cpp
+++ b/keystore/operation.cpp
@@ -31,7 +31,7 @@
                                        keymaster_key_characteristics_t* characteristics,
                                        bool pruneable) {
     sp<IBinder> token = new BBinder();
-    mMap[token] = std::move(Operation(handle, keyid, purpose, dev, characteristics, appToken));
+    mMap[token] = Operation(handle, keyid, purpose, dev, characteristics, appToken);
     if (pruneable) {
         mLru.push_back(token);
     }
diff --git a/keystore/test-keystore b/keystore/test-keystore
index 3be51b3..071cfcd 100755
--- a/keystore/test-keystore
+++ b/keystore/test-keystore
@@ -44,7 +44,7 @@
 function run() {
     # strip out carriage returns from adb
     # strip out date/time from ls -l
-    "$@" | tr --delete '\r' | sed -E 's/[0-9]{4}-[0-9]{2}-[0-9]{2} +[0-9]{1,2}:[0-9]{2} //' >> $log_file
+    "$@" | tr -d '\r' | sed -E 's/[0-9]{4}-[0-9]{2}-[0-9]{2} +[0-9]{1,2}:[0-9]{2} //' >> $log_file
 }
 
 function keystore() {
@@ -53,8 +53,15 @@
     run adb shell su $user keystore_cli "$@"
 }
 
+function keystore_in() {
+    declare -r user=$1
+    declare -r input=$2
+    shift; shift
+    run adb shell "echo '$input' | su $user keystore_cli $@"
+}
+
 function list_keystore_directory() {
-    run adb shell ls -al /data/misc/keystore
+    run adb shell ls -al /data/misc/keystore$@
 }
 
 function compare() {
@@ -68,195 +75,211 @@
     # reset
     #
     log "reset keystore as system user"
-    keystore system r
-    expect "1 No error"
+    keystore system reset
+    expect "reset: No error (1)"
     list_keystore_directory
+    expect "-rw------- keystore keystore        4 .metadata"
+    expect "drwx------ keystore keystore          user_0"
 
     #
     # basic tests as system/root
     #
     log "root does not have permission to run test"
-    keystore root t
-    expect "6 Permission denied"
-    
+    keystore root test
+    expect "test: Permission denied (6)"
+
     log "but system user does"
-    keystore system t
-    expect "3 Uninitialized"
+    keystore system test
+    expect "test: Uninitialized (3)"
     list_keystore_directory
+    expect "-rw------- keystore keystore        4 .metadata"
+    expect "drwx------ keystore keystore          user_0"
 
     log "password is now bar"
-    keystore system p bar
-    expect "1 No error"
-    list_keystore_directory
+    keystore system password bar
+    expect "password: No error (1)"
+    list_keystore_directory /user_0
     expect "-rw------- keystore keystore       84 .masterkey"
-    
+
     log "no error implies initialized and unlocked"
-    keystore system t
-    expect "1 No error"
-    
+    keystore system test
+    expect "test: No error (1)"
+
     log "saw with no argument"
-    keystore system s
-    expect "5 Protocol error"
+    keystore system saw
 
     log "saw nothing"
-    keystore system s ""
-    expect "1 No error"
+    keystore system saw ""
 
     log "add key baz"
-    keystore system i baz quux
-    expect "1 No error"
+    keystore_in system quux insert baz
+    expect "insert: No error (1)"
 
     log "1000 is uid of system"
-    list_keystore_directory
+    list_keystore_directory /user_0
     expect "-rw------- keystore keystore       84 .masterkey"
     expect "-rw------- keystore keystore       52 1000_baz"
 
     log "saw baz"
-    keystore system s ""
-    expect "1 No error"
+    keystore system saw
     expect "baz"
 
     log "get baz"
-    keystore system g baz
-    expect "1 No error"
+    keystore system get baz
     expect "quux"
 
     log "root can read system user keys (as can wifi or vpn users)"
-    keystore root g baz
-    expect "1 No error"
+    keystore root get baz
     expect "quux"
 
     #
     # app user tests
     #
 
-    # app_0 has uid 10000, as seen below
+    # u0_a0 has uid 10000, as seen below
     log "other uses cannot see the system keys"
-    keystore app_0 g baz
-    expect "7 Key not found"
-    
-    log "app user cannot use reset, password, lock, unlock"
-    keystore app_0 r
-    expect "6 Permission denied"
-    keystore app_0 p
-    expect "6 Permission denied"
-    keystore app_0 l
-    expect "6 Permission denied"
-    keystore app_0 u
-    expect "6 Permission denied"
+    keystore u0_a0 get baz
 
-    log "install app_0 key"
-    keystore app_0 i 0x deadbeef
-    expect 1 No error
-    list_keystore_directory
+    log "app user cannot use reset, password, lock, unlock"
+    keystore u0_a0 reset
+    expect "reset: Permission denied (6)"
+    keystore u0_a0 password some_pass
+    expect "password: Permission denied (6)"
+    keystore u0_a0 lock
+    expect "lock: Permission denied (6)"
+    keystore u0_a0 unlock some_pass
+    expect "unlock: Permission denied (6)"
+
+    log "install u0_a0 key"
+    keystore_in u0_a0 deadbeef insert 0x
+    expect "insert: No error (1)"
+    list_keystore_directory /user_0
     expect "-rw------- keystore keystore       84 .masterkey"
     expect "-rw------- keystore keystore       52 10000_0x"
     expect "-rw------- keystore keystore       52 1000_baz"
 
     log "get with no argument"
-    keystore app_0 g
-    expect "5 Protocol error"
-    
-    keystore app_0 g 0x
-    expect "1 No error"
+    keystore u0_a0 get
+    expect "Usage: keystore_cli get <name>"
+
+    log "few get tests for an app"
+    keystore u0_a0 get 0x
     expect "deadbeef"
-    
-    keystore app_0 i fred barney
-    expect "1 No error"
-    
-    keystore app_0 s ""
-    expect "1 No error"
+
+    keystore_in u0_a0 barney insert fred
+    expect "insert: No error (1)"
+
+    keystore u0_a0 saw
     expect "0x"
     expect "fred"
 
     log "note that saw returns the suffix of prefix matches"
-    keystore app_0 s fr # fred
-    expect "1 No error"
+    keystore u0_a0 saw fr # fred
     expect "ed" # fred
 
     #
     # lock tests
     #
     log "lock the store as system"
-    keystore system l
-    expect "1 No error"
-    keystore system t
-    expect "2 Locked"
-    
+    keystore system lock
+    expect "lock: No error (1)"
+    keystore system test
+    expect "test: Locked (2)"
+
     log "saw works while locked"
-    keystore app_0 s ""
-    expect "1 No error"
+    keystore u0_a0 saw
     expect "0x"
     expect "fred"
 
-    log "...but cannot read keys..."
-    keystore app_0 g 0x
-    expect "2 Locked"
-    
-    log "...but they can be deleted."
-    keystore app_0 e 0x
-    expect "1 No error"
-    keystore app_0 d 0x
-    expect "1 No error"
-    keystore app_0 e 0x
-    expect "7 Key not found"
+    log "...and app can read keys..."
+    keystore u0_a0 get 0x
+    expect "deadbeef"
+
+    log "...but they cannot be deleted."
+    keystore u0_a0 exist 0x
+    expect "exist: No error (1)"
+    keystore u0_a0 del_key 0x
+    expect "del_key: Key not found (7)"
 
     #
     # password
     #
     log "wrong password"
-    keystore system u foo
-    expect "13 Wrong password (4 tries left)"
+    keystore system unlock foo
+    expect "unlock: Wrong password (4 tries left) (13)"
     log "right password"
-    keystore system u bar
-    expect "1 No error"
-    
+    keystore system unlock bar
+    expect "unlock: No error (1)"
+
     log "make the password foo"
-    keystore system p foo
-    expect "1 No error"
-    
+    keystore system password foo
+    expect "password: No error (1)"
+
     #
     # final reset
     #
     log "reset wipes everything for all users"
-    keystore system r
-    expect "1 No error"
+    keystore system reset
+    expect "reset: No error (1)"
     list_keystore_directory
-    
-    keystore system t
-    expect "3 Uninitialized"
+    expect "-rw------- keystore keystore        4 .metadata"
+    expect "drwx------ keystore keystore          user_0"
+    list_keystore_directory /user_0
 
+    keystore system test
+    expect "test: Uninitialized (3)"
+}
+
+function test_grant() {
+    log "test granting"
+    keystore system reset
+    expect "reset: No error (1)"
+    keystore system password test_pass
+    expect "password: No error (1)"
+
+    keystore_in system granted_key_value insert granted_key
+    expect "insert: No error (1)"
+  
+    # Cannot read before grant.
+    keystore u10_a0 get granted_key
+    
+    # Grant and read.
+    log "System grants to u0_a1"
+    keystore system grant granted_key 10001 
+    expect "Working with uid 10001"
+    expect "grant: No error (1)"
+    keystore u0_a1 get 1000_granted_key
+    expect "granted_key_value"
 }
 
 function test_4599735() {
     # http://b/4599735
     log "start regression test for b/4599735"
-    keystore system r
-    expect "1 No error"
+    keystore system reset
+    expect "reset: No error (1)"
+    list_keystore_directory /user_0
 
-    keystore system p foo
-    expect "1 No error"
+    keystore system password foo
+    expect "password: No error (1)"
 
-    keystore system i baz quux
-    expect "1 No error"
-    
-    keystore root g baz
-    expect "1 No error"
+    keystore_in system quux insert baz
+    expect "insert: No error (1)"
+
+    keystore root get baz
     expect "quux"
 
-    keystore system l
-    expect "1 No error"
+    keystore system lock
+    expect "lock: No error (1)"
 
-    keystore system p foo
-    expect "1 No error"
+    keystore system password foo
+    expect "password: No error (1)"
 
     log "after unlock, regression led to result of '8 Value corrupted'"
-    keystore root g baz
-    expect "1 No error"
+    keystore root get baz
     expect "quux"
 
-    keystore system r
-    expect "1 No error"
+    keystore system reset
+    expect "reset: No error (1)"
     log "end regression test for b/4599735"
 }
 
@@ -265,6 +288,7 @@
     log $tag START
     test_basic
     test_4599735
+    test_grant
     compare
     log $tag PASSED
     cleanup_output