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
This commit is contained in:
parent
70313512ad
commit
013bdcb264
35
configure.ac
35
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
|
||||
|
||||
|
@ -195,6 +196,13 @@ AC_ARG_ENABLE(
|
|||
[enable_pcsc="yes"]
|
||||
)
|
||||
|
||||
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
|
||||
|
||||
|
|
|
@ -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
|
||||
#
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -0,0 +1,424 @@
|
|||
/*
|
||||
* reader-cryptotokenkit.m: Reader driver for CryptoTokenKit interface
|
||||
*
|
||||
* Copyright (C) 2017 Frank Morgner <frankmorgner@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
|
Loading…
Reference in New Issue