diff options
author | Shawn Willden <swillden@google.com> | 2016-01-28 23:20:01 +0000 |
---|---|---|
committer | Gerrit Code Review <noreply-gerritcodereview@google.com> | 2016-01-28 23:20:01 +0000 |
commit | a1433ee2f85ae9d2db4e9eb996b6b23af1542247 (patch) | |
tree | fcf3d25ebd157f2c4b1ba6be2e81270a9a8a763f | |
parent | fd50293cd5f91936ea954b0556f3f434243adf27 (diff) | |
parent | d3fac68c4982a5a188c0b3648eea2f16c4791d21 (diff) | |
download | security-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.mk | 2 | ||||
-rw-r--r-- | keystore/IKeystoreService.cpp | 111 | ||||
-rw-r--r-- | keystore/include/keystore/IKeystoreService.h | 14 | ||||
-rw-r--r-- | keystore/key_store_service.cpp | 34 | ||||
-rw-r--r-- | keystore/key_store_service.h | 3 | ||||
-rw-r--r-- | keystore/keystore_cli_v2.cpp | 97 |
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)); } } |