|
From: David W. <dw...@in...> - 2014-12-09 21:24:18
|
Here's a proof of concept which makes it use p11-kit-proxy.so if not
told to use anything different (which is a bit of a hack and definitely
at least needs to *find* it in $libdir or something). And also parses
PKCS#11 URIs for the key location.
Ideally I think we want to be using p11-kit's functions for loading the
modules, not p11-kit-proxy. But this is a start.
With a corresponding patch¹ to the client application I can now use
simple PKCS#11 URIs for keys when using OpenSSL just as I can when I
build with GnuTLS.
diff --git a/configure.ac b/configure.ac
index b67256e..84178ad 100644
--- a/configure.ac
+++ b/configure.ac
@@ -109,6 +109,7 @@ AC_CHECK_HEADERS([ \
])
PKG_CHECK_MODULES([LIBP11], [libp11 >= 0.2.5],, [AC_MSG_ERROR([libp11 >= 0.2.5 is required])])
+PKG_CHECK_MODULES([P11KIT], [p11-kit-1],, [AC_MSG_ERROR([p11-kit-1 is required])])
PKG_CHECK_MODULES(
[OPENSSL],
diff --git a/src/Makefile.am b/src/Makefile.am
index 72a3ffe..404a63d 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -18,8 +18,8 @@ else
dist_noinst_DATA = versioninfo.rc
endif
engine_pkcs11_la_CFLAGS = $(AM_CFLAGS) $(OPENSSL_EXTRA_CFLAGS) $(OPENSSL_CFLAGS) \
- $(LIBP11_CFLAGS)
-engine_pkcs11_la_LIBADD = $(ENGINE_LINK) $(OPENSSL_LIBS) $(LIBP11_LIBS)
+ $(LIBP11_CFLAGS) $(P11KIT_CFLAGS)
+engine_pkcs11_la_LIBADD = $(ENGINE_LINK) $(OPENSSL_LIBS) $(LIBP11_LIBS) $(P11KIT_LIBS)
engine_pkcs11_la_LDFLAGS = $(AM_LDFLAGS) $(OPENSSL_EXTRA_LDFLAGS) \
-module -shared -avoid-version \
-export-symbols "$(srcdir)/engine_pkcs11.exports" \
diff --git a/src/engine_pkcs11.c b/src/engine_pkcs11.c
index c1b8fbb..5b28d89 100644
--- a/src/engine_pkcs11.c
+++ b/src/engine_pkcs11.c
@@ -34,6 +34,8 @@
#include <libp11.h>
#include "engine_pkcs11.h"
+#include <p11-kit/uri.h>
+
#ifdef _WIN32
#define strncasecmp strnicmp
#endif
@@ -56,7 +58,7 @@ static int pin_length = 0;
static int verbose = 0;
-static char *module = NULL;
+static char *module = "/usr/lib64/p11-kit-proxy.so";
static char *init_args = NULL;
@@ -538,6 +540,28 @@ int load_cert_ctrl(ENGINE * e, void *p)
return 1;
}
+static int p11_match(const char *tokstr, const char *matchstr, size_t tokstrlen)
+{
+ int matchstrlen, i;
+
+ if (!matchstr)
+ return 0;
+
+ matchstrlen = strlen(matchstr);
+
+ if (matchstrlen > tokstrlen)
+ return 0;
+
+ if (strncmp(matchstr, tokstr, matchstrlen))
+ return 0;
+
+ for (i = matchstrlen; i < tokstrlen; i++)
+ if (tokstr[i] != ' ')
+ return 0;
+
+ return 1;
+}
+
static EVP_PKEY *pkcs11_load_key(ENGINE * e, const char *s_slot_key_id,
UI_METHOD * ui_method, void *callback_data,
int isPrivate)
@@ -548,6 +572,8 @@ static EVP_PKEY *pkcs11_load_key(ENGINE * e, const char *s_slot_key_id,
PKCS11_KEY *keys, *selected_key = NULL;
PKCS11_CERT *certs;
EVP_PKEY *pk;
+ P11KitUri *uri;
+ CK_ATTRIBUTE *uri_id = NULL, *uri_label = NULL;
unsigned int slot_count, cert_count, key_count, n, m;
unsigned char key_id[MAX_VALUE_LEN / 2];
size_t key_id_len = sizeof(key_id);
@@ -556,6 +582,24 @@ static EVP_PKEY *pkcs11_load_key(ENGINE * e, const char *s_slot_key_id,
char flags[64];
if (s_slot_key_id && *s_slot_key_id) {
+ if (!strncmp(s_slot_key_id, "pkcs11:", 7)) {
+ uri = p11_kit_uri_new();
+ if (p11_kit_uri_parse(s_slot_key_id, P11_KIT_URI_FOR_ANY, uri)) {
+ fprintf(stderr,
+ "Failed to parse PKCS#11 URI\n");
+ p11_kit_uri_free(uri);
+ return NULL;
+ }
+ uri_id = p11_kit_uri_get_attribute(uri, CKA_ID);
+ if (uri_id && uri_id->ulValueLen <= sizeof(key_id)) {
+ key_id_len = uri_id->ulValueLen;
+ memcpy(key_id, uri_id->pValue, uri_id->ulValueLen);
+ } else
+ key_id_len = 0;
+ uri_label = p11_kit_uri_get_attribute(uri, CKA_LABEL);
+ if (uri_label)
+ key_label = strdup(uri_label->pValue);
+ } else {
n = parse_slot_id_string(s_slot_key_id, &slot_nr,
key_id, &key_id_len, &key_label);
@@ -580,6 +624,7 @@ static EVP_PKEY *pkcs11_load_key(ENGINE * e, const char *s_slot_key_id,
} else
fprintf(stderr, "label: %s\n", key_label);
}
+ }
}
if (PKCS11_enumerate_slots(ctx, &slot_list, &slot_count) < 0)
@@ -611,6 +656,22 @@ static EVP_PKEY *pkcs11_load_key(ENGINE * e, const char *s_slot_key_id,
if (slot_nr != -1 &&
slot_nr == PKCS11_get_slotid_from_slot(slot)) {
found_slot = slot;
+ } else if (uri && slot->token) {
+ CK_TOKEN_INFO *tokinfo = p11_kit_uri_get_token_info(uri);
+ int match = 1;
+
+ if (tokinfo->label[0])
+ match = p11_match(tokinfo->label, slot->token->label, sizeof(tokinfo->label));
+ if (match && tokinfo->manufacturerID[0])
+ match = p11_match(tokinfo->manufacturerID, slot->token->manufacturer, sizeof(tokinfo->manufacturerID));
+ if (match && tokinfo->model[0])
+ match = p11_match(tokinfo->model, slot->token->model, sizeof(tokinfo->model));
+ if (match && tokinfo->serialNumber[0])
+ match = p11_match(tokinfo->serialNumber, slot->token->serialnr, sizeof(tokinfo->serialNumber));
+ if (match) {
+ slot_nr = PKCS11_get_slotid_from_slot(slot);
+ found_slot = slot;
+ }
}
if (verbose) {
@@ -755,22 +816,22 @@ static EVP_PKEY *pkcs11_load_key(ENGINE * e, const char *s_slot_key_id,
if (s_slot_key_id && *s_slot_key_id && (key_id_len != 0 || key_label != NULL)) {
for (n = 0; n < key_count; n++) {
PKCS11_KEY *k = keys + n;
+ int match = 1;
if (verbose) {
fprintf(stderr, " %2u %c%c %s\n", n + 1,
k->isPrivate ? 'P' : ' ',
k->needLogin ? 'L' : ' ', k->label);
}
- if (key_label == NULL) {
- if (key_id_len != 0 && k->id_len == key_id_len
- && memcmp(k->id, key_id, key_id_len) == 0) {
- selected_key = k;
- }
- } else {
- if (strcmp(k->label, key_label) == 0) {
- selected_key = k;
- }
+ if (key_id_len != 0 && (k->id_len != key_id_len ||
+ memcmp(k->id, key_id, key_id_len) != 0)) {
+ match = 0;
+ }
+ if (key_label && strcmp(k->label, key_label) != 0) {
+ match = 0;
}
+ if (match)
+ selected_key = k;
}
} else {
selected_key = keys; /* use first */
@@ -790,6 +851,8 @@ static EVP_PKEY *pkcs11_load_key(ENGINE * e, const char *s_slot_key_id,
}
if (key_label != NULL)
free(key_label);
+ if (uri)
+ p11_kit_uri_free(uri);
return pk;
}
--
dwmw2
¹ http://david.woodhou.se/openconnect-engine-pkcs11.patch
|