Implement keymaster 1.0 import_key method

Change-Id: I5bc24bc3177c6fc88141a42ed4d6a7a3d42e2c2f
diff --git a/keystore/keystore.cpp b/keystore/keystore.cpp
index 7300e16..456ebdd 100644
--- a/keystore/keystore.cpp
+++ b/keystore/keystore.cpp
@@ -2571,11 +2571,72 @@
         return rc ? rc : ::NO_ERROR;
     }
 
-    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*/) {
-        return KM_ERROR_UNIMPLEMENTED;
+    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) {
+        uid_t callingUid = IPCThreadState::self()->getCallingUid();
+        pid_t spid = IPCThreadState::self()->getCallingPid();
+        if (!has_permission(callingUid, P_INSERT, spid)) {
+            ALOGW("permission denied for %d: importKey", callingUid);
+            return ::PERMISSION_DENIED;
+        }
+
+        State state = mKeyStore->getState(callingUid);
+        if ((flags & KEYSTORE_FLAG_ENCRYPTED) && !isKeystoreUnlocked(state)) {
+            ALOGW("calling importKey in state: %d", state);
+            return state;
+        }
+
+        if (uid == -1) {
+            uid = callingUid;
+        } else if (!is_granted_to(callingUid, uid)) {
+            ALOGW("not granted to %d %d", callingUid, uid);
+            return ::PERMISSION_DENIED;
+        }
+
+        int rc = KM_ERROR_UNIMPLEMENTED;
+        bool isFallback = false;
+        keymaster_key_blob_t blob;
+        keymaster_key_characteristics_t *out = NULL;
+
+        const keymaster1_device_t* device = mKeyStore->getDevice();
+        const keymaster1_device_t* fallback = mKeyStore->getFallbackDevice();
+        if (device == NULL) {
+            return ::SYSTEM_ERROR;
+        }
+        if (device->common.module->module_api_version >= KEYMASTER_MODULE_API_VERSION_1_0 &&
+                device->import_key != NULL) {
+            rc = device->import_key(device, params.params.data(), params.params.size(),
+                                    format, keyData, keyLength, &blob, &out);
+        }
+        if (rc && fallback->import_key != NULL) {
+            isFallback = true;
+            rc = fallback->import_key(fallback, params.params.data(), params.params.size(),
+                                      format, keyData, keyLength, &blob, &out);
+        }
+        if (out) {
+            if (outCharacteristics) {
+                outCharacteristics->characteristics = *out;
+            } else {
+                keymaster_free_characteristics(out);
+            }
+            free(out);
+        }
+        if (rc) {
+            return rc;
+        }
+
+        String8 name8(name);
+        String8 filename(mKeyStore->getKeyNameForUidWithDir(name8, uid));
+
+        Blob keyBlob(blob.key_material, blob.key_material_size, NULL, 0, ::TYPE_KEYMASTER_10);
+        keyBlob.setFallback(isFallback);
+        keyBlob.setEncrypted(flags & KEYSTORE_FLAG_ENCRYPTED);
+
+        free((void*) blob.key_material);
+
+        return mKeyStore->put(filename.string(), &keyBlob, uid);
     }
 
     void exportKey(const String16& /*name*/, keymaster_key_format_t /*format*/,