Fix RSA and ECDSA key import in softkeymaster.

Bug: 20055613
Change-Id: Ie1998476659cb4c9e1311f0391cc3a6ecb9204ca
diff --git a/soft_keymaster_device.cpp b/soft_keymaster_device.cpp
index 3ddce33..b1e0161 100644
--- a/soft_keymaster_device.cpp
+++ b/soft_keymaster_device.cpp
@@ -27,6 +27,8 @@
 
 #include <type_traits>
 
+#include <openssl/x509.h>
+
 #include <hardware/keymaster1.h>
 #define LOG_TAG "SoftKeymasterDevice"
 #include <cutils/log.h>
@@ -228,6 +230,11 @@
 
     ImportKeyRequest request;
     StoreDefaultNewKeyParams(&request.key_description);
+    keymaster_algorithm_t algorithm;
+    keymaster_error_t err = GetPkcs8KeyAlgorithm(key, key_length, &algorithm);
+    if (err != KM_ERROR_OK)
+        return err;
+    request.key_description.push_back(TAG_ALGORITHM, algorithm);
     request.SetKeyMaterial(key, key_length);
     request.key_format = KM_KEY_FORMAT_PKCS8;
 
@@ -250,6 +257,50 @@
     return KM_ERROR_OK;
 }
 
+struct EVP_PKEY_Delete {
+    void operator()(EVP_PKEY* p) const { EVP_PKEY_free(p); }
+};
+
+struct PKCS8_PRIV_KEY_INFO_Delete {
+    void operator()(PKCS8_PRIV_KEY_INFO* p) const { PKCS8_PRIV_KEY_INFO_free(p); }
+};
+
+/* static */
+keymaster_error_t SoftKeymasterDevice::GetPkcs8KeyAlgorithm(const uint8_t* key, size_t key_length,
+                                                            keymaster_algorithm_t* algorithm) {
+    if (key == NULL) {
+        LOG_E("No key specified for import", 0);
+        return KM_ERROR_UNEXPECTED_NULL_POINTER;
+    }
+
+    UniquePtr<PKCS8_PRIV_KEY_INFO, PKCS8_PRIV_KEY_INFO_Delete> pkcs8(
+        d2i_PKCS8_PRIV_KEY_INFO(NULL, &key, key_length));
+    if (pkcs8.get() == NULL) {
+        LOG_E("Could not parse PKCS8 key blob", 0);
+        return KM_ERROR_INVALID_KEY_BLOB;
+    }
+
+    UniquePtr<EVP_PKEY, EVP_PKEY_Delete> pkey(EVP_PKCS82PKEY(pkcs8.get()));
+    if (pkey.get() == NULL) {
+        LOG_E("Could not extract key from PKCS8 key blob", 0);
+        return KM_ERROR_INVALID_KEY_BLOB;
+    }
+
+    switch (EVP_PKEY_type(pkey->type)) {
+    case EVP_PKEY_RSA:
+        *algorithm = KM_ALGORITHM_RSA;
+        break;
+    case EVP_PKEY_EC:
+        *algorithm = KM_ALGORITHM_ECDSA;
+        break;
+    default:
+        LOG_E("Unsupported algorithm %d", EVP_PKEY_type(pkey->type));
+        return KM_ERROR_UNSUPPORTED_ALGORITHM;
+    }
+
+    return KM_ERROR_OK;
+}
+
 /* static */
 int SoftKeymasterDevice::get_keypair_public(const struct keymaster1_device* dev,
                                             const uint8_t* key_blob, const size_t key_blob_length,