Merge changes from topic \'km_tag_allow_on_body\' am: a1433ee2f8
am: e30ca16ae0

* commit 'e30ca16ae0e41375201de9132866f5680a5d7baa':
  Add KM_TAG_ALLOW_WHILE_ON_BODY
  Add attestation support to keystore.
diff --git a/keystore/Android.mk b/keystore/Android.mk
index adc708e..baff509 100644
--- a/keystore/Android.mk
+++ b/keystore/Android.mk
@@ -77,7 +77,7 @@
 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 6e20f9d..d03a011 100644
--- a/keystore/IKeystoreService.cpp
+++ b/keystore/IKeystoreService.cpp
@@ -208,6 +208,69 @@
     }
 }
 
+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 @@
 }
 
 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;
 }
@@ -1262,6 +1311,34 @@
         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 7160b5a..64968e5 100644
--- a/keystore/include/keystore/IKeystoreService.h
+++ b/keystore/include/keystore/IKeystoreService.h
@@ -90,6 +90,16 @@
     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 @@
         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);
@@ -232,6 +243,9 @@
 
     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 b990407..e02ef8b 100644
--- a/keystore/key_store_service.cpp
+++ b/keystore/key_store_service.cpp
@@ -1095,6 +1095,40 @@
     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 4fe9012..12a342e 100644
--- a/keystore/key_store_service.h
+++ b/keystore/key_store_service.h
@@ -114,6 +114,9 @@
 
     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 3efc99a..c4dbf5d 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 @@
     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));
     }
 }