[prev in list] [next in list] [prev in thread] [next in thread]
List: strongswan-announce
Subject: [strongSwan-dev] [PATCH] pkcs11: keyid alias
From: Raphael Geissert <geissert () debian ! org>
Date: 2013-08-06 7:51:59
Message-ID: CAA7hUgHmR7hXjB9EQV13G_TKEoESYPeSu0fU9KPdQKRtZztMNw () mail ! gmail ! com
[Download RAW message or body]
Hi,
As briefly explained in IRC, the attached patches work around an issue
with charon-nm when the CKA_ID does not match the subject key
identifier. It is not pretty, I must admit, but it should work for
what I consider are "standard" users of the nm plugin: users with only
one token.
The first patch is just a bit of code refactoring. In the second patch
I'm using a 255 bytes buffer for the CKA_ID but now I think it is too
big. In any case, it is resized later on, so it shouldn't be a real
issue other than ("why 255?").
Please consider applying them.
Regards,
--
Raphael Geissert - Debian Developer
www.debian.org - get.debian.net
["0001-pkcs11-refactor-the-login-and-reauth-methods.patch" (application/octet-stream)]
From 3633d5efc5c192ca8b8ec76e2bf6ff0402df9bd6 Mon Sep 17 00:00:00 2001
From: Raphael Geissert <raphael-externe.geissert@edf.fr>
Date: Mon, 5 Aug 2013 16:05:15 +0200
Subject: [PATCH 1/2] pkcs11: refactor the login and reauth methods
Adds a generic_auth method to actually handle the login process.
---
.../plugins/pkcs11/pkcs11_private_key.c | 50 ++++++++------------
1 file changed, 21 insertions(+), 29 deletions(-)
diff --git a/src/libstrongswan/plugins/pkcs11/pkcs11_private_key.c \
b/src/libstrongswan/plugins/pkcs11/pkcs11_private_key.c index bb9cc7a..a9d7017 100644
--- a/src/libstrongswan/plugins/pkcs11/pkcs11_private_key.c
+++ b/src/libstrongswan/plugins/pkcs11/pkcs11_private_key.c
@@ -184,10 +184,10 @@ CK_MECHANISM_PTR \
pkcs11_encryption_scheme_to_mech(encryption_scheme_t scheme) }
/**
- * Reauthenticate to do a signature
+ * Generic login, it takes the CKU
*/
-static bool reauth(private_pkcs11_private_key_t *this,
- CK_SESSION_HANDLE session)
+static bool generic_auth(private_pkcs11_private_key_t *this,
+ CK_SESSION_HANDLE session, unsigned long type, identification_t *keyid)
{
enumerator_t *enumerator;
shared_key_t *shared;
@@ -196,30 +196,41 @@ static bool reauth(private_pkcs11_private_key_t *this,
bool found = FALSE, success = FALSE;
enumerator = lib->credmgr->create_shared_enumerator(lib->credmgr,
- SHARED_PIN, this->keyid, NULL);
+ SHARED_PIN, keyid, NULL);
while (enumerator->enumerate(enumerator, &shared, NULL, NULL))
{
found = TRUE;
pin = shared->get_key(shared);
- rv = this->lib->f->C_Login(session, CKU_CONTEXT_SPECIFIC,
+ rv = this->lib->f->C_Login(session, type,
pin.ptr, pin.len);
if (rv == CKR_OK)
{
success = TRUE;
break;
}
- DBG1(DBG_CFG, "reauthentication login failed: %N", ck_rv_names, rv);
+ DBG1(DBG_CFG, "authentication login failed: %N", ck_rv_names, rv);
}
enumerator->destroy(enumerator);
if (!found)
{
- DBG1(DBG_CFG, "private key requires reauthentication, but no PIN found");
+ DBG1(DBG_CFG, "private key requires authentication, but no PIN found for PKCS#11 \
key %Y", keyid); return FALSE;
}
return success;
}
+/**
+ * Reauthenticate to do a signature
+ */
+static bool reauth(private_pkcs11_private_key_t *this,
+ CK_SESSION_HANDLE session)
+{
+ DBG1(DBG_CFG, "reauthentication in progress");
+
+ return generic_auth(this, session, CKU_CONTEXT_SPECIFIC, this->keyid);
+}
+
METHOD(private_key_t, sign, bool,
private_pkcs11_private_key_t *this, signature_scheme_t scheme,
chunk_t data, chunk_t *signature)
@@ -527,12 +538,9 @@ static bool find_key(private_pkcs11_private_key_t *this, chunk_t \
keyid)
*/
static bool login(private_pkcs11_private_key_t *this, int slot)
{
- enumerator_t *enumerator;
- shared_key_t *shared;
- chunk_t pin;
CK_RV rv;
CK_SESSION_INFO info;
- bool found = FALSE, success = FALSE;
+ bool success;
rv = this->lib->f->C_GetSessionInfo(this->session, &info);
if (rv != CKR_OK)
@@ -546,28 +554,12 @@ static bool login(private_pkcs11_private_key_t *this, int slot)
return TRUE;
}
- enumerator = lib->credmgr->create_shared_enumerator(lib->credmgr,
- SHARED_PIN, this->keyid, NULL);
- while (enumerator->enumerate(enumerator, &shared, NULL, NULL))
+ success = generic_auth(this, this->session, CKU_USER, this->keyid);
+ if (!success)
{
- 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);
-
- if (!found)
- {
- DBG1(DBG_CFG, "no PIN found for PKCS#11 key %Y", this->keyid);
- return FALSE;
- }
return success;
}
--
1.7.10.4
["0002-pkcs11-allow-a-secondary-keyid-an-alias-to-be-used.patch" (application/octet-stream)]
From 27f975c05d1a4572889b2155b35ef9c572c2fd4a Mon Sep 17 00:00:00 2001
From: Raphael Geissert <raphael-externe.geissert@edf.fr>
Date: Mon, 5 Aug 2013 16:15:20 +0200
Subject: [PATCH 2/2] pkcs11: allow a secondary keyid (an "alias") to be used
This is mainly to workaround an issue with charon-nm when the CKA_ID
(objects) doesn't match the subject key id (x.509 certificate). When
the private key can not be found, charon-nm will now request the keyid
to be found - this is done by finding the first token where a pubkey/cert
is found. The CKA_ID of that object will then be used as an "alias" of
the original keyid.
This change should not affect anything else, as it requires a special,
negative, slot number to be passed to pkcs11_private_key_connect. Even
then, the alias is only tried *after* trying the original keyid.
---
src/charon-nm/nm/nm_service.c | 10 ++
.../plugins/pkcs11/pkcs11_private_key.c | 153 ++++++++++++++++++--
2 files changed, 152 insertions(+), 11 deletions(-)
diff --git a/src/charon-nm/nm/nm_service.c b/src/charon-nm/nm/nm_service.c
index 901abd3..17945ca 100644
--- a/src/charon-nm/nm/nm_service.c
+++ b/src/charon-nm/nm/nm_service.c
@@ -255,6 +255,16 @@ static identification_t \
*find_smartcard_key(NMStrongswanPluginPrivate *priv, \
priv->creds->set_pin(priv->creds, keyid, pin); key = lib->creds->create(lib->creds, \
CRED_PRIVATE_KEY, KEY_ANY, BUILD_PKCS11_KEYID, keyid, BUILD_END);
+ if (!key)
+ {
+ DBG1(DBG_CFG, "Building the private key with keyid %#B failed", &keyid);
+ key = lib->creds->create(lib->creds, CRED_PRIVATE_KEY,
+ KEY_ANY, BUILD_PKCS11_KEYID, keyid, BUILD_PKCS11_SLOT, -0x1057, BUILD_END);
+ if (!key)
+ {
+ DBG1(DBG_CFG, "building by slot didn't work either");
+ }
+ }
if (key)
{
/* prefer a more convenient subjectAltName */
diff --git a/src/libstrongswan/plugins/pkcs11/pkcs11_private_key.c \
b/src/libstrongswan/plugins/pkcs11/pkcs11_private_key.c index a9d7017..29da98f 100644
--- a/src/libstrongswan/plugins/pkcs11/pkcs11_private_key.c
+++ b/src/libstrongswan/plugins/pkcs11/pkcs11_private_key.c
@@ -67,6 +67,11 @@ struct private_pkcs11_private_key_t {
identification_t *keyid;
/**
+ * Keyid (alias) of the key we use
+ */
+ identification_t *keyid_alias;
+
+ /**
* Associated public key
*/
public_key_t *pubkey;
@@ -228,7 +233,15 @@ static bool reauth(private_pkcs11_private_key_t *this,
{
DBG1(DBG_CFG, "reauthentication in progress");
- return generic_auth(this, session, CKU_CONTEXT_SPECIFIC, this->keyid);
+ if (generic_auth(this, session, CKU_CONTEXT_SPECIFIC, this->keyid))
+ {
+ return TRUE;
+ }
+ else if (this->keyid_alias)
+ {
+ return generic_auth(this, session, CKU_CONTEXT_SPECIFIC, this->keyid_alias);
+ }
+ return FALSE;
}
METHOD(private_key_t, sign, bool,
@@ -390,6 +403,10 @@ METHOD(private_key_t, destroy, void,
this->pubkey->destroy(this->pubkey);
}
this->keyid->destroy(this->keyid);
+ if (this->keyid_alias)
+ {
+ this->keyid_alias->destroy(this->keyid_alias);
+ }
this->lib->f->C_CloseSession(this->session);
free(this);
}
@@ -484,6 +501,81 @@ static pkcs11_library_t* find_lib_by_keyid(chunk_t keyid, int \
*slot, }
/**
+ * Find the PKCS#11 lib having an object of the given class, yeah, wild-guess
+ */
+static pkcs11_library_t* find_lib_and_keyid(chunk_t *keyid, int *slot,
+ CK_OBJECT_CLASS class)
+{
+ pkcs11_manager_t *manager;
+ enumerator_t *enumerator;
+ pkcs11_library_t *p11, *found = NULL;
+ CK_SLOT_ID current;
+ chunk_t keyid_read = chunk_alloc(255);
+ CK_ATTRIBUTE attr[] = {
+ {CKA_ID, keyid_read.ptr, keyid_read.len},
+ };
+ memset(keyid_read.ptr, '\0', keyid_read.len);
+
+ manager = pkcs11_manager_get();
+ if (!manager)
+ {
+ return NULL;
+ }
+ enumerator = manager->create_token_enumerator(manager);
+ while (enumerator->enumerate(enumerator, &p11, ¤t))
+ {
+ /* look for a pubkey/cert, it is usually readable without login */
+ CK_ATTRIBUTE tmpl[] = {
+ {CKA_CLASS, &class, sizeof(class)},
+ };
+ CK_OBJECT_HANDLE object;
+ CK_SESSION_HANDLE session;
+ CK_RV rv;
+ enumerator_t *keys;
+
+ rv = p11->f->C_OpenSession(current, CKF_SERIAL_SESSION, NULL, NULL,
+ &session);
+ if (rv != CKR_OK)
+ {
+ DBG1(DBG_CFG, "opening PKCS#11 session failed: %N",
+ ck_rv_names, rv);
+ continue;
+ }
+ keys = p11->create_object_enumerator(p11, session,
+ tmpl, countof(tmpl), attr, countof(attr));
+ if (keys->enumerate(keys, &object))
+ {
+ u_char *ptr_to_nul;
+ DBG1(DBG_CFG, "found key on PKCS#11 token '%s':%d",
+ p11->get_name(p11), current);
+ ptr_to_nul = memchr(keyid_read.ptr, '\0', keyid_read.len);
+ if (!ptr_to_nul)
+ {
+ DBG1(DBG_CFG, "huh? no NUL in '%#B'? ", keyid_read);
+ chunk_free(&keyid_read);
+ }
+ else
+ {
+ keyid_read.len = (ptr_to_nul - keyid_read.ptr);
+ keyid_read.ptr = realloc(keyid_read.ptr, keyid_read.len);
+ DBG1(DBG_CFG, "Hope the correct CKA_ID is '%#B'", &keyid_read);
+ *keyid = keyid_read;
+ }
+ found = p11;
+ *slot = current;
+ }
+ keys->destroy(keys);
+ p11->f->C_CloseSession(session);
+ if (found)
+ {
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+ return found;
+}
+
+/**
* Find the key on the token
*/
static bool find_key(private_pkcs11_private_key_t *this, chunk_t keyid)
@@ -536,7 +628,7 @@ static bool find_key(private_pkcs11_private_key_t *this, chunk_t \
keyid) /**
* Find a PIN and try to log in
*/
-static bool login(private_pkcs11_private_key_t *this, int slot)
+static bool login(private_pkcs11_private_key_t *this, int slot, identification_t \
*keyid) {
CK_RV rv;
CK_SESSION_INFO info;
@@ -554,7 +646,7 @@ static bool login(private_pkcs11_private_key_t *this, int slot)
return TRUE;
}
- success = generic_auth(this, this->session, CKU_USER, this->keyid);
+ success = generic_auth(this, this->session, CKU_USER, keyid);
if (!success)
{
DBG1(DBG_CFG, "login to '%s':%d failed: %N",
@@ -614,7 +706,7 @@ pkcs11_private_key_t *pkcs11_private_key_connect(key_type_t type, \
va_list args) {
private_pkcs11_private_key_t *this;
char *module = NULL;
- chunk_t keyid = chunk_empty;
+ chunk_t keyid = chunk_empty, keyid_alias = chunk_empty;
int slot = -1;
CK_RV rv;
@@ -673,6 +765,25 @@ pkcs11_private_key_t *pkcs11_private_key_connect(key_type_t \
type, va_list args) return NULL;
}
}
+ else if (slot == -0x1057)
+ {
+ keyid_alias = chunk_clone(keyid);
+ this->lib = find_lib_and_keyid(&keyid_alias, &slot, CKO_PUBLIC_KEY);
+ if (!this->lib)
+ {
+ this->lib = find_lib_and_keyid(&keyid_alias, &slot, CKO_CERTIFICATE);
+ }
+ if (!this->lib)
+ {
+ DBG1(DBG_CFG, "no PKCS#11 module found having a keyid %#B", &keyid);
+ free(this);
+ return NULL;
+ }
+ else
+ {
+ DBG1(DBG_CFG, "found a PKCS#11 module in slot %d having a keyid %#B", slot, \
&keyid_alias); + }
+ }
else
{
this->lib = find_lib_by_keyid(keyid, &slot, CKO_PUBLIC_KEY);
@@ -700,11 +811,19 @@ pkcs11_private_key_t *pkcs11_private_key_connect(key_type_t \
type, va_list args)
this->slot = slot;
this->keyid = identification_create_from_encoding(ID_KEY_ID, keyid);
+ this->keyid_alias = NULL;
+ if (keyid_alias.ptr)
+ {
+ this->keyid_alias = identification_create_from_encoding(ID_KEY_ID, keyid_alias);
+ }
- if (!login(this, slot))
+ if (!login(this, slot, this->keyid))
{
- destroy(this);
- return NULL;
+ if (this->keyid_alias && !login(this, slot, this->keyid_alias))
+ {
+ destroy(this);
+ return NULL;
+ }
}
if (!find_key(this, keyid))
@@ -719,10 +838,22 @@ pkcs11_private_key_t *pkcs11_private_key_connect(key_type_t \
type, va_list args) this->pubkey = find_pubkey_in_certs(this, keyid);
if (!this->pubkey)
{
- DBG1(DBG_CFG, "no public key or certificate found for private key "
- "on '%s':%d", module, slot);
- destroy(this);
- return NULL;
+ DBG1(DBG_CFG, "no public key or certificate found for private key (keyid '%#B') "
+ "on '%s':%d", &keyid, module, slot);
+ if (!keyid_alias.ptr || !find_key(this, keyid_alias))
+ {
+ if (keyid_alias.ptr)
+ {
+ this->pubkey = find_pubkey_in_certs(this, keyid_alias);
+ }
+ if (!this->pubkey)
+ {
+ DBG1(DBG_CFG, "no public key or certificate found for private key (keyid '%#B') \
" + "on '%s':%d", &keyid_alias, module, slot);
+ destroy(this);
+ return NULL;
+ }
+ }
}
}
--
1.7.10.4
_______________________________________________
Dev mailing list
Dev@lists.strongswan.org
https://lists.strongswan.org/mailman/listinfo/dev
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic