summaryrefslogtreecommitdiff
path: root/src/libstrongswan/plugins/openssl/openssl_plugin.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/libstrongswan/plugins/openssl/openssl_plugin.c')
-rw-r--r--src/libstrongswan/plugins/openssl/openssl_plugin.c158
1 files changed, 154 insertions, 4 deletions
diff --git a/src/libstrongswan/plugins/openssl/openssl_plugin.c b/src/libstrongswan/plugins/openssl/openssl_plugin.c
index ab73d718f..8b0a7c5c7 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),
@@ -480,6 +624,10 @@ METHOD(plugin_t, get_features, int,
/* signature/encryption schemes */
PLUGIN_PROVIDE(PRIVKEY_SIGN, SIGN_RSA_EMSA_PKCS1_NULL),
PLUGIN_PROVIDE(PUBKEY_VERIFY, SIGN_RSA_EMSA_PKCS1_NULL),
+#if OPENSSL_VERSION_NUMBER >= 0x10000000L
+ PLUGIN_PROVIDE(PRIVKEY_SIGN, SIGN_RSA_EMSA_PSS),
+ PLUGIN_PROVIDE(PUBKEY_VERIFY, SIGN_RSA_EMSA_PSS),
+#endif
#ifndef OPENSSL_NO_SHA1
PLUGIN_PROVIDE(PRIVKEY_SIGN, SIGN_RSA_EMSA_PKCS1_SHA1),
PLUGIN_PROVIDE(PUBKEY_VERIFY, SIGN_RSA_EMSA_PKCS1_SHA1),
@@ -554,6 +702,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),