Port to binderized keymaster HAL
This patch ports keystore to the HIDL based binderized keymaster HAL.
Keystore has no more dependencies on legacy keymaster headers, and
therefore data structures, constant declarations, or enums. All
keymaster related data structures and enums used by keystore are the
once defined by the HIDL based keymaster HAL definition. In the process
of porting, keystore underwent some changes:
* Keystore got a new implementation of AuthorizationSet that is fully
based on the new HIDL data structures. Key parameters are now either
organised as AuthorizationSets or hidl_vec<KeyParameter>. (Formerly,
this was a mixture of keymaster's AuthorizationSet,
std::vec<keymaster_key_param_t>, and keymaster_key_param_set_t.) The
former is used for memory management and provides algorithms for
assembling, joining, and subtracting sets of parameters. The latter
is used as wire format for the HAL IPC; it can wrap the memory owned
by an AuthorizationSet for this purpose. The AuthorizationSet is
accompanied by a new implementation of type safe functions for
creating and accessing tagged key parameters,
Authorizations (keystore/keymaster_tags.h).
* A new type (KSSReturnCode) was introduced that wraps keystore service
response codes. Keystore has two sets of error codes. ErrorCode
errors are less than 0 and use 0 as success value. ResponseCode
errors are greater than zero and use 1 as success value. This patch
changes ResponseCode to be an enum class so that is no longer
assignable to int without a cast. The new return type can only be
initialized by ResponseCode or ErrorCode and when accessed as int32_t,
which happens on serialization when the response is send to a client,
the success values are coalesced onto 1 as expected by the
clients. KSSreturnCode is also comparable to ResponseCode and
ErrorCode, and the predicate isOk() returns true if it was initialized
with either ErrorCode::OK (0) or ReponseCode::NO_ERROR (1).
* A bug was fixed, that caused the keystore verify function to return
success, regardless of the input, internal errors, or lack of
permissions.
* The marshalling code in IKeystoreService.cpp was rewritten. For data
structures that are known to keymaster, the client facing side of
keystore uses HIDL based data structures as (target) source
for (un)marshaling to avoid further conversion. hidl_vecs are used to
wrap parcel memory without copying and taking ownership where
possible.
* Explicit use of malloc is reduced (malloc was required by the C nature
of the old HAL). The new implementations avoid explicit use of
malloc/new and waive the use of pointers for return values. Instead,
functions return by value objects that take ownership of secondary
memory allocations where required.
Test: runtest --path=cts/tests/tests/keystore/src/android/keystore/cts
Bug: 32020919
Change-Id: I59d3a0f4a6bdf6bb3bbf791ad8827c463effa286
diff --git a/keystore-engine/Android.mk b/keystore-engine/Android.mk
index b4ba269..6d6abe0 100644
--- a/keystore-engine/Android.mk
+++ b/keystore-engine/Android.mk
@@ -25,12 +25,13 @@
LOCAL_CFLAGS := -fvisibility=hidden -Wall -Werror
LOCAL_SHARED_LIBRARIES += \
- libcrypto \
- liblog \
- libcutils \
- libutils \
libbinder \
- libkeystore_binder
+ libcrypto \
+ libcutils \
+ libhidlbase \
+ libkeystore_binder \
+ liblog \
+ libutils
LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
diff --git a/keystore-engine/android_engine.cpp b/keystore-engine/android_engine.cpp
index de67df2..6295873 100644
--- a/keystore-engine/android_engine.cpp
+++ b/keystore-engine/android_engine.cpp
@@ -20,6 +20,8 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
+#define LOG_TAG "keystore-engine"
+
#include <UniquePtr.h>
#include <sys/socket.h>
@@ -39,10 +41,12 @@
#include <binder/IServiceManager.h>
#include <keystore/keystore.h>
#include <keystore/IKeystoreService.h>
+#include <keystore/keystore_hidl_support.h>
using namespace android;
namespace {
+using namespace keystore;
extern const RSA_METHOD keystore_rsa_method;
extern const ECDSA_METHOD keystore_ecdsa_method;
@@ -153,41 +157,35 @@
ALOGE("could not contact keystore");
return 0;
}
+ auto inBlob = blob2hidlVec(in ,len);
+ hidl_vec<uint8_t> reply;
- uint8_t* reply = NULL;
- size_t reply_len;
- int32_t ret = service->sign(String16(key_id), in, len, &reply, &reply_len);
- if (ret < 0) {
- ALOGW("There was an error during rsa_decrypt: could not connect");
+ auto ret = service->sign(String16(key_id), inBlob, &reply);
+ if (!ret.isOk()) {
+ ALOGW("Error during sign from keystore: %d", int32_t(ret));
return 0;
- } else if (ret != 0) {
- ALOGW("Error during sign from keystore: %d", ret);
- return 0;
- } else if (reply_len == 0) {
+ } else if (reply.size() == 0) {
ALOGW("No valid signature returned");
- free(reply);
return 0;
}
- if (reply_len > len) {
+ if (reply.size() > len) {
/* The result of the RSA operation can never be larger than the size of
* the modulus so we assume that the result has extra zeros on the
* left. This provides attackers with an oracle, but there's nothing
* that we can do about it here. */
- memcpy(out, reply + reply_len - len, len);
- } else if (reply_len < len) {
+ memcpy(out, &reply[reply.size() - len], len);
+ } else if (reply.size() < len) {
/* If the Keystore implementation returns a short value we assume that
* it's because it removed leading zeros from the left side. This is
* bad because it provides attackers with an oracle but we cannot do
* anything about a broken Keystore implementation here. */
memset(out, 0, len);
- memcpy(out + len - reply_len, reply, reply_len);
+ memcpy(out + len - reply.size(), &reply[0], reply.size());
} else {
- memcpy(out, reply, len);
+ memcpy(out, &reply[0], len);
}
- free(reply);
-
ALOGV("rsa=%p keystore_rsa_priv_dec successful", rsa);
return 1;
}
@@ -253,28 +251,24 @@
size_t ecdsa_size = ECDSA_size(ec_key);
- uint8_t* reply = NULL;
- size_t reply_len;
- int32_t ret = service->sign(String16(reinterpret_cast<const char*>(key_id)),
- digest, digest_len, &reply, &reply_len);
- if (ret < 0) {
- ALOGW("There was an error during ecdsa_sign: could not connect");
+ auto hidlDigest = blob2hidlVec(digest, digest_len);
+ hidl_vec<uint8_t> reply;
+ auto ret = service->sign(String16(reinterpret_cast<const char*>(key_id)),
+ hidlDigest, &reply);
+ if (!ret.isOk()) {
+ ALOGW("Error during sign from keystore: %d", int32_t(ret));
return 0;
- } else if (ret != 0) {
- ALOGW("Error during sign from keystore: %d", ret);
- return 0;
- } else if (reply_len == 0) {
+ } else if (reply.size() == 0) {
ALOGW("No valid signature returned");
- free(reply);
return 0;
- } else if (reply_len > ecdsa_size) {
+ } else if (reply.size() > ecdsa_size) {
ALOGW("Signature is too large");
- free(reply);
return 0;
}
- memcpy(sig, reply, reply_len);
- *sig_len = reply_len;
+ // Reviewer: should't sig_len be checked here? Or is it just assumed that it is at least ecdsa_size?
+ memcpy(sig, &reply[0], reply.size());
+ *sig_len = reply.size();
ALOGV("ecdsa_sign(%p, %u, %p) => success", digest, (unsigned)digest_len,
ec_key);
@@ -410,20 +404,15 @@
return 0;
}
- uint8_t *pubkey = NULL;
- size_t pubkey_len;
- int32_t ret = service->get_pubkey(String16(key_id), &pubkey, &pubkey_len);
- if (ret < 0) {
- ALOGW("could not contact keystore");
- return NULL;
- } else if (ret != 0) {
- ALOGW("keystore reports error: %d", ret);
+ hidl_vec<uint8_t> pubkey;
+ auto ret = service->get_pubkey(String16(key_id), &pubkey);
+ if (!ret.isOk()) {
+ ALOGW("keystore reports error: %d", int32_t(ret));
return NULL;
}
- const uint8_t *inp = pubkey;
- Unique_EVP_PKEY pkey(d2i_PUBKEY(NULL, &inp, pubkey_len));
- free(pubkey);
+ const uint8_t *inp = &pubkey[0];
+ Unique_EVP_PKEY pkey(d2i_PUBKEY(NULL, &inp, pubkey.size()));
if (pkey.get() == NULL) {
ALOGW("Cannot convert pubkey");
return NULL;
diff --git a/keystore/Android.mk b/keystore/Android.mk
index 91a63e5..500c2f6 100644
--- a/keystore/Android.mk
+++ b/keystore/Android.mk
@@ -38,6 +38,8 @@
keystore.cpp \
keystore_main.cpp \
keystore_utils.cpp \
+ legacy_keymaster_device_wrapper.cpp \
+ keymaster_enforcement.cpp \
operation.cpp \
permissions.cpp \
user_state.cpp \
@@ -54,7 +56,11 @@
libselinux \
libsoftkeymasterdevice \
libkeymaster_messages \
- libkeymaster1
+ libkeymaster1 \
+ libhwbinder \
+ libhidlbase \
+ libhidltransport \
+ android.hardware.keymaster@3.0
LOCAL_MODULE := keystore
LOCAL_MODULE_TAGS := optional
LOCAL_INIT_RC := keystore.rc
@@ -72,7 +78,10 @@
endif
LOCAL_CFLAGS := -Wall -Wextra -Werror
LOCAL_SRC_FILES := keystore_cli.cpp
-LOCAL_SHARED_LIBRARIES := libcutils libcrypto libkeystore_binder libutils liblog libbinder
+LOCAL_SHARED_LIBRARIES := libcutils libcrypto libkeystore_binder libutils liblog libbinder \
+ libhwbinder \
+ libhidlbase \
+ android.hardware.keymaster@3.0
LOCAL_MODULE := keystore_cli
LOCAL_MODULE_TAGS := debug
LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
@@ -86,8 +95,11 @@
LOCAL_SRC_FILES := keystore_cli_v2.cpp
LOCAL_SHARED_LIBRARIES := \
libchrome \
- libkeymaster_messages \
- libkeystore_binder
+ libkeystore_binder \
+ libhwbinder \
+ libhidlbase \
+ android.hardware.keymaster@3.0
+
LOCAL_MODULE := keystore_cli_v2
LOCAL_MODULE_TAGS := debug
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include external/gtest/include
@@ -108,20 +120,27 @@
keyblob_utils.cpp \
keystore_client.proto \
keystore_client_impl.cpp \
- keystore_get.cpp
+ keystore_get.cpp \
+ authorization_set.cpp \
+ keystore_tags_utils.cpp \
+ keystore_aidl_hidl_marshalling_utils.cpp
LOCAL_SHARED_LIBRARIES := \
libbinder \
- libkeymaster_messages \
liblog \
libprotobuf-cpp-lite \
- libsoftkeymasterdevice \
- libutils
+ libutils \
+ libhwbinder \
+ libhidlbase \
+ android.hardware.keymaster@3.0
LOCAL_MODULE_CLASS := SHARED_LIBRARIES
LOCAL_MODULE := libkeystore_binder
LOCAL_MODULE_TAGS := optional
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include $(call keystore_proto_include)
LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
-LOCAL_EXPORT_SHARED_LIBRARY_HEADERS := libbinder
+LOCAL_EXPORT_SHARED_LIBRARY_HEADERS := libbinder \
+ libhwbinder \
+ libhidlbase \
+ android.hardware.keymaster@3.0
LOCAL_CLANG := true
LOCAL_SANITIZE := integer
LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
@@ -137,7 +156,12 @@
LOCAL_MODULE := libkeystore_test
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include
LOCAL_STATIC_LIBRARIES := libgtest_main
-LOCAL_SHARED_LIBRARIES := libkeymaster_messages
+LOCAL_SHARED_LIBRARIES := libkeymaster_messages \
+ libutils \
+ libhwbinder \
+ libhidlbase \
+ android.hardware.keymaster@3.0
+
LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
include $(BUILD_STATIC_LIBRARY)
diff --git a/keystore/IKeystoreService.cpp b/keystore/IKeystoreService.cpp
index acd6968..4c26b60 100644
--- a/keystore/IKeystoreService.cpp
+++ b/keystore/IKeystoreService.cpp
@@ -19,28 +19,31 @@
#include <sys/limits.h>
#include <sys/types.h>
+#include <algorithm>
+#include <limits>
+
#define LOG_TAG "KeystoreService"
#include <utils/Log.h>
-#include <binder/Parcel.h>
#include <binder/IPCThreadState.h>
#include <binder/IServiceManager.h>
+#include <binder/Parcel.h>
#include <keystore/IKeystoreService.h>
+#include <keystore/keystore_hidl_support.h>
+
+#include "keystore_aidl_hidl_marshalling_utils.h"
namespace android {
+using namespace ::keystore;
const ssize_t MAX_GENERATE_ARGS = 3;
-static keymaster_key_param_t* readParamList(const Parcel& in, size_t* length);
-KeystoreArg::KeystoreArg(const void* data, size_t len)
- : mData(data), mSize(len) {
-}
+KeystoreArg::KeystoreArg(const void* data, size_t len) : mData(data), mSize(len) {}
-KeystoreArg::~KeystoreArg() {
-}
+KeystoreArg::~KeystoreArg() {}
-const void *KeystoreArg::data() const {
+const void* KeystoreArg::data() const {
return mData;
}
@@ -48,36 +51,18 @@
return mSize;
}
-OperationResult::OperationResult() : resultCode(0), token(), handle(0), inputConsumed(0),
- data(NULL), dataLength(0) {
-}
+OperationResult::OperationResult() : resultCode(), token(), handle(0), inputConsumed(0), data() {}
-OperationResult::~OperationResult() {
-}
+OperationResult::~OperationResult() {}
status_t OperationResult::readFromParcel(const Parcel* inn) {
const Parcel& in = *inn;
- resultCode = in.readInt32();
+ resultCode = ErrorCode(in.readInt32());
token = in.readStrongBinder();
- handle = static_cast<keymaster_operation_handle_t>(in.readInt64());
+ handle = static_cast<uint64_t>(in.readInt64());
inputConsumed = in.readInt32();
- ssize_t length = in.readInt32();
- dataLength = 0;
- if (length > 0) {
- const void* buf = in.readInplace(length);
- if (buf) {
- data.reset(reinterpret_cast<uint8_t*>(malloc(length)));
- if (data.get()) {
- memcpy(data.get(), buf, length);
- dataLength = (size_t) length;
- } else {
- ALOGE("Failed to allocate OperationResult buffer");
- }
- } else {
- ALOGE("Failed to readInplace OperationResult data");
- }
- }
- outParams.readFromParcel(in);
+ data = readKeymasterBlob(in);
+ outParams = readParamSetFromParcel(in);
return OK;
}
@@ -86,322 +71,28 @@
out->writeStrongBinder(token);
out->writeInt64(handle);
out->writeInt32(inputConsumed);
- out->writeInt32(dataLength);
- if (dataLength && data) {
- void* buf = out->writeInplace(dataLength);
- if (buf) {
- memcpy(buf, data.get(), dataLength);
- } else {
- ALOGE("Failed to writeInplace OperationResult data.");
- }
- }
- outParams.writeToParcel(out);
+ writeKeymasterBlob(data, out);
+ writeParamSetToParcel(outParams, out);
return OK;
}
-ExportResult::ExportResult() : resultCode(0), exportData(NULL), dataLength(0) {
-}
+ExportResult::ExportResult() : resultCode() {}
-ExportResult::~ExportResult() {
-}
+ExportResult::~ExportResult() {}
status_t ExportResult::readFromParcel(const Parcel* inn) {
const Parcel& in = *inn;
- resultCode = in.readInt32();
- ssize_t length = in.readInt32();
- dataLength = 0;
- if (length > 0) {
- const void* buf = in.readInplace(length);
- if (buf) {
- exportData.reset(reinterpret_cast<uint8_t*>(malloc(length)));
- if (exportData.get()) {
- memcpy(exportData.get(), buf, length);
- dataLength = (size_t) length;
- } else {
- ALOGE("Failed to allocate ExportData buffer");
- }
- } else {
- ALOGE("Failed to readInplace ExportData data");
- }
- }
+ resultCode = ErrorCode(in.readInt32());
+ exportData = readKeymasterBlob(in);
return OK;
}
status_t ExportResult::writeToParcel(Parcel* out) const {
out->writeInt32(resultCode);
- out->writeInt32(dataLength);
- if (exportData && dataLength) {
- void* buf = out->writeInplace(dataLength);
- if (buf) {
- memcpy(buf, exportData.get(), dataLength);
- } else {
- ALOGE("Failed to writeInplace ExportResult data.");
- }
- }
+ writeKeymasterBlob(exportData, out);
return OK;
}
-KeymasterArguments::KeymasterArguments() {
-}
-
-KeymasterArguments::~KeymasterArguments() {
- keymaster_free_param_values(params.data(), params.size());
-}
-
-void KeymasterArguments::readFromParcel(const Parcel& in) {
- ssize_t length = in.readInt32();
- size_t ulength = (size_t) length;
- if (length < 0) {
- ulength = 0;
- }
- keymaster_free_param_values(params.data(), params.size());
- params.clear();
- for(size_t i = 0; i < ulength; i++) {
- keymaster_key_param_t param;
- if (!readKeymasterArgumentFromParcel(in, ¶m)) {
- ALOGE("Error reading keymaster argument from parcel");
- break;
- }
- params.push_back(param);
- }
-}
-
-void KeymasterArguments::writeToParcel(Parcel* out) const {
- out->writeInt32(params.size());
- for (auto param : params) {
- out->writeInt32(1);
- writeKeymasterArgumentToParcel(param, out);
- }
-}
-
-KeyCharacteristics::KeyCharacteristics() {
- memset((void*) &characteristics, 0, sizeof(characteristics));
-}
-
-KeyCharacteristics::~KeyCharacteristics() {
- keymaster_free_characteristics(&characteristics);
-}
-
-status_t KeyCharacteristics::readFromParcel(const Parcel* inn) {
- const Parcel& in = *inn;
- size_t length = 0;
- keymaster_key_param_t* params = readParamList(in, &length);
- characteristics.sw_enforced.params = params;
- characteristics.sw_enforced.length = length;
-
- params = readParamList(in, &length);
- characteristics.hw_enforced.params = params;
- characteristics.hw_enforced.length = length;
- return OK;
-}
-
-status_t KeyCharacteristics::writeToParcel(Parcel* out) const {
- if (characteristics.sw_enforced.params) {
- out->writeInt32(characteristics.sw_enforced.length);
- for (size_t i = 0; i < characteristics.sw_enforced.length; i++) {
- out->writeInt32(1);
- writeKeymasterArgumentToParcel(characteristics.sw_enforced.params[i], out);
- }
- } else {
- out->writeInt32(0);
- }
- if (characteristics.hw_enforced.params) {
- out->writeInt32(characteristics.hw_enforced.length);
- for (size_t i = 0; i < characteristics.hw_enforced.length; i++) {
- out->writeInt32(1);
- writeKeymasterArgumentToParcel(characteristics.hw_enforced.params[i], out);
- }
- } else {
- out->writeInt32(0);
- }
- return OK;
-}
-
-KeymasterCertificateChain::KeymasterCertificateChain() {
- memset(&chain, 0, sizeof(chain));
-}
-
-KeymasterCertificateChain::~KeymasterCertificateChain() {
- keymaster_free_cert_chain(&chain);
-}
-
-static bool readKeymasterBlob(const Parcel& in, keymaster_blob_t* blob) {
- if (in.readInt32() != 1) {
- return false;
- }
-
- ssize_t length = in.readInt32();
- if (length <= 0) {
- return false;
- }
-
- blob->data = static_cast<const uint8_t*>(malloc(length));
- if (!blob->data)
- return false;
-
- const void* buf = in.readInplace(length);
- if (!buf)
- return false;
-
- blob->data_length = static_cast<size_t>(length);
- memcpy(const_cast<uint8_t*>(blob->data), buf, length);
-
- return true;
-}
-
-void KeymasterCertificateChain::readFromParcel(const Parcel& in) {
- keymaster_free_cert_chain(&chain);
-
- ssize_t count = in.readInt32();
- size_t ucount = count;
- if (count <= 0) {
- return;
- }
-
- chain.entries = reinterpret_cast<keymaster_blob_t*>(malloc(sizeof(keymaster_blob_t) * ucount));
- if (!chain.entries) {
- ALOGE("Error allocating memory for certificate chain");
- return;
- }
-
- memset(chain.entries, 0, sizeof(keymaster_blob_t) * ucount);
- for (size_t i = 0; i < ucount; ++i) {
- if (!readKeymasterBlob(in, &chain.entries[i])) {
- ALOGE("Error reading certificate from parcel");
- keymaster_free_cert_chain(&chain);
- return;
- }
- }
-}
-
-void KeymasterCertificateChain::writeToParcel(Parcel* out) const {
- out->writeInt32(chain.entry_count);
- for (size_t i = 0; i < chain.entry_count; ++i) {
- if (chain.entries[i].data) {
- out->writeInt32(chain.entries[i].data_length);
- void* buf = out->writeInplace(chain.entries[i].data_length);
- if (buf) {
- memcpy(buf, chain.entries[i].data, chain.entries[i].data_length);
- } else {
- ALOGE("Failed to writeInplace keymaster cert chain entry");
- }
- } else {
- out->writeInt32(0); // Tell Java side this object is NULL.
- ALOGE("Found NULL certificate chain entry");
- }
- }
-}
-
-void writeKeymasterArgumentToParcel(const keymaster_key_param_t& param, Parcel* out) {
- switch (keymaster_tag_get_type(param.tag)) {
- case KM_ENUM:
- case KM_ENUM_REP: {
- out->writeInt32(param.tag);
- out->writeInt32(param.enumerated);
- break;
- }
- case KM_UINT:
- case KM_UINT_REP: {
- out->writeInt32(param.tag);
- out->writeInt32(param.integer);
- break;
- }
- case KM_ULONG:
- case KM_ULONG_REP: {
- out->writeInt32(param.tag);
- out->writeInt64(param.long_integer);
- break;
- }
- case KM_DATE: {
- out->writeInt32(param.tag);
- out->writeInt64(param.date_time);
- break;
- }
- case KM_BOOL: {
- out->writeInt32(param.tag);
- break;
- }
- case KM_BIGNUM:
- case KM_BYTES: {
- out->writeInt32(param.tag);
- out->writeInt32(param.blob.data_length);
- void* buf = out->writeInplace(param.blob.data_length);
- if (buf) {
- memcpy(buf, param.blob.data, param.blob.data_length);
- } else {
- ALOGE("Failed to writeInplace keymaster blob param");
- }
- break;
- }
- default: {
- ALOGE("Failed to write argument: Unsupported keymaster_tag_t %d", param.tag);
- }
- }
-}
-
-
-bool readKeymasterArgumentFromParcel(const Parcel& in, keymaster_key_param_t* out) {
- if (in.readInt32() == 0) {
- return false;
- }
- keymaster_tag_t tag = static_cast<keymaster_tag_t>(in.readInt32());
- switch (keymaster_tag_get_type(tag)) {
- case KM_ENUM:
- case KM_ENUM_REP: {
- uint32_t value = in.readInt32();
- *out = keymaster_param_enum(tag, value);
- break;
- }
- case KM_UINT:
- case KM_UINT_REP: {
- uint32_t value = in.readInt32();
- *out = keymaster_param_int(tag, value);
- break;
- }
- case KM_ULONG:
- case KM_ULONG_REP: {
- uint64_t value = in.readInt64();
- *out = keymaster_param_long(tag, value);
- break;
- }
- case KM_DATE: {
- uint64_t value = in.readInt64();
- *out = keymaster_param_date(tag, value);
- break;
- }
- case KM_BOOL: {
- *out = keymaster_param_bool(tag);
- break;
- }
- case KM_BIGNUM:
- case KM_BYTES: {
- ssize_t length = in.readInt32();
- uint8_t* data = NULL;
- size_t ulength = 0;
- if (length >= 0) {
- ulength = (size_t) length;
- // use malloc here so we can use keymaster_free_param_values
- // consistently.
- data = reinterpret_cast<uint8_t*>(malloc(ulength));
- const void* buf = in.readInplace(ulength);
- if (!buf || !data) {
- ALOGE("Failed to allocate buffer for keymaster blob param");
- free(data);
- return false;
- }
- memcpy(data, buf, ulength);
- }
- *out = keymaster_param_blob(tag, data, ulength);
- break;
- }
- default: {
- ALOGE("Unsupported keymaster_tag_t %d", tag);
- return false;
- }
- }
- return true;
-}
-
/**
* Read a byte array from in. The data at *data is still owned by the parcel
*/
@@ -420,77 +111,31 @@
}
}
-// Read a keymaster_key_param_t* from a Parcel for use in a
-// keymaster_key_characteristics_t. This will be free'd by calling
-// keymaster_free_key_characteristics.
-static keymaster_key_param_t* readParamList(const Parcel& in, size_t* length) {
- ssize_t slength = in.readInt32();
- *length = 0;
- if (slength < 0) {
- return NULL;
- }
- *length = (size_t) slength;
- if (*length >= UINT_MAX / sizeof(keymaster_key_param_t)) {
- return NULL;
- }
- keymaster_key_param_t* list =
- reinterpret_cast<keymaster_key_param_t*>(malloc(*length *
- sizeof(keymaster_key_param_t)));
- if (!list) {
- ALOGD("Failed to allocate buffer for generateKey outCharacteristics");
- goto err;
- }
- for (size_t i = 0; i < *length ; i++) {
- if (!readKeymasterArgumentFromParcel(in, &list[i])) {
- ALOGE("Failed to read keymaster argument");
- keymaster_free_param_values(list, i);
- goto err;
- }
- }
- return list;
-err:
- free(list);
- return NULL;
-}
-
-static std::unique_ptr<keymaster_blob_t> readKeymasterBlob(const Parcel& in) {
- std::unique_ptr<keymaster_blob_t> blob (new keymaster_blob_t);
- if (!readKeymasterBlob(in, blob.get())) {
- blob.reset();
- }
- return blob;
-}
-
-class BpKeystoreService: public BpInterface<IKeystoreService>
-{
-public:
- explicit BpKeystoreService(const sp<IBinder>& impl)
- : BpInterface<IKeystoreService>(impl)
- {
- }
+class BpKeystoreService : public BpInterface<IKeystoreService> {
+ public:
+ explicit BpKeystoreService(const sp<IBinder>& impl) : BpInterface<IKeystoreService>(impl) {}
// test ping
- virtual int32_t getState(int32_t userId)
- {
+ KeyStoreServiceReturnCode getState(int32_t userId) override {
Parcel data, reply;
data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
data.writeInt32(userId);
status_t status = remote()->transact(BnKeystoreService::GET_STATE, data, &reply);
if (status != NO_ERROR) {
ALOGD("getState() could not contact remote: %d\n", status);
- return -1;
+ return ResponseCode::SYSTEM_ERROR;
}
int32_t err = reply.readExceptionCode();
- int32_t ret = reply.readInt32();
+ ResponseCode ret = ResponseCode(reply.readInt32());
if (err < 0) {
ALOGD("getState() caught exception %d\n", err);
- return -1;
+ return ResponseCode::SYSTEM_ERROR;
}
return ret;
}
- virtual int32_t get(const String16& name, int32_t uid, uint8_t** item, size_t* itemLength)
- {
+ KeyStoreServiceReturnCode get(const String16& name, int32_t uid,
+ hidl_vec<uint8_t>* item) override {
Parcel data, reply;
data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
data.writeString16(name);
@@ -498,58 +143,40 @@
status_t status = remote()->transact(BnKeystoreService::GET, data, &reply);
if (status != NO_ERROR) {
ALOGD("get() could not contact remote: %d\n", status);
- return -1;
+ return ResponseCode::SYSTEM_ERROR;
}
int32_t err = reply.readExceptionCode();
- ssize_t len = reply.readInt32();
- if (len >= 0 && (size_t) len <= reply.dataAvail()) {
- size_t ulen = (size_t) len;
- const void* buf = reply.readInplace(ulen);
- *item = (uint8_t*) malloc(ulen);
- if (*item != NULL) {
- memcpy(*item, buf, ulen);
- *itemLength = ulen;
- } else {
- ALOGE("out of memory allocating output array in get");
- *itemLength = 0;
- }
- } else {
- *itemLength = 0;
- }
if (err < 0) {
ALOGD("get() caught exception %d\n", err);
- return -1;
+ return ResponseCode::SYSTEM_ERROR;
}
- return 0;
+ auto resultItem = readBlobAsByteArray(reply);
+ if (item) *item = resultItem.value();
+ return ResponseCode(reply.readInt32());
}
- virtual int32_t insert(const String16& name, const uint8_t* item, size_t itemLength, int uid,
- int32_t flags)
- {
+ KeyStoreServiceReturnCode insert(const String16& name, const hidl_vec<uint8_t>& item, int uid,
+ int32_t flags) override {
Parcel data, reply;
data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
data.writeString16(name);
- data.writeInt32(itemLength);
- void* buf = data.writeInplace(itemLength);
- memcpy(buf, item, itemLength);
+ writeBlobAsByteArray(item, &data);
data.writeInt32(uid);
data.writeInt32(flags);
status_t status = remote()->transact(BnKeystoreService::INSERT, data, &reply);
if (status != NO_ERROR) {
ALOGD("import() could not contact remote: %d\n", status);
- return -1;
+ return ResponseCode::SYSTEM_ERROR;
}
int32_t err = reply.readExceptionCode();
- int32_t ret = reply.readInt32();
if (err < 0) {
ALOGD("import() caught exception %d\n", err);
- return -1;
+ return ResponseCode::SYSTEM_ERROR;
}
- return ret;
+ return ResponseCode(reply.readInt32());
}
- virtual int32_t del(const String16& name, int uid)
- {
+ KeyStoreServiceReturnCode del(const String16& name, int uid) override {
Parcel data, reply;
data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
data.writeString16(name);
@@ -557,19 +184,17 @@
status_t status = remote()->transact(BnKeystoreService::DEL, data, &reply);
if (status != NO_ERROR) {
ALOGD("del() could not contact remote: %d\n", status);
- return -1;
+ return ResponseCode::SYSTEM_ERROR;
}
int32_t err = reply.readExceptionCode();
- int32_t ret = reply.readInt32();
if (err < 0) {
ALOGD("del() caught exception %d\n", err);
- return -1;
+ return ResponseCode::SYSTEM_ERROR;
}
- return ret;
+ return ResponseCode(reply.readInt32());
}
- virtual int32_t exist(const String16& name, int uid)
- {
+ KeyStoreServiceReturnCode exist(const String16& name, int uid) override {
Parcel data, reply;
data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
data.writeString16(name);
@@ -577,19 +202,18 @@
status_t status = remote()->transact(BnKeystoreService::EXIST, data, &reply);
if (status != NO_ERROR) {
ALOGD("exist() could not contact remote: %d\n", status);
- return -1;
+ return ResponseCode::SYSTEM_ERROR;
}
int32_t err = reply.readExceptionCode();
- int32_t ret = reply.readInt32();
if (err < 0) {
ALOGD("exist() caught exception %d\n", err);
- return -1;
+ return ResponseCode::SYSTEM_ERROR;
}
- return ret;
+ return ResponseCode(reply.readInt32());
}
- virtual int32_t list(const String16& prefix, int uid, Vector<String16>* matches)
- {
+ KeyStoreServiceReturnCode list(const String16& prefix, int uid,
+ Vector<String16>* matches) override {
Parcel data, reply;
data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
data.writeString16(prefix);
@@ -597,81 +221,74 @@
status_t status = remote()->transact(BnKeystoreService::LIST, data, &reply);
if (status != NO_ERROR) {
ALOGD("list() could not contact remote: %d\n", status);
- return -1;
+ return ResponseCode::SYSTEM_ERROR;
}
int32_t err = reply.readExceptionCode();
int32_t numMatches = reply.readInt32();
for (int32_t i = 0; i < numMatches; i++) {
matches->push(reply.readString16());
}
- int32_t ret = reply.readInt32();
if (err < 0) {
ALOGD("list() caught exception %d\n", err);
- return -1;
+ return ResponseCode::SYSTEM_ERROR;
}
- return ret;
+ return ResponseCode(reply.readInt32());
}
- virtual int32_t reset()
- {
+ KeyStoreServiceReturnCode reset() override {
Parcel data, reply;
data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
status_t status = remote()->transact(BnKeystoreService::RESET, data, &reply);
if (status != NO_ERROR) {
ALOGD("reset() could not contact remote: %d\n", status);
- return -1;
+ return ResponseCode::SYSTEM_ERROR;
}
int32_t err = reply.readExceptionCode();
- int32_t ret = reply.readInt32();
if (err < 0) {
ALOGD("reset() caught exception %d\n", err);
- return -1;
+ return ResponseCode::SYSTEM_ERROR;
}
- return ret;
+ return ResponseCode(reply.readInt32());
}
- virtual int32_t onUserPasswordChanged(int32_t userId, const String16& password)
- {
+ KeyStoreServiceReturnCode onUserPasswordChanged(int32_t userId,
+ const String16& password) override {
Parcel data, reply;
data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
data.writeInt32(userId);
data.writeString16(password);
- status_t status = remote()->transact(BnKeystoreService::ON_USER_PASSWORD_CHANGED, data,
- &reply);
+ status_t status =
+ remote()->transact(BnKeystoreService::ON_USER_PASSWORD_CHANGED, data, &reply);
if (status != NO_ERROR) {
ALOGD("onUserPasswordChanged() could not contact remote: %d\n", status);
- return -1;
+ return ResponseCode::SYSTEM_ERROR;
}
int32_t err = reply.readExceptionCode();
- int32_t ret = reply.readInt32();
if (err < 0) {
ALOGD("onUserPasswordChanged() caught exception %d\n", err);
- return -1;
+ return ResponseCode::SYSTEM_ERROR;
}
- return ret;
+ return ResponseCode(reply.readInt32());
}
- virtual int32_t lock(int32_t userId)
- {
+ KeyStoreServiceReturnCode lock(int32_t userId) override {
Parcel data, reply;
data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
data.writeInt32(userId);
status_t status = remote()->transact(BnKeystoreService::LOCK, data, &reply);
if (status != NO_ERROR) {
ALOGD("lock() could not contact remote: %d\n", status);
- return -1;
+ return ResponseCode::SYSTEM_ERROR;
}
int32_t err = reply.readExceptionCode();
- int32_t ret = reply.readInt32();
if (err < 0) {
ALOGD("lock() caught exception %d\n", err);
- return -1;
+ return ResponseCode::SYSTEM_ERROR;
}
- return ret;
+ return ResponseCode(reply.readInt32());
}
- virtual int32_t unlock(int32_t userId, const String16& password)
- {
+ KeyStoreServiceReturnCode unlock(int32_t userId, const String16& password) override {
Parcel data, reply;
data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
data.writeInt32(userId);
@@ -679,19 +296,17 @@
status_t status = remote()->transact(BnKeystoreService::UNLOCK, data, &reply);
if (status != NO_ERROR) {
ALOGD("unlock() could not contact remote: %d\n", status);
- return -1;
+ return ResponseCode::SYSTEM_ERROR;
}
int32_t err = reply.readExceptionCode();
- int32_t ret = reply.readInt32();
if (err < 0) {
ALOGD("unlock() caught exception %d\n", err);
- return -1;
+ return ResponseCode::SYSTEM_ERROR;
}
- return ret;
+ return ResponseCode(reply.readInt32());
}
- virtual bool isEmpty(int32_t userId)
- {
+ bool isEmpty(int32_t userId) override {
Parcel data, reply;
data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
data.writeInt32(userId);
@@ -701,17 +316,16 @@
return false;
}
int32_t err = reply.readExceptionCode();
- int32_t ret = reply.readInt32();
if (err < 0) {
ALOGD("isEmpty() caught exception %d\n", err);
return false;
}
- return ret != 0;
+ return reply.readInt32() != 0;
}
- virtual int32_t generate(const String16& name, int32_t uid, int32_t keyType, int32_t keySize,
- int32_t flags, Vector<sp<KeystoreArg> >* args)
- {
+ KeyStoreServiceReturnCode generate(const String16& name, int32_t uid, int32_t keyType,
+ int32_t keySize, int32_t flags,
+ Vector<sp<KeystoreArg>>* args) override {
Parcel data, reply;
data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
data.writeString16(name);
@@ -721,7 +335,7 @@
data.writeInt32(flags);
data.writeInt32(1);
data.writeInt32(args->size());
- for (Vector<sp<KeystoreArg> >::iterator it = args->begin(); it != args->end(); ++it) {
+ for (Vector<sp<KeystoreArg>>::iterator it = args->begin(); it != args->end(); ++it) {
sp<KeystoreArg> item = *it;
size_t keyLength = item->size();
data.writeInt32(keyLength);
@@ -731,142 +345,104 @@
status_t status = remote()->transact(BnKeystoreService::GENERATE, data, &reply);
if (status != NO_ERROR) {
ALOGD("generate() could not contact remote: %d\n", status);
- return -1;
+ return ResponseCode::SYSTEM_ERROR;
}
int32_t err = reply.readExceptionCode();
- int32_t ret = reply.readInt32();
if (err < 0) {
ALOGD("generate() caught exception %d\n", err);
- return -1;
+ return ResponseCode::SYSTEM_ERROR;
}
- return ret;
+ return ResponseCode(reply.readInt32());
}
- virtual int32_t import(const String16& name, const uint8_t* key, size_t keyLength, int uid,
- int flags)
- {
+ KeyStoreServiceReturnCode import(const String16& name, const hidl_vec<uint8_t>& key, int uid,
+ int flags) override {
Parcel data, reply;
data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
data.writeString16(name);
- data.writeInt32(keyLength);
- void* buf = data.writeInplace(keyLength);
- memcpy(buf, key, keyLength);
+ writeBlobAsByteArray(key, &data);
data.writeInt32(uid);
data.writeInt32(flags);
status_t status = remote()->transact(BnKeystoreService::IMPORT, data, &reply);
if (status != NO_ERROR) {
ALOGD("import() could not contact remote: %d\n", status);
- return -1;
+ return ResponseCode::SYSTEM_ERROR;
}
int32_t err = reply.readExceptionCode();
- int32_t ret = reply.readInt32();
if (err < 0) {
ALOGD("import() caught exception %d\n", err);
- return -1;
+ return ResponseCode::SYSTEM_ERROR;
}
- return ret;
+ return ResponseCode(reply.readInt32());
}
- virtual int32_t sign(const String16& name, const uint8_t* in, size_t inLength, uint8_t** out,
- size_t* outLength)
- {
+ KeyStoreServiceReturnCode sign(const String16& name, const hidl_vec<uint8_t>& in,
+ hidl_vec<uint8_t>* out) override {
Parcel data, reply;
data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
data.writeString16(name);
- data.writeInt32(inLength);
- void* buf = data.writeInplace(inLength);
- memcpy(buf, in, inLength);
+ writeBlobAsByteArray(in, &data);
status_t status = remote()->transact(BnKeystoreService::SIGN, data, &reply);
if (status != NO_ERROR) {
ALOGD("import() could not contact remote: %d\n", status);
- return -1;
+ return ResponseCode::SYSTEM_ERROR;
}
int32_t err = reply.readExceptionCode();
- ssize_t len = reply.readInt32();
- if (len >= 0 && (size_t) len <= reply.dataAvail()) {
- size_t ulen = (size_t) len;
- const void* outBuf = reply.readInplace(ulen);
- *out = (uint8_t*) malloc(ulen);
- if (*out != NULL) {
- memcpy((void*) *out, outBuf, ulen);
- *outLength = ulen;
- } else {
- ALOGE("out of memory allocating output array in sign");
- *outLength = 0;
- }
- } else {
- *outLength = 0;
- }
if (err < 0) {
ALOGD("import() caught exception %d\n", err);
- return -1;
+ return ResponseCode::SYSTEM_ERROR;
}
- return 0;
+ auto outBlob = readBlobAsByteArray(reply);
+ if (out) {
+ // don't need to check outBlob.isOk()
+ // if !outBlob.isOk() the wrapped value is default constructed and therefore empty,
+ // as expected.
+ *out = outBlob.value();
+ }
+ return ResponseCode(reply.readInt32());
}
- virtual int32_t verify(const String16& name, const uint8_t* in, size_t inLength,
- const uint8_t* signature, size_t signatureLength)
- {
+ KeyStoreServiceReturnCode verify(const String16& name, const hidl_vec<uint8_t>& in,
+ const hidl_vec<uint8_t>& signature) override {
Parcel data, reply;
- void* buf;
data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
data.writeString16(name);
- data.writeInt32(inLength);
- buf = data.writeInplace(inLength);
- memcpy(buf, in, inLength);
- data.writeInt32(signatureLength);
- buf = data.writeInplace(signatureLength);
- memcpy(buf, signature, signatureLength);
+ writeBlobAsByteArray(in, &data);
+ writeBlobAsByteArray(signature, &data);
status_t status = remote()->transact(BnKeystoreService::VERIFY, data, &reply);
if (status != NO_ERROR) {
ALOGD("verify() could not contact remote: %d\n", status);
- return -1;
+ return ResponseCode::SYSTEM_ERROR;
}
int32_t err = reply.readExceptionCode();
- int32_t ret = reply.readInt32();
if (err < 0) {
ALOGD("verify() caught exception %d\n", err);
- return -1;
+ return ResponseCode::SYSTEM_ERROR;
}
- return ret;
+ return ResponseCode(reply.readInt32());
}
- virtual int32_t get_pubkey(const String16& name, uint8_t** pubkey, size_t* pubkeyLength)
- {
+ KeyStoreServiceReturnCode get_pubkey(const String16& name, hidl_vec<uint8_t>* pubkey) override {
Parcel data, reply;
data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
data.writeString16(name);
status_t status = remote()->transact(BnKeystoreService::GET_PUBKEY, data, &reply);
if (status != NO_ERROR) {
ALOGD("get_pubkey() could not contact remote: %d\n", status);
- return -1;
+ return ResponseCode::SYSTEM_ERROR;
}
int32_t err = reply.readExceptionCode();
- ssize_t len = reply.readInt32();
- if (len >= 0 && (size_t) len <= reply.dataAvail()) {
- size_t ulen = (size_t) len;
- const void* buf = reply.readInplace(ulen);
- *pubkey = (uint8_t*) malloc(ulen);
- if (*pubkey != NULL) {
- memcpy(*pubkey, buf, ulen);
- *pubkeyLength = ulen;
- } else {
- ALOGE("out of memory allocating output array in get_pubkey");
- *pubkeyLength = 0;
- }
- } else {
- *pubkeyLength = 0;
- }
if (err < 0) {
ALOGD("get_pubkey() caught exception %d\n", err);
- return -1;
+ return ResponseCode::SYSTEM_ERROR;
}
- return 0;
- }
+ auto resultKey = readBlobAsByteArray(reply);
+ if (pubkey) *pubkey = resultKey.value();
+ return ResponseCode(reply.readInt32());
+ }
- virtual int32_t grant(const String16& name, int32_t granteeUid)
- {
+ KeyStoreServiceReturnCode grant(const String16& name, int32_t granteeUid) override {
Parcel data, reply;
data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
data.writeString16(name);
@@ -874,19 +450,17 @@
status_t status = remote()->transact(BnKeystoreService::GRANT, data, &reply);
if (status != NO_ERROR) {
ALOGD("grant() could not contact remote: %d\n", status);
- return -1;
+ return ResponseCode::SYSTEM_ERROR;
}
int32_t err = reply.readExceptionCode();
- int32_t ret = reply.readInt32();
if (err < 0) {
ALOGD("grant() caught exception %d\n", err);
- return -1;
+ return ResponseCode::SYSTEM_ERROR;
}
- return ret;
+ return ResponseCode(reply.readInt32());
}
- virtual int32_t ungrant(const String16& name, int32_t granteeUid)
- {
+ KeyStoreServiceReturnCode ungrant(const String16& name, int32_t granteeUid) override {
Parcel data, reply;
data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
data.writeString16(name);
@@ -894,19 +468,17 @@
status_t status = remote()->transact(BnKeystoreService::UNGRANT, data, &reply);
if (status != NO_ERROR) {
ALOGD("ungrant() could not contact remote: %d\n", status);
- return -1;
+ return ResponseCode::SYSTEM_ERROR;
}
int32_t err = reply.readExceptionCode();
- int32_t ret = reply.readInt32();
if (err < 0) {
ALOGD("ungrant() caught exception %d\n", err);
- return -1;
+ return ResponseCode::SYSTEM_ERROR;
}
- return ret;
+ return ResponseCode(reply.readInt32());
}
- int64_t getmtime(const String16& name, int32_t uid)
- {
+ int64_t getmtime(const String16& name, int32_t uid) override {
Parcel data, reply;
data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
data.writeString16(name);
@@ -917,17 +489,15 @@
return -1;
}
int32_t err = reply.readExceptionCode();
- int64_t ret = reply.readInt64();
if (err < 0) {
ALOGD("getmtime() caught exception %d\n", err);
return -1;
}
- return ret;
+ return reply.readInt64();
}
- virtual int32_t duplicate(const String16& srcKey, int32_t srcUid, const String16& destKey,
- int32_t destUid)
- {
+ KeyStoreServiceReturnCode duplicate(const String16& srcKey, int32_t srcUid,
+ const String16& destKey, int32_t destUid) override {
Parcel data, reply;
data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
data.writeString16(srcKey);
@@ -937,19 +507,17 @@
status_t status = remote()->transact(BnKeystoreService::DUPLICATE, data, &reply);
if (status != NO_ERROR) {
ALOGD("duplicate() could not contact remote: %d\n", status);
- return -1;
+ return ResponseCode::SYSTEM_ERROR;
}
int32_t err = reply.readExceptionCode();
- int32_t ret = reply.readInt32();
if (err < 0) {
ALOGD("duplicate() caught exception %d\n", err);
- return -1;
+ return ResponseCode::SYSTEM_ERROR;
}
- return ret;
+ return ResponseCode(reply.readInt32());
}
- virtual int32_t is_hardware_backed(const String16& keyType)
- {
+ int32_t is_hardware_backed(const String16& keyType) override {
Parcel data, reply;
data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
data.writeString16(keyType);
@@ -959,151 +527,132 @@
return -1;
}
int32_t err = reply.readExceptionCode();
- int32_t ret = reply.readInt32();
if (err < 0) {
ALOGD("is_hardware_backed() caught exception %d\n", err);
return -1;
}
- return ret;
+ return reply.readInt32();
}
- virtual int32_t clear_uid(int64_t uid)
- {
+ KeyStoreServiceReturnCode clear_uid(int64_t uid) override {
Parcel data, reply;
data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
data.writeInt64(uid);
status_t status = remote()->transact(BnKeystoreService::CLEAR_UID, data, &reply);
if (status != NO_ERROR) {
ALOGD("clear_uid() could not contact remote: %d\n", status);
- return -1;
+ return ResponseCode::SYSTEM_ERROR;
}
int32_t err = reply.readExceptionCode();
- int32_t ret = reply.readInt32();
if (err < 0) {
ALOGD("clear_uid() caught exception %d\n", err);
- return -1;
+ return ResponseCode::SYSTEM_ERROR;
}
- return ret;
+ return ResponseCode(reply.readInt32());
}
- virtual int32_t addRngEntropy(const uint8_t* buf, size_t bufLength)
- {
+ KeyStoreServiceReturnCode addRngEntropy(const hidl_vec<uint8_t>& entropy) override {
Parcel data, reply;
data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
- data.writeByteArray(bufLength, buf);
+ writeBlobAsByteArray(entropy, &data);
status_t status = remote()->transact(BnKeystoreService::ADD_RNG_ENTROPY, data, &reply);
if (status != NO_ERROR) {
ALOGD("addRngEntropy() could not contact remote: %d\n", status);
- return -1;
+ return ResponseCode::SYSTEM_ERROR;
}
int32_t err = reply.readExceptionCode();
- int32_t ret = reply.readInt32();
if (err < 0) {
ALOGD("addRngEntropy() caught exception %d\n", err);
- return -1;
+ return ResponseCode::SYSTEM_ERROR;
}
- return ret;
+ return ResponseCode(reply.readInt32());
};
- virtual int32_t generateKey(const String16& name, const KeymasterArguments& params,
- const uint8_t* entropy, size_t entropyLength, int uid, int flags,
- KeyCharacteristics* outCharacteristics)
- {
+ KeyStoreServiceReturnCode generateKey(const String16& name,
+ const hidl_vec<KeyParameter>& params,
+ const hidl_vec<uint8_t>& entropy, int uid, int flags,
+ KeyCharacteristics* outCharacteristics) override {
Parcel data, reply;
data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
data.writeString16(name);
- data.writeInt32(1);
- params.writeToParcel(&data);
- data.writeByteArray(entropyLength, entropy);
+ nullable(writeParamSetToParcel, params, &data);
+ writeBlobAsByteArray(entropy, &data);
data.writeInt32(uid);
data.writeInt32(flags);
status_t status = remote()->transact(BnKeystoreService::GENERATE_KEY, data, &reply);
if (status != NO_ERROR) {
ALOGD("generateKey() could not contact remote: %d\n", status);
- return KM_ERROR_UNKNOWN_ERROR;
+ return ResponseCode::SYSTEM_ERROR;
}
int32_t err = reply.readExceptionCode();
- int32_t ret = reply.readInt32();
+ ResponseCode ret = ResponseCode(reply.readInt32());
if (err < 0) {
ALOGD("generateKey() caught exception %d\n", err);
- return KM_ERROR_UNKNOWN_ERROR;
+ return ResponseCode::SYSTEM_ERROR;
}
if (outCharacteristics) {
- reply.readParcelable(outCharacteristics);
+ *outCharacteristics = nullable(readKeyCharacteristicsFromParcel, reply).value();
}
return ret;
}
- virtual int32_t getKeyCharacteristics(const String16& name,
- const keymaster_blob_t* clientId,
- const keymaster_blob_t* appData,
- int32_t uid, KeyCharacteristics* outCharacteristics)
- {
+ KeyStoreServiceReturnCode
+ getKeyCharacteristics(const String16& name, const hidl_vec<uint8_t>& clientId,
+ const hidl_vec<uint8_t>& appData, int32_t uid,
+ KeyCharacteristics* outCharacteristics) override {
Parcel data, reply;
data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
data.writeString16(name);
- if (clientId) {
- data.writeByteArray(clientId->data_length, clientId->data);
- } else {
- data.writeInt32(-1);
- }
- if (appData) {
- data.writeByteArray(appData->data_length, appData->data);
- } else {
- data.writeInt32(-1);
- }
+ writeBlobAsByteArray(clientId, &data);
+ writeBlobAsByteArray(appData, &data);
data.writeInt32(uid);
- status_t status = remote()->transact(BnKeystoreService::GET_KEY_CHARACTERISTICS,
- data, &reply);
+ status_t status =
+ remote()->transact(BnKeystoreService::GET_KEY_CHARACTERISTICS, data, &reply);
if (status != NO_ERROR) {
ALOGD("getKeyCharacteristics() could not contact remote: %d\n", status);
- return KM_ERROR_UNKNOWN_ERROR;
+ return ResponseCode::SYSTEM_ERROR;
}
int32_t err = reply.readExceptionCode();
- int32_t ret = reply.readInt32();
+ ResponseCode ret = ResponseCode(reply.readInt32());
if (err < 0) {
ALOGD("getKeyCharacteristics() caught exception %d\n", err);
- return KM_ERROR_UNKNOWN_ERROR;
+ return ResponseCode::SYSTEM_ERROR;
}
if (outCharacteristics) {
- reply.readParcelable(outCharacteristics);
+ *outCharacteristics = nullable(readKeyCharacteristicsFromParcel, reply).value();
}
return ret;
}
- virtual int32_t importKey(const String16& name, const KeymasterArguments& params,
- keymaster_key_format_t format, const uint8_t *keyData,
- size_t keyLength, int uid, int flags,
- KeyCharacteristics* outCharacteristics)
- {
+ KeyStoreServiceReturnCode importKey(const String16& name, const hidl_vec<KeyParameter>& params,
+ KeyFormat format, const hidl_vec<uint8_t>& keyData, int uid,
+ int flags,
+ KeyCharacteristics* outCharacteristics) override {
Parcel data, reply;
data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
data.writeString16(name);
- data.writeInt32(1);
- params.writeToParcel(&data);
- data.writeInt32(format);
- data.writeByteArray(keyLength, keyData);
+ nullable(writeParamSetToParcel, params, &data);
+ data.writeInt32(uint32_t(format));
+ writeBlobAsByteArray(keyData, &data);
data.writeInt32(uid);
data.writeInt32(flags);
status_t status = remote()->transact(BnKeystoreService::IMPORT_KEY, data, &reply);
if (status != NO_ERROR) {
ALOGD("importKey() could not contact remote: %d\n", status);
- return KM_ERROR_UNKNOWN_ERROR;
+ return ResponseCode::SYSTEM_ERROR;
}
int32_t err = reply.readExceptionCode();
- int32_t ret = reply.readInt32();
+ ResponseCode ret = ResponseCode(reply.readInt32());
if (err < 0) {
ALOGD("importKey() caught exception %d\n", err);
- return KM_ERROR_UNKNOWN_ERROR;
+ return ResponseCode::SYSTEM_ERROR;
}
if (outCharacteristics) {
- reply.readParcelable(outCharacteristics);
+ *outCharacteristics = nullable(readKeyCharacteristicsFromParcel, reply).value();
}
return ret;
}
- virtual void exportKey(const String16& name, keymaster_key_format_t format,
- const keymaster_blob_t* clientId,
- const keymaster_blob_t* appData, int32_t uid, ExportResult* result)
- {
+ void exportKey(const String16& name, KeyFormat format, const hidl_vec<uint8_t>& clientId,
+ const hidl_vec<uint8_t>& appData, int32_t uid, ExportResult* result) override {
if (!result) {
return;
}
@@ -1111,39 +660,29 @@
Parcel data, reply;
data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
data.writeString16(name);
- data.writeInt32(format);
- if (clientId) {
- data.writeByteArray(clientId->data_length, clientId->data);
- } else {
- data.writeInt32(-1);
- }
- if (appData) {
- data.writeByteArray(appData->data_length, appData->data);
- } else {
- data.writeInt32(-1);
- }
+ data.writeInt32(int32_t(format));
+ writeBlobAsByteArray(clientId, &data);
+ writeBlobAsByteArray(appData, &data);
data.writeInt32(uid);
status_t status = remote()->transact(BnKeystoreService::EXPORT_KEY, data, &reply);
if (status != NO_ERROR) {
ALOGD("exportKey() could not contact remote: %d\n", status);
- result->resultCode = KM_ERROR_UNKNOWN_ERROR;
+ result->resultCode = ResponseCode::SYSTEM_ERROR;
return;
}
int32_t err = reply.readExceptionCode();
if (err < 0) {
ALOGD("exportKey() caught exception %d\n", err);
- result->resultCode = KM_ERROR_UNKNOWN_ERROR;
+ result->resultCode = ResponseCode::SYSTEM_ERROR;
return;
}
reply.readParcelable(result);
}
- virtual void begin(const sp<IBinder>& appToken, const String16& name,
- keymaster_purpose_t purpose, bool pruneable,
- const KeymasterArguments& params, const uint8_t* entropy,
- size_t entropyLength, int32_t uid, OperationResult* result)
- {
+ void begin(const sp<IBinder>& appToken, const String16& name, KeyPurpose purpose,
+ bool pruneable, const hidl_vec<KeyParameter>& params,
+ const hidl_vec<uint8_t>& entropy, int32_t uid, OperationResult* result) override {
if (!result) {
return;
}
@@ -1151,147 +690,134 @@
data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
data.writeStrongBinder(appToken);
data.writeString16(name);
- data.writeInt32(purpose);
+ data.writeInt32(int32_t(purpose));
data.writeInt32(pruneable ? 1 : 0);
- data.writeInt32(1);
- params.writeToParcel(&data);
- data.writeByteArray(entropyLength, entropy);
+ nullable(writeParamSetToParcel, params, &data);
+ writeBlobAsByteArray(entropy, &data);
data.writeInt32(uid);
status_t status = remote()->transact(BnKeystoreService::BEGIN, data, &reply);
if (status != NO_ERROR) {
ALOGD("begin() could not contact remote: %d\n", status);
- result->resultCode = KM_ERROR_UNKNOWN_ERROR;
+ result->resultCode = ResponseCode::SYSTEM_ERROR;
return;
}
int32_t err = reply.readExceptionCode();
if (err < 0) {
ALOGD("begin() caught exception %d\n", err);
- result->resultCode = KM_ERROR_UNKNOWN_ERROR;
+ result->resultCode = ResponseCode::SYSTEM_ERROR;
return;
}
reply.readParcelable(result);
}
- virtual void update(const sp<IBinder>& token, const KeymasterArguments& params,
- const uint8_t* opData, size_t dataLength, OperationResult* result)
- {
+ void update(const sp<IBinder>& token, const hidl_vec<KeyParameter>& params,
+ const hidl_vec<uint8_t>& opData, OperationResult* result) override {
if (!result) {
return;
}
Parcel data, reply;
data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
data.writeStrongBinder(token);
- data.writeInt32(1);
- params.writeToParcel(&data);
- data.writeByteArray(dataLength, opData);
+ nullable(writeParamSetToParcel, params, &data);
+ writeBlobAsByteArray(opData, &data);
status_t status = remote()->transact(BnKeystoreService::UPDATE, data, &reply);
if (status != NO_ERROR) {
ALOGD("update() could not contact remote: %d\n", status);
- result->resultCode = KM_ERROR_UNKNOWN_ERROR;
+ result->resultCode = ResponseCode::SYSTEM_ERROR;
return;
}
int32_t err = reply.readExceptionCode();
if (err < 0) {
ALOGD("update() caught exception %d\n", err);
- result->resultCode = KM_ERROR_UNKNOWN_ERROR;
+ result->resultCode = ResponseCode::SYSTEM_ERROR;
return;
}
reply.readParcelable(result);
}
- virtual void finish(const sp<IBinder>& token, const KeymasterArguments& params,
- const uint8_t* signature, size_t signatureLength,
- const uint8_t* entropy, size_t entropyLength,
- OperationResult* result)
- {
+ void finish(const sp<IBinder>& token, const hidl_vec<KeyParameter>& params,
+ const hidl_vec<uint8_t>& signature, const hidl_vec<uint8_t>& entropy,
+ OperationResult* result) override {
if (!result) {
return;
}
Parcel data, reply;
data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
data.writeStrongBinder(token);
- data.writeInt32(1);
- params.writeToParcel(&data);
- data.writeByteArray(signatureLength, signature);
- data.writeByteArray(entropyLength, entropy);
+ nullable(writeParamSetToParcel, params, &data);
+ writeBlobAsByteArray(signature, &data);
+ writeBlobAsByteArray(entropy, &data);
status_t status = remote()->transact(BnKeystoreService::FINISH, data, &reply);
if (status != NO_ERROR) {
ALOGD("finish() could not contact remote: %d\n", status);
- result->resultCode = KM_ERROR_UNKNOWN_ERROR;
+ result->resultCode = ResponseCode::SYSTEM_ERROR;
return;
}
int32_t err = reply.readExceptionCode();
if (err < 0) {
ALOGD("finish() caught exception %d\n", err);
- result->resultCode = KM_ERROR_UNKNOWN_ERROR;
+ result->resultCode = ResponseCode::SYSTEM_ERROR;
return;
}
reply.readParcelable(result);
}
- virtual int32_t abort(const sp<IBinder>& token)
- {
+ KeyStoreServiceReturnCode abort(const sp<IBinder>& token) override {
Parcel data, reply;
data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
data.writeStrongBinder(token);
status_t status = remote()->transact(BnKeystoreService::ABORT, data, &reply);
if (status != NO_ERROR) {
ALOGD("abort() could not contact remote: %d\n", status);
- return KM_ERROR_UNKNOWN_ERROR;
+ return ResponseCode::SYSTEM_ERROR;
}
int32_t err = reply.readExceptionCode();
- int32_t ret = reply.readInt32();
if (err < 0) {
ALOGD("abort() caught exception %d\n", err);
- return KM_ERROR_UNKNOWN_ERROR;
+ return ResponseCode::SYSTEM_ERROR;
}
- return ret;
+ return ResponseCode(reply.readInt32());
}
- virtual bool isOperationAuthorized(const sp<IBinder>& token)
- {
+ bool isOperationAuthorized(const sp<IBinder>& token) override {
Parcel data, reply;
data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
data.writeStrongBinder(token);
- status_t status = remote()->transact(BnKeystoreService::IS_OPERATION_AUTHORIZED, data,
- &reply);
+ status_t status =
+ remote()->transact(BnKeystoreService::IS_OPERATION_AUTHORIZED, data, &reply);
if (status != NO_ERROR) {
ALOGD("isOperationAuthorized() could not contact remote: %d\n", status);
return false;
}
int32_t err = reply.readExceptionCode();
- int32_t ret = reply.readInt32();
if (err < 0) {
ALOGD("isOperationAuthorized() caught exception %d\n", err);
return false;
}
- return ret == 1;
+ return reply.readInt32() == 1;
}
- virtual int32_t addAuthToken(const uint8_t* token, size_t length)
- {
+ KeyStoreServiceReturnCode addAuthToken(const uint8_t* token, size_t length) override {
Parcel data, reply;
data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
data.writeByteArray(length, token);
status_t status = remote()->transact(BnKeystoreService::ADD_AUTH_TOKEN, data, &reply);
if (status != NO_ERROR) {
ALOGD("addAuthToken() could not contact remote: %d\n", status);
- return -1;
+ return ResponseCode::SYSTEM_ERROR;
}
int32_t err = reply.readExceptionCode();
- int32_t ret = reply.readInt32();
if (err < 0) {
ALOGD("addAuthToken() caught exception %d\n", err);
- return -1;
+ return ResponseCode::SYSTEM_ERROR;
}
- return ret;
+ return ResponseCode(reply.readInt32());
};
- virtual int32_t onUserAdded(int32_t userId, int32_t parentId)
- {
+ KeyStoreServiceReturnCode onUserAdded(int32_t userId, int32_t parentId) override {
Parcel data, reply;
data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
data.writeInt32(userId);
@@ -1299,609 +825,499 @@
status_t status = remote()->transact(BnKeystoreService::ON_USER_ADDED, data, &reply);
if (status != NO_ERROR) {
ALOGD("onUserAdded() could not contact remote: %d\n", status);
- return -1;
+ return ResponseCode::SYSTEM_ERROR;
}
int32_t err = reply.readExceptionCode();
- int32_t ret = reply.readInt32();
if (err < 0) {
ALOGD("onUserAdded() caught exception %d\n", err);
- return -1;
+ return ResponseCode::SYSTEM_ERROR;
}
- return ret;
+ return ResponseCode(reply.readInt32());
}
- virtual int32_t onUserRemoved(int32_t userId)
- {
+ KeyStoreServiceReturnCode onUserRemoved(int32_t userId) override {
Parcel data, reply;
data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
data.writeInt32(userId);
status_t status = remote()->transact(BnKeystoreService::ON_USER_REMOVED, data, &reply);
if (status != NO_ERROR) {
ALOGD("onUserRemoved() could not contact remote: %d\n", status);
- return -1;
+ return ResponseCode::SYSTEM_ERROR;
}
int32_t err = reply.readExceptionCode();
- int32_t ret = reply.readInt32();
if (err < 0) {
ALOGD("onUserRemoved() caught exception %d\n", err);
- return -1;
+ return ResponseCode::SYSTEM_ERROR;
}
- return ret;
+ return ResponseCode(reply.readInt32());
}
- virtual int32_t attestKey(const String16& name, const KeymasterArguments& params,
- KeymasterCertificateChain* outChain) {
- if (!outChain)
- return KM_ERROR_OUTPUT_PARAMETER_NULL;
+ KeyStoreServiceReturnCode attestKey(const String16& name, const hidl_vec<KeyParameter>& params,
+ hidl_vec<hidl_vec<uint8_t>>* outChain) override {
+ if (!outChain) return ErrorCode::OUTPUT_PARAMETER_NULL;
Parcel data, reply;
data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
data.writeString16(name);
- data.writeInt32(1); // params is not NULL.
- params.writeToParcel(&data);
+ nullable(writeParamSetToParcel, params, &data);
status_t status = remote()->transact(BnKeystoreService::ATTEST_KEY, data, &reply);
if (status != NO_ERROR) {
ALOGD("attestkey() count not contact remote: %d\n", status);
- return KM_ERROR_UNKNOWN_ERROR;
+ return ResponseCode::SYSTEM_ERROR;
}
int32_t err = reply.readExceptionCode();
- int32_t ret = reply.readInt32();
+ ResponseCode ret = ResponseCode(reply.readInt32());
if (err < 0) {
ALOGD("attestKey() caught exception %d\n", err);
- return KM_ERROR_UNKNOWN_ERROR;
+ return ResponseCode::SYSTEM_ERROR;
}
if (reply.readInt32() != 0) {
- outChain->readFromParcel(reply);
+ *outChain = readCertificateChainFromParcel(reply);
}
return ret;
}
- virtual int32_t onDeviceOffBody()
- {
+ KeyStoreServiceReturnCode onDeviceOffBody() override {
Parcel data, reply;
data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
status_t status = remote()->transact(BnKeystoreService::ON_DEVICE_OFF_BODY, data, &reply);
if (status != NO_ERROR) {
ALOGD("onDeviceOffBody() could not contact remote: %d\n", status);
- return -1;
+ return ResponseCode::SYSTEM_ERROR;
}
int32_t err = reply.readExceptionCode();
- int32_t ret = reply.readInt32();
if (err < 0) {
ALOGD("onDeviceOffBody() caught exception %d\n", err);
- return -1;
+ return ResponseCode::SYSTEM_ERROR;
}
- return ret;
+ return ResponseCode(reply.readInt32());
}
-
};
IMPLEMENT_META_INTERFACE(KeystoreService, "android.security.IKeystoreService");
// ----------------------------------------------------------------------
-status_t BnKeystoreService::onTransact(
- uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
-{
- switch(code) {
- case GET_STATE: {
- CHECK_INTERFACE(IKeystoreService, data, reply);
- int32_t userId = data.readInt32();
- int32_t ret = getState(userId);
- reply->writeNoException();
- reply->writeInt32(ret);
- return NO_ERROR;
- } break;
- case GET: {
- CHECK_INTERFACE(IKeystoreService, data, reply);
- String16 name = data.readString16();
- int32_t uid = data.readInt32();
- void* out = NULL;
- size_t outSize = 0;
- int32_t ret = get(name, uid, (uint8_t**) &out, &outSize);
- reply->writeNoException();
- if (ret == 1) {
- reply->writeInt32(outSize);
- void* buf = reply->writeInplace(outSize);
- memcpy(buf, out, outSize);
- free(out);
- } else {
- reply->writeInt32(-1);
+status_t BnKeystoreService::onTransact(uint32_t code, const Parcel& data, Parcel* reply,
+ uint32_t flags) {
+ switch (code) {
+ case GET_STATE: {
+ CHECK_INTERFACE(IKeystoreService, data, reply);
+ int32_t userId = data.readInt32();
+ int32_t ret = getState(userId);
+ reply->writeNoException();
+ reply->writeInt32(ret);
+ return NO_ERROR;
+ } break;
+ case GET: {
+ CHECK_INTERFACE(IKeystoreService, data, reply);
+ String16 name = data.readString16();
+ int32_t uid = data.readInt32();
+ hidl_vec<uint8_t> out;
+ auto ret = get(name, uid, &out);
+ reply->writeNoException();
+ if (ret.isOk()) {
+ writeBlobAsByteArray(out, reply);
+ } else {
+ reply->writeInt32(-1);
+ }
+ reply->writeInt32(ret);
+ return NO_ERROR;
+ } break;
+ case INSERT: {
+ CHECK_INTERFACE(IKeystoreService, data, reply);
+ String16 name = data.readString16();
+ auto in = readBlobAsByteArray(data);
+ int uid = data.readInt32();
+ int32_t flags = data.readInt32();
+ int32_t ret = insert(name, in.value(), uid, flags);
+ reply->writeNoException();
+ reply->writeInt32(ret);
+ return NO_ERROR;
+ } break;
+ case DEL: {
+ CHECK_INTERFACE(IKeystoreService, data, reply);
+ String16 name = data.readString16();
+ int uid = data.readInt32();
+ int32_t ret = del(name, uid);
+ reply->writeNoException();
+ reply->writeInt32(ret);
+ return NO_ERROR;
+ } break;
+ case EXIST: {
+ CHECK_INTERFACE(IKeystoreService, data, reply);
+ String16 name = data.readString16();
+ int uid = data.readInt32();
+ int32_t ret = exist(name, uid);
+ reply->writeNoException();
+ reply->writeInt32(ret);
+ return NO_ERROR;
+ } break;
+ case LIST: {
+ CHECK_INTERFACE(IKeystoreService, data, reply);
+ String16 prefix = data.readString16();
+ int uid = data.readInt32();
+ Vector<String16> matches;
+ int32_t ret = list(prefix, uid, &matches);
+ reply->writeNoException();
+ reply->writeInt32(matches.size());
+ Vector<String16>::const_iterator it = matches.begin();
+ for (; it != matches.end(); ++it) {
+ reply->writeString16(*it);
+ }
+ reply->writeInt32(ret);
+ return NO_ERROR;
+ } break;
+ case RESET: {
+ CHECK_INTERFACE(IKeystoreService, data, reply);
+ int32_t ret = reset();
+ reply->writeNoException();
+ reply->writeInt32(ret);
+ return NO_ERROR;
+ } break;
+ case ON_USER_PASSWORD_CHANGED: {
+ CHECK_INTERFACE(IKeystoreService, data, reply);
+ int32_t userId = data.readInt32();
+ String16 pass = data.readString16();
+ int32_t ret = onUserPasswordChanged(userId, pass);
+ reply->writeNoException();
+ reply->writeInt32(ret);
+ return NO_ERROR;
+ } break;
+ case LOCK: {
+ CHECK_INTERFACE(IKeystoreService, data, reply);
+ int32_t userId = data.readInt32();
+ int32_t ret = lock(userId);
+ reply->writeNoException();
+ reply->writeInt32(ret);
+ return NO_ERROR;
+ } break;
+ case UNLOCK: {
+ CHECK_INTERFACE(IKeystoreService, data, reply);
+ int32_t userId = data.readInt32();
+ String16 pass = data.readString16();
+ int32_t ret = unlock(userId, pass);
+ reply->writeNoException();
+ reply->writeInt32(ret);
+ return NO_ERROR;
+ } break;
+ case IS_EMPTY: {
+ CHECK_INTERFACE(IKeystoreService, data, reply);
+ int32_t userId = data.readInt32();
+ bool ret = isEmpty(userId);
+ reply->writeNoException();
+ reply->writeInt32(ret ? 1 : 0);
+ return NO_ERROR;
+ } break;
+ case GENERATE: {
+ CHECK_INTERFACE(IKeystoreService, data, reply);
+ String16 name = data.readString16();
+ int32_t uid = data.readInt32();
+ int32_t keyType = data.readInt32();
+ int32_t keySize = data.readInt32();
+ int32_t flags = data.readInt32();
+ Vector<sp<KeystoreArg>> args;
+ int32_t argsPresent = data.readInt32();
+ if (argsPresent == 1) {
+ ssize_t numArgs = data.readInt32();
+ if (numArgs > MAX_GENERATE_ARGS) {
+ return BAD_VALUE;
}
- return NO_ERROR;
- } break;
- case INSERT: {
- CHECK_INTERFACE(IKeystoreService, data, reply);
- String16 name = data.readString16();
- ssize_t inSize = data.readInt32();
- const void* in;
- if (inSize >= 0 && (size_t) inSize <= data.dataAvail()) {
- in = data.readInplace(inSize);
- } else {
- in = NULL;
- inSize = 0;
- }
- int uid = data.readInt32();
- int32_t flags = data.readInt32();
- int32_t ret = insert(name, (const uint8_t*) in, (size_t) inSize, uid, flags);
- reply->writeNoException();
- reply->writeInt32(ret);
- return NO_ERROR;
- } break;
- case DEL: {
- CHECK_INTERFACE(IKeystoreService, data, reply);
- String16 name = data.readString16();
- int uid = data.readInt32();
- int32_t ret = del(name, uid);
- reply->writeNoException();
- reply->writeInt32(ret);
- return NO_ERROR;
- } break;
- case EXIST: {
- CHECK_INTERFACE(IKeystoreService, data, reply);
- String16 name = data.readString16();
- int uid = data.readInt32();
- int32_t ret = exist(name, uid);
- reply->writeNoException();
- reply->writeInt32(ret);
- return NO_ERROR;
- } break;
- case LIST: {
- CHECK_INTERFACE(IKeystoreService, data, reply);
- String16 prefix = data.readString16();
- int uid = data.readInt32();
- Vector<String16> matches;
- int32_t ret = list(prefix, uid, &matches);
- reply->writeNoException();
- reply->writeInt32(matches.size());
- Vector<String16>::const_iterator it = matches.begin();
- for (; it != matches.end(); ++it) {
- reply->writeString16(*it);
- }
- reply->writeInt32(ret);
- return NO_ERROR;
- } break;
- case RESET: {
- CHECK_INTERFACE(IKeystoreService, data, reply);
- int32_t ret = reset();
- reply->writeNoException();
- reply->writeInt32(ret);
- return NO_ERROR;
- } break;
- case ON_USER_PASSWORD_CHANGED: {
- CHECK_INTERFACE(IKeystoreService, data, reply);
- int32_t userId = data.readInt32();
- String16 pass = data.readString16();
- int32_t ret = onUserPasswordChanged(userId, pass);
- reply->writeNoException();
- reply->writeInt32(ret);
- return NO_ERROR;
- } break;
- case LOCK: {
- CHECK_INTERFACE(IKeystoreService, data, reply);
- int32_t userId = data.readInt32();
- int32_t ret = lock(userId);
- reply->writeNoException();
- reply->writeInt32(ret);
- return NO_ERROR;
- } break;
- case UNLOCK: {
- CHECK_INTERFACE(IKeystoreService, data, reply);
- int32_t userId = data.readInt32();
- String16 pass = data.readString16();
- int32_t ret = unlock(userId, pass);
- reply->writeNoException();
- reply->writeInt32(ret);
- return NO_ERROR;
- } break;
- case IS_EMPTY: {
- CHECK_INTERFACE(IKeystoreService, data, reply);
- int32_t userId = data.readInt32();
- bool ret = isEmpty(userId);
- reply->writeNoException();
- reply->writeInt32(ret ? 1 : 0);
- return NO_ERROR;
- } break;
- case GENERATE: {
- CHECK_INTERFACE(IKeystoreService, data, reply);
- String16 name = data.readString16();
- int32_t uid = data.readInt32();
- int32_t keyType = data.readInt32();
- int32_t keySize = data.readInt32();
- int32_t flags = data.readInt32();
- Vector<sp<KeystoreArg> > args;
- int32_t argsPresent = data.readInt32();
- if (argsPresent == 1) {
- ssize_t numArgs = data.readInt32();
- if (numArgs > MAX_GENERATE_ARGS) {
- return BAD_VALUE;
- }
- if (numArgs > 0) {
- for (size_t i = 0; i < (size_t) numArgs; i++) {
- ssize_t inSize = data.readInt32();
- if (inSize >= 0 && (size_t) inSize <= data.dataAvail()) {
- sp<KeystoreArg> arg = new KeystoreArg(data.readInplace(inSize),
- inSize);
- args.push_back(arg);
- } else {
- args.push_back(NULL);
- }
+ if (numArgs > 0) {
+ for (size_t i = 0; i < (size_t)numArgs; i++) {
+ ssize_t inSize = data.readInt32();
+ if (inSize >= 0 && (size_t)inSize <= data.dataAvail()) {
+ sp<KeystoreArg> arg = new KeystoreArg(data.readInplace(inSize), inSize);
+ args.push_back(arg);
+ } else {
+ args.push_back(NULL);
}
}
}
- int32_t ret = generate(name, uid, keyType, keySize, flags, &args);
- reply->writeNoException();
- reply->writeInt32(ret);
- return NO_ERROR;
- } break;
- case IMPORT: {
- CHECK_INTERFACE(IKeystoreService, data, reply);
- String16 name = data.readString16();
- ssize_t inSize = data.readInt32();
- const void* in;
- if (inSize >= 0 && (size_t) inSize <= data.dataAvail()) {
- in = data.readInplace(inSize);
- } else {
- in = NULL;
- inSize = 0;
- }
- int uid = data.readInt32();
- int32_t flags = data.readInt32();
- int32_t ret = import(name, (const uint8_t*) in, (size_t) inSize, uid, flags);
- reply->writeNoException();
- reply->writeInt32(ret);
- return NO_ERROR;
- } break;
- case SIGN: {
- CHECK_INTERFACE(IKeystoreService, data, reply);
- String16 name = data.readString16();
- ssize_t inSize = data.readInt32();
- const void* in;
- if (inSize >= 0 && (size_t) inSize <= data.dataAvail()) {
- in = data.readInplace(inSize);
- } else {
- in = NULL;
- inSize = 0;
- }
- void* out = NULL;
- size_t outSize = 0;
- int32_t ret = sign(name, (const uint8_t*) in, (size_t) inSize, (uint8_t**) &out, &outSize);
- reply->writeNoException();
- if (outSize > 0 && out != NULL) {
- reply->writeInt32(outSize);
- void* buf = reply->writeInplace(outSize);
- memcpy(buf, out, outSize);
- delete[] reinterpret_cast<uint8_t*>(out);
- } else {
- reply->writeInt32(-1);
- }
- reply->writeInt32(ret);
- return NO_ERROR;
- } break;
- case VERIFY: {
- CHECK_INTERFACE(IKeystoreService, data, reply);
- String16 name = data.readString16();
- ssize_t inSize = data.readInt32();
- const void* in;
- if (inSize >= 0 && (size_t) inSize <= data.dataAvail()) {
- in = data.readInplace(inSize);
- } else {
- in = NULL;
- inSize = 0;
- }
- ssize_t sigSize = data.readInt32();
- const void* sig;
- if (sigSize >= 0 && (size_t) sigSize <= data.dataAvail()) {
- sig = data.readInplace(sigSize);
- } else {
- sig = NULL;
- sigSize = 0;
- }
- bool ret = verify(name, (const uint8_t*) in, (size_t) inSize, (const uint8_t*) sig,
- (size_t) sigSize);
- reply->writeNoException();
- reply->writeInt32(ret ? 1 : 0);
- return NO_ERROR;
- } break;
- case GET_PUBKEY: {
- CHECK_INTERFACE(IKeystoreService, data, reply);
- String16 name = data.readString16();
- void* out = NULL;
- size_t outSize = 0;
- int32_t ret = get_pubkey(name, (unsigned char**) &out, &outSize);
- reply->writeNoException();
- if (outSize > 0 && out != NULL) {
- reply->writeInt32(outSize);
- void* buf = reply->writeInplace(outSize);
- memcpy(buf, out, outSize);
- free(out);
- } else {
- reply->writeInt32(-1);
- }
- reply->writeInt32(ret);
- return NO_ERROR;
- } break;
- case GRANT: {
- CHECK_INTERFACE(IKeystoreService, data, reply);
- String16 name = data.readString16();
- int32_t granteeUid = data.readInt32();
- int32_t ret = grant(name, granteeUid);
- reply->writeNoException();
- reply->writeInt32(ret);
- return NO_ERROR;
- } break;
- case UNGRANT: {
- CHECK_INTERFACE(IKeystoreService, data, reply);
- String16 name = data.readString16();
- int32_t granteeUid = data.readInt32();
- int32_t ret = ungrant(name, granteeUid);
- reply->writeNoException();
- reply->writeInt32(ret);
- return NO_ERROR;
- } break;
- case GETMTIME: {
- CHECK_INTERFACE(IKeystoreService, data, reply);
- String16 name = data.readString16();
- int32_t uid = data.readInt32();
- int64_t ret = getmtime(name, uid);
- reply->writeNoException();
- reply->writeInt64(ret);
- return NO_ERROR;
- } break;
- case DUPLICATE: {
- CHECK_INTERFACE(IKeystoreService, data, reply);
- String16 srcKey = data.readString16();
- int32_t srcUid = data.readInt32();
- String16 destKey = data.readString16();
- int32_t destUid = data.readInt32();
- int32_t ret = duplicate(srcKey, srcUid, destKey, destUid);
- reply->writeNoException();
- reply->writeInt32(ret);
- return NO_ERROR;
- } break;
- case IS_HARDWARE_BACKED: {
- CHECK_INTERFACE(IKeystoreService, data, reply);
- String16 keyType = data.readString16();
- int32_t ret = is_hardware_backed(keyType);
- reply->writeNoException();
- reply->writeInt32(ret);
- return NO_ERROR;
}
- case CLEAR_UID: {
- CHECK_INTERFACE(IKeystoreService, data, reply);
- int64_t uid = data.readInt64();
- int32_t ret = clear_uid(uid);
- reply->writeNoException();
- reply->writeInt32(ret);
- return NO_ERROR;
- }
- case ADD_RNG_ENTROPY: {
- CHECK_INTERFACE(IKeystoreService, data, reply);
- const uint8_t* bytes = NULL;
- size_t size = 0;
- readByteArray(data, &bytes, &size);
- int32_t ret = addRngEntropy(bytes, size);
- reply->writeNoException();
- reply->writeInt32(ret);
- return NO_ERROR;
- }
- case GENERATE_KEY: {
- CHECK_INTERFACE(IKeystoreService, data, reply);
- String16 name = data.readString16();
- KeymasterArguments args;
- if (data.readInt32() != 0) {
- args.readFromParcel(data);
- }
- const uint8_t* entropy = NULL;
- size_t entropyLength = 0;
- readByteArray(data, &entropy, &entropyLength);
- int32_t uid = data.readInt32();
- int32_t flags = data.readInt32();
- KeyCharacteristics outCharacteristics;
- int32_t ret = generateKey(name, args, entropy, entropyLength, uid, flags,
- &outCharacteristics);
- reply->writeNoException();
- reply->writeInt32(ret);
- reply->writeParcelable(outCharacteristics);
- return NO_ERROR;
- }
- case GET_KEY_CHARACTERISTICS: {
- CHECK_INTERFACE(IKeystoreService, data, reply);
- String16 name = data.readString16();
- std::unique_ptr<keymaster_blob_t> clientId = readKeymasterBlob(data);
- std::unique_ptr<keymaster_blob_t> appData = readKeymasterBlob(data);
- int32_t uid = data.readInt32();
- KeyCharacteristics outCharacteristics;
- int ret = getKeyCharacteristics(name, clientId.get(), appData.get(), uid,
- &outCharacteristics);
- if (clientId.get() && clientId->data) {
- free(const_cast<void*>(static_cast<const void*>(clientId->data)));
- }
- if (appData.get() && appData->data) {
- free(const_cast<void*>(static_cast<const void*>(appData->data)));
- }
- reply->writeNoException();
- reply->writeInt32(ret);
- reply->writeParcelable(outCharacteristics);
- return NO_ERROR;
- }
- case IMPORT_KEY: {
- CHECK_INTERFACE(IKeystoreService, data, reply);
- String16 name = data.readString16();
- KeymasterArguments args;
- if (data.readInt32() != 0) {
- args.readFromParcel(data);
- }
- keymaster_key_format_t format = static_cast<keymaster_key_format_t>(data.readInt32());
- const uint8_t* keyData = NULL;
- size_t keyLength = 0;
- readByteArray(data, &keyData, &keyLength);
- int32_t uid = data.readInt32();
- int32_t flags = data.readInt32();
- KeyCharacteristics outCharacteristics;
- int32_t ret = importKey(name, args, format, keyData, keyLength, uid, flags,
- &outCharacteristics);
- reply->writeNoException();
- reply->writeInt32(ret);
- reply->writeParcelable(outCharacteristics);
- return NO_ERROR;
- }
- case EXPORT_KEY: {
- CHECK_INTERFACE(IKeystoreService, data, reply);
- String16 name = data.readString16();
- keymaster_key_format_t format = static_cast<keymaster_key_format_t>(data.readInt32());
- std::unique_ptr<keymaster_blob_t> clientId = readKeymasterBlob(data);
- std::unique_ptr<keymaster_blob_t> appData = readKeymasterBlob(data);
- int32_t uid = data.readInt32();
- ExportResult result;
- exportKey(name, format, clientId.get(), appData.get(), uid, &result);
- if (clientId.get() && clientId->data) {
- free(const_cast<void*>(static_cast<const void*>(clientId->data)));
- }
- if (appData.get() && appData->data) {
- free(const_cast<void*>(static_cast<const void*>(appData->data)));
- }
- reply->writeNoException();
- reply->writeParcelable(result);
+ int32_t ret = generate(name, uid, keyType, keySize, flags, &args);
+ reply->writeNoException();
+ reply->writeInt32(ret);
+ return NO_ERROR;
+ } break;
+ case IMPORT: {
+ CHECK_INTERFACE(IKeystoreService, data, reply);
+ String16 name = data.readString16();
+ auto in = readBlobAsByteArray(data);
+ int uid = data.readInt32();
+ int32_t flags = data.readInt32();
+ auto ret = import(name, in.value(), uid, flags);
+ reply->writeNoException();
+ reply->writeInt32(ret);
+ return NO_ERROR;
+ } break;
+ case SIGN: {
+ CHECK_INTERFACE(IKeystoreService, data, reply);
+ String16 name = data.readString16();
+ auto in = readBlobAsByteArray(data);
+ hidl_vec<uint8_t> out;
+ auto ret = sign(name, in.value(), &out);
+ reply->writeNoException();
+ writeBlobAsByteArray(out, reply);
+ reply->writeInt32(ret);
+ return NO_ERROR;
+ } break;
+ case VERIFY: {
+ CHECK_INTERFACE(IKeystoreService, data, reply);
+ String16 name = data.readString16();
+ auto in = readBlobAsByteArray(data);
+ auto signature = readBlobAsByteArray(data);
+ auto ret = verify(name, in.value(), signature.value());
+ reply->writeNoException();
+ reply->writeInt32(ret);
+ return NO_ERROR;
+ } break;
+ case GET_PUBKEY: {
+ CHECK_INTERFACE(IKeystoreService, data, reply);
+ String16 name = data.readString16();
+ hidl_vec<uint8_t> out;
+ auto ret = get_pubkey(name, &out);
+ reply->writeNoException();
+ writeBlobAsByteArray(out, reply);
+ reply->writeInt32(ret);
+ return NO_ERROR;
+ } break;
+ case GRANT: {
+ CHECK_INTERFACE(IKeystoreService, data, reply);
+ String16 name = data.readString16();
+ int32_t granteeUid = data.readInt32();
+ int32_t ret = grant(name, granteeUid);
+ reply->writeNoException();
+ reply->writeInt32(ret);
+ return NO_ERROR;
+ } break;
+ case UNGRANT: {
+ CHECK_INTERFACE(IKeystoreService, data, reply);
+ String16 name = data.readString16();
+ int32_t granteeUid = data.readInt32();
+ int32_t ret = ungrant(name, granteeUid);
+ reply->writeNoException();
+ reply->writeInt32(ret);
+ return NO_ERROR;
+ } break;
+ case GETMTIME: {
+ CHECK_INTERFACE(IKeystoreService, data, reply);
+ String16 name = data.readString16();
+ int32_t uid = data.readInt32();
+ int64_t ret = getmtime(name, uid);
+ reply->writeNoException();
+ reply->writeInt64(ret);
+ return NO_ERROR;
+ } break;
+ case DUPLICATE: {
+ CHECK_INTERFACE(IKeystoreService, data, reply);
+ String16 srcKey = data.readString16();
+ int32_t srcUid = data.readInt32();
+ String16 destKey = data.readString16();
+ int32_t destUid = data.readInt32();
+ int32_t ret = duplicate(srcKey, srcUid, destKey, destUid);
+ reply->writeNoException();
+ reply->writeInt32(ret);
+ return NO_ERROR;
+ } break;
+ case IS_HARDWARE_BACKED: {
+ CHECK_INTERFACE(IKeystoreService, data, reply);
+ String16 keyType = data.readString16();
+ int32_t ret = is_hardware_backed(keyType);
+ reply->writeNoException();
+ reply->writeInt32(ret);
+ return NO_ERROR;
+ }
+ case CLEAR_UID: {
+ CHECK_INTERFACE(IKeystoreService, data, reply);
+ int64_t uid = data.readInt64();
+ int32_t ret = clear_uid(uid);
+ reply->writeNoException();
+ reply->writeInt32(ret);
+ return NO_ERROR;
+ }
+ case ADD_RNG_ENTROPY: {
+ CHECK_INTERFACE(IKeystoreService, data, reply);
+ auto entropy = readBlobAsByteArray(data);
+ auto ret = addRngEntropy(entropy.value());
+ reply->writeNoException();
+ reply->writeInt32(ret);
+ return NO_ERROR;
+ }
+ case GENERATE_KEY: {
+ CHECK_INTERFACE(IKeystoreService, data, reply);
+ String16 name = data.readString16();
+ auto params = nullable(readParamSetFromParcel, data);
+ auto entropy = readBlobAsByteArray(data);
+ int32_t uid = data.readInt32();
+ int32_t flags = data.readInt32();
+ KeyCharacteristics outCharacteristics;
+ int32_t ret =
+ generateKey(name, params.value(), entropy.value(), uid, flags, &outCharacteristics);
+ reply->writeNoException();
+ reply->writeInt32(ret);
+ nullable(writeKeyCharacteristicsToParcel, outCharacteristics, reply);
+ return NO_ERROR;
+ }
+ case GET_KEY_CHARACTERISTICS: {
+ CHECK_INTERFACE(IKeystoreService, data, reply);
+ String16 name = data.readString16();
+ auto clientId = nullable(readKeymasterBlob, data, true);
+ auto appData = nullable(readKeymasterBlob, data, true);
+ int32_t uid = data.readInt32();
+ KeyCharacteristics outCharacteristics;
+ int ret = getKeyCharacteristics(name, clientId.value(), appData.value(), uid,
+ &outCharacteristics);
+ reply->writeNoException();
+ reply->writeInt32(ret);
+ nullable(writeKeyCharacteristicsToParcel, outCharacteristics, reply);
+ return NO_ERROR;
+ }
+ case IMPORT_KEY: {
+ CHECK_INTERFACE(IKeystoreService, data, reply);
+ String16 name = data.readString16();
+ auto args = nullable(readParamSetFromParcel, data);
+ KeyFormat format = static_cast<KeyFormat>(data.readInt32());
+ auto keyData = readBlobAsByteArray(data);
+ int32_t uid = data.readInt32();
+ int32_t flags = data.readInt32();
+ KeyCharacteristics outCharacteristics;
+ int32_t ret =
+ importKey(name, args.value(), format, keyData.value(), uid, flags, &outCharacteristics);
+ reply->writeNoException();
+ reply->writeInt32(ret);
+ nullable(writeKeyCharacteristicsToParcel, outCharacteristics, reply);
+ return NO_ERROR;
+ }
+ case EXPORT_KEY: {
+ CHECK_INTERFACE(IKeystoreService, data, reply);
+ String16 name = data.readString16();
+ KeyFormat format = static_cast<KeyFormat>(data.readInt32());
+ auto clientId = nullable(readKeymasterBlob, data, true);
+ auto appData = nullable(readKeymasterBlob, data, true);
+ int32_t uid = data.readInt32();
+ ExportResult result;
+ exportKey(name, format, clientId.value(), appData.value(), uid, &result);
+ reply->writeNoException();
+ reply->writeParcelable(result);
- return NO_ERROR;
- }
- case BEGIN: {
- CHECK_INTERFACE(IKeystoreService, data, reply);
- sp<IBinder> token = data.readStrongBinder();
- String16 name = data.readString16();
- keymaster_purpose_t purpose = static_cast<keymaster_purpose_t>(data.readInt32());
- bool pruneable = data.readInt32() != 0;
- KeymasterArguments args;
- if (data.readInt32() != 0) {
- args.readFromParcel(data);
- }
- const uint8_t* entropy = NULL;
- size_t entropyLength = 0;
- readByteArray(data, &entropy, &entropyLength);
- int32_t uid = data.readInt32();
- OperationResult result;
- begin(token, name, purpose, pruneable, args, entropy, entropyLength, uid, &result);
- reply->writeNoException();
- reply->writeParcelable(result);
+ return NO_ERROR;
+ }
+ case BEGIN: {
+ CHECK_INTERFACE(IKeystoreService, data, reply);
+ sp<IBinder> token = data.readStrongBinder();
+ String16 name = data.readString16();
+ KeyPurpose purpose = static_cast<KeyPurpose>(data.readInt32());
+ bool pruneable = data.readInt32() != 0;
+ auto args = nullable(readParamSetFromParcel, data);
+ auto entropy = readBlobAsByteArray(data);
+ int32_t uid = data.readInt32();
+ OperationResult result;
+ begin(token, name, purpose, pruneable, args.value(), entropy.value(), uid, &result);
+ reply->writeNoException();
+ reply->writeParcelable(result);
- return NO_ERROR;
- }
- case UPDATE: {
- CHECK_INTERFACE(IKeystoreService, data, reply);
- sp<IBinder> token = data.readStrongBinder();
- KeymasterArguments args;
- if (data.readInt32() != 0) {
- args.readFromParcel(data);
- }
- const uint8_t* buf = NULL;
- size_t bufLength = 0;
- readByteArray(data, &buf, &bufLength);
- OperationResult result;
- update(token, args, buf, bufLength, &result);
- reply->writeNoException();
- reply->writeParcelable(result);
+ return NO_ERROR;
+ }
+ case UPDATE: {
+ CHECK_INTERFACE(IKeystoreService, data, reply);
+ sp<IBinder> token = data.readStrongBinder();
+ auto args = nullable(readParamSetFromParcel, data);
+ auto buf = readBlobAsByteArray(data);
+ OperationResult result;
+ update(token, args.value(), buf.value(), &result);
+ reply->writeNoException();
+ reply->writeParcelable(result);
- return NO_ERROR;
- }
- case FINISH: {
- CHECK_INTERFACE(IKeystoreService, data, reply);
- sp<IBinder> token = data.readStrongBinder();
- KeymasterArguments args;
- if (data.readInt32() != 0) {
- args.readFromParcel(data);
- }
- const uint8_t* signature = NULL;
- size_t signatureLength = 0;
- readByteArray(data, &signature, &signatureLength);
- const uint8_t* entropy = NULL;
- size_t entropyLength = 0;
- readByteArray(data, &entropy, &entropyLength);
- OperationResult result;
- finish(token, args, signature, signatureLength, entropy, entropyLength, &result);
- reply->writeNoException();
- reply->writeParcelable(result);
+ return NO_ERROR;
+ }
+ case FINISH: {
+ CHECK_INTERFACE(IKeystoreService, data, reply);
+ sp<IBinder> token = data.readStrongBinder();
+ auto args = nullable(readParamSetFromParcel, data);
+ auto signature = readBlobAsByteArray(data);
+ auto entropy = readBlobAsByteArray(data);
+ OperationResult result;
+ finish(token, args.value(), signature.value(), entropy.value(), &result);
+ reply->writeNoException();
+ reply->writeParcelable(result);
- return NO_ERROR;
- }
- case ABORT: {
- CHECK_INTERFACE(IKeystoreService, data, reply);
- sp<IBinder> token = data.readStrongBinder();
- int32_t result = abort(token);
- reply->writeNoException();
- reply->writeInt32(result);
+ return NO_ERROR;
+ }
+ case ABORT: {
+ CHECK_INTERFACE(IKeystoreService, data, reply);
+ sp<IBinder> token = data.readStrongBinder();
+ int32_t result = abort(token);
+ reply->writeNoException();
+ reply->writeInt32(result);
- return NO_ERROR;
- }
- case IS_OPERATION_AUTHORIZED: {
- CHECK_INTERFACE(IKeystoreService, data, reply);
- sp<IBinder> token = data.readStrongBinder();
- bool result = isOperationAuthorized(token);
- reply->writeNoException();
- reply->writeInt32(result ? 1 : 0);
+ return NO_ERROR;
+ }
+ case IS_OPERATION_AUTHORIZED: {
+ CHECK_INTERFACE(IKeystoreService, data, reply);
+ sp<IBinder> token = data.readStrongBinder();
+ bool result = isOperationAuthorized(token);
+ reply->writeNoException();
+ reply->writeInt32(result ? 1 : 0);
- return NO_ERROR;
- }
- case ADD_AUTH_TOKEN: {
- CHECK_INTERFACE(IKeystoreService, data, reply);
- const uint8_t* token_bytes = NULL;
- size_t size = 0;
- readByteArray(data, &token_bytes, &size);
- int32_t result = addAuthToken(token_bytes, size);
- reply->writeNoException();
- reply->writeInt32(result);
+ return NO_ERROR;
+ }
+ case ADD_AUTH_TOKEN: {
+ CHECK_INTERFACE(IKeystoreService, data, reply);
+ const uint8_t* token_bytes = NULL;
+ size_t size = 0;
+ readByteArray(data, &token_bytes, &size);
+ int32_t result = addAuthToken(token_bytes, size);
+ reply->writeNoException();
+ reply->writeInt32(result);
- return NO_ERROR;
- }
- case ON_USER_ADDED: {
- CHECK_INTERFACE(IKeystoreService, data, reply);
- int32_t userId = data.readInt32();
- int32_t parentId = data.readInt32();
- int32_t result = onUserAdded(userId, parentId);
- reply->writeNoException();
- reply->writeInt32(result);
+ return NO_ERROR;
+ }
+ case ON_USER_ADDED: {
+ CHECK_INTERFACE(IKeystoreService, data, reply);
+ int32_t userId = data.readInt32();
+ int32_t parentId = data.readInt32();
+ int32_t result = onUserAdded(userId, parentId);
+ reply->writeNoException();
+ reply->writeInt32(result);
- return NO_ERROR;
- }
- case ON_USER_REMOVED: {
- CHECK_INTERFACE(IKeystoreService, data, reply);
- int32_t userId = data.readInt32();
- int32_t result = onUserRemoved(userId);
- reply->writeNoException();
- reply->writeInt32(result);
+ return NO_ERROR;
+ }
+ case ON_USER_REMOVED: {
+ CHECK_INTERFACE(IKeystoreService, data, reply);
+ int32_t userId = data.readInt32();
+ int32_t result = onUserRemoved(userId);
+ reply->writeNoException();
+ reply->writeInt32(result);
- return NO_ERROR;
- }
- case ATTEST_KEY: {
- CHECK_INTERFACE(IKeystoreService, data, reply);
- String16 name = data.readString16();
- KeymasterArguments params;
- if (data.readInt32() != 0) {
- params.readFromParcel(data);
- }
- KeymasterCertificateChain chain;
- int ret = attestKey(name, params, &chain);
- reply->writeNoException();
- reply->writeInt32(ret);
- reply->writeInt32(1);
- chain.writeToParcel(reply);
+ return NO_ERROR;
+ }
+ case ATTEST_KEY: {
+ CHECK_INTERFACE(IKeystoreService, data, reply);
+ String16 name = data.readString16();
+ auto params = nullable(readParamSetFromParcel, data);
+ hidl_vec<hidl_vec<uint8_t>> chain;
+ int ret = attestKey(name, params.value(), &chain);
+ reply->writeNoException();
+ reply->writeInt32(ret);
+ nullable(writeCertificateChainToParcel, chain, reply);
- return NO_ERROR;
- }
- case ON_DEVICE_OFF_BODY: {
- CHECK_INTERFACE(IKeystoreService, data, reply);
- int32_t ret = onDeviceOffBody();
- reply->writeNoException();
- reply->writeInt32(ret);
+ return NO_ERROR;
+ }
+ case ON_DEVICE_OFF_BODY: {
+ CHECK_INTERFACE(IKeystoreService, data, reply);
+ int32_t ret = onDeviceOffBody();
+ reply->writeNoException();
+ reply->writeInt32(ret);
- return NO_ERROR;
- }
- default:
- return BBinder::onTransact(code, data, reply, flags);
+ return NO_ERROR;
+ }
+ default:
+ return BBinder::onTransact(code, data, reply, flags);
}
}
// ----------------------------------------------------------------------------
-}; // namespace android
+}; // namespace android
diff --git a/keystore/auth_token_table.cpp b/keystore/auth_token_table.cpp
index f0f4981..3f476cd 100644
--- a/keystore/auth_token_table.cpp
+++ b/keystore/auth_token_table.cpp
@@ -21,10 +21,36 @@
#include <algorithm>
-#include <keymaster/android_keymaster_utils.h>
-#include <keymaster/logger.h>
+#include <cutils/log.h>
-namespace keymaster {
+namespace keystore {
+
+template <typename IntType, uint32_t byteOrder> struct choose_hton;
+
+template <typename IntType> struct choose_hton<IntType, __ORDER_LITTLE_ENDIAN__> {
+ inline static IntType hton(const IntType& value) {
+ IntType result = 0;
+ const unsigned char* inbytes = reinterpret_cast<const unsigned char*>(&value);
+ unsigned char* outbytes = reinterpret_cast<unsigned char*>(&result);
+ for (int i = sizeof(IntType) - 1; i >= 0; --i) {
+ *(outbytes++) = inbytes[i];
+ }
+ return result;
+ }
+};
+
+template <typename IntType> struct choose_hton<IntType, __ORDER_BIG_ENDIAN__> {
+ inline static IntType hton(const IntType& value) { return value; }
+};
+
+template <typename IntType> inline IntType hton(const IntType& value) {
+ return choose_hton<IntType, __BYTE_ORDER__>::hton(value);
+}
+
+template <typename IntType> inline IntType ntoh(const IntType& value) {
+ // same operation and hton
+ return choose_hton<IntType, __BYTE_ORDER__>::hton(value);
+}
//
// Some trivial template wrappers around std algorithms, so they take containers not ranges.
@@ -49,48 +75,43 @@
return time.tv_sec;
}
-void AuthTokenTable::AddAuthenticationToken(const hw_auth_token_t* auth_token) {
+void AuthTokenTable::AddAuthenticationToken(const HardwareAuthToken* auth_token) {
Entry new_entry(auth_token, clock_function_());
RemoveEntriesSupersededBy(new_entry);
if (entries_.size() >= max_entries_) {
- LOG_W("Auth token table filled up; replacing oldest entry", 0);
+ ALOGW("Auth token table filled up; replacing oldest entry");
*min_element(entries_) = std::move(new_entry);
} else {
entries_.push_back(std::move(new_entry));
}
}
-inline bool is_secret_key_operation(keymaster_algorithm_t algorithm, keymaster_purpose_t purpose) {
- if ((algorithm != KM_ALGORITHM_RSA && algorithm != KM_ALGORITHM_EC))
+inline bool is_secret_key_operation(Algorithm algorithm, KeyPurpose purpose) {
+ if ((algorithm != Algorithm::RSA && algorithm != Algorithm::EC))
return true;
- if (purpose == KM_PURPOSE_SIGN || purpose == KM_PURPOSE_DECRYPT)
+ if (purpose == KeyPurpose::SIGN || purpose == KeyPurpose::DECRYPT)
return true;
return false;
}
-inline bool KeyRequiresAuthentication(const AuthorizationSet& key_info,
- keymaster_purpose_t purpose) {
- keymaster_algorithm_t algorithm = KM_ALGORITHM_AES;
- key_info.GetTagValue(TAG_ALGORITHM, &algorithm);
- return is_secret_key_operation(algorithm, purpose) && key_info.find(TAG_NO_AUTH_REQUIRED) == -1;
+inline bool KeyRequiresAuthentication(const AuthorizationSet& key_info, KeyPurpose purpose) {
+ auto algorithm = defaultOr(key_info.GetTagValue(TAG_ALGORITHM), Algorithm::AES);
+ return is_secret_key_operation(algorithm, purpose) &&
+ key_info.find(Tag::NO_AUTH_REQUIRED) == -1;
}
-inline bool KeyRequiresAuthPerOperation(const AuthorizationSet& key_info,
- keymaster_purpose_t purpose) {
- keymaster_algorithm_t algorithm = KM_ALGORITHM_AES;
- key_info.GetTagValue(TAG_ALGORITHM, &algorithm);
- return is_secret_key_operation(algorithm, purpose) && key_info.find(TAG_AUTH_TIMEOUT) == -1;
+inline bool KeyRequiresAuthPerOperation(const AuthorizationSet& key_info, KeyPurpose purpose) {
+ auto algorithm = defaultOr(key_info.GetTagValue(TAG_ALGORITHM), Algorithm::AES);
+ return is_secret_key_operation(algorithm, purpose) && key_info.find(Tag::AUTH_TIMEOUT) == -1;
}
AuthTokenTable::Error AuthTokenTable::FindAuthorization(const AuthorizationSet& key_info,
- keymaster_purpose_t purpose,
- keymaster_operation_handle_t op_handle,
- const hw_auth_token_t** found) {
- if (!KeyRequiresAuthentication(key_info, purpose))
- return AUTH_NOT_REQUIRED;
+ KeyPurpose purpose, uint64_t op_handle,
+ const HardwareAuthToken** found) {
+ if (!KeyRequiresAuthentication(key_info, purpose)) return AUTH_NOT_REQUIRED;
- hw_authenticator_type_t auth_type = HW_AUTH_NONE;
- key_info.GetTagValue(TAG_USER_AUTH_TYPE, &auth_type);
+ auto auth_type =
+ defaultOr(key_info.GetTagValue(TAG_USER_AUTH_TYPE), HardwareAuthenticatorType::NONE);
std::vector<uint64_t> key_sids;
ExtractSids(key_info, &key_sids);
@@ -101,44 +122,41 @@
return FindTimedAuthorization(key_sids, auth_type, key_info, found);
}
-AuthTokenTable::Error AuthTokenTable::FindAuthPerOpAuthorization(
- const std::vector<uint64_t>& sids, hw_authenticator_type_t auth_type,
- keymaster_operation_handle_t op_handle, const hw_auth_token_t** found) {
- if (op_handle == 0)
- return OP_HANDLE_REQUIRED;
+AuthTokenTable::Error
+AuthTokenTable::FindAuthPerOpAuthorization(const std::vector<uint64_t>& sids,
+ HardwareAuthenticatorType auth_type, uint64_t op_handle,
+ const HardwareAuthToken** found) {
+ if (op_handle == 0) return OP_HANDLE_REQUIRED;
auto matching_op = find_if(
entries_, [&](Entry& e) { return e.token()->challenge == op_handle && !e.completed(); });
- if (matching_op == entries_.end())
- return AUTH_TOKEN_NOT_FOUND;
+ if (matching_op == entries_.end()) return AUTH_TOKEN_NOT_FOUND;
- if (!matching_op->SatisfiesAuth(sids, auth_type))
- return AUTH_TOKEN_WRONG_SID;
+ if (!matching_op->SatisfiesAuth(sids, auth_type)) return AUTH_TOKEN_WRONG_SID;
*found = matching_op->token();
return OK;
}
AuthTokenTable::Error AuthTokenTable::FindTimedAuthorization(const std::vector<uint64_t>& sids,
- hw_authenticator_type_t auth_type,
+ HardwareAuthenticatorType auth_type,
const AuthorizationSet& key_info,
- const hw_auth_token_t** found) {
+ const HardwareAuthToken** found) {
Entry* newest_match = NULL;
for (auto& entry : entries_)
if (entry.SatisfiesAuth(sids, auth_type) && entry.is_newer_than(newest_match))
newest_match = &entry;
- if (!newest_match)
- return AUTH_TOKEN_NOT_FOUND;
+ if (!newest_match) return AUTH_TOKEN_NOT_FOUND;
- uint32_t timeout;
- key_info.GetTagValue(TAG_AUTH_TIMEOUT, &timeout);
+ auto timeout = defaultOr(key_info.GetTagValue(TAG_AUTH_TIMEOUT), 0);
+
time_t now = clock_function_();
if (static_cast<int64_t>(newest_match->time_received()) + timeout < static_cast<int64_t>(now))
return AUTH_TOKEN_EXPIRED;
- if (key_info.GetTagValue(TAG_ALLOW_WHILE_ON_BODY)) {
+ if (key_info.GetTagValue(TAG_ALLOW_WHILE_ON_BODY).isOk()) {
if (static_cast<int64_t>(newest_match->time_received()) <
static_cast<int64_t>(last_off_body_)) {
return AUTH_TOKEN_EXPIRED;
@@ -153,8 +171,8 @@
void AuthTokenTable::ExtractSids(const AuthorizationSet& key_info, std::vector<uint64_t>* sids) {
assert(sids);
for (auto& param : key_info)
- if (param.tag == TAG_USER_SECURE_ID)
- sids->push_back(param.long_integer);
+ if (param.tag == Tag::USER_SECURE_ID)
+ sids->push_back(authorizationValue(TAG_USER_SECURE_ID, param).value());
}
void AuthTokenTable::RemoveEntriesSupersededBy(const Entry& entry) {
@@ -175,38 +193,35 @@
[&](Entry& e) { return e.Supersedes(entry); });
}
-void AuthTokenTable::MarkCompleted(const keymaster_operation_handle_t op_handle) {
+void AuthTokenTable::MarkCompleted(const uint64_t op_handle) {
auto found = find_if(entries_, [&](Entry& e) { return e.token()->challenge == op_handle; });
- if (found == entries_.end())
- return;
+ if (found == entries_.end()) return;
assert(!IsSupersededBySomeEntry(*found));
found->mark_completed();
- if (IsSupersededBySomeEntry(*found))
- entries_.erase(found);
+ if (IsSupersededBySomeEntry(*found)) entries_.erase(found);
}
-AuthTokenTable::Entry::Entry(const hw_auth_token_t* token, time_t current_time)
+AuthTokenTable::Entry::Entry(const HardwareAuthToken* token, time_t current_time)
: token_(token), time_received_(current_time), last_use_(current_time),
- operation_completed_(token_->challenge == 0) {
-}
+ operation_completed_(token_->challenge == 0) {}
uint32_t AuthTokenTable::Entry::timestamp_host_order() const {
return ntoh(token_->timestamp);
}
-hw_authenticator_type_t AuthTokenTable::Entry::authenticator_type() const {
- hw_authenticator_type_t result = static_cast<hw_authenticator_type_t>(
- ntoh(static_cast<uint32_t>(token_->authenticator_type)));
+HardwareAuthenticatorType AuthTokenTable::Entry::authenticator_type() const {
+ HardwareAuthenticatorType result = static_cast<HardwareAuthenticatorType>(
+ ntoh(static_cast<uint32_t>(token_->authenticatorType)));
return result;
}
bool AuthTokenTable::Entry::SatisfiesAuth(const std::vector<uint64_t>& sids,
- hw_authenticator_type_t auth_type) {
+ HardwareAuthenticatorType auth_type) {
for (auto sid : sids)
- if ((sid == token_->authenticator_id) ||
- (sid == token_->user_id && (auth_type & authenticator_type()) != 0))
+ if ((sid == token_->authenticatorId) ||
+ (sid == token_->userId && (auth_type & authenticator_type()) != 0))
return true;
return false;
}
@@ -216,12 +231,11 @@
}
bool AuthTokenTable::Entry::Supersedes(const Entry& entry) const {
- if (!entry.completed())
- return false;
+ if (!entry.completed()) return false;
- return (token_->user_id == entry.token_->user_id &&
- token_->authenticator_type == entry.token_->authenticator_type &&
- token_->authenticator_type == entry.token_->authenticator_type &&
+ return (token_->userId == entry.token_->userId &&
+ token_->authenticatorType == entry.token_->authenticatorType &&
+ token_->authenticatorType == entry.token_->authenticatorType &&
timestamp_host_order() > entry.timestamp_host_order());
}
diff --git a/keystore/auth_token_table.h b/keystore/auth_token_table.h
index 4d54a39..6f7aab1 100644
--- a/keystore/auth_token_table.h
+++ b/keystore/auth_token_table.h
@@ -18,12 +18,14 @@
#include <vector>
#include <hardware/hw_auth_token.h>
-#include <keymaster/authorization_set.h>
+#include <keystore/authorization_set.h>
#ifndef KEYSTORE_AUTH_TOKEN_TABLE_H_
#define KEYSTORE_AUTH_TOKEN_TABLE_H_
-namespace keymaster {
+namespace keystore {
+
+using android::hardware::keymaster::V3_0::HardwareAuthToken;
namespace test {
class AuthTokenTableTest;
@@ -42,7 +44,8 @@
class AuthTokenTable {
public:
explicit AuthTokenTable(size_t max_entries = 32, time_t (*clock_function)() = clock_gettime_raw)
- : max_entries_(max_entries), last_off_body_(clock_function()), clock_function_(clock_function) {}
+ : max_entries_(max_entries), last_off_body_(clock_function()),
+ clock_function_(clock_function) {}
enum Error {
OK,
@@ -58,7 +61,7 @@
/**
* Add an authorization token to the table. The table takes ownership of the argument.
*/
- void AddAuthenticationToken(const hw_auth_token_t* token);
+ void AddAuthenticationToken(const HardwareAuthToken* token);
/**
* Find an authorization token that authorizes the operation specified by \p operation_handle on
@@ -70,30 +73,14 @@
*
* The table retains ownership of the returned object.
*/
- Error FindAuthorization(const AuthorizationSet& key_info, keymaster_purpose_t purpose,
- keymaster_operation_handle_t op_handle, const hw_auth_token_t** found);
-
- /**
- * Find an authorization token that authorizes the operation specified by \p operation_handle on
- * a key with the characteristics specified in \p key_info.
- *
- * This method is O(n * m), where n is the number of KM_TAG_USER_SECURE_ID entries in key_info
- * and m is the number of entries in the table. It could be made better, but n and m should
- * always be small.
- *
- * The table retains ownership of the returned object.
- */
- Error FindAuthorization(const keymaster_key_param_t* params, size_t params_count,
- keymaster_purpose_t purpose, keymaster_operation_handle_t op_handle,
- const hw_auth_token_t** found) {
- return FindAuthorization(AuthorizationSet(params, params_count), purpose, op_handle, found);
- }
+ Error FindAuthorization(const AuthorizationSet& key_info, KeyPurpose purpose,
+ uint64_t op_handle, const HardwareAuthToken** found);
/**
* Mark operation completed. This allows tokens associated with the specified operation to be
* superseded by new tokens.
*/
- void MarkCompleted(const keymaster_operation_handle_t op_handle);
+ void MarkCompleted(const uint64_t op_handle);
/**
* Update the last_off_body_ timestamp so that tokens which remain authorized only so long as
@@ -110,7 +97,7 @@
class Entry {
public:
- Entry(const hw_auth_token_t* token, time_t current_time);
+ Entry(const HardwareAuthToken* token, time_t current_time);
Entry(Entry&& entry) { *this = std::move(entry); }
void operator=(Entry&& rhs) {
@@ -125,36 +112,34 @@
void UpdateLastUse(time_t time);
bool Supersedes(const Entry& entry) const;
- bool SatisfiesAuth(const std::vector<uint64_t>& sids, hw_authenticator_type_t auth_type);
+ bool SatisfiesAuth(const std::vector<uint64_t>& sids, HardwareAuthenticatorType auth_type);
bool is_newer_than(const Entry* entry) {
- if (!entry)
- return true;
+ if (!entry) return true;
return timestamp_host_order() > entry->timestamp_host_order();
}
void mark_completed() { operation_completed_ = true; }
- const hw_auth_token_t* token() { return token_.get(); }
+ const HardwareAuthToken* token() { return token_.get(); }
time_t time_received() const { return time_received_; }
bool completed() const { return operation_completed_; }
uint32_t timestamp_host_order() const;
- hw_authenticator_type_t authenticator_type() const;
+ HardwareAuthenticatorType authenticator_type() const;
private:
- std::unique_ptr<const hw_auth_token_t> token_;
+ std::unique_ptr<const HardwareAuthToken> token_;
time_t time_received_;
time_t last_use_;
bool operation_completed_;
};
Error FindAuthPerOpAuthorization(const std::vector<uint64_t>& sids,
- hw_authenticator_type_t auth_type,
- keymaster_operation_handle_t op_handle,
- const hw_auth_token_t** found);
+ HardwareAuthenticatorType auth_type, uint64_t op_handle,
+ const HardwareAuthToken** found);
Error FindTimedAuthorization(const std::vector<uint64_t>& sids,
- hw_authenticator_type_t auth_type,
- const AuthorizationSet& key_info, const hw_auth_token_t** found);
+ HardwareAuthenticatorType auth_type,
+ const AuthorizationSet& key_info, const HardwareAuthToken** found);
void ExtractSids(const AuthorizationSet& key_info, std::vector<uint64_t>* sids);
void RemoveEntriesSupersededBy(const Entry& entry);
bool IsSupersededBySomeEntry(const Entry& entry);
diff --git a/keystore/authorization_set.cpp b/keystore/authorization_set.cpp
new file mode 100644
index 0000000..e30b32d
--- /dev/null
+++ b/keystore/authorization_set.cpp
@@ -0,0 +1,427 @@
+/*
+ * Copyright (C) 2014 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 <keystore/authorization_set.h>
+
+#include <assert.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+#include <limits>
+#include <ostream>
+#include <istream>
+
+#include <new>
+
+namespace keystore {
+
+inline bool keyParamLess(const KeyParameter& a, const KeyParameter& b) {
+ if (a.tag != b.tag) return a.tag < b.tag;
+ int retval;
+ switch (typeFromTag(a.tag)) {
+ case TagType::INVALID:
+ case TagType::BOOL:
+ return false;
+ case TagType::ENUM:
+ case TagType::ENUM_REP:
+ case TagType::UINT:
+ case TagType::UINT_REP:
+ return a.f.integer < b.f.integer;
+ case TagType::ULONG:
+ case TagType::ULONG_REP:
+ return a.f.longInteger < b.f.longInteger;
+ case TagType::DATE:
+ return a.f.dateTime < b.f.dateTime;
+ case TagType::BIGNUM:
+ case TagType::BYTES:
+ // Handle the empty cases.
+ if (a.blob.size() == 0)
+ return b.blob.size() != 0;
+ if (b.blob.size() == 0) return false;
+
+ retval = memcmp(&a.blob[0], &b.blob[0], std::min(a.blob.size(), b.blob.size()));
+ // if one is the prefix of the other the longer wins
+ if (retval == 0) return a.blob.size() < b.blob.size();
+ // Otherwise a is less if a is less.
+ else return retval < 0;
+ }
+ return false;
+}
+
+inline bool keyParamEqual(const KeyParameter& a, const KeyParameter& b) {
+ if (a.tag != b.tag) return false;
+
+ switch (typeFromTag(a.tag)) {
+ case TagType::INVALID:
+ case TagType::BOOL:
+ return true;
+ case TagType::ENUM:
+ case TagType::ENUM_REP:
+ case TagType::UINT:
+ case TagType::UINT_REP:
+ return a.f.integer == b.f.integer;
+ case TagType::ULONG:
+ case TagType::ULONG_REP:
+ return a.f.longInteger == b.f.longInteger;
+ case TagType::DATE:
+ return a.f.dateTime == b.f.dateTime;
+ case TagType::BIGNUM:
+ case TagType::BYTES:
+ if (a.blob.size() != b.blob.size()) return false;
+ return a.blob.size() == 0 ||
+ memcmp(&a.blob[0], &b.blob[0], a.blob.size()) == 0;
+ }
+ return false;
+}
+
+void AuthorizationSet::Sort() {
+ std::sort(data_.begin(), data_.end(), keyParamLess);
+}
+
+void AuthorizationSet::Deduplicate() {
+ if (data_.empty()) return;
+
+ Sort();
+ std::vector<KeyParameter> result;
+
+ auto curr = data_.begin();
+ auto prev = curr++;
+ for (; curr != data_.end(); ++prev, ++curr) {
+ if (prev->tag == Tag::INVALID) continue;
+
+ if (!keyParamEqual(*prev, *curr)) {
+ result.emplace_back(std::move(*prev));
+ }
+ }
+ result.emplace_back(std::move(*prev));
+
+ std::swap(data_, result);
+}
+
+void AuthorizationSet::Union(const AuthorizationSet& other) {
+ data_.insert(data_.end(), other.data_.begin(), other.data_.end());
+ Deduplicate();
+}
+
+void AuthorizationSet::Subtract(const AuthorizationSet& other) {
+ Deduplicate();
+
+ auto i = other.begin();
+ while (i != other.end()) {
+ int pos = -1;
+ do {
+ pos = find(i->tag, pos);
+ if (pos != -1 && keyParamEqual(*i, data_[pos])) {
+ data_.erase(data_.begin() + pos);
+ break;
+ }
+ } while (pos != -1);
+ ++i;
+ }
+}
+
+int AuthorizationSet::find(Tag tag, int begin) const {
+ auto iter = data_.begin() + (1 + begin);
+
+ while (iter != data_.end() && iter->tag != tag) ++iter;
+
+ if (iter != data_.end()) return iter - data_.begin();
+ return -1;
+}
+
+bool AuthorizationSet::erase(int index) {
+ auto pos = data_.begin() + index;
+ if (pos != data_.end()) {
+ data_.erase(pos);
+ return true;
+ }
+ return false;
+}
+
+KeyParameter& AuthorizationSet::operator[](int at) {
+ return data_[at];
+}
+
+const KeyParameter& AuthorizationSet::operator[](int at) const {
+ return data_[at];
+}
+
+void AuthorizationSet::Clear() {
+ data_.clear();
+}
+
+size_t AuthorizationSet::GetTagCount(Tag tag) const {
+ size_t count = 0;
+ for (int pos = -1; (pos = find(tag, pos)) != -1;)
+ ++count;
+ return count;
+}
+
+NullOr<const KeyParameter&> AuthorizationSet::GetEntry(Tag tag) const {
+ int pos = find(tag);
+ if (pos == -1) return {};
+ return data_[pos];
+}
+
+/**
+ * Persistent format is:
+ * | 32 bit indirect_size |
+ * --------------------------------
+ * | indirect_size bytes of data | this is where the blob data is stored
+ * --------------------------------
+ * | 32 bit element_count | number of entries
+ * | 32 bit elements_size | total bytes used by entries (entries have variable length)
+ * --------------------------------
+ * | elementes_size bytes of data | where the elements are stored
+ */
+
+/**
+ * Persistent format of blobs and bignums:
+ * | 32 bit tag |
+ * | 32 bit blob_length |
+ * | 32 bit indirect_offset |
+ */
+
+struct OutStreams {
+ std::ostream& indirect;
+ std::ostream& elements;
+};
+
+OutStreams& serializeParamValue(OutStreams& out, const hidl_vec<uint8_t>& blob) {
+ uint32_t buffer;
+
+ // write blob_length
+ auto blob_length = blob.size();
+ if (blob_length > std::numeric_limits<uint32_t>::max()) {
+ out.elements.setstate(std::ios_base::badbit);
+ return out;
+ }
+ buffer = blob_length;
+ out.elements.write(reinterpret_cast<const char*>(&buffer), sizeof(uint32_t));
+
+ // write indirect_offset
+ auto offset = out.indirect.tellp();
+ if (offset < 0 || offset > std::numeric_limits<uint32_t>::max() ||
+ uint32_t(offset) + uint32_t(blob_length) < uint32_t(offset)) { // overflow check
+ out.elements.setstate(std::ios_base::badbit);
+ return out;
+ }
+ buffer = offset;
+ out.elements.write(reinterpret_cast<const char*>(&buffer), sizeof(uint32_t));
+
+ // write blob to indirect stream
+ if(blob_length)
+ out.indirect.write(reinterpret_cast<const char*>(&blob[0]), blob_length);
+
+ return out;
+}
+
+template <typename T>
+OutStreams& serializeParamValue(OutStreams& out, const T& value) {
+ out.elements.write(reinterpret_cast<const char*>(&value), sizeof(T));
+ return out;
+}
+
+OutStreams& serialize(TAG_INVALID_t&&, OutStreams& out, const KeyParameter&) {
+ // skip invalid entries.
+ return out;
+}
+template <typename T>
+OutStreams& serialize(T ttag, OutStreams& out, const KeyParameter& param) {
+ out.elements.write(reinterpret_cast<const char*>(¶m.tag), sizeof(int32_t));
+ return serializeParamValue(out, accessTagValue(ttag, param));
+}
+
+template <typename... T>
+struct choose_serializer;
+template <typename... Tags>
+struct choose_serializer<MetaList<Tags...>> {
+ static OutStreams& serialize(OutStreams& out, const KeyParameter& param) {
+ return choose_serializer<Tags...>::serialize(out, param);
+ }
+};
+template <>
+struct choose_serializer<> {
+ static OutStreams& serialize(OutStreams& out, const KeyParameter&) {
+ return out;
+ }
+};
+template <TagType tag_type, Tag tag, typename... Tail>
+struct choose_serializer<TypedTag<tag_type, tag>, Tail...> {
+ static OutStreams& serialize(OutStreams& out, const KeyParameter& param) {
+ if (param.tag == tag) {
+ return keystore::serialize(TypedTag<tag_type, tag>(), out, param);
+ } else {
+ return choose_serializer<Tail...>::serialize(out, param);
+ }
+ }
+};
+
+OutStreams& serialize(OutStreams& out, const KeyParameter& param) {
+ return choose_serializer<all_tags_t>::serialize(out, param);
+}
+
+std::ostream& serialize(std::ostream& out, const std::vector<KeyParameter>& params) {
+ std::stringstream indirect;
+ std::stringstream elements;
+ OutStreams streams = { indirect, elements };
+ for (const auto& param: params) {
+ serialize(streams, param);
+ }
+ if (indirect.bad() || elements.bad()) {
+ out.setstate(std::ios_base::badbit);
+ return out;
+ }
+ auto pos = indirect.tellp();
+ if (pos < 0 || pos > std::numeric_limits<uint32_t>::max()) {
+ out.setstate(std::ios_base::badbit);
+ return out;
+ }
+ uint32_t indirect_size = pos;
+ pos = elements.tellp();
+ if (pos < 0 || pos > std::numeric_limits<uint32_t>::max()) {
+ out.setstate(std::ios_base::badbit);
+ return out;
+ }
+ uint32_t elements_size = pos;
+ uint32_t element_count = params.size();
+
+ out.write(reinterpret_cast<const char*>(&indirect_size), sizeof(uint32_t));
+
+ pos = out.tellp();
+ if (indirect_size)
+ out << indirect.rdbuf();
+ assert(out.tellp() - pos == indirect_size);
+
+ out.write(reinterpret_cast<const char*>(&element_count), sizeof(uint32_t));
+ out.write(reinterpret_cast<const char*>(&elements_size), sizeof(uint32_t));
+
+ pos = out.tellp();
+ if (elements_size)
+ out << elements.rdbuf();
+ assert(out.tellp() - pos == elements_size);
+
+ return out;
+}
+
+struct InStreams {
+ std::istream& indirect;
+ std::istream& elements;
+};
+
+InStreams& deserializeParamValue(InStreams& in, hidl_vec<uint8_t>* blob) {
+ uint32_t blob_length = 0;
+ uint32_t offset = 0;
+ in.elements.read(reinterpret_cast<char*>(&blob_length), sizeof(uint32_t));
+ blob->resize(blob_length);
+ in.elements.read(reinterpret_cast<char*>(&offset), sizeof(uint32_t));
+ in.indirect.seekg(offset);
+ in.indirect.read(reinterpret_cast<char*>(&(*blob)[0]), blob->size());
+ return in;
+}
+
+template <typename T>
+InStreams& deserializeParamValue(InStreams& in, T* value) {
+ in.elements.read(reinterpret_cast<char*>(value), sizeof(T));
+ return in;
+}
+
+InStreams& deserialize(TAG_INVALID_t&&, InStreams& in, KeyParameter*) {
+ // there should be no invalid KeyParamaters but if handle them as zero sized.
+ return in;
+}
+
+template <typename T>
+InStreams& deserialize(T&& ttag, InStreams& in, KeyParameter* param) {
+ return deserializeParamValue(in, &accessTagValue(ttag, *param));
+}
+
+template <typename... T>
+struct choose_deserializer;
+template <typename... Tags>
+struct choose_deserializer<MetaList<Tags...>> {
+ static InStreams& deserialize(InStreams& in, KeyParameter* param) {
+ return choose_deserializer<Tags...>::deserialize(in, param);
+ }
+};
+template <>
+struct choose_deserializer<> {
+ static InStreams& deserialize(InStreams& in, KeyParameter*) {
+ // encountered an unknown tag -> fail parsing
+ in.elements.setstate(std::ios_base::badbit);
+ return in;
+ }
+};
+template <TagType tag_type, Tag tag, typename... Tail>
+struct choose_deserializer<TypedTag<tag_type, tag>, Tail...> {
+ static InStreams& deserialize(InStreams& in, KeyParameter* param) {
+ if (param->tag == tag) {
+ return keystore::deserialize(TypedTag<tag_type, tag>(), in, param);
+ } else {
+ return choose_deserializer<Tail...>::deserialize(in, param);
+ }
+ }
+};
+
+InStreams& deserialize(InStreams& in, KeyParameter* param) {
+ in.elements.read(reinterpret_cast<char*>(¶m->tag), sizeof(Tag));
+ return choose_deserializer<all_tags_t>::deserialize(in, param);
+}
+
+std::istream& deserialize(std::istream& in, std::vector<KeyParameter>* params) {
+ uint32_t indirect_size = 0;
+ in.read(reinterpret_cast<char*>(&indirect_size), sizeof(uint32_t));
+ std::string indirect_buffer(indirect_size, '\0');
+ if (indirect_buffer.size() != indirect_size) {
+ in.setstate(std::ios_base::badbit);
+ return in;
+ }
+ in.read(&indirect_buffer[0], indirect_buffer.size());
+
+ uint32_t element_count = 0;
+ in.read(reinterpret_cast<char*>(&element_count), sizeof(uint32_t));
+ uint32_t elements_size = 0;
+ in.read(reinterpret_cast<char*>(&elements_size), sizeof(uint32_t));
+
+ std::string elements_buffer(elements_size, '\0');
+ if(elements_buffer.size() != elements_size) {
+ in.setstate(std::ios_base::badbit);
+ return in;
+ }
+ in.read(&elements_buffer[0], elements_buffer.size());
+
+ if (in.bad()) return in;
+
+ // TODO write one-shot stream buffer to avoid copying here
+ std::stringstream indirect(indirect_buffer);
+ std::stringstream elements(elements_buffer);
+ InStreams streams = { indirect, elements };
+
+ params->resize(element_count);
+
+ for (uint32_t i = 0; i < element_count; ++i) {
+ deserialize(streams, &(*params)[i]);
+ }
+ return in;
+}
+void AuthorizationSet::Serialize(std::ostream* out) const {
+ serialize(*out, data_);
+}
+void AuthorizationSet::Deserialize(std::istream* in) {
+ deserialize(*in, &data_);
+}
+
+} // namespace keystore
diff --git a/keystore/blob.cpp b/keystore/blob.cpp
index 8b08f07..7ee26f7 100644
--- a/keystore/blob.cpp
+++ b/keystore/blob.cpp
@@ -93,12 +93,12 @@
if (isEncrypted()) {
if (state != STATE_NO_ERROR) {
ALOGD("couldn't insert encrypted blob while not unlocked");
- return LOCKED;
+ return ResponseCode::LOCKED;
}
if (!entropy->generate_random_data(mBlob.vector, AES_BLOCK_SIZE)) {
ALOGW("Could not read random data for: %s", filename);
- return SYSTEM_ERROR;
+ return ResponseCode::SYSTEM_ERROR;
}
}
@@ -132,60 +132,60 @@
TEMP_FAILURE_RETRY(open(tmpFileName, O_WRONLY | O_TRUNC | O_CREAT, S_IRUSR | S_IWUSR));
if (out < 0) {
ALOGW("could not open file: %s: %s", tmpFileName, strerror(errno));
- return SYSTEM_ERROR;
+ return ResponseCode::SYSTEM_ERROR;
}
size_t writtenBytes = writeFully(out, (uint8_t*)&mBlob, fileLength);
if (close(out) != 0) {
- return SYSTEM_ERROR;
+ return ResponseCode::SYSTEM_ERROR;
}
if (writtenBytes != fileLength) {
ALOGW("blob not fully written %zu != %zu", writtenBytes, fileLength);
unlink(tmpFileName);
- return SYSTEM_ERROR;
+ return ResponseCode::SYSTEM_ERROR;
}
if (rename(tmpFileName, filename) == -1) {
ALOGW("could not rename blob to %s: %s", filename, strerror(errno));
- return SYSTEM_ERROR;
+ return ResponseCode::SYSTEM_ERROR;
}
- return NO_ERROR;
+ return ResponseCode::NO_ERROR;
}
ResponseCode Blob::readBlob(const char* filename, AES_KEY* aes_key, State state) {
ALOGV("reading blob %s", filename);
int in = TEMP_FAILURE_RETRY(open(filename, O_RDONLY));
if (in < 0) {
- return (errno == ENOENT) ? KEY_NOT_FOUND : SYSTEM_ERROR;
+ return (errno == ENOENT) ? ResponseCode::KEY_NOT_FOUND : ResponseCode::SYSTEM_ERROR;
}
// fileLength may be less than sizeof(mBlob) since the in
// memory version has extra padding to tolerate rounding up to
// the AES_BLOCK_SIZE
size_t fileLength = readFully(in, (uint8_t*)&mBlob, sizeof(mBlob));
if (close(in) != 0) {
- return SYSTEM_ERROR;
+ return ResponseCode::SYSTEM_ERROR;
}
if (fileLength == 0) {
- return VALUE_CORRUPTED;
+ return ResponseCode::VALUE_CORRUPTED;
}
if (isEncrypted() && (state != STATE_NO_ERROR)) {
- return LOCKED;
+ return ResponseCode::LOCKED;
}
size_t headerLength = (mBlob.encrypted - (uint8_t*)&mBlob);
if (fileLength < headerLength) {
- return VALUE_CORRUPTED;
+ return ResponseCode::VALUE_CORRUPTED;
}
ssize_t encryptedLength = fileLength - (headerLength + mBlob.info);
if (encryptedLength < 0) {
- return VALUE_CORRUPTED;
+ return ResponseCode::VALUE_CORRUPTED;
}
ssize_t digestedLength;
if (isEncrypted()) {
if (encryptedLength % AES_BLOCK_SIZE != 0) {
- return VALUE_CORRUPTED;
+ return ResponseCode::VALUE_CORRUPTED;
}
AES_cbc_encrypt(mBlob.encrypted, mBlob.encrypted, encryptedLength, aes_key, mBlob.vector,
@@ -194,7 +194,7 @@
uint8_t computedDigest[MD5_DIGEST_LENGTH];
MD5(mBlob.digested, digestedLength, computedDigest);
if (memcmp(mBlob.digest, computedDigest, MD5_DIGEST_LENGTH) != 0) {
- return VALUE_CORRUPTED;
+ return ResponseCode::VALUE_CORRUPTED;
}
} else {
digestedLength = encryptedLength;
@@ -203,11 +203,11 @@
ssize_t maxValueLength = digestedLength - sizeof(mBlob.length);
mBlob.length = ntohl(mBlob.length);
if (mBlob.length < 0 || mBlob.length > maxValueLength) {
- return VALUE_CORRUPTED;
+ return ResponseCode::VALUE_CORRUPTED;
}
if (mBlob.info != 0) {
// move info from after padding to after data
memmove(&mBlob.value[mBlob.length], &mBlob.value[maxValueLength], mBlob.info);
}
- return ::NO_ERROR;
+ return ResponseCode::NO_ERROR;
}
diff --git a/keystore/defaults.h b/keystore/defaults.h
index 9232dd0..6f7ff2d 100644
--- a/keystore/defaults.h
+++ b/keystore/defaults.h
@@ -24,19 +24,19 @@
*/
/* DSA */
-#define DSA_DEFAULT_KEY_SIZE 1024
-#define DSA_MIN_KEY_SIZE 512
-#define DSA_MAX_KEY_SIZE 8192
+constexpr int32_t DSA_DEFAULT_KEY_SIZE = 1024;
+constexpr int32_t DSA_MIN_KEY_SIZE = 512;
+constexpr int32_t DSA_MAX_KEY_SIZE = 8192;
/* EC */
-#define EC_DEFAULT_KEY_SIZE 256
-#define EC_MIN_KEY_SIZE 192
-#define EC_MAX_KEY_SIZE 521
+constexpr int32_t EC_DEFAULT_KEY_SIZE = 256;
+constexpr int32_t EC_MIN_KEY_SIZE = 192;
+constexpr int32_t EC_MAX_KEY_SIZE = 521;
/* RSA */
-#define RSA_DEFAULT_KEY_SIZE 2048
-#define RSA_DEFAULT_EXPONENT 0x10001
-#define RSA_MIN_KEY_SIZE 512
-#define RSA_MAX_KEY_SIZE 8192
+constexpr int32_t RSA_DEFAULT_KEY_SIZE = 2048;
+constexpr int32_t RSA_DEFAULT_EXPONENT = 0x10001;
+constexpr int32_t RSA_MIN_KEY_SIZE = 512;
+constexpr int32_t RSA_MAX_KEY_SIZE = 8192;
#endif /* KEYSTORE_DEFAULTS_H_ */
diff --git a/keystore/include/keystore/IKeystoreService.h b/keystore/include/keystore/IKeystoreService.h
index 1a2f554..5d88564 100644
--- a/keystore/include/keystore/IKeystoreService.h
+++ b/keystore/include/keystore/IKeystoreService.h
@@ -17,23 +17,25 @@
#ifndef KEYSTORE_IKEYSTORESERVICE_H
#define KEYSTORE_IKEYSTORESERVICE_H
-#include <hardware/keymaster_defs.h>
-#include <utils/RefBase.h>
+#include "keystore.h"
+#include "keystore_return_types.h"
#include <binder/IInterface.h>
#include <binder/Parcel.h>
+#include <keystore/keymaster_tags.h>
+#include <utils/RefBase.h>
#include <vector>
namespace android {
class KeystoreArg : public RefBase {
-public:
- KeystoreArg(const void *data, size_t len);
+ public:
+ KeystoreArg(const void* data, size_t len);
~KeystoreArg();
const void* data() const;
size_t size() const;
-private:
+ private:
const void* mData;
size_t mSize;
};
@@ -42,16 +44,6 @@
void operator()(uint8_t* p) { free(p); }
};
-// struct for serializing/deserializing a list of keymaster_key_param_t's
-struct KeymasterArguments {
- KeymasterArguments();
- ~KeymasterArguments();
- void readFromParcel(const Parcel& in);
- void writeToParcel(Parcel* out) const;
-
- std::vector<keymaster_key_param_t> params;
-};
-
// struct for serializing the results of begin/update/finish
struct OperationResult : public ::android::Parcelable {
OperationResult();
@@ -59,13 +51,12 @@
status_t readFromParcel(const Parcel* in) override;
status_t writeToParcel(Parcel* out) const override;
- int resultCode;
+ ::keystore::KeyStoreServiceReturnCode resultCode;
sp<IBinder> token;
- keymaster_operation_handle_t handle;
+ uint64_t handle;
int inputConsumed;
- std::unique_ptr<uint8_t[], MallocDeleter> data;
- size_t dataLength;
- KeymasterArguments outParams;
+ ::keystore::hidl_vec<uint8_t> data;
+ ::keystore::hidl_vec<::keystore::KeyParameter> outParams;
};
// struct for serializing the results of export
@@ -75,41 +66,15 @@
status_t readFromParcel(const Parcel* in) override;
status_t writeToParcel(Parcel* out) const override;
- int resultCode;
- std::unique_ptr<uint8_t[], MallocDeleter> exportData;
- size_t dataLength;
+ ::keystore::KeyStoreServiceReturnCode resultCode;
+ ::keystore::hidl_vec<uint8_t> exportData;
};
-// struct for serializing keymaster_key_characteristics_t's
-struct KeyCharacteristics : public ::android::Parcelable {
- KeyCharacteristics();
- ~KeyCharacteristics();
- status_t readFromParcel(const Parcel* in) override;
- status_t writeToParcel(Parcel* out) const override;
-
- keymaster_key_characteristics_t characteristics;
-};
-
-// struct for serializing keymaster_cert_chain_t's
-struct KeymasterCertificateChain {
- KeymasterCertificateChain();
- ~KeymasterCertificateChain();
- void readFromParcel(const Parcel& in);
- void writeToParcel(Parcel* out) const;
-
- void FreeChain();
-
- keymaster_cert_chain_t chain;
-};
-
-bool readKeymasterArgumentFromParcel(const Parcel& in, keymaster_key_param_t* out);
-void writeKeymasterArgumentToParcel(const keymaster_key_param_t& param, Parcel* out);
-
/*
* This must be kept manually in sync with frameworks/base's IKeystoreService.java
*/
-class IKeystoreService: public IInterface {
-public:
+class IKeystoreService : public IInterface {
+ public:
enum {
GET_STATE = IBinder::FIRST_CALL_TRANSACTION + 0,
GET = IBinder::FIRST_CALL_TRANSACTION + 1,
@@ -152,114 +117,134 @@
DECLARE_META_INTERFACE(KeystoreService);
- virtual int32_t getState(int32_t userId) = 0;
+ virtual ::keystore::KeyStoreServiceReturnCode getState(int32_t userId) = 0;
- virtual int32_t get(const String16& name, int32_t uid, uint8_t** item, size_t* itemLength) = 0;
+ virtual ::keystore::KeyStoreServiceReturnCode get(const String16& name, int32_t uid,
+ ::keystore::hidl_vec<uint8_t>* item) = 0;
- virtual int32_t insert(const String16& name, const uint8_t* item, size_t itemLength, int uid,
- int32_t flags) = 0;
+ virtual ::keystore::KeyStoreServiceReturnCode insert(const String16& name,
+ const ::keystore::hidl_vec<uint8_t>& item,
+ int uid, int32_t flags) = 0;
- virtual int32_t del(const String16& name, int uid) = 0;
+ virtual ::keystore::KeyStoreServiceReturnCode del(const String16& name, int uid) = 0;
- virtual int32_t exist(const String16& name, int uid) = 0;
+ virtual ::keystore::KeyStoreServiceReturnCode exist(const String16& name, int uid) = 0;
- virtual int32_t list(const String16& prefix, int uid, Vector<String16>* matches) = 0;
+ virtual ::keystore::KeyStoreServiceReturnCode list(const String16& prefix, int uid,
+ Vector<String16>* matches) = 0;
- virtual int32_t reset() = 0;
+ virtual ::keystore::KeyStoreServiceReturnCode reset() = 0;
- virtual int32_t onUserPasswordChanged(int32_t userId, const String16& newPassword) = 0;
+ virtual ::keystore::KeyStoreServiceReturnCode
+ onUserPasswordChanged(int32_t userId, const String16& newPassword) = 0;
- virtual int32_t lock(int32_t userId) = 0;
+ virtual ::keystore::KeyStoreServiceReturnCode lock(int32_t userId) = 0;
- virtual int32_t unlock(int32_t userId, const String16& password) = 0;
+ virtual ::keystore::KeyStoreServiceReturnCode unlock(int32_t userId,
+ const String16& password) = 0;
virtual bool isEmpty(int32_t userId) = 0;
- virtual int32_t generate(const String16& name, int32_t uid, int32_t keyType, int32_t keySize,
- int32_t flags, Vector<sp<KeystoreArg> >* args) = 0;
+ virtual ::keystore::KeyStoreServiceReturnCode generate(const String16& name, int32_t uid,
+ int32_t keyType, int32_t keySize,
+ int32_t flags,
+ Vector<sp<KeystoreArg>>* args) = 0;
- virtual int32_t import(const String16& name, const uint8_t* data, size_t length, int uid,
- int32_t flags) = 0;
+ virtual ::keystore::KeyStoreServiceReturnCode import(const String16& name,
+ const ::keystore::hidl_vec<uint8_t>& data,
+ int uid, int32_t flags) = 0;
- virtual int32_t sign(const String16& name, const uint8_t* data, size_t length, uint8_t** out,
- size_t* outLength) = 0;
+ virtual ::keystore::KeyStoreServiceReturnCode sign(const String16& name,
+ const ::keystore::hidl_vec<uint8_t>& data,
+ ::keystore::hidl_vec<uint8_t>* out) = 0;
- virtual int32_t verify(const String16& name, const uint8_t* data, size_t dataLength,
- const uint8_t* signature, size_t signatureLength) = 0;
+ virtual ::keystore::KeyStoreServiceReturnCode
+ verify(const String16& name, const ::keystore::hidl_vec<uint8_t>& data,
+ const ::keystore::hidl_vec<uint8_t>& signature) = 0;
- virtual int32_t get_pubkey(const String16& name, uint8_t** pubkey, size_t* pubkeyLength) = 0;
+ virtual ::keystore::KeyStoreServiceReturnCode
+ get_pubkey(const String16& name, ::keystore::hidl_vec<uint8_t>* pubKey) = 0;
- virtual int32_t grant(const String16& name, int32_t granteeUid) = 0;
+ virtual ::keystore::KeyStoreServiceReturnCode grant(const String16& name,
+ int32_t granteeUid) = 0;
- virtual int32_t ungrant(const String16& name, int32_t granteeUid) = 0;
+ virtual ::keystore::KeyStoreServiceReturnCode ungrant(const String16& name,
+ int32_t granteeUid) = 0;
virtual int64_t getmtime(const String16& name, int32_t uid) = 0;
- virtual int32_t duplicate(const String16& srcKey, int32_t srcUid, const String16& destKey,
- int32_t destUid) = 0;
+ virtual ::keystore::KeyStoreServiceReturnCode
+ duplicate(const String16& srcKey, int32_t srcUid, const String16& destKey, int32_t destUid) = 0;
virtual int32_t is_hardware_backed(const String16& keyType) = 0;
- virtual int32_t clear_uid(int64_t uid) = 0;
+ virtual ::keystore::KeyStoreServiceReturnCode clear_uid(int64_t uid) = 0;
- virtual int32_t addRngEntropy(const uint8_t* data, size_t dataLength) = 0;
+ virtual ::keystore::KeyStoreServiceReturnCode
+ addRngEntropy(const ::keystore::hidl_vec<uint8_t>& entropy) = 0;
- virtual int32_t generateKey(const String16& name, const KeymasterArguments& params,
- const uint8_t* entropy, size_t entropyLength, int uid, int flags,
- KeyCharacteristics* outCharacteristics) = 0;
+ virtual ::keystore::KeyStoreServiceReturnCode
+ generateKey(const String16& name, const ::keystore::hidl_vec<::keystore::KeyParameter>& params,
+ const ::keystore::hidl_vec<uint8_t>& entropy, int uid, int flags,
+ ::keystore::KeyCharacteristics* outCharacteristics) = 0;
- virtual int32_t getKeyCharacteristics(const String16& name,
- const keymaster_blob_t* clientId,
- const keymaster_blob_t* appData,
- int32_t uid,
- KeyCharacteristics* outCharacteristics) = 0;
+ virtual ::keystore::KeyStoreServiceReturnCode
+ getKeyCharacteristics(const String16& name, const ::keystore::hidl_vec<uint8_t>& clientId,
+ const ::keystore::hidl_vec<uint8_t>& appData, int32_t uid,
+ ::keystore::KeyCharacteristics* outCharacteristics) = 0;
- virtual int32_t importKey(const String16& name, const KeymasterArguments& params,
- keymaster_key_format_t format, const uint8_t *keyData,
- size_t keyLength, int uid, int flags,
- KeyCharacteristics* outCharacteristics) = 0;
+ virtual ::keystore::KeyStoreServiceReturnCode
+ importKey(const String16& name, const ::keystore::hidl_vec<::keystore::KeyParameter>& params,
+ ::keystore::KeyFormat format, const ::keystore::hidl_vec<uint8_t>& key, int uid,
+ int flags, ::keystore::KeyCharacteristics* outCharacteristics) = 0;
- virtual void exportKey(const String16& name, keymaster_key_format_t format,
- const keymaster_blob_t* clientId,
- const keymaster_blob_t* appData, int32_t uid, ExportResult* result) = 0;
+ virtual void exportKey(const String16& name, ::keystore::KeyFormat format,
+ const ::keystore::hidl_vec<uint8_t>& clientId,
+ const ::keystore::hidl_vec<uint8_t>& appData, int uid,
+ ExportResult* result) = 0;
virtual void begin(const sp<IBinder>& apptoken, const String16& name,
- keymaster_purpose_t purpose, bool pruneable,
- const KeymasterArguments& params, const uint8_t* entropy,
- size_t entropyLength, int32_t uid, OperationResult* result) = 0;
+ ::keystore::KeyPurpose purpose, bool pruneable,
+ const ::keystore::hidl_vec<::keystore::KeyParameter>& params,
+ const ::keystore::hidl_vec<uint8_t>& entropy, int32_t uid,
+ OperationResult* opResult) = 0;
- virtual void update(const sp<IBinder>& token, const KeymasterArguments& params,
- const uint8_t* data, size_t dataLength, OperationResult* result) = 0;
+ virtual void update(const sp<IBinder>& token,
+ const ::keystore::hidl_vec<::keystore::KeyParameter>& params,
+ const ::keystore::hidl_vec<uint8_t>& data, OperationResult* opResult) = 0;
- virtual void finish(const sp<IBinder>& token, const KeymasterArguments& params,
- const uint8_t* signature, size_t signatureLength,
- const uint8_t* entropy, size_t entropyLength,
- OperationResult* result) = 0;
+ virtual void finish(const sp<IBinder>& token,
+ const ::keystore::hidl_vec<::keystore::KeyParameter>& params,
+ const ::keystore::hidl_vec<uint8_t>& signature,
+ const ::keystore::hidl_vec<uint8_t>& entropy,
+ OperationResult* opResult) = 0;
- virtual int32_t abort(const sp<IBinder>& handle) = 0;
+ virtual ::keystore::KeyStoreServiceReturnCode abort(const sp<IBinder>& handle) = 0;
virtual bool isOperationAuthorized(const sp<IBinder>& handle) = 0;
- virtual int32_t addAuthToken(const uint8_t* token, size_t length) = 0;
+ virtual ::keystore::KeyStoreServiceReturnCode addAuthToken(const uint8_t* token,
+ size_t length) = 0;
- virtual int32_t onUserAdded(int32_t userId, int32_t parentId) = 0;
+ virtual ::keystore::KeyStoreServiceReturnCode onUserAdded(int32_t userId, int32_t parentId) = 0;
- virtual int32_t onUserRemoved(int32_t userId) = 0;
+ virtual ::keystore::KeyStoreServiceReturnCode onUserRemoved(int32_t userId) = 0;
- virtual int32_t attestKey(const String16& name, const KeymasterArguments& params,
- KeymasterCertificateChain* outChain) = 0;
+ virtual ::keystore::KeyStoreServiceReturnCode
+ attestKey(const String16& name, const ::keystore::hidl_vec<::keystore::KeyParameter>& params,
+ ::keystore::hidl_vec<::keystore::hidl_vec<uint8_t>>* outChain) = 0;
- virtual int32_t onDeviceOffBody() = 0;
+ virtual ::keystore::KeyStoreServiceReturnCode onDeviceOffBody() = 0;
};
// ----------------------------------------------------------------------------
-class BnKeystoreService: public BnInterface<IKeystoreService> {
-public:
+class BnKeystoreService : public BnInterface<IKeystoreService> {
+ public:
virtual status_t onTransact(uint32_t code, const Parcel& data, Parcel* reply,
- uint32_t flags = 0);
+ uint32_t flags = 0);
};
-} // namespace android
+} // namespace android
#endif
diff --git a/keystore/include/keystore/authorization_set.h b/keystore/include/keystore/authorization_set.h
new file mode 100644
index 0000000..0e57a19
--- /dev/null
+++ b/keystore/include/keystore/authorization_set.h
@@ -0,0 +1,336 @@
+/*
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef SYSTEM_SECURITY_KEYSTORE_AUTHORIZATION_SET_H_
+#define SYSTEM_SECURITY_KEYSTORE_AUTHORIZATION_SET_H_
+
+#include "keymaster_tags.h"
+#include <vector>
+
+namespace keystore {
+
+class AuthorizationSetBuilder;
+
+/**
+ * An ordered collection of KeyParameters. It provides memory ownership and some convenient
+ * functionality for sorting, deduplicating, joining, and subtracting sets of KeyParameters.
+ * For serialization, wrap the backing store of this structure in a hidl_vec<KeyParameter>.
+ */
+class AuthorizationSet {
+ public:
+ /**
+ * Construct an empty, dynamically-allocated, growable AuthorizationSet.
+ */
+ AuthorizationSet() {};
+
+ // Copy constructor.
+ AuthorizationSet(const AuthorizationSet& other) : data_(other.data_) {}
+
+ // Move constructor.
+ AuthorizationSet(AuthorizationSet&& other) : data_(std::move(other.data_)) {}
+
+ // Constructor from hidl_vec<KeyParameter>
+ AuthorizationSet(const hidl_vec<KeyParameter>& other) {
+ *this = other;
+ }
+
+ // Copy assignment.
+ AuthorizationSet& operator=(const AuthorizationSet& other) {
+ data_ = other.data_;
+ return *this;
+ }
+
+ // Move assignment.
+ AuthorizationSet& operator=(AuthorizationSet&& other) {
+ data_ = std::move(other.data_);
+ return *this;
+ }
+
+ AuthorizationSet& operator=(const hidl_vec<KeyParameter>& other) {
+ if (other.size() > 0) {
+ data_.resize(other.size());
+ for (size_t i = 0; i < data_.size(); ++i) {
+ /* This makes a deep copy even of embedded blobs.
+ * See assignment operator/copy constructor of hidl_vec.*/
+ data_[i] = other[i];
+ }
+ }
+ return *this;
+ }
+
+ /**
+ * Clear existing authorization set data
+ */
+ void Clear();
+
+ ~AuthorizationSet() = default;
+
+ /**
+ * Returns the size of the set.
+ */
+ size_t size() const { return data_.size(); }
+
+ /**
+ * Returns true if the set is empty.
+ */
+ bool empty() const { return size() == 0; }
+
+ /**
+ * Returns the data in the set, directly. Be careful with this.
+ */
+ const KeyParameter* data() const { return data_.data(); }
+
+ /**
+ * Sorts the set
+ */
+ void Sort();
+
+ /**
+ * Sorts the set and removes duplicates (inadvertently duplicating tags is easy to do with the
+ * AuthorizationSetBuilder).
+ */
+ void Deduplicate();
+
+ /**
+ * Adds all elements from \p set that are not already present in this AuthorizationSet. As a
+ * side-effect, if \p set is not null this AuthorizationSet will end up sorted.
+ */
+ void Union(const AuthorizationSet& set);
+
+ /**
+ * Removes all elements in \p set from this AuthorizationSet.
+ */
+ void Subtract(const AuthorizationSet& set);
+
+ /**
+ * Returns the offset of the next entry that matches \p tag, starting from the element after \p
+ * begin. If not found, returns -1.
+ */
+ int find(Tag tag, int begin = -1) const;
+
+ /**
+ * Removes the entry at the specified index. Returns true if successful, false if the index was
+ * out of bounds.
+ */
+ bool erase(int index);
+
+ /**
+ * Returns iterator (pointer) to beginning of elems array, to enable STL-style iteration
+ */
+ std::vector<KeyParameter>::const_iterator begin() const { return data_.begin(); }
+
+ /**
+ * Returns iterator (pointer) one past end of elems array, to enable STL-style iteration
+ */
+ std::vector<KeyParameter>::const_iterator end() const { return data_.end(); }
+
+ /**
+ * Returns the nth element of the set.
+ * Like for std::vector::operator[] there is no range check performed. Use of out of range
+ * indices is undefined.
+ */
+ KeyParameter& operator[](int n);
+
+ /**
+ * Returns the nth element of the set.
+ * Like for std::vector::operator[] there is no range check performed. Use of out of range
+ * indices is undefined.
+ */
+ const KeyParameter& operator[](int n) const;
+
+ /**
+ * Returns true if the set contains at least one instance of \p tag
+ */
+ bool Contains(Tag tag) const {
+ return find(tag) != -1;
+ }
+
+ template <TagType tag_type, Tag tag, typename ValueT>
+ bool Contains(TypedTag<tag_type, tag> ttag, const ValueT& value) const {
+ for (const auto& param: data_) {
+ auto entry = authorizationValue(ttag, param);
+ if (entry.isOk() && entry.value() == value) return true;
+ }
+ return false;
+ }
+ /**
+ * Returns the number of \p tag entries.
+ */
+ size_t GetTagCount(Tag tag) const;
+
+ template <typename T>
+ inline NullOr<const typename TypedTag2ValueType<T>::type&> GetTagValue(T tag) const {
+ auto entry = GetEntry(tag);
+ if (entry.isOk()) return authorizationValue(tag, entry.value());
+ return {};
+ }
+
+ void push_back(const KeyParameter& param) {
+ data_.push_back(param);
+ }
+ void push_back(KeyParameter&& param) {
+ data_.push_back(std::move(param));
+ }
+
+ /**
+ * Append the tag and enumerated value to the set.
+ * "val" may be exactly one parameter unless a boolean parameter is added.
+ * In this case "val" is omitted. This condition is checked at compile time by Authorization()
+ */
+ template <typename TypedTagT, typename... Value>
+ void push_back(TypedTagT tag, Value&&... val) {
+ push_back(Authorization(tag, std::forward<Value>(val)...));
+ }
+
+ template <typename Iterator>
+ void append(Iterator begin, Iterator end) {
+ while (begin != end) {
+ push_back(*begin);
+ ++begin;
+ }
+ }
+
+ hidl_vec<KeyParameter> hidl_data() const {
+ hidl_vec<KeyParameter> result;
+ result.setToExternal(const_cast<KeyParameter*>(data()), size());
+ return result;
+ }
+
+ void Serialize(std::ostream* out) const;
+ void Deserialize(std::istream* in);
+
+ private:
+ NullOr<const KeyParameter&> GetEntry(Tag tag) const;
+
+ std::vector<KeyParameter> data_;
+};
+
+class AuthorizationSetBuilder: public AuthorizationSet {
+ public:
+ template <typename TagType, typename... ValueType>
+ AuthorizationSetBuilder& Authorization(TagType ttag, ValueType&&... value) {
+ push_back(ttag, std::forward<ValueType>(value)...);
+ return *this;
+ }
+
+ template <Tag tag>
+ AuthorizationSetBuilder& Authorization(TypedTag<TagType::BYTES, tag> ttag, const uint8_t* data,
+ size_t data_length) {
+ hidl_vec<uint8_t> new_blob;
+ new_blob.setToExternal(const_cast<uint8_t*>(data), data_length);
+ push_back(ttag, std::move(new_blob));
+ return *this;
+ }
+
+ template <Tag tag>
+ AuthorizationSetBuilder& Authorization(TypedTag<TagType::BYTES, tag> ttag, const char* data,
+ size_t data_length) {
+ return Authorization(ttag, reinterpret_cast<const uint8_t*>(data), data_length);
+ }
+
+ AuthorizationSetBuilder& RsaKey(uint32_t key_size, uint64_t public_exponent);
+ AuthorizationSetBuilder& EcdsaKey(uint32_t key_size);
+ AuthorizationSetBuilder& AesKey(uint32_t key_size);
+ AuthorizationSetBuilder& HmacKey(uint32_t key_size);
+
+ AuthorizationSetBuilder& RsaSigningKey(uint32_t key_size, uint64_t public_exponent);
+ AuthorizationSetBuilder& RsaEncryptionKey(uint32_t key_size, uint64_t public_exponent);
+ AuthorizationSetBuilder& EcdsaSigningKey(uint32_t key_size);
+ AuthorizationSetBuilder& AesEncryptionKey(uint32_t key_size);
+
+ AuthorizationSetBuilder& SigningKey();
+ AuthorizationSetBuilder& EncryptionKey();
+ AuthorizationSetBuilder& NoDigestOrPadding();
+ AuthorizationSetBuilder& EcbMode();
+
+ AuthorizationSetBuilder& Digest(Digest digest) {
+ return Authorization(TAG_DIGEST, digest);
+ }
+
+ AuthorizationSetBuilder& Padding(PaddingMode padding) {
+ return Authorization(TAG_PADDING, padding);
+ }
+};
+
+inline AuthorizationSetBuilder& AuthorizationSetBuilder::RsaKey(uint32_t key_size,
+ uint64_t public_exponent) {
+ Authorization(TAG_ALGORITHM, Algorithm::RSA);
+ Authorization(TAG_KEY_SIZE, key_size);
+ Authorization(TAG_RSA_PUBLIC_EXPONENT, public_exponent);
+ return *this;
+}
+
+inline AuthorizationSetBuilder& AuthorizationSetBuilder::EcdsaKey(uint32_t key_size) {
+ Authorization(TAG_ALGORITHM, Algorithm::EC);
+ Authorization(TAG_KEY_SIZE, key_size);
+ return *this;
+}
+
+inline AuthorizationSetBuilder& AuthorizationSetBuilder::AesKey(uint32_t key_size) {
+ Authorization(TAG_ALGORITHM, Algorithm::AES);
+ return Authorization(TAG_KEY_SIZE, key_size);
+}
+
+inline AuthorizationSetBuilder& AuthorizationSetBuilder::HmacKey(uint32_t key_size) {
+ Authorization(TAG_ALGORITHM, Algorithm::HMAC);
+ Authorization(TAG_KEY_SIZE, key_size);
+ return SigningKey();
+}
+
+inline AuthorizationSetBuilder& AuthorizationSetBuilder::RsaSigningKey(uint32_t key_size,
+ uint64_t public_exponent) {
+ RsaKey(key_size, public_exponent);
+ return SigningKey();
+}
+
+inline AuthorizationSetBuilder&
+AuthorizationSetBuilder::RsaEncryptionKey(uint32_t key_size, uint64_t public_exponent) {
+ RsaKey(key_size, public_exponent);
+ return EncryptionKey();
+}
+
+inline AuthorizationSetBuilder& AuthorizationSetBuilder::EcdsaSigningKey(uint32_t key_size) {
+ EcdsaKey(key_size);
+ return SigningKey();
+}
+
+inline AuthorizationSetBuilder& AuthorizationSetBuilder::AesEncryptionKey(uint32_t key_size) {
+ AesKey(key_size);
+ return EncryptionKey();
+}
+
+inline AuthorizationSetBuilder& AuthorizationSetBuilder::SigningKey() {
+ Authorization(TAG_PURPOSE, KeyPurpose::SIGN);
+ return Authorization(TAG_PURPOSE, KeyPurpose::VERIFY);
+}
+
+inline AuthorizationSetBuilder& AuthorizationSetBuilder::EncryptionKey() {
+ Authorization(TAG_PURPOSE, KeyPurpose::ENCRYPT);
+ return Authorization(TAG_PURPOSE, KeyPurpose::DECRYPT);
+}
+
+inline AuthorizationSetBuilder& AuthorizationSetBuilder::NoDigestOrPadding() {
+ Authorization(TAG_DIGEST, Digest::NONE);
+ return Authorization(TAG_PADDING, PaddingMode::NONE);
+}
+
+inline AuthorizationSetBuilder& AuthorizationSetBuilder::EcbMode() {
+ return Authorization(TAG_BLOCK_MODE, BlockMode::ECB);
+}
+
+} // namespace keystore
+
+#endif // SYSTEM_SECURITY_KEYSTORE_AUTHORIZATION_SET_H_
diff --git a/keystore/include/keystore/keymaster_tags.h b/keystore/include/keystore/keymaster_tags.h
new file mode 100644
index 0000000..b347dbf
--- /dev/null
+++ b/keystore/include/keystore/keymaster_tags.h
@@ -0,0 +1,352 @@
+/*
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef SYSTEM_SECURITY_KEYSTORE_KEYMASTER_TAGS_H_
+#define SYSTEM_SECURITY_KEYSTORE_KEYMASTER_TAGS_H_
+
+/**
+ * This header contains various definitions that make working with keymaster tags safer and easier.
+ *
+ * It makes use of a fair amount of template metaprogramming. The metaprogramming serves the purpose
+ * of making it impossible to make certain classes of mistakes when operating on keymaster
+ * authorizations. For example, it's an error to create a KeyParameter with tag == Tag::PURPOSE
+ * and then to assign Algorithm::RSA to algorithm element of its union. But because the user
+ * must choose the union field, there could be a mismatch which the compiler has now way to
+ * diagnose.
+ *
+ * The machinery in this header solves these problems by describing which union field corresponds
+ * to which Tag. Central to this mechanism is the template TypedTag. It has zero size and binds a
+ * numeric Tag to a type that the compiler understands. By means of the macro DECLARE_TYPED_TAG,
+ * we declare types for each of the tags defined in hardware/interfaces/keymaster/2.0/types.hal.
+ *
+ * The macro DECLARE_TYPED_TAG(name) generates a typename TAG_name_t and a zero sized instance
+ * TAG_name. Once these typed tags have been declared we define metafunctions mapping the each tag
+ * to its value c++ type and the correct union element of KeyParameter. This is done by means of
+ * the macros MAKE_TAG_*VALUE_ACCESSOR, which generates TypedTag2ValueType, a metafunction mapping
+ * a typed tag to the corresponding c++ type, and access function, accessTagValue returning a
+ * reference to the correct element of KeyParameter.
+ * E.g.:
+ * given "KeyParameter param;" then "accessTagValue(TAG_PURPOSE, param)"
+ * yields a reference to param.f.purpose
+ * If used in an assignment the compiler can now check the compatibility of the assigned value.
+ *
+ * For convenience we also provide the constructor like function Authorization().
+ * Authorization takes a typed tag and a value and checks at compile time whether the value given
+ * is suitable for the given tag. At runtime it creates a new KeyParameter initialized with the
+ * given tag and value and returns it by value.
+ *
+ * The second convenience function, authorizationValue, allows access to the KeyParameter value in
+ * a safe way. It takes a typed tag and a KeyParameter and returns a reference to the value wrapped
+ * by NullOr. NullOr has out-of-band information about whether it is save to access the wrapped
+ * reference.
+ * E.g.:
+ * auto param = Authorization(TAG_ALGORITM, Algorithm::RSA);
+ * auto value1 = authorizationValue(TAG_PURPOSE, param);
+ * auto value2 = authorizationValue(TAG_ALGORITM, param);
+ * value1.isOk() yields false, but value2.isOk() yields true, thus value2.value() is save to access.
+ */
+
+#include <android/hardware/keymaster/3.0/IHwKeymasterDevice.h>
+#include <hardware/hw_auth_token.h>
+#include <type_traits>
+
+namespace keystore {
+
+using ::android::hardware::keymaster::V3_0::Algorithm;
+using ::android::hardware::keymaster::V3_0::BlockMode;
+using ::android::hardware::keymaster::V3_0::Digest;
+using ::android::hardware::keymaster::V3_0::EcCurve;
+using ::android::hardware::keymaster::V3_0::ErrorCode;
+using ::android::hardware::keymaster::V3_0::HardwareAuthToken;
+using ::android::hardware::keymaster::V3_0::HardwareAuthenticatorType;
+using ::android::hardware::keymaster::V3_0::IKeymasterDevice;
+using ::android::hardware::keymaster::V3_0::KeyBlobUsageRequirements;
+using ::android::hardware::keymaster::V3_0::KeyCharacteristics;
+using ::android::hardware::keymaster::V3_0::KeyDerivationFunction;
+using ::android::hardware::keymaster::V3_0::KeyFormat;
+using ::android::hardware::keymaster::V3_0::KeyOrigin;
+using ::android::hardware::keymaster::V3_0::KeyParameter;
+using ::android::hardware::keymaster::V3_0::KeyPurpose;
+using ::android::hardware::keymaster::V3_0::PaddingMode;
+using ::android::hardware::keymaster::V3_0::Tag;
+using ::android::hardware::keymaster::V3_0::TagType;
+
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+using ::android::hardware::Status;
+
+// The following create the numeric values that KM_TAG_PADDING and KM_TAG_DIGEST used to have. We
+// need these old values to be able to support old keys that use them.
+static const int32_t KM_TAG_DIGEST_OLD = static_cast<int32_t>(TagType::ENUM) | 5;
+static const int32_t KM_TAG_PADDING_OLD = static_cast<int32_t>(TagType::ENUM) | 7;
+
+constexpr TagType typeFromTag(Tag tag) {
+ return static_cast<TagType>(static_cast<uint32_t>(tag) & static_cast<uint32_t>(0xf0000000));
+}
+
+/**
+ * TypedTag is a templatized version of Tag, which provides compile-time checking of
+ * keymaster tag types. Instances are convertible to Tag, so they can be used wherever
+ * Tag is expected, and because they encode the tag type it's possible to create
+ * function overloads that only operate on tags with a particular type.
+ */
+template <TagType tag_type, Tag tag> struct TypedTag {
+ inline TypedTag() {
+ // Ensure that it's impossible to create a TypedTag instance whose 'tag' doesn't have type
+ // 'tag_type'. Attempting to instantiate a tag with the wrong type will result in a compile
+ // error (no match for template specialization StaticAssert<false>), with no run-time cost.
+ static_assert(typeFromTag(tag) == tag_type, "mismatch between tag and tag_type");
+ }
+ operator Tag() const { return tag; }
+};
+
+template <Tag tag> struct Tag2TypedTag { typedef TypedTag<typeFromTag(tag), tag> type; };
+
+template <Tag tag> struct Tag2String;
+
+#define _TAGS_STRINGIFY(x) #x
+#define TAGS_STRINGIFY(x) _TAGS_STRINGIFY(x)
+
+#define DECLARE_TYPED_TAG(name) \
+ typedef typename Tag2TypedTag<Tag::name>::type TAG_##name##_t; \
+ extern TAG_##name##_t TAG_##name; \
+ template <> struct Tag2String<Tag::name> { \
+ static const char* value() { return "Tag::" TAGS_STRINGIFY(name); } \
+ }
+
+DECLARE_TYPED_TAG(INVALID);
+DECLARE_TYPED_TAG(KEY_SIZE);
+DECLARE_TYPED_TAG(MAC_LENGTH);
+DECLARE_TYPED_TAG(CALLER_NONCE);
+DECLARE_TYPED_TAG(MIN_MAC_LENGTH);
+DECLARE_TYPED_TAG(RSA_PUBLIC_EXPONENT);
+DECLARE_TYPED_TAG(ECIES_SINGLE_HASH_MODE);
+DECLARE_TYPED_TAG(INCLUDE_UNIQUE_ID);
+DECLARE_TYPED_TAG(ACTIVE_DATETIME);
+DECLARE_TYPED_TAG(ORIGINATION_EXPIRE_DATETIME);
+DECLARE_TYPED_TAG(USAGE_EXPIRE_DATETIME);
+DECLARE_TYPED_TAG(MIN_SECONDS_BETWEEN_OPS);
+DECLARE_TYPED_TAG(MAX_USES_PER_BOOT);
+DECLARE_TYPED_TAG(ALL_USERS);
+DECLARE_TYPED_TAG(USER_ID);
+DECLARE_TYPED_TAG(USER_SECURE_ID);
+DECLARE_TYPED_TAG(NO_AUTH_REQUIRED);
+DECLARE_TYPED_TAG(AUTH_TIMEOUT);
+DECLARE_TYPED_TAG(ALLOW_WHILE_ON_BODY);
+DECLARE_TYPED_TAG(ALL_APPLICATIONS);
+DECLARE_TYPED_TAG(APPLICATION_ID);
+DECLARE_TYPED_TAG(APPLICATION_DATA);
+DECLARE_TYPED_TAG(CREATION_DATETIME);
+DECLARE_TYPED_TAG(ROLLBACK_RESISTANT);
+DECLARE_TYPED_TAG(ROOT_OF_TRUST);
+DECLARE_TYPED_TAG(ASSOCIATED_DATA);
+DECLARE_TYPED_TAG(NONCE);
+DECLARE_TYPED_TAG(AUTH_TOKEN);
+DECLARE_TYPED_TAG(BOOTLOADER_ONLY);
+DECLARE_TYPED_TAG(OS_VERSION);
+DECLARE_TYPED_TAG(OS_PATCHLEVEL);
+DECLARE_TYPED_TAG(UNIQUE_ID);
+DECLARE_TYPED_TAG(ATTESTATION_CHALLENGE);
+DECLARE_TYPED_TAG(ATTESTATION_APPLICATION_ID);
+DECLARE_TYPED_TAG(RESET_SINCE_ID_ROTATION);
+
+DECLARE_TYPED_TAG(PURPOSE);
+DECLARE_TYPED_TAG(ALGORITHM);
+DECLARE_TYPED_TAG(BLOCK_MODE);
+DECLARE_TYPED_TAG(DIGEST);
+DECLARE_TYPED_TAG(PADDING);
+DECLARE_TYPED_TAG(BLOB_USAGE_REQUIREMENTS);
+DECLARE_TYPED_TAG(ORIGIN);
+DECLARE_TYPED_TAG(USER_AUTH_TYPE);
+DECLARE_TYPED_TAG(KDF);
+DECLARE_TYPED_TAG(EC_CURVE);
+
+template <typename... Elems> struct MetaList {};
+
+using all_tags_t = MetaList<
+ TAG_INVALID_t, TAG_KEY_SIZE_t, TAG_MAC_LENGTH_t, TAG_CALLER_NONCE_t, TAG_MIN_MAC_LENGTH_t,
+ TAG_RSA_PUBLIC_EXPONENT_t, TAG_ECIES_SINGLE_HASH_MODE_t, TAG_INCLUDE_UNIQUE_ID_t,
+ TAG_ACTIVE_DATETIME_t, TAG_ORIGINATION_EXPIRE_DATETIME_t, TAG_USAGE_EXPIRE_DATETIME_t,
+ TAG_MIN_SECONDS_BETWEEN_OPS_t, TAG_MAX_USES_PER_BOOT_t, TAG_ALL_USERS_t, TAG_USER_ID_t,
+ TAG_USER_SECURE_ID_t, TAG_NO_AUTH_REQUIRED_t, TAG_AUTH_TIMEOUT_t, TAG_ALLOW_WHILE_ON_BODY_t,
+ TAG_ALL_APPLICATIONS_t, TAG_APPLICATION_ID_t, TAG_APPLICATION_DATA_t, TAG_CREATION_DATETIME_t,
+ TAG_ROLLBACK_RESISTANT_t, TAG_ROOT_OF_TRUST_t, TAG_ASSOCIATED_DATA_t, TAG_NONCE_t,
+ TAG_AUTH_TOKEN_t, TAG_BOOTLOADER_ONLY_t, TAG_OS_VERSION_t, TAG_OS_PATCHLEVEL_t, TAG_UNIQUE_ID_t,
+ TAG_ATTESTATION_CHALLENGE_t, TAG_ATTESTATION_APPLICATION_ID_t, TAG_RESET_SINCE_ID_ROTATION_t,
+ TAG_PURPOSE_t, TAG_ALGORITHM_t, TAG_BLOCK_MODE_t, TAG_DIGEST_t, TAG_PADDING_t,
+ TAG_BLOB_USAGE_REQUIREMENTS_t, TAG_ORIGIN_t, TAG_USER_AUTH_TYPE_t, TAG_KDF_t, TAG_EC_CURVE_t>;
+
+/* implementation in keystore_utils.cpp */
+extern const char* stringifyTag(Tag tag);
+
+template <typename TypedTagType> struct TypedTag2ValueType;
+
+#define MAKE_TAG_VALUE_ACCESSOR(tag_type, field_name) \
+ template <Tag tag> struct TypedTag2ValueType<TypedTag<tag_type, tag>> { \
+ typedef decltype(static_cast<KeyParameter*>(nullptr)->field_name) type; \
+ }; \
+ template <Tag tag> \
+ inline auto accessTagValue(TypedTag<tag_type, tag>, const KeyParameter& param) \
+ ->const decltype(param.field_name)& { \
+ return param.field_name; \
+ } \
+ template <Tag tag> \
+ inline auto accessTagValue(TypedTag<tag_type, tag>, KeyParameter& param) \
+ ->decltype(param.field_name)& { \
+ return param.field_name; \
+ }
+
+MAKE_TAG_VALUE_ACCESSOR(TagType::ULONG, f.longInteger)
+MAKE_TAG_VALUE_ACCESSOR(TagType::ULONG_REP, f.longInteger)
+MAKE_TAG_VALUE_ACCESSOR(TagType::DATE, f.dateTime)
+MAKE_TAG_VALUE_ACCESSOR(TagType::UINT, f.integer)
+MAKE_TAG_VALUE_ACCESSOR(TagType::UINT_REP, f.integer)
+MAKE_TAG_VALUE_ACCESSOR(TagType::BOOL, f.boolValue)
+MAKE_TAG_VALUE_ACCESSOR(TagType::BYTES, blob)
+MAKE_TAG_VALUE_ACCESSOR(TagType::BIGNUM, blob)
+
+#define MAKE_TAG_ENUM_VALUE_ACCESSOR(typed_tag, field_name) \
+ template <> struct TypedTag2ValueType<decltype(typed_tag)> { \
+ typedef decltype(static_cast<KeyParameter*>(nullptr)->field_name) type; \
+ }; \
+ inline auto accessTagValue(decltype(typed_tag), const KeyParameter& param) \
+ ->const decltype(param.field_name)& { \
+ return param.field_name; \
+ } \
+ inline auto accessTagValue(decltype(typed_tag), KeyParameter& param) \
+ ->decltype(param.field_name)& { \
+ return param.field_name; \
+ }
+
+MAKE_TAG_ENUM_VALUE_ACCESSOR(TAG_ALGORITHM, f.algorithm)
+MAKE_TAG_ENUM_VALUE_ACCESSOR(TAG_BLOB_USAGE_REQUIREMENTS, f.keyBlobUsageRequirements)
+MAKE_TAG_ENUM_VALUE_ACCESSOR(TAG_BLOCK_MODE, f.blockMode)
+MAKE_TAG_ENUM_VALUE_ACCESSOR(TAG_DIGEST, f.digest)
+MAKE_TAG_ENUM_VALUE_ACCESSOR(TAG_EC_CURVE, f.ecCurve)
+MAKE_TAG_ENUM_VALUE_ACCESSOR(TAG_KDF, f.keyDerivationFunction)
+MAKE_TAG_ENUM_VALUE_ACCESSOR(TAG_ORIGIN, f.origin)
+MAKE_TAG_ENUM_VALUE_ACCESSOR(TAG_PADDING, f.paddingMode)
+MAKE_TAG_ENUM_VALUE_ACCESSOR(TAG_PURPOSE, f.purpose)
+MAKE_TAG_ENUM_VALUE_ACCESSOR(TAG_USER_AUTH_TYPE, f.hardwareAuthenticatorType)
+
+template <TagType tag_type, Tag tag, typename ValueT>
+inline KeyParameter makeKeyParameter(TypedTag<tag_type, tag> ttag, ValueT&& value) {
+ KeyParameter param;
+ param.tag = tag;
+ param.f.longInteger = 0;
+ accessTagValue(ttag, param) = std::forward<ValueT>(value);
+ return param;
+}
+
+// the boolean case
+template <Tag tag> inline KeyParameter makeKeyParameter(TypedTag<TagType::BOOL, tag>) {
+ KeyParameter param;
+ param.tag = tag;
+ param.f.boolValue = true;
+ return param;
+}
+
+template <typename... Pack> struct FirstOrNoneHelper;
+template <typename First> struct FirstOrNoneHelper<First> { typedef First type; };
+template <> struct FirstOrNoneHelper<> {
+ struct type {};
+};
+
+template <typename... Pack> using FirstOrNone = typename FirstOrNoneHelper<Pack...>::type;
+
+template <TagType tag_type, Tag tag, typename... Args>
+inline KeyParameter Authorization(TypedTag<tag_type, tag> ttag, Args&&... args) {
+ static_assert(tag_type != TagType::BOOL || (sizeof...(args) == 0),
+ "TagType::BOOL Authorizations do not take parameters. Presence is truth.");
+ static_assert(tag_type == TagType::BOOL || (sizeof...(args) == 1),
+ "Authorization other then TagType::BOOL take exactly one parameter.");
+ static_assert(
+ tag_type == TagType::BOOL ||
+ std::is_convertible<std::remove_cv_t<std::remove_reference_t<FirstOrNone<Args...>>>,
+ typename TypedTag2ValueType<TypedTag<tag_type, tag>>::type>::value,
+ "Invalid argument type for given tag.");
+
+ return makeKeyParameter(ttag, std::forward<Args>(args)...);
+}
+
+/**
+ * This class wraps a (mostly return) value and stores whether or not the wrapped value is valid out
+ * of band. Note that if the wrapped value is a reference it is unsafe to access the value if
+ * !isOk(). If the wrapped type is a pointer or value and !isOk(), it is still safe to access the
+ * wrapped value. In this case the pointer will be NULL though, and the value will be default
+ * constructed.
+ */
+template <typename ValueT> class NullOr {
+ template <typename T> struct reference_initializer {
+ static T&& init() { return *static_cast<std::remove_reference_t<T>*>(nullptr); }
+ };
+ template <typename T> struct pointer_initializer {
+ static T init() { return nullptr; }
+ };
+ template <typename T> struct value_initializer {
+ static T init() { return T(); }
+ };
+ template <typename T>
+ using initializer_t =
+ std::conditional_t<std::is_lvalue_reference<T>::value, reference_initializer<T>,
+ std::conditional_t<std::is_pointer<T>::value, pointer_initializer<T>,
+ value_initializer<T>>>;
+
+ public:
+ NullOr() : value_(initializer_t<ValueT>::init()), null_(true) {}
+ NullOr(ValueT&& value) : value_(std::forward<ValueT>(value)), null_(false) {}
+
+ bool isOk() const { return !null_; }
+
+ const ValueT& value() const & { return value_; }
+ ValueT& value() & { return value_; }
+ ValueT&& value() && { return std::move(value_); }
+
+ private:
+ ValueT value_;
+ bool null_;
+};
+
+template <typename T> std::remove_reference_t<T> NullOrOr(T&& v) {
+ if (v.isOk()) return v;
+ return {};
+}
+
+template <typename Head, typename... Tail>
+std::remove_reference_t<Head> NullOrOr(Head&& head, Tail&&... tail) {
+ if (head.isOk()) return head;
+ return NullOrOr(std::forward<Tail>(tail)...);
+}
+
+template <typename Default, typename Wrapped>
+std::remove_reference_t<Wrapped> defaultOr(NullOr<Wrapped>&& optional, Default&& def) {
+ static_assert(std::is_convertible<std::remove_reference_t<Default>,
+ std::remove_reference_t<Wrapped>>::value,
+ "Type of default value must match the type wrapped by NullOr");
+ if (optional.isOk()) return optional.value();
+ return def;
+}
+
+template <TagType tag_type, Tag tag>
+inline NullOr<const typename TypedTag2ValueType<TypedTag<tag_type, tag>>::type&>
+authorizationValue(TypedTag<tag_type, tag> ttag, const KeyParameter& param) {
+ if (tag != param.tag) return {};
+ return accessTagValue(ttag, param);
+}
+
+} // namespace keymaster
+
+#endif // SYSTEM_SECURITY_KEYSTORE_KEYMASTER_TAGS_H_
diff --git a/keystore/include/keystore/keystore.h b/keystore/include/keystore/keystore.h
index dcb6032..6f13820 100644
--- a/keystore/include/keystore/keystore.h
+++ b/keystore/include/keystore/keystore.h
@@ -26,7 +26,7 @@
STATE_UNINITIALIZED = 3,
};
-enum ResponseCode {
+enum class ResponseCode: int32_t {
NO_ERROR = STATE_NO_ERROR, // 1
LOCKED = STATE_LOCKED, // 2
UNINITIALIZED = STATE_UNINITIALIZED, // 3
diff --git a/keystore/include/keystore/keystore_client.h b/keystore/include/keystore/keystore_client.h
index cec29f7..a0593c1 100644
--- a/keystore/include/keystore/keystore_client.h
+++ b/keystore/include/keystore/keystore_client.h
@@ -19,16 +19,19 @@
#include <string>
#include <vector>
-#include "hardware/keymaster_defs.h"
-#include "keymaster/authorization_set.h"
+#include "authorization_set.h"
+#include "keystore.h"
+#include "keystore_return_types.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]
+// - encourage the use of keystore::AuthorizationSet[Builder]
// - be convenient for native services integrating with keystore
// - be safely mocked for unit testing (e.g. pure virtual methods)
//
@@ -73,79 +76,79 @@
// 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,
+ virtual bool oneShotOperation(KeyPurpose purpose, const std::string& key_name,
+ const keystore::AuthorizationSet& input_parameters,
const std::string& input_data,
const std::string& signature_to_verify,
- keymaster::AuthorizationSet* output_parameters,
+ keystore::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;
+ virtual KeyStoreNativeReturnCode 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;
+ virtual KeyStoreNativeReturnCode generateKey(const std::string& key_name,
+ const keystore::AuthorizationSet& key_parameters,
+ keystore::AuthorizationSet* hardware_enforced_characteristics,
+ keystore::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
+ virtual KeyStoreNativeReturnCode
getKeyCharacteristics(const std::string& key_name,
- keymaster::AuthorizationSet* hardware_enforced_characteristics,
- keymaster::AuthorizationSet* software_enforced_characteristics) = 0;
+ keystore::AuthorizationSet* hardware_enforced_characteristics,
+ keystore::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;
+ virtual KeyStoreNativeReturnCode importKey(const std::string& key_name,
+ const keystore::AuthorizationSet& key_parameters,
+ KeyFormat key_format, const std::string& key_data,
+ keystore::AuthorizationSet* hardware_enforced_characteristics,
+ keystore::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,
+ virtual KeyStoreNativeReturnCode exportKey(KeyFormat 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;
+ virtual KeyStoreNativeReturnCode 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;
+ virtual KeyStoreNativeReturnCode 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;
+ virtual KeyStoreNativeReturnCode beginOperation(KeyPurpose purpose, const std::string& key_name,
+ const keystore::AuthorizationSet& input_parameters,
+ keystore::AuthorizationSet* output_parameters,
+ uint64_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,
+ virtual KeyStoreNativeReturnCode updateOperation(uint64_t handle,
+ const keystore::AuthorizationSet& input_parameters,
const std::string& input_data, size_t* num_input_bytes_consumed,
- keymaster::AuthorizationSet* output_parameters,
+ keystore::AuthorizationSet* output_parameters,
std::string* output_data) = 0;
// Finishes the operation associated with |handle| using the given
@@ -153,15 +156,15 @@
// 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,
+ virtual KeyStoreNativeReturnCode finishOperation(uint64_t handle,
+ const keystore::AuthorizationSet& input_parameters,
const std::string& signature_to_verify,
- keymaster::AuthorizationSet* output_parameters,
+ keystore::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;
+ virtual KeyStoreNativeReturnCode abortOperation(uint64_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.
diff --git a/keystore/include/keystore/keystore_client_impl.h b/keystore/include/keystore/keystore_client_impl.h
index 21f68f9..eb02275 100644
--- a/keystore/include/keystore/keystore_client_impl.h
+++ b/keystore/include/keystore/keystore_client_impl.h
@@ -15,16 +15,16 @@
#ifndef KEYSTORE_KEYSTORE_CLIENT_IMPL_H_
#define KEYSTORE_KEYSTORE_CLIENT_IMPL_H_
-#include "keystore/keystore_client.h"
+#include "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"
+#include <binder/IBinder.h>
+#include <binder/IServiceManager.h>
+#include "IKeystoreService.h"
+#include <utils/StrongPointer.h>
namespace keystore {
@@ -38,54 +38,54 @@
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,
+ bool oneShotOperation(KeyPurpose purpose, const std::string& key_name,
+ const keystore::AuthorizationSet& input_parameters,
const std::string& input_data, const std::string& signature_to_verify,
- keymaster::AuthorizationSet* output_parameters,
+ keystore::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
+ KeyStoreNativeReturnCode addRandomNumberGeneratorEntropy(const std::string& entropy) override;
+ KeyStoreNativeReturnCode generateKey(const std::string& key_name,
+ const keystore::AuthorizationSet& key_parameters,
+ keystore::AuthorizationSet* hardware_enforced_characteristics,
+ keystore::AuthorizationSet* software_enforced_characteristics) override;
+ KeyStoreNativeReturnCode
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,
+ keystore::AuthorizationSet* hardware_enforced_characteristics,
+ keystore::AuthorizationSet* software_enforced_characteristics) override;
+ KeyStoreNativeReturnCode importKey(const std::string& key_name,
+ const keystore::AuthorizationSet& key_parameters,
+ KeyFormat key_format, const std::string& key_data,
+ keystore::AuthorizationSet* hardware_enforced_characteristics,
+ keystore::AuthorizationSet* software_enforced_characteristics) override;
+ KeyStoreNativeReturnCode exportKey(KeyFormat 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,
+ KeyStoreNativeReturnCode deleteKey(const std::string& key_name) override;
+ KeyStoreNativeReturnCode deleteAllKeys() override;
+ KeyStoreNativeReturnCode beginOperation(KeyPurpose purpose, const std::string& key_name,
+ const keystore::AuthorizationSet& input_parameters,
+ keystore::AuthorizationSet* output_parameters,
+ uint64_t* handle) override;
+ KeyStoreNativeReturnCode updateOperation(uint64_t handle,
+ const keystore::AuthorizationSet& input_parameters,
const std::string& input_data, size_t* num_input_bytes_consumed,
- keymaster::AuthorizationSet* output_parameters,
+ keystore::AuthorizationSet* output_parameters,
std::string* output_data) override;
- int32_t finishOperation(keymaster_operation_handle_t handle,
- const keymaster::AuthorizationSet& input_parameters,
+ KeyStoreNativeReturnCode finishOperation(uint64_t handle,
+ const keystore::AuthorizationSet& input_parameters,
const std::string& signature_to_verify,
- keymaster::AuthorizationSet* output_parameters,
+ keystore::AuthorizationSet* output_parameters,
std::string* output_data) override;
- int32_t abortOperation(keymaster_operation_handle_t handle) override;
+ KeyStoreNativeReturnCode abortOperation(uint64_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();
+ uint64_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);
+// 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.
@@ -108,8 +108,8 @@
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_;
+ uint64_t next_virtual_handle_ = 1;
+ std::map<uint64_t, android::sp<android::IBinder>> active_operations_;
DISALLOW_COPY_AND_ASSIGN(KeystoreClientImpl);
};
diff --git a/keystore/include/keystore/keystore_hidl_support.h b/keystore/include/keystore/keystore_hidl_support.h
new file mode 100644
index 0000000..e858021
--- /dev/null
+++ b/keystore/include/keystore/keystore_hidl_support.h
@@ -0,0 +1,130 @@
+/*
+ **
+ ** Copyright 2016, The Android Open Source Project
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ ** http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ** See the License for the specific language governing permissions and
+ ** limitations under the License.
+ */
+
+#ifndef KEYSTORE_KEYSTORE_HIDL_SUPPORT_H_
+#define KEYSTORE_KEYSTORE_HIDL_SUPPORT_H_
+
+#include <android/hardware/keymaster/3.0/IKeymasterDevice.h>
+#include <hidl/Status.h>
+#include <keystore/keymaster_tags.h>
+#include <ostream>
+#include <sstream>
+#include <string>
+
+namespace keystore {
+
+inline static std::ostream& formatArgs(std::ostream& out) {
+ return out;
+}
+
+template <typename First, typename... Args>
+inline static std::ostream& formatArgs(std::ostream& out, First&& first, Args&&... args) {
+ out << first;
+ return formatArgs(out, args...);
+}
+
+template <typename... Args> inline static std::string argsToString(Args&&... args) {
+ std::stringstream s;
+ formatArgs(s, args...);
+ return s.str();
+}
+
+template <typename... Msgs>
+inline static ErrorCode ksHandleHidlError(const Return<ErrorCode>& error, Msgs&&... msgs) {
+ if (!error.isOk()) {
+ ALOGE("HIDL call failed with %s @ %s", error.description().c_str(),
+ argsToString(msgs...).c_str());
+ return ErrorCode::UNKNOWN_ERROR;
+ }
+ return ErrorCode(error);
+}
+template <typename... Msgs>
+inline static ErrorCode ksHandleHidlError(const Return<void>& error, Msgs&&... msgs) {
+ if (!error.isOk()) {
+ ALOGE("HIDL call failed with %s @ %s", error.description().c_str(),
+ argsToString(msgs...).c_str());
+ return ErrorCode::UNKNOWN_ERROR;
+ }
+ return ErrorCode::OK;
+}
+
+#define KS_HANDLE_HIDL_ERROR(rc) \
+ ::keystore::ksHandleHidlError(rc, __FILE__, ":", __LINE__, ":", __PRETTY_FUNCTION__)
+
+inline static hidl_vec<uint8_t> blob2hidlVec(const uint8_t* data, const size_t length,
+ bool inPlace = true) {
+ hidl_vec<uint8_t> result;
+ if (inPlace)
+ result.setToExternal(const_cast<unsigned char*>(data), length);
+ else {
+ result.resize(length);
+ memcpy(&result[0], data, length);
+ }
+ return result;
+}
+
+inline static hidl_vec<uint8_t> blob2hidlVec(const std::string& value) {
+ hidl_vec<uint8_t> result;
+ result.setToExternal(
+ reinterpret_cast<uint8_t*>(const_cast<std::string::value_type*>(value.data())),
+ static_cast<size_t>(value.size()));
+ return result;
+}
+
+inline static hidl_vec<uint8_t> blob2hidlVec(const std::vector<uint8_t>& blob) {
+ hidl_vec<uint8_t> result;
+ result.setToExternal(const_cast<uint8_t*>(blob.data()), static_cast<size_t>(blob.size()));
+ return result;
+}
+
+template <typename T, typename OutIter>
+inline static OutIter copy_bytes_to_iterator(const T& value, OutIter dest) {
+ const uint8_t* value_ptr = reinterpret_cast<const uint8_t*>(&value);
+ return std::copy(value_ptr, value_ptr + sizeof(value), dest);
+}
+
+inline static hidl_vec<uint8_t> authToken2HidlVec(const HardwareAuthToken& token) {
+ static_assert(
+ std::is_same<decltype(token.hmac), ::android::hardware::hidl_array<uint8_t, 32>>::value,
+ "This function assumes token HMAC is 32 bytes, but it might not be.");
+ static_assert(1 /* version size */ + sizeof(token.challenge) + sizeof(token.userId) +
+ sizeof(token.authenticatorId) + sizeof(token.authenticatorType) +
+ sizeof(token.timestamp) + 32 /* HMAC size */
+ == sizeof(hw_auth_token_t),
+ "HardwareAuthToken content size does not match hw_auth_token_t size");
+
+ hidl_vec<uint8_t> result;
+ result.resize(sizeof(hw_auth_token_t));
+ auto pos = result.begin();
+ *pos++ = 0; // Version byte
+ pos = copy_bytes_to_iterator(token.challenge, result.begin());
+ pos = copy_bytes_to_iterator(token.userId, pos);
+ pos = copy_bytes_to_iterator(token.authenticatorId, pos);
+ pos = copy_bytes_to_iterator(token.authenticatorType, pos);
+ pos = copy_bytes_to_iterator(token.timestamp, pos);
+ pos = std::copy(token.hmac.data(), token.hmac.data() + token.hmac.size(), pos);
+
+ return result;
+}
+
+inline std::string hidlVec2String(const hidl_vec<uint8_t>& value) {
+ return std::string(reinterpret_cast<const std::string::value_type*>(&value[0]), value.size());
+}
+
+} // namespace keystore
+
+#endif // KEYSTORE_KEYSTORE_HIDL_SUPPORT_H_
diff --git a/keystore/include/keystore/keystore_return_types.h b/keystore/include/keystore/keystore_return_types.h
new file mode 100644
index 0000000..70380c3
--- /dev/null
+++ b/keystore/include/keystore/keystore_return_types.h
@@ -0,0 +1,186 @@
+/*
+**
+** Copyright 2016, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+#ifndef KEYSTORE_INCLUDE_KEYSTORE_KEYSTORE_RETURN_TYPES_H_
+#define KEYSTORE_INCLUDE_KEYSTORE_KEYSTORE_RETURN_TYPES_H_
+
+#include "keystore.h"
+#include <android/hardware/keymaster/3.0/IHwKeymasterDevice.h>
+
+namespace keystore {
+
+using ::android::hardware::keymaster::V3_0::ErrorCode;
+
+class KeyStoreServiceReturnCode;
+class KeyStoreNativeReturnCode;
+
+/**
+ * The keystore service return code is a bit tricky. It can return error codes from two name spaces:
+ * ErrorCode, which has negative error codes and use 0 for ERROR_OK;
+ * ResponseCode, which has positive error codes and uses 1 for NO_ERROR.
+ * This class can be initialized by both. And when accessed through the operator int32_t () it
+ * always returns ResponseCode::NO_ERROR (1) on success, even if it was initialized with
+ * ErrorCode::OK (0), because this is what (java) clients expect.
+ *
+ * !!! Do not confuse this with KeyStoreNativeReturnCode which always converts to 0 on success. !!!
+ */
+class KeyStoreServiceReturnCode {
+ public:
+ KeyStoreServiceReturnCode() : errorCode_(0) {}
+ KeyStoreServiceReturnCode(const ErrorCode& errorCode) : errorCode_(int32_t(errorCode)) {}
+ KeyStoreServiceReturnCode(const ResponseCode& errorCode) : errorCode_(int32_t(errorCode)) {}
+ KeyStoreServiceReturnCode(const KeyStoreServiceReturnCode& errorCode)
+ : errorCode_(errorCode.errorCode_) {}
+ KeyStoreServiceReturnCode(const KeyStoreNativeReturnCode& errorCode);
+ inline KeyStoreServiceReturnCode& operator=(const ErrorCode& errorCode) {
+ errorCode_ = int32_t(errorCode);
+ return *this;
+ }
+ inline KeyStoreServiceReturnCode& operator=(const ResponseCode& errorCode) {
+ errorCode_ = int32_t(errorCode);
+ return *this;
+ }
+ inline KeyStoreServiceReturnCode& operator=(const KeyStoreServiceReturnCode& errorCode) {
+ errorCode_ = errorCode.errorCode_;
+ return *this;
+ }
+ inline bool isOk() const {
+ return errorCode_ == static_cast<int32_t>(ResponseCode::NO_ERROR) ||
+ errorCode_ == static_cast<int32_t>(ErrorCode::OK);
+ }
+ inline operator int32_t() const {
+ if (!errorCode_) return static_cast<int32_t>(ResponseCode::NO_ERROR);
+ return errorCode_;
+ }
+ inline bool operator==(const ResponseCode& rhs) const {
+ return (rhs == ResponseCode::NO_ERROR &&
+ errorCode_ == static_cast<int32_t>(ErrorCode::OK)) ||
+ errorCode_ == int32_t(rhs);
+ }
+ inline bool operator==(const ErrorCode& rhs) const {
+ return (rhs == ErrorCode::OK &&
+ errorCode_ == static_cast<int32_t>(ResponseCode::NO_ERROR)) ||
+ errorCode_ == int32_t(rhs);
+ }
+ inline bool operator!=(const ResponseCode& rhs) const { return !(*this == rhs); }
+ inline bool operator!=(const ErrorCode& rhs) const { return !(*this == rhs); }
+
+ private:
+ int32_t errorCode_;
+};
+
+inline bool operator==(const ResponseCode& lhs, const KeyStoreServiceReturnCode& rhs) {
+ return rhs == lhs;
+}
+inline bool operator==(const ErrorCode& lhs, const KeyStoreServiceReturnCode& rhs) {
+ return rhs == lhs;
+}
+inline bool operator!=(const ResponseCode& lhs, const KeyStoreServiceReturnCode& rhs) {
+ return rhs != lhs;
+}
+inline bool operator!=(const ErrorCode& lhs, const KeyStoreServiceReturnCode& rhs) {
+ return rhs != lhs;
+}
+
+inline std::ostream& operator<<(std::ostream& out, const KeyStoreServiceReturnCode& error) {
+ return out << int32_t(error);
+}
+
+/**
+ * The keystore native return code is a bit tricky. It can return error codes from two name spaces:
+ * ErrorCode, which has negative error codes and use 0 for ERROR_OK;
+ * ResponseCode, which has positive error codes and uses 1 for NO_ERROR.
+ * This class can be initialized by both. And when accessed through the operator int32_t () it
+ * always returns ErrorCode::OK (0) on success, even if it was initialized with
+ * ResponseCode::NO_ERROR (1), because this is what (native) clients expect.
+ *
+ * !!! Do not this confuse with KeyStoreServiceReturnCode which always converts to 1 on success. !!!
+ */
+class KeyStoreNativeReturnCode {
+ public:
+ KeyStoreNativeReturnCode() : errorCode_(0) {}
+ KeyStoreNativeReturnCode(const ErrorCode& errorCode) : errorCode_(int32_t(errorCode)) {}
+ KeyStoreNativeReturnCode(const ResponseCode& errorCode) : errorCode_(int32_t(errorCode)) {}
+ KeyStoreNativeReturnCode(const KeyStoreNativeReturnCode& errorCode)
+ : errorCode_(errorCode.errorCode_) {}
+ KeyStoreNativeReturnCode(const KeyStoreServiceReturnCode& errorcode);
+ inline KeyStoreNativeReturnCode& operator=(const ErrorCode& errorCode) {
+ errorCode_ = int32_t(errorCode);
+ return *this;
+ }
+ inline KeyStoreNativeReturnCode& operator=(const ResponseCode& errorCode) {
+ errorCode_ = int32_t(errorCode);
+ return *this;
+ }
+ inline KeyStoreNativeReturnCode& operator=(const KeyStoreNativeReturnCode& errorCode) {
+ errorCode_ = errorCode.errorCode_;
+ return *this;
+ }
+ inline bool isOk() const {
+ return errorCode_ == static_cast<int32_t>(ResponseCode::NO_ERROR) ||
+ errorCode_ == static_cast<int32_t>(ErrorCode::OK);
+ }
+ inline operator int32_t() const {
+ if (errorCode_ == static_cast<int32_t>(ResponseCode::NO_ERROR)) {
+ return static_cast<int32_t>(ErrorCode::OK);
+ }
+ return errorCode_;
+ }
+ inline bool operator==(const ResponseCode& rhs) const {
+ return (rhs == ResponseCode::NO_ERROR &&
+ errorCode_ == static_cast<int32_t>(ErrorCode::OK)) ||
+ errorCode_ == int32_t(rhs);
+ }
+ inline bool operator==(const ErrorCode& rhs) const {
+ return (rhs == ErrorCode::OK &&
+ errorCode_ == static_cast<int32_t>(ResponseCode::NO_ERROR)) ||
+ errorCode_ == int32_t(rhs);
+ }
+ inline bool operator!=(const ResponseCode& rhs) const { return !(*this == rhs); }
+ inline bool operator!=(const ErrorCode& rhs) const { return !(*this == rhs); }
+
+ private:
+ int32_t errorCode_;
+};
+
+inline bool operator==(const ResponseCode& lhs, const KeyStoreNativeReturnCode& rhs) {
+ return rhs == lhs;
+}
+inline bool operator==(const ErrorCode& lhs, const KeyStoreNativeReturnCode& rhs) {
+ return rhs == lhs;
+}
+inline bool operator!=(const ResponseCode& lhs, const KeyStoreNativeReturnCode& rhs) {
+ return rhs != lhs;
+}
+inline bool operator!=(const ErrorCode& lhs, const KeyStoreNativeReturnCode& rhs) {
+ return rhs != lhs;
+}
+
+inline KeyStoreNativeReturnCode::KeyStoreNativeReturnCode(
+ const KeyStoreServiceReturnCode& errorCode)
+ : errorCode_(int32_t(errorCode)) {}
+inline KeyStoreServiceReturnCode::KeyStoreServiceReturnCode(
+ const KeyStoreNativeReturnCode& errorCode)
+ : errorCode_(int32_t(errorCode)) {}
+
+inline std::ostream& operator<<(std::ostream& out, const KeyStoreNativeReturnCode& error) {
+ return out << int32_t(error);
+}
+
+} // namespace keystore
+
+#endif // KEYSTORE_INCLUDE_KEYSTORE_KEYSTORE_RETURN_TYPES_H_
diff --git a/keystore/key_store_service.cpp b/keystore/key_store_service.cpp
index 5b15e4b..d4032c1 100644
--- a/keystore/key_store_service.cpp
+++ b/keystore/key_store_service.cpp
@@ -28,18 +28,16 @@
#include <private/android_filesystem_config.h>
-#include <hardware/keymaster_defs.h>
+#include <android/hardware/keymaster/3.0/IHwKeymasterDevice.h>
#include "defaults.h"
#include "keystore_attestation_id.h"
+#include "keystore_keymaster_enforcement.h"
#include "keystore_utils.h"
+#include <keystore/keystore_hidl_support.h>
-using keymaster::AuthorizationSet;
-using keymaster::AuthorizationSetBuilder;
-using keymaster::TAG_APPLICATION_DATA;
-using keymaster::TAG_APPLICATION_ID;
-
-namespace android {
+namespace keystore {
+using namespace android;
const size_t MAX_OPERATIONS = 15;
@@ -48,10 +46,6 @@
};
typedef UniquePtr<BIGNUM, BIGNUM_Delete> Unique_BIGNUM;
-struct Malloc_Delete {
- void operator()(uint8_t* p) const { free(p); }
-};
-
void KeyStoreService::binderDied(const wp<IBinder>& who) {
auto operations = mOperationMap.getOperationsForToken(who.unsafe_get());
for (const auto& token : operations) {
@@ -59,116 +53,124 @@
}
}
-int32_t KeyStoreService::getState(int32_t userId) {
+KeyStoreServiceReturnCode KeyStoreService::getState(int32_t userId) {
if (!checkBinderPermission(P_GET_STATE)) {
- return ::PERMISSION_DENIED;
+ return ResponseCode::PERMISSION_DENIED;
}
- return mKeyStore->getState(userId);
+ return ResponseCode(mKeyStore->getState(userId));
}
-int32_t KeyStoreService::get(const String16& name, int32_t uid, uint8_t** item,
- size_t* itemLength) {
+KeyStoreServiceReturnCode KeyStoreService::get(const String16& name, int32_t uid,
+ hidl_vec<uint8_t>* item) {
uid_t targetUid = getEffectiveUid(uid);
if (!checkBinderPermission(P_GET, targetUid)) {
- return ::PERMISSION_DENIED;
+ return ResponseCode::PERMISSION_DENIED;
}
String8 name8(name);
Blob keyBlob;
- ResponseCode responseCode = mKeyStore->getKeyForName(&keyBlob, name8, targetUid, TYPE_GENERIC);
- if (responseCode != ::NO_ERROR) {
- *item = NULL;
- *itemLength = 0;
- return responseCode;
+ KeyStoreServiceReturnCode rc =
+ mKeyStore->getKeyForName(&keyBlob, name8, targetUid, TYPE_GENERIC);
+ if (!rc.isOk()) {
+ if (item) *item = hidl_vec<uint8_t>();
+ return rc;
}
- *item = (uint8_t*)malloc(keyBlob.getLength());
- memcpy(*item, keyBlob.getValue(), keyBlob.getLength());
- *itemLength = keyBlob.getLength();
+ // Do not replace this with "if (item) *item = blob2hidlVec(keyBlob)"!
+ // blob2hidlVec creates a hidl_vec<uint8_t> that references, but not owns, the data in keyBlob
+ // the subsequent assignment (*item = resultBlob) makes a deep copy, so that *item will own the
+ // corresponding resources.
+ auto resultBlob = blob2hidlVec(keyBlob);
+ if (item) {
+ *item = resultBlob;
+ }
- return ::NO_ERROR;
+ return ResponseCode::NO_ERROR;
}
-int32_t KeyStoreService::insert(const String16& name, const uint8_t* item, size_t itemLength,
- int targetUid, int32_t flags) {
+KeyStoreServiceReturnCode KeyStoreService::insert(const String16& name,
+ const hidl_vec<uint8_t>& item, int targetUid,
+ int32_t flags) {
targetUid = getEffectiveUid(targetUid);
- int32_t result =
+ auto result =
checkBinderPermissionAndKeystoreState(P_INSERT, targetUid, flags & KEYSTORE_FLAG_ENCRYPTED);
- if (result != ::NO_ERROR) {
+ if (!result.isOk()) {
return result;
}
String8 name8(name);
String8 filename(mKeyStore->getKeyNameForUidWithDir(name8, targetUid, ::TYPE_GENERIC));
- Blob keyBlob(item, itemLength, NULL, 0, ::TYPE_GENERIC);
+ Blob keyBlob(&item[0], item.size(), NULL, 0, ::TYPE_GENERIC);
keyBlob.setEncrypted(flags & KEYSTORE_FLAG_ENCRYPTED);
return mKeyStore->put(filename.string(), &keyBlob, get_user_id(targetUid));
}
-int32_t KeyStoreService::del(const String16& name, int targetUid) {
+KeyStoreServiceReturnCode KeyStoreService::del(const String16& name, int targetUid) {
targetUid = getEffectiveUid(targetUid);
if (!checkBinderPermission(P_DELETE, targetUid)) {
- return ::PERMISSION_DENIED;
+ return ResponseCode::PERMISSION_DENIED;
}
String8 name8(name);
String8 filename(mKeyStore->getKeyNameForUidWithDir(name8, targetUid, ::TYPE_ANY));
- int32_t result = mKeyStore->del(filename.string(), ::TYPE_ANY, get_user_id(targetUid));
- if (result != ::NO_ERROR) {
+ ResponseCode result = mKeyStore->del(filename.string(), ::TYPE_ANY, get_user_id(targetUid));
+ if (result != ResponseCode::NO_ERROR) {
return result;
}
// Also delete any characteristics files
- String8 chrFilename(mKeyStore->getKeyNameForUidWithDir(
- name8, targetUid, ::TYPE_KEY_CHARACTERISTICS));
+ String8 chrFilename(
+ mKeyStore->getKeyNameForUidWithDir(name8, targetUid, ::TYPE_KEY_CHARACTERISTICS));
return mKeyStore->del(chrFilename.string(), ::TYPE_KEY_CHARACTERISTICS, get_user_id(targetUid));
}
-int32_t KeyStoreService::exist(const String16& name, int targetUid) {
+KeyStoreServiceReturnCode KeyStoreService::exist(const String16& name, int targetUid) {
targetUid = getEffectiveUid(targetUid);
if (!checkBinderPermission(P_EXIST, targetUid)) {
- return ::PERMISSION_DENIED;
+ return ResponseCode::PERMISSION_DENIED;
}
String8 name8(name);
String8 filename(mKeyStore->getKeyNameForUidWithDir(name8, targetUid, ::TYPE_ANY));
if (access(filename.string(), R_OK) == -1) {
- return (errno != ENOENT) ? ::SYSTEM_ERROR : ::KEY_NOT_FOUND;
+ return (errno != ENOENT) ? ResponseCode::SYSTEM_ERROR : ResponseCode::KEY_NOT_FOUND;
}
- return ::NO_ERROR;
+ return ResponseCode::NO_ERROR;
}
-int32_t KeyStoreService::list(const String16& prefix, int targetUid, Vector<String16>* matches) {
+KeyStoreServiceReturnCode KeyStoreService::list(const String16& prefix, int targetUid,
+ Vector<String16>* matches) {
targetUid = getEffectiveUid(targetUid);
if (!checkBinderPermission(P_LIST, targetUid)) {
- return ::PERMISSION_DENIED;
+ return ResponseCode::PERMISSION_DENIED;
}
const String8 prefix8(prefix);
String8 filename(mKeyStore->getKeyNameForUid(prefix8, targetUid, TYPE_ANY));
- if (mKeyStore->list(filename, matches, get_user_id(targetUid)) != ::NO_ERROR) {
- return ::SYSTEM_ERROR;
+ if (mKeyStore->list(filename, matches, get_user_id(targetUid)) != ResponseCode::NO_ERROR) {
+ return ResponseCode::SYSTEM_ERROR;
}
- return ::NO_ERROR;
+ return ResponseCode::NO_ERROR;
}
-int32_t KeyStoreService::reset() {
+KeyStoreServiceReturnCode KeyStoreService::reset() {
if (!checkBinderPermission(P_RESET)) {
- return ::PERMISSION_DENIED;
+ return ResponseCode::PERMISSION_DENIED;
}
uid_t callingUid = IPCThreadState::self()->getCallingUid();
mKeyStore->resetUser(get_user_id(callingUid), false);
- return ::NO_ERROR;
+ return ResponseCode::NO_ERROR;
}
-int32_t KeyStoreService::onUserPasswordChanged(int32_t userId, const String16& password) {
+KeyStoreServiceReturnCode KeyStoreService::onUserPasswordChanged(int32_t userId,
+ const String16& password) {
if (!checkBinderPermission(P_PASSWORD)) {
- return ::PERMISSION_DENIED;
+ return ResponseCode::PERMISSION_DENIED;
}
const String8 password8(password);
@@ -179,7 +181,7 @@
if (password.size() == 0) {
ALOGI("Secure lockscreen for user %d removed, deleting encrypted entries", userId);
mKeyStore->resetUser(userId, true);
- return ::NO_ERROR;
+ return ResponseCode::NO_ERROR;
} else {
switch (mKeyStore->getState(userId)) {
case ::STATE_UNINITIALIZED: {
@@ -197,13 +199,13 @@
return mKeyStore->initializeUser(password8, userId);
}
}
- return ::SYSTEM_ERROR;
+ return ResponseCode::SYSTEM_ERROR;
}
}
-int32_t KeyStoreService::onUserAdded(int32_t userId, int32_t parentId) {
+KeyStoreServiceReturnCode KeyStoreService::onUserAdded(int32_t userId, int32_t parentId) {
if (!checkBinderPermission(P_USER_CHANGED)) {
- return ::PERMISSION_DENIED;
+ return ResponseCode::PERMISSION_DENIED;
}
// Sanity check that the new user has an empty keystore.
@@ -219,37 +221,37 @@
// parent profile, forever.
return mKeyStore->copyMasterKey(parentId, userId);
} else {
- return ::NO_ERROR;
+ return ResponseCode::NO_ERROR;
}
}
-int32_t KeyStoreService::onUserRemoved(int32_t userId) {
+KeyStoreServiceReturnCode KeyStoreService::onUserRemoved(int32_t userId) {
if (!checkBinderPermission(P_USER_CHANGED)) {
- return ::PERMISSION_DENIED;
+ return ResponseCode::PERMISSION_DENIED;
}
mKeyStore->resetUser(userId, false);
- return ::NO_ERROR;
+ return ResponseCode::NO_ERROR;
}
-int32_t KeyStoreService::lock(int32_t userId) {
+KeyStoreServiceReturnCode KeyStoreService::lock(int32_t userId) {
if (!checkBinderPermission(P_LOCK)) {
- return ::PERMISSION_DENIED;
+ return ResponseCode::PERMISSION_DENIED;
}
State state = mKeyStore->getState(userId);
if (state != ::STATE_NO_ERROR) {
ALOGD("calling lock in state: %d", state);
- return state;
+ return ResponseCode(state);
}
mKeyStore->lock(userId);
- return ::NO_ERROR;
+ return ResponseCode::NO_ERROR;
}
-int32_t KeyStoreService::unlock(int32_t userId, const String16& pw) {
+KeyStoreServiceReturnCode KeyStoreService::unlock(int32_t userId, const String16& pw) {
if (!checkBinderPermission(P_UNLOCK)) {
- return ::PERMISSION_DENIED;
+ return ResponseCode::PERMISSION_DENIED;
}
State state = mKeyStore->getState(userId);
@@ -265,7 +267,7 @@
ALOGE("unlock called on keystore in unknown state: %d", state);
break;
}
- return state;
+ return ResponseCode(state);
}
const String8 password8(pw);
@@ -281,43 +283,44 @@
return mKeyStore->isEmpty(userId);
}
-int32_t KeyStoreService::generate(const String16& name, int32_t targetUid, int32_t keyType,
- int32_t keySize, int32_t flags, Vector<sp<KeystoreArg>>* args) {
+KeyStoreServiceReturnCode KeyStoreService::generate(const String16& name, int32_t targetUid,
+ int32_t keyType, int32_t keySize, int32_t flags,
+ Vector<sp<KeystoreArg>>* args) {
targetUid = getEffectiveUid(targetUid);
- int32_t result =
+ auto result =
checkBinderPermissionAndKeystoreState(P_INSERT, targetUid, flags & KEYSTORE_FLAG_ENCRYPTED);
- if (result != ::NO_ERROR) {
+ if (!result.isOk()) {
return result;
}
- KeymasterArguments params;
- add_legacy_key_authorizations(keyType, ¶ms.params);
+ keystore::AuthorizationSet params;
+ add_legacy_key_authorizations(keyType, ¶ms);
switch (keyType) {
case EVP_PKEY_EC: {
- params.params.push_back(keymaster_param_enum(KM_TAG_ALGORITHM, KM_ALGORITHM_EC));
+ params.push_back(TAG_ALGORITHM, Algorithm::EC);
if (keySize == -1) {
keySize = EC_DEFAULT_KEY_SIZE;
} else if (keySize < EC_MIN_KEY_SIZE || keySize > EC_MAX_KEY_SIZE) {
ALOGI("invalid key size %d", keySize);
- return ::SYSTEM_ERROR;
+ return ResponseCode::SYSTEM_ERROR;
}
- params.params.push_back(keymaster_param_int(KM_TAG_KEY_SIZE, keySize));
+ params.push_back(TAG_KEY_SIZE, keySize);
break;
}
case EVP_PKEY_RSA: {
- params.params.push_back(keymaster_param_enum(KM_TAG_ALGORITHM, KM_ALGORITHM_RSA));
+ params.push_back(TAG_ALGORITHM, Algorithm::RSA);
if (keySize == -1) {
keySize = RSA_DEFAULT_KEY_SIZE;
} else if (keySize < RSA_MIN_KEY_SIZE || keySize > RSA_MAX_KEY_SIZE) {
ALOGI("invalid key size %d", keySize);
- return ::SYSTEM_ERROR;
+ return ResponseCode::SYSTEM_ERROR;
}
- params.params.push_back(keymaster_param_int(KM_TAG_KEY_SIZE, keySize));
+ params.push_back(TAG_KEY_SIZE, keySize);
unsigned long exponent = RSA_DEFAULT_EXPONENT;
if (args->size() > 1) {
ALOGI("invalid number of arguments: %zu", args->size());
- return ::SYSTEM_ERROR;
+ return ResponseCode::SYSTEM_ERROR;
} else if (args->size() == 1) {
const sp<KeystoreArg>& expArg = args->itemAt(0);
if (expArg != NULL) {
@@ -325,84 +328,88 @@
reinterpret_cast<const unsigned char*>(expArg->data()), expArg->size(), NULL));
if (pubExpBn.get() == NULL) {
ALOGI("Could not convert public exponent to BN");
- return ::SYSTEM_ERROR;
+ return ResponseCode::SYSTEM_ERROR;
}
exponent = BN_get_word(pubExpBn.get());
if (exponent == 0xFFFFFFFFL) {
ALOGW("cannot represent public exponent as a long value");
- return ::SYSTEM_ERROR;
+ return ResponseCode::SYSTEM_ERROR;
}
} else {
ALOGW("public exponent not read");
- return ::SYSTEM_ERROR;
+ return ResponseCode::SYSTEM_ERROR;
}
}
- params.params.push_back(keymaster_param_long(KM_TAG_RSA_PUBLIC_EXPONENT, exponent));
+ params.push_back(TAG_RSA_PUBLIC_EXPONENT, exponent);
break;
}
default: {
ALOGW("Unsupported key type %d", keyType);
- return ::SYSTEM_ERROR;
+ return ResponseCode::SYSTEM_ERROR;
}
}
- int32_t rc = generateKey(name, params, NULL, 0, targetUid, flags,
- /*outCharacteristics*/ NULL);
- if (rc != ::NO_ERROR) {
- ALOGW("generate failed: %d", rc);
+ auto rc = generateKey(name, params.hidl_data(), hidl_vec<uint8_t>(), targetUid, flags,
+ /*outCharacteristics*/ NULL);
+ if (!rc.isOk()) {
+ ALOGW("generate failed: %d", int32_t(rc));
}
return translateResultToLegacyResult(rc);
}
-int32_t KeyStoreService::import(const String16& name, const uint8_t* data, size_t length,
- int targetUid, int32_t flags) {
- const uint8_t* ptr = data;
+KeyStoreServiceReturnCode KeyStoreService::import(const String16& name,
+ const hidl_vec<uint8_t>& data, int targetUid,
+ int32_t flags) {
- Unique_PKCS8_PRIV_KEY_INFO pkcs8(d2i_PKCS8_PRIV_KEY_INFO(NULL, &ptr, length));
+ const uint8_t* ptr = &data[0];
+
+ Unique_PKCS8_PRIV_KEY_INFO pkcs8(d2i_PKCS8_PRIV_KEY_INFO(NULL, &ptr, data.size()));
if (!pkcs8.get()) {
- return ::SYSTEM_ERROR;
+ return ResponseCode::SYSTEM_ERROR;
}
Unique_EVP_PKEY pkey(EVP_PKCS82PKEY(pkcs8.get()));
if (!pkey.get()) {
- return ::SYSTEM_ERROR;
+ return ResponseCode::SYSTEM_ERROR;
}
int type = EVP_PKEY_type(pkey->type);
- KeymasterArguments params;
- add_legacy_key_authorizations(type, ¶ms.params);
+ AuthorizationSet params;
+ add_legacy_key_authorizations(type, ¶ms);
switch (type) {
case EVP_PKEY_RSA:
- params.params.push_back(keymaster_param_enum(KM_TAG_ALGORITHM, KM_ALGORITHM_RSA));
+ params.push_back(TAG_ALGORITHM, Algorithm::RSA);
break;
case EVP_PKEY_EC:
- params.params.push_back(keymaster_param_enum(KM_TAG_ALGORITHM, KM_ALGORITHM_EC));
+ params.push_back(TAG_ALGORITHM, Algorithm::EC);
break;
default:
ALOGW("Unsupported key type %d", type);
- return ::SYSTEM_ERROR;
+ return ResponseCode::SYSTEM_ERROR;
}
- int32_t rc = importKey(name, params, KM_KEY_FORMAT_PKCS8, data, length, targetUid, flags,
- /*outCharacteristics*/ NULL);
- if (rc != ::NO_ERROR) {
- ALOGW("importKey failed: %d", rc);
+
+ auto rc = importKey(name, params.hidl_data(), KeyFormat::PKCS8, data, targetUid, flags,
+ /*outCharacteristics*/ NULL);
+
+ if (!rc.isOk()) {
+ ALOGW("importKey failed: %d", int32_t(rc));
}
return translateResultToLegacyResult(rc);
}
-int32_t KeyStoreService::sign(const String16& name, const uint8_t* data, size_t length,
- uint8_t** out, size_t* outLength) {
+KeyStoreServiceReturnCode KeyStoreService::sign(const String16& name, const hidl_vec<uint8_t>& data,
+ hidl_vec<uint8_t>* out) {
if (!checkBinderPermission(P_SIGN)) {
- return ::PERMISSION_DENIED;
+ return ResponseCode::PERMISSION_DENIED;
}
- return doLegacySignVerify(name, data, length, out, outLength, NULL, 0, KM_PURPOSE_SIGN);
+ return doLegacySignVerify(name, data, out, hidl_vec<uint8_t>(), KeyPurpose::SIGN);
}
-int32_t KeyStoreService::verify(const String16& name, const uint8_t* data, size_t dataLength,
- const uint8_t* signature, size_t signatureLength) {
+KeyStoreServiceReturnCode KeyStoreService::verify(const String16& name,
+ const hidl_vec<uint8_t>& data,
+ const hidl_vec<uint8_t>& signature) {
if (!checkBinderPermission(P_VERIFY)) {
- return ::PERMISSION_DENIED;
+ return ResponseCode::PERMISSION_DENIED;
}
- return doLegacySignVerify(name, data, dataLength, NULL, NULL, signature, signatureLength,
- KM_PURPOSE_VERIFY);
+ return doLegacySignVerify(name, data, nullptr, signature, KeyPurpose::VERIFY);
}
/*
@@ -416,23 +423,23 @@
* "del_key" since the Java code doesn't really communicate what it's
* intentions are.
*/
-int32_t KeyStoreService::get_pubkey(const String16& name, uint8_t** pubkey, size_t* pubkeyLength) {
+KeyStoreServiceReturnCode KeyStoreService::get_pubkey(const String16& name,
+ hidl_vec<uint8_t>* pubKey) {
ExportResult result;
- exportKey(name, KM_KEY_FORMAT_X509, NULL, NULL, UID_SELF, &result);
- if (result.resultCode != ::NO_ERROR) {
- ALOGW("export failed: %d", result.resultCode);
+ exportKey(name, KeyFormat::X509, hidl_vec<uint8_t>(), hidl_vec<uint8_t>(), UID_SELF, &result);
+ if (!result.resultCode.isOk()) {
+ ALOGW("export failed: %d", int32_t(result.resultCode));
return translateResultToLegacyResult(result.resultCode);
}
- *pubkey = result.exportData.release();
- *pubkeyLength = result.dataLength;
- return ::NO_ERROR;
+ if (pubKey) *pubKey = std::move(result.exportData);
+ return ResponseCode::NO_ERROR;
}
-int32_t KeyStoreService::grant(const String16& name, int32_t granteeUid) {
+KeyStoreServiceReturnCode KeyStoreService::grant(const String16& name, int32_t granteeUid) {
uid_t callingUid = IPCThreadState::self()->getCallingUid();
- int32_t result = checkBinderPermissionAndKeystoreState(P_GRANT);
- if (result != ::NO_ERROR) {
+ auto result = checkBinderPermissionAndKeystoreState(P_GRANT);
+ if (!result.isOk()) {
return result;
}
@@ -440,17 +447,17 @@
String8 filename(mKeyStore->getKeyNameForUidWithDir(name8, callingUid, ::TYPE_ANY));
if (access(filename.string(), R_OK) == -1) {
- return (errno != ENOENT) ? ::SYSTEM_ERROR : ::KEY_NOT_FOUND;
+ return (errno != ENOENT) ? ResponseCode::SYSTEM_ERROR : ResponseCode::KEY_NOT_FOUND;
}
mKeyStore->addGrant(filename.string(), granteeUid);
- return ::NO_ERROR;
+ return ResponseCode::NO_ERROR;
}
-int32_t KeyStoreService::ungrant(const String16& name, int32_t granteeUid) {
+KeyStoreServiceReturnCode KeyStoreService::ungrant(const String16& name, int32_t granteeUid) {
uid_t callingUid = IPCThreadState::self()->getCallingUid();
- int32_t result = checkBinderPermissionAndKeystoreState(P_GRANT);
- if (result != ::NO_ERROR) {
+ auto result = checkBinderPermissionAndKeystoreState(P_GRANT);
+ if (!result.isOk()) {
return result;
}
@@ -458,10 +465,11 @@
String8 filename(mKeyStore->getKeyNameForUidWithDir(name8, callingUid, ::TYPE_ANY));
if (access(filename.string(), R_OK) == -1) {
- return (errno != ENOENT) ? ::SYSTEM_ERROR : ::KEY_NOT_FOUND;
+ return (errno != ENOENT) ? ResponseCode::SYSTEM_ERROR : ResponseCode::KEY_NOT_FOUND;
}
- return mKeyStore->removeGrant(filename.string(), granteeUid) ? ::NO_ERROR : ::KEY_NOT_FOUND;
+ return mKeyStore->removeGrant(filename.string(), granteeUid) ? ResponseCode::NO_ERROR
+ : ResponseCode::KEY_NOT_FOUND;
}
int64_t KeyStoreService::getmtime(const String16& name, int32_t uid) {
@@ -497,26 +505,26 @@
}
// TODO(tuckeris): This is dead code, remove it. Don't bother copying over key characteristics here
-int32_t KeyStoreService::duplicate(const String16& srcKey, int32_t srcUid, const String16& destKey,
- int32_t destUid) {
+KeyStoreServiceReturnCode KeyStoreService::duplicate(const String16& srcKey, int32_t srcUid,
+ const String16& destKey, int32_t destUid) {
uid_t callingUid = IPCThreadState::self()->getCallingUid();
pid_t spid = IPCThreadState::self()->getCallingPid();
if (!has_permission(callingUid, P_DUPLICATE, spid)) {
ALOGW("permission denied for %d: duplicate", callingUid);
- return -1L;
+ return ResponseCode::PERMISSION_DENIED;
}
State state = mKeyStore->getState(get_user_id(callingUid));
if (!isKeystoreUnlocked(state)) {
ALOGD("calling duplicate in state: %d", state);
- return state;
+ return ResponseCode(state);
}
if (srcUid == -1 || static_cast<uid_t>(srcUid) == callingUid) {
srcUid = callingUid;
} else if (!is_granted_to(callingUid, srcUid)) {
ALOGD("migrate not granted from source: %d -> %d", callingUid, srcUid);
- return ::PERMISSION_DENIED;
+ return ResponseCode::PERMISSION_DENIED;
}
if (destUid == -1) {
@@ -528,12 +536,12 @@
ALOGD("can only duplicate from caller to other or to same uid: "
"calling=%d, srcUid=%d, destUid=%d",
callingUid, srcUid, destUid);
- return ::PERMISSION_DENIED;
+ return ResponseCode::PERMISSION_DENIED;
}
if (!is_granted_to(callingUid, destUid)) {
ALOGD("duplicate not granted to dest: %d -> %d", callingUid, destUid);
- return ::PERMISSION_DENIED;
+ return ResponseCode::PERMISSION_DENIED;
}
}
@@ -545,13 +553,13 @@
if (access(targetFile.string(), W_OK) != -1 || errno != ENOENT) {
ALOGD("destination already exists: %s", targetFile.string());
- return ::SYSTEM_ERROR;
+ return ResponseCode::SYSTEM_ERROR;
}
Blob keyBlob;
ResponseCode responseCode =
mKeyStore->get(sourceFile.string(), &keyBlob, TYPE_ANY, get_user_id(srcUid));
- if (responseCode != ::NO_ERROR) {
+ if (responseCode != ResponseCode::NO_ERROR) {
return responseCode;
}
@@ -562,16 +570,16 @@
return mKeyStore->isHardwareBacked(keyType) ? 1 : 0;
}
-int32_t KeyStoreService::clear_uid(int64_t targetUid64) {
+KeyStoreServiceReturnCode KeyStoreService::clear_uid(int64_t targetUid64) {
uid_t targetUid = getEffectiveUid(targetUid64);
if (!checkBinderPermissionSelfOrSystem(P_CLEAR_UID, targetUid)) {
- return ::PERMISSION_DENIED;
+ return ResponseCode::PERMISSION_DENIED;
}
String8 prefix = String8::format("%u_", targetUid);
Vector<String16> aliases;
- if (mKeyStore->list(prefix, &aliases, get_user_id(targetUid)) != ::NO_ERROR) {
- return ::SYSTEM_ERROR;
+ if (mKeyStore->list(prefix, &aliases, get_user_id(targetUid)) != ResponseCode::NO_ERROR) {
+ return ResponseCode::SYSTEM_ERROR;
}
for (uint32_t i = 0; i < aliases.size(); i++) {
@@ -580,141 +588,101 @@
mKeyStore->del(filename.string(), ::TYPE_ANY, get_user_id(targetUid));
// del() will fail silently if no cached characteristics are present for this alias.
- String8 chr_filename(mKeyStore->getKeyNameForUidWithDir(name8, targetUid,
- ::TYPE_KEY_CHARACTERISTICS));
+ String8 chr_filename(
+ mKeyStore->getKeyNameForUidWithDir(name8, targetUid, ::TYPE_KEY_CHARACTERISTICS));
mKeyStore->del(chr_filename.string(), ::TYPE_KEY_CHARACTERISTICS, get_user_id(targetUid));
}
- return ::NO_ERROR;
+ return ResponseCode::NO_ERROR;
}
-int32_t KeyStoreService::addRngEntropy(const uint8_t* data, size_t dataLength) {
- const auto* device = mKeyStore->getDevice();
- const auto* fallback = mKeyStore->getFallbackDevice();
- int32_t devResult = KM_ERROR_UNIMPLEMENTED;
- int32_t fallbackResult = KM_ERROR_UNIMPLEMENTED;
- if (device->common.module->module_api_version >= KEYMASTER_MODULE_API_VERSION_1_0 &&
- device->add_rng_entropy != NULL) {
- devResult = device->add_rng_entropy(device, data, dataLength);
- }
- if (fallback->add_rng_entropy) {
- fallbackResult = fallback->add_rng_entropy(fallback, data, dataLength);
- }
- if (devResult) {
- return devResult;
- }
- if (fallbackResult) {
- return fallbackResult;
- }
- return ::NO_ERROR;
+KeyStoreServiceReturnCode KeyStoreService::addRngEntropy(const hidl_vec<uint8_t>& entropy) {
+ const auto& device = mKeyStore->getDevice();
+ return KS_HANDLE_HIDL_ERROR(device->addRngEntropy(entropy));
}
-int32_t KeyStoreService::generateKey(const String16& name, const KeymasterArguments& params,
- const uint8_t* entropy, size_t entropyLength, int uid,
- int flags, KeyCharacteristics* outCharacteristics) {
+KeyStoreServiceReturnCode KeyStoreService::generateKey(const String16& name,
+ const hidl_vec<KeyParameter>& params,
+ const hidl_vec<uint8_t>& entropy, int uid,
+ int flags,
+ KeyCharacteristics* outCharacteristics) {
uid = getEffectiveUid(uid);
- int rc = checkBinderPermissionAndKeystoreState(P_INSERT, uid, flags & KEYSTORE_FLAG_ENCRYPTED);
- if (rc != ::NO_ERROR) {
+ KeyStoreServiceReturnCode rc =
+ checkBinderPermissionAndKeystoreState(P_INSERT, uid, flags & KEYSTORE_FLAG_ENCRYPTED);
+ if (!rc.isOk()) {
return rc;
}
- rc = KM_ERROR_UNIMPLEMENTED;
- bool isFallback = false;
- keymaster_key_blob_t blob;
- keymaster_key_characteristics_t out = {{nullptr, 0}, {nullptr, 0}};
-
- const auto* device = mKeyStore->getDevice();
- const auto* fallback = mKeyStore->getFallbackDevice();
- std::vector<keymaster_key_param_t> opParams(params.params);
- const keymaster_key_param_set_t inParams = {opParams.data(), opParams.size()};
- if (device == NULL) {
- return ::SYSTEM_ERROR;
- }
-
- // Capture characteristics before they're potentially stripped by the device
- AuthorizationSet keyCharacteristics(opParams.data(), opParams.size());
- if (keyCharacteristics.is_valid() != AuthorizationSet::Error::OK) {
- return KM_ERROR_MEMORY_ALLOCATION_FAILED;
- }
- UniquePtr<uint8_t[]> kc_buf;
- kc_buf.reset(new (std::nothrow) uint8_t[keyCharacteristics.SerializedSize()]);
- if (!kc_buf.get()) {
- return KM_ERROR_MEMORY_ALLOCATION_FAILED;
- }
- keyCharacteristics.Serialize(kc_buf.get(), kc_buf.get() + keyCharacteristics.SerializedSize());
+ bool usingFallback = false;
+ auto& dev = mKeyStore->getDevice();
+ AuthorizationSet keyCharacteristics = params;
// TODO: Seed from Linux RNG before this.
- if (device->common.module->module_api_version >= KEYMASTER_MODULE_API_VERSION_1_0 &&
- device->generate_key != NULL) {
- if (!entropy) {
- rc = KM_ERROR_OK;
- } else if (device->add_rng_entropy) {
- rc = device->add_rng_entropy(device, entropy, entropyLength);
- } else {
- rc = KM_ERROR_UNIMPLEMENTED;
- }
- if (rc == KM_ERROR_OK) {
- rc =
- device->generate_key(device, &inParams, &blob, outCharacteristics ? &out : nullptr);
- }
- }
- // If the HW device didn't support generate_key or generate_key failed
- // fall back to the software implementation.
- if (rc && fallback->generate_key != NULL) {
- ALOGW("Primary keymaster device failed to generate key, falling back to SW.");
- isFallback = true;
- if (!entropy) {
- rc = KM_ERROR_OK;
- } else if (fallback->add_rng_entropy) {
- rc = fallback->add_rng_entropy(fallback, entropy, entropyLength);
- } else {
- rc = KM_ERROR_UNIMPLEMENTED;
- }
- if (rc == KM_ERROR_OK) {
- rc = fallback->generate_key(fallback, &inParams, &blob,
- outCharacteristics ? &out : nullptr);
- }
- }
-
- if (outCharacteristics) {
- outCharacteristics->characteristics = out;
- }
-
- if (rc) {
+ rc = addRngEntropy(entropy);
+ if (!rc.isOk()) {
return rc;
}
- // Write the key:
- String8 name8(name);
- String8 filename(mKeyStore->getKeyNameForUidWithDir(name8, uid, ::TYPE_KEYMASTER_10));
+ KeyStoreServiceReturnCode error;
+ auto hidl_cb = [&](ErrorCode ret, const hidl_vec<uint8_t>& hidlKeyBlob,
+ const KeyCharacteristics& keyCharacteristics) {
+ error = ret;
+ if (!error.isOk()) {
+ return;
+ }
+ if (outCharacteristics) *outCharacteristics = keyCharacteristics;
- Blob keyBlob(blob.key_material, blob.key_material_size, NULL, 0, ::TYPE_KEYMASTER_10);
- keyBlob.setFallback(isFallback);
- keyBlob.setEncrypted(flags & KEYSTORE_FLAG_ENCRYPTED);
+ // Write the key
+ String8 name8(name);
+ String8 filename(mKeyStore->getKeyNameForUidWithDir(name8, uid, ::TYPE_KEYMASTER_10));
- free(const_cast<uint8_t*>(blob.key_material));
- rc = mKeyStore->put(filename.string(), &keyBlob, get_user_id(uid));
+ Blob keyBlob(&hidlKeyBlob[0], hidlKeyBlob.size(), NULL, 0, ::TYPE_KEYMASTER_10);
+ keyBlob.setFallback(usingFallback);
+ keyBlob.setEncrypted(flags & KEYSTORE_FLAG_ENCRYPTED);
- if (rc != ::NO_ERROR) {
+ error = mKeyStore->put(filename.string(), &keyBlob, get_user_id(uid));
+ };
+
+ rc = KS_HANDLE_HIDL_ERROR(dev->generateKey(params, hidl_cb));
+ if (!rc.isOk()) {
return rc;
}
+ if (!error.isOk()) {
+ ALOGE("Failed to generate key -> falling back to software keymaster");
+ usingFallback = true;
+ auto& fallback = mKeyStore->getFallbackDevice();
+ rc = KS_HANDLE_HIDL_ERROR(fallback->generateKey(params, hidl_cb));
+ if (!rc.isOk()) {
+ return rc;
+ }
+ if (!error.isOk()) {
+ return error;
+ }
+ }
// Write the characteristics:
+ String8 name8(name);
String8 cFilename(mKeyStore->getKeyNameForUidWithDir(name8, uid, ::TYPE_KEY_CHARACTERISTICS));
- Blob charBlob(kc_buf.get(), keyCharacteristics.SerializedSize(),
- NULL, 0, ::TYPE_KEY_CHARACTERISTICS);
- charBlob.setFallback(isFallback);
+ std::stringstream kc_stream;
+ keyCharacteristics.Serialize(&kc_stream);
+ if (kc_stream.bad()) {
+ return ResponseCode::SYSTEM_ERROR;
+ }
+ auto kc_buf = kc_stream.str();
+ Blob charBlob(reinterpret_cast<const uint8_t*>(kc_buf.data()), kc_buf.size(), NULL, 0,
+ ::TYPE_KEY_CHARACTERISTICS);
+ charBlob.setFallback(usingFallback);
charBlob.setEncrypted(flags & KEYSTORE_FLAG_ENCRYPTED);
return mKeyStore->put(cFilename.string(), &charBlob, get_user_id(uid));
}
-int32_t KeyStoreService::getKeyCharacteristics(const String16& name,
- const keymaster_blob_t* clientId,
- const keymaster_blob_t* appData, int32_t uid,
- KeyCharacteristics* outCharacteristics) {
+KeyStoreServiceReturnCode
+KeyStoreService::getKeyCharacteristics(const String16& name, const hidl_vec<uint8_t>& clientId,
+ const hidl_vec<uint8_t>& appData, int32_t uid,
+ KeyCharacteristics* outCharacteristics) {
if (!outCharacteristics) {
- return KM_ERROR_UNEXPECTED_NULL_POINTER;
+ return ErrorCode::UNEXPECTED_NULL_POINTER;
}
uid_t targetUid = getEffectiveUid(uid);
@@ -722,300 +690,309 @@
if (!is_granted_to(callingUid, targetUid)) {
ALOGW("uid %d not permitted to act for uid %d in getKeyCharacteristics", callingUid,
targetUid);
- return ::PERMISSION_DENIED;
+ return ResponseCode::PERMISSION_DENIED;
}
Blob keyBlob;
String8 name8(name);
- int rc;
- ResponseCode responseCode =
+ KeyStoreServiceReturnCode rc =
mKeyStore->getKeyForName(&keyBlob, name8, targetUid, TYPE_KEYMASTER_10);
- if (responseCode != ::NO_ERROR) {
- return responseCode;
+ if (!rc.isOk()) {
+ return rc;
}
- keymaster_key_blob_t key = {keyBlob.getValue(), static_cast<size_t>(keyBlob.getLength())};
- auto* dev = mKeyStore->getDeviceForBlob(keyBlob);
- keymaster_key_characteristics_t out = {};
- if (!dev->get_key_characteristics) {
- ALOGE("device does not implement get_key_characteristics");
- return KM_ERROR_UNIMPLEMENTED;
- }
- rc = dev->get_key_characteristics(dev, &key, clientId, appData, &out);
- if (rc == KM_ERROR_KEY_REQUIRES_UPGRADE) {
- AuthorizationSet upgradeParams;
- if (clientId && clientId->data && clientId->data_length) {
- upgradeParams.push_back(TAG_APPLICATION_ID, *clientId);
+
+ auto hidlKeyBlob = blob2hidlVec(keyBlob);
+ auto& dev = mKeyStore->getDevice(keyBlob);
+
+ KeyStoreServiceReturnCode error;
+
+ auto hidlCb = [&](ErrorCode ret, const KeyCharacteristics& keyCharacteristics) {
+ error = ret;
+ if (!error.isOk()) {
+ return;
}
- if (appData && appData->data && appData->data_length) {
- upgradeParams.push_back(TAG_APPLICATION_DATA, *appData);
+ *outCharacteristics = keyCharacteristics;
+ };
+
+ rc = KS_HANDLE_HIDL_ERROR(dev->getKeyCharacteristics(hidlKeyBlob, clientId, appData, hidlCb));
+ if (!rc.isOk()) {
+ return rc;
+ }
+
+ if (error == ErrorCode::KEY_REQUIRES_UPGRADE) {
+ AuthorizationSet upgradeParams;
+ if (clientId.size()) {
+ upgradeParams.push_back(TAG_APPLICATION_ID, clientId);
+ }
+ if (appData.size()) {
+ upgradeParams.push_back(TAG_APPLICATION_DATA, appData);
}
rc = upgradeKeyBlob(name, targetUid, upgradeParams, &keyBlob);
- if (rc != ::NO_ERROR) {
+ if (!rc.isOk()) {
return rc;
}
- key = {keyBlob.getValue(), static_cast<size_t>(keyBlob.getLength())};
- rc = dev->get_key_characteristics(dev, &key, clientId, appData, &out);
- }
- if (rc != KM_ERROR_OK) {
- return rc;
- }
- outCharacteristics->characteristics = out;
- return ::NO_ERROR;
+ auto upgradedHidlKeyBlob = blob2hidlVec(keyBlob);
+
+ rc = KS_HANDLE_HIDL_ERROR(
+ dev->getKeyCharacteristics(upgradedHidlKeyBlob, clientId, appData, hidlCb));
+ if (!rc.isOk()) {
+ return rc;
+ }
+ // Note that, on success, "error" will have been updated by the hidlCB callback.
+ // So it is fine to return "error" below.
+ }
+ return error;
}
-int32_t KeyStoreService::importKey(const String16& name, const KeymasterArguments& params,
- keymaster_key_format_t format, const uint8_t* keyData,
- size_t keyLength, int uid, int flags,
- KeyCharacteristics* outCharacteristics) {
+KeyStoreServiceReturnCode
+KeyStoreService::importKey(const String16& name, const hidl_vec<KeyParameter>& params,
+ KeyFormat format, const hidl_vec<uint8_t>& keyData, int uid, int flags,
+ KeyCharacteristics* outCharacteristics) {
uid = getEffectiveUid(uid);
- int rc = checkBinderPermissionAndKeystoreState(P_INSERT, uid, flags & KEYSTORE_FLAG_ENCRYPTED);
- if (rc != ::NO_ERROR) {
+ KeyStoreServiceReturnCode rc =
+ checkBinderPermissionAndKeystoreState(P_INSERT, uid, flags & KEYSTORE_FLAG_ENCRYPTED);
+ if (!rc.isOk()) {
return rc;
}
- rc = KM_ERROR_UNIMPLEMENTED;
- bool isFallback = false;
- keymaster_key_blob_t blob;
- keymaster_key_characteristics_t out = {{nullptr, 0}, {nullptr, 0}};
+ bool usingFallback = false;
+ auto& dev = mKeyStore->getDevice();
- const auto* device = mKeyStore->getDevice();
- const auto* fallback = mKeyStore->getFallbackDevice();
- std::vector<keymaster_key_param_t> opParams(params.params);
- const keymaster_key_param_set_t inParams = {opParams.data(), opParams.size()};
- const keymaster_blob_t input = {keyData, keyLength};
- if (device == NULL) {
- return ::SYSTEM_ERROR;
- }
-
- // Capture characteristics before they're potentially stripped
- AuthorizationSet keyCharacteristics(opParams.data(), opParams.size());
- if (keyCharacteristics.is_valid() != AuthorizationSet::Error::OK) {
- return KM_ERROR_MEMORY_ALLOCATION_FAILED;
- }
- UniquePtr<uint8_t[]> kc_buf;
- kc_buf.reset(new (std::nothrow) uint8_t[keyCharacteristics.SerializedSize()]);
- if (!kc_buf.get()) {
- return KM_ERROR_MEMORY_ALLOCATION_FAILED;
- }
- keyCharacteristics.Serialize(kc_buf.get(), kc_buf.get() + keyCharacteristics.SerializedSize());
-
- if (device->common.module->module_api_version >= KEYMASTER_MODULE_API_VERSION_1_0 &&
- device->import_key != NULL) {
- rc = device->import_key(device, &inParams, format, &input, &blob,
- outCharacteristics ? &out : nullptr);
- }
- if (rc && fallback->import_key != NULL) {
- ALOGW("Primary keymaster device failed to import key, falling back to SW.");
- isFallback = true;
- rc = fallback->import_key(fallback, &inParams, format, &input, &blob,
- outCharacteristics ? &out : nullptr);
- }
- if (outCharacteristics) {
- outCharacteristics->characteristics = out;
- }
-
- if (rc) {
- return rc;
- }
-
- // Write the key:
String8 name8(name);
- String8 filename(mKeyStore->getKeyNameForUidWithDir(name8, uid, ::TYPE_KEYMASTER_10));
- Blob keyBlob(blob.key_material, blob.key_material_size, NULL, 0, ::TYPE_KEYMASTER_10);
- keyBlob.setFallback(isFallback);
- keyBlob.setEncrypted(flags & KEYSTORE_FLAG_ENCRYPTED);
+ KeyStoreServiceReturnCode error;
- free(const_cast<uint8_t*>(blob.key_material));
- rc = mKeyStore->put(filename.string(), &keyBlob, get_user_id(uid));
+ auto hidlCb = [&](ErrorCode ret, const hidl_vec<uint8_t>& keyBlob,
+ const KeyCharacteristics& keyCharacteristics) {
+ error = ret;
+ if (!error.isOk()) {
+ return;
+ }
- if (rc != ::NO_ERROR) {
+ if (outCharacteristics) *outCharacteristics = keyCharacteristics;
+
+ // Write the key:
+ String8 filename(mKeyStore->getKeyNameForUidWithDir(name8, uid, ::TYPE_KEYMASTER_10));
+
+ Blob ksBlob(&keyBlob[0], keyBlob.size(), NULL, 0, ::TYPE_KEYMASTER_10);
+ ksBlob.setFallback(usingFallback);
+ ksBlob.setEncrypted(flags & KEYSTORE_FLAG_ENCRYPTED);
+
+ error = mKeyStore->put(filename.string(), &ksBlob, get_user_id(uid));
+ };
+
+ rc = KS_HANDLE_HIDL_ERROR(dev->importKey(params, format, keyData, hidlCb));
+ // possible hidl error
+ if (!rc.isOk()) {
return rc;
}
+ // now check error from callback
+ if (!error.isOk()) {
+ ALOGE("Failed to import key -> falling back to software keymaster");
+ usingFallback = true;
+ auto& fallback = mKeyStore->getFallbackDevice();
+ rc = KS_HANDLE_HIDL_ERROR(fallback->importKey(params, format, keyData, hidlCb));
+ // possible hidl error
+ if (!rc.isOk()) {
+ return rc;
+ }
+ // now check error from callback
+ if (!error.isOk()) {
+ return error;
+ }
+ }
// Write the characteristics:
String8 cFilename(mKeyStore->getKeyNameForUidWithDir(name8, uid, ::TYPE_KEY_CHARACTERISTICS));
- Blob charBlob(kc_buf.get(), keyCharacteristics.SerializedSize(),
- NULL, 0, ::TYPE_KEY_CHARACTERISTICS);
- charBlob.setFallback(isFallback);
+ AuthorizationSet opParams = params;
+ std::stringstream kcStream;
+ opParams.Serialize(&kcStream);
+ if (kcStream.bad()) return ResponseCode::SYSTEM_ERROR;
+ auto kcBuf = kcStream.str();
+
+ Blob charBlob(reinterpret_cast<const uint8_t*>(kcBuf.data()), kcBuf.size(), NULL, 0,
+ ::TYPE_KEY_CHARACTERISTICS);
+ charBlob.setFallback(usingFallback);
charBlob.setEncrypted(flags & KEYSTORE_FLAG_ENCRYPTED);
return mKeyStore->put(cFilename.string(), &charBlob, get_user_id(uid));
}
-void KeyStoreService::exportKey(const String16& name, keymaster_key_format_t format,
- const keymaster_blob_t* clientId, const keymaster_blob_t* appData,
+void KeyStoreService::exportKey(const String16& name, KeyFormat format,
+ const hidl_vec<uint8_t>& clientId, const hidl_vec<uint8_t>& appData,
int32_t uid, ExportResult* result) {
uid_t targetUid = getEffectiveUid(uid);
uid_t callingUid = IPCThreadState::self()->getCallingUid();
if (!is_granted_to(callingUid, targetUid)) {
ALOGW("uid %d not permitted to act for uid %d in exportKey", callingUid, targetUid);
- result->resultCode = ::PERMISSION_DENIED;
+ result->resultCode = ResponseCode::PERMISSION_DENIED;
return;
}
Blob keyBlob;
String8 name8(name);
- int rc;
- ResponseCode responseCode =
- mKeyStore->getKeyForName(&keyBlob, name8, targetUid, TYPE_KEYMASTER_10);
- if (responseCode != ::NO_ERROR) {
- result->resultCode = responseCode;
+ result->resultCode = mKeyStore->getKeyForName(&keyBlob, name8, targetUid, TYPE_KEYMASTER_10);
+ if (!result->resultCode.isOk()) {
return;
}
- keymaster_key_blob_t key;
- key.key_material_size = keyBlob.getLength();
- key.key_material = keyBlob.getValue();
- auto* dev = mKeyStore->getDeviceForBlob(keyBlob);
- if (!dev->export_key) {
- result->resultCode = KM_ERROR_UNIMPLEMENTED;
- return;
- }
- keymaster_blob_t output = {NULL, 0};
- rc = dev->export_key(dev, format, &key, clientId, appData, &output);
- if (rc == KM_ERROR_KEY_REQUIRES_UPGRADE) {
- AuthorizationSet upgradeParams;
- if (clientId && clientId->data && clientId->data_length) {
- upgradeParams.push_back(TAG_APPLICATION_ID, *clientId);
- }
- if (appData && appData->data && appData->data_length) {
- upgradeParams.push_back(TAG_APPLICATION_DATA, *appData);
- }
- rc = upgradeKeyBlob(name, targetUid, upgradeParams, &keyBlob);
- if (rc != ::NO_ERROR) {
- result->resultCode = rc;
+
+ auto key = blob2hidlVec(keyBlob);
+ auto& dev = mKeyStore->getDevice(keyBlob);
+
+ auto hidlCb = [&](ErrorCode ret, const ::android::hardware::hidl_vec<uint8_t>& keyMaterial) {
+ result->resultCode = ret;
+ if (!result->resultCode.isOk()) {
return;
}
- key = {keyBlob.getValue(), static_cast<size_t>(keyBlob.getLength())};
- rc = dev->export_key(dev, format, &key, clientId, appData, &output);
+ result->exportData = keyMaterial;
+ };
+ KeyStoreServiceReturnCode rc =
+ KS_HANDLE_HIDL_ERROR(dev->exportKey(format, key, clientId, appData, hidlCb));
+ // Overwrite result->resultCode only on HIDL error. Otherwise we want the result set in the
+ // callback hidlCb.
+ if (!rc.isOk()) {
+ result->resultCode = rc;
}
- result->exportData.reset(const_cast<uint8_t*>(output.data));
- result->dataLength = output.data_length;
- result->resultCode = rc ? rc : ::NO_ERROR;
+ if (result->resultCode == ErrorCode::KEY_REQUIRES_UPGRADE) {
+ AuthorizationSet upgradeParams;
+ if (clientId.size()) {
+ upgradeParams.push_back(TAG_APPLICATION_ID, clientId);
+ }
+ if (appData.size()) {
+ upgradeParams.push_back(TAG_APPLICATION_DATA, appData);
+ }
+ result->resultCode = upgradeKeyBlob(name, targetUid, upgradeParams, &keyBlob);
+ if (!result->resultCode.isOk()) {
+ return;
+ }
+
+ auto upgradedHidlKeyBlob = blob2hidlVec(keyBlob);
+
+ result->resultCode = KS_HANDLE_HIDL_ERROR(
+ dev->exportKey(format, upgradedHidlKeyBlob, clientId, appData, hidlCb));
+ if (!result->resultCode.isOk()) {
+ return;
+ }
+ }
}
-void KeyStoreService::begin(const sp<IBinder>& appToken, const String16& name,
- keymaster_purpose_t purpose, bool pruneable,
- const KeymasterArguments& params, const uint8_t* entropy,
- size_t entropyLength, int32_t uid, OperationResult* result) {
+static inline void addAuthTokenToParams(AuthorizationSet* params, const HardwareAuthToken* token) {
+ if (token) {
+ params->push_back(TAG_AUTH_TOKEN, authToken2HidlVec(*token));
+ }
+}
+
+void KeyStoreService::begin(const sp<IBinder>& appToken, const String16& name, KeyPurpose purpose,
+ bool pruneable, const hidl_vec<KeyParameter>& params,
+ const hidl_vec<uint8_t>& entropy, int32_t uid,
+ OperationResult* result) {
uid_t callingUid = IPCThreadState::self()->getCallingUid();
uid_t targetUid = getEffectiveUid(uid);
if (!is_granted_to(callingUid, targetUid)) {
ALOGW("uid %d not permitted to act for uid %d in begin", callingUid, targetUid);
- result->resultCode = ::PERMISSION_DENIED;
+ result->resultCode = ResponseCode::PERMISSION_DENIED;
return;
}
if (!pruneable && get_app_id(callingUid) != AID_SYSTEM) {
ALOGE("Non-system uid %d trying to start non-pruneable operation", callingUid);
- result->resultCode = ::PERMISSION_DENIED;
+ result->resultCode = ResponseCode::PERMISSION_DENIED;
return;
}
- if (!checkAllowedOperationParams(params.params)) {
- result->resultCode = KM_ERROR_INVALID_ARGUMENT;
+ if (!checkAllowedOperationParams(params)) {
+ result->resultCode = ErrorCode::INVALID_ARGUMENT;
return;
}
Blob keyBlob;
String8 name8(name);
- ResponseCode responseCode =
- mKeyStore->getKeyForName(&keyBlob, name8, targetUid, TYPE_KEYMASTER_10);
- if (responseCode != ::NO_ERROR) {
- result->resultCode = responseCode;
+ result->resultCode = mKeyStore->getKeyForName(&keyBlob, name8, targetUid, TYPE_KEYMASTER_10);
+ if (!result->resultCode.isOk()) {
return;
}
- keymaster_key_blob_t key;
- key.key_material_size = keyBlob.getLength();
- key.key_material = keyBlob.getValue();
- keymaster_operation_handle_t handle;
- auto* dev = mKeyStore->getDeviceForBlob(keyBlob);
- keymaster_error_t err = KM_ERROR_UNIMPLEMENTED;
- std::vector<keymaster_key_param_t> opParams(params.params);
- Unique_keymaster_key_characteristics characteristics;
- characteristics.reset(new keymaster_key_characteristics_t);
- err = getOperationCharacteristics(key, dev, opParams, characteristics.get());
- if (err == KM_ERROR_KEY_REQUIRES_UPGRADE) {
- int32_t rc = upgradeKeyBlob(name, targetUid,
- AuthorizationSet(opParams.data(), opParams.size()), &keyBlob);
- if (rc != ::NO_ERROR) {
- result->resultCode = rc;
+
+ auto key = blob2hidlVec(keyBlob);
+ auto& dev = mKeyStore->getDevice(keyBlob);
+ AuthorizationSet opParams = params;
+ KeyCharacteristics characteristics;
+ result->resultCode = getOperationCharacteristics(key, &dev, opParams, &characteristics);
+
+ if (result->resultCode == ErrorCode::KEY_REQUIRES_UPGRADE) {
+ result->resultCode = upgradeKeyBlob(name, targetUid, opParams, &keyBlob);
+ if (!result->resultCode.isOk()) {
return;
}
- key = {keyBlob.getValue(), static_cast<size_t>(keyBlob.getLength())};
- err = getOperationCharacteristics(key, dev, opParams, characteristics.get());
+ key = blob2hidlVec(keyBlob);
+ result->resultCode = getOperationCharacteristics(key, &dev, opParams, &characteristics);
}
- if (err) {
- result->resultCode = err;
+ if (!result->resultCode.isOk()) {
return;
}
- const hw_auth_token_t* authToken = NULL;
+
+ const HardwareAuthToken* authToken = NULL;
// Merge these characteristics with the ones cached when the key was generated or imported
Blob charBlob;
AuthorizationSet persistedCharacteristics;
- responseCode = mKeyStore->getKeyForName(&charBlob, name8, targetUid, TYPE_KEY_CHARACTERISTICS);
- if (responseCode == ::NO_ERROR) {
- const uint8_t* serializedCharacteristics = charBlob.getValue();
- persistedCharacteristics.Deserialize(&serializedCharacteristics,
- serializedCharacteristics + charBlob.getLength());
+ result->resultCode =
+ mKeyStore->getKeyForName(&charBlob, name8, targetUid, TYPE_KEY_CHARACTERISTICS);
+ if (result->resultCode.isOk()) {
+ // TODO write one shot stream buffer to avoid copying (twice here)
+ std::string charBuffer(reinterpret_cast<const char*>(charBlob.getValue()),
+ charBlob.getLength());
+ std::stringstream charStream(charBuffer);
+ persistedCharacteristics.Deserialize(&charStream);
} else {
ALOGD("Unable to read cached characteristics for key");
}
// Replace the sw_enforced set with those persisted to disk, minus hw_enforced
- persistedCharacteristics.Union(characteristics.get()->sw_enforced);
- persistedCharacteristics.Difference(characteristics.get()->hw_enforced);
- persistedCharacteristics.CopyToParamSet(&characteristics.get()->sw_enforced);
+ AuthorizationSet softwareEnforced = characteristics.softwareEnforced;
+ AuthorizationSet teeEnforced = characteristics.teeEnforced;
+ persistedCharacteristics.Union(softwareEnforced);
+ persistedCharacteristics.Subtract(teeEnforced);
+ characteristics.softwareEnforced = persistedCharacteristics.hidl_data();
- int32_t authResult = getAuthToken(characteristics.get(), 0, purpose, &authToken,
+ result->resultCode = getAuthToken(characteristics, 0, purpose, &authToken,
/*failOnTokenMissing*/ false);
// If per-operation auth is needed we need to begin the operation and
// the client will need to authorize that operation before calling
// update. Any other auth issues stop here.
- if (authResult != ::NO_ERROR && authResult != ::OP_AUTH_NEEDED) {
- result->resultCode = authResult;
- return;
- }
- addAuthToParams(&opParams, authToken);
+ if (!result->resultCode.isOk() && result->resultCode != ResponseCode::OP_AUTH_NEEDED) return;
+
+ addAuthTokenToParams(&opParams, authToken);
+
// Add entropy to the device first.
- if (entropy) {
- if (dev->add_rng_entropy) {
- err = dev->add_rng_entropy(dev, entropy, entropyLength);
- } else {
- err = KM_ERROR_UNIMPLEMENTED;
- }
- if (err) {
- result->resultCode = err;
+ if (entropy.size()) {
+ result->resultCode = addRngEntropy(entropy);
+ if (!result->resultCode.isOk()) {
return;
}
}
- keymaster_key_param_set_t inParams = {opParams.data(), opParams.size()};
// Create a keyid for this key.
- keymaster::km_id_t keyid;
+ km_id_t keyid;
if (!enforcement_policy.CreateKeyId(key, &keyid)) {
ALOGE("Failed to create a key ID for authorization checking.");
- result->resultCode = KM_ERROR_UNKNOWN_ERROR;
+ result->resultCode = ErrorCode::UNKNOWN_ERROR;
return;
}
// Check that all key authorization policy requirements are met.
- keymaster::AuthorizationSet key_auths(characteristics->hw_enforced);
- key_auths.push_back(characteristics->sw_enforced);
- keymaster::AuthorizationSet operation_params(inParams);
- err = enforcement_policy.AuthorizeOperation(purpose, keyid, key_auths, operation_params,
- 0 /* op_handle */, true /* is_begin_operation */);
- if (err) {
- result->resultCode = err;
+ AuthorizationSet key_auths = characteristics.teeEnforced;
+ key_auths.append(&characteristics.softwareEnforced[0],
+ &characteristics.softwareEnforced[characteristics.softwareEnforced.size()]);
+
+ result->resultCode = enforcement_policy.AuthorizeOperation(
+ purpose, keyid, key_auths, opParams, 0 /* op_handle */, true /* is_begin_operation */);
+ if (!result->resultCode.isOk()) {
return;
}
- keymaster_key_param_set_t outParams = {NULL, 0};
-
// If there are more than MAX_OPERATIONS, abort the oldest operation that was started as
// pruneable.
while (mOperationMap.getOperationCount() >= MAX_OPERATIONS) {
@@ -1025,27 +1002,42 @@
}
}
- err = dev->begin(dev, purpose, &key, &inParams, &outParams, &handle);
- if (err != KM_ERROR_OK) {
- ALOGE("Got error %d from begin()", err);
+ auto hidlCb = [&](ErrorCode ret, const hidl_vec<KeyParameter>& outParams,
+ uint64_t operationHandle) {
+ result->resultCode = ret;
+ if (!result->resultCode.isOk()) {
+ return;
+ }
+ result->handle = operationHandle;
+ result->outParams = outParams;
+ };
+
+ ErrorCode rc = KS_HANDLE_HIDL_ERROR(dev->begin(purpose, key, opParams.hidl_data(), hidlCb));
+ if (rc != ErrorCode::OK) {
+ ALOGW("Got error %d from begin()", rc);
}
// If there are too many operations abort the oldest operation that was
// started as pruneable and try again.
- while (err == KM_ERROR_TOO_MANY_OPERATIONS && mOperationMap.hasPruneableOperation()) {
- ALOGE("Ran out of operation handles");
+ while (rc == ErrorCode::TOO_MANY_OPERATIONS && mOperationMap.hasPruneableOperation()) {
+ ALOGW("Ran out of operation handles");
if (!pruneOperation()) {
break;
}
- err = dev->begin(dev, purpose, &key, &inParams, &outParams, &handle);
+ rc = KS_HANDLE_HIDL_ERROR(dev->begin(purpose, key, opParams.hidl_data(), hidlCb));
}
- if (err) {
- result->resultCode = err;
+ if (rc != ErrorCode::OK) {
+ result->resultCode = rc;
return;
}
- sp<IBinder> operationToken = mOperationMap.addOperation(handle, keyid, purpose, dev, appToken,
- characteristics.release(), pruneable);
+ // Note: The operation map takes possession of the contents of "characteristics".
+ // It is safe to use characteristics after the following line but it will be empty.
+ sp<IBinder> operationToken = mOperationMap.addOperation(
+ result->handle, keyid, purpose, dev, appToken, std::move(characteristics), pruneable);
+ assert(characteristics.teeEnforced.size() == 0);
+ assert(characteristics.softwareEnforced.size() == 0);
+
if (authToken) {
mOperationMap.setOperationAuthToken(operationToken, authToken);
}
@@ -1054,241 +1046,251 @@
// application should get an auth token using the handle before the
// first call to update, which will fail if keystore hasn't received the
// auth token.
- result->resultCode = authResult;
+ // All fields but "token" were set in the begin operation's callback.
result->token = operationToken;
- result->handle = handle;
- if (outParams.params) {
- result->outParams.params.assign(outParams.params, outParams.params + outParams.length);
- free(outParams.params);
- }
}
-void KeyStoreService::update(const sp<IBinder>& token, const KeymasterArguments& params,
- const uint8_t* data, size_t dataLength, OperationResult* result) {
- if (!checkAllowedOperationParams(params.params)) {
- result->resultCode = KM_ERROR_INVALID_ARGUMENT;
+void KeyStoreService::update(const sp<IBinder>& token, const hidl_vec<KeyParameter>& params,
+ const hidl_vec<uint8_t>& data, OperationResult* result) {
+ if (!checkAllowedOperationParams(params)) {
+ result->resultCode = ErrorCode::INVALID_ARGUMENT;
return;
}
- const keymaster2_device_t* dev;
- keymaster_operation_handle_t handle;
- keymaster_purpose_t purpose;
- keymaster::km_id_t keyid;
- const keymaster_key_characteristics_t* characteristics;
+ km_device_t dev;
+ uint64_t handle;
+ KeyPurpose purpose;
+ km_id_t keyid;
+ const KeyCharacteristics* characteristics;
if (!mOperationMap.getOperation(token, &handle, &keyid, &purpose, &dev, &characteristics)) {
- result->resultCode = KM_ERROR_INVALID_OPERATION_HANDLE;
+ result->resultCode = ErrorCode::INVALID_OPERATION_HANDLE;
return;
}
- std::vector<keymaster_key_param_t> opParams(params.params);
- int32_t authResult = addOperationAuthTokenIfNeeded(token, &opParams);
- if (authResult != ::NO_ERROR) {
- result->resultCode = authResult;
+ AuthorizationSet opParams = params;
+ result->resultCode = addOperationAuthTokenIfNeeded(token, &opParams);
+ if (!result->resultCode.isOk()) {
return;
}
- keymaster_key_param_set_t inParams = {opParams.data(), opParams.size()};
- keymaster_blob_t input = {data, dataLength};
- size_t consumed = 0;
- keymaster_blob_t output = {NULL, 0};
- keymaster_key_param_set_t outParams = {NULL, 0};
// Check that all key authorization policy requirements are met.
- keymaster::AuthorizationSet key_auths(characteristics->hw_enforced);
- key_auths.push_back(characteristics->sw_enforced);
- keymaster::AuthorizationSet operation_params(inParams);
+ AuthorizationSet key_auths(characteristics->teeEnforced);
+ key_auths.append(&characteristics->softwareEnforced[0],
+ &characteristics->softwareEnforced[characteristics->softwareEnforced.size()]);
result->resultCode = enforcement_policy.AuthorizeOperation(
- purpose, keyid, key_auths, operation_params, handle, false /* is_begin_operation */);
- if (result->resultCode) {
+ purpose, keyid, key_auths, opParams, handle, false /* is_begin_operation */);
+ if (!result->resultCode.isOk()) {
return;
}
- keymaster_error_t err =
- dev->update(dev, handle, &inParams, &input, &consumed, &outParams, &output);
- result->data.reset(const_cast<uint8_t*>(output.data));
- result->dataLength = output.data_length;
- result->inputConsumed = consumed;
- result->resultCode = err ? (int32_t)err : ::NO_ERROR;
- if (outParams.params) {
- result->outParams.params.assign(outParams.params, outParams.params + outParams.length);
- free(outParams.params);
+ auto hidlCb = [&](ErrorCode ret, uint32_t inputConsumed,
+ const hidl_vec<KeyParameter>& outParams, const hidl_vec<uint8_t>& output) {
+ result->resultCode = ret;
+ if (!result->resultCode.isOk()) {
+ return;
+ }
+ result->inputConsumed = inputConsumed;
+ result->outParams = outParams;
+ result->data = output;
+ };
+
+ KeyStoreServiceReturnCode rc = KS_HANDLE_HIDL_ERROR(dev->update(handle, params, data, hidlCb));
+ // just a reminder: on success result->resultCode was set in the callback. So we only overwrite
+ // it if there was a communication error indicated by the ErrorCode.
+ if (!rc.isOk()) {
+ result->resultCode = rc;
}
}
-void KeyStoreService::finish(const sp<IBinder>& token, const KeymasterArguments& params,
- const uint8_t* signature, size_t signatureLength,
- const uint8_t* entropy, size_t entropyLength,
+void KeyStoreService::finish(const sp<IBinder>& token, const hidl_vec<KeyParameter>& params,
+ const hidl_vec<uint8_t>& signature, const hidl_vec<uint8_t>& entropy,
OperationResult* result) {
- if (!checkAllowedOperationParams(params.params)) {
- result->resultCode = KM_ERROR_INVALID_ARGUMENT;
+ if (!checkAllowedOperationParams(params)) {
+ result->resultCode = ErrorCode::INVALID_ARGUMENT;
return;
}
- const keymaster2_device_t* dev;
- keymaster_operation_handle_t handle;
- keymaster_purpose_t purpose;
- keymaster::km_id_t keyid;
- const keymaster_key_characteristics_t* characteristics;
+ km_device_t dev;
+ uint64_t handle;
+ KeyPurpose purpose;
+ km_id_t keyid;
+ const KeyCharacteristics* characteristics;
if (!mOperationMap.getOperation(token, &handle, &keyid, &purpose, &dev, &characteristics)) {
- result->resultCode = KM_ERROR_INVALID_OPERATION_HANDLE;
+ result->resultCode = ErrorCode::INVALID_OPERATION_HANDLE;
return;
}
- std::vector<keymaster_key_param_t> opParams(params.params);
- int32_t authResult = addOperationAuthTokenIfNeeded(token, &opParams);
- if (authResult != ::NO_ERROR) {
- result->resultCode = authResult;
+ AuthorizationSet opParams = params;
+ result->resultCode = addOperationAuthTokenIfNeeded(token, &opParams);
+ if (!result->resultCode.isOk()) {
return;
}
- keymaster_error_t err;
- if (entropy) {
- if (dev->add_rng_entropy) {
- err = dev->add_rng_entropy(dev, entropy, entropyLength);
- } else {
- err = KM_ERROR_UNIMPLEMENTED;
- }
- if (err) {
- result->resultCode = err;
+
+ if (entropy.size()) {
+ result->resultCode = addRngEntropy(entropy);
+ if (!result->resultCode.isOk()) {
return;
}
}
- keymaster_key_param_set_t inParams = {opParams.data(), opParams.size()};
- keymaster_blob_t input = {nullptr, 0};
- keymaster_blob_t sig = {signature, signatureLength};
- keymaster_blob_t output = {nullptr, 0};
- keymaster_key_param_set_t outParams = {nullptr, 0};
-
// Check that all key authorization policy requirements are met.
- keymaster::AuthorizationSet key_auths(characteristics->hw_enforced);
- key_auths.push_back(characteristics->sw_enforced);
- keymaster::AuthorizationSet operation_params(inParams);
- err = enforcement_policy.AuthorizeOperation(purpose, keyid, key_auths, operation_params, handle,
- false /* is_begin_operation */);
- if (err) {
- result->resultCode = err;
- return;
- }
+ AuthorizationSet key_auths(characteristics->teeEnforced);
+ key_auths.append(&characteristics->softwareEnforced[0],
+ &characteristics->softwareEnforced[characteristics->softwareEnforced.size()]);
+ result->resultCode = enforcement_policy.AuthorizeOperation(
+ purpose, keyid, key_auths, opParams, handle, false /* is_begin_operation */);
+ if (!result->resultCode.isOk()) return;
- err =
- dev->finish(dev, handle, &inParams, &input /* TODO(swillden): wire up input to finish() */,
- &sig, &outParams, &output);
+ auto hidlCb = [&](ErrorCode ret, const hidl_vec<KeyParameter>& outParams,
+ const hidl_vec<uint8_t>& output) {
+ result->resultCode = ret;
+ if (!result->resultCode.isOk()) {
+ return;
+ }
+ result->outParams = outParams;
+ result->data = output;
+ };
+
+ KeyStoreServiceReturnCode rc = KS_HANDLE_HIDL_ERROR(dev->finish(
+ handle, opParams.hidl_data(),
+ hidl_vec<uint8_t>() /* TODO(swillden): wire up input to finish() */, signature, hidlCb));
// Remove the operation regardless of the result
mOperationMap.removeOperation(token);
mAuthTokenTable.MarkCompleted(handle);
- result->data.reset(const_cast<uint8_t*>(output.data));
- result->dataLength = output.data_length;
- result->resultCode = err ? (int32_t)err : ::NO_ERROR;
- if (outParams.params) {
- result->outParams.params.assign(outParams.params, outParams.params + outParams.length);
- free(outParams.params);
+ // just a reminder: on success result->resultCode was set in the callback. So we only overwrite
+ // it if there was a communication error indicated by the ErrorCode.
+ if (!rc.isOk()) {
+ result->resultCode = rc;
}
}
-int32_t KeyStoreService::abort(const sp<IBinder>& token) {
- const keymaster2_device_t* dev;
- keymaster_operation_handle_t handle;
- keymaster_purpose_t purpose;
- keymaster::km_id_t keyid;
+KeyStoreServiceReturnCode KeyStoreService::abort(const sp<IBinder>& token) {
+ km_device_t dev;
+ uint64_t handle;
+ KeyPurpose purpose;
+ km_id_t keyid;
if (!mOperationMap.getOperation(token, &handle, &keyid, &purpose, &dev, NULL)) {
- return KM_ERROR_INVALID_OPERATION_HANDLE;
+ return ErrorCode::INVALID_OPERATION_HANDLE;
}
mOperationMap.removeOperation(token);
- int32_t rc;
- if (!dev->abort) {
- rc = KM_ERROR_UNIMPLEMENTED;
- } else {
- rc = dev->abort(dev, handle);
- }
+
+ ErrorCode rc = KS_HANDLE_HIDL_ERROR(dev->abort(handle));
mAuthTokenTable.MarkCompleted(handle);
- if (rc) {
- return rc;
- }
- return ::NO_ERROR;
+ return rc;
}
bool KeyStoreService::isOperationAuthorized(const sp<IBinder>& token) {
- const keymaster2_device_t* dev;
- keymaster_operation_handle_t handle;
- const keymaster_key_characteristics_t* characteristics;
- keymaster_purpose_t purpose;
- keymaster::km_id_t keyid;
+ km_device_t dev;
+ uint64_t handle;
+ const KeyCharacteristics* characteristics;
+ KeyPurpose purpose;
+ km_id_t keyid;
if (!mOperationMap.getOperation(token, &handle, &keyid, &purpose, &dev, &characteristics)) {
return false;
}
- const hw_auth_token_t* authToken = NULL;
+ const HardwareAuthToken* authToken = NULL;
mOperationMap.getOperationAuthToken(token, &authToken);
- std::vector<keymaster_key_param_t> ignored;
- int32_t authResult = addOperationAuthTokenIfNeeded(token, &ignored);
- return authResult == ::NO_ERROR;
+ AuthorizationSet ignored;
+ auto authResult = addOperationAuthTokenIfNeeded(token, &ignored);
+ return authResult.isOk();
}
-int32_t KeyStoreService::addAuthToken(const uint8_t* token, size_t length) {
+KeyStoreServiceReturnCode KeyStoreService::addAuthToken(const uint8_t* token, size_t length) {
+ // TODO(swillden): When gatekeeper and fingerprint are ready, this should be updated to
+ // receive a HardwareAuthToken, rather than an opaque byte array.
+
if (!checkBinderPermission(P_ADD_AUTH)) {
ALOGW("addAuthToken: permission denied for %d", IPCThreadState::self()->getCallingUid());
- return ::PERMISSION_DENIED;
+ return ResponseCode::PERMISSION_DENIED;
}
if (length != sizeof(hw_auth_token_t)) {
- return KM_ERROR_INVALID_ARGUMENT;
+ return ErrorCode::INVALID_ARGUMENT;
}
- hw_auth_token_t* authToken = new hw_auth_token_t;
- memcpy(reinterpret_cast<void*>(authToken), token, sizeof(hw_auth_token_t));
+
+ hw_auth_token_t authToken;
+ memcpy(reinterpret_cast<void*>(&authToken), token, sizeof(hw_auth_token_t));
+ if (authToken.version != 0) {
+ return ErrorCode::INVALID_ARGUMENT;
+ }
+
+ std::unique_ptr<HardwareAuthToken> hidlAuthToken(new HardwareAuthToken);
+ hidlAuthToken->challenge = authToken.challenge;
+ hidlAuthToken->userId = authToken.user_id;
+ hidlAuthToken->authenticatorId = authToken.authenticator_id;
+ hidlAuthToken->authenticatorType = authToken.authenticator_type;
+ hidlAuthToken->timestamp = authToken.timestamp;
+ static_assert(
+ std::is_same<decltype(hidlAuthToken->hmac),
+ ::android::hardware::hidl_array<uint8_t, sizeof(authToken.hmac)>>::value,
+ "This function assumes token HMAC is 32 bytes, but it might not be.");
+ std::copy(authToken.hmac, authToken.hmac + sizeof(authToken.hmac), hidlAuthToken->hmac.data());
+
// The table takes ownership of authToken.
- mAuthTokenTable.AddAuthenticationToken(authToken);
- return ::NO_ERROR;
+ mAuthTokenTable.AddAuthenticationToken(hidlAuthToken.release());
+ return ResponseCode::NO_ERROR;
}
constexpr size_t KEY_ATTESTATION_APPLICATION_ID_MAX_SIZE = 1024;
-int32_t KeyStoreService::attestKey(const String16& name, const KeymasterArguments& params,
- KeymasterCertificateChain* outChain) {
- if (!outChain) return KM_ERROR_OUTPUT_PARAMETER_NULL;
+KeyStoreServiceReturnCode KeyStoreService::attestKey(const String16& name,
+ const hidl_vec<KeyParameter>& params,
+ hidl_vec<hidl_vec<uint8_t>>* outChain) {
+ if (!outChain) {
+ return ErrorCode::OUTPUT_PARAMETER_NULL;
+ }
- if (!checkAllowedOperationParams(params.params)) {
- return KM_ERROR_INVALID_ARGUMENT;
+ if (!checkAllowedOperationParams(params)) {
+ return ErrorCode::INVALID_ARGUMENT;
}
uid_t callingUid = IPCThreadState::self()->getCallingUid();
Blob keyBlob;
String8 name8(name);
- ResponseCode responseCode =
+ KeyStoreServiceReturnCode responseCode =
mKeyStore->getKeyForName(&keyBlob, name8, callingUid, TYPE_KEYMASTER_10);
- if (responseCode != ::NO_ERROR) {
+ if (!responseCode.isOk()) {
return responseCode;
}
- keymaster_key_blob_t key = {keyBlob.getValue(),
- static_cast<size_t>(std::max(0, keyBlob.getLength()))};
- auto* dev = mKeyStore->getDeviceForBlob(keyBlob);
- if (!dev->attest_key) return KM_ERROR_UNIMPLEMENTED;
-
auto asn1_attestation_id_result = security::gather_attestation_application_id(callingUid);
if (!asn1_attestation_id_result.isOk()) {
ALOGE("failed to gather attestation_id");
- return KM_ERROR_ATTESTATION_APPLICATION_ID_MISSING;
+ return ErrorCode::ATTESTATION_APPLICATION_ID_MISSING;
}
- const std::vector<uint8_t>& asn1_attestation_id = asn1_attestation_id_result;
+ std::vector<uint8_t>& asn1_attestation_id = asn1_attestation_id_result;
/*
- * Make a mutable copy of the params vector which to append the attestation id to.
- * The copy is shallow, and the lifetime of the inner objects is the calling scope.
+ * The attestation application ID cannot be longer than
+ * KEY_ATTESTATION_APPLICATION_ID_MAX_SIZE, so we truncate if too long.
*/
- auto mutable_params = params.params;
+ if (asn1_attestation_id.size() > KEY_ATTESTATION_APPLICATION_ID_MAX_SIZE)
+ asn1_attestation_id.resize(KEY_ATTESTATION_APPLICATION_ID_MAX_SIZE);
- mutable_params.push_back(
- {.tag = KM_TAG_ATTESTATION_APPLICATION_ID,
- .blob = {asn1_attestation_id.data(),
- std::min(asn1_attestation_id.size(), KEY_ATTESTATION_APPLICATION_ID_MAX_SIZE)}});
+ AuthorizationSet mutableParams = params;
- const keymaster_key_param_set_t in_params = {
- const_cast<keymaster_key_param_t*>(mutable_params.data()), mutable_params.size()};
- outChain->chain = {nullptr, 0};
- int32_t rc = dev->attest_key(dev, &key, &in_params, &outChain->chain);
- if (rc) return rc;
- return ::NO_ERROR;
+ mutableParams.push_back(TAG_ATTESTATION_APPLICATION_ID, blob2hidlVec(asn1_attestation_id));
+
+ KeyStoreServiceReturnCode error;
+ auto hidlCb = [&](ErrorCode ret, const hidl_vec<hidl_vec<uint8_t>>& certChain) {
+ error = ret;
+ if (!error.isOk()) {
+ return;
+ }
+ if (outChain) *outChain = certChain;
+ };
+
+ auto hidlKey = blob2hidlVec(keyBlob);
+ auto& dev = mKeyStore->getDevice(keyBlob);
+ KeyStoreServiceReturnCode rc =
+ KS_HANDLE_HIDL_ERROR(dev->attestKey(hidlKey, mutableParams.hidl_data(), hidlCb));
+ if (!rc.isOk()) {
+ return rc;
+ }
+ return error;
}
-int32_t KeyStoreService::onDeviceOffBody() {
+KeyStoreServiceReturnCode KeyStoreService::onDeviceOffBody() {
// TODO(tuckeris): add permission check. This should be callable from ClockworkHome only.
mAuthTokenTable.onDeviceOffBody();
- return ::NO_ERROR;
+ return ResponseCode::NO_ERROR;
}
/**
@@ -1375,17 +1377,19 @@
* otherwise the state of keystore when not unlocked and checkUnlocked is
* true.
*/
-int32_t KeyStoreService::checkBinderPermissionAndKeystoreState(perm_t permission, int32_t targetUid,
- bool checkUnlocked) {
+KeyStoreServiceReturnCode
+KeyStoreService::checkBinderPermissionAndKeystoreState(perm_t permission, int32_t targetUid,
+ bool checkUnlocked) {
if (!checkBinderPermission(permission, targetUid)) {
- return ::PERMISSION_DENIED;
+ return ResponseCode::PERMISSION_DENIED;
}
State state = mKeyStore->getState(get_user_id(getEffectiveUid(targetUid)));
if (checkUnlocked && !isKeystoreUnlocked(state)) {
- return state;
+ // All State values coincide with ResponseCodes
+ return static_cast<ResponseCode>(state);
}
- return ::NO_ERROR;
+ return ResponseCode::NO_ERROR;
}
bool KeyStoreService::isKeystoreUnlocked(State state) {
@@ -1399,45 +1403,16 @@
return false;
}
-bool KeyStoreService::isKeyTypeSupported(const keymaster2_device_t* device,
- keymaster_keypair_t keyType) {
- const int32_t device_api = device->common.module->module_api_version;
- if (device_api == KEYMASTER_MODULE_API_VERSION_0_2) {
- switch (keyType) {
- case TYPE_RSA:
- case TYPE_DSA:
- case TYPE_EC:
- return true;
- default:
- return false;
- }
- } else if (device_api >= KEYMASTER_MODULE_API_VERSION_0_3) {
- switch (keyType) {
- case TYPE_RSA:
- return true;
- case TYPE_DSA:
- return device->flags & KEYMASTER_SUPPORTS_DSA;
- case TYPE_EC:
- return device->flags & KEYMASTER_SUPPORTS_EC;
- default:
- return false;
- }
- } else {
- return keyType == TYPE_RSA;
- }
-}
-
/**
- * Check that all keymaster_key_param_t's provided by the application are
+ * Check that all KeyParameter's provided by the application are
* allowed. Any parameter that keystore adds itself should be disallowed here.
*/
-bool KeyStoreService::checkAllowedOperationParams(
- const std::vector<keymaster_key_param_t>& params) {
- for (auto param : params) {
- switch (param.tag) {
- case KM_TAG_AUTH_TOKEN:
+bool KeyStoreService::checkAllowedOperationParams(const hidl_vec<KeyParameter>& params) {
+ for (size_t i = 0; i < params.size(); ++i) {
+ switch (params[i].tag) {
+ case Tag::AUTH_TOKEN:
// fall through intended
- case KM_TAG_ATTESTATION_APPLICATION_ID:
+ case Tag::ATTESTATION_APPLICATION_ID:
return false;
default:
break;
@@ -1446,30 +1421,32 @@
return true;
}
-keymaster_error_t KeyStoreService::getOperationCharacteristics(
- const keymaster_key_blob_t& key, const keymaster2_device_t* dev,
- const std::vector<keymaster_key_param_t>& params, keymaster_key_characteristics_t* out) {
- UniquePtr<keymaster_blob_t> appId;
- UniquePtr<keymaster_blob_t> appData;
+ErrorCode KeyStoreService::getOperationCharacteristics(const hidl_vec<uint8_t>& key,
+ km_device_t* dev,
+ const AuthorizationSet& params,
+ KeyCharacteristics* out) {
+ hidl_vec<uint8_t> appId;
+ hidl_vec<uint8_t> appData;
for (auto param : params) {
- if (param.tag == KM_TAG_APPLICATION_ID) {
- appId.reset(new keymaster_blob_t);
- appId->data = param.blob.data;
- appId->data_length = param.blob.data_length;
- } else if (param.tag == KM_TAG_APPLICATION_DATA) {
- appData.reset(new keymaster_blob_t);
- appData->data = param.blob.data;
- appData->data_length = param.blob.data_length;
+ if (param.tag == Tag::APPLICATION_ID) {
+ appId = authorizationValue(TAG_APPLICATION_ID, param).value();
+ } else if (param.tag == Tag::APPLICATION_DATA) {
+ appData = authorizationValue(TAG_APPLICATION_DATA, param).value();
}
}
- keymaster_key_characteristics_t result = {{nullptr, 0}, {nullptr, 0}};
- if (!dev->get_key_characteristics) {
- return KM_ERROR_UNIMPLEMENTED;
- }
- keymaster_error_t error =
- dev->get_key_characteristics(dev, &key, appId.get(), appData.get(), &result);
- if (error == KM_ERROR_OK) {
- *out = result;
+ ErrorCode error = ErrorCode::OK;
+
+ auto hidlCb = [&](ErrorCode ret, const KeyCharacteristics& keyCharacteristics) {
+ error = ret;
+ if (error != ErrorCode::OK) {
+ return;
+ }
+ if (out) *out = keyCharacteristics;
+ };
+
+ ErrorCode rc = KS_HANDLE_HIDL_ERROR((*dev)->getKeyCharacteristics(key, appId, appData, hidlCb));
+ if (rc != ErrorCode::OK) {
+ return rc;
}
return error;
}
@@ -1477,49 +1454,41 @@
/**
* Get the auth token for this operation from the auth token table.
*
- * Returns ::NO_ERROR if the auth token was set or none was required.
+ * Returns ResponseCode::NO_ERROR if the auth token was set or none was required.
* ::OP_AUTH_NEEDED if it is a per op authorization, no
* authorization token exists for that operation and
* failOnTokenMissing is false.
* KM_ERROR_KEY_USER_NOT_AUTHENTICATED if there is no valid auth
* token for the operation
*/
-int32_t KeyStoreService::getAuthToken(const keymaster_key_characteristics_t* characteristics,
- keymaster_operation_handle_t handle,
- keymaster_purpose_t purpose,
- const hw_auth_token_t** authToken, bool failOnTokenMissing) {
+KeyStoreServiceReturnCode KeyStoreService::getAuthToken(const KeyCharacteristics& characteristics,
+ uint64_t handle, KeyPurpose purpose,
+ const HardwareAuthToken** authToken,
+ bool failOnTokenMissing) {
- std::vector<keymaster_key_param_t> allCharacteristics;
- for (size_t i = 0; i < characteristics->sw_enforced.length; i++) {
- allCharacteristics.push_back(characteristics->sw_enforced.params[i]);
+ AuthorizationSet allCharacteristics;
+ for (size_t i = 0; i < characteristics.softwareEnforced.size(); i++) {
+ allCharacteristics.push_back(characteristics.softwareEnforced[i]);
}
- for (size_t i = 0; i < characteristics->hw_enforced.length; i++) {
- allCharacteristics.push_back(characteristics->hw_enforced.params[i]);
+ for (size_t i = 0; i < characteristics.teeEnforced.size(); i++) {
+ allCharacteristics.push_back(characteristics.teeEnforced[i]);
}
- keymaster::AuthTokenTable::Error err = mAuthTokenTable.FindAuthorization(
- allCharacteristics.data(), allCharacteristics.size(), purpose, handle, authToken);
+ AuthTokenTable::Error err =
+ mAuthTokenTable.FindAuthorization(allCharacteristics, purpose, handle, authToken);
switch (err) {
- case keymaster::AuthTokenTable::OK:
- case keymaster::AuthTokenTable::AUTH_NOT_REQUIRED:
- return ::NO_ERROR;
- case keymaster::AuthTokenTable::AUTH_TOKEN_NOT_FOUND:
- case keymaster::AuthTokenTable::AUTH_TOKEN_EXPIRED:
- case keymaster::AuthTokenTable::AUTH_TOKEN_WRONG_SID:
- return KM_ERROR_KEY_USER_NOT_AUTHENTICATED;
- case keymaster::AuthTokenTable::OP_HANDLE_REQUIRED:
- return failOnTokenMissing ? (int32_t)KM_ERROR_KEY_USER_NOT_AUTHENTICATED
- : (int32_t)::OP_AUTH_NEEDED;
+ case AuthTokenTable::OK:
+ case AuthTokenTable::AUTH_NOT_REQUIRED:
+ return ResponseCode::NO_ERROR;
+ case AuthTokenTable::AUTH_TOKEN_NOT_FOUND:
+ case AuthTokenTable::AUTH_TOKEN_EXPIRED:
+ case AuthTokenTable::AUTH_TOKEN_WRONG_SID:
+ return ErrorCode::KEY_USER_NOT_AUTHENTICATED;
+ case AuthTokenTable::OP_HANDLE_REQUIRED:
+ return failOnTokenMissing ? KeyStoreServiceReturnCode(ErrorCode::KEY_USER_NOT_AUTHENTICATED)
+ : KeyStoreServiceReturnCode(ResponseCode::OP_AUTH_NEEDED);
default:
ALOGE("Unexpected FindAuthorization return value %d", err);
- return KM_ERROR_INVALID_ARGUMENT;
- }
-}
-
-inline void KeyStoreService::addAuthToParams(std::vector<keymaster_key_param_t>* params,
- const hw_auth_token_t* token) {
- if (token) {
- params->push_back(keymaster_param_blob(
- KM_TAG_AUTH_TOKEN, reinterpret_cast<const uint8_t*>(token), sizeof(hw_auth_token_t)));
+ return ErrorCode::INVALID_ARGUMENT;
}
}
@@ -1528,185 +1497,194 @@
* requires authorization. Uses the cached result in the OperationMap if available
* otherwise gets the token from the AuthTokenTable and caches the result.
*
- * Returns ::NO_ERROR if the auth token was added or not needed.
+ * Returns ResponseCode::NO_ERROR if the auth token was added or not needed.
* KM_ERROR_KEY_USER_NOT_AUTHENTICATED if the operation is not
* authenticated.
* KM_ERROR_INVALID_OPERATION_HANDLE if token is not a valid
* operation token.
*/
-int32_t KeyStoreService::addOperationAuthTokenIfNeeded(const sp<IBinder>& token,
- std::vector<keymaster_key_param_t>* params) {
- const hw_auth_token_t* authToken = NULL;
+KeyStoreServiceReturnCode KeyStoreService::addOperationAuthTokenIfNeeded(const sp<IBinder>& token,
+ AuthorizationSet* params) {
+ const HardwareAuthToken* authToken = nullptr;
mOperationMap.getOperationAuthToken(token, &authToken);
if (!authToken) {
- const keymaster2_device_t* dev;
- keymaster_operation_handle_t handle;
- const keymaster_key_characteristics_t* characteristics = NULL;
- keymaster_purpose_t purpose;
- keymaster::km_id_t keyid;
+ km_device_t dev;
+ uint64_t handle;
+ const KeyCharacteristics* characteristics = nullptr;
+ KeyPurpose purpose;
+ km_id_t keyid;
if (!mOperationMap.getOperation(token, &handle, &keyid, &purpose, &dev, &characteristics)) {
- return KM_ERROR_INVALID_OPERATION_HANDLE;
+ return ErrorCode::INVALID_OPERATION_HANDLE;
}
- int32_t result = getAuthToken(characteristics, handle, purpose, &authToken);
- if (result != ::NO_ERROR) {
+ auto result = getAuthToken(*characteristics, handle, purpose, &authToken);
+ if (!result.isOk()) {
return result;
}
if (authToken) {
mOperationMap.setOperationAuthToken(token, authToken);
}
}
- addAuthToParams(params, authToken);
- return ::NO_ERROR;
+ addAuthTokenToParams(params, authToken);
+ return ResponseCode::NO_ERROR;
}
/**
* Translate a result value to a legacy return value. All keystore errors are
* preserved and keymaster errors become SYSTEM_ERRORs
*/
-int32_t KeyStoreService::translateResultToLegacyResult(int32_t result) {
+KeyStoreServiceReturnCode KeyStoreService::translateResultToLegacyResult(int32_t result) {
if (result > 0) {
- return result;
+ return static_cast<ResponseCode>(result);
}
- return ::SYSTEM_ERROR;
+ return ResponseCode::SYSTEM_ERROR;
}
-keymaster_key_param_t*
-KeyStoreService::getKeyAlgorithm(keymaster_key_characteristics_t* characteristics) {
- for (size_t i = 0; i < characteristics->hw_enforced.length; i++) {
- if (characteristics->hw_enforced.params[i].tag == KM_TAG_ALGORITHM) {
- return &characteristics->hw_enforced.params[i];
- }
+static NullOr<const Algorithm&>
+getKeyAlgoritmFromKeyCharacteristics(const KeyCharacteristics& characteristics) {
+ for (size_t i = 0; i < characteristics.teeEnforced.size(); ++i) {
+ auto algo = authorizationValue(TAG_ALGORITHM, characteristics.teeEnforced[i]);
+ if (algo.isOk()) return algo.value();
}
- for (size_t i = 0; i < characteristics->sw_enforced.length; i++) {
- if (characteristics->sw_enforced.params[i].tag == KM_TAG_ALGORITHM) {
- return &characteristics->sw_enforced.params[i];
- }
+ for (size_t i = 0; i < characteristics.softwareEnforced.size(); ++i) {
+ auto algo = authorizationValue(TAG_ALGORITHM, characteristics.softwareEnforced[i]);
+ if (algo.isOk()) return algo.value();
}
- return NULL;
+ return {};
}
-void KeyStoreService::addLegacyBeginParams(const String16& name,
- std::vector<keymaster_key_param_t>& params) {
+void KeyStoreService::addLegacyBeginParams(const String16& name, AuthorizationSet* params) {
// All legacy keys are DIGEST_NONE/PAD_NONE.
- params.push_back(keymaster_param_enum(KM_TAG_DIGEST, KM_DIGEST_NONE));
- params.push_back(keymaster_param_enum(KM_TAG_PADDING, KM_PAD_NONE));
+ params->push_back(TAG_DIGEST, Digest::NONE);
+ params->push_back(TAG_PADDING, PaddingMode::NONE);
// Look up the algorithm of the key.
KeyCharacteristics characteristics;
- int32_t rc = getKeyCharacteristics(name, NULL, NULL, UID_SELF, &characteristics);
- if (rc != ::NO_ERROR) {
+ auto rc = getKeyCharacteristics(name, hidl_vec<uint8_t>(), hidl_vec<uint8_t>(), UID_SELF,
+ &characteristics);
+ if (!rc.isOk()) {
ALOGE("Failed to get key characteristics");
return;
}
- keymaster_key_param_t* algorithm = getKeyAlgorithm(&characteristics.characteristics);
- if (!algorithm) {
+ auto algorithm = getKeyAlgoritmFromKeyCharacteristics(characteristics);
+ if (!algorithm.isOk()) {
ALOGE("getKeyCharacteristics did not include KM_TAG_ALGORITHM");
return;
}
- params.push_back(*algorithm);
+ params->push_back(TAG_ALGORITHM, algorithm.value());
}
-int32_t KeyStoreService::doLegacySignVerify(const String16& name, const uint8_t* data,
- size_t length, uint8_t** out, size_t* outLength,
- const uint8_t* signature, size_t signatureLength,
- keymaster_purpose_t purpose) {
+KeyStoreServiceReturnCode KeyStoreService::doLegacySignVerify(const String16& name,
+ const hidl_vec<uint8_t>& data,
+ hidl_vec<uint8_t>* out,
+ const hidl_vec<uint8_t>& signature,
+ KeyPurpose purpose) {
std::basic_stringstream<uint8_t> outBuffer;
OperationResult result;
- KeymasterArguments inArgs;
- addLegacyBeginParams(name, inArgs.params);
+ AuthorizationSet inArgs;
+ addLegacyBeginParams(name, &inArgs);
sp<IBinder> appToken(new BBinder);
sp<IBinder> token;
- begin(appToken, name, purpose, true, inArgs, NULL, 0, UID_SELF, &result);
- if (result.resultCode != ResponseCode::NO_ERROR) {
- if (result.resultCode == ::KEY_NOT_FOUND) {
+ begin(appToken, name, purpose, true, inArgs.hidl_data(), hidl_vec<uint8_t>(), UID_SELF,
+ &result);
+ if (!result.resultCode.isOk()) {
+ if (result.resultCode == ResponseCode::KEY_NOT_FOUND) {
ALOGW("Key not found");
} else {
- ALOGW("Error in begin: %d", result.resultCode);
+ ALOGW("Error in begin: %d", int32_t(result.resultCode));
}
return translateResultToLegacyResult(result.resultCode);
}
- inArgs.params.clear();
+ inArgs.Clear();
token = result.token;
size_t consumed = 0;
size_t lastConsumed = 0;
+ hidl_vec<uint8_t> data_view;
do {
- update(token, inArgs, data + consumed, length - consumed, &result);
+ data_view.setToExternal(const_cast<uint8_t*>(&data[consumed]), data.size() - consumed);
+ update(token, inArgs.hidl_data(), data_view, &result);
if (result.resultCode != ResponseCode::NO_ERROR) {
- ALOGW("Error in update: %d", result.resultCode);
+ ALOGW("Error in update: %d", int32_t(result.resultCode));
return translateResultToLegacyResult(result.resultCode);
}
if (out) {
- outBuffer.write(result.data.get(), result.dataLength);
+ outBuffer.write(&result.data[0], result.data.size());
}
lastConsumed = result.inputConsumed;
consumed += lastConsumed;
- } while (consumed < length && lastConsumed > 0);
+ } while (consumed < data.size() && lastConsumed > 0);
- if (consumed != length) {
- ALOGW("Not all data consumed. Consumed %zu of %zu", consumed, length);
- return ::SYSTEM_ERROR;
+ if (consumed != data.size()) {
+ ALOGW("Not all data consumed. Consumed %zu of %zu", consumed, data.size());
+ return ResponseCode::SYSTEM_ERROR;
}
- finish(token, inArgs, signature, signatureLength, NULL, 0, &result);
+ finish(token, inArgs.hidl_data(), signature, hidl_vec<uint8_t>(), &result);
if (result.resultCode != ResponseCode::NO_ERROR) {
- ALOGW("Error in finish: %d", result.resultCode);
+ ALOGW("Error in finish: %d", int32_t(result.resultCode));
return translateResultToLegacyResult(result.resultCode);
}
if (out) {
- outBuffer.write(result.data.get(), result.dataLength);
+ outBuffer.write(&result.data[0], result.data.size());
}
if (out) {
auto buf = outBuffer.str();
- *out = new uint8_t[buf.size()];
- memcpy(*out, buf.c_str(), buf.size());
- *outLength = buf.size();
+ out->resize(buf.size());
+ memcpy(&(*out)[0], buf.data(), out->size());
}
- return ::NO_ERROR;
+ return ResponseCode::NO_ERROR;
}
-int32_t KeyStoreService::upgradeKeyBlob(const String16& name, uid_t uid,
- const AuthorizationSet& params, Blob* blob) {
+KeyStoreServiceReturnCode KeyStoreService::upgradeKeyBlob(const String16& name, uid_t uid,
+ const AuthorizationSet& params,
+ Blob* blob) {
// Read the blob rather than assuming the caller provided the right name/uid/blob triplet.
String8 name8(name);
ResponseCode responseCode = mKeyStore->getKeyForName(blob, name8, uid, TYPE_KEYMASTER_10);
- if (responseCode != ::NO_ERROR) {
+ if (responseCode != ResponseCode::NO_ERROR) {
return responseCode;
}
- keymaster_key_blob_t key = {blob->getValue(), static_cast<size_t>(blob->getLength())};
- auto* dev = mKeyStore->getDeviceForBlob(*blob);
- keymaster_key_blob_t upgraded_key;
- int32_t rc = dev->upgrade_key(dev, &key, ¶ms, &upgraded_key);
- if (rc != KM_ERROR_OK) {
- return rc;
- }
- UniquePtr<uint8_t, Malloc_Delete> upgraded_key_deleter(
- const_cast<uint8_t*>(upgraded_key.key_material));
+ auto hidlKey = blob2hidlVec(*blob);
+ auto& dev = mKeyStore->getDevice(*blob);
- String8 filename(mKeyStore->getKeyNameForUidWithDir(name8, uid, ::TYPE_KEYMASTER_10));
- rc = mKeyStore->del(filename.string(), ::TYPE_ANY, get_user_id(uid));
- if (rc != ::NO_ERROR) {
+ KeyStoreServiceReturnCode error;
+ auto hidlCb = [&](ErrorCode ret, const hidl_vec<uint8_t>& upgradedKeyBlob) {
+ error = ret;
+ if (!error.isOk()) {
+ return;
+ }
+
+ String8 filename(mKeyStore->getKeyNameForUidWithDir(name8, uid, ::TYPE_KEYMASTER_10));
+ error = mKeyStore->del(filename.string(), ::TYPE_ANY, get_user_id(uid));
+ if (!error.isOk()) {
+ return;
+ }
+
+ Blob newBlob(&upgradedKeyBlob[0], upgradedKeyBlob.size(), nullptr /* info */,
+ 0 /* infoLength */, ::TYPE_KEYMASTER_10);
+ newBlob.setFallback(blob->isFallback());
+ newBlob.setEncrypted(blob->isEncrypted());
+
+ error = mKeyStore->put(filename.string(), &newBlob, get_user_id(uid));
+ if (!error.isOk()) {
+ return;
+ }
+
+ // Re-read blob for caller. We can't use newBlob because writing it modified it.
+ error = mKeyStore->getKeyForName(blob, name8, uid, TYPE_KEYMASTER_10);
+ };
+
+ KeyStoreServiceReturnCode rc =
+ KS_HANDLE_HIDL_ERROR(dev->upgradeKey(hidlKey, params.hidl_data(), hidlCb));
+ if (!rc.isOk()) {
return rc;
}
- Blob newBlob(upgraded_key.key_material, upgraded_key.key_material_size, nullptr /* info */,
- 0 /* infoLength */, ::TYPE_KEYMASTER_10);
- newBlob.setFallback(blob->isFallback());
- newBlob.setEncrypted(blob->isEncrypted());
-
- rc = mKeyStore->put(filename.string(), &newBlob, get_user_id(uid));
-
- // Re-read blob for caller. We can't use newBlob because writing it modified it.
- responseCode = mKeyStore->getKeyForName(blob, name8, uid, TYPE_KEYMASTER_10);
- if (responseCode != ::NO_ERROR) {
- return responseCode;
- }
-
- return rc;
+ return error;
}
} // namespace android
diff --git a/keystore/key_store_service.h b/keystore/key_store_service.h
index cfbc91f..432e780 100644
--- a/keystore/key_store_service.h
+++ b/keystore/key_store_service.h
@@ -19,7 +19,7 @@
#include <keystore/IKeystoreService.h>
-#include <keymaster/authorization_set.h>
+#include <keystore/authorization_set.h>
#include "auth_token_table.h"
#include "keystore.h"
@@ -27,42 +27,48 @@
#include "operation.h"
#include "permissions.h"
-namespace android {
+namespace keystore {
-class KeyStoreService : public BnKeystoreService, public IBinder::DeathRecipient {
+class KeyStoreService : public android::BnKeystoreService, public android::IBinder::DeathRecipient {
+ typedef ::android::sp<::android::hardware::keymaster::V3_0::IKeymasterDevice> km_device_t;
+
public:
explicit KeyStoreService(KeyStore* keyStore) : mKeyStore(keyStore), mOperationMap(this) {}
- void binderDied(const wp<IBinder>& who);
+ void binderDied(const android::wp<android::IBinder>& who);
- int32_t getState(int32_t userId);
+ KeyStoreServiceReturnCode getState(int32_t userId) override;
- int32_t get(const String16& name, int32_t uid, uint8_t** item, size_t* itemLength);
- int32_t insert(const String16& name, const uint8_t* item, size_t itemLength, int targetUid,
- int32_t flags);
- int32_t del(const String16& name, int targetUid);
- int32_t exist(const String16& name, int targetUid);
- int32_t list(const String16& prefix, int targetUid, Vector<String16>* matches);
+ KeyStoreServiceReturnCode get(const android::String16& name, int32_t uid,
+ hidl_vec<uint8_t>* item) override;
+ KeyStoreServiceReturnCode insert(const android::String16& name, const hidl_vec<uint8_t>& item,
+ int targetUid, int32_t flags) override;
+ KeyStoreServiceReturnCode del(const android::String16& name, int targetUid) override;
+ KeyStoreServiceReturnCode exist(const android::String16& name, int targetUid) override;
+ KeyStoreServiceReturnCode list(const android::String16& prefix, int targetUid,
+ android::Vector<android::String16>* matches) override;
- int32_t reset();
+ KeyStoreServiceReturnCode reset() override;
- int32_t onUserPasswordChanged(int32_t userId, const String16& password);
- int32_t onUserAdded(int32_t userId, int32_t parentId);
- int32_t onUserRemoved(int32_t userId);
+ KeyStoreServiceReturnCode onUserPasswordChanged(int32_t userId,
+ const android::String16& password) override;
+ KeyStoreServiceReturnCode onUserAdded(int32_t userId, int32_t parentId) override;
+ KeyStoreServiceReturnCode onUserRemoved(int32_t userId) override;
- int32_t lock(int32_t userId);
- int32_t unlock(int32_t userId, const String16& pw);
+ KeyStoreServiceReturnCode lock(int32_t userId) override;
+ KeyStoreServiceReturnCode unlock(int32_t userId, const android::String16& pw) override;
- bool isEmpty(int32_t userId);
+ bool isEmpty(int32_t userId) override;
- int32_t generate(const String16& name, int32_t targetUid, int32_t keyType, int32_t keySize,
- int32_t flags, Vector<sp<KeystoreArg>>* args);
- int32_t import(const String16& name, const uint8_t* data, size_t length, int targetUid,
- int32_t flags);
- int32_t sign(const String16& name, const uint8_t* data, size_t length, uint8_t** out,
- size_t* outLength);
- int32_t verify(const String16& name, const uint8_t* data, size_t dataLength,
- const uint8_t* signature, size_t signatureLength);
+ KeyStoreServiceReturnCode
+ generate(const android::String16& name, int32_t targetUid, int32_t keyType, int32_t keySize,
+ int32_t flags, android::Vector<android::sp<android::KeystoreArg>>* args) override;
+ KeyStoreServiceReturnCode import(const android::String16& name, const hidl_vec<uint8_t>& data,
+ int targetUid, int32_t flags) override;
+ KeyStoreServiceReturnCode sign(const android::String16& name, const hidl_vec<uint8_t>& data,
+ hidl_vec<uint8_t>* out) override;
+ KeyStoreServiceReturnCode verify(const android::String16& name, const hidl_vec<uint8_t>& data,
+ const hidl_vec<uint8_t>& signature) override;
/*
* TODO: The abstraction between things stored in hardware and regular blobs
@@ -75,51 +81,57 @@
* "del_key" since the Java code doesn't really communicate what it's
* intentions are.
*/
- int32_t get_pubkey(const String16& name, uint8_t** pubkey, size_t* pubkeyLength);
+ KeyStoreServiceReturnCode get_pubkey(const android::String16& name,
+ hidl_vec<uint8_t>* pubKey) override;
- int32_t grant(const String16& name, int32_t granteeUid);
- int32_t ungrant(const String16& name, int32_t granteeUid);
+ KeyStoreServiceReturnCode grant(const android::String16& name, int32_t granteeUid) override;
+ KeyStoreServiceReturnCode ungrant(const android::String16& name, int32_t granteeUid) override;
- int64_t getmtime(const String16& name, int32_t uid);
+ int64_t getmtime(const android::String16& name, int32_t uid) override;
- int32_t duplicate(const String16& srcKey, int32_t srcUid, const String16& destKey,
- int32_t destUid);
+ KeyStoreServiceReturnCode duplicate(const android::String16& srcKey, int32_t srcUid,
+ const android::String16& destKey, int32_t destUid) override;
- int32_t is_hardware_backed(const String16& keyType);
+ int32_t is_hardware_backed(const android::String16& keyType) override;
- int32_t clear_uid(int64_t targetUid64);
+ KeyStoreServiceReturnCode clear_uid(int64_t targetUid64) override;
- int32_t addRngEntropy(const uint8_t* data, size_t dataLength);
- int32_t generateKey(const String16& name, const KeymasterArguments& params,
- const uint8_t* entropy, size_t entropyLength, int uid, int flags,
- KeyCharacteristics* outCharacteristics);
- int32_t getKeyCharacteristics(const String16& name, const keymaster_blob_t* clientId,
- const keymaster_blob_t* appData, int32_t uid,
- KeyCharacteristics* outCharacteristics);
- int32_t importKey(const String16& name, const KeymasterArguments& params,
- keymaster_key_format_t format, const uint8_t* keyData, size_t keyLength,
- int uid, int flags, KeyCharacteristics* outCharacteristics);
- void exportKey(const String16& name, keymaster_key_format_t format,
- const keymaster_blob_t* clientId, const keymaster_blob_t* appData, int32_t uid,
- ExportResult* result);
- void begin(const sp<IBinder>& appToken, const String16& name, keymaster_purpose_t purpose,
- bool pruneable, const KeymasterArguments& params, const uint8_t* entropy,
- size_t entropyLength, int32_t uid, OperationResult* result);
- void update(const sp<IBinder>& token, const KeymasterArguments& params, const uint8_t* data,
- size_t dataLength, OperationResult* result);
- void finish(const sp<IBinder>& token, const KeymasterArguments& params,
- const uint8_t* signature, size_t signatureLength, const uint8_t* entropy,
- size_t entropyLength, OperationResult* result);
- int32_t abort(const sp<IBinder>& token);
+ KeyStoreServiceReturnCode addRngEntropy(const hidl_vec<uint8_t>& entropy) override;
+ KeyStoreServiceReturnCode generateKey(const android::String16& name,
+ const hidl_vec<KeyParameter>& params,
+ const hidl_vec<uint8_t>& entropy, int uid, int flags,
+ KeyCharacteristics* outCharacteristics) override;
+ KeyStoreServiceReturnCode
+ getKeyCharacteristics(const android::String16& name, const hidl_vec<uint8_t>& clientId,
+ const hidl_vec<uint8_t>& appData, int32_t uid,
+ KeyCharacteristics* outCharacteristics) override;
+ KeyStoreServiceReturnCode importKey(const android::String16& name,
+ const hidl_vec<KeyParameter>& params, KeyFormat format,
+ const hidl_vec<uint8_t>& keyData, int uid, int flags,
+ KeyCharacteristics* outCharacteristics) override;
+ void exportKey(const android::String16& name, KeyFormat format,
+ const hidl_vec<uint8_t>& clientId, const hidl_vec<uint8_t>& appData, int32_t uid,
+ android::ExportResult* result) override;
+ void begin(const sp<android::IBinder>& appToken, const android::String16& name,
+ KeyPurpose purpose, bool pruneable, const hidl_vec<KeyParameter>& params,
+ const hidl_vec<uint8_t>& entropy, int32_t uid,
+ android::OperationResult* result) override;
+ void update(const sp<android::IBinder>& token, const hidl_vec<KeyParameter>& params,
+ const hidl_vec<uint8_t>& data, android::OperationResult* result) override;
+ void finish(const sp<android::IBinder>& token, const hidl_vec<KeyParameter>& params,
+ const hidl_vec<uint8_t>& signature, const hidl_vec<uint8_t>& entropy,
+ android::OperationResult* result) override;
+ KeyStoreServiceReturnCode abort(const sp<android::IBinder>& token) override;
- bool isOperationAuthorized(const sp<IBinder>& token);
+ bool isOperationAuthorized(const sp<android::IBinder>& token) override;
- int32_t addAuthToken(const uint8_t* token, size_t length);
+ KeyStoreServiceReturnCode addAuthToken(const uint8_t* token, size_t length) override;
- int32_t attestKey(const String16& name, const KeymasterArguments& params,
- KeymasterCertificateChain* outChain) override;
+ KeyStoreServiceReturnCode attestKey(const android::String16& name,
+ const hidl_vec<KeyParameter>& params,
+ hidl_vec<hidl_vec<uint8_t>>* outChain) override;
- int32_t onDeviceOffBody();
+ KeyStoreServiceReturnCode onDeviceOffBody() override;
private:
static const int32_t UID_SELF = -1;
@@ -164,23 +176,20 @@
* otherwise the state of keystore when not unlocked and checkUnlocked is
* true.
*/
- int32_t checkBinderPermissionAndKeystoreState(perm_t permission, int32_t targetUid = -1,
- bool checkUnlocked = true);
+ KeyStoreServiceReturnCode checkBinderPermissionAndKeystoreState(perm_t permission,
+ int32_t targetUid = -1,
+ bool checkUnlocked = true);
bool isKeystoreUnlocked(State state);
- bool isKeyTypeSupported(const keymaster2_device_t* device, keymaster_keypair_t keyType);
-
/**
* Check that all keymaster_key_param_t's provided by the application are
* allowed. Any parameter that keystore adds itself should be disallowed here.
*/
- bool checkAllowedOperationParams(const std::vector<keymaster_key_param_t>& params);
+ bool checkAllowedOperationParams(const hidl_vec<KeyParameter>& params);
- keymaster_error_t getOperationCharacteristics(const keymaster_key_blob_t& key,
- const keymaster2_device_t* dev,
- const std::vector<keymaster_key_param_t>& params,
- keymaster_key_characteristics_t* out);
+ ErrorCode getOperationCharacteristics(const hidl_vec<uint8_t>& key, km_device_t* dev,
+ const AuthorizationSet& params, KeyCharacteristics* out);
/**
* Get the auth token for this operation from the auth token table.
@@ -192,11 +201,10 @@
* KM_ERROR_KEY_USER_NOT_AUTHENTICATED if there is no valid auth
* token for the operation
*/
- int32_t getAuthToken(const keymaster_key_characteristics_t* characteristics,
- keymaster_operation_handle_t handle, keymaster_purpose_t purpose,
- const hw_auth_token_t** authToken, bool failOnTokenMissing = true);
-
- void addAuthToParams(std::vector<keymaster_key_param_t>* params, const hw_auth_token_t* token);
+ KeyStoreServiceReturnCode getAuthToken(const KeyCharacteristics& characteristics,
+ uint64_t handle, KeyPurpose purpose,
+ const HardwareAuthToken** authToken,
+ bool failOnTokenMissing = true);
/**
* Add the auth token for the operation to the param list if the operation
@@ -209,22 +217,22 @@
* KM_ERROR_INVALID_OPERATION_HANDLE if token is not a valid
* operation token.
*/
- int32_t addOperationAuthTokenIfNeeded(const sp<IBinder>& token,
- std::vector<keymaster_key_param_t>* params);
+ KeyStoreServiceReturnCode addOperationAuthTokenIfNeeded(const sp<android::IBinder>& token,
+ AuthorizationSet* params);
/**
* Translate a result value to a legacy return value. All keystore errors are
* preserved and keymaster errors become SYSTEM_ERRORs
*/
- int32_t translateResultToLegacyResult(int32_t result);
+ KeyStoreServiceReturnCode translateResultToLegacyResult(int32_t result);
- keymaster_key_param_t* getKeyAlgorithm(keymaster_key_characteristics_t* characteristics);
+ void addLegacyBeginParams(const android::String16& name, AuthorizationSet* params);
- void addLegacyBeginParams(const String16& name, std::vector<keymaster_key_param_t>& params);
-
- int32_t doLegacySignVerify(const String16& name, const uint8_t* data, size_t length,
- uint8_t** out, size_t* outLength, const uint8_t* signature,
- size_t signatureLength, keymaster_purpose_t purpose);
+ KeyStoreServiceReturnCode doLegacySignVerify(const android::String16& name,
+ const hidl_vec<uint8_t>& data,
+ hidl_vec<uint8_t>* out,
+ const hidl_vec<uint8_t>& signature,
+ KeyPurpose purpose);
/**
* Upgrade a key blob under alias "name", returning the new blob in "blob". If "blob"
@@ -234,15 +242,15 @@
* KM_ERROR_VERSION_MISMATCH if called on a key whose patch level is greater than or
* equal to the current system patch level.
*/
- int32_t upgradeKeyBlob(const String16& name, uid_t targetUid,
- const keymaster::AuthorizationSet& params, Blob* blob);
+ KeyStoreServiceReturnCode upgradeKeyBlob(const android::String16& name, uid_t targetUid,
+ const AuthorizationSet& params, Blob* blob);
::KeyStore* mKeyStore;
OperationMap mOperationMap;
- keymaster::AuthTokenTable mAuthTokenTable;
+ keystore::AuthTokenTable mAuthTokenTable;
KeystoreKeymasterEnforcement enforcement_policy;
};
-}; // namespace android
+}; // namespace keystore
#endif // KEYSTORE_KEYSTORE_SERVICE_H_
diff --git a/keystore/keymaster_enforcement.cpp b/keystore/keymaster_enforcement.cpp
new file mode 100644
index 0000000..117f048
--- /dev/null
+++ b/keystore/keymaster_enforcement.cpp
@@ -0,0 +1,598 @@
+/*
+ * Copyright (C) 2014 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"
+
+#include "keymaster_enforcement.h"
+
+#include <assert.h>
+#include <inttypes.h>
+#include <limits.h>
+#include <string.h>
+
+#include <openssl/evp.h>
+
+#include <cutils/log.h>
+#include <hardware/hw_auth_token.h>
+#include <list>
+
+namespace keystore {
+
+class AccessTimeMap {
+ public:
+ explicit AccessTimeMap(uint32_t max_size) : max_size_(max_size) {}
+
+ /* If the key is found, returns true and fills \p last_access_time. If not found returns
+ * false. */
+ bool LastKeyAccessTime(km_id_t keyid, uint32_t* last_access_time) const;
+
+ /* Updates the last key access time with the currentTime parameter. Adds the key if
+ * needed, returning false if key cannot be added because list is full. */
+ bool UpdateKeyAccessTime(km_id_t keyid, uint32_t current_time, uint32_t timeout);
+
+ private:
+ struct AccessTime {
+ km_id_t keyid;
+ uint32_t access_time;
+ uint32_t timeout;
+ };
+ std::list<AccessTime> last_access_list_;
+ const uint32_t max_size_;
+};
+
+class AccessCountMap {
+ public:
+ explicit AccessCountMap(uint32_t max_size) : max_size_(max_size) {}
+
+ /* If the key is found, returns true and fills \p count. If not found returns
+ * false. */
+ bool KeyAccessCount(km_id_t keyid, uint32_t* count) const;
+
+ /* Increments key access count, adding an entry if the key has never been used. Returns
+ * false if the list has reached maximum size. */
+ bool IncrementKeyAccessCount(km_id_t keyid);
+
+ private:
+ struct AccessCount {
+ km_id_t keyid;
+ uint64_t access_count;
+ };
+ std::list<AccessCount> access_count_list_;
+ const uint32_t max_size_;
+};
+
+bool is_public_key_algorithm(const AuthorizationSet& auth_set) {
+ auto algorithm = auth_set.GetTagValue(TAG_ALGORITHM);
+ return algorithm.isOk() &&
+ (algorithm.value() == Algorithm::RSA || algorithm.value() == Algorithm::EC);
+}
+
+static ErrorCode authorized_purpose(const KeyPurpose purpose, const AuthorizationSet& auth_set) {
+ switch (purpose) {
+ case KeyPurpose::VERIFY:
+ case KeyPurpose::ENCRYPT:
+ case KeyPurpose::SIGN:
+ case KeyPurpose::DECRYPT:
+ if (auth_set.Contains(TAG_PURPOSE, purpose)) return ErrorCode::OK;
+ return ErrorCode::INCOMPATIBLE_PURPOSE;
+
+ default:
+ return ErrorCode::UNSUPPORTED_PURPOSE;
+ }
+}
+
+inline bool is_origination_purpose(KeyPurpose purpose) {
+ return purpose == KeyPurpose::ENCRYPT || purpose == KeyPurpose::SIGN;
+}
+
+inline bool is_usage_purpose(KeyPurpose purpose) {
+ return purpose == KeyPurpose::DECRYPT || purpose == KeyPurpose::VERIFY;
+}
+
+KeymasterEnforcement::KeymasterEnforcement(uint32_t max_access_time_map_size,
+ uint32_t max_access_count_map_size)
+ : access_time_map_(new (std::nothrow) AccessTimeMap(max_access_time_map_size)),
+ access_count_map_(new (std::nothrow) AccessCountMap(max_access_count_map_size)) {}
+
+KeymasterEnforcement::~KeymasterEnforcement() {
+ delete access_time_map_;
+ delete access_count_map_;
+}
+
+ErrorCode KeymasterEnforcement::AuthorizeOperation(const KeyPurpose purpose, const km_id_t keyid,
+ const AuthorizationSet& auth_set,
+ const AuthorizationSet& operation_params,
+ uint64_t op_handle, bool is_begin_operation) {
+ if (is_public_key_algorithm(auth_set)) {
+ switch (purpose) {
+ case KeyPurpose::ENCRYPT:
+ case KeyPurpose::VERIFY:
+ /* Public key operations are always authorized. */
+ return ErrorCode::OK;
+
+ case KeyPurpose::DECRYPT:
+ case KeyPurpose::SIGN:
+ case KeyPurpose::DERIVE_KEY:
+ break;
+ case KeyPurpose::WRAP_KEY:
+ return ErrorCode::INCOMPATIBLE_PURPOSE;
+ };
+ };
+
+ if (is_begin_operation)
+ return AuthorizeBegin(purpose, keyid, auth_set, operation_params);
+ else
+ return AuthorizeUpdateOrFinish(auth_set, operation_params, op_handle);
+}
+
+// For update and finish the only thing to check is user authentication, and then only if it's not
+// timeout-based.
+ErrorCode KeymasterEnforcement::AuthorizeUpdateOrFinish(const AuthorizationSet& auth_set,
+ const AuthorizationSet& operation_params,
+ uint64_t op_handle) {
+ int auth_type_index = -1;
+ for (size_t pos = 0; pos < auth_set.size(); ++pos) {
+ switch (auth_set[pos].tag) {
+ case Tag::NO_AUTH_REQUIRED:
+ case Tag::AUTH_TIMEOUT:
+ // If no auth is required or if auth is timeout-based, we have nothing to check.
+ return ErrorCode::OK;
+
+ case Tag::USER_AUTH_TYPE:
+ auth_type_index = pos;
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ // Note that at this point we should be able to assume that authentication is required, because
+ // authentication is required if KM_TAG_NO_AUTH_REQUIRED is absent. However, there are legacy
+ // keys which have no authentication-related tags, so we assume that absence is equivalent to
+ // presence of KM_TAG_NO_AUTH_REQUIRED.
+ //
+ // So, if we found KM_TAG_USER_AUTH_TYPE or if we find KM_TAG_USER_SECURE_ID then authentication
+ // is required. If we find neither, then we assume authentication is not required and return
+ // success.
+ bool authentication_required = (auth_type_index != -1);
+ for (auto& param : auth_set) {
+ auto user_secure_id = authorizationValue(TAG_USER_SECURE_ID, param);
+ if (user_secure_id.isOk()) {
+ authentication_required = true;
+ int auth_timeout_index = -1;
+ if (AuthTokenMatches(auth_set, operation_params, user_secure_id.value(),
+ auth_type_index, auth_timeout_index, op_handle,
+ false /* is_begin_operation */))
+ return ErrorCode::OK;
+ }
+ }
+
+ if (authentication_required) return ErrorCode::KEY_USER_NOT_AUTHENTICATED;
+
+ return ErrorCode::OK;
+}
+
+ErrorCode KeymasterEnforcement::AuthorizeBegin(const KeyPurpose purpose, const km_id_t keyid,
+ const AuthorizationSet& auth_set,
+ const AuthorizationSet& operation_params) {
+ // Find some entries that may be needed to handle KM_TAG_USER_SECURE_ID
+ int auth_timeout_index = -1;
+ int auth_type_index = -1;
+ int no_auth_required_index = -1;
+ for (size_t pos = 0; pos < auth_set.size(); ++pos) {
+ switch (auth_set[pos].tag) {
+ case Tag::AUTH_TIMEOUT:
+ auth_timeout_index = pos;
+ break;
+ case Tag::USER_AUTH_TYPE:
+ auth_type_index = pos;
+ break;
+ case Tag::NO_AUTH_REQUIRED:
+ no_auth_required_index = pos;
+ break;
+ default:
+ break;
+ }
+ }
+
+ ErrorCode error = authorized_purpose(purpose, auth_set);
+ if (error != ErrorCode::OK) return error;
+
+ // If successful, and if key has a min time between ops, this will be set to the time limit
+ uint32_t min_ops_timeout = UINT32_MAX;
+
+ bool update_access_count = false;
+ bool caller_nonce_authorized_by_key = false;
+ bool authentication_required = false;
+ bool auth_token_matched = false;
+
+ for (auto& param : auth_set) {
+
+ // KM_TAG_PADDING_OLD and KM_TAG_DIGEST_OLD aren't actually members of the enum, so we can't
+ // switch on them. There's nothing to validate for them, though, so just ignore them.
+ if (int32_t(param.tag) == KM_TAG_PADDING_OLD || int32_t(param.tag) == KM_TAG_DIGEST_OLD)
+ continue;
+
+ switch (param.tag) {
+
+ case Tag::ACTIVE_DATETIME: {
+ auto date = authorizationValue(TAG_ACTIVE_DATETIME, param);
+ if (date.isOk() && !activation_date_valid(date.value()))
+ return ErrorCode::KEY_NOT_YET_VALID;
+ break;
+ }
+ case Tag::ORIGINATION_EXPIRE_DATETIME: {
+ auto date = authorizationValue(TAG_ORIGINATION_EXPIRE_DATETIME, param);
+ if (is_origination_purpose(purpose) && date.isOk() &&
+ expiration_date_passed(date.value()))
+ return ErrorCode::KEY_EXPIRED;
+ break;
+ }
+ case Tag::USAGE_EXPIRE_DATETIME: {
+ auto date = authorizationValue(TAG_USAGE_EXPIRE_DATETIME, param);
+ if (is_usage_purpose(purpose) && date.isOk() && expiration_date_passed(date.value()))
+ return ErrorCode::KEY_EXPIRED;
+ break;
+ }
+ case Tag::MIN_SECONDS_BETWEEN_OPS: {
+ auto min_ops_timeout = authorizationValue(TAG_MIN_SECONDS_BETWEEN_OPS, param);
+ if (min_ops_timeout.isOk() && !MinTimeBetweenOpsPassed(min_ops_timeout.value(), keyid))
+ return ErrorCode::KEY_RATE_LIMIT_EXCEEDED;
+ break;
+ }
+ case Tag::MAX_USES_PER_BOOT: {
+ auto max_users = authorizationValue(TAG_MAX_USES_PER_BOOT, param);
+ update_access_count = true;
+ if (max_users.isOk() && !MaxUsesPerBootNotExceeded(keyid, max_users.value()))
+ return ErrorCode::KEY_MAX_OPS_EXCEEDED;
+ break;
+ }
+ case Tag::USER_SECURE_ID:
+ if (no_auth_required_index != -1) {
+ // Key has both KM_TAG_USER_SECURE_ID and KM_TAG_NO_AUTH_REQUIRED
+ return ErrorCode::INVALID_KEY_BLOB;
+ }
+
+ if (auth_timeout_index != -1) {
+ auto secure_id = authorizationValue(TAG_USER_SECURE_ID, param);
+ authentication_required = true;
+ if (secure_id.isOk() &&
+ AuthTokenMatches(auth_set, operation_params, secure_id.value(), auth_type_index,
+ auth_timeout_index, 0 /* op_handle */,
+ true /* is_begin_operation */))
+ auth_token_matched = true;
+ }
+ break;
+
+ case Tag::CALLER_NONCE:
+ caller_nonce_authorized_by_key = true;
+ break;
+
+ /* Tags should never be in key auths. */
+ case Tag::INVALID:
+ case Tag::AUTH_TOKEN:
+ case Tag::ROOT_OF_TRUST:
+ case Tag::APPLICATION_DATA:
+ case Tag::ATTESTATION_CHALLENGE:
+ case Tag::ATTESTATION_APPLICATION_ID:
+ return ErrorCode::INVALID_KEY_BLOB;
+
+ /* Tags used for cryptographic parameters in keygen. Nothing to enforce. */
+ case Tag::PURPOSE:
+ case Tag::ALGORITHM:
+ case Tag::KEY_SIZE:
+ case Tag::BLOCK_MODE:
+ case Tag::DIGEST:
+ case Tag::MAC_LENGTH:
+ case Tag::PADDING:
+ case Tag::NONCE:
+ case Tag::MIN_MAC_LENGTH:
+ case Tag::KDF:
+ case Tag::EC_CURVE:
+
+ /* Tags not used for operations. */
+ case Tag::BLOB_USAGE_REQUIREMENTS:
+ case Tag::EXPORTABLE:
+
+ /* Algorithm specific parameters not used for access control. */
+ case Tag::RSA_PUBLIC_EXPONENT:
+ case Tag::ECIES_SINGLE_HASH_MODE:
+
+ /* Informational tags. */
+ case Tag::CREATION_DATETIME:
+ case Tag::ORIGIN:
+ case Tag::ROLLBACK_RESISTANT:
+
+ /* Tags handled when KM_TAG_USER_SECURE_ID is handled */
+ case Tag::NO_AUTH_REQUIRED:
+ case Tag::USER_AUTH_TYPE:
+ case Tag::AUTH_TIMEOUT:
+
+ /* Tag to provide data to operations. */
+ case Tag::ASSOCIATED_DATA:
+
+ /* Tags that are implicitly verified by secure side */
+ case Tag::ALL_APPLICATIONS:
+ case Tag::APPLICATION_ID:
+ case Tag::OS_VERSION:
+ case Tag::OS_PATCHLEVEL:
+
+ /* Ignored pending removal */
+ case Tag::USER_ID:
+ case Tag::ALL_USERS:
+
+ /* TODO(swillden): Handle these */
+ case Tag::INCLUDE_UNIQUE_ID:
+ case Tag::UNIQUE_ID:
+ case Tag::RESET_SINCE_ID_ROTATION:
+ case Tag::ALLOW_WHILE_ON_BODY:
+ break;
+
+ case Tag::BOOTLOADER_ONLY:
+ return ErrorCode::INVALID_KEY_BLOB;
+ }
+ }
+
+ if (authentication_required && !auth_token_matched) {
+ ALOGE("Auth required but no matching auth token found");
+ return ErrorCode::KEY_USER_NOT_AUTHENTICATED;
+ }
+
+ if (!caller_nonce_authorized_by_key && is_origination_purpose(purpose) &&
+ operation_params.Contains(Tag::NONCE))
+ return ErrorCode::CALLER_NONCE_PROHIBITED;
+
+ if (min_ops_timeout != UINT32_MAX) {
+ if (!access_time_map_) {
+ ALOGE("Rate-limited keys table not allocated. Rate-limited keys disabled");
+ return ErrorCode::MEMORY_ALLOCATION_FAILED;
+ }
+
+ if (!access_time_map_->UpdateKeyAccessTime(keyid, get_current_time(), min_ops_timeout)) {
+ ALOGE("Rate-limited keys table full. Entries will time out.");
+ return ErrorCode::TOO_MANY_OPERATIONS;
+ }
+ }
+
+ if (update_access_count) {
+ if (!access_count_map_) {
+ ALOGE("Usage-count limited keys tabel not allocated. Count-limited keys disabled");
+ return ErrorCode::MEMORY_ALLOCATION_FAILED;
+ }
+
+ if (!access_count_map_->IncrementKeyAccessCount(keyid)) {
+ ALOGE("Usage count-limited keys table full, until reboot.");
+ return ErrorCode::TOO_MANY_OPERATIONS;
+ }
+ }
+
+ return ErrorCode::OK;
+}
+
+class EvpMdCtx {
+ public:
+ EvpMdCtx() { EVP_MD_CTX_init(&ctx_); }
+ ~EvpMdCtx() { EVP_MD_CTX_cleanup(&ctx_); }
+
+ EVP_MD_CTX* get() { return &ctx_; }
+
+ private:
+ EVP_MD_CTX ctx_;
+};
+
+/* static */
+bool KeymasterEnforcement::CreateKeyId(const hidl_vec<uint8_t>& key_blob, km_id_t* keyid) {
+ EvpMdCtx ctx;
+
+ uint8_t hash[EVP_MAX_MD_SIZE];
+ unsigned int hash_len;
+ if (EVP_DigestInit_ex(ctx.get(), EVP_sha256(), nullptr /* ENGINE */) &&
+ EVP_DigestUpdate(ctx.get(), &key_blob[0], key_blob.size()) &&
+ EVP_DigestFinal_ex(ctx.get(), hash, &hash_len)) {
+ assert(hash_len >= sizeof(*keyid));
+ memcpy(keyid, hash, sizeof(*keyid));
+ return true;
+ }
+
+ return false;
+}
+
+bool KeymasterEnforcement::MinTimeBetweenOpsPassed(uint32_t min_time_between, const km_id_t keyid) {
+ if (!access_time_map_) return false;
+
+ uint32_t last_access_time;
+ if (!access_time_map_->LastKeyAccessTime(keyid, &last_access_time)) return true;
+ return min_time_between <= static_cast<int64_t>(get_current_time()) - last_access_time;
+}
+
+bool KeymasterEnforcement::MaxUsesPerBootNotExceeded(const km_id_t keyid, uint32_t max_uses) {
+ if (!access_count_map_) return false;
+
+ uint32_t key_access_count;
+ if (!access_count_map_->KeyAccessCount(keyid, &key_access_count)) return true;
+ return key_access_count < max_uses;
+}
+
+template <typename IntType, uint32_t byteOrder> struct choose_hton;
+
+template <typename IntType> struct choose_hton<IntType, __ORDER_LITTLE_ENDIAN__> {
+ inline static IntType hton(const IntType& value) {
+ IntType result = 0;
+ const unsigned char* inbytes = reinterpret_cast<const unsigned char*>(&value);
+ unsigned char* outbytes = reinterpret_cast<unsigned char*>(&result);
+ for (int i = sizeof(IntType) - 1; i >= 0; --i) {
+ *(outbytes++) = inbytes[i];
+ }
+ return result;
+ }
+};
+
+template <typename IntType> struct choose_hton<IntType, __ORDER_BIG_ENDIAN__> {
+ inline static IntType hton(const IntType& value) { return value; }
+};
+
+template <typename IntType> inline IntType hton(const IntType& value) {
+ return choose_hton<IntType, __BYTE_ORDER__>::hton(value);
+}
+
+template <typename IntType> inline IntType ntoh(const IntType& value) {
+ // same operation and hton
+ return choose_hton<IntType, __BYTE_ORDER__>::hton(value);
+}
+
+bool KeymasterEnforcement::AuthTokenMatches(const AuthorizationSet& auth_set,
+ const AuthorizationSet& operation_params,
+ const uint64_t user_secure_id,
+ const int auth_type_index, const int auth_timeout_index,
+ const uint64_t op_handle,
+ bool is_begin_operation) const {
+ assert(auth_type_index < static_cast<int>(auth_set.size()));
+ assert(auth_timeout_index < static_cast<int>(auth_set.size()));
+
+ auto auth_token_blob = operation_params.GetTagValue(TAG_AUTH_TOKEN);
+ if (!auth_token_blob.isOk()) {
+ ALOGE("Authentication required, but auth token not provided");
+ return false;
+ }
+
+ if (auth_token_blob.value().size() != sizeof(hw_auth_token_t)) {
+ ALOGE("Bug: Auth token is the wrong size (%zu expected, %zu found)",
+ sizeof(hw_auth_token_t), auth_token_blob.value().size());
+ return false;
+ }
+
+ hw_auth_token_t auth_token;
+ memcpy(&auth_token, &auth_token_blob.value()[0], sizeof(hw_auth_token_t));
+ if (auth_token.version != HW_AUTH_TOKEN_VERSION) {
+ ALOGE("Bug: Auth token is the version %hhu (or is not an auth token). Expected %d",
+ auth_token.version, HW_AUTH_TOKEN_VERSION);
+ return false;
+ }
+
+ if (!ValidateTokenSignature(auth_token)) {
+ ALOGE("Auth token signature invalid");
+ return false;
+ }
+
+ if (auth_timeout_index == -1 && op_handle && op_handle != auth_token.challenge) {
+ ALOGE("Auth token has the challenge %" PRIu64 ", need %" PRIu64, auth_token.challenge,
+ op_handle);
+ return false;
+ }
+
+ if (user_secure_id != auth_token.user_id && user_secure_id != auth_token.authenticator_id) {
+ ALOGI("Auth token SIDs %" PRIu64 " and %" PRIu64 " do not match key SID %" PRIu64,
+ auth_token.user_id, auth_token.authenticator_id, user_secure_id);
+ return false;
+ }
+
+ if (auth_type_index < 0 || auth_type_index > static_cast<int>(auth_set.size())) {
+ ALOGE("Auth required but no auth type found");
+ return false;
+ }
+
+ assert(auth_set[auth_type_index].tag == KM_TAG_USER_AUTH_TYPE);
+ auto key_auth_type_mask = authorizationValue(TAG_USER_AUTH_TYPE, auth_set[auth_type_index]);
+ if (!key_auth_type_mask.isOk()) return false;
+
+ uint32_t token_auth_type = ntoh(auth_token.authenticator_type);
+ if ((uint32_t(key_auth_type_mask.value()) & token_auth_type) == 0) {
+ ALOGE("Key requires match of auth type mask 0%uo, but token contained 0%uo",
+ key_auth_type_mask.value(), token_auth_type);
+ return false;
+ }
+
+ if (auth_timeout_index != -1 && is_begin_operation) {
+ assert(auth_set[auth_timeout_index].tag == KM_TAG_AUTH_TIMEOUT);
+ auto auth_token_timeout =
+ authorizationValue(TAG_AUTH_TIMEOUT, auth_set[auth_timeout_index]);
+ if (!auth_token_timeout.isOk()) return false;
+
+ if (auth_token_timed_out(auth_token, auth_token_timeout.value())) {
+ ALOGE("Auth token has timed out");
+ return false;
+ }
+ }
+
+ // Survived the whole gauntlet. We have authentage!
+ return true;
+}
+
+bool AccessTimeMap::LastKeyAccessTime(km_id_t keyid, uint32_t* last_access_time) const {
+ for (auto& entry : last_access_list_)
+ if (entry.keyid == keyid) {
+ *last_access_time = entry.access_time;
+ return true;
+ }
+ return false;
+}
+
+bool AccessTimeMap::UpdateKeyAccessTime(km_id_t keyid, uint32_t current_time, uint32_t timeout) {
+ for (auto iter = last_access_list_.begin(); iter != last_access_list_.end();) {
+ if (iter->keyid == keyid) {
+ iter->access_time = current_time;
+ return true;
+ }
+
+ // Expire entry if possible.
+ assert(current_time >= iter->access_time);
+ if (current_time - iter->access_time >= iter->timeout)
+ iter = last_access_list_.erase(iter);
+ else
+ ++iter;
+ }
+
+ if (last_access_list_.size() >= max_size_) return false;
+
+ AccessTime new_entry;
+ new_entry.keyid = keyid;
+ new_entry.access_time = current_time;
+ new_entry.timeout = timeout;
+ last_access_list_.push_front(new_entry);
+ return true;
+}
+
+bool AccessCountMap::KeyAccessCount(km_id_t keyid, uint32_t* count) const {
+ for (auto& entry : access_count_list_)
+ if (entry.keyid == keyid) {
+ *count = entry.access_count;
+ return true;
+ }
+ return false;
+}
+
+bool AccessCountMap::IncrementKeyAccessCount(km_id_t keyid) {
+ for (auto& entry : access_count_list_)
+ if (entry.keyid == keyid) {
+ // Note that the 'if' below will always be true because KM_TAG_MAX_USES_PER_BOOT is a
+ // uint32_t, and as soon as entry.access_count reaches the specified maximum value
+ // operation requests will be rejected and access_count won't be incremented any more.
+ // And, besides, UINT64_MAX is huge. But we ensure that it doesn't wrap anyway, out of
+ // an abundance of caution.
+ if (entry.access_count < UINT64_MAX) ++entry.access_count;
+ return true;
+ }
+
+ if (access_count_list_.size() >= max_size_) return false;
+
+ AccessCount new_entry;
+ new_entry.keyid = keyid;
+ new_entry.access_count = 1;
+ access_count_list_.push_front(new_entry);
+ return true;
+}
+}; /* namespace keystore */
diff --git a/keystore/keymaster_enforcement.h b/keystore/keymaster_enforcement.h
new file mode 100644
index 0000000..4f22f01
--- /dev/null
+++ b/keystore/keymaster_enforcement.h
@@ -0,0 +1,160 @@
+/*
+ * Copyright (C) 2014 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_KEYMASTER_ENFORCEMENT_H
+#define KEYSTORE_KEYMASTER_ENFORCEMENT_H
+
+#include <stdio.h>
+
+#include <keystore/authorization_set.h>
+
+namespace keystore {
+
+typedef uint64_t km_id_t;
+
+class KeymasterEnforcementContext {
+ public:
+ virtual ~KeymasterEnforcementContext() {}
+ /*
+ * Get current time.
+ */
+};
+
+class AccessTimeMap;
+class AccessCountMap;
+
+class KeymasterEnforcement {
+ public:
+ /**
+ * Construct a KeymasterEnforcement.
+ */
+ KeymasterEnforcement(uint32_t max_access_time_map_size, uint32_t max_access_count_map_size);
+ virtual ~KeymasterEnforcement();
+
+ /**
+ * Iterates through the authorization set and returns the corresponding keymaster error. Will
+ * return KM_ERROR_OK if all criteria is met for the given purpose in the authorization set with
+ * the given operation params and handle. Used for encrypt, decrypt sign, and verify.
+ */
+ ErrorCode AuthorizeOperation(const KeyPurpose purpose, const km_id_t keyid,
+ const AuthorizationSet& auth_set,
+ const AuthorizationSet& operation_params, uint64_t op_handle,
+ bool is_begin_operation);
+
+ /**
+ * Iterates through the authorization set and returns the corresponding keymaster error. Will
+ * return KM_ERROR_OK if all criteria is met for the given purpose in the authorization set with
+ * the given operation params. Used for encrypt, decrypt sign, and verify.
+ */
+ ErrorCode AuthorizeBegin(const KeyPurpose purpose, const km_id_t keyid,
+ const AuthorizationSet& auth_set,
+ const AuthorizationSet& operation_params);
+
+ /**
+ * Iterates through the authorization set and returns the corresponding keymaster error. Will
+ * return KM_ERROR_OK if all criteria is met for the given purpose in the authorization set with
+ * the given operation params and handle. Used for encrypt, decrypt sign, and verify.
+ */
+ ErrorCode AuthorizeUpdate(const AuthorizationSet& auth_set,
+ const AuthorizationSet& operation_params, uint64_t op_handle) {
+ return AuthorizeUpdateOrFinish(auth_set, operation_params, op_handle);
+ }
+
+ /**
+ * Iterates through the authorization set and returns the corresponding keymaster error. Will
+ * return KM_ERROR_OK if all criteria is met for the given purpose in the authorization set with
+ * the given operation params and handle. Used for encrypt, decrypt sign, and verify.
+ */
+ ErrorCode AuthorizeFinish(const AuthorizationSet& auth_set,
+ const AuthorizationSet& operation_params, uint64_t op_handle) {
+ return AuthorizeUpdateOrFinish(auth_set, operation_params, op_handle);
+ }
+
+ /**
+ * Creates a key ID for use in subsequent calls to AuthorizeOperation. Clients needn't use this
+ * method of creating key IDs, as long as they use something consistent and unique. This method
+ * hashes the key blob.
+ *
+ * Returns false if an error in the crypto library prevents creation of an ID.
+ */
+ static bool CreateKeyId(const hidl_vec<uint8_t>& key_blob, km_id_t* keyid);
+
+ //
+ // Methods that must be implemented by subclasses
+ //
+ // The time-related methods address the fact that different enforcement contexts may have
+ // different time-related capabilities. In particular:
+ //
+ // - They may or may not be able to check dates against real-world clocks.
+ //
+ // - They may or may not be able to check timestampls against authentication trustlets (minters
+ // of hw_auth_token_t structs).
+ //
+ // - They must have some time source for relative times, but may not be able to provide more
+ // than reliability and monotonicity.
+
+ /*
+ * Returns true if the specified activation date has passed, or if activation cannot be
+ * enforced.
+ */
+ virtual bool activation_date_valid(uint64_t activation_date) const = 0;
+
+ /*
+ * Returns true if the specified expiration date has passed. Returns false if it has not, or if
+ * expiration cannot be enforced.
+ */
+ virtual bool expiration_date_passed(uint64_t expiration_date) const = 0;
+
+ /*
+ * Returns true if the specified auth_token is older than the specified timeout.
+ */
+ virtual bool auth_token_timed_out(const hw_auth_token_t& token, uint32_t timeout) const = 0;
+
+ /*
+ * Get current time in seconds from some starting point. This value is used to compute relative
+ * times between events. It must be monotonically increasing, and must not skip or lag. It
+ * need not have any relation to any external time standard (other than the duration of
+ * "second").
+ *
+ * On POSIX systems, it's recommented to use clock_gettime(CLOCK_MONOTONIC, ...) to implement
+ * this method.
+ */
+ virtual uint32_t get_current_time() const = 0;
+
+ /*
+ * Returns true if the specified auth_token has a valid signature, or if signature validation is
+ * not available.
+ */
+ virtual bool ValidateTokenSignature(const hw_auth_token_t& token) const = 0;
+
+ private:
+ ErrorCode AuthorizeUpdateOrFinish(const AuthorizationSet& auth_set,
+ const AuthorizationSet& operation_params, uint64_t op_handle);
+
+ bool MinTimeBetweenOpsPassed(uint32_t min_time_between, const km_id_t keyid);
+ bool MaxUsesPerBootNotExceeded(const km_id_t keyid, uint32_t max_uses);
+ bool AuthTokenMatches(const AuthorizationSet& auth_set,
+ const AuthorizationSet& operation_params, const uint64_t user_secure_id,
+ const int auth_type_index, const int auth_timeout_index,
+ const uint64_t op_handle, bool is_begin_operation) const;
+
+ AccessTimeMap* access_time_map_;
+ AccessCountMap* access_count_map_;
+};
+
+}; /* namespace keystore */
+
+#endif // KEYSTORE_KEYMASTER_ENFORCEMENT_H
diff --git a/keystore/keystore.cpp b/keystore/keystore.cpp
index 0b86e83..3fc9efc 100644
--- a/keystore/keystore.cpp
+++ b/keystore/keystore.cpp
@@ -14,6 +14,8 @@
* limitations under the License.
*/
+#define LOG_TAG "keystore"
+
#include "keystore.h"
#include <dirent.h>
@@ -25,15 +27,20 @@
#include <keystore/IKeystoreService.h>
+#include <android/hardware/keymaster/3.0/IKeymasterDevice.h>
+
#include "keystore_utils.h"
#include "permissions.h"
+#include <keystore/keystore_hidl_support.h>
const char* KeyStore::sOldMasterKey = ".masterkey";
const char* KeyStore::sMetaDataFile = ".metadata";
const android::String16 KeyStore::sRSAKeyType("RSA");
-KeyStore::KeyStore(Entropy* entropy, keymaster2_device_t* device, keymaster2_device_t* fallback)
+using namespace keystore;
+
+KeyStore::KeyStore(Entropy* entropy, const km_device_t& device, const km_device_t& fallback)
: mEntropy(entropy), mDevice(device), mFallbackDevice(fallback) {
memset(&mMetaData, '\0', sizeof(mMetaData));
}
@@ -57,7 +64,7 @@
writeMetaData();
}
- return ::NO_ERROR;
+ return ResponseCode::NO_ERROR;
}
ResponseCode KeyStore::initializeUser(const android::String8& pw, uid_t userId) {
@@ -154,7 +161,7 @@
android::String8 prefix("");
android::Vector<android::String16> aliases;
UserState* userState = getUserState(userId);
- if (list(prefix, &aliases, userId) != ::NO_ERROR) {
+ if (list(prefix, &aliases, userId) != ResponseCode::NO_ERROR) {
return;
}
for (uint32_t i = 0; i < aliases.size(); i++) {
@@ -172,7 +179,7 @@
* other reasons err on the safe side and delete them since we
* can't tell if they're encrypted.
*/
- shouldDelete = !(rc == ::NO_ERROR && !blob.isEncrypted());
+ shouldDelete = !(rc == ResponseCode::NO_ERROR && !blob.isEncrypted());
}
if (shouldDelete) {
del(filename, ::TYPE_ANY, userId);
@@ -236,7 +243,7 @@
UserState* userState = getUserState(userId);
ResponseCode rc =
keyBlob->readBlob(filename, userState->getDecryptionKey(), userState->getState());
- if (rc != NO_ERROR) {
+ if (rc != ResponseCode::NO_ERROR) {
return rc;
}
@@ -247,28 +254,25 @@
* it's written.
*/
if (upgradeBlob(filename, keyBlob, version, type, userId)) {
- if ((rc = this->put(filename, keyBlob, userId)) != NO_ERROR ||
+ if ((rc = this->put(filename, keyBlob, userId)) != ResponseCode::NO_ERROR ||
(rc = keyBlob->readBlob(filename, userState->getDecryptionKey(),
- userState->getState())) != NO_ERROR) {
+ userState->getState())) != ResponseCode::NO_ERROR) {
return rc;
}
}
}
/*
- * This will upgrade software-backed keys to hardware-backed keys when
- * the HAL for the device supports the newer key types.
+ * This will upgrade software-backed keys to hardware-backed keys.
*/
- if (rc == NO_ERROR && type == TYPE_KEY_PAIR &&
- mDevice->common.module->module_api_version >= KEYMASTER_MODULE_API_VERSION_0_2 &&
- keyBlob->isFallback()) {
+ if (rc == ResponseCode::NO_ERROR && type == TYPE_KEY_PAIR && keyBlob->isFallback()) {
ResponseCode imported =
importKey(keyBlob->getValue(), keyBlob->getLength(), filename, userId,
keyBlob->isEncrypted() ? KEYSTORE_FLAG_ENCRYPTED : KEYSTORE_FLAG_NONE);
// The HAL allowed the import, reget the key to have the "fresh"
// version.
- if (imported == NO_ERROR) {
+ if (imported == ResponseCode::NO_ERROR) {
rc = get(filename, keyBlob, TYPE_KEY_PAIR, userId);
}
}
@@ -281,7 +285,7 @@
if (type != TYPE_ANY && keyBlob->getType() != type) {
ALOGW("key found but type doesn't match: %d vs %d", keyBlob->getType(), type);
- return KEY_NOT_FOUND;
+ return ResponseCode::KEY_NOT_FOUND;
}
return rc;
@@ -296,38 +300,25 @@
ResponseCode KeyStore::del(const char* filename, const BlobType type, uid_t userId) {
Blob keyBlob;
ResponseCode rc = get(filename, &keyBlob, type, userId);
- if (rc == ::VALUE_CORRUPTED) {
+ if (rc == ResponseCode::VALUE_CORRUPTED) {
// The file is corrupt, the best we can do is rm it.
- return (unlink(filename) && errno != ENOENT) ? ::SYSTEM_ERROR : ::NO_ERROR;
+ return (unlink(filename) && errno != ENOENT) ?
+ ResponseCode::SYSTEM_ERROR : ResponseCode::NO_ERROR;
}
- if (rc != ::NO_ERROR) {
+ if (rc != ResponseCode::NO_ERROR) {
return rc;
}
- if (keyBlob.getType() == ::TYPE_KEY_PAIR) {
+ if (keyBlob.getType() == ::TYPE_KEY_PAIR || keyBlob.getType() == ::TYPE_KEYMASTER_10) {
+ auto ret = KS_HANDLE_HIDL_ERROR(mDevice->deleteKey(blob2hidlVec(keyBlob)));
+
// A device doesn't have to implement delete_key.
- if (mDevice->delete_key != NULL && !keyBlob.isFallback()) {
- keymaster_key_blob_t blob = {keyBlob.getValue(),
- static_cast<size_t>(keyBlob.getLength())};
- if (mDevice->delete_key(mDevice, &blob)) {
- rc = ::SYSTEM_ERROR;
- }
- }
- }
- if (keyBlob.getType() == ::TYPE_KEYMASTER_10) {
- auto* dev = getDeviceForBlob(keyBlob);
- if (dev->delete_key) {
- keymaster_key_blob_t blob;
- blob.key_material = keyBlob.getValue();
- blob.key_material_size = keyBlob.getLength();
- dev->delete_key(dev, &blob);
- }
- }
- if (rc != ::NO_ERROR) {
- return rc;
+ if (ret != ErrorCode::OK && ret != ErrorCode::UNIMPLEMENTED)
+ return ResponseCode::SYSTEM_ERROR;
}
- return (unlink(filename) && errno != ENOENT) ? ::SYSTEM_ERROR : ::NO_ERROR;
+ return (unlink(filename) && errno != ENOENT) ?
+ ResponseCode::SYSTEM_ERROR : ResponseCode::NO_ERROR;
}
/*
@@ -376,7 +367,7 @@
DIR* dir = opendir(userState->getUserDirName());
if (!dir) {
ALOGW("can't open directory for user: %s", strerror(errno));
- return ::SYSTEM_ERROR;
+ return ResponseCode::SYSTEM_ERROR;
}
struct dirent* file;
@@ -407,7 +398,7 @@
}
}
closedir(dir);
- return ::NO_ERROR;
+ return ResponseCode::NO_ERROR;
}
void KeyStore::addGrant(const char* filename, uid_t granteeUid) {
@@ -436,74 +427,68 @@
uid_t userId, int32_t flags) {
Unique_PKCS8_PRIV_KEY_INFO pkcs8(d2i_PKCS8_PRIV_KEY_INFO(NULL, &key, keyLen));
if (!pkcs8.get()) {
- return ::SYSTEM_ERROR;
+ return ResponseCode::SYSTEM_ERROR;
}
Unique_EVP_PKEY pkey(EVP_PKCS82PKEY(pkcs8.get()));
if (!pkey.get()) {
- return ::SYSTEM_ERROR;
+ return ResponseCode::SYSTEM_ERROR;
}
int type = EVP_PKEY_type(pkey->type);
- android::KeymasterArguments params;
- add_legacy_key_authorizations(type, ¶ms.params);
+ AuthorizationSet params;
+ add_legacy_key_authorizations(type, ¶ms);
switch (type) {
case EVP_PKEY_RSA:
- params.params.push_back(keymaster_param_enum(KM_TAG_ALGORITHM, KM_ALGORITHM_RSA));
+ params.push_back(TAG_ALGORITHM, Algorithm::RSA);
break;
case EVP_PKEY_EC:
- params.params.push_back(keymaster_param_enum(KM_TAG_ALGORITHM, KM_ALGORITHM_EC));
+ params.push_back(TAG_ALGORITHM, Algorithm::EC);
break;
default:
ALOGW("Unsupported key type %d", type);
- return ::SYSTEM_ERROR;
+ return ResponseCode::SYSTEM_ERROR;
}
- std::vector<keymaster_key_param_t> opParams(params.params);
- const keymaster_key_param_set_t inParams = {opParams.data(), opParams.size()};
- keymaster_blob_t input = {key, keyLen};
- keymaster_key_blob_t blob = {nullptr, 0};
- bool isFallback = false;
- keymaster_error_t error = mDevice->import_key(mDevice, &inParams, KM_KEY_FORMAT_PKCS8, &input,
- &blob, NULL /* characteristics */);
- if (error != KM_ERROR_OK) {
- ALOGE("Keymaster error %d importing key pair, falling back", error);
+ AuthorizationSet opParams(params);
+ hidl_vec<uint8_t> blob;
- /*
- * There should be no way to get here. Fallback shouldn't ever really happen
- * because the main device may be many (SW, KM0/SW hybrid, KM1/SW hybrid), but it must
- * provide full support of the API. In any case, we'll do the fallback just for
- * consistency... and I suppose to cover for broken HW implementations.
- */
- error = mFallbackDevice->import_key(mFallbackDevice, &inParams, KM_KEY_FORMAT_PKCS8, &input,
- &blob, NULL /* characteristics */);
- isFallback = true;
+ ErrorCode error;
+ auto hidlCb = [&] (ErrorCode ret, const hidl_vec<uint8_t>& keyBlob,
+ const KeyCharacteristics& /* ignored */) {
+ error = ret;
+ if (error != ErrorCode::OK) return;
+ blob = keyBlob;
+ };
+ auto input = blob2hidlVec(key, keyLen);
- if (error) {
- ALOGE("Keymaster error while importing key pair with fallback: %d", error);
- return SYSTEM_ERROR;
- }
+ ErrorCode rc = KS_HANDLE_HIDL_ERROR(
+ mDevice->importKey(params.hidl_data(), KeyFormat::PKCS8, input, hidlCb));
+ if (rc != ErrorCode::OK) return ResponseCode::SYSTEM_ERROR;
+ if (error != ErrorCode::OK) {
+ ALOGE("Keymaster error %d importing key pair", error);
+ return ResponseCode::SYSTEM_ERROR;
}
- Blob keyBlob(blob.key_material, blob.key_material_size, NULL, 0, TYPE_KEYMASTER_10);
- free(const_cast<uint8_t*>(blob.key_material));
+ Blob keyBlob(&blob[0], blob.size(), NULL, 0, TYPE_KEYMASTER_10);
keyBlob.setEncrypted(flags & KEYSTORE_FLAG_ENCRYPTED);
- keyBlob.setFallback(isFallback);
+ keyBlob.setFallback(false);
return put(filename, &keyBlob, userId);
}
-bool KeyStore::isHardwareBacked(const android::String16& keyType) const {
+bool KeyStore::isHardwareBacked(const android::String16& /*keyType*/) const {
if (mDevice == NULL) {
ALOGW("can't get keymaster device");
return false;
}
-
- if (sRSAKeyType == keyType) {
- return (mDevice->flags & KEYMASTER_SOFTWARE_ONLY) == 0;
- } else {
- return (mDevice->flags & KEYMASTER_SOFTWARE_ONLY) == 0 &&
- (mDevice->common.module->module_api_version >= KEYMASTER_MODULE_API_VERSION_0_2);
- }
+// TODO: This information seems not to be available here
+// if (sRSAKeyType == keyType) {
+// return (mDevice->flags & KEYMASTER_SOFTWARE_ONLY) == 0;
+// } else {
+// return (mDevice->flags & KEYMASTER_SOFTWARE_ONLY) == 0 &&
+// (mDevice->common.module->module_api_version >= KEYMASTER_MODULE_API_VERSION_0_2);
+// }
+ return true;
}
ResponseCode KeyStore::getKeyForName(Blob* keyBlob, const android::String8& keyName,
@@ -512,7 +497,7 @@
uid_t userId = get_user_id(uid);
ResponseCode responseCode = get(filepath8.string(), keyBlob, type, userId);
- if (responseCode == NO_ERROR) {
+ if (responseCode == ResponseCode::NO_ERROR) {
return responseCode;
}
@@ -521,7 +506,7 @@
if (euid != uid) {
filepath8 = getKeyNameForUidWithDir(keyName, euid, type);
responseCode = get(filepath8.string(), keyBlob, type, userId);
- if (responseCode == NO_ERROR) {
+ if (responseCode == ResponseCode::NO_ERROR) {
return responseCode;
}
}
@@ -531,7 +516,7 @@
char* end;
strtoul(filename8.string(), &end, 10);
if (end[0] != '_' || end[1] == 0) {
- return KEY_NOT_FOUND;
+ return ResponseCode::KEY_NOT_FOUND;
}
filepath8 = android::String8::format("%s/%s", getUserState(userId)->getUserDirName(),
filename8.string());
@@ -645,32 +630,32 @@
Unique_BIO b(BIO_new_mem_buf(const_cast<uint8_t*>(blob->getValue()), blob->getLength()));
if (b.get() == NULL) {
ALOGE("Problem instantiating BIO");
- return SYSTEM_ERROR;
+ return ResponseCode::SYSTEM_ERROR;
}
Unique_EVP_PKEY pkey(PEM_read_bio_PrivateKey(b.get(), NULL, NULL, NULL));
if (pkey.get() == NULL) {
ALOGE("Couldn't read old PEM file");
- return SYSTEM_ERROR;
+ return ResponseCode::SYSTEM_ERROR;
}
Unique_PKCS8_PRIV_KEY_INFO pkcs8(EVP_PKEY2PKCS8(pkey.get()));
int len = i2d_PKCS8_PRIV_KEY_INFO(pkcs8.get(), NULL);
if (len < 0) {
ALOGE("Couldn't measure PKCS#8 length");
- return SYSTEM_ERROR;
+ return ResponseCode::SYSTEM_ERROR;
}
UniquePtr<unsigned char[]> pkcs8key(new unsigned char[len]);
uint8_t* tmp = pkcs8key.get();
if (i2d_PKCS8_PRIV_KEY_INFO(pkcs8.get(), &tmp) != len) {
ALOGE("Couldn't convert to PKCS#8");
- return SYSTEM_ERROR;
+ return ResponseCode::SYSTEM_ERROR;
}
ResponseCode rc = importKey(pkcs8key.get(), len, filename, get_user_id(uid),
blob->isEncrypted() ? KEYSTORE_FLAG_ENCRYPTED : KEYSTORE_FLAG_NONE);
- if (rc != NO_ERROR) {
+ if (rc != ResponseCode::NO_ERROR) {
return rc;
}
diff --git a/keystore/keystore.h b/keystore/keystore.h
index 278a0a0..210d99d 100644
--- a/keystore/keystore.h
+++ b/keystore/keystore.h
@@ -19,7 +19,7 @@
#include "user_state.h"
-#include <hardware/keymaster2.h>
+#include <android/hardware/keymaster/3.0/IKeymasterDevice.h>
#include <utils/Vector.h>
@@ -31,15 +31,17 @@
} grant_t;
class KeyStore {
+ typedef ::android::sp<::android::hardware::keymaster::V3_0::IKeymasterDevice> km_device_t;
+
public:
- KeyStore(Entropy* entropy, keymaster2_device_t* device, keymaster2_device_t* fallback);
+ KeyStore(Entropy* entropy, const km_device_t& device, const km_device_t& fallback);
~KeyStore();
- keymaster2_device_t* getDevice() const { return mDevice; }
+ km_device_t& getDevice() { return mDevice; }
- keymaster2_device_t* getFallbackDevice() const { return mFallbackDevice; }
+ km_device_t& getFallbackDevice() { return mFallbackDevice; }
- keymaster2_device_t* getDeviceForBlob(const Blob& blob) const {
+ km_device_t& getDevice(const Blob& blob) {
return blob.isFallback() ? mFallbackDevice : mDevice;
}
@@ -115,8 +117,8 @@
static const android::String16 sRSAKeyType;
Entropy* mEntropy;
- keymaster2_device_t* mDevice;
- keymaster2_device_t* mFallbackDevice;
+ km_device_t mDevice;
+ km_device_t mFallbackDevice;
android::Vector<UserState*> mMasterKeys;
diff --git a/keystore/keystore_aidl_hidl_marshalling_utils.cpp b/keystore/keystore_aidl_hidl_marshalling_utils.cpp
new file mode 100644
index 0000000..3137ae1
--- /dev/null
+++ b/keystore/keystore_aidl_hidl_marshalling_utils.cpp
@@ -0,0 +1,225 @@
+/*
+**
+** Copyright 2016, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+#define LOG_TAG "KeystoreService"
+#include <utils/Log.h>
+
+#include "keystore_aidl_hidl_marshalling_utils.h"
+#include <keystore/keystore_hidl_support.h>
+
+namespace keystore {
+
+hidl_vec<uint8_t> readKeymasterBlob(const android::Parcel& in, bool inPlace) {
+ ssize_t length = in.readInt32();
+ if (length <= 0) {
+ return {};
+ }
+
+ const void* buf = in.readInplace(length);
+ if (!buf) return {};
+
+ return blob2hidlVec(reinterpret_cast<const uint8_t*>(buf), size_t(length), inPlace);
+}
+
+android::status_t writeKeymasterBlob(const hidl_vec<uint8_t>& blob, android::Parcel* out) {
+ int32_t size = int32_t(std::min<size_t>(blob.size(), std::numeric_limits<int32_t>::max()));
+
+ auto rc = out->writeInt32(size);
+ if (rc != ::android::OK) return rc;
+
+ if (!size) return ::android::OK;
+
+ return out->write(&blob[0], size);
+}
+
+NullOr<hidl_vec<uint8_t>> readBlobAsByteArray(const android::Parcel& in, bool inPlace) {
+ // The distinction from readKeymasterBob is that the byte array is not prefixed with a presence
+ // value, instead a -1 in the length field indicates NULL.
+ ssize_t length = in.readInt32();
+ if (length < 0) {
+ return {};
+ }
+
+ if (length == 0) {
+ return hidl_vec<uint8_t>();
+ }
+
+ const void* buf = in.readInplace(length);
+ if (!buf) return hidl_vec<uint8_t>();
+
+ return blob2hidlVec(reinterpret_cast<const uint8_t*>(buf), size_t(length), inPlace);
+}
+
+android::status_t writeBlobAsByteArray(const NullOr<const hidl_vec<uint8_t>&>& blob,
+ android::Parcel* out) {
+ if (!blob.isOk()) {
+ return out->writeInt32(-1);
+ }
+ int32_t size =
+ int32_t(std::min<size_t>(blob.value().size(), std::numeric_limits<int32_t>::max()));
+
+ auto rc = out->writeInt32(size);
+ if (rc != ::android::OK) return rc;
+
+ if (!size) return ::android::OK;
+
+ return out->write(&blob.value()[0], size);
+}
+
+NullOr<KeyParameter> readKeyParameterFromParcel(const android::Parcel& in) {
+ if (in.readInt32() == 0) {
+ return {};
+ }
+ KeyParameter result;
+
+ Tag tag = static_cast<Tag>(in.readInt32());
+ result.tag = tag;
+ switch (typeFromTag(tag)) {
+ case TagType::ENUM:
+ case TagType::ENUM_REP:
+ case TagType::UINT:
+ case TagType::UINT_REP:
+ result.f.integer = in.readInt32();
+ break;
+ case TagType::ULONG:
+ case TagType::ULONG_REP:
+ case TagType::DATE:
+ result.f.longInteger = in.readInt64();
+ break;
+ case TagType::BOOL:
+ result.f.boolValue = true;
+ break;
+ case TagType::BIGNUM:
+ case TagType::BYTES:
+ result.blob = readKeymasterBlob(in);
+ break;
+ default:
+ ALOGE("Unsupported KeyParameter tag %d", tag);
+ return {};
+ }
+ return result;
+}
+
+android::status_t writeKeyParameterToParcel(const KeyParameter& param, android::Parcel* out) {
+ auto tag = param.tag;
+ auto rc = out->writeInt32(uint32_t(tag));
+ if (rc != ::android::OK) return rc;
+ switch (typeFromTag(param.tag)) {
+ case TagType::ENUM:
+ case TagType::ENUM_REP:
+ case TagType::UINT:
+ case TagType::UINT_REP:
+ rc = out->writeInt32(param.f.integer);
+ break;
+ case TagType::ULONG:
+ case TagType::ULONG_REP:
+ case TagType::DATE:
+ rc = out->writeInt64(param.f.longInteger);
+ break;
+ case TagType::BOOL:
+ // nothing to do here presence indicates true
+ break;
+ case TagType::BIGNUM:
+ case TagType::BYTES:
+ rc = writeKeymasterBlob(param.blob, out);
+ break;
+ default:
+ ALOGE("Failed to write KeyParameter: Unsupported tag %d", param.tag);
+ rc = android::BAD_VALUE;
+ break;
+ }
+ return rc;
+}
+
+hidl_vec<KeyParameter> readParamSetFromParcel(const android::Parcel& in) {
+ ssize_t length = in.readInt32();
+ size_t ulength = (size_t)length;
+ if (length < 0) {
+ ulength = 0;
+ }
+ hidl_vec<KeyParameter> result;
+ result.resize(ulength);
+ for (size_t i = 0; i < ulength; ++i) {
+ auto param = readKeyParameterFromParcel(in);
+ if (!param.isOk()) {
+ ALOGE("Error reading KeyParameter from parcel");
+ return {};
+ }
+ result[i] = param.value();
+ }
+ return result;
+}
+
+android::status_t writeParamSetToParcel(const hidl_vec<KeyParameter>& params,
+ android::Parcel* out) {
+ int32_t size = int32_t(std::min<size_t>(params.size(), std::numeric_limits<int32_t>::max()));
+
+ auto rc = out->writeInt32(size);
+ if (rc != ::android::OK) return rc;
+ for (int32_t i = 0; i < size; ++i) {
+ rc = out->writeInt32(1);
+ if (rc != ::android::OK) return rc;
+ rc = writeKeyParameterToParcel(params[i], out);
+ if (rc != ::android::OK) return rc;
+ }
+ return rc;
+}
+
+KeyCharacteristics readKeyCharacteristicsFromParcel(const android::Parcel& in) {
+ KeyCharacteristics result;
+ result.softwareEnforced = readParamSetFromParcel(in);
+ result.teeEnforced = readParamSetFromParcel(in);
+ return result;
+}
+
+android::status_t writeKeyCharacteristicsToParcel(const KeyCharacteristics& keyChara,
+ android::Parcel* out) {
+ auto rc = writeParamSetToParcel(keyChara.softwareEnforced, out);
+ if (rc != ::android::OK) return rc;
+
+ return writeParamSetToParcel(keyChara.teeEnforced, out);
+}
+
+hidl_vec<hidl_vec<uint8_t>> readCertificateChainFromParcel(const android::Parcel& in) {
+ hidl_vec<hidl_vec<uint8_t>> result;
+
+ ssize_t count = in.readInt32();
+ size_t ucount = count;
+ if (count <= 0) {
+ return result;
+ }
+
+ result.resize(ucount);
+
+ for (size_t i = 0; i < ucount; ++i) {
+ result[i] = readKeymasterBlob(in);
+ }
+ return result;
+}
+
+android::status_t writeCertificateChainToParcel(const hidl_vec<hidl_vec<uint8_t>>& certs,
+ android::Parcel* out) {
+ int32_t count = int32_t(std::min<size_t>(certs.size(), std::numeric_limits<int32_t>::max()));
+ auto rc = out->writeInt32(count);
+
+ for (int32_t i = 0; i < count; ++i) {
+ rc = writeKeymasterBlob(certs[i], out);
+ if (rc != ::android::OK) return rc;
+ }
+ return rc;
+}
+}
diff --git a/keystore/keystore_aidl_hidl_marshalling_utils.h b/keystore/keystore_aidl_hidl_marshalling_utils.h
new file mode 100644
index 0000000..fcd02ae
--- /dev/null
+++ b/keystore/keystore_aidl_hidl_marshalling_utils.h
@@ -0,0 +1,83 @@
+/*
+**
+** Copyright 2016, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+#ifndef KEYSTORE_KEYSTORE_AIDL_HIDL_MARSHALLING_UTILS_H_
+#define KEYSTORE_KEYSTORE_AIDL_HIDL_MARSHALLING_UTILS_H_
+
+#include <binder/Parcel.h>
+#include <keystore/keymaster_tags.h>
+#include <utility>
+
+namespace keystore {
+
+template <typename Fn, typename... Args>
+inline auto nullable(Fn fn, const android::Parcel& in, Args&&... args)
+ -> NullOr<decltype(fn(in, std::forward<Args>(args)...))> {
+ if (in.readInt32() != 1) {
+ return {};
+ }
+
+ return fn(in, std::forward<Args>(args)...);
+}
+template <typename Fn, typename Arg>
+inline android::status_t nullable(Fn fn, const NullOr<Arg>& arg, android::Parcel* out) {
+ if (!arg.isOk()) {
+ return out->writeInt32(0);
+ }
+ auto rc = out->writeInt32(1);
+ if (rc != ::android::OK) return rc;
+
+ return fn(arg.value(), out);
+}
+template <typename Fn, typename Arg>
+inline android::status_t nullable(Fn fn, Arg&& arg, android::Parcel* out) {
+ auto rc = out->writeInt32(1);
+ if (rc != ::android::OK) return rc;
+
+ return fn(std::forward<Arg>(arg), out);
+}
+
+inline android::status_t nullable(android::Parcel* out) {
+ return out->writeInt32(0);
+}
+
+/**
+ * makes a copy only if inPlace is false
+ */
+hidl_vec<uint8_t> readKeymasterBlob(const android::Parcel& in, bool inPlace = true);
+android::status_t writeKeymasterBlob(const hidl_vec<uint8_t>& blob, android::Parcel* out);
+
+NullOr<hidl_vec<uint8_t>> readBlobAsByteArray(const android::Parcel& in, bool inPlace = true);
+android::status_t writeBlobAsByteArray(const NullOr<const hidl_vec<uint8_t>&>& blob,
+ android::Parcel* out);
+
+NullOr<KeyParameter> readKeyParameterFromParcel(const android::Parcel& in);
+android::status_t writeKeyParameterToParcel(const KeyParameter& param, android::Parcel* out);
+
+hidl_vec<KeyParameter> readParamSetFromParcel(const android::Parcel& in);
+android::status_t writeParamSetToParcel(const hidl_vec<KeyParameter>& params, android::Parcel* out);
+
+KeyCharacteristics readKeyCharacteristicsFromParcel(const android::Parcel& in);
+android::status_t writeKeyCharacteristicsToParcel(const KeyCharacteristics& keyChara,
+ android::Parcel* out);
+
+hidl_vec<hidl_vec<uint8_t>> readCertificateChainFromParcel(const android::Parcel& in);
+android::status_t writeCertificateChainToParcel(const hidl_vec<hidl_vec<uint8_t>>& certs,
+ android::Parcel* out);
+}
+
+#endif // KEYSTORE_KEYSTORE_AIDL_HIDL_MARSHALLING_UTILS_H_
diff --git a/keystore/keystore_cli.cpp b/keystore/keystore_cli.cpp
index d9781e0..24af024 100644
--- a/keystore/keystore_cli.cpp
+++ b/keystore/keystore_cli.cpp
@@ -26,6 +26,7 @@
#include <keystore/keystore.h>
using namespace android;
+using namespace keystore;
static const char* responses[] = {
NULL,
@@ -124,14 +125,13 @@
fprintf(stderr, "Usage: %s " #cmd " <name> <uid>\n", argv[0]); \
return 1; \
} \
- uint8_t* data; \
- size_t dataSize; \
+ hidl_vec<uint8_t> data; \
int uid = -1; \
if (argc > 3) { \
uid = atoi(argv[3]); \
fprintf(stderr, "Running as uid %d\n", uid); \
} \
- int32_t ret = service->cmd(String16(argv[2]), uid, &data, &dataSize); \
+ int32_t ret = service->cmd(String16(argv[2]), uid, &data); \
if (ret < 0) { \
fprintf(stderr, "%s: could not connect: %d\n", argv[0], ret); \
return 1; \
@@ -139,9 +139,8 @@
fprintf(stderr, "%s: " #cmd ": %s (%d)\n", argv[0], responses[ret], ret); \
return 1; \
} else { \
- fwrite(data, dataSize, 1, stdout); \
+ fwrite(&data[0], data.size(), 1, stdout); \
fflush(stdout); \
- free(data); \
return 0; \
} \
} \
@@ -175,9 +174,8 @@
fprintf(stderr, "Usage: %s " #cmd " <name>\n", argv[0]); \
return 1; \
} \
- uint8_t* data; \
- size_t dataSize; \
- int32_t ret = service->cmd(String16(argv[2]), &data, &dataSize); \
+ hidl_vec<uint8_t> data; \
+ int32_t ret = service->cmd(String16(argv[2]), &data); \
if (ret < 0) { \
fprintf(stderr, "%s: could not connect: %d\n", argv[0], ret); \
return 1; \
@@ -185,9 +183,8 @@
fprintf(stderr, "%s: " #cmd ": %s (%d)\n", argv[0], responses[ret], ret); \
return 1; \
} else { \
- fwrite(data, dataSize, 1, stdout); \
+ fwrite(&data[0], data.size(), 1, stdout); \
fflush(stdout); \
- free(data); \
return 0; \
} \
} \
diff --git a/keystore/keystore_cli_v2.cpp b/keystore/keystore_cli_v2.cpp
index 6c229db..95fc491 100644
--- a/keystore/keystore_cli_v2.cpp
+++ b/keystore/keystore_cli_v2.cpp
@@ -20,16 +20,17 @@
#include "base/command_line.h"
#include "base/files/file_util.h"
#include "base/strings/string_util.h"
-#include "keymaster/authorization_set.h"
-#include "keymaster/keymaster_tags.h"
+#include "keystore/authorization_set.h"
+#include "keystore/keymaster_tags.h"
#include "keystore/keystore_client_impl.h"
using base::CommandLine;
-using keymaster::AuthorizationSet;
-using keymaster::AuthorizationSetBuilder;
+using keystore::AuthorizationSet;
+//using keymaster::AuthorizationSetBuilder;
using keystore::KeystoreClient;
namespace {
+using namespace keystore;
struct TestCase {
std::string name;
@@ -55,17 +56,13 @@
}
std::unique_ptr<KeystoreClient> CreateKeystoreInstance() {
- return std::unique_ptr<KeystoreClient>(new keystore::KeystoreClientImpl);
+ return std::unique_ptr<KeystoreClient>(
+ static_cast<KeystoreClient*>(new keystore::KeystoreClientImpl));
}
-#ifndef KEYMASTER_NAME_TAGS
-#error KEYMASTER_NAME_TAGS must be defined
-#endif
-
void PrintTags(const AuthorizationSet& parameters) {
- const keymaster_key_param_t* iter = nullptr;
- for (iter = parameters.begin(); iter != parameters.end(); ++iter) {
- printf(" %s\n", keymaster::StringifyTag(iter->tag));
+ for (auto iter = parameters.begin(); iter != parameters.end(); ++iter) {
+ printf(" %s\n", stringifyTag(iter->tag));
}
}
@@ -81,16 +78,16 @@
std::unique_ptr<KeystoreClient> keystore = CreateKeystoreInstance();
AuthorizationSet hardware_enforced_characteristics;
AuthorizationSet software_enforced_characteristics;
- int32_t result = keystore->generateKey("tmp", parameters, &hardware_enforced_characteristics,
+ auto result = keystore->generateKey("tmp", parameters, &hardware_enforced_characteristics,
&software_enforced_characteristics);
const char kBoldRedAbort[] = "\033[1;31mABORT\033[0m";
- if (result != KM_ERROR_OK) {
+ if (!result.isOk()) {
LOG(ERROR) << "Failed to generate key: " << result;
printf("[%s] %s\n", kBoldRedAbort, name.c_str());
return false;
}
result = keystore->deleteKey("tmp");
- if (result != KM_ERROR_OK) {
+ if (!result.isOk()) {
LOG(ERROR) << "Failed to delete key: " << result;
printf("[%s] %s\n", kBoldRedAbort, name.c_str());
return false;
@@ -99,9 +96,9 @@
printf("%s Key Characteristics:\n", name.c_str());
PrintKeyCharacteristics(hardware_enforced_characteristics, software_enforced_characteristics);
bool hardware_backed = (hardware_enforced_characteristics.size() > 0);
- if (software_enforced_characteristics.GetTagCount(KM_TAG_ALGORITHM) > 0 ||
- software_enforced_characteristics.GetTagCount(KM_TAG_KEY_SIZE) > 0 ||
- software_enforced_characteristics.GetTagCount(KM_TAG_RSA_PUBLIC_EXPONENT) > 0) {
+ if (software_enforced_characteristics.GetTagCount(TAG_ALGORITHM) > 0 ||
+ software_enforced_characteristics.GetTagCount(TAG_KEY_SIZE) > 0 ||
+ software_enforced_characteristics.GetTagCount(TAG_RSA_PUBLIC_EXPONENT) > 0) {
VLOG(1) << "Hardware-backed key but required characteristics enforced in software.";
hardware_backed = false;
}
@@ -118,62 +115,62 @@
AuthorizationSet GetRSASignParameters(uint32_t key_size, bool sha256_only) {
AuthorizationSetBuilder parameters;
parameters.RsaSigningKey(key_size, 65537)
- .Digest(KM_DIGEST_SHA_2_256)
- .Padding(KM_PAD_RSA_PKCS1_1_5_SIGN)
- .Padding(KM_PAD_RSA_PSS)
- .Authorization(keymaster::TAG_NO_AUTH_REQUIRED);
+ .Digest(Digest::SHA_2_256)
+ .Padding(PaddingMode::RSA_PKCS1_1_5_SIGN)
+ .Padding(PaddingMode::RSA_PSS)
+ .Authorization(TAG_NO_AUTH_REQUIRED);
if (!sha256_only) {
- parameters.Digest(KM_DIGEST_SHA_2_224)
- .Digest(KM_DIGEST_SHA_2_384)
- .Digest(KM_DIGEST_SHA_2_512);
+ parameters.Digest(Digest::SHA_2_224)
+ .Digest(Digest::SHA_2_384)
+ .Digest(Digest::SHA_2_512);
}
- return parameters.build();
+ return parameters;
}
AuthorizationSet GetRSAEncryptParameters(uint32_t key_size) {
AuthorizationSetBuilder parameters;
parameters.RsaEncryptionKey(key_size, 65537)
- .Padding(KM_PAD_RSA_PKCS1_1_5_ENCRYPT)
- .Padding(KM_PAD_RSA_OAEP)
- .Authorization(keymaster::TAG_NO_AUTH_REQUIRED);
- return parameters.build();
+ .Padding(PaddingMode::RSA_PKCS1_1_5_ENCRYPT)
+ .Padding(PaddingMode::RSA_OAEP)
+ .Authorization(TAG_NO_AUTH_REQUIRED);
+ return parameters;
}
AuthorizationSet GetECDSAParameters(uint32_t key_size, bool sha256_only) {
AuthorizationSetBuilder parameters;
parameters.EcdsaSigningKey(key_size)
- .Digest(KM_DIGEST_SHA_2_256)
- .Authorization(keymaster::TAG_NO_AUTH_REQUIRED);
+ .Digest(Digest::SHA_2_256)
+ .Authorization(TAG_NO_AUTH_REQUIRED);
if (!sha256_only) {
- parameters.Digest(KM_DIGEST_SHA_2_224)
- .Digest(KM_DIGEST_SHA_2_384)
- .Digest(KM_DIGEST_SHA_2_512);
+ parameters.Digest(Digest::SHA_2_224)
+ .Digest(Digest::SHA_2_384)
+ .Digest(Digest::SHA_2_512);
}
- return parameters.build();
+ return parameters;
}
AuthorizationSet GetAESParameters(uint32_t key_size, bool with_gcm_mode) {
AuthorizationSetBuilder parameters;
- parameters.AesEncryptionKey(key_size).Authorization(keymaster::TAG_NO_AUTH_REQUIRED);
+ parameters.AesEncryptionKey(key_size).Authorization(TAG_NO_AUTH_REQUIRED);
if (with_gcm_mode) {
- parameters.Authorization(keymaster::TAG_BLOCK_MODE, KM_MODE_GCM)
- .Authorization(keymaster::TAG_MIN_MAC_LENGTH, 128);
+ parameters.Authorization(TAG_BLOCK_MODE, BlockMode::GCM)
+ .Authorization(TAG_MIN_MAC_LENGTH, 128);
} else {
- parameters.Authorization(keymaster::TAG_BLOCK_MODE, KM_MODE_ECB);
- parameters.Authorization(keymaster::TAG_BLOCK_MODE, KM_MODE_CBC);
- parameters.Authorization(keymaster::TAG_BLOCK_MODE, KM_MODE_CTR);
- parameters.Padding(KM_PAD_NONE);
+ parameters.Authorization(TAG_BLOCK_MODE, BlockMode::ECB);
+ parameters.Authorization(TAG_BLOCK_MODE, BlockMode::CBC);
+ parameters.Authorization(TAG_BLOCK_MODE, BlockMode::CTR);
+ parameters.Padding(PaddingMode::NONE);
}
- return parameters.build();
+ return parameters;
}
-AuthorizationSet GetHMACParameters(uint32_t key_size, keymaster_digest_t digest) {
+AuthorizationSet GetHMACParameters(uint32_t key_size, Digest digest) {
AuthorizationSetBuilder parameters;
parameters.HmacKey(key_size)
.Digest(digest)
- .Authorization(keymaster::TAG_MIN_MAC_LENGTH, 224)
- .Authorization(keymaster::TAG_NO_AUTH_REQUIRED);
- return parameters.build();
+ .Authorization(TAG_MIN_MAC_LENGTH, 224)
+ .Authorization(TAG_NO_AUTH_REQUIRED);
+ return parameters;
}
std::vector<TestCase> GetTestCases() {
@@ -194,12 +191,12 @@
{"AES-256", true, GetAESParameters(256, false)},
{"AES-128-GCM", false, GetAESParameters(128, true)},
{"AES-256-GCM", false, GetAESParameters(256, true)},
- {"HMAC-SHA256-16", true, GetHMACParameters(16, KM_DIGEST_SHA_2_256)},
- {"HMAC-SHA256-32", true, GetHMACParameters(32, KM_DIGEST_SHA_2_256)},
- {"HMAC-SHA256-64", false, GetHMACParameters(64, KM_DIGEST_SHA_2_256)},
- {"HMAC-SHA224-32", false, GetHMACParameters(32, KM_DIGEST_SHA_2_224)},
- {"HMAC-SHA384-32", false, GetHMACParameters(32, KM_DIGEST_SHA_2_384)},
- {"HMAC-SHA512-32", false, GetHMACParameters(32, KM_DIGEST_SHA_2_512)},
+ {"HMAC-SHA256-16", true, GetHMACParameters(16, Digest::SHA_2_256)},
+ {"HMAC-SHA256-32", true, GetHMACParameters(32, Digest::SHA_2_256)},
+ {"HMAC-SHA256-64", false, GetHMACParameters(64, Digest::SHA_2_256)},
+ {"HMAC-SHA224-32", false, GetHMACParameters(32, Digest::SHA_2_224)},
+ {"HMAC-SHA384-32", false, GetHMACParameters(32, Digest::SHA_2_384)},
+ {"HMAC-SHA512-32", false, GetHMACParameters(32, Digest::SHA_2_512)},
};
return std::vector<TestCase>(&test_cases[0], &test_cases[arraysize(test_cases)]);
}
@@ -273,19 +270,19 @@
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);
+ .Digest(Digest::SHA_2_224)
+ .Digest(Digest::SHA_2_256)
+ .Digest(Digest::SHA_2_384)
+ .Digest(Digest::SHA_2_512)
+ .Padding(PaddingMode::RSA_PKCS1_1_5_SIGN)
+ .Padding(PaddingMode::RSA_PSS)
+ .Authorization(TAG_NO_AUTH_REQUIRED);
AuthorizationSet hardware_enforced_characteristics;
AuthorizationSet software_enforced_characteristics;
- int32_t result = keystore->generateKey(name, params.build(), &hardware_enforced_characteristics,
+ auto result = keystore->generateKey(name, params, &hardware_enforced_characteristics,
&software_enforced_characteristics);
- printf("GenerateKey: %d\n", result);
- if (result == KM_ERROR_OK) {
+ printf("GenerateKey: %d\n", int32_t(result));
+ if (result.isOk()) {
PrintKeyCharacteristics(hardware_enforced_characteristics,
software_enforced_characteristics);
}
@@ -296,10 +293,10 @@
std::unique_ptr<KeystoreClient> keystore = CreateKeystoreInstance();
AuthorizationSet hardware_enforced_characteristics;
AuthorizationSet software_enforced_characteristics;
- int32_t result = keystore->getKeyCharacteristics(name, &hardware_enforced_characteristics,
+ auto result = keystore->getKeyCharacteristics(name, &hardware_enforced_characteristics,
&software_enforced_characteristics);
- printf("GetCharacteristics: %d\n", result);
- if (result == KM_ERROR_OK) {
+ printf("GetCharacteristics: %d\n", int32_t(result));
+ if (result.isOk()) {
PrintKeyCharacteristics(hardware_enforced_characteristics,
software_enforced_characteristics);
}
@@ -309,7 +306,7 @@
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);
+ int32_t result = keystore->exportKey(KeyFormat::X509, name, &data);
printf("ExportKey: %d (%zu)\n", result, data.size());
return result;
}
@@ -351,14 +348,14 @@
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);
+ sign_params.Padding(PaddingMode::RSA_PKCS1_1_5_SIGN);
+ sign_params.Digest(Digest::SHA_2_256);
AuthorizationSet output_params;
- keymaster_operation_handle_t handle;
- int32_t result = keystore->beginOperation(KM_PURPOSE_SIGN, name, sign_params.build(),
+ uint64_t handle;
+ auto result = keystore->beginOperation(KeyPurpose::SIGN, name, sign_params,
&output_params, &handle);
- if (result != KM_ERROR_OK) {
- printf("Sign: BeginOperation failed: %d\n", result);
+ if (!result.isOk()) {
+ printf("Sign: BeginOperation failed: %d\n", int32_t(result));
return result;
}
AuthorizationSet empty_params;
@@ -366,40 +363,40 @@
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);
+ if (!result.isOk()) {
+ printf("Sign: UpdateOperation failed: %d\n", int32_t(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);
+ if (!result.isOk()) {
+ printf("Sign: FinishOperation failed: %d\n", int32_t(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,
+ result = keystore->beginOperation(KeyPurpose::VERIFY, name, sign_params, &output_params,
&handle);
- if (result != KM_ERROR_OK) {
- printf("Verify: BeginOperation failed: %d\n", result);
+ if (!result.isOk()) {
+ printf("Verify: BeginOperation failed: %d\n", int32_t(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);
+ if (!result.isOk()) {
+ printf("Verify: UpdateOperation failed: %d\n", int32_t(result));
return result;
}
result = keystore->finishOperation(handle, empty_params, signature_to_verify, &output_params,
&output_data);
- if (result == KM_ERROR_VERIFICATION_FAILED) {
+ if (result == ErrorCode::VERIFICATION_FAILED) {
printf("Verify: Failed to verify signature.\n");
return result;
}
- if (result != KM_ERROR_OK) {
- printf("Verify: FinishOperation failed: %d\n", result);
+ if (!result.isOk()) {
+ printf("Verify: FinishOperation failed: %d\n", int32_t(result));
return result;
}
printf("Verify: OK\n");
diff --git a/keystore/keystore_client_impl.cpp b/keystore/keystore_client_impl.cpp
index c3d8f35..f9df134 100644
--- a/keystore/keystore_client_impl.cpp
+++ b/keystore/keystore_client_impl.cpp
@@ -19,24 +19,25 @@
#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 <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"
+#include <keystore/authorization_set.h>
+#include <keystore/keystore_hidl_support.h>
using android::ExportResult;
-using android::KeyCharacteristics;
-using android::KeymasterArguments;
+using keystore::KeyCharacteristics;
using android::OperationResult;
using android::String16;
-using keymaster::AuthorizationSet;
-using keymaster::AuthorizationSetBuilder;
+using keystore::AuthorizationSet;
+using keystore::AuthorizationSetBuilder;
namespace {
@@ -44,24 +45,9 @@
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);
-}
+constexpr uint32_t kAESKeySize = 256; // bits
+constexpr uint32_t kHMACKeySize = 256; // bits
+constexpr uint32_t kHMACOutputSize = 256; // bits
} // namespace
@@ -89,29 +75,28 @@
return false;
}
AuthorizationSetBuilder encrypt_params;
- encrypt_params.Padding(KM_PAD_PKCS7);
- encrypt_params.Authorization(keymaster::TAG_BLOCK_MODE, KM_MODE_CBC);
+ encrypt_params.Padding(PaddingMode::PKCS7);
+ encrypt_params.Authorization(TAG_BLOCK_MODE, BlockMode::CBC);
AuthorizationSet output_params;
std::string raw_encrypted_data;
- if (!oneShotOperation(KM_PURPOSE_ENCRYPT, encryption_key_name, encrypt_params.build(), data,
+ if (!oneShotOperation(KeyPurpose::ENCRYPT, encryption_key_name, encrypt_params, 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)) {
+ auto init_vector_blob = output_params.GetTagValue(TAG_NONCE);
+ if (!init_vector_blob.isOk()){
ALOGE("Encrypt: Missing initialization vector.");
return false;
}
- std::string init_vector =
- ByteArrayAsString(init_vector_blob.data, init_vector_blob.data_length);
+ std::string init_vector = hidlVec2String(init_vector_blob.value());
AuthorizationSetBuilder authenticate_params;
- authenticate_params.Digest(KM_DIGEST_SHA_2_256);
- authenticate_params.Authorization(keymaster::TAG_MAC_LENGTH, kHMACOutputSize);
+ authenticate_params.Digest(Digest::SHA_2_256);
+ authenticate_params.Authorization(TAG_MAC_LENGTH, kHMACOutputSize);
std::string raw_authentication_data;
- if (!oneShotOperation(KM_PURPOSE_SIGN, authentication_key_name, authenticate_params.build(),
+ if (!oneShotOperation(KeyPurpose::SIGN, authentication_key_name, authenticate_params,
init_vector + raw_encrypted_data, std::string(), /* signature_to_verify */
&output_params, &raw_authentication_data)) {
ALOGE("Encrypt: HMAC operation failed.");
@@ -138,10 +123,10 @@
// Verify authentication before attempting decryption.
std::string authentication_key_name = key_name + kAuthenticateSuffix;
AuthorizationSetBuilder authenticate_params;
- authenticate_params.Digest(KM_DIGEST_SHA_2_256);
+ authenticate_params.Digest(Digest::SHA_2_256);
AuthorizationSet output_params;
std::string output_data;
- if (!oneShotOperation(KM_PURPOSE_VERIFY, authentication_key_name, authenticate_params.build(),
+ if (!oneShotOperation(KeyPurpose::VERIFY, authentication_key_name, authenticate_params,
protobuf.init_vector() + protobuf.encrypted_data(),
protobuf.authentication_data(), &output_params, &output_data)) {
ALOGE("Decrypt: HMAC operation failed.");
@@ -149,11 +134,11 @@
}
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(),
+ encrypt_params.Padding(PaddingMode::PKCS7);
+ encrypt_params.Authorization(TAG_BLOCK_MODE, BlockMode::CBC);
+ encrypt_params.Authorization(TAG_NONCE, protobuf.init_vector().data(),
protobuf.init_vector().size());
- if (!oneShotOperation(KM_PURPOSE_DECRYPT, encryption_key_name, encrypt_params.build(),
+ if (!oneShotOperation(KeyPurpose::DECRYPT, encryption_key_name, encrypt_params,
protobuf.encrypted_data(), std::string(), /* signature_to_verify */
&output_params, data)) {
ALOGE("Decrypt: AES operation failed.");
@@ -162,17 +147,17 @@
return true;
}
-bool KeystoreClientImpl::oneShotOperation(keymaster_purpose_t purpose, const std::string& key_name,
- const keymaster::AuthorizationSet& input_parameters,
+bool KeystoreClientImpl::oneShotOperation(KeyPurpose purpose, const std::string& key_name,
+ const AuthorizationSet& input_parameters,
const std::string& input_data,
const std::string& signature_to_verify,
- keymaster::AuthorizationSet* output_parameters,
+ AuthorizationSet* output_parameters,
std::string* output_data) {
- keymaster_operation_handle_t handle;
- int32_t result =
+ uint64_t handle;
+ auto result =
beginOperation(purpose, key_name, input_parameters, output_parameters, &handle);
- if (result != KM_ERROR_OK) {
- ALOGE("BeginOperation failed: %d", result);
+ if (!result.isOk()) {
+ ALOGE("BeginOperation failed: %d", int32_t(result));
return false;
}
AuthorizationSet empty_params;
@@ -180,174 +165,172 @@
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);
+ if (!result.isOk()) {
+ ALOGE("UpdateOperation failed: %d", int32_t(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);
+ if (!result.isOk()) {
+ ALOGE("FinishOperation failed: %d", int32_t(result));
return false;
}
return true;
}
-int32_t KeystoreClientImpl::addRandomNumberGeneratorEntropy(const std::string& entropy) {
- return mapKeystoreError(keystore_->addRngEntropy(StringAsByteArray(entropy), entropy.size()));
+KeyStoreNativeReturnCode KeystoreClientImpl::addRandomNumberGeneratorEntropy(const std::string& entropy) {
+ return keystore_->addRngEntropy(blob2hidlVec(entropy));
}
-int32_t KeystoreClientImpl::generateKey(const std::string& key_name,
+KeyStoreNativeReturnCode 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*/,
+ auto result =
+ keystore_->generateKey(key_name16, key_parameters.hidl_data(), hidl_vec<uint8_t>(),
kDefaultUID, KEYSTORE_FLAG_NONE, &characteristics);
- hardware_enforced_characteristics->Reinitialize(characteristics.characteristics.hw_enforced);
- software_enforced_characteristics->Reinitialize(characteristics.characteristics.sw_enforced);
- return mapKeystoreError(result);
+
+ /* assignment (hidl_vec<KeyParameter> -> AuthorizationSet) makes a deep copy.
+ * There are no references to Parcel memory after that, and ownership of the newly acquired
+ * memory is with the AuthorizationSet objects. */
+ *hardware_enforced_characteristics = characteristics.teeEnforced;
+ *software_enforced_characteristics = characteristics.softwareEnforced;
+ return result;
}
-int32_t
+KeyStoreNativeReturnCode
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,
+ auto result = keystore_->getKeyCharacteristics(key_name16, hidl_vec<uint8_t>(), hidl_vec<uint8_t>(),
kDefaultUID, &characteristics);
- hardware_enforced_characteristics->Reinitialize(characteristics.characteristics.hw_enforced);
- software_enforced_characteristics->Reinitialize(characteristics.characteristics.sw_enforced);
- return mapKeystoreError(result);
+
+ /* assignment (hidl_vec<KeyParameter> -> AuthorizationSet) makes a deep copy.
+ * There are no references to Parcel memory after that, and ownership of the newly acquired
+ * memory is with the AuthorizationSet objects. */
+ *hardware_enforced_characteristics = characteristics.teeEnforced;
+ *software_enforced_characteristics = characteristics.softwareEnforced;
+ return result;
}
-int32_t KeystoreClientImpl::importKey(const std::string& key_name,
+KeyStoreNativeReturnCode KeystoreClientImpl::importKey(const std::string& key_name,
const AuthorizationSet& key_parameters,
- keymaster_key_format_t key_format,
+ KeyFormat 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);
+ auto hidlKeyData = blob2hidlVec(key_data);
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);
+ auto result = keystore_->importKey(key_name16, key_parameters.hidl_data(), key_format,
+ hidlKeyData, kDefaultUID, KEYSTORE_FLAG_NONE, &characteristics);
+
+ /* assignment (hidl_vec<KeyParameter> -> AuthorizationSet) makes a deep copy.
+ * There are no references to Parcel memory after that, and ownership of the newly acquired
+ * memory is with the AuthorizationSet objects. */
+ *hardware_enforced_characteristics = characteristics.teeEnforced;
+ *software_enforced_characteristics = characteristics.softwareEnforced;
+ return result;
}
-int32_t KeystoreClientImpl::exportKey(keymaster_key_format_t export_format,
+KeyStoreNativeReturnCode KeystoreClientImpl::exportKey(KeyFormat 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,
+ keystore_->exportKey(key_name16, export_format, hidl_vec<uint8_t>(), hidl_vec<uint8_t>(),
kDefaultUID, &export_result);
- *export_data = ByteArrayAsString(export_result.exportData.get(), export_result.dataLength);
- return mapKeystoreError(export_result.resultCode);
+ *export_data = hidlVec2String(export_result.exportData);
+ return export_result.resultCode;
}
-int32_t KeystoreClientImpl::deleteKey(const std::string& key_name) {
+KeyStoreNativeReturnCode KeystoreClientImpl::deleteKey(const std::string& key_name) {
String16 key_name16(key_name.data(), key_name.size());
- return mapKeystoreError(keystore_->del(key_name16, kDefaultUID));
+ return keystore_->del(key_name16, kDefaultUID);
}
-int32_t KeystoreClientImpl::deleteAllKeys() {
- return mapKeystoreError(keystore_->clear_uid(kDefaultUID));
+KeyStoreNativeReturnCode KeystoreClientImpl::deleteAllKeys() {
+ return keystore_->clear_uid(kDefaultUID);
}
-int32_t KeystoreClientImpl::beginOperation(keymaster_purpose_t purpose, const std::string& key_name,
+KeyStoreNativeReturnCode KeystoreClientImpl::beginOperation(KeyPurpose purpose, const std::string& key_name,
const AuthorizationSet& input_parameters,
AuthorizationSet* output_parameters,
- keymaster_operation_handle_t* handle) {
+ uint64_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*/, kDefaultUID, &result);
- int32_t error_code = mapKeystoreError(result.resultCode);
- if (error_code == KM_ERROR_OK) {
+ keystore_->begin(token, key_name16, purpose, true /*pruneable*/, input_parameters.hidl_data(),
+ hidl_vec<uint8_t>(), kDefaultUID, &result);
+ if (result.resultCode.isOk()) {
*handle = getNextVirtualHandle();
active_operations_[*handle] = result.token;
- if (!result.outParams.params.empty()) {
- output_parameters->Reinitialize(&*result.outParams.params.begin(),
- result.outParams.params.size());
+ if (result.outParams.size()) {
+ *output_parameters = result.outParams;
}
}
- return error_code;
+ return result.resultCode;
}
-int32_t KeystoreClientImpl::updateOperation(keymaster_operation_handle_t handle,
+KeyStoreNativeReturnCode KeystoreClientImpl::updateOperation(uint64_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;
+ return ErrorCode::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) {
+ auto hidlInputData = blob2hidlVec(input_data);
+ keystore_->update(active_operations_[handle], input_parameters.hidl_data(), hidlInputData,
+ &result);
+
+ if (result.resultCode.isOk()) {
*num_input_bytes_consumed = result.inputConsumed;
- if (!result.outParams.params.empty()) {
- output_parameters->Reinitialize(&*result.outParams.params.begin(),
- result.outParams.params.size());
+ if (result.outParams.size()) {
+ *output_parameters = result.outParams;
}
- output_data->append(ByteArrayAsString(result.data.get(), result.dataLength));
+ // TODO verify that append should not be assign
+ output_data->append(hidlVec2String(result.data));
}
- return error_code;
+ return result.resultCode;
}
-int32_t KeystoreClientImpl::finishOperation(keymaster_operation_handle_t handle,
+KeyStoreNativeReturnCode KeystoreClientImpl::finishOperation(uint64_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;
+ return ErrorCode::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());
+ auto hidlSignature = blob2hidlVec(signature_to_verify);
+ keystore_->finish(active_operations_[handle], input_parameters.hidl_data(),
+ hidlSignature,
+ hidl_vec<uint8_t>(), &result);
+
+ if (result.resultCode.isOk()) {
+ if (result.outParams.size()) {
+ *output_parameters = result.outParams;
}
- output_data->append(ByteArrayAsString(result.data.get(), result.dataLength));
+ // TODO verify that append should not be assign
+ output_data->append(hidlVec2String(result.data));
active_operations_.erase(handle);
}
- return error_code;
+ return result.resultCode;
}
-int32_t KeystoreClientImpl::abortOperation(keymaster_operation_handle_t handle) {
+KeyStoreNativeReturnCode KeystoreClientImpl::abortOperation(uint64_t handle) {
if (active_operations_.count(handle) == 0) {
- return KM_ERROR_INVALID_OPERATION_HANDLE;
+ return ErrorCode::INVALID_OPERATION_HANDLE;
}
- int32_t error_code = mapKeystoreError(keystore_->abort(active_operations_[handle]));
- if (error_code == KM_ERROR_OK) {
+ auto error_code = keystore_->abort(active_operations_[handle]);
+ if (error_code.isOk()) {
active_operations_.erase(handle);
}
return error_code;
@@ -355,16 +338,16 @@
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);
+ auto error_code = keystore_->exist(key_name16, kDefaultUID);
+ return error_code.isOk();
}
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) {
+ auto error_code = keystore_->list(prefix16, kDefaultUID, &matches);
+ if (error_code.isOk()) {
for (const auto& match : matches) {
android::String8 key_name(match);
key_name_list->push_back(prefix + std::string(key_name.string(), key_name.size()));
@@ -374,18 +357,10 @@
return false;
}
-keymaster_operation_handle_t KeystoreClientImpl::getNextVirtualHandle() {
+uint64_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) {
@@ -394,9 +369,9 @@
return false;
}
if (!verified) {
- int32_t result = deleteKey(key_name);
- if (result != KM_ERROR_OK) {
- ALOGE("Failed to delete invalid encryption key: %d", result);
+ auto result = deleteKey(key_name);
+ if (!result.isOk()) {
+ ALOGE("Failed to delete invalid encryption key: %d", int32_t(result));
return false;
}
key_exists = false;
@@ -405,16 +380,16 @@
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);
+ .Padding(PaddingMode::PKCS7)
+ .Authorization(TAG_BLOCK_MODE, BlockMode::CBC)
+ .Authorization(TAG_NO_AUTH_REQUIRED);
AuthorizationSet hardware_enforced_characteristics;
AuthorizationSet software_enforced_characteristics;
- int32_t result =
- generateKey(key_name, key_parameters.build(), &hardware_enforced_characteristics,
+ auto result =
+ generateKey(key_name, key_parameters, &hardware_enforced_characteristics,
&software_enforced_characteristics);
- if (result != KM_ERROR_OK) {
- ALOGE("Failed to generate encryption key: %d", result);
+ if (!result.isOk()) {
+ ALOGE("Failed to generate encryption key: %d", int32_t(result));
return false;
}
if (hardware_enforced_characteristics.size() == 0) {
@@ -432,9 +407,9 @@
return false;
}
if (!verified) {
- int32_t result = deleteKey(key_name);
- if (result != KM_ERROR_OK) {
- ALOGE("Failed to delete invalid authentication key: %d", result);
+ auto result = deleteKey(key_name);
+ if (!result.isOk()) {
+ ALOGE("Failed to delete invalid authentication key: %d", int32_t(result));
return false;
}
key_exists = false;
@@ -443,16 +418,16 @@
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);
+ .Digest(Digest::SHA_2_256)
+ .Authorization(TAG_MIN_MAC_LENGTH, kHMACOutputSize)
+ .Authorization(TAG_NO_AUTH_REQUIRED);
AuthorizationSet hardware_enforced_characteristics;
AuthorizationSet software_enforced_characteristics;
- int32_t result =
- generateKey(key_name, key_parameters.build(), &hardware_enforced_characteristics,
+ auto result =
+ generateKey(key_name, key_parameters, &hardware_enforced_characteristics,
&software_enforced_characteristics);
- if (result != KM_ERROR_OK) {
- ALOGE("Failed to generate authentication key: %d", result);
+ if (!result.isOk()) {
+ ALOGE("Failed to generate authentication key: %d", int32_t(result));
return false;
}
if (hardware_enforced_characteristics.size() == 0) {
@@ -466,38 +441,34 @@
bool* verified) {
AuthorizationSet hardware_enforced_characteristics;
AuthorizationSet software_enforced_characteristics;
- int32_t result = getKeyCharacteristics(key_name, &hardware_enforced_characteristics,
+ auto result = getKeyCharacteristics(key_name, &hardware_enforced_characteristics,
&software_enforced_characteristics);
- if (result != KM_ERROR_OK) {
- ALOGE("Failed to query encryption key: %d", result);
+ if (!result.isOk()) {
+ ALOGE("Failed to query encryption key: %d", int32_t(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) {
+ auto algorithm = NullOrOr(hardware_enforced_characteristics.GetTagValue(TAG_ALGORITHM),
+ software_enforced_characteristics.GetTagValue(TAG_ALGORITHM));
+ if (!algorithm.isOk() || algorithm.value() != 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) {
+ auto key_size = NullOrOr(hardware_enforced_characteristics.GetTagValue(TAG_KEY_SIZE),
+ software_enforced_characteristics.GetTagValue(TAG_KEY_SIZE));
+ if (!key_size.isOk() || key_size.value() != 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) {
+ auto block_mode = NullOrOr(hardware_enforced_characteristics.GetTagValue(TAG_BLOCK_MODE),
+ software_enforced_characteristics.GetTagValue(TAG_BLOCK_MODE));
+ if (!block_mode.isOk() || block_mode.value() != BlockMode::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) {
+ auto padding_mode = NullOrOr(hardware_enforced_characteristics.GetTagValue(TAG_PADDING),
+ software_enforced_characteristics.GetTagValue(TAG_PADDING));
+ if (!padding_mode.isOk() || padding_mode.value() != PaddingMode::PKCS7) {
ALOGW("Found encryption key with invalid padding mode.");
*verified = false;
}
@@ -511,39 +482,34 @@
bool* verified) {
AuthorizationSet hardware_enforced_characteristics;
AuthorizationSet software_enforced_characteristics;
- int32_t result = getKeyCharacteristics(key_name, &hardware_enforced_characteristics,
+ auto result = getKeyCharacteristics(key_name, &hardware_enforced_characteristics,
&software_enforced_characteristics);
- if (result != KM_ERROR_OK) {
- ALOGE("Failed to query authentication key: %d", result);
+ if (!result.isOk()) {
+ ALOGE("Failed to query authentication key: %d", int32_t(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) {
+ auto algorithm = NullOrOr(hardware_enforced_characteristics.GetTagValue(TAG_ALGORITHM),
+ software_enforced_characteristics.GetTagValue(TAG_ALGORITHM));
+ if (!algorithm.isOk() || algorithm.value() != 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) {
+ auto key_size = NullOrOr(hardware_enforced_characteristics.GetTagValue(TAG_KEY_SIZE),
+ software_enforced_characteristics.GetTagValue(TAG_KEY_SIZE));
+ if (!key_size.isOk() || key_size.value() != 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) {
+ auto mac_size = NullOrOr(hardware_enforced_characteristics.GetTagValue(TAG_MIN_MAC_LENGTH),
+ software_enforced_characteristics.GetTagValue(TAG_MIN_MAC_LENGTH));
+ if (!mac_size.isOk() || mac_size.value() != 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) {
+ auto digest = NullOrOr(hardware_enforced_characteristics.GetTagValue(TAG_DIGEST),
+ software_enforced_characteristics.GetTagValue(TAG_DIGEST));
+ if (!digest.isOk() || digest.value() != Digest::SHA_2_256) {
ALOGW("Found authentication key with invalid digest list.");
*verified = false;
}
diff --git a/keystore/keystore_get.cpp b/keystore/keystore_get.cpp
index 2783816..8fb7f80 100644
--- a/keystore/keystore_get.cpp
+++ b/keystore/keystore_get.cpp
@@ -20,6 +20,7 @@
#include <keystore/keystore_get.h>
using namespace android;
+using namespace keystore;
ssize_t keystore_get(const char *key, size_t keyLength, uint8_t** value) {
sp<IServiceManager> sm = defaultServiceManager();
@@ -30,13 +31,15 @@
return -1;
}
- size_t valueLength;
- int32_t ret = service->get(String16(key, keyLength), -1, value, &valueLength);
- if (ret < 0) {
- return -1;
- } else if (ret != ::NO_ERROR) {
- return -1;
- } else {
- return valueLength;
+ hidl_vec<uint8_t> result;
+ auto ret = service->get(String16(key, keyLength), -1, &result);
+ if (!ret.isOk()) return -1;
+
+ if (value) {
+ *value = reinterpret_cast<uint8_t*>(malloc(result.size()));
+ if (!*value) return -1;
+ memcpy(*value, &result[0], result.size());
}
+ return result.size();
+
}
diff --git a/keystore/keystore_keymaster_enforcement.h b/keystore/keystore_keymaster_enforcement.h
index d20d7a6..0389201 100644
--- a/keystore/keystore_keymaster_enforcement.h
+++ b/keystore/keystore_keymaster_enforcement.h
@@ -14,18 +14,19 @@
* limitations under the License.
*/
-#ifndef KEYSTORE_KEYMASTER_ENFORCEMENT_H_
-#define KEYSTORE_KEYMASTER_ENFORCEMENT_H_
+#ifndef KEYSTORE_KEYSTORE_KEYMASTER_ENFORCEMENT_H_
+#define KEYSTORE_KEYSTORE_KEYMASTER_ENFORCEMENT_H_
#include <time.h>
-#include <keymaster/keymaster_enforcement.h>
+#include "keymaster_enforcement.h"
+namespace keystore {
/**
* This is a specialization of the KeymasterEnforcement class to be used by Keystore to enforce
* keymaster requirements on all key operation.
*/
-class KeystoreKeymasterEnforcement : public keymaster::KeymasterEnforcement {
+class KeystoreKeymasterEnforcement : public KeymasterEnforcement {
public:
KeystoreKeymasterEnforcement() : KeymasterEnforcement(64, 64) {}
@@ -85,4 +86,6 @@
}
};
-#endif // KEYSTORE_KEYMASTER_ENFORCEMENT_H_
+} // namespace keystore
+
+#endif // KEYSTORE_KEYSTORE_KEYMASTER_ENFORCEMENT_H_
diff --git a/keystore/keystore_main.cpp b/keystore/keystore_main.cpp
index e84fb37..c5b36fd 100644
--- a/keystore/keystore_main.cpp
+++ b/keystore/keystore_main.cpp
@@ -17,19 +17,18 @@
//#define LOG_NDEBUG 0
#define LOG_TAG "keystore"
-#include <keymaster/keymaster_configuration.h>
-#include <keymaster/soft_keymaster_device.h>
-#include <keymaster/soft_keymaster_logger.h>
-
#include <binder/IPCThreadState.h>
#include <binder/IServiceManager.h>
+#include <android/hardware/keymaster/3.0/IHwKeymasterDevice.h>
+
#include <cutils/log.h>
#include "entropy.h"
#include "key_store_service.h"
#include "keystore.h"
#include "permissions.h"
+#include "legacy_keymaster_device_wrapper.h"
/* KeyStore is a secured storage for key-value pairs. In this implementation,
* each file stores one key-value pair. Keys are encoded in file names, and
@@ -37,157 +36,9 @@
* user-defined password. To keep things simple, buffers are always larger than
* the maximum space we needed, so boundary checks on buffers are omitted. */
-using keymaster::AuthorizationSet;
-using keymaster::AuthorizationSetBuilder;
-using keymaster::SoftKeymasterDevice;
-
-static int configure_keymaster_devices(keymaster2_device_t* main, keymaster2_device_t* fallback) {
- keymaster_error_t error = keymaster::ConfigureDevice(main);
- if (error != KM_ERROR_OK) {
- return -1;
- }
-
- error = keymaster::ConfigureDevice(fallback);
- if (error != KM_ERROR_OK) {
- return -1;
- }
-
- return 0;
-}
-
-static int keymaster0_device_initialize(const hw_module_t* mod, keymaster2_device_t** dev) {
- assert(mod->module_api_version < KEYMASTER_MODULE_API_VERSION_1_0);
- ALOGI("Found keymaster0 module %s, version %x", mod->name, mod->module_api_version);
-
- UniquePtr<SoftKeymasterDevice> soft_keymaster(new SoftKeymasterDevice);
- keymaster0_device_t* km0_device = NULL;
- keymaster_error_t error = KM_ERROR_OK;
-
- int rc = keymaster0_open(mod, &km0_device);
- if (rc) {
- ALOGE("Error opening keystore keymaster0 device.");
- goto err;
- }
-
- if (km0_device->flags & KEYMASTER_SOFTWARE_ONLY) {
- ALOGI("Keymaster0 module is software-only. Using SoftKeymasterDevice instead.");
- km0_device->common.close(&km0_device->common);
- km0_device = NULL;
- // SoftKeymasterDevice will be deleted by keymaster_device_release()
- *dev = soft_keymaster.release()->keymaster2_device();
- return 0;
- }
-
- ALOGD("Wrapping keymaster0 module %s with SoftKeymasterDevice", mod->name);
- error = soft_keymaster->SetHardwareDevice(km0_device);
- km0_device = NULL; // SoftKeymasterDevice has taken ownership.
- if (error != KM_ERROR_OK) {
- ALOGE("Got error %d from SetHardwareDevice", error);
- rc = error;
- goto err;
- }
-
- // SoftKeymasterDevice will be deleted by keymaster_device_release()
- *dev = soft_keymaster.release()->keymaster2_device();
- return 0;
-
-err:
- if (km0_device)
- km0_device->common.close(&km0_device->common);
- *dev = NULL;
- return rc;
-}
-
-static int keymaster1_device_initialize(const hw_module_t* mod, keymaster2_device_t** dev) {
- assert(mod->module_api_version >= KEYMASTER_MODULE_API_VERSION_1_0);
- ALOGI("Found keymaster1 module %s, version %x", mod->name, mod->module_api_version);
-
- UniquePtr<SoftKeymasterDevice> soft_keymaster(new SoftKeymasterDevice);
- keymaster1_device_t* km1_device = nullptr;
- keymaster_error_t error = KM_ERROR_OK;
-
- int rc = keymaster1_open(mod, &km1_device);
- if (rc) {
- ALOGE("Error %d opening keystore keymaster1 device", rc);
- goto err;
- }
-
- ALOGD("Wrapping keymaster1 module %s with SofKeymasterDevice", mod->name);
- error = soft_keymaster->SetHardwareDevice(km1_device);
- km1_device = nullptr; // SoftKeymasterDevice has taken ownership.
- if (error != KM_ERROR_OK) {
- ALOGE("Got error %d from SetHardwareDevice", error);
- rc = error;
- goto err;
- }
-
- // SoftKeymasterDevice will be deleted by keymaster_device_release()
- *dev = soft_keymaster.release()->keymaster2_device();
- return 0;
-
-err:
- if (km1_device)
- km1_device->common.close(&km1_device->common);
- *dev = NULL;
- return rc;
-}
-
-static int keymaster2_device_initialize(const hw_module_t* mod, keymaster2_device_t** dev) {
- assert(mod->module_api_version >= KEYMASTER_MODULE_API_VERSION_2_0);
- ALOGI("Found keymaster2 module %s, version %x", mod->name, mod->module_api_version);
-
- UniquePtr<SoftKeymasterDevice> soft_keymaster(new SoftKeymasterDevice);
- keymaster2_device_t* km2_device = nullptr;
-
- int rc = keymaster2_open(mod, &km2_device);
- if (rc) {
- ALOGE("Error %d opening keystore keymaster2 device", rc);
- goto err;
- }
-
- *dev = km2_device;
- return 0;
-
-err:
- if (km2_device)
- km2_device->common.close(&km2_device->common);
- *dev = nullptr;
- return rc;
-}
-
-static int keymaster_device_initialize(keymaster2_device_t** dev) {
- const hw_module_t* mod;
-
- int rc = hw_get_module_by_class(KEYSTORE_HARDWARE_MODULE_ID, NULL, &mod);
- if (rc) {
- ALOGI("Could not find any keystore module, using software-only implementation.");
- // SoftKeymasterDevice will be deleted by keymaster_device_release()
- *dev = (new SoftKeymasterDevice)->keymaster2_device();
- return 0;
- }
-
- if (mod->module_api_version < KEYMASTER_MODULE_API_VERSION_1_0) {
- return keymaster0_device_initialize(mod, dev);
- } else if (mod->module_api_version == KEYMASTER_MODULE_API_VERSION_1_0) {
- return keymaster1_device_initialize(mod, dev);
- } else {
- return keymaster2_device_initialize(mod, dev);
- }
-}
-
-// softkeymaster_logger appears not to be used in keystore, but it installs itself as the
-// logger used by SoftKeymasterDevice.
-static keymaster::SoftKeymasterLogger softkeymaster_logger;
-
-static int fallback_keymaster_device_initialize(keymaster2_device_t** dev) {
- *dev = (new SoftKeymasterDevice)->keymaster2_device();
- // SoftKeymasterDevice will be deleted by keymaster_device_release()
- return 0;
-}
-
-static void keymaster_device_release(keymaster2_device_t* dev) {
- dev->common.close(&dev->common);
-}
+/**
+ * TODO implement keystore daemon using binderized keymaster HAL.
+ */
int main(int argc, char* argv[]) {
if (argc < 2) {
@@ -204,21 +55,13 @@
return 1;
}
- keymaster2_device_t* dev;
- if (keymaster_device_initialize(&dev)) {
- ALOGE("keystore keymaster could not be initialized; exiting");
- return 1;
+ auto dev = android::hardware::keymaster::V3_0::IKeymasterDevice::getService("keymaster");
+ if (dev.get() == nullptr) {
+ return -1;
}
-
- keymaster2_device_t* fallback;
- if (fallback_keymaster_device_initialize(&fallback)) {
- ALOGE("software keymaster could not be initialized; exiting");
- return 1;
- }
-
- if (configure_keymaster_devices(dev, fallback)) {
- ALOGE("Keymaster devices could not be configured; exiting");
- return 1;
+ auto fallback = android::keystore::makeSoftwareKeymasterDevice();
+ if (dev.get() == nullptr) {
+ return -1;
}
if (configure_selinux() == -1) {
@@ -228,7 +71,7 @@
KeyStore keyStore(&entropy, dev, fallback);
keyStore.initialize();
android::sp<android::IServiceManager> sm = android::defaultServiceManager();
- android::sp<android::KeyStoreService> service = new android::KeyStoreService(&keyStore);
+ android::sp<keystore::KeyStoreService> service = new keystore::KeyStoreService(&keyStore);
android::status_t ret = sm->addService(android::String16("android.security.keystore"), service);
if (ret != android::OK) {
ALOGE("Couldn't register binder service!");
@@ -240,7 +83,5 @@
* Binder transaction as a single-threaded program.
*/
android::IPCThreadState::self()->joinThreadPool();
-
- keymaster_device_release(dev);
return 1;
}
diff --git a/keystore/keystore_tags_utils.cpp b/keystore/keystore_tags_utils.cpp
new file mode 100644
index 0000000..278348a
--- /dev/null
+++ b/keystore/keystore_tags_utils.cpp
@@ -0,0 +1,46 @@
+/*
+**
+** Copyright 2016, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+#include <keystore/keymaster_tags.h>
+
+namespace keystore {
+
+template<typename TagList>
+struct TagStringifier;
+
+template<typename ... Tags>
+struct TagStringifier<MetaList<Tags...>> {
+ template<TagType tag_type, Tag tag>
+ static TypedTag<tag_type, tag> chooseString(TypedTag<tag_type, tag> ttag, Tag runtime_tag,
+ const char** result) {
+ if (tag == runtime_tag) {
+ *result = Tag2String<tag>::value();
+ }
+ return ttag;
+ }
+ static const char* stringify(Tag tag) {
+ const char* result = "unknown tag";
+ [] (Tags&&...) {}(chooseString(Tags(), tag, &result)...);
+ return result;
+ }
+};
+
+const char* stringifyTag(Tag tag) {
+ return TagStringifier<all_tags_t>::stringify(tag);
+}
+
+}
diff --git a/keystore/keystore_utils.cpp b/keystore/keystore_utils.cpp
index 4617afd..0d3f0ec 100644
--- a/keystore/keystore_utils.cpp
+++ b/keystore/keystore_utils.cpp
@@ -26,6 +26,9 @@
#include <private/android_filesystem_config.h>
#include <keymaster/android_keymaster_utils.h>
+#include <keystore/authorization_set.h>
+#include <keystore/keystore_client.h>
+#include <keystore/IKeystoreService.h>
size_t readFully(int fd, uint8_t* data, size_t size) {
size_t remaining = size;
@@ -58,30 +61,31 @@
return size;
}
-void add_legacy_key_authorizations(int keyType, std::vector<keymaster_key_param_t>* params) {
- params->push_back(keymaster_param_enum(KM_TAG_PURPOSE, KM_PURPOSE_SIGN));
- params->push_back(keymaster_param_enum(KM_TAG_PURPOSE, KM_PURPOSE_VERIFY));
- params->push_back(keymaster_param_enum(KM_TAG_PURPOSE, KM_PURPOSE_ENCRYPT));
- params->push_back(keymaster_param_enum(KM_TAG_PURPOSE, KM_PURPOSE_DECRYPT));
- params->push_back(keymaster_param_enum(KM_TAG_PADDING, KM_PAD_NONE));
+void add_legacy_key_authorizations(int keyType, keystore::AuthorizationSet* params) {
+ using namespace keystore;
+ params->push_back(TAG_PURPOSE, KeyPurpose::SIGN);
+ params->push_back(TAG_PURPOSE, KeyPurpose::VERIFY);
+ params->push_back(TAG_PURPOSE, KeyPurpose::ENCRYPT);
+ params->push_back(TAG_PURPOSE, KeyPurpose::DECRYPT);
+ params->push_back(TAG_PADDING, PaddingMode::NONE);
if (keyType == EVP_PKEY_RSA) {
- params->push_back(keymaster_param_enum(KM_TAG_PADDING, KM_PAD_RSA_PKCS1_1_5_SIGN));
- params->push_back(keymaster_param_enum(KM_TAG_PADDING, KM_PAD_RSA_PKCS1_1_5_ENCRYPT));
- params->push_back(keymaster_param_enum(KM_TAG_PADDING, KM_PAD_RSA_PSS));
- params->push_back(keymaster_param_enum(KM_TAG_PADDING, KM_PAD_RSA_OAEP));
+ params->push_back(TAG_PADDING, PaddingMode::RSA_PKCS1_1_5_SIGN);
+ params->push_back(TAG_PADDING, PaddingMode::RSA_PKCS1_1_5_ENCRYPT);
+ params->push_back(TAG_PADDING, PaddingMode::RSA_PSS);
+ params->push_back(TAG_PADDING, PaddingMode::RSA_OAEP);
}
- params->push_back(keymaster_param_enum(KM_TAG_DIGEST, KM_DIGEST_NONE));
- params->push_back(keymaster_param_enum(KM_TAG_DIGEST, KM_DIGEST_MD5));
- params->push_back(keymaster_param_enum(KM_TAG_DIGEST, KM_DIGEST_SHA1));
- params->push_back(keymaster_param_enum(KM_TAG_DIGEST, KM_DIGEST_SHA_2_224));
- params->push_back(keymaster_param_enum(KM_TAG_DIGEST, KM_DIGEST_SHA_2_256));
- params->push_back(keymaster_param_enum(KM_TAG_DIGEST, KM_DIGEST_SHA_2_384));
- params->push_back(keymaster_param_enum(KM_TAG_DIGEST, KM_DIGEST_SHA_2_512));
- params->push_back(keymaster_param_bool(KM_TAG_ALL_USERS));
- params->push_back(keymaster_param_bool(KM_TAG_NO_AUTH_REQUIRED));
- params->push_back(keymaster_param_date(KM_TAG_ORIGINATION_EXPIRE_DATETIME, LLONG_MAX));
- params->push_back(keymaster_param_date(KM_TAG_USAGE_EXPIRE_DATETIME, LLONG_MAX));
- params->push_back(keymaster_param_date(KM_TAG_ACTIVE_DATETIME, 0));
+ params->push_back(TAG_DIGEST, Digest::NONE);
+ params->push_back(TAG_DIGEST, Digest::MD5);
+ params->push_back(TAG_DIGEST, Digest::SHA1);
+ params->push_back(TAG_DIGEST, Digest::SHA_2_224);
+ params->push_back(TAG_DIGEST, Digest::SHA_2_256);
+ params->push_back(TAG_DIGEST, Digest::SHA_2_384);
+ params->push_back(TAG_DIGEST, Digest::SHA_2_512);
+ params->push_back(TAG_ALL_USERS);
+ params->push_back(TAG_NO_AUTH_REQUIRED);
+ params->push_back(TAG_ORIGINATION_EXPIRE_DATETIME, LLONG_MAX);
+ params->push_back(TAG_USAGE_EXPIRE_DATETIME, LLONG_MAX);
+ params->push_back(TAG_ACTIVE_DATETIME, 0);
}
uid_t get_app_id(uid_t uid) {
diff --git a/keystore/keystore_utils.h b/keystore/keystore_utils.h
index eaa5eb3..0f7922a 100644
--- a/keystore/keystore_utils.h
+++ b/keystore/keystore_utils.h
@@ -28,10 +28,14 @@
#include <UniquePtr.h>
+#include <keystore/authorization_set.h>
+
+#include "blob.h"
+
size_t readFully(int fd, uint8_t* data, size_t size);
size_t writeFully(int fd, uint8_t* data, size_t size);
-void add_legacy_key_authorizations(int keyType, std::vector<keymaster_key_param_t>* params);
+void add_legacy_key_authorizations(int keyType, keystore::AuthorizationSet* params);
/**
* Returns the app ID (in the Android multi-user sense) for the current
@@ -55,4 +59,14 @@
};
typedef UniquePtr<PKCS8_PRIV_KEY_INFO, PKCS8_PRIV_KEY_INFO_Delete> Unique_PKCS8_PRIV_KEY_INFO;
+namespace keystore {
+
+inline static hidl_vec<uint8_t> blob2hidlVec(const Blob& blob) {
+ hidl_vec<uint8_t> result;
+ result.setToExternal(const_cast<uint8_t*>(blob.getValue()), blob.getLength());
+ return result;
+}
+
+} // namespace keystore
+
#endif // KEYSTORE_KEYSTORE_UTILS_H_
diff --git a/keystore/legacy_keymaster_device_wrapper.cpp b/keystore/legacy_keymaster_device_wrapper.cpp
new file mode 100644
index 0000000..9e36ae6
--- /dev/null
+++ b/keystore/legacy_keymaster_device_wrapper.cpp
@@ -0,0 +1,519 @@
+/*
+ **
+ ** Copyright 2016, The Android Open Source Project
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ ** http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ** See the License for the specific language governing permissions and
+ ** limitations under the License.
+ */
+
+#define LOG_TAG "android.hardware.keymaster@3.0-impl"
+
+#include "legacy_keymaster_device_wrapper.h"
+
+#include <cutils/log.h>
+
+#include <hardware/keymaster2.h>
+#include <hardware/keymaster_defs.h>
+#include <keymaster/keymaster_configuration.h>
+#include <keymaster/soft_keymaster_device.h>
+
+namespace android {
+namespace keystore {
+
+using ::keymaster::SoftKeymasterDevice;
+
+LegacyKeymasterDeviceWrapper::LegacyKeymasterDeviceWrapper(keymaster2_device_t* dev)
+ : keymaster_device_(dev) {}
+
+LegacyKeymasterDeviceWrapper::~LegacyKeymasterDeviceWrapper() {
+ if (keymaster_device_) keymaster_device_->common.close(&keymaster_device_->common);
+}
+
+static inline keymaster_tag_type_t typeFromTag(const keymaster_tag_t tag) {
+ return keymaster_tag_get_type(tag);
+}
+
+/**
+ * legacy_enum_conversion converts enums from hidl to keymaster and back. Currently, this is just a
+ * cast to make the compiler happy. One of two thigs should happen though:
+ * TODO The keymaster enums should become aliases for the hidl generated enums so that we have a
+ * single point of truth. Then this cast function can go away.
+ */
+inline static keymaster_tag_t legacy_enum_conversion(const Tag value) {
+ return keymaster_tag_t(value);
+}
+inline static Tag legacy_enum_conversion(const keymaster_tag_t value) {
+ return Tag(value);
+}
+inline static keymaster_purpose_t legacy_enum_conversion(const KeyPurpose value) {
+ return keymaster_purpose_t(value);
+}
+inline static keymaster_key_format_t legacy_enum_conversion(const KeyFormat value) {
+ return keymaster_key_format_t(value);
+}
+inline static ErrorCode legacy_enum_conversion(const keymaster_error_t value) {
+ return ErrorCode(value);
+}
+
+class KmParamSet : public keymaster_key_param_set_t {
+ public:
+ KmParamSet(const hidl_vec<KeyParameter>& keyParams) {
+ params = new keymaster_key_param_t[keyParams.size()];
+ length = keyParams.size();
+ for (size_t i = 0; i < keyParams.size(); ++i) {
+ auto tag = legacy_enum_conversion(keyParams[i].tag);
+ switch (typeFromTag(tag)) {
+ case KM_ENUM:
+ case KM_ENUM_REP:
+ params[i] = keymaster_param_enum(tag, keyParams[i].f.integer);
+ break;
+ case KM_UINT:
+ case KM_UINT_REP:
+ params[i] = keymaster_param_int(tag, keyParams[i].f.integer);
+ break;
+ case KM_ULONG:
+ case KM_ULONG_REP:
+ params[i] = keymaster_param_long(tag, keyParams[i].f.longInteger);
+ break;
+ case KM_DATE:
+ params[i] = keymaster_param_date(tag, keyParams[i].f.dateTime);
+ break;
+ case KM_BOOL:
+ if (keyParams[i].f.boolValue)
+ params[i] = keymaster_param_bool(tag);
+ else
+ params[i].tag = KM_TAG_INVALID;
+ break;
+ case KM_BIGNUM:
+ case KM_BYTES:
+ params[i] =
+ keymaster_param_blob(tag, &keyParams[i].blob[0], keyParams[i].blob.size());
+ break;
+ case KM_INVALID:
+ default:
+ params[i].tag = KM_TAG_INVALID;
+ /* just skip */
+ break;
+ }
+ }
+ }
+ KmParamSet(KmParamSet&& other) : keymaster_key_param_set_t{other.params, other.length} {
+ other.length = 0;
+ other.params = nullptr;
+ }
+ KmParamSet(const KmParamSet&) = delete;
+ ~KmParamSet() { delete[] params; }
+};
+
+inline static KmParamSet hidlParams2KmParamSet(const hidl_vec<KeyParameter>& params) {
+ return KmParamSet(params);
+}
+
+inline static keymaster_blob_t hidlVec2KmBlob(const hidl_vec<uint8_t>& blob) {
+ /* hidl unmarshals funny pointers if the the blob is empty */
+ if (blob.size()) return {&blob[0], blob.size()};
+ return {};
+}
+
+inline static keymaster_key_blob_t hidlVec2KmKeyBlob(const hidl_vec<uint8_t>& blob) {
+ /* hidl unmarshals funny pointers if the the blob is empty */
+ if (blob.size()) return {&blob[0], blob.size()};
+ return {};
+}
+
+inline static hidl_vec<uint8_t> kmBlob2hidlVec(const keymaster_key_blob_t& blob) {
+ hidl_vec<uint8_t> result;
+ result.setToExternal(const_cast<unsigned char*>(blob.key_material), blob.key_material_size);
+ return result;
+}
+inline static hidl_vec<uint8_t> kmBlob2hidlVec(const keymaster_blob_t& blob) {
+ hidl_vec<uint8_t> result;
+ result.setToExternal(const_cast<unsigned char*>(blob.data), blob.data_length);
+ return result;
+}
+
+inline static hidl_vec<hidl_vec<uint8_t>>
+kmCertChain2Hidl(const keymaster_cert_chain_t* cert_chain) {
+ hidl_vec<hidl_vec<uint8_t>> result;
+ if (!cert_chain || cert_chain->entry_count == 0 || !cert_chain->entries) return result;
+
+ result.resize(cert_chain->entry_count);
+ for (size_t i = 0; i < cert_chain->entry_count; ++i) {
+ auto& entry = cert_chain->entries[i];
+ result[i] = kmBlob2hidlVec(entry);
+ }
+
+ return result;
+}
+
+static inline hidl_vec<KeyParameter> kmParamSet2Hidl(const keymaster_key_param_set_t& set) {
+ hidl_vec<KeyParameter> result;
+ if (set.length == 0 || set.params == nullptr) return result;
+
+ result.resize(set.length);
+ keymaster_key_param_t* params = set.params;
+ for (size_t i = 0; i < set.length; ++i) {
+ auto tag = params[i].tag;
+ result[i].tag = legacy_enum_conversion(tag);
+ switch (typeFromTag(tag)) {
+ case KM_ENUM:
+ case KM_ENUM_REP:
+ result[i].f.integer = params[i].enumerated;
+ break;
+ case KM_UINT:
+ case KM_UINT_REP:
+ result[i].f.integer = params[i].integer;
+ break;
+ case KM_ULONG:
+ case KM_ULONG_REP:
+ result[i].f.longInteger = params[i].long_integer;
+ break;
+ case KM_DATE:
+ result[i].f.dateTime = params[i].date_time;
+ break;
+ case KM_BOOL:
+ result[i].f.boolValue = params[i].boolean;
+ break;
+ case KM_BIGNUM:
+ case KM_BYTES:
+ result[i].blob.setToExternal(const_cast<unsigned char*>(params[i].blob.data),
+ params[i].blob.data_length);
+ break;
+ case KM_INVALID:
+ default:
+ params[i].tag = KM_TAG_INVALID;
+ /* just skip */
+ break;
+ }
+ }
+ return result;
+}
+
+// Methods from ::android::hardware::keymaster::V3_0::IKeymasterDevice follow.
+Return<void> LegacyKeymasterDeviceWrapper::getHardwareFeatures(getHardwareFeatures_cb _hidl_cb) {
+ _hidl_cb(false, false, false, false);
+ return Void();
+}
+
+Return<ErrorCode> LegacyKeymasterDeviceWrapper::addRngEntropy(const hidl_vec<uint8_t>& data) {
+ return legacy_enum_conversion(
+ keymaster_device_->add_rng_entropy(keymaster_device_, &data[0], data.size()));
+}
+
+Return<void> LegacyKeymasterDeviceWrapper::generateKey(const hidl_vec<KeyParameter>& keyParams,
+ generateKey_cb _hidl_cb) {
+ // result variables for the wire
+ KeyCharacteristics resultCharacteristics;
+ hidl_vec<uint8_t> resultKeyBlob;
+
+ // result variables the backend understands
+ keymaster_key_blob_t key_blob{nullptr, 0};
+ keymaster_key_characteristics_t key_characteristics{{nullptr, 0}, {nullptr, 0}};
+
+ // convert the parameter set to something our backend understands
+ auto kmParams = hidlParams2KmParamSet(keyParams);
+
+ auto rc = keymaster_device_->generate_key(keymaster_device_, &kmParams, &key_blob,
+ &key_characteristics);
+
+ if (rc == KM_ERROR_OK) {
+ // on success convert the result to wire format
+ resultKeyBlob = kmBlob2hidlVec(key_blob);
+ resultCharacteristics.softwareEnforced = kmParamSet2Hidl(key_characteristics.sw_enforced);
+ resultCharacteristics.teeEnforced = kmParamSet2Hidl(key_characteristics.hw_enforced);
+ }
+
+ // send results off to the client
+ _hidl_cb(legacy_enum_conversion(rc), resultKeyBlob, resultCharacteristics);
+
+ // free buffers that we are responsible for
+ if (key_blob.key_material) free(const_cast<uint8_t*>(key_blob.key_material));
+ keymaster_free_characteristics(&key_characteristics);
+
+ return Void();
+}
+
+Return<void> LegacyKeymasterDeviceWrapper::getKeyCharacteristics(
+ const hidl_vec<uint8_t>& keyBlob, const hidl_vec<uint8_t>& clientId,
+ const hidl_vec<uint8_t>& appData, getKeyCharacteristics_cb _hidl_cb) {
+ // result variables for the wire
+ KeyCharacteristics resultCharacteristics;
+
+ // result variables the backend understands
+ keymaster_key_characteristics_t key_characteristics{{nullptr, 0}, {nullptr, 0}};
+
+ auto kmKeyBlob = hidlVec2KmKeyBlob(keyBlob);
+ auto kmClientId = hidlVec2KmBlob(clientId);
+ auto kmAppData = hidlVec2KmBlob(appData);
+
+ auto rc = keymaster_device_->get_key_characteristics(
+ keymaster_device_, keyBlob.size() ? &kmKeyBlob : nullptr,
+ clientId.size() ? &kmClientId : nullptr, appData.size() ? &kmAppData : nullptr,
+ &key_characteristics);
+
+ if (rc == KM_ERROR_OK) {
+ resultCharacteristics.softwareEnforced = kmParamSet2Hidl(key_characteristics.sw_enforced);
+ resultCharacteristics.teeEnforced = kmParamSet2Hidl(key_characteristics.hw_enforced);
+ }
+
+ _hidl_cb(legacy_enum_conversion(rc), resultCharacteristics);
+
+ keymaster_free_characteristics(&key_characteristics);
+
+ return Void();
+}
+
+Return<void> LegacyKeymasterDeviceWrapper::importKey(const hidl_vec<KeyParameter>& params,
+ KeyFormat keyFormat,
+ const hidl_vec<uint8_t>& keyData,
+ importKey_cb _hidl_cb) {
+ // result variables for the wire
+ KeyCharacteristics resultCharacteristics;
+ hidl_vec<uint8_t> resultKeyBlob;
+
+ // result variables the backend understands
+ keymaster_key_blob_t key_blob{nullptr, 0};
+ keymaster_key_characteristics_t key_characteristics{{nullptr, 0}, {nullptr, 0}};
+
+ auto kmParams = hidlParams2KmParamSet(params);
+ auto kmKeyData = hidlVec2KmBlob(keyData);
+
+ auto rc = keymaster_device_->import_key(keymaster_device_, &kmParams,
+ legacy_enum_conversion(keyFormat), &kmKeyData,
+ &key_blob, &key_characteristics);
+
+ if (rc == KM_ERROR_OK) {
+ // on success convert the result to wire format
+ resultKeyBlob = kmBlob2hidlVec(key_blob);
+ resultCharacteristics.softwareEnforced = kmParamSet2Hidl(key_characteristics.sw_enforced);
+ resultCharacteristics.teeEnforced = kmParamSet2Hidl(key_characteristics.hw_enforced);
+ }
+
+ _hidl_cb(legacy_enum_conversion(rc), resultKeyBlob, resultCharacteristics);
+
+ // free buffers that we are responsible for
+ if (key_blob.key_material) free(const_cast<uint8_t*>(key_blob.key_material));
+ keymaster_free_characteristics(&key_characteristics);
+
+ return Void();
+}
+
+Return<void> LegacyKeymasterDeviceWrapper::exportKey(KeyFormat exportFormat,
+ const hidl_vec<uint8_t>& keyBlob,
+ const hidl_vec<uint8_t>& clientId,
+ const hidl_vec<uint8_t>& appData,
+ exportKey_cb _hidl_cb) {
+
+ // result variables for the wire
+ hidl_vec<uint8_t> resultKeyBlob;
+
+ // result variables the backend understands
+ keymaster_blob_t out_blob = {};
+
+ auto kmKeyBlob = hidlVec2KmKeyBlob(keyBlob);
+ auto kmClientId = hidlVec2KmBlob(clientId);
+ auto kmAppData = hidlVec2KmBlob(appData);
+
+ auto rc = keymaster_device_->export_key(keymaster_device_, legacy_enum_conversion(exportFormat),
+ keyBlob.size() ? &kmKeyBlob : nullptr,
+ clientId.size() ? &kmClientId : nullptr,
+ appData.size() ? &kmAppData : nullptr, &out_blob);
+
+ if (rc == KM_ERROR_OK) {
+ // on success convert the result to wire format
+ // (Can we assume that key_blob is {nullptr, 0} or a valid buffer description?)
+ resultKeyBlob = kmBlob2hidlVec(out_blob);
+ }
+
+ _hidl_cb(legacy_enum_conversion(rc), resultKeyBlob);
+
+ // free buffers that we are responsible for
+ if (out_blob.data) free(const_cast<uint8_t*>(out_blob.data));
+
+ return Void();
+}
+
+Return<void> LegacyKeymasterDeviceWrapper::attestKey(const hidl_vec<uint8_t>& keyToAttest,
+ const hidl_vec<KeyParameter>& attestParams,
+ attestKey_cb _hidl_cb) {
+
+ hidl_vec<hidl_vec<uint8_t>> resultCertChain;
+
+ keymaster_cert_chain_t cert_chain = {};
+
+ auto kmKeyToAttest = hidlVec2KmKeyBlob(keyToAttest);
+ auto kmAttestParams = hidlParams2KmParamSet(attestParams);
+
+ auto rc = keymaster_device_->attest_key(keymaster_device_, &kmKeyToAttest, &kmAttestParams,
+ &cert_chain);
+
+ if (rc == KM_ERROR_OK) {
+ resultCertChain = kmCertChain2Hidl(&cert_chain);
+ }
+
+ _hidl_cb(legacy_enum_conversion(rc), resultCertChain);
+
+ keymaster_free_cert_chain(&cert_chain);
+
+ return Void();
+}
+
+Return<void> LegacyKeymasterDeviceWrapper::upgradeKey(const hidl_vec<uint8_t>& keyBlobToUpgrade,
+ const hidl_vec<KeyParameter>& upgradeParams,
+ upgradeKey_cb _hidl_cb) {
+
+ // result variables for the wire
+ hidl_vec<uint8_t> resultKeyBlob;
+
+ // result variables the backend understands
+ keymaster_key_blob_t key_blob = {};
+
+ auto kmKeyBlobToUpgrade = hidlVec2KmKeyBlob(keyBlobToUpgrade);
+ auto kmUpgradeParams = hidlParams2KmParamSet(upgradeParams);
+
+ auto rc = keymaster_device_->upgrade_key(keymaster_device_, &kmKeyBlobToUpgrade,
+ &kmUpgradeParams, &key_blob);
+
+ if (rc == KM_ERROR_OK) {
+ // on success convert the result to wire format
+ resultKeyBlob = kmBlob2hidlVec(key_blob);
+ }
+
+ _hidl_cb(legacy_enum_conversion(rc), resultKeyBlob);
+
+ if (key_blob.key_material) free(const_cast<uint8_t*>(key_blob.key_material));
+
+ return Void();
+}
+
+Return<ErrorCode> LegacyKeymasterDeviceWrapper::deleteKey(const hidl_vec<uint8_t>& keyBlob) {
+ auto kmKeyBlob = hidlVec2KmKeyBlob(keyBlob);
+ return legacy_enum_conversion(keymaster_device_->delete_key(keymaster_device_, &kmKeyBlob));
+}
+
+Return<ErrorCode> LegacyKeymasterDeviceWrapper::deleteAllKeys() {
+ return legacy_enum_conversion(keymaster_device_->delete_all_keys(keymaster_device_));
+}
+
+Return<void> LegacyKeymasterDeviceWrapper::begin(KeyPurpose purpose, const hidl_vec<uint8_t>& key,
+ const hidl_vec<KeyParameter>& inParams,
+ begin_cb _hidl_cb) {
+
+ // result variables for the wire
+ hidl_vec<KeyParameter> resultParams;
+ uint64_t resultOpHandle = 0;
+
+ // result variables the backend understands
+ keymaster_key_param_set_t out_params{nullptr, 0};
+ keymaster_operation_handle_t& operation_handle = resultOpHandle;
+
+ auto kmKey = hidlVec2KmKeyBlob(key);
+ auto kmInParams = hidlParams2KmParamSet(inParams);
+
+ auto rc = keymaster_device_->begin(keymaster_device_, legacy_enum_conversion(purpose), &kmKey,
+ &kmInParams, &out_params, &operation_handle);
+
+ if (rc == KM_ERROR_OK) resultParams = kmParamSet2Hidl(out_params);
+
+ _hidl_cb(legacy_enum_conversion(rc), resultParams, resultOpHandle);
+
+ keymaster_free_param_set(&out_params);
+
+ return Void();
+}
+
+Return<void> LegacyKeymasterDeviceWrapper::update(uint64_t operationHandle,
+ const hidl_vec<KeyParameter>& inParams,
+ const hidl_vec<uint8_t>& input,
+ update_cb _hidl_cb) {
+ // result variables for the wire
+ uint32_t resultConsumed = 0;
+ hidl_vec<KeyParameter> resultParams;
+ hidl_vec<uint8_t> resultBlob;
+
+ // result variables the backend understands
+ size_t consumed = 0;
+ keymaster_key_param_set_t out_params = {};
+ keymaster_blob_t out_blob = {};
+
+ auto kmInParams = hidlParams2KmParamSet(inParams);
+ auto kmInput = hidlVec2KmBlob(input);
+
+ auto rc = keymaster_device_->update(keymaster_device_, operationHandle, &kmInParams, &kmInput,
+ &consumed, &out_params, &out_blob);
+
+ if (rc == KM_ERROR_OK) {
+ resultConsumed = consumed;
+ resultParams = kmParamSet2Hidl(out_params);
+ resultBlob = kmBlob2hidlVec(out_blob);
+ }
+
+ _hidl_cb(legacy_enum_conversion(rc), resultConsumed, resultParams, resultBlob);
+
+ keymaster_free_param_set(&out_params);
+ if (out_blob.data) free(const_cast<uint8_t*>(out_blob.data));
+
+ return Void();
+}
+
+Return<void> LegacyKeymasterDeviceWrapper::finish(uint64_t operationHandle,
+ const hidl_vec<KeyParameter>& inParams,
+ const hidl_vec<uint8_t>& input,
+ const hidl_vec<uint8_t>& signature,
+ finish_cb _hidl_cb) {
+ // result variables for the wire
+ hidl_vec<KeyParameter> resultParams;
+ hidl_vec<uint8_t> resultBlob;
+
+ // result variables the backend understands
+ keymaster_key_param_set_t out_params = {};
+ keymaster_blob_t out_blob = {};
+
+ auto kmInParams = hidlParams2KmParamSet(inParams);
+ auto kmInput = hidlVec2KmBlob(input);
+ auto kmSignature = hidlVec2KmBlob(signature);
+
+ auto rc = keymaster_device_->finish(keymaster_device_, operationHandle, &kmInParams, &kmInput,
+ &kmSignature, &out_params, &out_blob);
+
+ if (rc == KM_ERROR_OK) {
+ resultParams = kmParamSet2Hidl(out_params);
+ resultBlob = kmBlob2hidlVec(out_blob);
+ }
+
+ _hidl_cb(legacy_enum_conversion(rc), resultParams, resultBlob);
+
+ keymaster_free_param_set(&out_params);
+ if (out_blob.data) free(const_cast<uint8_t*>(out_blob.data));
+
+ return Void();
+}
+
+Return<ErrorCode> LegacyKeymasterDeviceWrapper::abort(uint64_t operationHandle) {
+ return legacy_enum_conversion(keymaster_device_->abort(keymaster_device_, operationHandle));
+}
+
+sp<IKeymasterDevice> makeSoftwareKeymasterDevice() {
+ keymaster2_device_t* dev = nullptr;
+ dev = (new SoftKeymasterDevice)->keymaster2_device();
+
+ auto kmrc = ::keymaster::ConfigureDevice(dev);
+ if (kmrc != KM_ERROR_OK) {
+ dev->common.close(&dev->common);
+ return nullptr;
+ }
+
+ return new LegacyKeymasterDeviceWrapper(dev);
+}
+
+} // namespace keystore
+} // namespace android
diff --git a/keystore/legacy_keymaster_device_wrapper.h b/keystore/legacy_keymaster_device_wrapper.h
new file mode 100644
index 0000000..5712178
--- /dev/null
+++ b/keystore/legacy_keymaster_device_wrapper.h
@@ -0,0 +1,89 @@
+/*
+ **
+ ** Copyright 2016, The Android Open Source Project
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ ** http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ** See the License for the specific language governing permissions and
+ ** limitations under the License.
+ */
+
+#ifndef LEGACY_KEYMASTER_DEVICE_WRAPPER_H_
+#define LEGACY_KEYMASTER_DEVICE_WRAPPER_H_
+
+#include <android/hardware/keymaster/3.0/IKeymasterDevice.h>
+#include <hidl/Status.h>
+#include <hidl/MQDescriptor.h>
+
+struct keymaster2_device;
+typedef struct keymaster2_device keymaster2_device_t;
+
+namespace android {
+namespace keystore {
+
+using ::android::hardware::keymaster::V3_0::ErrorCode;
+using ::android::hardware::keymaster::V3_0::IKeymasterDevice;
+using ::android::hardware::keymaster::V3_0::KeyCharacteristics;
+using ::android::hardware::keymaster::V3_0::KeyFormat;
+using ::android::hardware::keymaster::V3_0::KeyParameter;
+using ::android::hardware::keymaster::V3_0::KeyPurpose;
+using ::android::hardware::keymaster::V3_0::Tag;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::hidl_string;
+using ::android::sp;
+
+class LegacyKeymasterDeviceWrapper : public IKeymasterDevice {
+ public:
+ LegacyKeymasterDeviceWrapper(keymaster2_device_t* dev);
+ virtual ~LegacyKeymasterDeviceWrapper();
+
+ // Methods from ::android::hardware::keymaster::V3_0::IKeymasterDevice follow.
+ Return<void> getHardwareFeatures(getHardwareFeatures_cb _hidl_cb);
+ Return<ErrorCode> addRngEntropy(const hidl_vec<uint8_t>& data) override;
+ Return<void> generateKey(const hidl_vec<KeyParameter>& keyParams,
+ generateKey_cb _hidl_cb) override;
+ Return<void> getKeyCharacteristics(const hidl_vec<uint8_t>& keyBlob,
+ const hidl_vec<uint8_t>& clientId,
+ const hidl_vec<uint8_t>& appData,
+ getKeyCharacteristics_cb _hidl_cb) override;
+ Return<void> importKey(const hidl_vec<KeyParameter>& params, KeyFormat keyFormat,
+ const hidl_vec<uint8_t>& keyData, importKey_cb _hidl_cb) override;
+ Return<void> exportKey(KeyFormat exportFormat, const hidl_vec<uint8_t>& keyBlob,
+ const hidl_vec<uint8_t>& clientId, const hidl_vec<uint8_t>& appData,
+ exportKey_cb _hidl_cb) override;
+ Return<void> attestKey(const hidl_vec<uint8_t>& keyToAttest,
+ const hidl_vec<KeyParameter>& attestParams,
+ attestKey_cb _hidl_cb) override;
+ Return<void> upgradeKey(const hidl_vec<uint8_t>& keyBlobToUpgrade,
+ const hidl_vec<KeyParameter>& upgradeParams,
+ upgradeKey_cb _hidl_cb) override;
+ Return<ErrorCode> deleteKey(const hidl_vec<uint8_t>& keyBlob) override;
+ Return<ErrorCode> deleteAllKeys() override;
+ Return<void> begin(KeyPurpose purpose, const hidl_vec<uint8_t>& key,
+ const hidl_vec<KeyParameter>& inParams, begin_cb _hidl_cb) override;
+ Return<void> update(uint64_t operationHandle, const hidl_vec<KeyParameter>& inParams,
+ const hidl_vec<uint8_t>& input, update_cb _hidl_cb) override;
+ Return<void> finish(uint64_t operationHandle, const hidl_vec<KeyParameter>& inParams,
+ const hidl_vec<uint8_t>& input, const hidl_vec<uint8_t>& signature,
+ finish_cb _hidl_cb) override;
+ Return<ErrorCode> abort(uint64_t operationHandle) override;
+
+ private:
+ keymaster2_device_t* keymaster_device_;
+};
+
+sp<IKeymasterDevice> makeSoftwareKeymasterDevice();
+
+} // namespace keystore
+} // namespace android
+
+#endif // LEGACY_KEYMASTER_DEVICE_WRAPPER_H_
diff --git a/keystore/operation.cpp b/keystore/operation.cpp
index e8ae8b7..8c39716 100644
--- a/keystore/operation.cpp
+++ b/keystore/operation.cpp
@@ -19,17 +19,18 @@
#include <algorithm>
-namespace android {
+namespace keystore {
+using namespace android;
+
OperationMap::OperationMap(IBinder::DeathRecipient* deathRecipient)
: mDeathRecipient(deathRecipient) {}
-sp<IBinder> OperationMap::addOperation(keymaster_operation_handle_t handle, uint64_t keyid,
- keymaster_purpose_t purpose, const keymaster2_device_t* dev,
+sp<IBinder> OperationMap::addOperation(uint64_t handle, uint64_t keyid, KeyPurpose purpose,
+ const OperationMap::km_device_t& dev,
const sp<IBinder>& appToken,
- keymaster_key_characteristics_t* characteristics,
- bool pruneable) {
+ KeyCharacteristics&& characteristics, bool pruneable) {
sp<IBinder> token = new BBinder();
- mMap[token] = Operation(handle, keyid, purpose, dev, characteristics, appToken);
+ mMap[token] = Operation(handle, keyid, purpose, dev, std::move(characteristics), appToken);
if (pruneable) {
mLru.push_back(token);
}
@@ -40,10 +41,9 @@
return token;
}
-bool OperationMap::getOperation(const sp<IBinder>& token, keymaster_operation_handle_t* outHandle,
- uint64_t* outKeyid, keymaster_purpose_t* outPurpose,
- const keymaster2_device_t** outDevice,
- const keymaster_key_characteristics_t** outCharacteristics) {
+bool OperationMap::getOperation(const sp<IBinder>& token, uint64_t* outHandle, uint64_t* outKeyid,
+ KeyPurpose* outPurpose, km_device_t* outDevice,
+ const KeyCharacteristics** outCharacteristics) {
if (!outHandle || !outDevice) {
return false;
}
@@ -58,7 +58,7 @@
*outPurpose = entry->second.purpose;
*outDevice = entry->second.device;
if (outCharacteristics) {
- *outCharacteristics = entry->second.characteristics.get();
+ *outCharacteristics = &entry->second.characteristics;
}
return true;
}
@@ -116,7 +116,8 @@
return mLru[0];
}
-bool OperationMap::getOperationAuthToken(const sp<IBinder>& token, const hw_auth_token_t** outToken) {
+bool OperationMap::getOperationAuthToken(const sp<IBinder>& token,
+ const HardwareAuthToken** outToken) {
auto entry = mMap.find(token);
if (entry == mMap.end()) {
return false;
@@ -125,12 +126,13 @@
return true;
}
-bool OperationMap::setOperationAuthToken(const sp<IBinder>& token, const hw_auth_token_t* authToken) {
+bool OperationMap::setOperationAuthToken(const sp<IBinder>& token,
+ const HardwareAuthToken* authToken) {
auto entry = mMap.find(token);
if (entry == mMap.end()) {
return false;
}
- entry->second.authToken.reset(new hw_auth_token_t);
+ entry->second.authToken.reset(new HardwareAuthToken);
*entry->second.authToken = *authToken;
return true;
}
@@ -144,13 +146,13 @@
}
}
-OperationMap::Operation::Operation(keymaster_operation_handle_t handle_, uint64_t keyid_,
- keymaster_purpose_t purpose_, const keymaster2_device_t* device_,
- keymaster_key_characteristics_t* characteristics_,
- sp<IBinder> appToken_)
+OperationMap::Operation::Operation(uint64_t handle_, uint64_t keyid_, KeyPurpose purpose_,
+ const OperationMap::km_device_t& device_,
+ KeyCharacteristics&& characteristics_, sp<IBinder> appToken_)
: handle(handle_), keyid(keyid_), purpose(purpose_), device(device_),
characteristics(characteristics_), appToken(appToken_) {}
-OperationMap::Operation::Operation() : handle(0), device(NULL), characteristics(), appToken(NULL) {}
+OperationMap::Operation::Operation()
+ : handle(0), keyid(0), device(nullptr), characteristics(), appToken(nullptr) {}
} // namespace android
diff --git a/keystore/operation.h b/keystore/operation.h
index 263b5c9..e69b43a 100644
--- a/keystore/operation.h
+++ b/keystore/operation.h
@@ -17,73 +17,74 @@
#ifndef KEYSTORE_OPERATION_H_
#define KEYSTORE_OPERATION_H_
-#include <hardware/hw_auth_token.h>
-#include <hardware/keymaster2.h>
#include <binder/Binder.h>
#include <binder/IBinder.h>
+#include <keystore/keymaster_tags.h>
+#include <map>
#include <utils/LruCache.h>
#include <utils/StrongPointer.h>
-#include <map>
#include <vector>
-namespace android {
+namespace keystore {
-struct keymaster_key_characteristics_t_Delete {
- void operator()(keymaster_key_characteristics_t* characteristics) const {
- keymaster_free_characteristics(characteristics);
- delete characteristics;
- }
-};
-typedef std::unique_ptr<keymaster_key_characteristics_t, keymaster_key_characteristics_t_Delete>
- Unique_keymaster_key_characteristics;
+using ::android::IBinder;
+using ::android::sp;
/**
- * OperationMap handles the translation of keymaster_operation_handle_t's and
- * keymaster2_device_t's to opaque binder tokens that can be used to reference
- * that operation at a later time by applications. It also does LRU tracking
- * for operation pruning and keeps a mapping of clients to operations to allow
- * for graceful handling of application death.
+ * OperationMap handles the translation of uint64_t's and keymaster2_device_t's to opaque binder
+ * tokens that can be used to reference that operation at a later time by applications. It also does
+ * LRU tracking for operation pruning and keeps a mapping of clients to operations to allow for
+ * graceful handling of application death.
*/
+
class OperationMap {
-public:
+ typedef ::android::sp<::android::hardware::keymaster::V3_0::IKeymasterDevice> km_device_t;
+
+ public:
explicit OperationMap(IBinder::DeathRecipient* deathRecipient);
- sp<IBinder> addOperation(keymaster_operation_handle_t handle, uint64_t keyid,
- keymaster_purpose_t purpose, const keymaster2_device_t* dev,
- const sp<IBinder>& appToken, keymaster_key_characteristics_t* characteristics,
- bool pruneable);
- bool getOperation(const sp<IBinder>& token, keymaster_operation_handle_t* outHandle,
- uint64_t* outKeyid, keymaster_purpose_t* outPurpose,
- const keymaster2_device_t** outDev,
- const keymaster_key_characteristics_t** outCharacteristics);
- bool removeOperation(const sp<IBinder>& token);
+ android::sp<android::IBinder> addOperation(uint64_t handle, uint64_t keyid, KeyPurpose purpose,
+ const km_device_t& dev,
+ const android::sp<android::IBinder>& appToken,
+ KeyCharacteristics&& characteristics,
+ bool pruneable);
+ bool getOperation(const android::sp<android::IBinder>& token, uint64_t* outHandle,
+ uint64_t* outKeyid, KeyPurpose* outPurpose, km_device_t* outDev,
+ const KeyCharacteristics** outCharacteristics);
+ bool removeOperation(const android::sp<android::IBinder>& token);
bool hasPruneableOperation() const;
size_t getOperationCount() const { return mMap.size(); }
size_t getPruneableOperationCount() const;
- bool getOperationAuthToken(const sp<IBinder>& token, const hw_auth_token_t** outToken);
- bool setOperationAuthToken(const sp<IBinder>& token, const hw_auth_token_t* authToken);
- sp<IBinder> getOldestPruneableOperation();
- std::vector<sp<IBinder>> getOperationsForToken(const sp<IBinder>& appToken);
+ bool getOperationAuthToken(const android::sp<android::IBinder>& token,
+ const HardwareAuthToken** outToken);
+ bool setOperationAuthToken(const android::sp<android::IBinder>& token,
+ const HardwareAuthToken* authToken);
+ android::sp<android::IBinder> getOldestPruneableOperation();
+ std::vector<android::sp<android::IBinder>>
+ getOperationsForToken(const android::sp<android::IBinder>& appToken);
-private:
- void updateLru(const sp<IBinder>& token);
- void removeOperationTracking(const sp<IBinder>& token, const sp<IBinder>& appToken);
+ private:
+ void updateLru(const android::sp<android::IBinder>& token);
+ void removeOperationTracking(const android::sp<android::IBinder>& token,
+ const android::sp<android::IBinder>& appToken);
struct Operation {
Operation();
- Operation(keymaster_operation_handle_t handle, uint64_t keyid, keymaster_purpose_t purpose,
- const keymaster2_device_t* device,
- keymaster_key_characteristics_t* characteristics, sp<IBinder> appToken);
- keymaster_operation_handle_t handle;
+ Operation(uint64_t handle, uint64_t keyid, KeyPurpose purpose, const km_device_t& device,
+ KeyCharacteristics&& characteristics, android::sp<android::IBinder> appToken);
+ uint64_t handle;
uint64_t keyid;
- keymaster_purpose_t purpose;
- const keymaster2_device_t* device;
- Unique_keymaster_key_characteristics characteristics;
- sp<IBinder> appToken;
- std::unique_ptr<hw_auth_token_t> authToken;
+ KeyPurpose purpose;
+ km_device_t device;
+ KeyCharacteristics characteristics;
+ android::sp<android::IBinder> appToken;
+ std::unique_ptr<HardwareAuthToken> authToken;
};
- std::map<sp<IBinder>, struct Operation> mMap;
- std::vector<sp<IBinder>> mLru;
- std::map<sp<IBinder>, std::vector<sp<IBinder>>> mAppTokenMap;
- IBinder::DeathRecipient* mDeathRecipient;
+ std::map<android::sp<android::IBinder>, Operation> mMap;
+ std::vector<android::sp<android::IBinder>> mLru;
+ std::map<android::sp<android::IBinder>, std::vector<android::sp<android::IBinder>>>
+ mAppTokenMap;
+ android::IBinder::DeathRecipient* mDeathRecipient;
};
-} // namespace android
+
+} // namespace keystore
+
#endif
diff --git a/keystore/user_state.cpp b/keystore/user_state.cpp
index 3da88c2..bd4f979 100644
--- a/keystore/user_state.cpp
+++ b/keystore/user_state.cpp
@@ -31,7 +31,9 @@
#include "blob.h"
#include "keystore_utils.h"
-UserState::UserState(uid_t userId) : mUserId(userId), mRetry(MAX_RETRY) {
+
+UserState::UserState(uid_t userId) :
+ mUserId(userId), mState(STATE_UNINITIALIZED), mRetry(MAX_RETRY) {
asprintf(&mUserDir, "user_%u", mUserId);
asprintf(&mMasterKeyFile, "%s/.masterkey", mUserDir);
}
@@ -78,22 +80,22 @@
ResponseCode UserState::initialize(const android::String8& pw, Entropy* entropy) {
if (!generateMasterKey(entropy)) {
- return SYSTEM_ERROR;
+ return ResponseCode::SYSTEM_ERROR;
}
ResponseCode response = writeMasterKey(pw, entropy);
- if (response != NO_ERROR) {
+ if (response != ResponseCode::NO_ERROR) {
return response;
}
setupMasterKeys();
- return ::NO_ERROR;
+ return ResponseCode::NO_ERROR;
}
ResponseCode UserState::copyMasterKey(UserState* src) {
if (mState != STATE_UNINITIALIZED) {
- return ::SYSTEM_ERROR;
+ return ResponseCode::SYSTEM_ERROR;
}
if (src->getState() != STATE_NO_ERROR) {
- return ::SYSTEM_ERROR;
+ return ResponseCode::SYSTEM_ERROR;
}
memcpy(mMasterKey, src->mMasterKey, MASTER_KEY_SIZE_BYTES);
setupMasterKeys();
@@ -106,28 +108,28 @@
*/
int in = TEMP_FAILURE_RETRY(open(src->getMasterKeyFileName(), O_RDONLY));
if (in < 0) {
- return ::SYSTEM_ERROR;
+ return ResponseCode::SYSTEM_ERROR;
}
blob rawBlob;
size_t length = readFully(in, (uint8_t*)&rawBlob, sizeof(rawBlob));
if (close(in) != 0) {
- return ::SYSTEM_ERROR;
+ return ResponseCode::SYSTEM_ERROR;
}
int out =
TEMP_FAILURE_RETRY(open(mMasterKeyFile, O_WRONLY | O_TRUNC | O_CREAT, S_IRUSR | S_IWUSR));
if (out < 0) {
- return ::SYSTEM_ERROR;
+ return ResponseCode::SYSTEM_ERROR;
}
size_t outLength = writeFully(out, (uint8_t*)&rawBlob, length);
if (close(out) != 0) {
- return ::SYSTEM_ERROR;
+ return ResponseCode::SYSTEM_ERROR;
}
if (outLength != length) {
ALOGW("blob not fully written %zu != %zu", outLength, length);
unlink(mMasterKeyFile);
- return ::SYSTEM_ERROR;
+ return ResponseCode::SYSTEM_ERROR;
}
- return ::NO_ERROR;
+ return ResponseCode::NO_ERROR;
}
ResponseCode UserState::writeMasterKey(const android::String8& pw, Entropy* entropy) {
@@ -142,7 +144,7 @@
ResponseCode UserState::readMasterKey(const android::String8& pw, Entropy* entropy) {
int in = TEMP_FAILURE_RETRY(open(mMasterKeyFile, O_RDONLY));
if (in < 0) {
- return SYSTEM_ERROR;
+ return ResponseCode::SYSTEM_ERROR;
}
// We read the raw blob to just to get the salt to generate the AES key, then we create the Blob
@@ -150,7 +152,7 @@
blob rawBlob;
size_t length = readFully(in, (uint8_t*)&rawBlob, sizeof(rawBlob));
if (close(in) != 0) {
- return SYSTEM_ERROR;
+ return ResponseCode::SYSTEM_ERROR;
}
// find salt at EOF if present, otherwise we have an old file
uint8_t* salt;
@@ -165,18 +167,18 @@
AES_set_decrypt_key(passwordKey, MASTER_KEY_SIZE_BITS, &passwordAesKey);
Blob masterKeyBlob(rawBlob);
ResponseCode response = masterKeyBlob.readBlob(mMasterKeyFile, &passwordAesKey, STATE_NO_ERROR);
- if (response == SYSTEM_ERROR) {
+ if (response == ResponseCode::SYSTEM_ERROR) {
return response;
}
- if (response == NO_ERROR && masterKeyBlob.getLength() == MASTER_KEY_SIZE_BYTES) {
+ if (response == ResponseCode::NO_ERROR && masterKeyBlob.getLength() == MASTER_KEY_SIZE_BYTES) {
// If salt was missing, generate one and write a new master key file with the salt.
if (salt == NULL) {
if (!generateSalt(entropy)) {
- return SYSTEM_ERROR;
+ return ResponseCode::SYSTEM_ERROR;
}
response = writeMasterKey(pw, entropy);
}
- if (response == NO_ERROR) {
+ if (response == ResponseCode::NO_ERROR) {
memcpy(mMasterKey, masterKeyBlob.getValue(), MASTER_KEY_SIZE_BYTES);
setupMasterKeys();
}
@@ -184,20 +186,20 @@
}
if (mRetry <= 0) {
reset();
- return UNINITIALIZED;
+ return ResponseCode::UNINITIALIZED;
}
--mRetry;
switch (mRetry) {
case 0:
- return WRONG_PASSWORD_0;
+ return ResponseCode::WRONG_PASSWORD_0;
case 1:
- return WRONG_PASSWORD_1;
+ return ResponseCode::WRONG_PASSWORD_1;
case 2:
- return WRONG_PASSWORD_2;
+ return ResponseCode::WRONG_PASSWORD_2;
case 3:
- return WRONG_PASSWORD_3;
+ return ResponseCode::WRONG_PASSWORD_3;
default:
- return WRONG_PASSWORD_3;
+ return ResponseCode::WRONG_PASSWORD_3;
}
}