From f95c6f2f2db009c345e8dfb0da7d7e003de2ada7 Mon Sep 17 00:00:00 2001 From: Alessio Di Mauro Date: Fri, 3 Jul 2015 17:23:16 +0200 Subject: [PATCH] Added basic multivendor support for token information. --- lib/ykpiv.c | 2 +- ykcs11/Makefile.am | 2 ++ ykcs11/vendors.c | 28 +++++++++++++++++ ykcs11/vendors.h | 20 ++++++++++++ ykcs11/ykcs11.c | 78 +++++++++++++++++++++++++++++++++++++++------- ykcs11/yubico.c | 29 +++++++++++++++++ ykcs11/yubico.h | 8 +++++ 7 files changed, 154 insertions(+), 13 deletions(-) create mode 100644 ykcs11/vendors.c create mode 100644 ykcs11/vendors.h create mode 100644 ykcs11/yubico.c create mode 100644 ykcs11/yubico.h diff --git a/lib/ykpiv.c b/lib/ykpiv.c index 2481d2a..b3a5114 100644 --- a/lib/ykpiv.c +++ b/lib/ykpiv.c @@ -177,7 +177,7 @@ ykpiv_rc ykpiv_connect(ykpiv_state *state, const char *wanted) { } // ********* - reader_ptr = reader_buf; + reader_ptr = reader_buf; // TODO: reader_buf is never free'd if(wanted) { while(*reader_ptr != '\0') { if(strstr(reader_ptr, wanted)) { diff --git a/ykcs11/Makefile.am b/ykcs11/Makefile.am index a30eed8..050c4dc 100644 --- a/ykcs11/Makefile.am +++ b/ykcs11/Makefile.am @@ -34,6 +34,8 @@ AM_CPPFLAGS += -I$(top_srcdir)/lib -I$(top_builddir)/lib lib_LTLIBRARIES = libykcs11.la libykcs11_la_SOURCES = ykcs11.c version.c ykcs11.pc.in ykcs11.map +libykcs11_la_SOURCES += vendors.c vendor.h yubico.c yubico. h + #internal.h #libykcs11_la_SOURCES += error.c #libykcs11_la_LDADD = ../lib/libykpiv.la diff --git a/ykcs11/vendors.c b/ykcs11/vendors.c new file mode 100644 index 0000000..fcbb803 --- /dev/null +++ b/ykcs11/vendors.c @@ -0,0 +1,28 @@ +#include "vendors.h" +#include "yubico.h" + +vendor_id_t get_vendor_id(char *vendor_name) { + vendor_id_t vid; + + if (strncmp(vendor_name, "Yubico", 6) == 0) + return YUBICO; + + return UNKNOWN; +} + +vendor_t get_vendor(vendor_id_t vid) { + vendor_t v; + + switch (vid) { + case YUBICO: + v.get_version = YUBICO_get_version; + break; + + case UNKNOWN: + v.get_version = NULL; + + } + + return v; + +} diff --git a/ykcs11/vendors.h b/ykcs11/vendors.h new file mode 100644 index 0000000..c456d0e --- /dev/null +++ b/ykcs11/vendors.h @@ -0,0 +1,20 @@ +#ifndef VENDORS_H +#define VENDORS_H + +#include "pkcs11.h" + +typedef enum { + UNKNOWN = 0x00, + YUBICO = 0x01 +} vendor_id_t; + +typedef CK_VERSION (*get_version_f)(char *, int); + +typedef struct { + get_version_f get_version; +} vendor_t; + +vendor_id_t get_vendor_id(char *vendor_name); +vendor_t get_vendor(vendor_id_t vid); + +#endif diff --git a/ykcs11/ykcs11.c b/ykcs11/ykcs11.c index 9011620..242e767 100644 --- a/ykcs11/ykcs11.c +++ b/ykcs11/ykcs11.c @@ -2,6 +2,7 @@ #include #include #include +#include "vendors.h" // TODO: do a bit of backend magic or should be handled by libykpiv? @@ -111,21 +112,29 @@ CK_DEFINE_FUNCTION(CK_RV, C_GetSlotList)( { DIN; unsigned long tot_readers_len; - ykpiv_get_reader_slot_number(piv_state, pulCount, &tot_readers_len); - //DBG(("%u val %x ptr", *pulCount, pSlotList)); + unsigned long n_readers; + int i; + ykpiv_get_reader_slot_number(piv_state, &n_readers, &tot_readers_len); // TODO: maybe refactor this with a reader struct? if (pSlotList == NULL_PTR) { // Just return the number of slots + *pulCount = n_readers; + DOUT; return CKR_OK; } - pSlotList[0] = 0; - return CKR_OK; - /*if ((*pulCount / sizeof(CK_SLOT_ID)) < tot_readers_len) { - DBG(("Buffer too small: needed %u, provided %u", tot_readers_len, *pulCount / sizeof(CK_SLOT_ID))) - return CKR_BUFFER_TOO_SMALL; - }*/ + if (*pulCount < n_readers) { + DBG(("Buffer too small: needed %u, provided %u", n_readers, *pulCount)); + return CKR_BUFFER_TOO_SMALL; + } + + for (i = 0; i < n_readers; i++) { + pSlotList[i] = i; + } + DBG(("%d token", tokenPresent)); DBG(("%u count", *pulCount)); + + DOUT; return CKR_OK; } @@ -140,14 +149,12 @@ CK_DEFINE_FUNCTION(CK_RV, C_GetSlotInfo)( * name [interface] (serial) index slot * http://ludovicrousseau.blogspot.se/2010/05/what-is-in-pcsc-reader-name.html */ - ykpiv_get_reader_slot(piv_state, 0, pInfo->slotDescription); + ykpiv_get_reader_slot(piv_state, slotID, pInfo->slotDescription); // TODO: should be ' ' padded strcpy(pInfo->manufacturerID, "ADD SLOT MANUFACTURER NAME HERE"); - pInfo->flags = CKF_TOKEN_PRESENT | CKF_REMOVABLE_DEVICE | CKF_HW_SLOT; + pInfo->flags = CKF_TOKEN_PRESENT | CKF_REMOVABLE_DEVICE | CKF_HW_SLOT; // TODO: What for other brands? Query for token status? DBG(("slotID %u, pInfo %s", slotID, pInfo->slotDescription)); - - return CKR_OK; } @@ -157,6 +164,53 @@ CK_DEFINE_FUNCTION(CK_RV, C_GetTokenInfo)( ) { DIN; + CK_VERSION ver = {0, 0}; + vendor_t yubico; + char buf[64]; + + ykpiv_get_version(piv_state, buf, 64); + yubico = get_vendor(get_vendor_id("Yubico")); + ver = yubico.get_version(buf, strlen(buf)); + + memset(pInfo->label, ' ', sizeof(pInfo->label)); + strncpy(pInfo->label, "LABEL", 5); + + memset(pInfo->manufacturerID, ' ', sizeof(pInfo->manufacturerID)); + strncpy(pInfo->manufacturerID, "MANUFACTURER_ID", 15); + + memset(pInfo->model, ' ', sizeof(pInfo->model)); + strncpy(pInfo->model, "MODEL", 5); + + memset(pInfo->serialNumber, ' ', sizeof(pInfo->serialNumber)); + strncpy(pInfo->serialNumber, "12345", 5); + + pInfo->flags = 0x00000400; // bit flags indicating capabilities and status of the device as defined below + + pInfo->ulMaxSessionCount = CK_UNAVAILABLE_INFORMATION; // TODO: should this be 1? + + pInfo->ulSessionCount = CK_UNAVAILABLE_INFORMATION; // number of sessions that this application currently has open with the token + + pInfo->ulMaxRwSessionCount = CK_UNAVAILABLE_INFORMATION; // maximum number of read/write sessions that can be opened with the token at one time by a single TODO: should this be 1? + + pInfo->ulRwSessionCount = CK_UNAVAILABLE_INFORMATION; // number of read/write sessions that this application currently has open with the token + + pInfo->ulMaxPinLen = 127; // maximum length in bytes of the PIN + + pInfo->ulMinPinLen = 3; // minimum length in bytes of the PIN + + pInfo->ulTotalPublicMemory = CK_UNAVAILABLE_INFORMATION; + + pInfo->ulFreePublicMemory = CK_UNAVAILABLE_INFORMATION; + + pInfo->ulTotalPrivateMemory = CK_UNAVAILABLE_INFORMATION; + + pInfo->ulFreePrivateMemory = CK_UNAVAILABLE_INFORMATION; + + pInfo->hardwareVersion = ver; // version number of hardware + + pInfo->firmwareVersion = ver; // version number of firmware + + memset(pInfo->utcTime, ' ', sizeof(pInfo->utcTime)); return CKR_OK; } diff --git a/ykcs11/yubico.c b/ykcs11/yubico.c new file mode 100644 index 0000000..80f40be --- /dev/null +++ b/ykcs11/yubico.c @@ -0,0 +1,29 @@ +#include "yubico.h" +#include "pkcs11.h" + +CK_VERSION YUBICO_get_version(char *version, int len) { + + CK_VERSION v = {0, 0}; + int i = 0; + + while (i < len && version[i] != '.') { + v.major *= 10; + v.major += version[i++] - '0'; + } + + i++; + + while (i < len && version[i] != '.') { + v.minor *= 10; + v.minor += version[i++] - '0'; + } + + i++; + + while (i < len && version[i] != '.') { + v.minor *= 10; + v.minor += version[i++] - '0'; + } + + return v; +} diff --git a/ykcs11/yubico.h b/ykcs11/yubico.h new file mode 100644 index 0000000..e2487f6 --- /dev/null +++ b/ykcs11/yubico.h @@ -0,0 +1,8 @@ +#ifndef YUBICO_H +#define YUBICO_H + +#include "pkcs11.h" + +CK_VERSION YUBICO_get_version(char *version, int len); + +#endif