diff options
author | Martin Willi <martin@revosec.ch> | 2010-07-19 10:25:51 +0200 |
---|---|---|
committer | Martin Willi <martin@revosec.ch> | 2010-08-04 09:26:21 +0200 |
commit | 0556667dcafd30e47150395861aebfddd751816b (patch) | |
tree | 07dd5fcffccd6948efc46cae0352bf0259b68f9f | |
parent | 70789d28a13ac8f2448d97c23df2c7707b11937a (diff) | |
download | strongswan-0556667dcafd30e47150395861aebfddd751816b.tar.bz2 strongswan-0556667dcafd30e47150395861aebfddd751816b.tar.xz |
Use credential sets to load smartcard keys
-rw-r--r-- | src/libcharon/plugins/stroke/stroke_cred.c | 111 | ||||
-rw-r--r-- | src/libstrongswan/plugins/openssl/openssl_rsa_private_key.c | 58 | ||||
-rw-r--r-- | src/libstrongswan/plugins/pkcs11/pkcs11_private_key.c | 33 |
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; } /** |