diff --git a/npa/Makefile.am b/npa/Makefile.am index 03ed334..4109515 100644 --- a/npa/Makefile.am +++ b/npa/Makefile.am @@ -1,7 +1,7 @@ ACLOCAL_AMFLAGS = -I m4 SUBDIRS = src m4 doc cross certs -EXTRA_DIST = libnpa.pc.in apdus test_vicc_with_npa-tool.sh +EXTRA_DIST = libnpa.pc.in opensc.conf.in apdus test_vicc_with_npa-tool.sh do_subst = $(SED) \ -e 's,[@]PACKAGE_NAME[@],$(PACKAGE_NAME),g' \ @@ -11,6 +11,7 @@ do_subst = $(SED) \ -e 's,[@]prefix[@],$(prefix),g' \ -e 's,[@]exec_prefix[@],$(exec_prefix),g' \ -e 's,[@]libdir[@],$(libdir),g' \ + -e 's,[@]DYN_LIB_EXT[@],$(DYN_LIB_EXT),g' \ -e 's,[@]includedir[@],$(includedir),g' \ -e 's,[@]VERSION[@],$(VERSION),g' \ -e 's,[@]OPENSC_LIBS[@],$(OPENSC_LIBS),g' \ @@ -21,14 +22,19 @@ pkgconfig_DATA = libnpa.pc libnpa.pc: libnpa.pc.in $(do_subst) < $(srcdir)/libnpa.pc.in > libnpa.pc +opensc.conf: opensc.conf.in + $(do_subst) < $(srcdir)/opensc.conf.in > opensc.conf + win: make -C cross $@ android: make -C cross $@ +all-local: opensc.conf + clean-local: - rm -f libnpa.pc + rm -f libnpa.pc opensc.conf distcheck-hook: test -d .svn && \ diff --git a/npa/configure.ac b/npa/configure.ac index d523cdf..409e609 100644 --- a/npa/configure.ac +++ b/npa/configure.ac @@ -62,6 +62,7 @@ AC_TRY_LINK_FUNC(iasecc_sm_external_authentication, [ AC_MSG_RESULT([yes]) ], [ AC_MSG_ERROR([Cannot link against libopensc with SM]) ]) AC_CHECK_FUNCS([sc_apdu_get_octets]) +AC_CHECK_FUNCS([_sc_match_atr]) CPPFLAGS="$saved_CPPFLAGS" LIBS="$saved_LIBS" @@ -161,6 +162,30 @@ AC_FUNC_MALLOC AC_FUNC_REALLOC AC_CHECK_FUNCS([getline memmove memset strerror gettimeofday strtol]) +AC_SUBST(DYN_LIB_EXT) +case "$host" in +*-*-darwin*) + DYN_LIB_EXT="dylib" + ;; +*-*-freebsd*) + DYN_LIB_EXT="so" + ;; +*-*-openbsd*) + DYN_LIB_EXT="so.0.0" + ;; +*-*-solaris*) + DYN_LIB_EXT="so" + ;; +*-*-dragonfly*) + DYN_LIB_EXT="so" + ;; +*-*-cygwin*) + DYN_LIB_EXT="dll" + ;; +*) + DYN_LIB_EXT="so" +esac + cat << EOF ${PACKAGE} has been configured with following options: diff --git a/npa/opensc.conf.in b/npa/opensc.conf.in new file mode 100644 index 0000000..a33cd95 --- /dev/null +++ b/npa/opensc.conf.in @@ -0,0 +1,23 @@ +app default { + + # What card drivers to load at start-up + # + # A special value of 'internal' will load all + # statically linked drivers. If an unknown (ie. not + # internal) driver is supplied, a separate configuration + # configuration block has to be written for the driver. + # Default: internal + # NOTE: When "internal" keyword is used, must be last entry + # + card_drivers = npa, internal; + + # Card driver configuration blocks. + # + # For card drivers loaded from an external shared library/DLL, + # you need to specify the path name of the module + # + card_driver npa { + # The location of the driver library + module = @libdir@/libcardnpa.@DYN_LIB_EXT@; + # } +} diff --git a/npa/src/Makefile.am b/npa/src/Makefile.am index 00cb360..fe9807a 100644 --- a/npa/src/Makefile.am +++ b/npa/src/Makefile.am @@ -11,7 +11,7 @@ do_subst = $(SED) \ BUILT_SOURCES = cmdline.h cmdline.c -EXTRA_DIST = npa-tool.ggo npa-tool.ggo.in opensc/src/libopensc/apdu.c +EXTRA_DIST = npa-tool.ggo npa-tool.ggo.in opensc/src/libopensc/apdu.c opensc/src/libopensc/card.c EXTRA_DIST += $(shell find -L $(top_srcdir)/src/opensc/src -path '*/.git' -prune -o -type f -a -name '*.h' -print) MAINTAINERCLEANFILES = $(BUILT_SOURCES) npa-tool.ggo $(dist_man1_MANS) @@ -22,6 +22,11 @@ libnpa_la_LIBADD = $(OPENSC_LIBS) $(OPENPACE_LIBS) $(OPENSSL_LIBS) libnpa_la_CFLAGS = $(OPENSSL_CFLAGS) $(OPENPACE_CFLAGS) $(OPENSC_CFLAGS) libnpa_la_LDFLAGS = -no-undefined +libcardnpa_la_SOURCES = card-npa.c +libcardnpa_la_LIBADD = $(OPENSC_LIBS) libnpa.la +libcardnpa_la_CFLAGS = $(OPENSSL_CFLAGS) $(OPENPACE_CFLAGS) $(OPENSC_CFLAGS) +libcardnpa_la_LDFLAGS = -no-undefined + npa_tool_SOURCES = npa-tool.c $(BUILT_SOURCES) npa_tool_LDADD = libnpa.la $(OPENSC_LIBS) $(OPENPACE_LIBS) $(OPENSSL_LIBS) npa_tool_CFLAGS = $(OPENSSL_CFLAGS) $(OPENPACE_CFLAGS) $(OPENSC_CFLAGS) @@ -51,10 +56,11 @@ npa-tool.1: npa-tool.ggo bin_PROGRAMS = npa-tool noinst_PROGRAMS = example -lib_LTLIBRARIES = libnpa.la +lib_LTLIBRARIES = libnpa.la libcardnpa.la noinst_HEADERS = \ sslutil.h \ + iso-sm-internal.h \ ccid-types.h nobase_include_HEADERS = \ diff --git a/npa/src/card-npa.c b/npa/src/card-npa.c new file mode 100644 index 0000000..bb4e79f --- /dev/null +++ b/npa/src/card-npa.c @@ -0,0 +1,98 @@ +/* + * card-npa.c: Recognize known German identity cards + * + * Copyright (C) 2011-2012 Frank Morgner + * + * 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 + */ + +#include "iso-sm-internal.h" +#include "libopensc/internal.h" +#include + +#ifndef HAVE_SC_APDU_GET_OCTETS +#include "libopensc/card.c" +#endif + +enum { + SC_CARD_TYPE_NPA = 42000, + SC_CARD_TYPE_NPA_TEST, + SC_CARD_TYPE_NPA_ONLINE, +}; + +static struct sc_atr_table npa_atrs[] = { + {"3B:8A:80:01:80:31:F8:73:F7:41:E0:82:90:00:75", NULL, "German ID card (neuer Personalausweis, nPA)", SC_CARD_TYPE_NPA, 0, NULL}, + {"3B:84:80:01:00:00:90:00:95", NULL, "German ID card (Test neuer Personalausweis)", SC_CARD_TYPE_NPA_TEST, 0, NULL}, + {"3B:88:80:01:00:E1:F3:5E:13:77:83:00:00", "FF:FF:FF:FF:00:FF:FF:FF:FF:FF:FF:FF:00", "German ID card (Test Online-Ausweisfunktion)", SC_CARD_TYPE_NPA_ONLINE, 0, NULL}, + {NULL, NULL, NULL, 0, 0, NULL} +}; + +static struct sc_card_operations npa_ops; +static struct sc_card_driver npa_drv = { + "German ID card (neuer Personalausweis, nPA)", + "npa", + &npa_ops, + NULL, 0, NULL +}; + + +static int npa_match_card(sc_card_t * card) +{ + if (_sc_match_atr(card, npa_atrs, &card->type) < 0) + return 0; + return 1; +} + +static int npa_init(sc_card_t * card) +{ + card->drv_data = NULL; + card->caps |= SC_CARD_CAP_APDU_EXT | SC_CARD_CAP_RNG; + +#ifdef ENABLE_SM + card->sm_ctx.ops.get_sm_apdu = iso_get_sm_apdu; + card->sm_ctx.ops.free_sm_apdu = iso_free_sm_apdu; +#endif + + return SC_SUCCESS; +} + +static struct sc_card_driver *npa_get_driver(void) +{ + struct sc_card_driver *iso_drv = sc_get_iso7816_driver(); + + npa_ops = *iso_drv->ops; + npa_ops.match_card = npa_match_card; + npa_ops.init = npa_init; + + return &npa_drv; +} + +void *sc_module_init(const char *name) +{ + const char npa_name[] = "npa"; + if (name) { + if (strcmp(npa_name, name) == 0) + return npa_get_driver; + } + return NULL; +} + +const char *sc_driver_version(void) +{ + /* Tested with OpenSC 0.12 and 0.13.0, which can't be captured by checking + * our version info against OpenSC's PACKAGE_VERSION. For this reason we + * tell OpenSC that everything is fine, here. */ + return sc_get_version(); +} diff --git a/npa/src/iso-sm-internal.h b/npa/src/iso-sm-internal.h new file mode 100644 index 0000000..609d222 --- /dev/null +++ b/npa/src/iso-sm-internal.h @@ -0,0 +1,90 @@ +/* + * Copyright (C) 2014 Frank Morgner + * + * This file is part of npa. + * + * npa is free software: you can redistribute it and/or modify it under the + * terms of the GNU General Public License as published by the Free Software + * Foundation, either version 3 of the License, or (at your option) any later + * version. + * + * npa 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 General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License along with + * npa. If not, see . + */ +/** + * @file + * @defgroup sm Interface to Secure Messaging (SM) defined in ISO 7816 + * @{ + */ +#ifndef _CCID_SM_INTERNAL_H +#define _CCID_SM_INTERNAL_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + + + +/* @brief Protect an APDU with Secure Messaging + * + * If secure messaging (SM) is activated in \a sctx and \a apdu is not already + * SM protected, \a apdu is processed with the following steps: + * \li call to \a sctx->pre_transmit + * \li encrypt \a apdu calling \a sctx->encrypt + * \li authenticate \a apdu calling \a sctx->authenticate + * \li copy the SM protected data to \a sm_apdu + * + * Data for authentication or encryption is always padded before the callback + * functions are called + * + * @param[in] card + * @param[in] apdu + * @param[in,out] sm_apdu + * + * @return \c SC_SUCCESS or error code if an error occurred + */ +int iso_get_sm_apdu(struct sc_card *card, struct sc_apdu *apdu, struct sc_apdu **sm_apdu); + +/* @brief Remove Secure Messaging from an APDU + * + * If secure messaging (SM) is activated in \a sctx and \a apdu is not already + * SM protected, \a apdu is processed with the following steps: + * \li verify SM protected \a apdu calling \a sctx->verify_authentication + * \li decrypt SM protected \a apdu calling \a sctx->decrypt + * \li copy decrypted/authenticated data and status bytes to \a apdu + * + * Callback functions must not remove padding. + * + * @param[in] card + * @param[in,out] apdu + * @param[in,out] sm_apdu will be freed when done. + * + * @return \c SC_SUCCESS or error code if an error occurred + */ +int iso_free_sm_apdu(struct sc_card *card, struct sc_apdu *apdu, struct sc_apdu **sm_apdu); + +/** + * @brief Cleans up allocated ressources of the ISO SM driver + * + * \c iso_sm_close() is designed as SM card operation. However, have in mind + * that this card operation is not called automatically for \c + * sc_disconnect_card() . + * + * @param[in] card + * + * @return \c SC_SUCCESS or error code if an error occurred + */ +int iso_sm_close(struct sc_card *card); + +#ifdef __cplusplus +} +#endif +#endif +/* @} */ diff --git a/npa/src/iso-sm.c b/npa/src/iso-sm.c index 7054c0f..4d12f50 100644 --- a/npa/src/iso-sm.c +++ b/npa/src/iso-sm.c @@ -20,6 +20,7 @@ #include "config.h" #endif +#include "iso-sm-internal.h" #include #include #include @@ -27,57 +28,6 @@ #include #include -/* @brief Protect an APDU with Secure Messaging - * - * If secure messaging (SM) is activated in \a sctx and \a apdu is not already - * SM protected, \a apdu is processed with the following steps: - * \li call to \a sctx->pre_transmit - * \li encrypt \a apdu calling \a sctx->encrypt - * \li authenticate \a apdu calling \a sctx->authenticate - * \li copy the SM protected data to \a sm_apdu - * - * Data for authentication or encryption is always padded before the callback - * functions are called - * - * @param[in] card - * @param[in] apdu - * @param[in,out] sm_apdu - * - * @return \c SC_SUCCESS or error code if an error occurred - */ -static int iso_get_sm_apdu(struct sc_card *card, struct sc_apdu *apdu, struct sc_apdu **sm_apdu); - -/* @brief Remove Secure Messaging from an APDU - * - * If secure messaging (SM) is activated in \a sctx and \a apdu is not already - * SM protected, \a apdu is processed with the following steps: - * \li verify SM protected \a apdu calling \a sctx->verify_authentication - * \li decrypt SM protected \a apdu calling \a sctx->decrypt - * \li copy decrypted/authenticated data and status bytes to \a apdu - * - * Callback functions must not remove padding. - * - * @param[in] card - * @param[in,out] apdu - * @param[in,out] sm_apdu will be freed when done. - * - * @return \c SC_SUCCESS or error code if an error occurred - */ -static int iso_free_sm_apdu(struct sc_card *card, struct sc_apdu *apdu, struct sc_apdu **sm_apdu); - -/** - * @brief Cleans up allocated ressources of the ISO SM driver - * - * \c iso_sm_close() is designed as SM card operation. However, have in mind - * that this card operation is not called automatically for \c - * sc_disconnect_card() . - * - * @param[in] card - * - * @return \c SC_SUCCESS or error code if an error occurred - */ -static int iso_sm_close(struct sc_card *card); - static const struct sc_asn1_entry c_sm_capdu[] = { { "Padding-content indicator followed by cryptogram", SC_ASN1_OCTET_STRING, SC_ASN1_CTX|0x07, SC_ASN1_OPTIONAL, NULL, NULL },