diff options
Diffstat (limited to 'src')
5 files changed, 168 insertions, 155 deletions
diff --git a/src/libstrongswan/plugins/openssl/openssl_ec_private_key.c b/src/libstrongswan/plugins/openssl/openssl_ec_private_key.c index 22bbf6dc7..d187c06ed 100644 --- a/src/libstrongswan/plugins/openssl/openssl_ec_private_key.c +++ b/src/libstrongswan/plugins/openssl/openssl_ec_private_key.c @@ -49,6 +49,11 @@ struct private_openssl_ec_private_key_t { EC_KEY *ec; /** + * TRUE if the key is from an OpenSSL ENGINE and might not be readable + */ + bool engine; + + /** * reference count */ refcount_t ref; @@ -226,6 +231,11 @@ METHOD(private_key_t, get_encoding, bool, { u_char *p; + if (this->engine) + { + return FALSE; + } + switch (type) { case PRIVKEY_ASN1_DER: @@ -307,7 +317,7 @@ static private_openssl_ec_private_key_t *create_empty(void) /* * See header. */ -private_key_t *openssl_ec_private_key_create(EVP_PKEY *key) +private_key_t *openssl_ec_private_key_create(EVP_PKEY *key, bool engine) { private_openssl_ec_private_key_t *this; EC_KEY *ec; @@ -320,6 +330,7 @@ private_key_t *openssl_ec_private_key_create(EVP_PKEY *key) } this = create_empty(); this->ec = ec; + this->engine = engine; return &this->public.key; } diff --git a/src/libstrongswan/plugins/openssl/openssl_ec_private_key.h b/src/libstrongswan/plugins/openssl/openssl_ec_private_key.h index 84314f671..56c59cfc8 100644 --- a/src/libstrongswan/plugins/openssl/openssl_ec_private_key.h +++ b/src/libstrongswan/plugins/openssl/openssl_ec_private_key.h @@ -67,8 +67,9 @@ openssl_ec_private_key_t *openssl_ec_private_key_load(key_type_t type, * Wrap an EVP_PKEY object of type EVP_PKEY_EC * * @param key EVP_PKEY_EC key object (adopted) + * @param engine whether the key was loaded via an engine * @return loaded key, NULL on failure */ -private_key_t *openssl_ec_private_key_create(EVP_PKEY *key); +private_key_t *openssl_ec_private_key_create(EVP_PKEY *key, bool engine); #endif /** OPENSSL_EC_PRIVATE_KEY_H_ @}*/ diff --git a/src/libstrongswan/plugins/openssl/openssl_plugin.c b/src/libstrongswan/plugins/openssl/openssl_plugin.c index ab73d718f..2f05b2b3d 100644 --- a/src/libstrongswan/plugins/openssl/openssl_plugin.c +++ b/src/libstrongswan/plugins/openssl/openssl_plugin.c @@ -301,11 +301,11 @@ static private_key_t *openssl_private_key_load(key_type_t type, va_list args) { #ifndef OPENSSL_NO_RSA case EVP_PKEY_RSA: - return openssl_rsa_private_key_create(key); + return openssl_rsa_private_key_create(key, FALSE); #endif #ifndef OPENSSL_NO_ECDSA case EVP_PKEY_EC: - return openssl_ec_private_key_create(key); + return openssl_ec_private_key_create(key, FALSE); #endif default: EVP_PKEY_free(key); @@ -316,6 +316,152 @@ static private_key_t *openssl_private_key_load(key_type_t type, va_list args) return NULL; } +#ifndef OPENSSL_NO_ENGINE +/** + * Login to engine with a PIN specified for a keyid + */ +static bool login(ENGINE *engine, chunk_t keyid) +{ + enumerator_t *enumerator; + shared_key_t *shared; + identification_t *id; + chunk_t key; + char pin[64]; + bool found = FALSE, success = FALSE; + + id = identification_create_from_encoding(ID_KEY_ID, keyid); + enumerator = lib->credmgr->create_shared_enumerator(lib->credmgr, + SHARED_PIN, id, NULL); + while (enumerator->enumerate(enumerator, &shared, NULL, NULL)) + { + found = TRUE; + key = shared->get_key(shared); + if (snprintf(pin, sizeof(pin), + "%.*s", (int)key.len, key.ptr) >= sizeof(pin)) + { + continue; + } + if (ENGINE_ctrl_cmd_string(engine, "PIN", pin, 0)) + { + success = TRUE; + break; + } + else + { + DBG1(DBG_CFG, "setting PIN on engine failed"); + } + } + enumerator->destroy(enumerator); + id->destroy(id); + if (!found) + { + DBG1(DBG_CFG, "no PIN found for %#B", &keyid); + } + return success; +} +#endif /* OPENSSL_NO_ENGINE */ + +/** + * Load private key via engine + */ +static private_key_t *openssl_private_key_connect(key_type_t type, + va_list args) +{ +#ifndef OPENSSL_NO_ENGINE + char *engine_id = NULL; + char keyname[BUF_LEN]; + chunk_t keyid = chunk_empty;; + EVP_PKEY *key; + ENGINE *engine; + int slot = -1; + + while (TRUE) + { + switch (va_arg(args, builder_part_t)) + { + case BUILD_PKCS11_KEYID: + keyid = va_arg(args, chunk_t); + continue; + case BUILD_PKCS11_SLOT: + slot = va_arg(args, int); + continue; + case BUILD_PKCS11_MODULE: + engine_id = va_arg(args, char*); + continue; + case BUILD_END: + break; + default: + return NULL; + } + break; + } + if (!keyid.len || keyid.len > 40) + { + return NULL; + } + + memset(keyname, 0, sizeof(keyname)); + if (slot != -1) + { + snprintf(keyname, sizeof(keyname), "%d:", slot); + } + if (sizeof(keyname) - strlen(keyname) <= keyid.len * 4 / 3 + 1) + { + return NULL; + } + chunk_to_hex(keyid, keyname + strlen(keyname), FALSE); + + if (!engine_id) + { + engine_id = lib->settings->get_str(lib->settings, + "%s.plugins.openssl.engine_id", "pkcs11", lib->ns); + } + engine = ENGINE_by_id(engine_id); + if (!engine) + { + DBG2(DBG_LIB, "engine '%s' is not available", engine_id); + return NULL; + } + if (!ENGINE_init(engine)) + { + DBG1(DBG_LIB, "failed to initialize engine '%s'", engine_id); + ENGINE_free(engine); + return NULL; + } + if (!login(engine, keyid)) + { + DBG1(DBG_LIB, "login to engine '%s' failed", engine_id); + ENGINE_free(engine); + return NULL; + } + key = ENGINE_load_private_key(engine, keyname, NULL, NULL); + if (!key) + { + DBG1(DBG_LIB, "failed to load private key with ID '%s' from " + "engine '%s'", keyname, engine_id); + ENGINE_free(engine); + return NULL; + } + ENGINE_free(engine); + + switch (EVP_PKEY_base_id(key)) + { +#ifndef OPENSSL_NO_RSA + case EVP_PKEY_RSA: + return openssl_rsa_private_key_create(key, TRUE); +#endif +#ifndef OPENSSL_NO_ECDSA + case EVP_PKEY_EC: + return openssl_ec_private_key_create(key, TRUE); +#endif + default: + EVP_PKEY_free(key); + break; + } +#endif /* OPENSSL_NO_ENGINE */ + return NULL; +} + METHOD(plugin_t, get_name, char*, private_openssl_plugin_t *this) { @@ -469,8 +615,6 @@ METHOD(plugin_t, get_features, int, /* RSA private/public key loading */ PLUGIN_REGISTER(PRIVKEY, openssl_rsa_private_key_load, TRUE), PLUGIN_PROVIDE(PRIVKEY, KEY_RSA), - PLUGIN_REGISTER(PRIVKEY, openssl_rsa_private_key_connect, FALSE), - PLUGIN_PROVIDE(PRIVKEY, KEY_ANY), PLUGIN_REGISTER(PRIVKEY_GEN, openssl_rsa_private_key_gen, FALSE), PLUGIN_PROVIDE(PRIVKEY_GEN, KEY_RSA), PLUGIN_REGISTER(PUBKEY, openssl_rsa_public_key_load, TRUE), @@ -554,6 +698,8 @@ METHOD(plugin_t, get_features, int, /* generic key loader */ PLUGIN_REGISTER(PRIVKEY, openssl_private_key_load, TRUE), PLUGIN_PROVIDE(PRIVKEY, KEY_ANY), + PLUGIN_REGISTER(PRIVKEY, openssl_private_key_connect, FALSE), + PLUGIN_PROVIDE(PRIVKEY, KEY_ANY), PLUGIN_REGISTER(RNG, openssl_rng_create), PLUGIN_PROVIDE(RNG, RNG_STRONG), PLUGIN_PROVIDE(RNG, RNG_WEAK), diff --git a/src/libstrongswan/plugins/openssl/openssl_rsa_private_key.c b/src/libstrongswan/plugins/openssl/openssl_rsa_private_key.c index 54ecf2542..fd624e6a3 100644 --- a/src/libstrongswan/plugins/openssl/openssl_rsa_private_key.c +++ b/src/libstrongswan/plugins/openssl/openssl_rsa_private_key.c @@ -27,9 +27,6 @@ #include <openssl/bn.h> #include <openssl/evp.h> #include <openssl/rsa.h> -#ifndef OPENSSL_NO_ENGINE -#include <openssl/engine.h> -#endif /* OPENSSL_NO_ENGINE */ /** * Public exponent to use for key generation. @@ -386,7 +383,7 @@ error: /* * See header */ -private_key_t *openssl_rsa_private_key_create(EVP_PKEY *key) +private_key_t *openssl_rsa_private_key_create(EVP_PKEY *key, bool engine) { private_openssl_rsa_private_key_t *this; RSA *rsa; @@ -399,6 +396,7 @@ private_key_t *openssl_rsa_private_key_create(EVP_PKEY *key) } this = create_empty(); this->rsa = rsa; + this->engine = engine; return &this->public.key; } @@ -502,148 +500,4 @@ openssl_rsa_private_key_t *openssl_rsa_private_key_load(key_type_t type, return NULL; } -#ifndef OPENSSL_NO_ENGINE -/** - * Login to engine with a PIN specified for a keyid - */ -static bool login(ENGINE *engine, chunk_t keyid) -{ - enumerator_t *enumerator; - shared_key_t *shared; - identification_t *id; - chunk_t key; - char pin[64]; - bool found = FALSE, success = FALSE; - - id = identification_create_from_encoding(ID_KEY_ID, keyid); - enumerator = lib->credmgr->create_shared_enumerator(lib->credmgr, - SHARED_PIN, id, NULL); - while (enumerator->enumerate(enumerator, &shared, NULL, NULL)) - { - found = TRUE; - key = shared->get_key(shared); - if (snprintf(pin, sizeof(pin), - "%.*s", (int)key.len, key.ptr) >= sizeof(pin)) - { - continue; - } - if (ENGINE_ctrl_cmd_string(engine, "PIN", pin, 0)) - { - success = TRUE; - break; - } - else - { - DBG1(DBG_CFG, "setting PIN on engine failed"); - } - } - enumerator->destroy(enumerator); - id->destroy(id); - if (!found) - { - DBG1(DBG_CFG, "no PIN found for %#B", &keyid); - } - return success; -} -#endif /* OPENSSL_NO_ENGINE */ - -/* - * See header. - */ -openssl_rsa_private_key_t *openssl_rsa_private_key_connect(key_type_t type, - va_list args) -{ -#ifndef OPENSSL_NO_ENGINE - private_openssl_rsa_private_key_t *this; - char *engine_id = NULL; - char keyname[64]; - chunk_t keyid = chunk_empty;; - EVP_PKEY *key; - ENGINE *engine; - int slot = -1; - - while (TRUE) - { - switch (va_arg(args, builder_part_t)) - { - case BUILD_PKCS11_KEYID: - keyid = va_arg(args, chunk_t); - continue; - case BUILD_PKCS11_SLOT: - slot = va_arg(args, int); - continue; - case BUILD_PKCS11_MODULE: - engine_id = va_arg(args, char*); - continue; - case BUILD_END: - break; - default: - return NULL; - } - break; - } - if (!keyid.len || keyid.len > 40) - { - return NULL; - } - - memset(keyname, 0, sizeof(keyname)); - if (slot != -1) - { - snprintf(keyname, sizeof(keyname), "%d:", slot); - } - if (sizeof(keyname) - strlen(keyname) <= keyid.len * 4 / 3 + 1) - { - return NULL; - } - chunk_to_hex(keyid, keyname + strlen(keyname), FALSE); - - if (!engine_id) - { - engine_id = lib->settings->get_str(lib->settings, - "%s.plugins.openssl.engine_id", "pkcs11", lib->ns); - } - engine = ENGINE_by_id(engine_id); - if (!engine) - { - DBG2(DBG_LIB, "engine '%s' is not available", engine_id); - return NULL; - } - if (!ENGINE_init(engine)) - { - DBG1(DBG_LIB, "failed to initialize engine '%s'", engine_id); - ENGINE_free(engine); - return NULL; - } - if (!login(engine, keyid)) - { - DBG1(DBG_LIB, "login to engine '%s' failed", engine_id); - ENGINE_free(engine); - return NULL; - } - key = ENGINE_load_private_key(engine, keyname, NULL, NULL); - if (!key) - { - DBG1(DBG_LIB, "failed to load private key with ID '%s' from " - "engine '%s'", keyname, engine_id); - ENGINE_free(engine); - return NULL; - } - ENGINE_free(engine); - - this = create_empty(); - this->rsa = EVP_PKEY_get1_RSA(key); - this->engine = TRUE; - if (!this->rsa) - { - destroy(this); - return NULL; - } - - return &this->public; -#else /* OPENSSL_NO_ENGINE */ - return NULL; -#endif /* OPENSSL_NO_ENGINE */ -} - #endif /* OPENSSL_NO_RSA */ diff --git a/src/libstrongswan/plugins/openssl/openssl_rsa_private_key.h b/src/libstrongswan/plugins/openssl/openssl_rsa_private_key.h index 34ce4c776..783181c1d 100644 --- a/src/libstrongswan/plugins/openssl/openssl_rsa_private_key.h +++ b/src/libstrongswan/plugins/openssl/openssl_rsa_private_key.h @@ -67,9 +67,10 @@ openssl_rsa_private_key_t *openssl_rsa_private_key_load(key_type_t type, * Wrap an EVP_PKEY object of type EVP_PKEY_RSA * * @param key EVP_PKEY_RSA key object (adopted) + * @param engine whether the key was loaded via an engine * @return loaded key, NULL on failure */ -private_key_t *openssl_rsa_private_key_create(EVP_PKEY *key); +private_key_t *openssl_rsa_private_key_create(EVP_PKEY *key, bool engine); /** * Connect to a RSA private key on a smartcard. |