summaryrefslogtreecommitdiff
path: root/asymmetric_key.cpp
diff options
context:
space:
mode:
authorShawn Willden <swillden@google.com>2014-12-23 11:22:21 -0700
committerShawn Willden <swillden@google.com>2015-02-18 15:32:45 -0700
commita278f6156b9e57e1de8ca380b14fef113ad10be8 (patch)
treef86b0d237424582ede1d61fdf229fa7c08a83f3d /asymmetric_key.cpp
parentc24c110db36b01b737f51c16ae479650635f6324 (diff)
downloadkeymaster-a278f6156b9e57e1de8ca380b14fef113ad10be8.tar.gz
Refactor key creation to use a registry of key factories.
Change-Id: I6ebab7b44e4a5dbea282397ab8aca437e71bdca0
Diffstat (limited to 'asymmetric_key.cpp')
-rw-r--r--asymmetric_key.cpp65
1 files changed, 64 insertions, 1 deletions
diff --git a/asymmetric_key.cpp b/asymmetric_key.cpp
index 064cd7e..65249fe 100644
--- a/asymmetric_key.cpp
+++ b/asymmetric_key.cpp
@@ -14,16 +14,79 @@
* limitations under the License.
*/
+#include "asymmetric_key.h"
+
#include <openssl/x509.h>
#include <hardware/keymaster_defs.h>
-#include "asymmetric_key.h"
+#include "ecdsa_key.h"
#include "openssl_utils.h"
+#include "rsa_key.h"
#include "unencrypted_key_blob.h"
namespace keymaster {
+struct PKCS8_PRIV_KEY_INFO_Delete {
+ void operator()(PKCS8_PRIV_KEY_INFO* p) const { PKCS8_PRIV_KEY_INFO_free(p); }
+};
+
+EVP_PKEY* AsymmetricKeyFactory::ExtractEvpKey(keymaster_key_format_t key_format,
+ keymaster_algorithm_t expected_algorithm,
+ const uint8_t* key_data, size_t key_data_length,
+ keymaster_error_t* error) {
+ *error = KM_ERROR_OK;
+
+ if (key_data == NULL || key_data_length <= 0) {
+ *error = KM_ERROR_INVALID_KEY_BLOB;
+ return NULL;
+ }
+
+ if (key_format != KM_KEY_FORMAT_PKCS8) {
+ *error = KM_ERROR_UNSUPPORTED_KEY_FORMAT;
+ return NULL;
+ }
+
+ UniquePtr<PKCS8_PRIV_KEY_INFO, PKCS8_PRIV_KEY_INFO_Delete> pkcs8(
+ d2i_PKCS8_PRIV_KEY_INFO(NULL, &key_data, key_data_length));
+ if (pkcs8.get() == NULL) {
+ *error = KM_ERROR_MEMORY_ALLOCATION_FAILED;
+ return NULL;
+ }
+
+ UniquePtr<EVP_PKEY, EVP_PKEY_Delete> pkey(EVP_PKCS82PKEY(pkcs8.get()));
+ if (pkey.get() == NULL || EVP_PKEY_type(pkey->type) != convert_to_evp(expected_algorithm)) {
+ *error = KM_ERROR_INVALID_KEY_BLOB;
+ return NULL;
+ }
+
+ return pkey.release();
+}
+
+static const keymaster_key_format_t supported_import_formats[] = {KM_KEY_FORMAT_PKCS8};
+const keymaster_key_format_t* AsymmetricKeyFactory::SupportedImportFormats(size_t* format_count) {
+ *format_count = array_length(supported_import_formats);
+ return supported_import_formats;
+}
+
+static const keymaster_key_format_t supported_export_formats[] = {KM_KEY_FORMAT_X509};
+const keymaster_key_format_t* AsymmetricKeyFactory::SupportedExportFormats(size_t* format_count) {
+ *format_count = array_length(supported_export_formats);
+ return supported_export_formats;
+}
+
+/* static */
+int AsymmetricKeyFactory::convert_to_evp(keymaster_algorithm_t algorithm) {
+ switch (algorithm) {
+ case KM_ALGORITHM_RSA:
+ return EVP_PKEY_RSA;
+ case KM_ALGORITHM_ECDSA:
+ return EVP_PKEY_EC;
+ default:
+ return -1;
+ };
+}
+
keymaster_error_t AsymmetricKey::LoadKey(const UnencryptedKeyBlob& blob) {
UniquePtr<EVP_PKEY, EVP_PKEY_Delete> evp_key(EVP_PKEY_new());
if (evp_key.get() == NULL)