aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMartin Willi <martin@revosec.ch>2010-07-19 10:25:51 +0200
committerMartin Willi <martin@revosec.ch>2010-08-04 09:26:21 +0200
commit0556667dcafd30e47150395861aebfddd751816b (patch)
tree07dd5fcffccd6948efc46cae0352bf0259b68f9f
parent70789d28a13ac8f2448d97c23df2c7707b11937a (diff)
downloadstrongswan-0556667dcafd30e47150395861aebfddd751816b.tar.bz2
strongswan-0556667dcafd30e47150395861aebfddd751816b.tar.xz
Use credential sets to load smartcard keys
-rw-r--r--src/libcharon/plugins/stroke/stroke_cred.c111
-rw-r--r--src/libstrongswan/plugins/openssl/openssl_rsa_private_key.c58
-rw-r--r--src/libstrongswan/plugins/pkcs11/pkcs11_private_key.c33
3 files changed, 150 insertions, 52 deletions
diff --git a/src/libcharon/plugins/stroke/stroke_cred.c b/src/libcharon/plugins/stroke/stroke_cred.c
index e5718e583..cfa33a746 100644
--- a/src/libcharon/plugins/stroke/stroke_cred.c
+++ b/src/libcharon/plugins/stroke/stroke_cred.c
@@ -31,6 +31,7 @@
#include <credentials/certificates/crl.h>
#include <credentials/certificates/ac.h>
#include <credentials/sets/mem_cred.h>
+#include <credentials/sets/callback_cred.h>
#include <utils/linked_list.h>
#include <utils/lexparser.h>
#include <threading/rwlock.h>
@@ -717,28 +718,60 @@ chunk_t passphrase_cb(passphrase_cb_data_t *data, int try)
}
/**
- * Smartcard PIN callback to read from stroke fd
+ * Data for PIN callback
*/
-chunk_t smartcard_cb(passphrase_cb_data_t *data, int try)
+typedef struct {
+ /** socket we use for prompting */
+ FILE *prompt;
+ /** card label */
+ char *card;
+ /** card keyid */
+ chunk_t keyid;
+ /** number of tries */
+ int try;
+} pin_cb_data_t;
+
+/**
+ * Callback function to receive PINs
+ */
+static shared_key_t* pin_cb(pin_cb_data_t *data,
+ identification_t *me, identification_t *other,
+ id_match_t *match_me, id_match_t *match_other)
{
- chunk_t secret = chunk_empty;;
+ chunk_t secret;
+ char buf[256];
- if (try != 1)
+ if (!me || !chunk_equals(me->get_encoding(me), data->keyid))
{
- fprintf(data->prompt, "invalid passphrase, aborting\n");
- return chunk_empty;
+ return NULL;
}
- fprintf(data->prompt, "Login to '%s' required\n", data->file);
- fprintf(data->prompt, "Passphrase:\n");
- if (fgets(data->buf, sizeof(data->buf), data->prompt))
+
+ if (data->try > 1)
{
- secret = chunk_create(data->buf, strlen(data->buf));
- if (secret.len)
+ fprintf(data->prompt, "PIN invalid, giving up.\n", data->card);
+ return NULL;
+ }
+ data->try++;
+ fprintf(data->prompt, "Login to '%s' required\n", data->card);
+ fprintf(data->prompt, "PIN:\n");
+ if (fgets(buf, sizeof(buf), data->prompt))
+ {
+ secret = chunk_create(buf, strlen(buf));
+ if (secret.len > 1)
{ /* trim appended \n */
secret.len--;
+ if (match_me)
+ {
+ *match_me = ID_MATCH_PERFECT;
+ }
+ if (match_other)
+ {
+ *match_other = ID_MATCH_NONE;
+ }
+ return shared_key_create(SHARED_PIN, chunk_clone(secret));
}
}
- return secret;
+ return NULL;
}
/**
@@ -754,8 +787,9 @@ static bool load_pin(private_stroke_cred_t *this, chunk_t line, int line_nr,
chunk_t chunk;
shared_key_t *shared;
identification_t *id;
- mem_cred_t *mem;
- callback_set_t *cb;
+ mem_cred_t *mem = NULL;
+ callback_cred_t *cb = NULL;
+ pin_cb_data_t pin_data;
enum {
SC_FORMAT_SLOT_MODULE_KEYID,
SC_FORMAT_SLOT_KEYID,
@@ -821,22 +855,33 @@ static bool load_pin(private_stroke_cred_t *this, chunk_t line, int line_nr,
DBG1(DBG_CFG, "line %d: malformed PIN: %s", line_nr, ugh);
return FALSE;
}
+
+ chunk = chunk_from_hex(chunk_create(keyid, strlen(keyid)), NULL);
if (secret.len == 7 && strneq(secret.ptr, "%prompt", 7))
{
- if (prompt)
- {
- passphrase_cb_data_t data = {
- .prompt = prompt,
- .file = path,
- };
+ if (!prompt)
+ { /* no IO channel to prompt, skip */
+ free(chunk.ptr);
+ return TRUE;
+ }
+ /* use callback credential set to prompt for the pin */
+ pin_data.prompt = prompt;
+ pin_data.card = smartcard;
+ pin_data.keyid = chunk;
+ pin_data.try = 1;
+ cb = callback_cred_create_shared((void*)pin_cb, &pin_data);
+ lib->credmgr->add_local_set(lib->credmgr, &cb->set);
+ }
+ else
+ {
+ /* provide our pin in a temporary credential set */
+ shared = shared_key_create(SHARED_PIN, secret);
+ id = identification_create_from_encoding(ID_KEY_ID, chunk);
+ mem = mem_cred_create();
+ mem->add_shared(mem, shared, id, NULL);
+ lib->credmgr->add_local_set(lib->credmgr, &mem->set);
+ }
- /* provide our pin in a temporary credential set */
- shared = shared_key_create(SHARED_PIN, secret);
- chunk = chunk_from_hex(chunk_create(keyid, strlen(keyid)), NULL);
- id = identification_create_from_encoding(ID_KEY_ID, chunk);
- set = mem_cred_create();
- set->add_shared(set, shared, id, NULL);
- lib->credmgr->add_local_set(lib->credmgr, &set->set);
/* unlock: smartcard needs the pin and potentially calls public set */
this->lock->unlock(this->lock);
switch (format)
@@ -861,8 +906,16 @@ static bool load_pin(private_stroke_cred_t *this, chunk_t line, int line_nr,
break;
}
this->lock->write_lock(this->lock);
- lib->credmgr->remove_local_set(lib->credmgr, &set->set);
- set->destroy(set);
+ if (mem)
+ {
+ lib->credmgr->remove_local_set(lib->credmgr, &mem->set);
+ mem->destroy(mem);
+ }
+ if (cb)
+ {
+ lib->credmgr->remove_local_set(lib->credmgr, &cb->set);
+ cb->destroy(cb);
+ }
if (key)
{
diff --git a/src/libstrongswan/plugins/openssl/openssl_rsa_private_key.c b/src/libstrongswan/plugins/openssl/openssl_rsa_private_key.c
index 3bca34244..e50656ef1 100644
--- a/src/libstrongswan/plugins/openssl/openssl_rsa_private_key.c
+++ b/src/libstrongswan/plugins/openssl/openssl_rsa_private_key.c
@@ -444,6 +444,48 @@ openssl_rsa_private_key_t *openssl_rsa_private_key_load(key_type_t type,
}
/**
+ * 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", 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;
+}
+
+/**
* See header.
*/
openssl_rsa_private_key_t *openssl_rsa_private_key_connect(key_type_t type,
@@ -452,8 +494,8 @@ openssl_rsa_private_key_t *openssl_rsa_private_key_connect(key_type_t type,
#ifndef OPENSSL_NO_ENGINE
private_openssl_rsa_private_key_t *this;
char *engine_id = NULL;
- char keyname[64], pin[32];;
- chunk_t secret = chunk_empty, keyid = chunk_empty;;
+ char keyname[64];
+ chunk_t keyid = chunk_empty;;
EVP_PKEY *key;
ENGINE *engine;
int slot = -1;
@@ -465,9 +507,6 @@ openssl_rsa_private_key_t *openssl_rsa_private_key_connect(key_type_t type,
case BUILD_PKCS11_KEYID:
keyid = va_arg(args, chunk_t);
continue;
- case BUILD_PASSPHRASE:
- secret = va_arg(args, chunk_t);
- continue;
case BUILD_PKCS11_SLOT:
slot = va_arg(args, int);
continue;
@@ -481,7 +520,7 @@ openssl_rsa_private_key_t *openssl_rsa_private_key_connect(key_type_t type,
}
break;
}
- if (!keyid.len || keyid.len > 40 || !secret.len)
+ if (!keyid.len || keyid.len > 40)
{
return NULL;
}
@@ -497,8 +536,6 @@ openssl_rsa_private_key_t *openssl_rsa_private_key_connect(key_type_t type,
}
chunk_to_hex(keyid, keyname + strlen(keyname), FALSE);
- snprintf(pin, sizeof(pin), "%.*s", secret.len, secret.ptr);
-
if (!engine_id)
{
engine_id = lib->settings->get_str(lib->settings,
@@ -516,13 +553,12 @@ openssl_rsa_private_key_t *openssl_rsa_private_key_connect(key_type_t type,
ENGINE_free(engine);
return NULL;
}
- if (!ENGINE_ctrl_cmd_string(engine, "PIN", pin, 0))
+ if (!login(engine, keyid))
{
- DBG1(DBG_LIB, "failed to set PIN on engine '%s'", engine_id);
+ 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)
{
diff --git a/src/libstrongswan/plugins/pkcs11/pkcs11_private_key.c b/src/libstrongswan/plugins/pkcs11/pkcs11_private_key.c
index b50ae070f..fa96c7f22 100644
--- a/src/libstrongswan/plugins/pkcs11/pkcs11_private_key.c
+++ b/src/libstrongswan/plugins/pkcs11/pkcs11_private_key.c
@@ -335,29 +335,38 @@ static bool find_key(private_pkcs11_private_key_t *this, chunk_t keyid)
*/
static bool login(private_pkcs11_private_key_t *this, chunk_t keyid, int slot)
{
+ enumerator_t *enumerator;
identification_t *id;
shared_key_t *shared;
chunk_t pin;
CK_RV rv;
+ bool found = FALSE, success = FALSE;
id = identification_create_from_encoding(ID_KEY_ID, keyid);
- shared = lib->credmgr->get_shared(lib->credmgr, SHARED_PIN, id, NULL);
- id->destroy(id);
- if (!shared)
- {
- DBG1(DBG_CFG, "no PIN found for PKCS#11 key %#B", keyid);
- return FALSE;
- }
- pin = shared->get_key(shared);
- rv = this->lib->f->C_Login(this->session, CKU_USER, pin.ptr, pin.len);
- shared->destroy(shared);
- if (rv != CKR_OK)
+ enumerator = lib->credmgr->create_shared_enumerator(lib->credmgr,
+ SHARED_PIN, id, NULL);
+ while (enumerator->enumerate(enumerator, &shared, NULL, NULL))
{
+ found = TRUE;
+ pin = shared->get_key(shared);
+ rv = this->lib->f->C_Login(this->session, CKU_USER, pin.ptr, pin.len);
+ if (rv == CKR_OK)
+ {
+ success = TRUE;
+ break;
+ }
DBG1(DBG_CFG, "login to '%s':%d failed: %N",
this->lib->get_name(this->lib), slot, ck_rv_names, rv);
+ }
+ enumerator->destroy(enumerator);
+ id->destroy(id);
+
+ if (!found)
+ {
+ DBG1(DBG_CFG, "no PIN found for PKCS#11 key %#B", &keyid);
return FALSE;
}
- return TRUE;
+ return success;
}
/**