[pkg-opensc-commit] [opensc] 222/295: macOS: added support for access via CryptoTokenKit

Eric Dorland eric at moszumanska.debian.org
Sat Jun 24 21:11:34 UTC 2017


This is an automated email from the git hooks/post-receive script.

eric pushed a commit to branch master
in repository opensc.

commit 013bdcb26409c3fae84258fbc5f318d468660b1b
Author: Frank Morgner <frankmorgner at gmail.com>
Date:   Tue Feb 7 15:45:10 2017 +0100

    macOS: added support for access via CryptoTokenKit
    
    Binaries still need to be signed with the com.apple.security.smartcard
    entitlement. The command should look something like this:
    
    codesign --force --entitlements MacOSX/pcsc.entitlements --sign "Mac Developer" target/Library/OpenSC/bin/*
    codesign --force --entitlements MacOSX/pcsc.entitlements --sign "Mac Developer" target/Library/OpenSC/lib/*.dylib
    codesign --force --entitlements MacOSX/pcsc.entitlements --sign "Mac Developer" --deep target/Library/OpenSC/lib/opensc-pkcs11.bundle
    codesign --force --entitlements MacOSX/pcsc.entitlements --sign "Mac Developer" --deep target/Library/Security/tokend/OpenSC.tokend
---
 configure.ac                          |  35 ++-
 etc/opensc.conf.in                    |  13 +-
 src/libopensc/Makefile.am             |  12 +
 src/libopensc/ctx.c                   |   2 +
 src/libopensc/internal.h              |   1 +
 src/libopensc/reader-cryptotokenkit.m | 424 ++++++++++++++++++++++++++++++++++
 6 files changed, 483 insertions(+), 4 deletions(-)

diff --git a/configure.ac b/configure.ac
index 4c6b9ff..182bb69 100644
--- a/configure.ac
+++ b/configure.ac
@@ -58,6 +58,7 @@ AC_CANONICAL_HOST
 AC_PROG_CC
 # AC_PROG_CXX is needed to built the win32 custom action. Indeed dutil.h use [extern "C"] definition which fails on pure c compiler
 AC_PROG_CXX
+AC_PROG_OBJC
 PKG_PROG_PKG_CONFIG
 AC_C_BIGENDIAN
 
@@ -196,6 +197,13 @@ AC_ARG_ENABLE(
 )
 
 AC_ARG_ENABLE(
+	[cryptotokenkit],
+	[AS_HELP_STRING([--disable-cryptotokenkit],[disable CryptoTokenKit support @<:@enabled@:>@])],
+	,
+	[enable_cryptotokenkit="no"]
+)
+
+AC_ARG_ENABLE(
 	[ctapi],
 	[AS_HELP_STRING([--enable-ctapi],[enable CT-API support @<:@disabled@:>@])],
 	,
@@ -267,11 +275,11 @@ AC_ARG_WITH(
 
 dnl ./configure check
 reader_count=""
-for rdriver in "${enable_pcsc}" "${enable_openct}" "${enable_ctapi}"; do
+for rdriver in "${enable_pcsc}" "${enable_cryptotokenkit}" "${enable_openct}" "${enable_ctapi}"; do
 	test "${rdriver}" = "yes" && reader_count="${reader_count}x"
 done
 if test "${reader_count}" != "x"; then
-	AC_MSG_ERROR([Only one of --enable-pcsc, --enable-openct, --enable-ctapi can be specified!])
+	AC_MSG_ERROR([Only one of --enable-pcsc, --enable-cryptotokenkit, --enable-openct, --enable-ctapi can be specified!])
 fi
 
 dnl Checks for programs.
@@ -711,6 +719,22 @@ if test "${enable_pcsc}" = "yes"; then
 	AC_DEFINE([ENABLE_PCSC], [1], [Define if PC/SC is to be enabled])
 fi
 
+if test "${enable_cryptotokenkit}" = "yes"; then
+	if test -z "${CRYPTOTOKENKIT_CFLAGS}"; then
+		case "${host}" in
+			*-apple-*)
+				CRYPTOTOKENKIT_CFLAGS="-framework CryptoTokenKit -framework Foundation"
+				LDFLAGS="${LDFLAGS} -framework CryptoTokenKit -framework Foundation"
+			;;
+			*)
+				AC_MSG_ERROR([CryptoTokenKit only supported on Darwin])
+			;;
+		esac
+	fi
+	AC_DEFINE([ENABLE_CRYPTOTOKENKIT], [1], [Define if CryptoTokenKit is to be enabled])
+fi
+
+
 AC_SUBST(DYN_LIB_EXT)
 AC_SUBST(LIBDIR)
 AC_SUBST(LIB_PRE)
@@ -803,6 +827,9 @@ if test "${enable_pcsc}" = "yes"; then
 	OPENSC_FEATURES="${OPENSC_FEATURES} pcsc(${DEFAULT_PCSC_PROVIDER})"
 	OPTIONAL_PCSC_CFLAGS="${PCSC_CFLAGS}"
 fi
+if test "${enable_cryptotokenkit}" = "yes"; then
+	OPTIONAL_CRYPTOTOKENKIT_CFLAGS="${CRYPTOTOKENKIT_CFLAGS}"
+fi
 if test "${enable_ctapi}" = "yes"; then
 	OPENSC_FEATURES="${OPENSC_FEATURES} ctapi"
 fi
@@ -878,7 +905,7 @@ AM_CONDITIONAL([ENABLE_THREAD_LOCKING], [test "${enable_thread_locking}" = "yes"
 AM_CONDITIONAL([ENABLE_ZLIB], [test "${enable_zlib}" = "yes"])
 AM_CONDITIONAL([ENABLE_READLINE], [test "${enable_readline}" = "yes"])
 AM_CONDITIONAL([ENABLE_OPENSSL], [test "${enable_openssl}" = "yes"])
-AM_CONDITIONAL([ENABLE_OPENCT], [test "${enable_openct}" = "yes"])
+AM_CONDITIONAL([ENABLE_CRYPTOTOKENKIT], [test "${enable_cryptotokenkit}" = "yes"])
 AM_CONDITIONAL([ENABLE_DOC], [test "${enable_doc}" = "yes"])
 AM_CONDITIONAL([WIN32], [test "${WIN32}" = "yes"])
 AM_CONDITIONAL([CYGWIN], [test "${CYGWIN}" = "yes"])
@@ -970,6 +997,7 @@ zlib support:            ${enable_zlib}
 readline support:        ${enable_readline}
 OpenSSL support:         ${enable_openssl}
 PC/SC support:           ${enable_pcsc}
+CryptoTokenKit support:  ${enable_cryptotokenkit}
 OpenCT support:          ${enable_openct}
 CT-API support:          ${enable_ctapi}
 minidriver support:      ${enable_minidriver}
@@ -999,6 +1027,7 @@ OPENPACE_LIBS:           ${OPENPACE_LIBS}
 OPENCT_CFLAGS:           ${OPENCT_CFLAGS}
 OPENCT_LIBS:             ${OPENCT_LIBS}
 PCSC_CFLAGS:             ${PCSC_CFLAGS}
+CRYPTOTOKENKIT_CFLAGS:   ${CRYPTOTOKENKIT_CFLAGS}
 
 EOF
 
diff --git a/etc/opensc.conf.in b/etc/opensc.conf.in
index 237c128..239c44c 100644
--- a/etc/opensc.conf.in
+++ b/etc/opensc.conf.in
@@ -124,7 +124,18 @@ app default {
 		# Default: n/a
 		# max_send_size = 255;
 		# max_recv_size = 256;
-	};
+	}
+
+	# Options for CryptoTokenKit support
+	reader_driver cryptotokenkit {
+		# Limit command and response sizes. Some Readers don't propagate their
+		# transceive capabilities correctly. max_send_size and max_recv_size
+		# allow setting the limits manually, for example to enable extended
+		# length capabilities.
+		# Default: autodetect
+		# max_send_size = 65535;
+		# max_recv_size = 65536;
+	}
 
 	# Whitelist of card drivers to load at start-up
 	#
diff --git a/src/libopensc/Makefile.am b/src/libopensc/Makefile.am
index 1f6d07a..269cbf0 100644
--- a/src/libopensc/Makefile.am
+++ b/src/libopensc/Makefile.am
@@ -18,6 +18,7 @@ AM_CPPFLAGS = -DOPENSC_CONF_PATH=\"$(sysconfdir)/opensc.conf\" \
 	-I$(top_srcdir)/src
 AM_CFLAGS = $(OPENPACE_CFLAGS) $(OPTIONAL_OPENSSL_CFLAGS) $(OPTIONAL_OPENCT_CFLAGS) \
 	$(OPTIONAL_PCSC_CFLAGS) $(OPTIONAL_ZLIB_CFLAGS)
+AM_OBJCFLAGS = $(AM_CFLAGS)
 
 libopensc_la_SOURCES_BASE = \
 	sc.c ctx.c log.c errors.c \
@@ -55,9 +56,20 @@ libopensc_la_SOURCES_BASE = \
 	pkcs15-dnie.c pkcs15-gids.c pkcs15-iasecc.c pkcs15-jpki.c \
 	compression.c p15card-helper.c sm.c \
 	aux-data.c
+
+if ENABLE_CRYPTOTOKENKIT
+# most platforms don't support objective C the way we needed.
+# Only include it if needed
+libopensc_la_SOURCES_BASE += reader-cryptotokenkit.m
+else
+libopensc_la_LIBTOOLFLAGS = --tag CC
+libopensc_static_la_LIBTOOLFLAGS = --tag CC
+endif
+
 libopensc_la_SOURCES = $(libopensc_la_SOURCES_BASE) \
 	libopensc.exports
 libopensc_static_la_SOURCES = $(libopensc_la_SOURCES_BASE)
+
 if WIN32
 libopensc_la_SOURCES += $(top_builddir)/win32/versioninfo.rc
 endif
diff --git a/src/libopensc/ctx.c b/src/libopensc/ctx.c
index 6b08bd0..81a9bd7 100644
--- a/src/libopensc/ctx.c
+++ b/src/libopensc/ctx.c
@@ -797,6 +797,8 @@ int sc_context_create(sc_context_t **ctx_out, const sc_context_param_t *parm)
 	if(strcmp(ctx->app_name, "cardmod") == 0)
 		ctx->reader_driver = sc_get_cardmod_driver();
 #endif
+#elif defined(ENABLE_CRYPTOTOKENKIT)
+	ctx->reader_driver = sc_get_cryptotokenkit_driver();
 #elif defined(ENABLE_CTAPI)
 	ctx->reader_driver = sc_get_ctapi_driver();
 #elif defined(ENABLE_OPENCT)
diff --git a/src/libopensc/internal.h b/src/libopensc/internal.h
index efc076a..9ff27d8 100644
--- a/src/libopensc/internal.h
+++ b/src/libopensc/internal.h
@@ -257,6 +257,7 @@ extern struct sc_reader_driver *sc_get_pcsc_driver(void);
 extern struct sc_reader_driver *sc_get_ctapi_driver(void);
 extern struct sc_reader_driver *sc_get_openct_driver(void);
 extern struct sc_reader_driver *sc_get_cardmod_driver(void);
+extern struct sc_reader_driver *sc_get_cryptotokenkit_driver(void);
 
 #ifdef __cplusplus
 }
diff --git a/src/libopensc/reader-cryptotokenkit.m b/src/libopensc/reader-cryptotokenkit.m
new file mode 100644
index 0000000..cead041
--- /dev/null
+++ b/src/libopensc/reader-cryptotokenkit.m
@@ -0,0 +1,424 @@
+/*
+ * reader-cryptotokenkit.m: Reader driver for CryptoTokenKit interface
+ *
+ * Copyright (C) 2017 Frank Morgner <frankmorgner at gmail.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#ifdef ENABLE_CRYPTOTOKENKIT /* empty file without cryptotokenkit */
+
+#import <CryptoTokenKit/CryptoTokenKit.h>
+#include "internal.h"
+#include "log.h"
+#include "opensc.h"
+
+struct cryptotokenkit_private_data {
+	TKSmartCardSlot* tksmartcardslot;
+	TKSmartCard* tksmartcard;
+};
+
+static struct sc_reader_operations cryptotokenkit_ops;
+
+static struct sc_reader_driver cryptotokenkit_reader_driver = {
+	"CryptoTokenKit pseudo reader",
+	"cryptotokenkit",
+	&cryptotokenkit_ops,
+	NULL
+};
+
+static int cryptotokenkit_init(sc_context_t *ctx)
+{
+	return SC_SUCCESS;
+}
+
+static int cryptotokenkit_release(sc_reader_t *reader)
+{
+	struct cryptotokenkit_private_data *priv = reader->drv_data;
+
+	free(priv);
+	return SC_SUCCESS;
+}
+
+static int cryptotokenkit_detect_card_presence(sc_reader_t *reader)
+{
+	struct cryptotokenkit_private_data *priv = reader->drv_data;
+	int r = SC_SUCCESS;
+	int old_flags = reader->flags;
+
+	LOG_FUNC_CALLED(reader->ctx);
+
+	reader->flags &= ~(SC_READER_CARD_INUSE);
+
+	switch (priv->tksmartcardslot.state) {
+	 	case TKSmartCardSlotStateMuteCard:
+	  		// The card inserted in the slot does not answer.
+	  		r = SC_ERROR_CARD_UNRESPONSIVE;
+	  		// fall through */
+	 	case TKSmartCardSlotStateProbing:
+	  		// The card was inserted into the slot and an initial probe is in progress.
+	  		reader->flags |= SC_READER_CARD_INUSE;
+	  		// fall through */
+	 	case TKSmartCardSlotStateValidCard:
+	  		// Card properly answered to reset.
+	  		reader->flags |= SC_READER_CARD_PRESENT;
+	  		if ([priv->tksmartcardslot.ATR.bytes length] > SC_MAX_ATR_SIZE)
+	   			return SC_ERROR_INTERNAL;
+	  		reader->atr.len = [priv->tksmartcardslot.ATR.bytes length];
+	  		memcpy(reader->atr.value, (unsigned char*) [priv->tksmartcardslot.ATR.bytes bytes], reader->atr.len);
+	  		break;
+	 	case TKSmartCardSlotStateMissing:
+	  		// Slot is no longer known to the system.
+	  		reader->flags &= ~(SC_READER_CARD_PRESENT);
+	  		reader->flags |= SC_READER_REMOVED;
+	  		r = SC_ERROR_READER_DETACHED;
+	  		break;
+	 	case TKSmartCardSlotStateEmpty:
+	  		/// The slot is empty, no card is inserted.
+	  		reader->flags &= ~SC_READER_CARD_PRESENT;
+	  		break;
+	 	default:
+	  		r = SC_ERROR_UNKNOWN;
+	  		break;
+	}
+
+	if ((old_flags & SC_READER_CARD_PRESENT) == (reader->flags & SC_READER_CARD_PRESENT))
+	 	reader->flags &= ~SC_READER_CARD_CHANGED;
+	else
+	 	reader->flags |= SC_READER_CARD_CHANGED;
+
+	sc_log(reader->ctx, "card %s%s",
+			reader->flags & SC_READER_CARD_PRESENT ? "present" : "absent",
+		   reader->flags & SC_READER_CARD_CHANGED ? ", changed": "");
+
+	if (r == SC_SUCCESS)
+	 	r = reader->flags;
+
+	LOG_FUNC_RETURN(reader->ctx, r);
+}
+
+static int ctk_proto_to_opensc(TKSmartCardProtocol proto)
+{
+	switch (proto) {
+	   	case TKSmartCardProtocolT0:
+			return SC_PROTO_T0;
+	   	case TKSmartCardProtocolT1:
+			/* fall through */
+	   	case TKSmartCardProtocolT15:
+			return SC_PROTO_T1;
+	   	case TKSmartCardProtocolAny:
+			return SC_PROTO_ANY;
+	   	default:
+			return 0;
+	}
+}
+
+static void ctk_set_proto(sc_reader_t *reader)
+{
+ 	struct cryptotokenkit_private_data *priv = reader->drv_data;
+ 	if (priv->tksmartcard) {
+  		reader->active_protocol = ctk_proto_to_opensc(priv->tksmartcard.currentProtocol);
+  		if (priv->tksmartcard.allowedProtocols & TKSmartCardProtocolAny) {
+   			reader->supported_protocols = ctk_proto_to_opensc(TKSmartCardProtocolAny);
+  		} else {
+   			if (priv->tksmartcard.allowedProtocols & TKSmartCardProtocolT0)
+				reader->supported_protocols |= ctk_proto_to_opensc(TKSmartCardProtocolT0);
+   			if (priv->tksmartcard.allowedProtocols & TKSmartCardProtocolT1)
+				reader->supported_protocols |= ctk_proto_to_opensc(TKSmartCardProtocolT1);
+   			if (priv->tksmartcard.allowedProtocols & TKSmartCardProtocolT15)
+				reader->supported_protocols |= ctk_proto_to_opensc(TKSmartCardProtocolT1);
+  		}
+ 	}
+}
+
+static int cryptotokenkit_connect(sc_reader_t *reader)
+{
+	struct cryptotokenkit_private_data *priv = reader->drv_data;
+
+	if (!priv->tksmartcard) {
+		priv->tksmartcard = [priv->tksmartcardslot makeSmartCard];
+	}
+
+	if (!priv->tksmartcard || ![priv->tksmartcard valid])
+		return SC_ERROR_CARD_NOT_PRESENT;
+
+	/* attempt to detect protocol in use T0/T1/RAW */
+	ctk_set_proto(reader);
+
+	return SC_SUCCESS;
+}
+
+static int cryptotokenkit_disconnect(sc_reader_t * reader)
+{
+	struct cryptotokenkit_private_data *priv = reader->drv_data;
+
+	priv->tksmartcard = NULL;
+
+	reader->flags = 0;
+	return SC_SUCCESS;
+}
+
+static int cryptotokenkit_lock(sc_reader_t *reader)
+{
+	__block int r = SC_ERROR_NOT_ALLOWED;
+	struct cryptotokenkit_private_data *priv = reader->drv_data;
+	dispatch_semaphore_t sema = dispatch_semaphore_create(0);
+
+	LOG_FUNC_CALLED(reader->ctx);
+
+	if (reader->ctx->flags & SC_CTX_FLAG_TERMINATE)
+		goto err;
+
+	[priv->tksmartcard beginSessionWithReply:^(BOOL success, NSError *error) {
+		if (success != TRUE) {
+			NSLog(@"Error locking card <%@>", error);
+			r = SC_ERROR_UNKNOWN;
+		} else {
+			r = SC_SUCCESS;
+		}
+		dispatch_semaphore_signal(sema);
+	}];
+	dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);
+
+err:
+	LOG_FUNC_RETURN(reader->ctx, r);
+}
+
+static int cryptotokenkit_unlock(sc_reader_t *reader)
+{
+	struct cryptotokenkit_private_data *priv = reader->drv_data;
+
+	LOG_FUNC_CALLED(reader->ctx);
+
+	if (reader->ctx->flags & SC_CTX_FLAG_TERMINATE)
+		return SC_ERROR_NOT_ALLOWED;
+
+	[priv->tksmartcard endSession];
+
+	LOG_FUNC_RETURN(reader->ctx, SC_SUCCESS);
+}
+
+static int cryptotokenkit_transmit(sc_reader_t *reader, sc_apdu_t *apdu)
+{
+	size_t ssize = 0;
+	__block u8 *rbuf = NULL;
+	__block int r;
+	__block size_t rsize;
+	u8 *sbuf = NULL;
+	struct cryptotokenkit_private_data *priv = reader->drv_data;
+	dispatch_semaphore_t sema = dispatch_semaphore_create(0);
+
+	LOG_FUNC_CALLED(reader->ctx);
+
+	r = sc_apdu_get_octets(reader->ctx, apdu, &sbuf, &ssize, reader->active_protocol);
+	if (r != SC_SUCCESS)
+		goto err;
+
+	if (reader->name)
+		sc_log(reader->ctx, "reader '%s'", reader->name);
+	sc_apdu_log(reader->ctx, SC_LOG_DEBUG_NORMAL, sbuf, ssize, 1);
+
+	[priv->tksmartcard transmitRequest:
+			[NSData dataWithBytes: sbuf length: ssize]
+			reply:^(NSData *response, NSError *error) {
+		if (response) {
+			rsize = [response length];
+			rbuf = malloc(rsize);
+			if (!rbuf)
+				r = SC_ERROR_OUT_OF_MEMORY;
+			else
+				memcpy(rbuf, (unsigned char*) [response bytes], rsize);
+		}
+		if (r == SC_SUCCESS) {
+			if (error) {
+				NSLog(@"Error transmitting to card <%@>", error);
+				r = SC_ERROR_TRANSMIT_FAILED;
+			} else {
+				r = SC_SUCCESS;
+			}
+		}
+		dispatch_semaphore_signal(sema);
+	}];
+	dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);
+	if (r != SC_SUCCESS)
+		goto err;
+
+	sc_apdu_log(reader->ctx, SC_LOG_DEBUG_NORMAL, rbuf, rsize, 0);
+	r = sc_apdu_set_resp(reader->ctx, apdu, rbuf, rsize);
+
+err:
+	if (sbuf != NULL) {
+		sc_mem_clear(sbuf, ssize);
+		free(sbuf);
+	}
+	if (rbuf != NULL) {
+		sc_mem_clear(rbuf, rsize);
+		free(rbuf);
+	}
+
+	LOG_FUNC_RETURN(reader->ctx, r);
+}
+
+int cryptotokenkit_use_reader(sc_context_t *ctx, void *pcsc_context_handle, void *pcsc_card_handle)
+{
+	int r;
+	struct cryptotokenkit_private_data *priv;
+	sc_reader_t *reader = NULL;
+	scconf_block *conf_block = NULL;
+	TKSmartCardSlot* tksmartcardslot = (__bridge TKSmartCardSlot *)(pcsc_context_handle);
+	TKSmartCard* tksmartcard = (__bridge TKSmartCard *)(pcsc_card_handle);
+	const char* utf8String;
+
+	if (!pcsc_context_handle) {
+		if (!pcsc_card_handle)
+			return SC_ERROR_INVALID_ARGUMENTS;
+		tksmartcardslot = tksmartcard.slot;
+	}
+
+	if ((reader = calloc(1, sizeof(sc_reader_t))) == NULL) {
+		r = SC_ERROR_OUT_OF_MEMORY;
+		goto err;
+	}
+	if ((priv = calloc(1, sizeof(struct cryptotokenkit_private_data))) == NULL) {
+		r = SC_ERROR_OUT_OF_MEMORY;
+		goto err;
+	}
+	[priv->tksmartcard autorelease];
+	priv->tksmartcard = [tksmartcard retain];
+	[priv->tksmartcardslot autorelease];
+	priv->tksmartcardslot = [tksmartcardslot retain];
+
+	reader->drv_data = priv;
+	reader->ops = &cryptotokenkit_ops;
+	reader->driver = &cryptotokenkit_reader_driver;
+	utf8String = [tksmartcardslot.name UTF8String];
+	if ((reader->name = strdup(utf8String)) == NULL) {
+		r = SC_ERROR_OUT_OF_MEMORY;
+		goto err;
+	}
+
+	/* By testing we found that maxInputLength/maxOutputLength are
+	 * most likely initialized badly. We still take this value as is
+	 * and leave it up to the user to overwrite the reader's
+	 * capabilities */
+	reader->max_send_size = tksmartcardslot.maxInputLength;
+	reader->max_recv_size = tksmartcardslot.maxOutputLength;
+
+	conf_block = sc_get_conf_block(ctx, "reader_driver", "cryptotokenkit", 1);
+	if (conf_block) {
+		reader->max_send_size = scconf_get_int(conf_block, "max_send_size", reader->max_send_size);
+		reader->max_recv_size = scconf_get_int(conf_block, "max_recv_size", reader->max_recv_size);
+	}
+
+	/* attempt to detect protocol in use T0/T1/RAW */
+	ctk_set_proto(reader);
+
+	r = _sc_add_reader(ctx, reader);
+
+err:
+	if (r != SC_SUCCESS) {
+		free(priv);
+		if (reader != NULL) {
+			free(reader->name);
+			free(reader->vendor);
+			free(reader);
+		}
+	}
+
+	return r;
+}
+
+static int cryptotokenkit_detect_readers(sc_context_t *ctx)
+{
+	size_t i;
+	int r;
+	TKSmartCardSlotManager *mngr = [TKSmartCardSlotManager defaultManager];
+
+	LOG_FUNC_CALLED(ctx);
+
+	if (!mngr) {
+	 	/* com.apple.security.smartcard entitlement is disabled */
+	 	r = SC_ERROR_NOT_ALLOWED;
+	 	goto err;
+	}
+
+	/* temporarily mark all readers as removed */
+	for (i=0; i < sc_ctx_get_reader_count(ctx); i++) {
+		sc_reader_t *reader = sc_ctx_get_reader(ctx, i);
+		reader->flags |= SC_READER_REMOVED;
+	}
+
+	sc_log(ctx, "Probing CryptoTokenKit readers");
+
+	for (NSString *slotName in [mngr slotNames]) {
+		sc_reader_t *old_reader;
+		int found = 0;
+		const char *reader_name = [slotName UTF8String];
+		dispatch_semaphore_t sema = dispatch_semaphore_create(0);
+
+		for (i=0; i < sc_ctx_get_reader_count(ctx) && !found; i++) {
+			old_reader = sc_ctx_get_reader(ctx, i);
+			if (old_reader == NULL) {
+				r = SC_ERROR_INTERNAL;
+				goto err;
+			}
+			if (!strcmp(old_reader->name, reader_name)) {
+				found = 1;
+			}
+		}
+
+		/* Reader already available, skip */
+		if (found) {
+			old_reader->flags &= ~SC_READER_REMOVED;
+			continue;
+		}
+
+		sc_log(ctx, "Found new CryptoTokenKit reader '%s'", reader_name);
+		[mngr getSlotWithName:slotName reply:^(TKSmartCardSlot *slot) {
+			cryptotokenkit_use_reader(ctx, slot, NULL);
+		 	dispatch_semaphore_signal(sema);
+		}];
+		dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);
+	}
+
+	r = SC_SUCCESS;
+
+err:
+	LOG_FUNC_RETURN(ctx, r);
+}
+
+struct sc_reader_driver *sc_get_cryptotokenkit_driver(void)
+{
+	cryptotokenkit_ops.init = cryptotokenkit_init;
+	cryptotokenkit_ops.finish = NULL;
+	cryptotokenkit_ops.release = cryptotokenkit_release;
+	cryptotokenkit_ops.detect_card_presence = cryptotokenkit_detect_card_presence;
+	cryptotokenkit_ops.connect = cryptotokenkit_connect;
+	cryptotokenkit_ops.disconnect = cryptotokenkit_disconnect;
+	cryptotokenkit_ops.lock = cryptotokenkit_lock;
+	cryptotokenkit_ops.unlock = cryptotokenkit_unlock;
+	cryptotokenkit_ops.transmit = cryptotokenkit_transmit;
+	cryptotokenkit_ops.perform_verify = NULL;
+	cryptotokenkit_ops.perform_pace = NULL;
+	cryptotokenkit_ops.use_reader = cryptotokenkit_use_reader;
+	cryptotokenkit_ops.detect_readers = cryptotokenkit_detect_readers;
+
+	return &cryptotokenkit_reader_driver;
+}
+#endif

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-opensc/opensc.git



More information about the pkg-opensc-commit mailing list