Add key export, RSA only.  (rileyspahn@google.com implemented).

Change-Id: I55c3497a1dc5360bfc8518a388b73776388a47e4
diff --git a/google_keymaster.cpp b/google_keymaster.cpp
index 6e9d5cf..df3373c 100644
--- a/google_keymaster.cpp
+++ b/google_keymaster.cpp
@@ -20,6 +20,7 @@
 #include <cstddef>
 
 #include <openssl/rand.h>
+#include <openssl/x509.h>
 
 #include <UniquePtr.h>
 
@@ -54,6 +55,16 @@
 };
 typedef UniquePtr<ae_ctx, AE_CTX_Delete> Unique_ae_ctx;
 
+struct EVP_PKEY_Delete {
+    void operator()(EVP_PKEY* p) { EVP_PKEY_free(p); }
+};
+typedef UniquePtr<EVP_PKEY, EVP_PKEY_Delete> Unique_EVP_PKEY;
+
+struct PKCS8_PRIV_KEY_INFO_Delete {
+    void operator()(PKCS8_PRIV_KEY_INFO* p) const { PKCS8_PRIV_KEY_INFO_free(p); }
+};
+typedef UniquePtr<PKCS8_PRIV_KEY_INFO, PKCS8_PRIV_KEY_INFO_Delete> Unique_PKCS8_PRIV_KEY_INFO;
+
 keymaster_algorithm_t supported_algorithms[] = {
     KM_ALGORITHM_RSA, KM_ALGORITHM_DSA, KM_ALGORITHM_ECDSA,
 };
@@ -292,6 +303,126 @@
     return KM_ERROR_OK;
 }
 
+bool GoogleKeymaster::is_supported_export_format(keymaster_key_format_t test_format) {
+    unsigned int index;
+    for (index = 0; index < array_length(supported_export_formats); index++) {
+        if (test_format == supported_export_formats[index]) {
+            return true;
+        }
+    }
+
+    return false;
+}
+
+bool GoogleKeymaster::is_supported_import_format(keymaster_key_format_t test_format) {
+    unsigned int index;
+    for (index = 0; index < array_length(supported_import_formats); index++) {
+        if (test_format == supported_import_formats[index]) {
+            return true;
+        }
+    }
+
+    return false;
+}
+
+void GoogleKeymaster::ExportKey(const ExportKeyRequest& request, ExportKeyResponse* response) {
+    if (response == NULL)
+        return;
+
+    keymaster_error_t blob_error;
+    UniquePtr<KeyBlob> to_export(
+        LoadKeyBlob(request.key_blob, request.additional_params, &response->error));
+    if (to_export.get() == NULL)
+        return;
+
+    Unique_EVP_PKEY pkey(EVP_PKEY_new());
+    if (pkey.get() == NULL) {
+        response->error = KM_ERROR_MEMORY_ALLOCATION_FAILED;
+        return;
+    }
+
+    EVP_PKEY* pkey_tmp = pkey.get();
+    const uint8_t* km_tmp = to_export->key_material();
+    if (d2i_PrivateKey(EVP_PKEY_RSA, &pkey_tmp, &km_tmp, to_export->key_material_length()) ==
+        NULL) {
+        response->error = KM_ERROR_INVALID_KEY_BLOB;
+        return;
+    }
+
+    int len = i2d_PUBKEY(pkey.get(), NULL);
+    if (len <= 0) {
+        response->error = KM_ERROR_UNKNOWN_ERROR;
+        return;
+    }
+
+    UniquePtr<uint8_t[]> out_key(new uint8_t[len]);
+    if (out_key.get() == NULL) {
+        response->error = KM_ERROR_MEMORY_ALLOCATION_FAILED;
+        return;
+    }
+
+    uint8_t* tmp = out_key.get();
+    if (i2d_PUBKEY(pkey.get(), &tmp) != len) {
+        fprintf(stderr, "i2d_pubkey(x, len) failed.\n");
+        response->error = KM_ERROR_INVALID_KEY_BLOB;
+
+        return;
+    }
+
+    response->key_data = out_key.release();
+    response->error = KM_ERROR_OK;
+}
+
+void GoogleKeymaster::ImportKey(const ImportKeyRequest& request, ImportKeyResponse* response) {
+
+    if (request.key_data == NULL || request.key_data_length <= 0) {
+        response->error = KM_ERROR_INVALID_KEY_BLOB;
+        return;
+    }
+
+    if (!is_supported_export_format(request.key_format)) {
+        response->error = KM_ERROR_UNSUPPORTED_KEY_FORMAT;
+        return;
+    }
+
+    const uint8_t* key_data = request.key_data;
+    Unique_PKCS8_PRIV_KEY_INFO pkcs8(
+        d2i_PKCS8_PRIV_KEY_INFO(NULL, &key_data, request.key_data_length));
+    if (pkcs8.get() == NULL) {
+        response->error = KM_ERROR_MEMORY_ALLOCATION_FAILED;
+        return;
+    }
+
+    Unique_EVP_PKEY pkey(EVP_PKCS82PKEY(pkcs8.get()));
+    if (pkey.get() == NULL) {
+        response->error = KM_ERROR_INVALID_KEY_BLOB;
+        return;
+    }
+
+    int len = i2d_PrivateKey(pkey.get(), NULL);
+    if (len <= 0) {
+        response->error = KM_ERROR_INVALID_KEY_BLOB;
+        return;
+    }
+
+    UniquePtr<uint8_t[]> der_encoded_key(new uint8_t[len]);
+    if (der_encoded_key.get() == NULL) {
+        response->error = KM_ERROR_MEMORY_ALLOCATION_FAILED;
+        return;
+    }
+
+    uint8_t* tmp_der = der_encoded_key.get();
+    if (i2d_PrivateKey(pkey.get(), &tmp_der) != len) {
+        response->error = KM_ERROR_INVALID_KEY_BLOB;
+        return;
+    }
+
+    void* key_material = der_encoded_key.release();
+    response->SetKeyMaterial(key_material, len);
+
+    response->error = KM_ERROR_OK;
+}
+
 bool GoogleKeymaster::GenerateRsa(const AuthorizationSet& key_auths, GenerateKeyResponse* response,
                                   AuthorizationSet* hidden_auths) {
     uint64_t public_exponent = RSA_DEFAULT_EXPONENT;