am eb819f75: am a39da5a2: Fallback to software keystore on import_key failure
* commit 'eb819f75ae440b39b441cff73808df5641286139':
diff --git a/keystore-engine/Android.mk b/keystore-engine/Android.mk
index bd86b6a..b33a347 100644
--- a/keystore-engine/Android.mk
+++ b/keystore-engine/Android.mk
@@ -15,25 +15,33 @@
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
+include $(TOP)/external/openssl/flavor.mk
-LOCAL_MODULE := libkeystore
+ifeq ($(OPENSSL_FLAVOR),BoringSSL)
+ LOCAL_MODULE := libkeystore-engine
-LOCAL_MODULE_TAGS := optional
+ LOCAL_SRC_FILES := \
+ android_engine.cpp
-LOCAL_MODULE_RELATIVE_PATH := ssl/engines
+ LOCAL_C_INCLUDES += \
+ external/openssl/src/include
+else
+ LOCAL_MODULE := libkeystore
-LOCAL_SRC_FILES := \
+ LOCAL_SRC_FILES := \
eng_keystore.cpp \
keyhandle.cpp \
ecdsa_meth.cpp \
dsa_meth.cpp \
rsa_meth.cpp
-LOCAL_CFLAGS := -fvisibility=hidden -Wall -Werror
-
-LOCAL_C_INCLUDES += \
+ LOCAL_C_INCLUDES += \
external/openssl/include \
external/openssl
+endif
+
+LOCAL_MODULE_TAGS := optional
+LOCAL_CFLAGS := -fvisibility=hidden -Wall -Werror
LOCAL_SHARED_LIBRARIES += \
libcrypto \
diff --git a/keystore-engine/android_engine.cpp b/keystore-engine/android_engine.cpp
new file mode 100644
index 0000000..ee16312
--- /dev/null
+++ b/keystore-engine/android_engine.cpp
@@ -0,0 +1,452 @@
+/* Copyright 2014 The Android Open Source Project
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
+
+#include <UniquePtr.h>
+
+#include <sys/socket.h>
+#include <stdarg.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <openssl/bn.h>
+#include <openssl/ec.h>
+#include <openssl/ec_key.h>
+#include <openssl/ecdsa.h>
+#include <openssl/engine.h>
+#include <openssl/evp.h>
+#include <openssl/rsa.h>
+#include <openssl/x509.h>
+
+#include <binder/IServiceManager.h>
+#include <keystore/keystore.h>
+#include <keystore/IKeystoreService.h>
+
+using namespace android;
+
+namespace {
+
+extern const RSA_METHOD keystore_rsa_method;
+extern const ECDSA_METHOD keystore_ecdsa_method;
+
+/* key_id_dup is called when one of the RSA or EC_KEY objects is duplicated. */
+int key_id_dup(CRYPTO_EX_DATA* to,
+ const CRYPTO_EX_DATA* from,
+ void** from_d,
+ int index,
+ long argl,
+ void* argp) {
+ char *key_id = reinterpret_cast<char *>(*from_d);
+ if (key_id != NULL) {
+ *from_d = strdup(key_id);
+ }
+ return 1;
+}
+
+/* key_id_free is called when one of the RSA, DSA or EC_KEY object is freed. */
+void key_id_free(void* parent,
+ void* ptr,
+ CRYPTO_EX_DATA* ad,
+ int index,
+ long argl,
+ void* argp) {
+ char *key_id = reinterpret_cast<char *>(ptr);
+ free(key_id);
+}
+
+/* KeystoreEngine is a BoringSSL ENGINE that implements RSA and ECDSA by
+ * forwarding the requested operations to Keystore. */
+class KeystoreEngine {
+ public:
+ KeystoreEngine()
+ : rsa_index_(RSA_get_ex_new_index(0 /* argl */,
+ NULL /* argp */,
+ NULL /* new_func */,
+ key_id_dup,
+ key_id_free)),
+ ec_key_index_(EC_KEY_get_ex_new_index(0 /* argl */,
+ NULL /* argp */,
+ NULL /* new_func */,
+ key_id_dup,
+ key_id_free)),
+ engine_(ENGINE_new()) {
+ ENGINE_set_RSA_method(
+ engine_, &keystore_rsa_method, sizeof(keystore_rsa_method));
+ ENGINE_set_ECDSA_method(
+ engine_, &keystore_ecdsa_method, sizeof(keystore_ecdsa_method));
+ }
+
+ int rsa_ex_index() const { return rsa_index_; }
+ int ec_key_ex_index() const { return ec_key_index_; }
+
+ const ENGINE* engine() const { return engine_; }
+
+ private:
+ const int rsa_index_;
+ const int ec_key_index_;
+ ENGINE* const engine_;
+};
+
+pthread_once_t g_keystore_engine_once = PTHREAD_ONCE_INIT;
+KeystoreEngine *g_keystore_engine;
+
+/* init_keystore_engine is called to initialize |g_keystore_engine|. This
+ * should only be called by |pthread_once|. */
+void init_keystore_engine() {
+ g_keystore_engine = new KeystoreEngine;
+}
+
+/* ensure_keystore_engine ensures that |g_keystore_engine| is pointing to a
+ * valid |KeystoreEngine| object and creates one if not. */
+void ensure_keystore_engine() {
+ pthread_once(&g_keystore_engine_once, init_keystore_engine);
+}
+
+/* Many OpenSSL APIs take ownership of an argument on success but don't free
+ * the argument on failure. This means we need to tell our scoped pointers when
+ * we've transferred ownership, without triggering a warning by not using the
+ * result of release(). */
+#define OWNERSHIP_TRANSFERRED(obj) \
+ typeof (obj.release()) _dummy __attribute__((unused)) = obj.release()
+
+const char* rsa_get_key_id(const RSA* rsa) {
+ return reinterpret_cast<char*>(
+ RSA_get_ex_data(rsa, g_keystore_engine->rsa_ex_index()));
+}
+
+/* rsa_private_transform takes a big-endian integer from |in|, calculates the
+ * d'th power of it, modulo the RSA modulus, and writes the result as a
+ * big-endian integer to |out|. Both |in| and |out| are |len| bytes long. It
+ * returns one on success and zero otherwise. */
+int rsa_private_transform(RSA *rsa, uint8_t *out, const uint8_t *in, size_t len) {
+ ALOGV("rsa_private_transform(%p, %p, %p, %u)", rsa, out, in, (unsigned) len);
+
+ const char *key_id = rsa_get_key_id(rsa);
+ if (key_id == NULL) {
+ ALOGE("key had no key_id!");
+ return 0;
+ }
+
+ sp<IServiceManager> sm = defaultServiceManager();
+ sp<IBinder> binder = sm->getService(String16("android.security.keystore"));
+ sp<IKeystoreService> service = interface_cast<IKeystoreService>(binder);
+
+ if (service == NULL) {
+ ALOGE("could not contact keystore");
+ return 0;
+ }
+
+ 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");
+ return 0;
+ } else if (ret != 0) {
+ ALOGW("Error during sign from keystore: %d", ret);
+ return 0;
+ } else if (reply_len == 0) {
+ ALOGW("No valid signature returned");
+ free(reply);
+ return 0;
+ }
+
+ if (reply_len > 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) {
+ /* 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);
+ } else {
+ memcpy(out, reply, len);
+ }
+
+ free(reply);
+
+ ALOGV("rsa=%p keystore_rsa_priv_dec successful", rsa);
+ return 1;
+}
+
+const struct rsa_meth_st keystore_rsa_method = {
+ {
+ 0 /* references */,
+ 1 /* is_static */,
+ },
+ NULL /* app_data */,
+
+ NULL /* init */,
+ NULL /* finish */,
+
+ NULL /* size */,
+
+ NULL /* sign */,
+ NULL /* verify */,
+
+ NULL /* encrypt */,
+ NULL /* sign_raw */,
+ NULL /* decrypt */,
+ NULL /* verify_raw */,
+
+ rsa_private_transform,
+
+ NULL /* mod_exp */,
+ NULL /* bn_mod_exp */,
+
+ RSA_FLAG_CACHE_PUBLIC | RSA_FLAG_OPAQUE | RSA_FLAG_EXT_PKEY,
+
+ NULL /* keygen */,
+};
+
+const char* ecdsa_get_key_id(const EC_KEY* ec_key) {
+ return reinterpret_cast<char*>(
+ EC_KEY_get_ex_data(ec_key, g_keystore_engine->ec_key_ex_index()));
+}
+
+/* ecdsa_sign signs |digest_len| bytes from |digest| with |ec_key| and writes
+ * the resulting signature (an ASN.1 encoded blob) to |sig|. It returns one on
+ * success and zero otherwise. */
+static int ecdsa_sign(const uint8_t* digest, size_t digest_len, uint8_t* sig,
+ unsigned int* sig_len, EC_KEY* ec_key) {
+ ALOGV("ecdsa_sign(%p, %u, %p)", digest, (unsigned) digest_len, ec_key);
+
+ const char *key_id = ecdsa_get_key_id(ec_key);
+ if (key_id == NULL) {
+ ALOGE("key had no key_id!");
+ return 0;
+ }
+
+ sp<IServiceManager> sm = defaultServiceManager();
+ sp<IBinder> binder = sm->getService(String16("android.security.keystore"));
+ sp<IKeystoreService> service = interface_cast<IKeystoreService>(binder);
+
+ if (service == NULL) {
+ ALOGE("could not contact keystore");
+ return 0;
+ }
+
+ 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");
+ return 0;
+ } else if (ret != 0) {
+ ALOGW("Error during sign from keystore: %d", ret);
+ return 0;
+ } else if (reply_len == 0) {
+ ALOGW("No valid signature returned");
+ free(reply);
+ return 0;
+ } else if (reply_len > ecdsa_size) {
+ ALOGW("Signature is too large");
+ free(reply);
+ return 0;
+ }
+
+ memcpy(sig, reply, reply_len);
+ *sig_len = reply_len;
+
+ ALOGV("ecdsa_sign(%p, %u, %p) => success", digest, (unsigned)digest_len,
+ ec_key);
+ return 1;
+}
+
+const ECDSA_METHOD keystore_ecdsa_method = {
+ {
+ 0 /* references */,
+ 1 /* is_static */
+ } /* common */,
+ NULL /* app_data */,
+
+ NULL /* init */,
+ NULL /* finish */,
+ NULL /* group_order_size */,
+ ecdsa_sign,
+ NULL /* verify */,
+ ECDSA_FLAG_OPAQUE,
+};
+
+struct EVP_PKEY_Delete {
+ void operator()(EVP_PKEY* p) const {
+ EVP_PKEY_free(p);
+ }
+};
+typedef UniquePtr<EVP_PKEY, EVP_PKEY_Delete> Unique_EVP_PKEY;
+
+struct RSA_Delete {
+ void operator()(RSA* p) const {
+ RSA_free(p);
+ }
+};
+typedef UniquePtr<RSA, RSA_Delete> Unique_RSA;
+
+struct EC_KEY_Delete {
+ void operator()(EC_KEY* ec) const {
+ EC_KEY_free(ec);
+ }
+};
+typedef UniquePtr<EC_KEY, EC_KEY_Delete> Unique_EC_KEY;
+
+/* wrap_rsa returns an |EVP_PKEY| that contains an RSA key where the public
+ * part is taken from |public_rsa| and the private operations are forwarded to
+ * KeyStore and operate on the key named |key_id|. */
+static EVP_PKEY *wrap_rsa(const char *key_id, const RSA *public_rsa) {
+ Unique_RSA rsa(RSA_new_method(g_keystore_engine->engine()));
+ if (rsa.get() == NULL) {
+ return NULL;
+ }
+
+ char *key_id_copy = strdup(key_id);
+ if (key_id_copy == NULL) {
+ return NULL;
+ }
+
+ if (!RSA_set_ex_data(rsa.get(), g_keystore_engine->rsa_ex_index(),
+ key_id_copy)) {
+ free(key_id_copy);
+ return NULL;
+ }
+
+ rsa->n = BN_dup(public_rsa->n);
+ rsa->e = BN_dup(public_rsa->e);
+ if (rsa->n == NULL || rsa->e == NULL) {
+ return NULL;
+ }
+
+ Unique_EVP_PKEY result(EVP_PKEY_new());
+ if (result.get() == NULL ||
+ !EVP_PKEY_assign_RSA(result.get(), rsa.get())) {
+ return NULL;
+ }
+ OWNERSHIP_TRANSFERRED(rsa);
+
+ return result.release();
+}
+
+/* wrap_ecdsa returns an |EVP_PKEY| that contains an ECDSA key where the public
+ * part is taken from |public_rsa| and the private operations are forwarded to
+ * KeyStore and operate on the key named |key_id|. */
+static EVP_PKEY *wrap_ecdsa(const char *key_id, const EC_KEY *public_ecdsa) {
+ Unique_EC_KEY ec(EC_KEY_new_method(g_keystore_engine->engine()));
+ if (ec.get() == NULL) {
+ return NULL;
+ }
+
+ if (!EC_KEY_set_group(ec.get(), EC_KEY_get0_group(public_ecdsa)) ||
+ !EC_KEY_set_public_key(ec.get(), EC_KEY_get0_public_key(public_ecdsa))) {
+ return NULL;
+ }
+
+ char *key_id_copy = strdup(key_id);
+ if (key_id_copy == NULL) {
+ return NULL;
+ }
+
+ if (!EC_KEY_set_ex_data(ec.get(), g_keystore_engine->ec_key_ex_index(),
+ key_id_copy)) {
+ free(key_id_copy);
+ return NULL;
+ }
+
+ Unique_EVP_PKEY result(EVP_PKEY_new());
+ if (result.get() == NULL ||
+ !EVP_PKEY_assign_EC_KEY(result.get(), ec.get())) {
+ return NULL;
+ }
+ OWNERSHIP_TRANSFERRED(ec);
+
+ return result.release();
+}
+
+} /* anonymous namespace */
+
+extern "C" {
+
+EVP_PKEY* EVP_PKEY_from_keystore(const char* key_id) __attribute__((visibility("default")));
+
+/* EVP_PKEY_from_keystore returns an |EVP_PKEY| that contains either an RSA or
+ * ECDSA key where the public part of the key reflects the value of the key
+ * named |key_id| in Keystore and the private operations are forwarded onto
+ * KeyStore. */
+EVP_PKEY* EVP_PKEY_from_keystore(const char* key_id) {
+ ALOGV("EVP_PKEY_from_keystore(\"%s\")", key_id);
+
+ sp<IServiceManager> sm = defaultServiceManager();
+ sp<IBinder> binder = sm->getService(String16("android.security.keystore"));
+ sp<IKeystoreService> service = interface_cast<IKeystoreService>(binder);
+
+ if (service == NULL) {
+ ALOGE("could not contact keystore");
+ 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);
+ return NULL;
+ }
+
+ const uint8_t *inp = pubkey;
+ Unique_EVP_PKEY pkey(d2i_PUBKEY(NULL, &inp, pubkey_len));
+ free(pubkey);
+ if (pkey.get() == NULL) {
+ ALOGW("Cannot convert pubkey");
+ return NULL;
+ }
+
+ ensure_keystore_engine();
+
+ EVP_PKEY *result;
+ switch (EVP_PKEY_type(pkey->type)) {
+ case EVP_PKEY_RSA: {
+ Unique_RSA public_rsa(EVP_PKEY_get1_RSA(pkey.get()));
+ result = wrap_rsa(key_id, public_rsa.get());
+ break;
+ }
+ case EVP_PKEY_EC: {
+ Unique_EC_KEY public_ecdsa(EVP_PKEY_get1_EC_KEY(pkey.get()));
+ result = wrap_ecdsa(key_id, public_ecdsa.get());
+ break;
+ }
+ default:
+ ALOGE("Unsupported key type %d", EVP_PKEY_type(pkey->type));
+ result = NULL;
+ }
+
+ return result;
+}
+
+} // extern "C"
diff --git a/keystore/keystore.cpp b/keystore/keystore.cpp
index 3372d04..e56edfd 100644
--- a/keystore/keystore.cpp
+++ b/keystore/keystore.cpp
@@ -998,7 +998,6 @@
return userState->writeMasterKey(pw, mEntropy);
}
-
ResponseCode readMasterKey(const android::String8& pw, uid_t uid) {
UserState* userState = getUserState(uid);
return userState->readMasterKey(pw, mEntropy);
@@ -1024,7 +1023,20 @@
}
bool reset(uid_t uid) {
+ android::String8 prefix("");
+ android::Vector<android::String16> aliases;
+ if (saw(prefix, &aliases, uid) != ::NO_ERROR) {
+ return ::SYSTEM_ERROR;
+ }
+
UserState* userState = getUserState(uid);
+ for (uint32_t i = 0; i < aliases.size(); i++) {
+ android::String8 filename(aliases[i]);
+ filename = android::String8::format("%s/%s", userState->getUserDirName(),
+ getKeyName(filename).string());
+ del(filename, ::TYPE_ANY, uid);
+ }
+
userState->zeroizeMasterKeysInMemory();
userState->setState(STATE_UNINITIALIZED);
return userState->reset();
@@ -1121,6 +1133,71 @@
mEntropy);
}
+ ResponseCode del(const char *filename, const BlobType type, uid_t uid) {
+ Blob keyBlob;
+ ResponseCode rc = get(filename, &keyBlob, type, uid);
+ if (rc != ::NO_ERROR) {
+ return rc;
+ }
+
+ if (keyBlob.getType() == ::TYPE_KEY_PAIR) {
+ // A device doesn't have to implement delete_keypair.
+ if (mDevice->delete_keypair != NULL && !keyBlob.isFallback()) {
+ if (mDevice->delete_keypair(mDevice, keyBlob.getValue(), keyBlob.getLength())) {
+ rc = ::SYSTEM_ERROR;
+ }
+ }
+ }
+ if (rc != ::NO_ERROR) {
+ return rc;
+ }
+
+ return (unlink(filename) && errno != ENOENT) ? ::SYSTEM_ERROR : ::NO_ERROR;
+ }
+
+ ResponseCode saw(const android::String8& prefix, android::Vector<android::String16> *matches,
+ uid_t uid) {
+
+ UserState* userState = getUserState(uid);
+ size_t n = prefix.length();
+
+ DIR* dir = opendir(userState->getUserDirName());
+ if (!dir) {
+ ALOGW("can't open directory for user: %s", strerror(errno));
+ return ::SYSTEM_ERROR;
+ }
+
+ struct dirent* file;
+ while ((file = readdir(dir)) != NULL) {
+ // We only care about files.
+ if (file->d_type != DT_REG) {
+ continue;
+ }
+
+ // Skip anything that starts with a "."
+ if (file->d_name[0] == '.') {
+ continue;
+ }
+
+ if (!strncmp(prefix.string(), file->d_name, n)) {
+ const char* p = &file->d_name[n];
+ size_t plen = strlen(p);
+
+ size_t extra = decode_key_length(p, plen);
+ char *match = (char*) malloc(extra + 1);
+ if (match != NULL) {
+ decode_key(match, p, plen);
+ matches->push(android::String16(match, extra));
+ free(match);
+ } else {
+ ALOGW("could not allocate match of size %zd", extra);
+ }
+ }
+ }
+ closedir(dir);
+ return ::NO_ERROR;
+ }
+
void addGrant(const char* filename, uid_t granteeUid) {
const grant_t* existing = getGrant(filename, granteeUid);
if (existing == NULL) {
@@ -1598,14 +1675,7 @@
String8 name8(name);
String8 filename(mKeyStore->getKeyNameForUidWithDir(name8, targetUid));
-
- Blob keyBlob;
- ResponseCode responseCode = mKeyStore->get(filename.string(), &keyBlob, TYPE_GENERIC,
- targetUid);
- if (responseCode != ::NO_ERROR) {
- return responseCode;
- }
- return (unlink(filename) && errno != ENOENT) ? ::SYSTEM_ERROR : ::NO_ERROR;
+ return mKeyStore->del(filename.string(), ::TYPE_GENERIC, targetUid);
}
int32_t exist(const String16& name, int targetUid) {
@@ -1645,46 +1715,12 @@
return ::PERMISSION_DENIED;
}
- UserState* userState = mKeyStore->getUserState(targetUid);
- DIR* dir = opendir(userState->getUserDirName());
- if (!dir) {
- ALOGW("can't open directory for user: %s", strerror(errno));
- return ::SYSTEM_ERROR;
- }
-
const String8 prefix8(prefix);
String8 filename(mKeyStore->getKeyNameForUid(prefix8, targetUid));
- size_t n = filename.length();
- struct dirent* file;
- while ((file = readdir(dir)) != NULL) {
- // We only care about files.
- if (file->d_type != DT_REG) {
- continue;
- }
-
- // Skip anything that starts with a "."
- if (file->d_name[0] == '.') {
- continue;
- }
-
- if (!strncmp(filename.string(), file->d_name, n)) {
- const char* p = &file->d_name[n];
- size_t plen = strlen(p);
-
- size_t extra = decode_key_length(p, plen);
- char *match = (char*) malloc(extra + 1);
- if (match != NULL) {
- decode_key(match, p, plen);
- matches->push(String16(match, extra));
- free(match);
- } else {
- ALOGW("could not allocate match of size %zd", extra);
- }
- }
+ if (mKeyStore->saw(filename, matches, targetUid) != ::NO_ERROR) {
+ return ::SYSTEM_ERROR;
}
- closedir(dir);
-
return ::NO_ERROR;
}
@@ -1696,25 +1732,7 @@
return ::PERMISSION_DENIED;
}
- ResponseCode rc = mKeyStore->reset(callingUid) ? ::NO_ERROR : ::SYSTEM_ERROR;
-
- const keymaster_device_t* device = mKeyStore->getDevice();
- if (device == NULL) {
- ALOGE("No keymaster device!");
- return ::SYSTEM_ERROR;
- }
-
- if (device->delete_all == NULL) {
- ALOGV("keymaster device doesn't implement delete_all");
- return rc;
- }
-
- if (device->delete_all(device)) {
- ALOGE("Problem calling keymaster's delete_all");
- return ::SYSTEM_ERROR;
- }
-
- return rc;
+ return mKeyStore->reset(callingUid) ? ::NO_ERROR : ::SYSTEM_ERROR;
}
/*
@@ -2151,33 +2169,7 @@
String8 name8(name);
String8 filename(mKeyStore->getKeyNameForUidWithDir(name8, targetUid));
-
- Blob keyBlob;
- ResponseCode responseCode = mKeyStore->get(filename.string(), &keyBlob, ::TYPE_KEY_PAIR,
- targetUid);
- if (responseCode != ::NO_ERROR) {
- return responseCode;
- }
-
- ResponseCode rc = ::NO_ERROR;
-
- const keymaster_device_t* device = mKeyStore->getDevice();
- if (device == NULL) {
- rc = ::SYSTEM_ERROR;
- } else {
- // A device doesn't have to implement delete_keypair.
- if (device->delete_keypair != NULL && !keyBlob.isFallback()) {
- if (device->delete_keypair(device, keyBlob.getValue(), keyBlob.getLength())) {
- rc = ::SYSTEM_ERROR;
- }
- }
- }
-
- if (rc != ::NO_ERROR) {
- return rc;
- }
-
- return (unlink(filename) && errno != ENOENT) ? ::SYSTEM_ERROR : ::NO_ERROR;
+ return mKeyStore->del(filename.string(), ::TYPE_KEY_PAIR, targetUid);
}
int32_t grant(const String16& name, int32_t granteeUid) {
@@ -2348,75 +2340,34 @@
return ::SYSTEM_ERROR;
}
- UserState* userState = mKeyStore->getUserState(targetUid);
- DIR* dir = opendir(userState->getUserDirName());
- if (!dir) {
- ALOGW("can't open user directory: %s", strerror(errno));
+ String8 prefix = String8::format("%u_", targetUid);
+ Vector<String16> aliases;
+ if (mKeyStore->saw(prefix, &aliases, targetUid) != ::NO_ERROR) {
return ::SYSTEM_ERROR;
}
- char prefix[NAME_MAX];
- int n = snprintf(prefix, NAME_MAX, "%u_", targetUid);
-
- ResponseCode rc = ::NO_ERROR;
-
- struct dirent* file;
- while ((file = readdir(dir)) != NULL) {
- // We only care about files.
- if (file->d_type != DT_REG) {
- continue;
- }
-
- // Skip anything that starts with a "."
- if (file->d_name[0] == '.') {
- continue;
- }
-
- if (strncmp(prefix, file->d_name, n)) {
- continue;
- }
-
- String8 filename(String8::format("%s/%s", userState->getUserDirName(), file->d_name));
- Blob keyBlob;
- if (mKeyStore->get(filename.string(), &keyBlob, ::TYPE_ANY, targetUid)
- != ::NO_ERROR) {
- ALOGW("couldn't open %s", filename.string());
- continue;
- }
-
- if (keyBlob.getType() == ::TYPE_KEY_PAIR) {
- // A device doesn't have to implement delete_keypair.
- if (device->delete_keypair != NULL && !keyBlob.isFallback()) {
- if (device->delete_keypair(device, keyBlob.getValue(), keyBlob.getLength())) {
- rc = ::SYSTEM_ERROR;
- ALOGW("device couldn't remove %s", filename.string());
- }
- }
- }
-
- if (unlinkat(dirfd(dir), file->d_name, 0) && errno != ENOENT) {
- rc = ::SYSTEM_ERROR;
- ALOGW("couldn't unlink %s", filename.string());
- }
+ for (uint32_t i = 0; i < aliases.size(); i++) {
+ String8 name8(aliases[i]);
+ String8 filename(mKeyStore->getKeyNameForUidWithDir(name8, targetUid));
+ mKeyStore->del(filename.string(), ::TYPE_ANY, targetUid);
}
- closedir(dir);
-
- return rc;
+ return ::NO_ERROR;
}
- int32_t reset_uid(int32_t uid) {
+ int32_t reset_uid(int32_t targetUid) {
uid_t callingUid = IPCThreadState::self()->getCallingUid();
pid_t spid = IPCThreadState::self()->getCallingPid();
+
if (!has_permission(callingUid, P_RESET_UID, spid)) {
- ALOGW("permission denied for %d: reset_uid %d", callingUid, uid);
+ ALOGW("permission denied for %d: reset_uid %d", callingUid, targetUid);
return ::PERMISSION_DENIED;
}
- if (callingUid != AID_SYSTEM) {
- ALOGW("permission denied for %d: reset_uid %d", callingUid, uid);
+ if (!is_self_or_system(callingUid, targetUid)) {
+ ALOGW("permission denied for %d: reset_uid %d", callingUid, targetUid);
return ::PERMISSION_DENIED;
}
- return mKeyStore->reset(uid) ? ::NO_ERROR : ::SYSTEM_ERROR;
+ return mKeyStore->reset(targetUid) ? ::NO_ERROR : ::SYSTEM_ERROR;
}
int32_t sync_uid(int32_t sourceUid, int32_t targetUid) {
diff --git a/softkeymaster/keymaster_openssl.cpp b/softkeymaster/keymaster_openssl.cpp
index 85ecc6e..2dc4109 100644
--- a/softkeymaster/keymaster_openssl.cpp
+++ b/softkeymaster/keymaster_openssl.cpp
@@ -118,7 +118,7 @@
}
ERR_clear_error();
- ERR_remove_state(0);
+ ERR_remove_thread_state(NULL);
}
static int wrap_key(EVP_PKEY* pkey, int type, uint8_t** keyBlob, size_t* keyBlobLength) {
@@ -291,9 +291,6 @@
static int generate_ec_keypair(EVP_PKEY* pkey, const keymaster_ec_keygen_params_t* ec_params) {
Unique_EC_GROUP group;
switch (ec_params->field_size) {
- case 192:
- group.reset(EC_GROUP_new_by_curve_name(NID_X9_62_prime192v1));
- break;
case 224:
group.reset(EC_GROUP_new_by_curve_name(NID_secp224r1));
break;
@@ -316,7 +313,9 @@
}
EC_GROUP_set_point_conversion_form(group.get(), POINT_CONVERSION_UNCOMPRESSED);
+#if !defined(OPENSSL_IS_BORINGSSL)
EC_GROUP_set_asn1_flag(group.get(), OPENSSL_EC_NAMED_CURVE);
+#endif
/* initialize EC key */
Unique_EC_KEY eckey(EC_KEY_new());