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 |