summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorShawn Willden <swillden@google.com>2016-01-28 23:20:01 +0000
committerGerrit Code Review <noreply-gerritcodereview@google.com>2016-01-28 23:20:01 +0000
commita1433ee2f85ae9d2db4e9eb996b6b23af1542247 (patch)
treefcf3d25ebd157f2c4b1ba6be2e81270a9a8a763f
parentfd50293cd5f91936ea954b0556f3f434243adf27 (diff)
parentd3fac68c4982a5a188c0b3648eea2f16c4791d21 (diff)
downloadsecurity-brillo-m10-release.tar.gz
Merge changes from topic 'km_tag_allow_on_body'brillo-m10-releasebrillo-m10-dev
* changes: Add KM_TAG_ALLOW_WHILE_ON_BODY Add attestation support to keystore.
-rw-r--r--keystore/Android.mk2
-rw-r--r--keystore/IKeystoreService.cpp111
-rw-r--r--keystore/include/keystore/IKeystoreService.h14
-rw-r--r--keystore/key_store_service.cpp34
-rw-r--r--keystore/key_store_service.h3
-rw-r--r--keystore/keystore_cli_v2.cpp97
6 files changed, 151 insertions, 110 deletions
diff --git a/keystore/Android.mk b/keystore/Android.mk
index f2262c12..04ca220e 100644
--- a/keystore/Android.mk
+++ b/keystore/Android.mk
@@ -74,7 +74,7 @@ include $(CLEAR_VARS)
ifeq ($(USE_32_BIT_KEYSTORE), true)
LOCAL_MULTILIB := 32
endif
-LOCAL_CFLAGS := -Wall -Wextra -Werror -Wno-unused-parameter
+LOCAL_CFLAGS := -Wall -Wextra -Werror -Wno-unused-parameter -DKEYMASTER_NAME_TAGS
LOCAL_SRC_FILES := keystore_cli_v2.cpp
LOCAL_SHARED_LIBRARIES := \
libchrome \
diff --git a/keystore/IKeystoreService.cpp b/keystore/IKeystoreService.cpp
index 8ed09c4c..466ac241 100644
--- a/keystore/IKeystoreService.cpp
+++ b/keystore/IKeystoreService.cpp
@@ -208,6 +208,69 @@ void KeyCharacteristics::writeToParcel(Parcel* out) const {
}
}
+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;
+ }
+
+ blob->data_length = 0;
+ ssize_t length = in.readInt32();
+ if (length <= 0) {
+ blob->data = nullptr;
+ return false;
+ }
+
+ blob->data = reinterpret_cast<const uint8_t*>(in.readInplace(length));
+ if (blob->data) {
+ blob->data_length = static_cast<size_t>(length);
+ }
+ return true;
+}
+
+void KeymasterCertificateChain::readFromParcel(const Parcel& in) {
+ ssize_t count = in.readInt32();
+ size_t ucount = count;
+ if (count < 0) {
+ ucount = 0;
+ }
+ keymaster_free_cert_chain(&chain);
+ chain.entries = new keymaster_blob_t[ucount];
+ memset(chain.entries, 0, sizeof(keymaster_blob_t) * ucount);
+ for (size_t i = 0; i < ucount; ++i) {
+ if (!readKeymasterBlob(in, &chain.entries[i])) {
+ 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(1); // Tell Java side that object is not NULL
+ 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:
@@ -369,23 +432,9 @@ err:
}
static std::unique_ptr<keymaster_blob_t> readKeymasterBlob(const Parcel& in) {
- std::unique_ptr<keymaster_blob_t> blob;
- if (in.readInt32() != 1) {
- blob.reset(NULL);
- return blob;
- }
- ssize_t length = in.readInt32();
- blob.reset(new keymaster_blob_t);
- if (length > 0) {
- blob->data = reinterpret_cast<const uint8_t*>(in.readInplace(length));
- if (blob->data) {
- blob->data_length = static_cast<size_t>(length);
- } else {
- blob->data_length = 0;
- }
- } else {
- blob->data = NULL;
- blob->data_length = 0;
+ std::unique_ptr<keymaster_blob_t> blob (new keymaster_blob_t);
+ if (!readKeymasterBlob(in, blob.get())) {
+ blob.reset();
}
return blob;
}
@@ -1257,6 +1306,34 @@ public:
return ret;
}
+ virtual int32_t attestKey(const String16& name, const KeymasterArguments& params,
+ KeymasterCertificateChain* outChain) {
+ if (!outChain)
+ return KM_ERROR_OUTPUT_PARAMETER_NULL;
+
+ Parcel data, reply;
+ data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
+ data.writeString16(name);
+ data.writeInt32(1); // params is not NULL.
+ params.writeToParcel(&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;
+ }
+ int32_t err = reply.readExceptionCode();
+ int32_t ret = reply.readInt32();
+ if (err < 0) {
+ ALOGD("attestKey() caught exception %d\n", err);
+ return KM_ERROR_UNKNOWN_ERROR;
+ }
+ if (reply.readInt32() != 0) {
+ outChain->readFromParcel(reply);
+ }
+ return ret;
+ }
+
};
IMPLEMENT_META_INTERFACE(KeystoreService, "android.security.IKeystoreService");
diff --git a/keystore/include/keystore/IKeystoreService.h b/keystore/include/keystore/IKeystoreService.h
index c136dfd0..1c2f6a58 100644
--- a/keystore/include/keystore/IKeystoreService.h
+++ b/keystore/include/keystore/IKeystoreService.h
@@ -90,6 +90,16 @@ struct KeyCharacteristics {
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;
+
+ 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);
@@ -134,6 +144,7 @@ public:
ADD_AUTH_TOKEN = IBinder::FIRST_CALL_TRANSACTION + 32,
ON_USER_ADDED = IBinder::FIRST_CALL_TRANSACTION + 33,
ON_USER_REMOVED = IBinder::FIRST_CALL_TRANSACTION + 34,
+ ATTEST_KEY = IBinder::FIRST_CALL_TRANSACTION + 35,
};
DECLARE_META_INTERFACE(KeystoreService);
@@ -231,6 +242,9 @@ public:
virtual int32_t onUserRemoved(int32_t userId) = 0;
+ virtual int32_t attestKey(const String16& name, const KeymasterArguments& params,
+ KeymasterCertificateChain* outChain) = 0;
+
};
// ----------------------------------------------------------------------------
diff --git a/keystore/key_store_service.cpp b/keystore/key_store_service.cpp
index 9fbb6bc6..759ef06a 100644
--- a/keystore/key_store_service.cpp
+++ b/keystore/key_store_service.cpp
@@ -1076,6 +1076,40 @@ int32_t KeyStoreService::addAuthToken(const uint8_t* token, size_t length) {
return ::NO_ERROR;
}
+int32_t KeyStoreService::attestKey(const String16& name, const KeymasterArguments& params,
+ KeymasterCertificateChain* outChain) {
+ if (!outChain)
+ return KM_ERROR_OUTPUT_PARAMETER_NULL;
+
+ if (!checkAllowedOperationParams(params.params)) {
+ return KM_ERROR_INVALID_ARGUMENT;
+ }
+
+ uid_t callingUid = IPCThreadState::self()->getCallingUid();
+
+ Blob keyBlob;
+ String8 name8(name);
+ ResponseCode responseCode =
+ mKeyStore->getKeyForName(&keyBlob, name8, callingUid, TYPE_KEYMASTER_10);
+ if (responseCode != ::NO_ERROR) {
+ 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;
+
+ const keymaster_key_param_set_t in_params = {
+ const_cast<keymaster_key_param_t*>(params.params.data()), params.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;
+}
+
/**
* Prune the oldest pruneable operation.
*/
diff --git a/keystore/key_store_service.h b/keystore/key_store_service.h
index e61bdea1..35b89289 100644
--- a/keystore/key_store_service.h
+++ b/keystore/key_store_service.h
@@ -114,6 +114,9 @@ class KeyStoreService : public BnKeystoreService, public IBinder::DeathRecipient
int32_t addAuthToken(const uint8_t* token, size_t length);
+ int32_t attestKey(const String16& name, const KeymasterArguments& params,
+ KeymasterCertificateChain* outChain) override;
+
private:
static const int32_t UID_SELF = -1;
diff --git a/keystore/keystore_cli_v2.cpp b/keystore/keystore_cli_v2.cpp
index 3efc99af..c4dbf5dd 100644
--- a/keystore/keystore_cli_v2.cpp
+++ b/keystore/keystore_cli_v2.cpp
@@ -20,6 +20,7 @@
#include "base/command_line.h"
#include "base/files/file_util.h"
#include "keymaster/authorization_set.h"
+#include "keymaster/keymaster_tags.h"
#include "keystore/keystore_client_impl.h"
using base::CommandLine;
@@ -56,102 +57,14 @@ std::unique_ptr<KeystoreClient> CreateKeystoreInstance() {
return std::unique_ptr<KeystoreClient>(new keystore::KeystoreClientImpl);
}
-const char* StringifyTag(keymaster_tag_t tag) {
- switch (tag) {
- case KM_TAG_INVALID:
- return "KM_TAG_INVALID";
- case KM_TAG_PURPOSE:
- return "KM_TAG_PURPOSE";
- case KM_TAG_ALGORITHM:
- return "KM_TAG_ALGORITHM";
- case KM_TAG_KEY_SIZE:
- return "KM_TAG_KEY_SIZE";
- case KM_TAG_BLOCK_MODE:
- return "KM_TAG_BLOCK_MODE";
- case KM_TAG_DIGEST:
- return "KM_TAG_DIGEST";
- case KM_TAG_PADDING:
- return "KM_TAG_PADDING";
- case KM_TAG_CALLER_NONCE:
- return "KM_TAG_CALLER_NONCE";
- case KM_TAG_MIN_MAC_LENGTH:
- return "KM_TAG_MIN_MAC_LENGTH";
- case KM_TAG_RSA_PUBLIC_EXPONENT:
- return "KM_TAG_RSA_PUBLIC_EXPONENT";
- case KM_TAG_BLOB_USAGE_REQUIREMENTS:
- return "KM_TAG_BLOB_USAGE_REQUIREMENTS";
- case KM_TAG_BOOTLOADER_ONLY:
- return "KM_TAG_BOOTLOADER_ONLY";
- case KM_TAG_ACTIVE_DATETIME:
- return "KM_TAG_ACTIVE_DATETIME";
- case KM_TAG_ORIGINATION_EXPIRE_DATETIME:
- return "KM_TAG_ORIGINATION_EXPIRE_DATETIME";
- case KM_TAG_USAGE_EXPIRE_DATETIME:
- return "KM_TAG_USAGE_EXPIRE_DATETIME";
- case KM_TAG_MIN_SECONDS_BETWEEN_OPS:
- return "KM_TAG_MIN_SECONDS_BETWEEN_OPS";
- case KM_TAG_MAX_USES_PER_BOOT:
- return "KM_TAG_MAX_USES_PER_BOOT";
- case KM_TAG_ALL_USERS:
- return "KM_TAG_ALL_USERS";
- case KM_TAG_USER_ID:
- return "KM_TAG_USER_ID";
- case KM_TAG_USER_SECURE_ID:
- return "KM_TAG_USER_SECURE_ID";
- case KM_TAG_NO_AUTH_REQUIRED:
- return "KM_TAG_NO_AUTH_REQUIRED";
- case KM_TAG_USER_AUTH_TYPE:
- return "KM_TAG_USER_AUTH_TYPE";
- case KM_TAG_AUTH_TIMEOUT:
- return "KM_TAG_AUTH_TIMEOUT";
- case KM_TAG_ALL_APPLICATIONS:
- return "KM_TAG_ALL_APPLICATIONS";
- case KM_TAG_APPLICATION_ID:
- return "KM_TAG_APPLICATION_ID";
- case KM_TAG_APPLICATION_DATA:
- return "KM_TAG_APPLICATION_DATA";
- case KM_TAG_CREATION_DATETIME:
- return "KM_TAG_CREATION_DATETIME";
- case KM_TAG_ORIGIN:
- return "KM_TAG_ORIGIN";
- case KM_TAG_ROLLBACK_RESISTANT:
- return "KM_TAG_ROLLBACK_RESISTANT";
- case KM_TAG_ROOT_OF_TRUST:
- return "KM_TAG_ROOT_OF_TRUST";
- case KM_TAG_ASSOCIATED_DATA:
- return "KM_TAG_ASSOCIATED_DATA";
- case KM_TAG_NONCE:
- return "KM_TAG_NONCE";
- case KM_TAG_AUTH_TOKEN:
- return "KM_TAG_AUTH_TOKEN";
- case KM_TAG_MAC_LENGTH:
- return "KM_TAG_MAC_LENGTH";
- case KM_TAG_KDF:
- return "KM_TAG_KDF";
- case KM_TAG_EC_CURVE:
- return "KM_TAG_EC_CURVE";
- case KM_TAG_ECIES_SINGLE_HASH_MODE:
- return "KM_TAG_ECIES_SINGLE_HASH_MODE";
- case KM_TAG_OS_VERSION:
- return "KM_TAG_OS_VERSION";
- case KM_TAG_OS_PATCHLEVEL:
- return "KM_TAG_OS_PATCHLEVEL";
- case KM_TAG_EXPORTABLE:
- return "KM_TAG_EXPORTABLE";
- case KM_TAG_UNIQUE_ID:
- return "KM_TAG_UNIQUE_ID";
- case KM_TAG_INCLUDE_UNIQUE_ID:
- return "KM_TAG_INCLUDE_UNIQUE_ID";
- case KM_TAG_RESET_SINCE_ID_ROTATION:
- return "KM_TAG_RESET_SINCE_ID_ROTATION";
- }
- return "<Unknown>";
-}
+#ifndef KEYMASTER_NAME_TAGS
+#erro 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", StringifyTag(iter->tag));
+ printf(" %s\n", keymaster::StringifyTag(iter->tag));
}
}