diff options
author | Shawn Willden <swillden@google.com> | 2014-12-23 11:22:21 -0700 |
---|---|---|
committer | Shawn Willden <swillden@google.com> | 2015-02-18 15:32:45 -0700 |
commit | a278f6156b9e57e1de8ca380b14fef113ad10be8 (patch) | |
tree | f86b0d237424582ede1d61fdf229fa7c08a83f3d /asymmetric_key.cpp | |
parent | c24c110db36b01b737f51c16ae479650635f6324 (diff) | |
download | keymaster-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.cpp | 65 |
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) |