Wrap incomplete keymaster1 implementations with sw keymaster.

SoftKeymasteDevice can provide software digesting and padding for
keymaster1 implementations that don't provide all of the required
digests.  This CL modifies keymaster to check for such keymaster1
implementations and add a SoftKeymasterDevice wrapper.

The SoftKeymasterDevice work necessary to make this function would have
required adding an implementation of the keymaster0 API import_keypair
in terms of keymaster1 API calls (import_key).  Rather than do that, I
instead implemented the relevant keystore function directly on the
keymaster1 API.  This approach is cleaner than adding the same code into
the translation layer, and allows removal of the last vestiges of
keymaster0 API usage from keystore.

Bug: 22529223
Change-Id: Ie4c7bba7943a549f35df3086dccea001edb5bb2b
diff --git a/keystore/keystore.cpp b/keystore/keystore.cpp
index 8a43f02..413dd5d 100644
--- a/keystore/keystore.cpp
+++ b/keystore/keystore.cpp
@@ -80,6 +80,7 @@
 #define VALUE_SIZE      32768
 #define PASSWORD_SIZE   VALUE_SIZE
 
+using keymaster::SoftKeymasterDevice;
 
 struct BIGNUM_Delete {
     void operator()(BIGNUM* p) const {
@@ -109,47 +110,121 @@
 };
 typedef UniquePtr<PKCS8_PRIV_KEY_INFO, PKCS8_PRIV_KEY_INFO_Delete> Unique_PKCS8_PRIV_KEY_INFO;
 
-static int keymaster_device_initialize(keymaster1_device_t** dev) {
-    int rc;
+static int keymaster0_device_initialize(const hw_module_t* mod, keymaster1_device_t** dev) {
+    assert(mod->module_api_version < KEYMASTER_MODULE_API_VERSION_1_0);
+    ALOGI("Found keymaster0 module %s, version %x", mod->name, mod->module_api_version);
 
-    const hw_module_t* mod;
-    keymaster::SoftKeymasterDevice* softkeymaster = NULL;
-    rc = hw_get_module_by_class(KEYSTORE_HARDWARE_MODULE_ID, NULL, &mod);
+    UniquePtr<SoftKeymasterDevice> soft_keymaster(new SoftKeymasterDevice);
+    keymaster0_device_t* km0_device = NULL;
+    keymaster_error_t error = KM_ERROR_OK;
+
+    int rc = keymaster0_open(mod, &km0_device);
     if (rc) {
-        ALOGE("could not find any keystore module");
-        goto out;
+        ALOGE("Error opening keystore keymaster0 device.");
+        goto err;
     }
 
-    rc = mod->methods->open(mod, KEYSTORE_KEYMASTER, reinterpret_cast<struct hw_device_t**>(dev));
-    if (rc) {
-        ALOGE("could not open keymaster device in %s (%s)",
-            KEYSTORE_HARDWARE_MODULE_ID, strerror(-rc));
-        goto out;
-    }
-
-    // Wrap older hardware modules with a softkeymaster adapter.
-    if ((*dev)->common.module->module_api_version >= KEYMASTER_MODULE_API_VERSION_1_0) {
+    if (km0_device->flags & KEYMASTER_SOFTWARE_ONLY) {
+        ALOGI("Keymaster0 module is software-only.  Using SoftKeymasterDevice instead.");
+        km0_device->common.close(&km0_device->common);
+        km0_device = NULL;
+        // SoftKeymasterDevice will be deleted by keymaster_device_release()
+        *dev = soft_keymaster.release()->keymaster_device();
         return 0;
     }
-    softkeymaster =
-            new keymaster::SoftKeymasterDevice(reinterpret_cast<keymaster0_device_t*>(*dev));
-    *dev = softkeymaster->keymaster_device();
+
+    ALOGE("Wrapping keymaster0 module %s with SoftKeymasterDevice", mod->name);
+    error = soft_keymaster->SetHardwareDevice(km0_device);
+    km0_device = NULL;  // SoftKeymasterDevice has taken ownership.
+    if (error != KM_ERROR_OK) {
+        ALOGE("Got error %d from SetHardwareDevice", error);
+        rc = error;
+        goto err;
+    }
+
+    // SoftKeymasterDevice will be deleted by keymaster_device_release()
+    *dev = soft_keymaster.release()->keymaster_device();
     return 0;
 
-out:
+err:
+    if (km0_device)
+        km0_device->common.close(&km0_device->common);
     *dev = NULL;
     return rc;
 }
 
+static int keymaster1_device_initialize(const hw_module_t* mod, keymaster1_device_t** dev) {
+    assert(mod->module_api_version >= KEYMASTER_MODULE_API_VERSION_1_0);
+    ALOGI("Found keymaster1 module %s, version %x", mod->name, mod->module_api_version);
+
+    UniquePtr<SoftKeymasterDevice> soft_keymaster(new SoftKeymasterDevice);
+    keymaster1_device_t* km1_device = NULL;
+    keymaster_error_t error = KM_ERROR_OK;
+
+    int rc = keymaster1_open(mod, &km1_device);
+    if (rc) {
+        ALOGE("Error %d opening keystore keymaster1 device", rc);
+        goto err;
+    }
+
+    error = soft_keymaster->SetHardwareDevice(km1_device);
+    km1_device = NULL;  // SoftKeymasterDevice has taken ownership.
+    if (error != KM_ERROR_OK) {
+        ALOGE("Got error %d from SetHardwareDevice", error);
+        rc = error;
+        goto err;
+    }
+
+    if (!soft_keymaster->Keymaster1DeviceIsGood()) {
+        ALOGI("Keymaster1 module is incomplete, using SoftKeymasterDevice wrapper");
+        // SoftKeymasterDevice will be deleted by keymaster_device_release()
+        *dev = soft_keymaster.release()->keymaster_device();
+        return 0;
+    } else {
+        ALOGI("Keymaster1 module is good, destroying wrapper and re-opening");
+        soft_keymaster.reset(NULL);
+        rc = keymaster1_open(mod, &km1_device);
+        if (rc) {
+            ALOGE("Error %d re-opening keystore keymaster1 device.", rc);
+            goto err;
+        }
+        *dev = km1_device;
+        return 0;
+    }
+
+err:
+    if (km1_device)
+        km1_device->common.close(&km1_device->common);
+    *dev = NULL;
+    return rc;
+
+}
+
+static int keymaster_device_initialize(keymaster1_device_t** dev) {
+    const hw_module_t* mod;
+
+    int rc = hw_get_module_by_class(KEYSTORE_HARDWARE_MODULE_ID, NULL, &mod);
+    if (rc) {
+        ALOGI("Could not find any keystore module, using software-only implementation.");
+        // SoftKeymasterDevice will be deleted by keymaster_device_release()
+        *dev = (new SoftKeymasterDevice)->keymaster_device();
+        return 0;
+    }
+
+    if (mod->module_api_version < KEYMASTER_MODULE_API_VERSION_1_0) {
+        return keymaster0_device_initialize(mod, dev);
+    } else {
+        return keymaster1_device_initialize(mod, dev);
+    }
+}
+
 // softkeymaster_logger appears not to be used in keystore, but it installs itself as the
 // logger used by SoftKeymasterDevice.
 static keymaster::SoftKeymasterLogger softkeymaster_logger;
 
 static int fallback_keymaster_device_initialize(keymaster1_device_t** dev) {
-    keymaster::SoftKeymasterDevice* softkeymaster =
-            new keymaster::SoftKeymasterDevice();
-    *dev = softkeymaster->keymaster_device();
-    // softkeymaster will be freed by *dev->close_device; don't delete here.
+    *dev = (new SoftKeymasterDevice)->keymaster_device();
+    // SoftKeymasterDevice will be deleted by keymaster_device_release()
     return 0;
 }
 
@@ -157,6 +232,34 @@
     dev->common.close(&dev->common);
 }
 
+static void add_legacy_key_authorizations(int keyType, std::vector<keymaster_key_param_t>* params) {
+    params->push_back(keymaster_param_enum(KM_TAG_PURPOSE, KM_PURPOSE_SIGN));
+    params->push_back(keymaster_param_enum(KM_TAG_PURPOSE, KM_PURPOSE_VERIFY));
+    params->push_back(keymaster_param_enum(KM_TAG_PURPOSE, KM_PURPOSE_ENCRYPT));
+    params->push_back(keymaster_param_enum(KM_TAG_PURPOSE, KM_PURPOSE_DECRYPT));
+    params->push_back(keymaster_param_enum(KM_TAG_PADDING, KM_PAD_NONE));
+    if (keyType == EVP_PKEY_RSA) {
+        params->push_back(keymaster_param_enum(KM_TAG_PADDING, KM_PAD_RSA_PKCS1_1_5_SIGN));
+        params->push_back(keymaster_param_enum(KM_TAG_PADDING, KM_PAD_RSA_PKCS1_1_5_ENCRYPT));
+        params->push_back(keymaster_param_enum(KM_TAG_PADDING, KM_PAD_RSA_PSS));
+        params->push_back(keymaster_param_enum(KM_TAG_PADDING, KM_PAD_RSA_OAEP));
+    }
+    params->push_back(keymaster_param_enum(KM_TAG_DIGEST, KM_DIGEST_NONE));
+    params->push_back(keymaster_param_enum(KM_TAG_DIGEST, KM_DIGEST_MD5));
+    params->push_back(keymaster_param_enum(KM_TAG_DIGEST, KM_DIGEST_SHA1));
+    params->push_back(keymaster_param_enum(KM_TAG_DIGEST, KM_DIGEST_SHA_2_224));
+    params->push_back(keymaster_param_enum(KM_TAG_DIGEST, KM_DIGEST_SHA_2_256));
+    params->push_back(keymaster_param_enum(KM_TAG_DIGEST, KM_DIGEST_SHA_2_384));
+    params->push_back(keymaster_param_enum(KM_TAG_DIGEST, KM_DIGEST_SHA_2_512));
+    params->push_back(keymaster_param_bool(KM_TAG_ALL_USERS));
+    params->push_back(keymaster_param_bool(KM_TAG_NO_AUTH_REQUIRED));
+    params->push_back(keymaster_param_date(KM_TAG_ORIGINATION_EXPIRE_DATETIME, LLONG_MAX));
+    params->push_back(keymaster_param_date(KM_TAG_USAGE_EXPIRE_DATETIME, LLONG_MAX));
+    params->push_back(keymaster_param_date(KM_TAG_ACTIVE_DATETIME, 0));
+    uint64_t now = keymaster::java_time(time(NULL));
+    params->push_back(keymaster_param_date(KM_TAG_CREATION_DATETIME, now));
+}
+
 /***************
  * PERMISSIONS *
  ***************/
@@ -1229,9 +1332,11 @@
         }
 
         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())) {
+            // A device doesn't have to implement delete_key.
+            if (mDevice->delete_key != NULL && !keyBlob.isFallback()) {
+                keymaster_key_blob_t blob = {keyBlob.getValue(),
+                                             static_cast<size_t>(keyBlob.getLength())};
+                if (mDevice->delete_key(mDevice, &blob)) {
                     rc = ::SYSTEM_ERROR;
                 }
             }
@@ -1324,35 +1429,58 @@
 
     ResponseCode importKey(const uint8_t* key, size_t keyLen, const char* filename, uid_t userId,
             int32_t flags) {
-        uint8_t* data;
-        size_t dataLength;
-        int rc;
-
-        if (mDevice->import_keypair == NULL) {
-            ALOGE("Keymaster doesn't support import!");
-            return SYSTEM_ERROR;
+        Unique_PKCS8_PRIV_KEY_INFO pkcs8(d2i_PKCS8_PRIV_KEY_INFO(NULL, &key, keyLen));
+        if (!pkcs8.get()) {
+            return ::SYSTEM_ERROR;
+        }
+        Unique_EVP_PKEY pkey(EVP_PKCS82PKEY(pkcs8.get()));
+        if (!pkey.get()) {
+            return ::SYSTEM_ERROR;
+        }
+        int type = EVP_PKEY_type(pkey->type);
+        android::KeymasterArguments params;
+        add_legacy_key_authorizations(type, &params.params);
+        switch (type) {
+            case EVP_PKEY_RSA:
+                params.params.push_back(keymaster_param_enum(KM_TAG_ALGORITHM, KM_ALGORITHM_RSA));
+                break;
+            case EVP_PKEY_EC:
+                params.params.push_back(keymaster_param_enum(KM_TAG_ALGORITHM,
+                                                             KM_ALGORITHM_EC));
+                break;
+            default:
+                ALOGW("Unsupported key type %d", type);
+                return ::SYSTEM_ERROR;
         }
 
+        std::vector<keymaster_key_param_t> opParams(params.params);
+        const keymaster_key_param_set_t inParams = {opParams.data(), opParams.size()};
+        keymaster_blob_t input = {key, keyLen};
+        keymaster_key_blob_t blob = {nullptr, 0};
         bool isFallback = false;
-        rc = mDevice->import_keypair(mDevice, key, keyLen, &data, &dataLength);
-        if (rc) {
+        keymaster_error_t error = mDevice->import_key(mDevice, &inParams, KM_KEY_FORMAT_PKCS8,
+                                                      &input, &blob, NULL /* characteristics */);
+        if (error != KM_ERROR_OK){
+            ALOGE("Keymaster error %d importing key pair, falling back", error);
+
             /*
-             * Maybe the device doesn't support this type of key. Try to use the
-             * software fallback keymaster implementation. This is a little bit
-             * lazier than checking the PKCS#8 key type, but the software
-             * implementation will do that anyway.
+             * There should be no way to get here.  Fallback shouldn't ever really happen
+             * because the main device may be many (SW, KM0/SW hybrid, KM1/SW hybrid), but it must
+             * provide full support of the API.  In any case, we'll do the fallback just for
+             * consistency... and I suppose to cover for broken HW implementations.
              */
-            rc = mFallbackDevice->import_keypair(mFallbackDevice, key, keyLen, &data, &dataLength);
+            error = mFallbackDevice->import_key(mFallbackDevice, &inParams, KM_KEY_FORMAT_PKCS8,
+                                                &input, &blob, NULL /* characteristics */);
             isFallback = true;
 
-            if (rc) {
-                ALOGE("Error while importing keypair: %d", rc);
+            if (error) {
+                ALOGE("Keymaster error while importing key pair with fallback: %d", error);
                 return SYSTEM_ERROR;
             }
         }
 
-        Blob keyBlob(data, dataLength, NULL, 0, TYPE_KEY_PAIR);
-        free(data);
+        Blob keyBlob(blob.key_material, blob.key_material_size, NULL, 0, TYPE_KEYMASTER_10);
+        free(const_cast<uint8_t*>(blob.key_material));
 
         keyBlob.setEncrypted(flags & KEYSTORE_FLAG_ENCRYPTED);
         keyBlob.setFallback(isFallback);
@@ -1920,7 +2048,7 @@
         }
 
         KeymasterArguments params;
-        addLegacyKeyAuthorizations(params.params, keyType);
+        add_legacy_key_authorizations(keyType, &params.params);
 
         switch (keyType) {
             case EVP_PKEY_EC: {
@@ -1999,7 +2127,7 @@
         }
         int type = EVP_PKEY_type(pkey->type);
         KeymasterArguments params;
-        addLegacyKeyAuthorizations(params.params, type);
+        add_legacy_key_authorizations(type, &params.params);
         switch (type) {
             case EVP_PKEY_RSA:
                 params.params.push_back(keymaster_param_enum(KM_TAG_ALGORITHM, KM_ALGORITHM_RSA));
@@ -2272,6 +2400,7 @@
         // If the HW device didn't support generate_key or generate_key failed
         // fall back to the software implementation.
         if (rc && fallback->generate_key != NULL) {
+            ALOGW("Primary keymaster device failed to generate key, falling back to SW.");
             isFallback = true;
             if (!entropy) {
                 rc = KM_ERROR_OK;
@@ -2375,6 +2504,7 @@
             rc = device->import_key(device, &inParams, format,&input, &blob, &out);
         }
         if (rc && fallback->import_key != NULL) {
+            ALOGW("Primary keymaster device failed to import key, falling back to SW.");
             isFallback = true;
             rc = fallback->import_key(fallback, &inParams, format, &input, &blob, &out);
         }
@@ -2998,34 +3128,6 @@
         return ::SYSTEM_ERROR;
     }
 
-    void addLegacyKeyAuthorizations(std::vector<keymaster_key_param_t>& params, int keyType) {
-        params.push_back(keymaster_param_enum(KM_TAG_PURPOSE, KM_PURPOSE_SIGN));
-        params.push_back(keymaster_param_enum(KM_TAG_PURPOSE, KM_PURPOSE_VERIFY));
-        params.push_back(keymaster_param_enum(KM_TAG_PURPOSE, KM_PURPOSE_ENCRYPT));
-        params.push_back(keymaster_param_enum(KM_TAG_PURPOSE, KM_PURPOSE_DECRYPT));
-        params.push_back(keymaster_param_enum(KM_TAG_PADDING, KM_PAD_NONE));
-        if (keyType == EVP_PKEY_RSA) {
-            params.push_back(keymaster_param_enum(KM_TAG_PADDING, KM_PAD_RSA_PKCS1_1_5_SIGN));
-            params.push_back(keymaster_param_enum(KM_TAG_PADDING, KM_PAD_RSA_PKCS1_1_5_ENCRYPT));
-            params.push_back(keymaster_param_enum(KM_TAG_PADDING, KM_PAD_RSA_PSS));
-            params.push_back(keymaster_param_enum(KM_TAG_PADDING, KM_PAD_RSA_OAEP));
-        }
-        params.push_back(keymaster_param_enum(KM_TAG_DIGEST, KM_DIGEST_NONE));
-        params.push_back(keymaster_param_enum(KM_TAG_DIGEST, KM_DIGEST_MD5));
-        params.push_back(keymaster_param_enum(KM_TAG_DIGEST, KM_DIGEST_SHA1));
-        params.push_back(keymaster_param_enum(KM_TAG_DIGEST, KM_DIGEST_SHA_2_224));
-        params.push_back(keymaster_param_enum(KM_TAG_DIGEST, KM_DIGEST_SHA_2_256));
-        params.push_back(keymaster_param_enum(KM_TAG_DIGEST, KM_DIGEST_SHA_2_384));
-        params.push_back(keymaster_param_enum(KM_TAG_DIGEST, KM_DIGEST_SHA_2_512));
-        params.push_back(keymaster_param_bool(KM_TAG_ALL_USERS));
-        params.push_back(keymaster_param_bool(KM_TAG_NO_AUTH_REQUIRED));
-        params.push_back(keymaster_param_date(KM_TAG_ORIGINATION_EXPIRE_DATETIME, LLONG_MAX));
-        params.push_back(keymaster_param_date(KM_TAG_USAGE_EXPIRE_DATETIME, LLONG_MAX));
-        params.push_back(keymaster_param_date(KM_TAG_ACTIVE_DATETIME, 0));
-        uint64_t now = keymaster::java_time(time(NULL));
-        params.push_back(keymaster_param_date(KM_TAG_CREATION_DATETIME, now));
-    }
-
     keymaster_key_param_t* getKeyAlgorithm(keymaster_key_characteristics_t* characteristics) {
         for (size_t i = 0; i < characteristics->hw_enforced.length; i++) {
             if (characteristics->hw_enforced.params[i].tag == KM_TAG_ALGORITHM) {