switched to opensc.0.12.0. note that this has some issues when linking against both libnpa and the opensc libraries at the same time. readme information would be usefull for this...

git-svn-id: https://vsmartcard.svn.sourceforge.net/svnroot/vsmartcard@385 96b47cad-a561-4643-ad3b-153ac7d7599c
This commit is contained in:
frankmorgner
2011-01-14 14:24:04 +00:00
parent b891483a19
commit 79dc468cc5
14 changed files with 350 additions and 393 deletions

View File

@@ -19,21 +19,6 @@ AM_PROG_CC_C_O
PKG_PROG_PKG_CONFIG PKG_PROG_PKG_CONFIG
# Checks for libraries. # Checks for libraries.
PKG_CHECK_EXISTS([libopensc],
[PKG_CHECK_MODULES([OPENSC], [libopensc < 0.12])],
[AC_MSG_WARN([libopensc < 0.12 not found by pkg-config])])
saved_CPPFLAGS="$CPPFLAGS"
saved_LIBS="$LIBS"
CPPFLAGS="$CPPFLAGS $OPENSC_CFLAGS"
LIBS="$LDFLAGS $OPENSC_LIBS"
AC_CHECK_HEADERS(opensc/opensc.h,,
[ AC_MSG_ERROR([opensc/opensc.h not found, install libopensc < 0.12 or use ./configure OPENSC_CFLAGS=...]) ])
AC_MSG_CHECKING([for sc_context_create])
AC_TRY_LINK_FUNC(sc_context_create, [ AC_MSG_RESULT([yes]) ],
[ AC_MSG_ERROR([libopensc < 0.12 not found, use ./configure OPENSC_LIBS=...]) ])
CPPFLAGS="$saved_CPPFLAGS"
LIBS="$saved_LIBS"
# --disable-ccid # --disable-ccid
AC_ARG_ENABLE(ccid, AC_ARG_ENABLE(ccid,
@@ -92,7 +77,7 @@ if test "x$enable_pace" != xno ; then
[AC_MSG_WARN([libpace not found by pkg-config])]) [AC_MSG_WARN([libpace not found by pkg-config])])
saved_CPPFLAGS="$CPPFLAGS" saved_CPPFLAGS="$CPPFLAGS"
saved_LIBS="$LIBS" saved_LIBS="$LIBS"
CPPFLAGS="$CPPFLAGS $LIBPACE_CFLAGS" CPPFLAGS="$CPPFLAGS $LIBPACE_CFLAGS -I$(pwd)/src/opensc-0.12.0/src"
LIBS="$LDFLAGS $LIBPACE_LIBS" LIBS="$LDFLAGS $LIBPACE_LIBS"
AC_CHECK_HEADERS(pace/pace.h, [], [ AC_MSG_ERROR([pace/pace.h not found, install libpace or use ./configure LIBPACE_CFLAGS=...]) ]) AC_CHECK_HEADERS(pace/pace.h, [], [ AC_MSG_ERROR([pace/pace.h not found, install libpace or use ./configure LIBPACE_CFLAGS=...]) ])
AC_MSG_CHECKING([for EstablishPACEChannel]) AC_MSG_CHECKING([for EstablishPACEChannel])
@@ -126,7 +111,7 @@ if test "x$enable_cats" != xno ; then
AC_CHECK_HEADERS(reader.h, [AC_DEFINE(HAVE_READER_H, 1, [use reader.h from PC/SC Lite])], []) AC_CHECK_HEADERS(reader.h, [AC_DEFINE(HAVE_READER_H, 1, [use reader.h from PC/SC Lite])], [])
AC_CHECK_HEADERS(pcsclite.h, [AC_DEFINE(HAVE_PCSCLITE_H, 1, [use pcsclite.h from PC/SC Lite])], []) AC_CHECK_HEADERS(pcsclite.h, [AC_DEFINE(HAVE_PCSCLITE_H, 1, [use pcsclite.h from PC/SC Lite])], [])
AC_CHECK_DECL(FEATURE_EXECUTE_PACE, [], AC_CHECK_DECL(FEATURE_EXECUTE_PACE, [],
[AC_MSG_ERROR([libpcsclite > 1.4.102 patched with pcsclite_trunk.patch not found, use ./configure PCSC_LIBS=...]) ], [AC_MSG_WARN([libpcsclite > 1.4.102 patched with pcsclite_trunk.patch not found]) ],
[#include <reader.h>]) [#include <reader.h>])
AC_MSG_CHECKING([for SCardEstablishContext]) AC_MSG_CHECKING([for SCardEstablishContext])
AC_TRY_LINK_FUNC(SCardEstablishContext, [ AC_MSG_RESULT([yes]) ], AC_TRY_LINK_FUNC(SCardEstablishContext, [ AC_MSG_RESULT([yes]) ],
@@ -188,8 +173,6 @@ Linker flags: ${LDFLAGS}
Libraries: ${LIBS} Libraries: ${LIBS}
PTHREAD_CFLAGS: ${PTHREAD_CFLAGS} PTHREAD_CFLAGS: ${PTHREAD_CFLAGS}
PTHREAD_LIBS: ${PTHREAD_LIBS} PTHREAD_LIBS: ${PTHREAD_LIBS}
OPENSC_CFLAGS: ${OPENSC_CFLAGS}
OPENSC_LIBS: ${OPENSC_LIBS}
OPENSSL_CFLAGS: ${OPENSSL_CFLAGS} OPENSSL_CFLAGS: ${OPENSSL_CFLAGS}
OPENSSL_LIBS: ${OPENSSL_LIBS} OPENSSL_LIBS: ${OPENSSL_LIBS}
LIBPACE_CFLAGS: ${LIBPACE_CFLAGS} LIBPACE_CFLAGS: ${LIBPACE_CFLAGS}

View File

@@ -1,3 +1,9 @@
OPENSCVERSION = 0.12.0
EXTRA_DIST = opensc-$(OPENSCVERSION)
AM_CPPFLAGS = -I$(top_srcdir)/src/opensc-$(OPENSCVERSION)/src
ccid_emulator_SOURCES = ccid.c usbstring.c usb.c binutil.c ccid_emulator_SOURCES = ccid.c usbstring.c usb.c binutil.c
ccid_emulator_LDADD = $(OPENSC_LIBS) $(OPENSSL_LIBS) $(PTHREAD_LIBS) ccid_emulator_LDADD = $(OPENSC_LIBS) $(OPENSSL_LIBS) $(PTHREAD_LIBS)
ccid_emulator_CFLAGS = $(OPENSC_CFLAGS) $(OPENSSL_CFLAGS) $(PTHREAD_CFLAGS) ccid_emulator_CFLAGS = $(OPENSC_CFLAGS) $(OPENSSL_CFLAGS) $(PTHREAD_CFLAGS)
@@ -15,6 +21,14 @@ noinst_HEADERS = \
ccid.h \ ccid.h \
usbstring.h usbstring.h
opensc: opensc-$(OPENSCVERSION)
cd $(top_builddir)/src && cp -r opensc-$(OPENSCVERSION) opensc
libopensc.la: opensc
cd $(top_builddir)/src/opensc && ./configure
$(MAKE) -C opensc
cp $(top_builddir)/src/opensc/src/libopensc/.libs/libopensc* $(top_builddir)/src
flaw: flaw:
flawfinder -SQD *.h *.c flawfinder -SQD *.h *.c
@@ -33,4 +47,5 @@ ccid_emulator_LDADD += $(LIBPACE_LIBS)
ccid_emulator_CFLAGS += $(LIBPACE_CFLAGS) ccid_emulator_CFLAGS += $(LIBPACE_CFLAGS)
else else
ccid_emulator_SOURCES += scutil.c ccid_emulator_SOURCES += scutil.c
ccid_emulator_LDADD += libopensc.la
endif endif

View File

@@ -16,15 +16,15 @@
* You should have received a copy of the GNU General Public License along with * You should have received a copy of the GNU General Public License along with
* ccid. If not, see <http://www.gnu.org/licenses/>. * ccid. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include <stdint.h>
#include <stdarg.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <asm/byteorder.h> #include <asm/byteorder.h>
#include <opensc/opensc.h> #include <libopensc/log.h>
#include <libopensc/opensc.h>
#include <openssl/evp.h> #include <openssl/evp.h>
#include <opensc/log.h> #include <stdarg.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "ccid.h" #include "ccid.h"
#include "config.h" #include "config.h"
@@ -45,11 +45,8 @@ static size_t ef_cardaccess_length = 0;
#endif #endif
static sc_context_t *ctx = NULL; static sc_context_t *ctx = NULL;
#ifdef BUERGERCLIENT_WORKAROUND #define SC_MAX_SLOTS 1
static sc_card_t *card_in_slot[1];
#else
static sc_card_t *card_in_slot[SC_MAX_SLOTS]; static sc_card_t *card_in_slot[SC_MAX_SLOTS];
#endif
static sc_reader_t *reader; static sc_reader_t *reader;
struct ccid_class_descriptor struct ccid_class_descriptor
@@ -98,35 +95,30 @@ ccid_desc = {
#define debug_sc_result(sc_result) \ #define debug_sc_result(sc_result) \
{ \ { \
if (sc_result < 0) \ if (sc_result < 0) \
sc_error(ctx, sc_strerror(sc_result)); \ sc_debug(ctx, SC_LOG_DEBUG_VERBOSE, sc_strerror(sc_result)); \
else \ else \
sc_debug(ctx, sc_strerror(sc_result)); \ sc_debug(ctx, SC_LOG_DEBUG_NORMAL, sc_strerror(sc_result)); \
} }
static int static int
detect_card_presence(int slot) detect_card_presence(void)
{ {
int sc_result; int sc_result;
if (slot >= sizeof card_in_slot/sizeof *card_in_slot ) sc_result = sc_detect_card_presence(reader);
return SC_ERROR_INVALID_ARGUMENTS;
sc_result = sc_detect_card_presence(reader, slot);
if (sc_result == 0 if (sc_result == 0
&& card_in_slot[slot] && card_in_slot[0]) {
&& sc_card_valid(card_in_slot[slot])) { sc_disconnect_card(card_in_slot[0]);
sc_disconnect_card(card_in_slot[slot], 0); sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "Card removed from slot 0");
sc_debug(ctx, "Card removed from slot %d", slot);
} }
if (sc_result & SC_SLOT_CARD_CHANGED) { if (sc_result & SC_READER_CARD_CHANGED) {
sc_disconnect_card(card_in_slot[slot], 0); sc_disconnect_card(card_in_slot[0]);
sc_debug(ctx, "Card exchanged in slot %d", slot); sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "Card exchanged in slot 0");
} }
if (sc_result & SC_SLOT_CARD_PRESENT if (sc_result & SC_READER_CARD_PRESENT
&& (!card_in_slot[slot] && !card_in_slot[0]) {
|| !sc_card_valid(card_in_slot[slot]))) { sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "Unused card in slot 0");
sc_debug(ctx, "Unused card in slot %d", slot);
} }
return sc_result; return sc_result;
@@ -144,7 +136,7 @@ int ccid_initialize(int reader_id, const char *cdriver, int verbose)
if (i < 0) if (i < 0)
return i; return i;
ccid_desc.bMaxSlotIndex = reader->slot_count - 1; ccid_desc.bMaxSlotIndex = 1;
#ifdef WITH_PACE #ifdef WITH_PACE
memset(&sctx, 0, sizeof(sctx)); memset(&sctx, 0, sizeof(sctx));
@@ -162,8 +154,8 @@ void ccid_shutdown()
{ {
int i; int i;
for (i = 0; i < sizeof card_in_slot/sizeof *card_in_slot; i++) { for (i = 0; i < sizeof card_in_slot/sizeof *card_in_slot; i++) {
if (card_in_slot[i] && sc_card_valid(card_in_slot[i])) { if (card_in_slot[i]) {
sc_disconnect_card(card_in_slot[i], 0); sc_disconnect_card(card_in_slot[i]);
} }
} }
if (ctx) if (ctx)
@@ -208,7 +200,7 @@ static int get_rapdu(sc_apdu_t *apdu, size_t slot, __u8 **buf, size_t *resplen)
} }
if (apdu->sw1 > 0xff || apdu->sw2 > 0xff || apdu->sw1 < 0 || apdu->sw2 < 0) { if (apdu->sw1 > 0xff || apdu->sw2 > 0xff || apdu->sw1 < 0 || apdu->sw2 < 0) {
sc_error(ctx, "Received invalid status bytes SW1=%d SW2=%d", apdu->sw1, apdu->sw2); sc_debug(ctx, SC_LOG_DEBUG_VERBOSE, "Received invalid status bytes SW1=%d SW2=%d", apdu->sw1, apdu->sw2);
sc_result = SC_ERROR_INVALID_DATA; sc_result = SC_ERROR_INVALID_DATA;
goto err; goto err;
} }
@@ -219,7 +211,7 @@ static int get_rapdu(sc_apdu_t *apdu, size_t slot, __u8 **buf, size_t *resplen)
*buf = apdu->resp; *buf = apdu->resp;
*resplen = apdu->resplen + sizeof(__u8) + sizeof(__u8); *resplen = apdu->resplen + sizeof(__u8) + sizeof(__u8);
sc_debug(ctx, "R-APDU, %d byte%s:\tsw1=%02x sw2=%02x", sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "R-APDU, %d byte%s:\tsw1=%02x sw2=%02x",
(unsigned int) *resplen, !*resplen ? "" : "s", (unsigned int) *resplen, !*resplen ? "" : "s",
apdu->sw1, apdu->sw2); apdu->sw1, apdu->sw2);
@@ -236,9 +228,6 @@ static __u8 get_bError(int sc_result)
case SC_SUCCESS: case SC_SUCCESS:
return CCID_BERROR_OK; return CCID_BERROR_OK;
case SC_ERROR_SLOT_ALREADY_CONNECTED:
return CCID_BERROR_CMD_SLOT_BUSY;
case SC_ERROR_KEYPAD_TIMEOUT: case SC_ERROR_KEYPAD_TIMEOUT:
return CCID_BERROR_PIN_TIMEOUT; return CCID_BERROR_PIN_TIMEOUT;
@@ -261,43 +250,41 @@ static __u8 get_bStatus(int sc_result, __u8 bSlot)
int flags; int flags;
__u8 bstatus = 0; __u8 bstatus = 0;
flags = detect_card_presence(bSlot); flags = detect_card_presence();
if (flags >= 0) { if (flags >= 0) {
if (sc_result < 0) { if (sc_result < 0) {
if (flags & SC_SLOT_CARD_PRESENT) { if (flags & SC_READER_CARD_PRESENT) {
if (flags & SC_SLOT_CARD_CHANGED if (flags & SC_READER_CARD_CHANGED
|| (card_in_slot[bSlot] || (card_in_slot[bSlot])) {
&& !sc_card_valid(card_in_slot[bSlot]))) { /*sc_debug(ctx, SC_LOG_DEBUG_NORMAL, SC_LOG_DEBUG_NORMAL, "error inactive");*/
/*sc_debug(ctx, "error inactive");*/
bstatus = CCID_BSTATUS_ERROR_INACTIVE; bstatus = CCID_BSTATUS_ERROR_INACTIVE;
} else { } else {
/*sc_debug(ctx, "error active");*/ /*sc_debug(ctx, SC_LOG_DEBUG_NORMAL, SC_LOG_DEBUG_NORMAL, "error active");*/
bstatus = CCID_BSTATUS_ERROR_ACTIVE; bstatus = CCID_BSTATUS_ERROR_ACTIVE;
} }
} else { } else {
/*sc_debug(ctx, "error no icc");*/ /*sc_debug(ctx, SC_LOG_DEBUG_NORMAL, SC_LOG_DEBUG_NORMAL, "error no icc");*/
bstatus = CCID_BSTATUS_ERROR_NOICC; bstatus = CCID_BSTATUS_ERROR_NOICC;
} }
} else { } else {
if (flags & SC_SLOT_CARD_PRESENT) { if (flags & SC_READER_CARD_PRESENT) {
if (flags & SC_SLOT_CARD_CHANGED || ( if (flags & SC_READER_CARD_CHANGED || (
card_in_slot[bSlot] card_in_slot[bSlot])) {
&& !sc_card_valid(card_in_slot[bSlot]))) { /*sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "ok inactive");*/
/*sc_debug(ctx, "ok inactive");*/
bstatus = CCID_BSTATUS_OK_INACTIVE; bstatus = CCID_BSTATUS_OK_INACTIVE;
} else { } else {
/*sc_debug(ctx, "ok active");*/ /*sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "ok active");*/
bstatus = CCID_BSTATUS_OK_ACTIVE; bstatus = CCID_BSTATUS_OK_ACTIVE;
} }
} else { } else {
/*sc_debug(ctx, "ok no icc");*/ /*sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "ok no icc");*/
bstatus = CCID_BSTATUS_OK_NOICC; bstatus = CCID_BSTATUS_OK_NOICC;
} }
} }
} else { } else {
debug_sc_result(flags); debug_sc_result(flags);
sc_error(ctx, "Could not detect card presence." sc_debug(ctx, SC_LOG_DEBUG_VERBOSE, "Could not detect card presence."
" Falling back to default (bStatus=0x%02X).", bstatus); " Falling back to default (bStatus=0x%02X).", bstatus);
} }
@@ -311,7 +298,7 @@ get_RDR_to_PC_SlotStatus(__u8 bSlot, __u8 bSeq, int sc_result, __u8 **outbuf, si
if (!outbuf) if (!outbuf)
return SC_ERROR_INVALID_ARGUMENTS; return SC_ERROR_INVALID_ARGUMENTS;
if (abProtocolDataStructureLen > 0xffff) { if (abProtocolDataStructureLen > 0xffff) {
sc_error(ctx, "abProtocolDataStructure %u bytes too long", sc_debug(ctx, SC_LOG_DEBUG_VERBOSE, "abProtocolDataStructure %u bytes too long",
abProtocolDataStructureLen-0xffff); abProtocolDataStructureLen-0xffff);
return SC_ERROR_INVALID_DATA; return SC_ERROR_INVALID_DATA;
} }
@@ -343,7 +330,7 @@ get_RDR_to_PC_DataBlock(__u8 bSlot, __u8 bSeq, int sc_result, __u8 **outbuf,
if (!outbuf) if (!outbuf)
return SC_ERROR_INVALID_ARGUMENTS; return SC_ERROR_INVALID_ARGUMENTS;
if (abDataLen > 0xffff) { if (abDataLen > 0xffff) {
sc_error(ctx, "abProtocolDataStructure %u bytes too long", sc_debug(ctx, SC_LOG_DEBUG_VERBOSE, "abProtocolDataStructure %u bytes too long",
abDataLen-0xffff); abDataLen-0xffff);
return SC_ERROR_INVALID_DATA; return SC_ERROR_INVALID_DATA;
} }
@@ -377,7 +364,7 @@ perform_PC_to_RDR_GetSlotStatus(const __u8 *in, size_t inlen, __u8 **out, size_t
return SC_ERROR_INVALID_ARGUMENTS; return SC_ERROR_INVALID_ARGUMENTS;
if (inlen < sizeof *request) if (inlen < sizeof *request)
SC_FUNC_RETURN(ctx, SC_LOG_TYPE_ERROR, SC_ERROR_INVALID_DATA); SC_FUNC_RETURN(ctx, SC_LOG_DEBUG_VERBOSE, SC_ERROR_INVALID_DATA);
*outlen = sizeof(RDR_to_PC_SlotStatus_t); *outlen = sizeof(RDR_to_PC_SlotStatus_t);
@@ -385,7 +372,7 @@ perform_PC_to_RDR_GetSlotStatus(const __u8 *in, size_t inlen, __u8 **out, size_t
request->dwLength != __constant_cpu_to_le32(0) || request->dwLength != __constant_cpu_to_le32(0) ||
request->abRFU1 != 0 || request->abRFU1 != 0 ||
request->abRFU2 != 0) request->abRFU2 != 0)
sc_debug(ctx, "warning: malformed PC_to_RDR_GetSlotStatus"); sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "warning: malformed PC_to_RDR_GetSlotStatus");
return get_RDR_to_PC_SlotStatus(request->bSlot, request->bSeq, SC_SUCCESS, return get_RDR_to_PC_SlotStatus(request->bSlot, request->bSeq, SC_SUCCESS,
out, outlen, NULL, 0); out, outlen, NULL, 0);
@@ -401,29 +388,28 @@ perform_PC_to_RDR_IccPowerOn(const __u8 *in, size_t inlen, __u8 **out, size_t *o
return SC_ERROR_INVALID_ARGUMENTS; return SC_ERROR_INVALID_ARGUMENTS;
if (inlen < sizeof *request) if (inlen < sizeof *request)
SC_FUNC_RETURN(ctx, SC_LOG_TYPE_ERROR, SC_ERROR_INVALID_DATA); SC_FUNC_RETURN(ctx, SC_LOG_DEBUG_VERBOSE, SC_ERROR_INVALID_DATA);
if ( request->bMessageType != 0x62 || if ( request->bMessageType != 0x62 ||
request->dwLength != __constant_cpu_to_le32(0) || request->dwLength != __constant_cpu_to_le32(0) ||
!( request->bPowerSelect == 0 || !( request->bPowerSelect == 0 ||
request->bPowerSelect & ccid_desc.bVoltageSupport ) || request->bPowerSelect & ccid_desc.bVoltageSupport ) ||
request->abRFU != 0) request->abRFU != 0)
sc_debug(ctx, "warning: malformed PC_to_RDR_IccPowerOn"); sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "warning: malformed PC_to_RDR_IccPowerOn");
if (request->bSlot < sizeof card_in_slot/sizeof *card_in_slot) { if (request->bSlot < sizeof card_in_slot/sizeof *card_in_slot) {
if (card_in_slot[request->bSlot] if (card_in_slot[request->bSlot]) {
&& sc_card_valid(card_in_slot[request->bSlot])) { sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "Card is already powered on.");
sc_debug(ctx, "Card is already powered on."); /*sc_reset(card_in_slot[request->bSlot], 0);*/
/*sc_reset(card_in_slot[request->bSlot]);*/ /*sc_disconnect_card(card_in_slot[request->bSlot]);*/
/*sc_disconnect_card(card_in_slot[request->bSlot], 0);*/
} else { } else {
sc_result = sc_connect_card(reader, request->bSlot, sc_result = sc_connect_card(reader,
&card_in_slot[request->bSlot]); &card_in_slot[request->bSlot]);
#ifdef BUERGERCLIENT_WORKAROUND #ifdef BUERGERCLIENT_WORKAROUND
if (sc_result >= 0) { if (sc_result >= 0) {
if (get_ef_card_access(card_in_slot[request->bSlot], if (get_ef_card_access(card_in_slot[request->bSlot],
(u8 **) &ef_cardaccess, &ef_cardaccess_length) < 0) { (u8 **) &ef_cardaccess, &ef_cardaccess_length) < 0) {
sc_error(ctx, "Could not get EF.CardAccess."); sc_debug(ctx, SC_LOG_DEBUG_VERBOSE, "Could not get EF.CardAccess.");
} }
} }
#endif #endif
@@ -437,7 +423,7 @@ perform_PC_to_RDR_IccPowerOn(const __u8 *in, size_t inlen, __u8 **out, size_t *o
sc_result, out, outlen, card_in_slot[request->bSlot]->atr, sc_result, out, outlen, card_in_slot[request->bSlot]->atr,
card_in_slot[request->bSlot]->atr_len); card_in_slot[request->bSlot]->atr_len);
} else { } else {
sc_error(ctx, "Returning default status package."); sc_debug(ctx, SC_LOG_DEBUG_VERBOSE, "Returning default status package.");
return get_RDR_to_PC_SlotStatus(request->bSlot, request->bSeq, return get_RDR_to_PC_SlotStatus(request->bSlot, request->bSeq,
sc_result, out, outlen, NULL, 0); sc_result, out, outlen, NULL, 0);
} }
@@ -453,19 +439,19 @@ perform_PC_to_RDR_IccPowerOff(const __u8 *in, size_t inlen, __u8 **out, size_t *
return SC_ERROR_INVALID_ARGUMENTS; return SC_ERROR_INVALID_ARGUMENTS;
if (inlen < sizeof *request) if (inlen < sizeof *request)
SC_FUNC_RETURN(ctx, SC_LOG_TYPE_ERROR, SC_ERROR_INVALID_DATA); SC_FUNC_RETURN(ctx, SC_LOG_DEBUG_VERBOSE, SC_ERROR_INVALID_DATA);
if ( request->bMessageType != 0x63 || if ( request->bMessageType != 0x63 ||
request->dwLength != __constant_cpu_to_le32(0) || request->dwLength != __constant_cpu_to_le32(0) ||
request->abRFU1 != 0 || request->abRFU1 != 0 ||
request->abRFU2 != 0) request->abRFU2 != 0)
sc_debug(ctx, "warning: malformed PC_to_RDR_IccPowerOff"); sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "warning: malformed PC_to_RDR_IccPowerOff");
if (request->bSlot > sizeof card_in_slot/sizeof *card_in_slot) if (request->bSlot > sizeof card_in_slot/sizeof *card_in_slot)
sc_result = SC_ERROR_INVALID_DATA; sc_result = SC_ERROR_INVALID_DATA;
else { else {
sc_reset(card_in_slot[request->bSlot]); sc_reset(card_in_slot[request->bSlot], 1);
sc_result = sc_disconnect_card(card_in_slot[request->bSlot], 0); sc_result = sc_disconnect_card(card_in_slot[request->bSlot]);
} }
return get_RDR_to_PC_SlotStatus(request->bSlot, request->bSeq, sc_result, return get_RDR_to_PC_SlotStatus(request->bSlot, request->bSeq, sc_result,
@@ -486,11 +472,11 @@ perform_PC_to_RDR_XfrBlock(const u8 *in, size_t inlen, __u8** out, size_t *outle
return SC_ERROR_INVALID_ARGUMENTS; return SC_ERROR_INVALID_ARGUMENTS;
if (inlen < sizeof *request) if (inlen < sizeof *request)
SC_FUNC_RETURN(ctx, SC_LOG_TYPE_ERROR, SC_ERROR_INVALID_DATA); SC_FUNC_RETURN(ctx, SC_LOG_DEBUG_VERBOSE, SC_ERROR_INVALID_DATA);
if ( request->bMessageType != 0x6F || if ( request->bMessageType != 0x6F ||
request->bBWI != 0) request->bBWI != 0)
sc_debug(ctx, "malformed PC_to_RDR_XfrBlock, will continue anyway"); sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "malformed PC_to_RDR_XfrBlock, will continue anyway");
if (request->bSlot > sizeof card_in_slot/sizeof *card_in_slot) if (request->bSlot > sizeof card_in_slot/sizeof *card_in_slot)
sc_result = SC_ERROR_INVALID_DATA; sc_result = SC_ERROR_INVALID_DATA;
@@ -501,7 +487,7 @@ perform_PC_to_RDR_XfrBlock(const u8 *in, size_t inlen, __u8** out, size_t *outle
sc_result = get_rapdu(&apdu, request->bSlot, &abDataOut, sc_result = get_rapdu(&apdu, request->bSlot, &abDataOut,
&abDataOutLen); &abDataOutLen);
else else
bin_log(ctx, "Invalid APDU", abDataIn, bin_log(ctx, SC_LOG_DEBUG_VERBOSE, "Invalid APDU", abDataIn,
__le32_to_cpu(request->dwLength)); __le32_to_cpu(request->dwLength));
} }
@@ -526,14 +512,14 @@ perform_PC_to_RDR_GetParamters(const __u8 *in, size_t inlen, __u8** out, size_t
return SC_ERROR_INVALID_ARGUMENTS; return SC_ERROR_INVALID_ARGUMENTS;
if (inlen < sizeof *request) if (inlen < sizeof *request)
SC_FUNC_RETURN(ctx, SC_LOG_TYPE_ERROR, SC_ERROR_INVALID_DATA); SC_FUNC_RETURN(ctx, SC_LOG_DEBUG_VERBOSE, SC_ERROR_INVALID_DATA);
if ( request->bMessageType != 0x6C || if ( request->bMessageType != 0x6C ||
request->dwLength != __constant_cpu_to_le32(0)) request->dwLength != __constant_cpu_to_le32(0))
sc_debug(ctx, "warning: malformed PC_to_RDR_GetParamters"); sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "warning: malformed PC_to_RDR_GetParamters");
if (request->bSlot < sizeof card_in_slot/sizeof *card_in_slot) { if (request->bSlot < sizeof card_in_slot/sizeof *card_in_slot) {
switch (reader->slot[request->bSlot].active_protocol) { switch (reader->active_protocol) {
case SC_PROTO_T0: case SC_PROTO_T0:
result = realloc(*out, sizeof *result + sizeof *t0); result = realloc(*out, sizeof *result + sizeof *t0);
if (!result) if (!result)
@@ -650,7 +636,7 @@ write_pin_length(sc_apdu_t *apdu, const struct sc_pin_cmd_pin *pin,
if (length_size) { if (length_size) {
if (length_size != 8) { if (length_size != 8) {
sc_error(ctx, "Writing PIN length only if it fits into " sc_debug(ctx, SC_LOG_DEBUG_VERBOSE, "Writing PIN length only if it fits into "
"a full byte (length of PIN size was %u bits)", "a full byte (length of PIN size was %u bits)",
length_size); length_size);
*sc_result = SC_ERROR_NOT_SUPPORTED; *sc_result = SC_ERROR_NOT_SUPPORTED;
@@ -728,7 +714,7 @@ encode_pin(u8 *buf, size_t buf_len, struct sc_pin_cmd_pin *pin,
else if (encoding == CCID_PIN_ENCODING_ASCII) else if (encoding == CCID_PIN_ENCODING_ASCII)
pin->encoding = SC_PIN_ENCODING_ASCII; pin->encoding = SC_PIN_ENCODING_ASCII;
else { else {
sc_error(ctx, "PIN encoding not supported (0x%02x)", encoding); sc_debug(ctx, SC_LOG_DEBUG_VERBOSE, "PIN encoding not supported (0x%02x)", encoding);
*sc_result = SC_ERROR_NOT_SUPPORTED; *sc_result = SC_ERROR_NOT_SUPPORTED;
return 0; return 0;
} }
@@ -758,7 +744,7 @@ write_pin(sc_apdu_t *apdu, struct sc_pin_cmd_pin *pin, uint8_t blocksize,
if (justify_right) { if (justify_right) {
if (encoding == CCID_PIN_ENCODING_BCD) { if (encoding == CCID_PIN_ENCODING_BCD) {
if (pin->len % 2) { if (pin->len % 2) {
sc_error(ctx, "Right aligning BCD encoded PIN only if it fits " sc_debug(ctx, SC_LOG_DEBUG_VERBOSE, "Right aligning BCD encoded PIN only if it fits "
"into a full byte (length of encoded PIN was %u bits)", "into a full byte (length of encoded PIN was %u bits)",
(pin->len)*4); (pin->len)*4);
*sc_result = SC_ERROR_NOT_SUPPORTED; *sc_result = SC_ERROR_NOT_SUPPORTED;
@@ -800,7 +786,7 @@ perform_PC_to_RDR_Secure_EstablishPACEChannel(sc_card_t *card,
} }
if (abDatalen < parsed+1) { if (abDatalen < parsed+1) {
sc_error(ctx, "Buffer too small, could not get PinID"); sc_debug(ctx, SC_LOG_DEBUG_VERBOSE, "Buffer too small, could not get PinID");
sc_result = SC_ERROR_INVALID_ARGUMENTS; sc_result = SC_ERROR_INVALID_ARGUMENTS;
goto err; goto err;
} }
@@ -809,7 +795,7 @@ perform_PC_to_RDR_Secure_EstablishPACEChannel(sc_card_t *card,
if (abDatalen < parsed+1) { if (abDatalen < parsed+1) {
sc_error(ctx, "Buffer too small, could not get lengthCHAT"); sc_debug(ctx, SC_LOG_DEBUG_VERBOSE, "Buffer too small, could not get lengthCHAT");
sc_result = SC_ERROR_INVALID_ARGUMENTS; sc_result = SC_ERROR_INVALID_ARGUMENTS;
goto err; goto err;
} }
@@ -817,19 +803,19 @@ perform_PC_to_RDR_Secure_EstablishPACEChannel(sc_card_t *card,
parsed++; parsed++;
if (abDatalen < parsed+pace_input.chat_length) { if (abDatalen < parsed+pace_input.chat_length) {
sc_error(ctx, "Buffer too small, could not get CHAT"); sc_debug(ctx, SC_LOG_DEBUG_VERBOSE, "Buffer too small, could not get CHAT");
sc_result = SC_ERROR_INVALID_ARGUMENTS; sc_result = SC_ERROR_INVALID_ARGUMENTS;
goto err; goto err;
} }
pace_input.chat = &abData[parsed]; pace_input.chat = &abData[parsed];
parsed += pace_input.chat_length; parsed += pace_input.chat_length;
if (pace_input.chat_length) if (pace_input.chat_length)
bin_log(ctx, "Card holder authorization template", bin_log(ctx, SC_LOG_DEBUG_VERBOSE, "Card holder authorization template",
pace_input.chat, pace_input.chat_length); pace_input.chat, pace_input.chat_length);
if (abDatalen < parsed+1) { if (abDatalen < parsed+1) {
sc_error(ctx, "Buffer too small, could not get lengthPIN"); sc_debug(ctx, SC_LOG_DEBUG_VERBOSE, "Buffer too small, could not get lengthPIN");
sc_result = SC_ERROR_INVALID_ARGUMENTS; sc_result = SC_ERROR_INVALID_ARGUMENTS;
goto err; goto err;
} }
@@ -837,7 +823,7 @@ perform_PC_to_RDR_Secure_EstablishPACEChannel(sc_card_t *card,
parsed++; parsed++;
if (abDatalen < parsed+pace_input.pin_length) { if (abDatalen < parsed+pace_input.pin_length) {
sc_error(ctx, "Buffer too small, could not get PIN"); sc_debug(ctx, SC_LOG_DEBUG_VERBOSE, "Buffer too small, could not get PIN");
sc_result = SC_ERROR_INVALID_ARGUMENTS; sc_result = SC_ERROR_INVALID_ARGUMENTS;
goto err; goto err;
} }
@@ -846,7 +832,7 @@ perform_PC_to_RDR_Secure_EstablishPACEChannel(sc_card_t *card,
if (abDatalen < parsed+sizeof word) { if (abDatalen < parsed+sizeof word) {
sc_error(ctx, "Buffer too small, could not get lengthCertificateDescription"); sc_debug(ctx, SC_LOG_DEBUG_VERBOSE, "Buffer too small, could not get lengthCertificateDescription");
sc_result = SC_ERROR_INVALID_ARGUMENTS; sc_result = SC_ERROR_INVALID_ARGUMENTS;
goto err; goto err;
} }
@@ -856,14 +842,14 @@ perform_PC_to_RDR_Secure_EstablishPACEChannel(sc_card_t *card,
parsed += sizeof word; parsed += sizeof word;
if (abDatalen < parsed+pace_input.certificate_description_length) { if (abDatalen < parsed+pace_input.certificate_description_length) {
sc_error(ctx, "Buffer too small, could not get CertificateDescription"); sc_debug(ctx, SC_LOG_DEBUG_VERBOSE, "Buffer too small, could not get CertificateDescription");
sc_result = SC_ERROR_INVALID_ARGUMENTS; sc_result = SC_ERROR_INVALID_ARGUMENTS;
goto err; goto err;
} }
pace_input.certificate_description = &abData[parsed]; pace_input.certificate_description = &abData[parsed];
parsed += pace_input.certificate_description_length; parsed += pace_input.certificate_description_length;
if (pace_input.certificate_description_length) if (pace_input.certificate_description_length)
bin_log(ctx, "Certificate description", bin_log(ctx, SC_LOG_DEBUG_VERBOSE, "Certificate description",
pace_input.certificate_description, pace_input.certificate_description,
pace_input.certificate_description_length); pace_input.certificate_description_length);
@@ -919,7 +905,7 @@ perform_PC_to_RDR_Secure_EstablishPACEChannel(sc_card_t *card,
if (pace_output.ef_cardaccess_length > 0xffff) { if (pace_output.ef_cardaccess_length > 0xffff) {
sc_error(ctx, "EF.CardAcces %u bytes too long", sc_debug(ctx, SC_LOG_DEBUG_VERBOSE, "EF.CardAcces %u bytes too long",
pace_output.ef_cardaccess_length-0xffff); pace_output.ef_cardaccess_length-0xffff);
sc_result = SC_ERROR_INVALID_DATA; sc_result = SC_ERROR_INVALID_DATA;
goto err; goto err;
@@ -936,7 +922,7 @@ perform_PC_to_RDR_Secure_EstablishPACEChannel(sc_card_t *card,
if (pace_output.recent_car_length > 0xff) { if (pace_output.recent_car_length > 0xff) {
sc_error(ctx, "Most recent CAR %u bytes too long", sc_debug(ctx, SC_LOG_DEBUG_VERBOSE, "Most recent CAR %u bytes too long",
pace_output.recent_car_length-0xff); pace_output.recent_car_length-0xff);
sc_result = SC_ERROR_INVALID_DATA; sc_result = SC_ERROR_INVALID_DATA;
goto err; goto err;
@@ -951,7 +937,7 @@ perform_PC_to_RDR_Secure_EstablishPACEChannel(sc_card_t *card,
if (pace_output.previous_car_length > 0xff) { if (pace_output.previous_car_length > 0xff) {
sc_error(ctx, "Previous CAR %u bytes too long", sc_debug(ctx, SC_LOG_DEBUG_VERBOSE, "Previous CAR %u bytes too long",
pace_output.previous_car_length-0xff); pace_output.previous_car_length-0xff);
sc_result = SC_ERROR_INVALID_DATA; sc_result = SC_ERROR_INVALID_DATA;
goto err; goto err;
@@ -966,7 +952,7 @@ perform_PC_to_RDR_Secure_EstablishPACEChannel(sc_card_t *card,
if (pace_output.id_icc_length > 0xffff) { if (pace_output.id_icc_length > 0xffff) {
sc_error(ctx, "ID ICC %u bytes too long", sc_debug(ctx, SC_LOG_DEBUG_VERBOSE, "ID ICC %u bytes too long",
pace_output.id_icc_length-0xffff); pace_output.id_icc_length-0xffff);
sc_result = SC_ERROR_INVALID_DATA; sc_result = SC_ERROR_INVALID_DATA;
goto err; goto err;
@@ -1050,14 +1036,14 @@ perform_PC_to_RDR_Secure_EstablishPACEChannel(sc_card_t *card,
const __u8 *abData, size_t abDatalen, const __u8 *abData, size_t abDatalen,
__u8 **abDataOut, size_t *abDataOutLen) __u8 **abDataOut, size_t *abDataOutLen)
{ {
sc_error(ctx, "ccid compiled without PACE support."); sc_debug(ctx, SC_LOG_DEBUG_VERBOSE, "ccid compiled without PACE support.");
return SC_ERROR_NOT_SUPPORTED; return SC_ERROR_NOT_SUPPORTED;
} }
static int static int
perform_PC_to_RDR_Secure_GetReadersPACECapabilities(__u8 **abDataOut, perform_PC_to_RDR_Secure_GetReadersPACECapabilities(__u8 **abDataOut,
size_t *abDataOutLen) size_t *abDataOutLen)
{ {
sc_error(ctx, "ccid compiled without PACE support."); sc_debug(ctx, SC_LOG_DEBUG_VERBOSE, "ccid compiled without PACE support.");
return SC_ERROR_NOT_SUPPORTED; return SC_ERROR_NOT_SUPPORTED;
} }
#endif #endif
@@ -1083,18 +1069,18 @@ perform_PC_to_RDR_Secure(const __u8 *in, size_t inlen, __u8** out, size_t *outle
return SC_ERROR_INVALID_ARGUMENTS; return SC_ERROR_INVALID_ARGUMENTS;
if (inlen < sizeof *request + 1) if (inlen < sizeof *request + 1)
SC_FUNC_RETURN(ctx, SC_LOG_TYPE_ERROR, SC_ERROR_INVALID_DATA); SC_FUNC_RETURN(ctx, SC_LOG_DEBUG_VERBOSE, SC_ERROR_INVALID_DATA);
if (request->bMessageType != 0x69) if (request->bMessageType != 0x69)
sc_debug(ctx, "warning: malformed PC_to_RDR_Secure"); sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "warning: malformed PC_to_RDR_Secure");
if (request->bSlot > sizeof card_in_slot/sizeof *card_in_slot) { if (request->bSlot > sizeof card_in_slot/sizeof *card_in_slot) {
sc_error(ctx, "Received request to invalid slot (bSlot=0x%02x)", request->bSlot); sc_debug(ctx, SC_LOG_DEBUG_VERBOSE, "Received request to invalid slot (bSlot=0x%02x)", request->bSlot);
goto err; goto err;
} }
if (request->wLevelParameter != CCID_WLEVEL_DIRECT) { if (request->wLevelParameter != CCID_WLEVEL_DIRECT) {
sc_error(ctx, "Received request with unsupported wLevelParameter (0x%04x)", sc_debug(ctx, SC_LOG_DEBUG_VERBOSE, "Received request with unsupported wLevelParameter (0x%04x)",
__le16_to_cpu(request->wLevelParameter)); __le16_to_cpu(request->wLevelParameter));
sc_result = SC_ERROR_NOT_SUPPORTED; sc_result = SC_ERROR_NOT_SUPPORTED;
goto err; goto err;
@@ -1131,7 +1117,7 @@ perform_PC_to_RDR_Secure(const __u8 *in, size_t inlen, __u8** out, size_t *outle
(abData + sizeof(__u8)); (abData + sizeof(__u8));
if (abDatalen < sizeof *modify) { if (abDatalen < sizeof *modify) {
sc_error(ctx, "Not enough data for abPINDataStucture_Modification_t"); sc_debug(ctx, SC_LOG_DEBUG_VERBOSE, "Not enough data for abPINDataStucture_Modification_t");
sc_result = SC_ERROR_INVALID_DATA; sc_result = SC_ERROR_INVALID_DATA;
goto err; goto err;
} }
@@ -1150,7 +1136,7 @@ perform_PC_to_RDR_Secure(const __u8 *in, size_t inlen, __u8** out, size_t *outle
&abDataOut, &abDataOutLen); &abDataOut, &abDataOutLen);
if (card_in_slot[request->bSlot]) if (card_in_slot[request->bSlot])
bin_log(card_in_slot[request->bSlot]->ctx, "PACE Capabilities", abDataOut, abDataOutLen); bin_log(card_in_slot[request->bSlot]->ctx, SC_LOG_DEBUG_VERBOSE, "PACE Capabilities", abDataOut, abDataOutLen);
goto err; goto err;
break; break;
@@ -1164,7 +1150,7 @@ perform_PC_to_RDR_Secure(const __u8 *in, size_t inlen, __u8** out, size_t *outle
case 0x04: case 0x04:
// Cancel PIN function // Cancel PIN function
default: default:
sc_error(ctx, "Received request with unsupported PIN operation (bPINOperation=0x%02x)", sc_debug(ctx, SC_LOG_DEBUG_VERBOSE, "Received request with unsupported PIN operation (bPINOperation=0x%02x)",
*abData); *abData);
sc_result = SC_ERROR_NOT_SUPPORTED; sc_result = SC_ERROR_NOT_SUPPORTED;
goto err; goto err;
@@ -1172,10 +1158,9 @@ perform_PC_to_RDR_Secure(const __u8 *in, size_t inlen, __u8** out, size_t *outle
sc_result = build_apdu(ctx, abPINApdu, apdulen, &apdu); sc_result = build_apdu(ctx, abPINApdu, apdulen, &apdu);
if (sc_result < 0) { if (sc_result < 0) {
bin_log(ctx, "Invalid APDU", abPINApdu, apdulen); bin_log(ctx, SC_LOG_DEBUG_VERBOSE, "Invalid APDU", abPINApdu, apdulen);
goto err; goto err;
} }
apdu.sensitive = 1;
new_pin.min_length = curr_pin.min_length = wPINMaxExtraDigit >> 8; new_pin.min_length = curr_pin.min_length = wPINMaxExtraDigit >> 8;
new_pin.min_length = curr_pin.max_length = wPINMaxExtraDigit & 0x00ff; new_pin.min_length = curr_pin.max_length = wPINMaxExtraDigit & 0x00ff;
@@ -1187,7 +1172,7 @@ perform_PC_to_RDR_Secure(const __u8 *in, size_t inlen, __u8** out, size_t *outle
uint8_t encoding = bmFormatString & 2; uint8_t encoding = bmFormatString & 2;
uint8_t blocksize = bmPINBlockString & 0xf; uint8_t blocksize = bmPINBlockString & 0xf;
sc_debug(ctx, "PIN %s block (%d bytes) proberties:\n" sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "PIN %s block (%d bytes) proberties:\n"
"\tminimum %d, maximum %d PIN digits\n" "\tminimum %d, maximum %d PIN digits\n"
"\t%s PIN encoding, %s justification\n" "\t%s PIN encoding, %s justification\n"
"\tsystem units are %s\n" "\tsystem units are %s\n"
@@ -1212,7 +1197,7 @@ perform_PC_to_RDR_Secure(const __u8 *in, size_t inlen, __u8** out, size_t *outle
"Please enter your PIN for verification: ", "Please enter your PIN for verification: ",
0)) { 0)) {
sc_result = SC_ERROR_INTERNAL; sc_result = SC_ERROR_INTERNAL;
sc_error(ctx, "Could not read PIN.\n"); sc_debug(ctx, SC_LOG_DEBUG_VERBOSE, "Could not read PIN.\n");
goto err; goto err;
} }
} else { } else {
@@ -1223,7 +1208,7 @@ perform_PC_to_RDR_Secure(const __u8 *in, size_t inlen, __u8** out, size_t *outle
"Please enter your current PIN for modification: ", "Please enter your current PIN for modification: ",
0)) { 0)) {
sc_result = SC_ERROR_INTERNAL; sc_result = SC_ERROR_INTERNAL;
sc_error(ctx, "Could not read current PIN.\n"); sc_debug(ctx, SC_LOG_DEBUG_VERBOSE, "Could not read current PIN.\n");
goto err; goto err;
} }
} }
@@ -1233,7 +1218,7 @@ perform_PC_to_RDR_Secure(const __u8 *in, size_t inlen, __u8** out, size_t *outle
"Please enter your new PIN for modification: ", "Please enter your new PIN for modification: ",
modify->bConfirmPIN & CCID_PIN_CONFIRM_NEW)) { modify->bConfirmPIN & CCID_PIN_CONFIRM_NEW)) {
sc_result = SC_ERROR_INTERNAL; sc_result = SC_ERROR_INTERNAL;
sc_error(ctx, "Could not read new PIN.\n"); sc_debug(ctx, SC_LOG_DEBUG_VERBOSE, "Could not read new PIN.\n");
goto err; goto err;
} }
} }
@@ -1325,46 +1310,38 @@ get_RDR_to_PC_NotifySlotChange(RDR_to_PC_NotifySlotChange_t **out)
result->bmSlotICCState = CCID_SLOTS_UNCHANGED; result->bmSlotICCState = CCID_SLOTS_UNCHANGED;
oldmask = CCID_SLOTS_UNCHANGED; oldmask = CCID_SLOTS_UNCHANGED;
for (i = 0; i < reader->slot_count; i++) { sc_result = detect_card_presence();
sc_result = detect_card_presence(i); if (sc_result < 0) {
if (sc_result < 0) { sc_debug(ctx, SC_LOG_DEBUG_VERBOSE, "Could not detect card presence.");
sc_error(ctx, "Could not detect card presence, skipping slot %d.", debug_sc_result(sc_result);
i);
debug_sc_result(sc_result);
continue;
}
if (sc_result & SC_SLOT_CARD_PRESENT)
oldmask |= present[i];
if (sc_result & SC_SLOT_CARD_CHANGED) {
sc_debug(ctx, "Card status changed in slot %d.", i);
result->bmSlotICCState |= changed[i];
}
} }
if (sc_result & SC_READER_CARD_PRESENT)
oldmask |= present[0];
if (sc_result & SC_READER_CARD_CHANGED) {
sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "Card status changed in slot 0.");
result->bmSlotICCState |= changed[0];
}
sleep(10); sleep(10);
for (i = 0; i < reader->slot_count; i++) { sc_result = detect_card_presence();
sc_result = detect_card_presence(i); if (sc_result < 0) {
if (sc_result < 0) { sc_debug(ctx, SC_LOG_DEBUG_VERBOSE, "Could not detect card presence.");
sc_error(ctx, "Could not detect card presence, skipping slot %d.", debug_sc_result(sc_result);
i); }
debug_sc_result(sc_result);
continue;
}
if (sc_result & SC_SLOT_CARD_PRESENT) if (sc_result & SC_READER_CARD_PRESENT)
result->bmSlotICCState |= present[i]; result->bmSlotICCState |= present[0];
if (sc_result & SC_SLOT_CARD_CHANGED) { if (sc_result & SC_READER_CARD_CHANGED) {
sc_debug(ctx, "Card status changed in slot %d.", i); sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "Card status changed in slot 0.");
result->bmSlotICCState |= changed[i]; result->bmSlotICCState |= changed[0];
} }
if ((oldmask & present[i]) != (result->bmSlotICCState & present[i])) { if ((oldmask & present[0]) != (result->bmSlotICCState & present[0])) {
sc_debug(ctx, "Card status changed in slot %d.", i); sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "Card status changed in slot 0.");
result->bmSlotICCState |= changed[i]; result->bmSlotICCState |= changed[0];
}
} }
return SC_SUCCESS; return SC_SUCCESS;
@@ -1380,7 +1357,7 @@ perform_unknown(const __u8 *in, size_t inlen, __u8 **out, size_t *outlen)
return SC_ERROR_INVALID_ARGUMENTS; return SC_ERROR_INVALID_ARGUMENTS;
if (inlen < sizeof *request) if (inlen < sizeof *request)
SC_FUNC_RETURN(ctx, SC_LOG_TYPE_ERROR, SC_ERROR_INVALID_DATA); SC_FUNC_RETURN(ctx, SC_LOG_DEBUG_VERBOSE, SC_ERROR_INVALID_DATA);
result = realloc(*out, sizeof *result); result = realloc(*out, sizeof *result);
if (!result) if (!result)
@@ -1413,7 +1390,7 @@ perform_unknown(const __u8 *in, size_t inlen, __u8 **out, size_t *outlen)
result->bMessageType = 0x84; result->bMessageType = 0x84;
break; break;
default: default:
sc_debug(ctx, "Unknown message type in request (0x%02x). " sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "Unknown message type in request (0x%02x). "
"Using bMessageType=0x%02x for output.", "Using bMessageType=0x%02x for output.",
request->bMessageType, 0); request->bMessageType, 0);
result->bMessageType = 0; result->bMessageType = 0;
@@ -1441,37 +1418,37 @@ int ccid_parse_bulkout(const __u8* inbuf, size_t inlen, __u8** outbuf)
switch (*inbuf) { switch (*inbuf) {
case 0x62: case 0x62:
sc_debug(ctx, "PC_to_RDR_IccPowerOn"); sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "PC_to_RDR_IccPowerOn");
sc_result = perform_PC_to_RDR_IccPowerOn(inbuf, inlen, outbuf, &outlen); sc_result = perform_PC_to_RDR_IccPowerOn(inbuf, inlen, outbuf, &outlen);
break; break;
case 0x63: case 0x63:
sc_debug(ctx, "PC_to_RDR_IccPowerOff"); sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "PC_to_RDR_IccPowerOff");
sc_result = perform_PC_to_RDR_IccPowerOff(inbuf, inlen, outbuf, &outlen); sc_result = perform_PC_to_RDR_IccPowerOff(inbuf, inlen, outbuf, &outlen);
break; break;
case 0x65: case 0x65:
sc_debug(ctx, "PC_to_RDR_GetSlotStatus"); sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "PC_to_RDR_GetSlotStatus");
sc_result = perform_PC_to_RDR_GetSlotStatus(inbuf, inlen, outbuf, &outlen); sc_result = perform_PC_to_RDR_GetSlotStatus(inbuf, inlen, outbuf, &outlen);
break; break;
case 0x6F: case 0x6F:
sc_debug(ctx, "PC_to_RDR_XfrBlock"); sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "PC_to_RDR_XfrBlock");
sc_result = perform_PC_to_RDR_XfrBlock(inbuf, inlen, outbuf, &outlen); sc_result = perform_PC_to_RDR_XfrBlock(inbuf, inlen, outbuf, &outlen);
break; break;
case 0x6C: case 0x6C:
sc_debug(ctx, "PC_to_RDR_GetParameters"); sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "PC_to_RDR_GetParameters");
sc_result = perform_PC_to_RDR_GetParamters(inbuf, inlen, outbuf, &outlen); sc_result = perform_PC_to_RDR_GetParamters(inbuf, inlen, outbuf, &outlen);
break; break;
case 0x69: case 0x69:
sc_debug(ctx, "PC_to_RDR_Secure"); sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "PC_to_RDR_Secure");
sc_result = perform_PC_to_RDR_Secure(inbuf, inlen, outbuf, &outlen); sc_result = perform_PC_to_RDR_Secure(inbuf, inlen, outbuf, &outlen);
break; break;
default: default:
sc_error(ctx, "Unknown ccid bulk-in message. " sc_debug(ctx, SC_LOG_DEBUG_VERBOSE, "Unknown ccid bulk-in message. "
"Starting default handler..."); "Starting default handler...");
sc_result = perform_unknown(inbuf, inlen, outbuf, &outlen); sc_result = perform_unknown(inbuf, inlen, outbuf, &outlen);
} }
@@ -1500,18 +1477,18 @@ int ccid_parse_control(struct usb_ctrlrequest *setup, __u8 **outbuf)
if (setup->bRequestType == USB_REQ_CCID) { if (setup->bRequestType == USB_REQ_CCID) {
switch(setup->bRequest) { switch(setup->bRequest) {
case CCID_CONTROL_ABORT: case CCID_CONTROL_ABORT:
sc_debug(ctx, "ABORT"); sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "ABORT");
if (length != 0x00) { if (length != 0x00) {
sc_debug(ctx, "warning: malformed ABORT"); sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "warning: malformed ABORT");
} }
r = 0; r = 0;
break; break;
case CCID_CONTROL_GET_CLOCK_FREQUENCIES: case CCID_CONTROL_GET_CLOCK_FREQUENCIES:
sc_debug(ctx, "GET_CLOCK_FREQUENCIES"); sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "GET_CLOCK_FREQUENCIES");
if (value != 0x00) { if (value != 0x00) {
sc_debug(ctx, "warning: malformed GET_CLOCK_FREQUENCIES"); sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "warning: malformed GET_CLOCK_FREQUENCIES");
} }
r = sizeof(__le32); r = sizeof(__le32);
@@ -1527,9 +1504,9 @@ int ccid_parse_control(struct usb_ctrlrequest *setup, __u8 **outbuf)
break; break;
case CCID_CONTROL_GET_DATA_RATES: case CCID_CONTROL_GET_DATA_RATES:
sc_debug(ctx, "GET_DATA_RATES"); sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "GET_DATA_RATES");
if (value != 0x00) { if (value != 0x00) {
sc_debug(ctx, "warning: malformed GET_DATA_RATES"); sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "warning: malformed GET_DATA_RATES");
} }
r = sizeof (__le32); r = sizeof (__le32);
@@ -1545,7 +1522,7 @@ int ccid_parse_control(struct usb_ctrlrequest *setup, __u8 **outbuf)
break; break;
default: default:
sc_error(ctx, "Unknown ccid control command."); sc_debug(ctx, SC_LOG_DEBUG_VERBOSE, "Unknown ccid control command.");
r = SC_ERROR_NOT_SUPPORTED; r = SC_ERROR_NOT_SUPPORTED;
} }

View File

@@ -23,7 +23,7 @@
#define _CCID_H #define _CCID_H
#include <linux/usb/ch9.h> #include <linux/usb/ch9.h>
#include <opensc/opensc.h> #include <libopensc/opensc.h>
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {

View File

@@ -16,6 +16,20 @@ do_subst = sed \
-e 's,[@]VERSION[@],$(VERSION),g' \ -e 's,[@]VERSION[@],$(VERSION),g' \
-e 's,[@]top_srcdir[@],$(top_srcdir),g' -e 's,[@]top_srcdir[@],$(top_srcdir),g'
opensc-0.11.13.tar.gz:
wget http://www.opensc-project.org/files/opensc/opensc-0.11.13.tar.gz
opensc-0.11.13: opensc-0.11.13.tar.gz
tar xzf opensc-0.11.13.tar.gz
patch -p1 -d opensc-0.11.13 < opensc/le0.patch
patch -p0 -d opensc-0.11.13 < opensc/hex_dump_align.2.patch
win: opensc-0.11.13
cd opensc-0.11.13 && \
./bootstrap && \
./configure --disable-doc && \
env OPENSSL_VERSION="1.0.0c_with_openpace-0.4.1" OPENSSL_URL="http://downloads.sourceforge.net/project/openpace/openssl-1.0.0c_with_openpace-0.4.1.tar.gz" EXTRA_OPENSSL_CONFIG="experimental-pace" ../opensc/installer_from_build.sh opensc/win32/build
if DOC_ENABLED if DOC_ENABLED
clean-local: clean-local:
rm -rf doc rm -rf doc

View File

@@ -19,9 +19,6 @@ AM_PROG_CC_C_O
PKG_PROG_PKG_CONFIG PKG_PROG_PKG_CONFIG
# Checks for libraries. # Checks for libraries.
PKG_CHECK_EXISTS([libopensc],
[PKG_CHECK_MODULES([OPENSC], [libopensc < 0.12 ])],
[AC_MSG_WARN([libopensc < 0.12 not found by pkg-config])])
PKG_CHECK_EXISTS([libssl], PKG_CHECK_EXISTS([libssl],
[PKG_CHECK_MODULES([OPENSSL], [libssl])], [PKG_CHECK_MODULES([OPENSSL], [libssl])],
[AC_MSG_WARN([libssl not found by pkg-config])]) [AC_MSG_WARN([libssl not found by pkg-config])])
@@ -29,14 +26,8 @@ PKG_CHECK_EXISTS([libssl],
saved_CPPFLAGS="$CPPFLAGS" saved_CPPFLAGS="$CPPFLAGS"
saved_LIBS="$LIBS" saved_LIBS="$LIBS"
CPPFLAGS="$CPPFLAGS $OPENSC_CFLAGS $OPENSSL_CFLAGS" CPPFLAGS="$CPPFLAGS $OPENSSL_CFLAGS"
LIBS="$LDFLAGS $OPENSC_LIBS $OPENSSL_LIBS" LIBS="$LDFLAGS $OPENSSL_LIBS"
AC_CHECK_HEADERS(opensc/opensc.h,,
[ AC_MSG_ERROR([opensc/opensc.h not found, install libopensc < 0.12 or use ./configure OPENSC_CFLAGS=...]) ])
AC_MSG_CHECKING([for sc_context_create])
AC_TRY_LINK_FUNC(sc_context_create, [ AC_MSG_RESULT([yes]) ],
[ AC_MSG_ERROR([libopensc < 0.12 not found, use ./configure OPENSC_LIBS=...]) ])
AC_CHECK_HEADERS(openssl/evp.h, [], [ AC_MSG_ERROR([openssl/evp.h not found, install OpenSSL or use ./configure OPENSSL_CFLAGS=...]) ]) AC_CHECK_HEADERS(openssl/evp.h, [], [ AC_MSG_ERROR([openssl/evp.h not found, install OpenSSL or use ./configure OPENSSL_CFLAGS=...]) ])
AC_MSG_CHECKING([for EVP_read_pw_string_min]) AC_MSG_CHECKING([for EVP_read_pw_string_min])
@@ -100,8 +91,6 @@ Compiler flags: ${CFLAGS}
Preprocessor flags: ${CPPFLAGS} Preprocessor flags: ${CPPFLAGS}
Linker flags: ${LDFLAGS} Linker flags: ${LDFLAGS}
Libraries: ${LIBS} Libraries: ${LIBS}
OPENSC_CFLAGS: ${OPENSC_CFLAGS}
OPENSC_LIBS: ${OPENSC_LIBS}
OPENSSL_CFLAGS: ${OPENSSL_CFLAGS} OPENSSL_CFLAGS: ${OPENSSL_CFLAGS}
OPENSSL_LIBS: ${OPENSSL_LIBS} OPENSSL_LIBS: ${OPENSSL_LIBS}

View File

@@ -1,17 +1,26 @@
AM_CPPFLAGS = -I$(top_srcdir)/src/pace -I$(top_builddir)/src/pace OPENSCVERSION = 0.12.0
EXTRA_DIST = opensc-$(OPENSCVERSION)
AM_CPPFLAGS = -I$(top_srcdir)/src/pace -I$(top_srcdir)/src/opensc-$(OPENSCVERSION)/src
libpace_la_SOURCES = sm.c scutil.c pace.c pace_lib.c libpace_la_SOURCES = sm.c scutil.c pace.c pace_lib.c
libpace_la_LIBADD = $(OPENSC_LIBS) $(OPENSSL_LIBS) libpace_la_LIBADD = $(OPENSSL_LIBS) libopensc.la
libpace_la_CFLAGS = $(OPENSC_CFLAGS) $(OPENSSL_CFLAGS) libpace_la_CFLAGS = $(OPENSSL_CFLAGS)
pace_tool_SOURCES = pace-tool.c binutil.c pace_tool_SOURCES = pace-tool.c binutil.c
pace_tool_LDADD = $(OPENSC_LIBS) $(OPENSSL_LIBS) libpace.la pace_tool_LDADD = $(OPENSSL_LIBS) libpace.la libopensc.la
pace_tool_CFLAGS = $(OPENSC_CFLAGS) $(OPENSSL_CFLAGS) pace_tool_CFLAGS = $(OPENSSL_CFLAGS)
noinst_HEADERS = \ noinst_HEADERS = \
binutil.h binutil.h
flaw: opensc: opensc-$(OPENSCVERSION)
flawfinder -SQD *.h *.c cd $(top_builddir)/src && cp -r opensc-$(OPENSCVERSION) opensc
libopensc.la: opensc
cd $(top_builddir)/src/opensc && ./configure
$(MAKE) -C opensc
cp $(top_builddir)/src/opensc/src/libopensc/.libs/libopensc* $(top_builddir)/src
bin_PROGRAMS = pace-tool bin_PROGRAMS = pace-tool

View File

@@ -19,7 +19,7 @@
#include "binutil.h" #include "binutil.h"
#include "pace.h" #include "pace.h"
#include "scutil.h" #include "scutil.h"
#include <opensc/log.h> #include <libopensc/log.h>
#include <openssl/pace.h> #include <openssl/pace.h>
#include <stdint.h> #include <stdint.h>
#include <stdio.h> #include <stdio.h>
@@ -130,7 +130,8 @@ int pace_translate_apdus(struct sm_ctx *sctx, sc_card_t *card, FILE *input)
if (linelen <= 1) { if (linelen <= 1) {
if (linelen < 0) { if (linelen < 0) {
r = SC_ERROR_INTERNAL; r = SC_ERROR_INTERNAL;
sc_error(card->ctx, "Could not read line"); sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE_TOOL,
"Could not read line");
} else { } else {
r = SC_SUCCESS; r = SC_SUCCESS;
printf("Thanks for flying with ccid\n"); printf("Thanks for flying with ccid\n");
@@ -141,7 +142,8 @@ int pace_translate_apdus(struct sm_ctx *sctx, sc_card_t *card, FILE *input)
apdulen = sizeof buf; apdulen = sizeof buf;
if (sc_hex_to_bin(read, buf, &apdulen) < 0) { if (sc_hex_to_bin(read, buf, &apdulen) < 0) {
sc_error(card->ctx, "Could not format binary string"); sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE_TOOL,
"Could not format binary string");
continue; continue;
} }
if (input != stdin) if (input != stdin)
@@ -149,7 +151,7 @@ int pace_translate_apdus(struct sm_ctx *sctx, sc_card_t *card, FILE *input)
r = build_apdu(card->ctx, buf, apdulen, &apdu); r = build_apdu(card->ctx, buf, apdulen, &apdu);
if (r < 0) { if (r < 0) {
bin_log(ctx, "Invalid C-APDU", buf, apdulen); bin_log(ctx, SC_LOG_DEBUG_NORMAL, "Invalid C-APDU", buf, apdulen);
continue; continue;
} }
@@ -158,7 +160,8 @@ int pace_translate_apdus(struct sm_ctx *sctx, sc_card_t *card, FILE *input)
r = sm_transmit_apdu(sctx, card, &apdu); r = sm_transmit_apdu(sctx, card, &apdu);
if (r < 0) { if (r < 0) {
sc_error(card->ctx, "Could not send C-APDU: %s", sc_strerror(r)); sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE_TOOL,
"Could not send C-APDU: %s", sc_strerror(r));
continue; continue;
} }
@@ -312,14 +315,8 @@ main (int argc, char **argv)
exit(1); exit(1);
} }
for (i = 0; i < SC_MAX_SLOTS; i++) { if (sc_connect_card(reader, &card) < 0) {
if (sc_detect_card_presence(reader, 0) & SC_SLOT_CARD_PRESENT) { fprintf(stderr, "Could not connect to card\n");
sc_connect_card(reader, i, &card);
break;
}
}
if (i == SC_MAX_SLOTS) {
fprintf(stderr, "No card found\n");
sc_release_context(ctx); sc_release_context(ctx);
exit(1); exit(1);
} }
@@ -547,8 +544,8 @@ err:
if (pace_output.id_pcd) if (pace_output.id_pcd)
free(pace_output.id_pcd); free(pace_output.id_pcd);
sc_reset(card); sc_reset(card, 1);
sc_disconnect_card(card, 0); sc_disconnect_card(card);
sc_release_context(ctx); sc_release_context(ctx);
return -i; return -i;

View File

@@ -19,9 +19,9 @@
#include "pace.h" #include "pace.h"
#include "sm.h" #include "sm.h"
#include "scutil.h" #include "scutil.h"
#include <opensc/asn1.h> #include <libopensc/asn1.h>
#include <opensc/log.h> #include <libopensc/log.h>
#include <opensc/opensc.h> #include <libopensc/opensc.h>
#include <openssl/asn1t.h> #include <openssl/asn1t.h>
#include <openssl/bio.h> #include <openssl/bio.h>
#include <openssl/buffer.h> #include <openssl/buffer.h>
@@ -198,18 +198,18 @@ int get_ef_card_access(sc_card_t *card,
memset(&path, 0, sizeof path); memset(&path, 0, sizeof path);
r = sc_append_file_id(&path, FID_EF_CARDACCESS); r = sc_append_file_id(&path, FID_EF_CARDACCESS);
if (r < 0) { if (r < 0) {
sc_error(card->ctx, "Could not create path object."); sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Could not create path object.");
goto err; goto err;
} }
r = sc_concatenate_path(&path, sc_get_mf_path(), &path); r = sc_concatenate_path(&path, sc_get_mf_path(), &path);
if (r < 0) { if (r < 0) {
sc_error(card->ctx, "Could not create path object."); sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Could not create path object.");
goto err; goto err;
} }
r = sc_select_file(card, &path, &file); r = sc_select_file(card, &path, &file);
if (r < 0) { if (r < 0) {
sc_error(card->ctx, "Could not select EF.CardAccess."); sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Could not select EF.CardAccess.");
goto err; goto err;
} }
@@ -231,7 +231,7 @@ int get_ef_card_access(sc_card_t *card,
} }
if (r < 0) { if (r < 0) {
sc_error(card->ctx, "Could not read EF.CardAccess."); sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Could not read EF.CardAccess.");
goto err; goto err;
} }
@@ -241,7 +241,7 @@ int get_ef_card_access(sc_card_t *card,
/* test cards only return an empty FCI template, /* test cards only return an empty FCI template,
* so we can't determine any file proberties */ * so we can't determine any file proberties */
if (*length_ef_cardaccess < file->size) { if (*length_ef_cardaccess < file->size) {
sc_error(card->ctx, "Actual filesize differs from the size in file " sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Actual filesize differs from the size in file "
"proberties (%u!=%u).", *length_ef_cardaccess, file->size); "proberties (%u!=%u).", *length_ef_cardaccess, file->size);
r = SC_ERROR_FILE_TOO_SMALL; r = SC_ERROR_FILE_TOO_SMALL;
goto err; goto err;
@@ -298,7 +298,7 @@ static int pace_mse_set_at(struct sm_ctx *oldpacectx, sc_card_t *card,
} }
if (!ASN1_INTEGER_set(data->key_reference1, secret_key)) { if (!ASN1_INTEGER_set(data->key_reference1, secret_key)) {
sc_error(card->ctx, "Error setting key reference 1 of MSE:Set AT data"); sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Error setting key reference 1 of MSE:Set AT data");
r = SC_ERROR_INTERNAL; r = SC_ERROR_INTERNAL;
goto err; goto err;
} }
@@ -308,7 +308,7 @@ static int pace_mse_set_at(struct sm_ctx *oldpacectx, sc_card_t *card,
r = i2d_PACE_MSE_SET_AT_C(data, &d); r = i2d_PACE_MSE_SET_AT_C(data, &d);
if (r < 0) { if (r < 0) {
sc_error(card->ctx, "Error encoding MSE:Set AT APDU data"); sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Error encoding MSE:Set AT APDU data");
r = SC_ERROR_INTERNAL; r = SC_ERROR_INTERNAL;
goto err; goto err;
} }
@@ -318,8 +318,7 @@ static int pace_mse_set_at(struct sm_ctx *oldpacectx, sc_card_t *card,
apdu.data = sc_asn1_find_tag(card->ctx, d, r, 0x30, &apdu.datalen); apdu.data = sc_asn1_find_tag(card->ctx, d, r, 0x30, &apdu.datalen);
apdu.lc = apdu.datalen; apdu.lc = apdu.datalen;
if (card->ctx->debug > SC_LOG_TYPE_DEBUG) bin_log(card->ctx, SC_LOG_DEBUG_NORMAL, "MSE:Set AT command data", apdu.data, apdu.datalen);
bin_log(card->ctx, "MSE:Set AT command data", apdu.data, apdu.datalen);
if (oldpacectx) if (oldpacectx)
r = sm_transmit_apdu(oldpacectx, card, &apdu); r = sm_transmit_apdu(oldpacectx, card, &apdu);
@@ -329,7 +328,7 @@ static int pace_mse_set_at(struct sm_ctx *oldpacectx, sc_card_t *card,
goto err; goto err;
if (apdu.resplen) { if (apdu.resplen) {
sc_error(card->ctx, "MSE:Set AT response data should be empty " sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "MSE:Set AT response data should be empty "
"(contains %u bytes)", apdu.resplen); "(contains %u bytes)", apdu.resplen);
r = SC_ERROR_UNKNOWN_DATA_RECEIVED; r = SC_ERROR_UNKNOWN_DATA_RECEIVED;
goto err; goto err;
@@ -343,19 +342,19 @@ static int pace_mse_set_at(struct sm_ctx *oldpacectx, sc_card_t *card,
tries = apdu.sw2 & 0x0f; tries = apdu.sw2 & 0x0f;
if (tries <= 1) { if (tries <= 1) {
/* this is only a warning... */ /* this is only a warning... */
sc_error(card->ctx, "Remaining tries: %d (%s must be %s)\n", sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Remaining tries: %d (%s must be %s)\n",
tries, pace_secret_name(secret_key), tries, pace_secret_name(secret_key),
tries ? "resumed" : "unblocked"); tries ? "resumed" : "unblocked");
} }
r = SC_SUCCESS; r = SC_SUCCESS;
} else { } else {
sc_error(card->ctx, "Unknown status bytes: SW1=%02X, SW2=%02X\n", sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Unknown status bytes: SW1=%02X, SW2=%02X\n",
apdu.sw1, apdu.sw2); apdu.sw1, apdu.sw2);
r = SC_ERROR_CARD_CMD_FAILED; r = SC_ERROR_CARD_CMD_FAILED;
goto err; goto err;
} }
} else if (apdu.sw1 == 0x62 && apdu.sw2 == 0x83) { } else if (apdu.sw1 == 0x62 && apdu.sw2 == 0x83) {
sc_error(card->ctx, "Password is deactivated\n"); sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Password is deactivated\n");
r = SC_ERROR_AUTH_METHOD_BLOCKED; r = SC_ERROR_AUTH_METHOD_BLOCKED;
goto err; goto err;
} else { } else {
@@ -405,8 +404,7 @@ static int pace_gen_auth_1_encrypted_nonce(struct sm_ctx *oldpacectx,
apdu.datalen = r; apdu.datalen = r;
apdu.lc = r; apdu.lc = r;
if (card->ctx->debug > SC_LOG_TYPE_DEBUG) bin_log(card->ctx, SC_LOG_DEBUG_NORMAL, "General authenticate (Encrypted Nonce) command data", apdu.data, apdu.datalen);
bin_log(card->ctx, "General authenticate (Encrypted Nonce) command data", apdu.data, apdu.datalen);
apdu.resplen = maxresp; apdu.resplen = maxresp;
apdu.resp = malloc(apdu.resplen); apdu.resp = malloc(apdu.resplen);
@@ -421,12 +419,11 @@ static int pace_gen_auth_1_encrypted_nonce(struct sm_ctx *oldpacectx,
if (r < 0) if (r < 0)
goto err; goto err;
if (card->ctx->debug > SC_LOG_TYPE_DEBUG) bin_log(card->ctx, SC_LOG_DEBUG_NORMAL, "General authenticate (Encrypted Nonce) response data", apdu.resp, apdu.resplen);
bin_log(card->ctx, "General authenticate (Encrypted Nonce) response data", apdu.resp, apdu.resplen);
if (!d2i_PACE_GEN_AUTH_R(&r_data, if (!d2i_PACE_GEN_AUTH_R(&r_data,
(const unsigned char **) &apdu.resp, apdu.resplen)) { (const unsigned char **) &apdu.resp, apdu.resplen)) {
sc_error(card->ctx, "Could not parse general authenticate response data."); sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Could not parse general authenticate response data.");
r = SC_ERROR_INTERNAL; r = SC_ERROR_INTERNAL;
goto err; goto err;
} }
@@ -437,7 +434,7 @@ static int pace_gen_auth_1_encrypted_nonce(struct sm_ctx *oldpacectx,
|| r_data->auth_token || r_data->auth_token
|| r_data->cur_car || r_data->cur_car
|| r_data->prev_car) { || r_data->prev_car) {
sc_error(card->ctx, "Response data of general authenticate for " sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Response data of general authenticate for "
"step 1 should (only) contain the encrypted nonce."); "step 1 should (only) contain the encrypted nonce.");
r = SC_ERROR_UNKNOWN_DATA_RECEIVED; r = SC_ERROR_UNKNOWN_DATA_RECEIVED;
goto err; goto err;
@@ -520,8 +517,7 @@ static int pace_gen_auth_2_map_nonce(struct sm_ctx *oldpacectx,
apdu.datalen = r; apdu.datalen = r;
apdu.lc = r; apdu.lc = r;
if (card->ctx->debug > SC_LOG_TYPE_DEBUG) bin_log(card->ctx, SC_LOG_DEBUG_NORMAL, "General authenticate (Map Nonce) command data", apdu.data, apdu.datalen);
bin_log(card->ctx, "General authenticate (Map Nonce) command data", apdu.data, apdu.datalen);
apdu.resplen = maxresp; apdu.resplen = maxresp;
apdu.resp = malloc(apdu.resplen); apdu.resp = malloc(apdu.resplen);
@@ -536,12 +532,11 @@ static int pace_gen_auth_2_map_nonce(struct sm_ctx *oldpacectx,
if (r < 0) if (r < 0)
goto err; goto err;
if (card->ctx->debug > SC_LOG_TYPE_DEBUG) bin_log(card->ctx, SC_LOG_DEBUG_NORMAL, "General authenticate (Map Nonce) response data", apdu.resp, apdu.resplen);
bin_log(card->ctx, "General authenticate (Map Nonce) response data", apdu.resp, apdu.resplen);
if (!d2i_PACE_GEN_AUTH_R(&r_data, if (!d2i_PACE_GEN_AUTH_R(&r_data,
(const unsigned char **) &apdu.resp, apdu.resplen)) { (const unsigned char **) &apdu.resp, apdu.resplen)) {
sc_error(card->ctx, "Could not parse general authenticate response data."); sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Could not parse general authenticate response data.");
r = SC_ERROR_INTERNAL; r = SC_ERROR_INTERNAL;
goto err; goto err;
} }
@@ -552,7 +547,7 @@ static int pace_gen_auth_2_map_nonce(struct sm_ctx *oldpacectx,
|| r_data->auth_token || r_data->auth_token
|| r_data->cur_car || r_data->cur_car
|| r_data->prev_car) { || r_data->prev_car) {
sc_error(card->ctx, "Response data of general authenticate for " sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Response data of general authenticate for "
"step 2 should (only) contain the mapping data."); "step 2 should (only) contain the mapping data.");
r = SC_ERROR_UNKNOWN_DATA_RECEIVED; r = SC_ERROR_UNKNOWN_DATA_RECEIVED;
goto err; goto err;
@@ -635,8 +630,7 @@ static int pace_gen_auth_3_perform_key_agreement(
apdu.datalen = r; apdu.datalen = r;
apdu.lc = r; apdu.lc = r;
if (card->ctx->debug > SC_LOG_TYPE_DEBUG) bin_log(card->ctx, SC_LOG_DEBUG_NORMAL, "General authenticate (Perform Key Agreement) command data", apdu.data, apdu.datalen);
bin_log(card->ctx, "General authenticate (Perform Key Agreement) command data", apdu.data, apdu.datalen);
apdu.resplen = maxresp; apdu.resplen = maxresp;
apdu.resp = malloc(apdu.resplen); apdu.resp = malloc(apdu.resplen);
@@ -651,12 +645,11 @@ static int pace_gen_auth_3_perform_key_agreement(
if (r < 0) if (r < 0)
goto err; goto err;
if (card->ctx->debug > SC_LOG_TYPE_DEBUG) bin_log(card->ctx, SC_LOG_DEBUG_NORMAL, "General authenticate (Perform Key Agreement) response data", apdu.resp, apdu.resplen);
bin_log(card->ctx, "General authenticate (Perform Key Agreement) response data", apdu.resp, apdu.resplen);
if (!d2i_PACE_GEN_AUTH_R(&r_data, if (!d2i_PACE_GEN_AUTH_R(&r_data,
(const unsigned char **) &apdu.resp, apdu.resplen)) { (const unsigned char **) &apdu.resp, apdu.resplen)) {
sc_error(card->ctx, "Could not parse general authenticate response data."); sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Could not parse general authenticate response data.");
r = SC_ERROR_INTERNAL; r = SC_ERROR_INTERNAL;
goto err; goto err;
} }
@@ -667,7 +660,7 @@ static int pace_gen_auth_3_perform_key_agreement(
|| r_data->auth_token || r_data->auth_token
|| r_data->cur_car || r_data->cur_car
|| r_data->prev_car) { || r_data->prev_car) {
sc_error(card->ctx, "Response data of general authenticate for " sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Response data of general authenticate for "
"step 3 should (only) contain the ephemeral public key."); "step 3 should (only) contain the ephemeral public key.");
r = SC_ERROR_UNKNOWN_DATA_RECEIVED; r = SC_ERROR_UNKNOWN_DATA_RECEIVED;
goto err; goto err;
@@ -753,8 +746,7 @@ static int pace_gen_auth_4_mutual_authentication(
apdu.datalen = r; apdu.datalen = r;
apdu.lc = r; apdu.lc = r;
if (card->ctx->debug > SC_LOG_TYPE_DEBUG) bin_log(card->ctx, SC_LOG_DEBUG_NORMAL, "General authenticate (Perform Key Agreement) command data", apdu.data, apdu.datalen);
bin_log(card->ctx, "General authenticate (Perform Key Agreement) command data", apdu.data, apdu.datalen);
apdu.resplen = maxresp; apdu.resplen = maxresp;
apdu.resp = malloc(apdu.resplen); apdu.resp = malloc(apdu.resplen);
@@ -769,12 +761,11 @@ static int pace_gen_auth_4_mutual_authentication(
if (r < 0) if (r < 0)
goto err; goto err;
if (card->ctx->debug > SC_LOG_TYPE_DEBUG) bin_log(card->ctx, SC_LOG_DEBUG_NORMAL, "General authenticate (Perform Key Agreement) response data", apdu.resp, apdu.resplen);
bin_log(card->ctx, "General authenticate (Perform Key Agreement) response data", apdu.resp, apdu.resplen);
if (!d2i_PACE_GEN_AUTH_R(&r_data, if (!d2i_PACE_GEN_AUTH_R(&r_data,
(const unsigned char **) &apdu.resp, apdu.resplen)) { (const unsigned char **) &apdu.resp, apdu.resplen)) {
sc_error(card->ctx, "Could not parse general authenticate response data."); sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Could not parse general authenticate response data.");
r = SC_ERROR_INTERNAL; r = SC_ERROR_INTERNAL;
goto err; goto err;
} }
@@ -783,7 +774,7 @@ static int pace_gen_auth_4_mutual_authentication(
|| r_data->mapping_data || r_data->mapping_data
|| r_data->eph_pub_key || r_data->eph_pub_key
|| !r_data->auth_token) { || !r_data->auth_token) {
sc_error(card->ctx, "Response data of general authenticate for " sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Response data of general authenticate for "
"step 4 should (only) contain the authentication token."); "step 4 should (only) contain the authentication token.");
r = SC_ERROR_UNKNOWN_DATA_RECEIVED; r = SC_ERROR_UNKNOWN_DATA_RECEIVED;
goto err; goto err;
@@ -792,7 +783,7 @@ static int pace_gen_auth_4_mutual_authentication(
l = r_data->auth_token->length; l = r_data->auth_token->length;
/* XXX CAR sould be returned as result in some way */ /* XXX CAR sould be returned as result in some way */
if (r_data->cur_car) { if (r_data->cur_car) {
bin_log(card->ctx, "Most recent Certificate Authority Reference", bin_log(card->ctx, SC_LOG_DEBUG_NORMAL, "Most recent Certificate Authority Reference",
r_data->cur_car->data, r_data->cur_car->length); r_data->cur_car->data, r_data->cur_car->length);
*recent_car = malloc(r_data->cur_car->length); *recent_car = malloc(r_data->cur_car->length);
if (!*recent_car) { if (!*recent_car) {
@@ -805,7 +796,7 @@ static int pace_gen_auth_4_mutual_authentication(
} else } else
*recent_car_len = 0; *recent_car_len = 0;
if (r_data->prev_car) { if (r_data->prev_car) {
bin_log(card->ctx, "Previous Certificate Authority Reference", bin_log(card->ctx, SC_LOG_DEBUG_NORMAL, "Previous Certificate Authority Reference",
r_data->prev_car->data, r_data->prev_car->length); r_data->prev_car->data, r_data->prev_car->length);
*prev_car = malloc(r_data->prev_car->length); *prev_car = malloc(r_data->prev_car->length);
if (!*prev_car) { if (!*prev_car) {
@@ -869,13 +860,13 @@ pace_reset_retry_counter(struct sm_ctx *ctx, sc_card_t *card,
if (ask_for_secret && (!new || !new_len)) { if (ask_for_secret && (!new || !new_len)) {
p = malloc(MAX_PIN_LEN+1); p = malloc(MAX_PIN_LEN+1);
if (!p) { if (!p) {
sc_error(card->ctx, "Not enough memory for new PIN.\n"); sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Not enough memory for new PIN.\n");
return SC_ERROR_OUT_OF_MEMORY; return SC_ERROR_OUT_OF_MEMORY;
} }
if (0 > EVP_read_pw_string_min(p, if (0 > EVP_read_pw_string_min(p,
MIN_PIN_LEN, MAX_PIN_LEN+1, MIN_PIN_LEN, MAX_PIN_LEN+1,
"Please enter your new PIN: ", 0)) { "Please enter your new PIN: ", 0)) {
sc_error(card->ctx, "Could not read new PIN.\n"); sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Could not read new PIN.\n");
free(p); free(p);
return SC_ERROR_INTERNAL; return SC_ERROR_INTERNAL;
} }
@@ -921,17 +912,17 @@ get_psec(sc_card_t *card, const char *pin, size_t length_pin, enum s_type pin_id
if (!length_pin || !pin) { if (!length_pin || !pin) {
if (0 > snprintf(buf, sizeof buf, "Please enter your %s: ", if (0 > snprintf(buf, sizeof buf, "Please enter your %s: ",
pace_secret_name(pin_id))) { pace_secret_name(pin_id))) {
sc_error(card->ctx, "Could not create password prompt.\n"); sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Could not create password prompt.\n");
return NULL; return NULL;
} }
p = malloc(MAX_MRZ_LEN); p = malloc(MAX_MRZ_LEN);
if (!p) { if (!p) {
sc_error(card->ctx, "Not enough memory for %s.\n", sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Not enough memory for %s.\n",
pace_secret_name(pin_id)); pace_secret_name(pin_id));
return NULL; return NULL;
} }
if (0 > EVP_read_pw_string_min(p, 0, MAX_MRZ_LEN, buf, 0)) { if (0 > EVP_read_pw_string_min(p, 0, MAX_MRZ_LEN, buf, 0)) {
sc_error(card->ctx, "Could not read %s.\n", sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Could not read %s.\n",
pace_secret_name(pin_id)); pace_secret_name(pin_id));
return NULL; return NULL;
} }
@@ -953,7 +944,7 @@ void ssl_error(sc_context_t *ctx) {
unsigned long r; unsigned long r;
ERR_load_crypto_strings(); ERR_load_crypto_strings();
for (r = ERR_get_error(); r; r = ERR_get_error()) { for (r = ERR_get_error(); r; r = ERR_get_error()) {
sc_error(ctx, ERR_error_string(r, NULL)); sc_debug(ctx, SC_LOG_DEBUG_VERBOSE, ERR_error_string(r, NULL));
} }
ERR_free_strings(); ERR_free_strings();
} }
@@ -989,7 +980,7 @@ int EstablishPACEChannel(struct sm_ctx *oldpacectx, sc_card_t *card,
if (!bio_stdout) if (!bio_stdout)
bio_stdout = BIO_new_fp(stdout, BIO_NOCLOSE); bio_stdout = BIO_new_fp(stdout, BIO_NOCLOSE);
if (!bio_stdout) { if (!bio_stdout) {
sc_error(card->ctx, "Could not create output buffer."); sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Could not create output buffer.");
ssl_error(card->ctx); ssl_error(card->ctx);
r = SC_ERROR_INTERNAL; r = SC_ERROR_INTERNAL;
goto err; goto err;
@@ -1000,24 +991,24 @@ int EstablishPACEChannel(struct sm_ctx *oldpacectx, sc_card_t *card,
pace_input.certificate_description, pace_input.certificate_description,
pace_input.certificate_description_length, "\t")) { pace_input.certificate_description_length, "\t")) {
case -1: case -1:
sc_error(card->ctx, "Could not print certificate description."); sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Could not print certificate description.");
ssl_error(card->ctx); ssl_error(card->ctx);
r = SC_ERROR_INTERNAL; r = SC_ERROR_INTERNAL;
goto err; goto err;
case 0: case 0:
break; break;
case 1: case 1:
sc_error(card->ctx, "Certificate description in " sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Certificate description in "
"HTML format can not (yet) be handled."); "HTML format can not (yet) be handled.");
r = SC_ERROR_NOT_SUPPORTED; r = SC_ERROR_NOT_SUPPORTED;
goto err; goto err;
case 2: case 2:
sc_error(card->ctx, "Certificate description in " sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Certificate description in "
"PDF format can not (yet) be handled."); "PDF format can not (yet) be handled.");
r = SC_ERROR_NOT_SUPPORTED; r = SC_ERROR_NOT_SUPPORTED;
goto err; goto err;
default: default:
sc_error(card->ctx, "Certificate description in " sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Certificate description in "
"unknown format can not (yet) be handled."); "unknown format can not (yet) be handled.");
r = SC_ERROR_NOT_SUPPORTED; r = SC_ERROR_NOT_SUPPORTED;
goto err; goto err;
@@ -1027,7 +1018,7 @@ int EstablishPACEChannel(struct sm_ctx *oldpacectx, sc_card_t *card,
pace_input.certificate_description, pace_input.certificate_description,
pace_input.certificate_description_length); pace_input.certificate_description_length);
if (!hash_cert_desc) { if (!hash_cert_desc) {
sc_error(card->ctx, "Could not hash certificate description."); sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Could not hash certificate description.");
ssl_error(card->ctx); ssl_error(card->ctx);
r = SC_ERROR_INTERNAL; r = SC_ERROR_INTERNAL;
goto err; goto err;
@@ -1035,7 +1026,7 @@ int EstablishPACEChannel(struct sm_ctx *oldpacectx, sc_card_t *card,
p = realloc(pace_output->hash_cert_desc, hash_cert_desc->length); p = realloc(pace_output->hash_cert_desc, hash_cert_desc->length);
if (!p) { if (!p) {
sc_error(card->ctx, "Not enough memory for hash of certificate description.\n"); sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Not enough memory for hash of certificate description.\n");
r = SC_ERROR_OUT_OF_MEMORY; r = SC_ERROR_OUT_OF_MEMORY;
goto err; goto err;
} }
@@ -1050,7 +1041,7 @@ int EstablishPACEChannel(struct sm_ctx *oldpacectx, sc_card_t *card,
if (!bio_stdout) if (!bio_stdout)
bio_stdout = BIO_new_fp(stdout, BIO_NOCLOSE); bio_stdout = BIO_new_fp(stdout, BIO_NOCLOSE);
if (!bio_stdout) { if (!bio_stdout) {
sc_error(card->ctx, "Could not create output buffer."); sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Could not create output buffer.");
ssl_error(card->ctx); ssl_error(card->ctx);
r = SC_ERROR_INTERNAL; r = SC_ERROR_INTERNAL;
goto err; goto err;
@@ -1058,14 +1049,14 @@ int EstablishPACEChannel(struct sm_ctx *oldpacectx, sc_card_t *card,
if (!d2i_CVC_CHAT(&chat, (const unsigned char **) &pace_input.chat, if (!d2i_CVC_CHAT(&chat, (const unsigned char **) &pace_input.chat,
pace_input.chat_length)) { pace_input.chat_length)) {
sc_error(card->ctx, "Could not parse card holder authorization template (CHAT)."); sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Could not parse card holder authorization template (CHAT).");
r = SC_ERROR_INTERNAL; r = SC_ERROR_INTERNAL;
goto err; goto err;
} }
printf("Card holder authorization template (CHAT)\n"); printf("Card holder authorization template (CHAT)\n");
if (!cvc_chat_print(bio_stdout, chat, "\t")) { if (!cvc_chat_print(bio_stdout, chat, "\t")) {
sc_error(card->ctx, "Could not print card holder authorization template (CHAT)."); sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Could not print card holder authorization template (CHAT).");
ssl_error(card->ctx); ssl_error(card->ctx);
r = SC_ERROR_INTERNAL; r = SC_ERROR_INTERNAL;
goto err; goto err;
@@ -1076,16 +1067,16 @@ int EstablishPACEChannel(struct sm_ctx *oldpacectx, sc_card_t *card,
r = get_ef_card_access(card, &pace_output->ef_cardaccess, r = get_ef_card_access(card, &pace_output->ef_cardaccess,
&pace_output->ef_cardaccess_length); &pace_output->ef_cardaccess_length);
if (r < 0) { if (r < 0) {
sc_error(card->ctx, "Could not get EF.CardAccess."); sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Could not get EF.CardAccess.");
goto err; goto err;
} }
} }
bin_log(card->ctx, "EF.CardAccess", pace_output->ef_cardaccess, bin_log(card->ctx, SC_LOG_DEBUG_NORMAL, "EF.CardAccess", pace_output->ef_cardaccess,
pace_output->ef_cardaccess_length); pace_output->ef_cardaccess_length);
if (!parse_ef_card_access(pace_output->ef_cardaccess, if (!parse_ef_card_access(pace_output->ef_cardaccess,
pace_output->ef_cardaccess_length, &info, &static_dp)) { pace_output->ef_cardaccess_length, &info, &static_dp)) {
sc_error(card->ctx, "Could not parse EF.CardAccess."); sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Could not parse EF.CardAccess.");
ssl_error(card->ctx); ssl_error(card->ctx);
r = SC_ERROR_INTERNAL; r = SC_ERROR_INTERNAL;
goto err; goto err;
@@ -1093,7 +1084,7 @@ int EstablishPACEChannel(struct sm_ctx *oldpacectx, sc_card_t *card,
pctx = PACE_CTX_new(); pctx = PACE_CTX_new();
if (!pctx || !PACE_init(pctx, &static_dp, info)) { if (!pctx || !PACE_init(pctx, &static_dp, info)) {
sc_error(card->ctx, "Could not initialize PACE parameters."); sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Could not initialize PACE parameters.");
ssl_error(card->ctx); ssl_error(card->ctx);
r = SC_ERROR_INTERNAL; r = SC_ERROR_INTERNAL;
goto err; goto err;
@@ -1103,7 +1094,7 @@ int EstablishPACEChannel(struct sm_ctx *oldpacectx, sc_card_t *card,
r = pace_mse_set_at(oldpacectx, card, info->protocol, pace_input.pin_id, r = pace_mse_set_at(oldpacectx, card, info->protocol, pace_input.pin_id,
chat, &pace_output->mse_set_at_sw1, &pace_output->mse_set_at_sw2); chat, &pace_output->mse_set_at_sw1, &pace_output->mse_set_at_sw2);
if (r < 0) { if (r < 0) {
sc_error(card->ctx, "Could not select protocol proberties " sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Could not select protocol proberties "
"(MSE: Set AT failed)."); "(MSE: Set AT failed).");
goto err; goto err;
} }
@@ -1115,18 +1106,17 @@ int EstablishPACEChannel(struct sm_ctx *oldpacectx, sc_card_t *card,
r = pace_gen_auth_1_encrypted_nonce(oldpacectx, card, (u8 **) &enc_nonce->data, r = pace_gen_auth_1_encrypted_nonce(oldpacectx, card, (u8 **) &enc_nonce->data,
&enc_nonce->length); &enc_nonce->length);
if (r < 0) { if (r < 0) {
sc_error(card->ctx, "Could not get encrypted nonce from card " sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Could not get encrypted nonce from card "
"(General Authenticate step 1 failed)."); "(General Authenticate step 1 failed).");
goto err; goto err;
} }
if (card->ctx->debug >= SC_LOG_TYPE_DEBUG) bin_log(card->ctx, SC_LOG_DEBUG_NORMAL, "Encrypted nonce from MRTD", (u8 *)enc_nonce->data, enc_nonce->length);
bin_log(card->ctx, "Encrypted nonce from MRTD", (u8 *)enc_nonce->data, enc_nonce->length);
enc_nonce->max = enc_nonce->length; enc_nonce->max = enc_nonce->length;
sec = get_psec(card, (char *) pace_input.pin, pace_input.pin_length, sec = get_psec(card, (char *) pace_input.pin, pace_input.pin_length,
pace_input.pin_id); pace_input.pin_id);
if (!sec) { if (!sec) {
sc_error(card->ctx, "Could not encode PACE secret."); sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Could not encode PACE secret.");
ssl_error(card->ctx); ssl_error(card->ctx);
r = SC_ERROR_INTERNAL; r = SC_ERROR_INTERNAL;
goto err; goto err;
@@ -1137,7 +1127,7 @@ int EstablishPACEChannel(struct sm_ctx *oldpacectx, sc_card_t *card,
mdata_opp = BUF_MEM_new(); mdata_opp = BUF_MEM_new();
mdata = PACE_STEP3A_generate_mapping_data(static_dp, pctx); mdata = PACE_STEP3A_generate_mapping_data(static_dp, pctx);
if (!nonce || !mdata || !mdata_opp) { if (!nonce || !mdata || !mdata_opp) {
sc_error(card->ctx, "Could not generate mapping data."); sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Could not generate mapping data.");
ssl_error(card->ctx); ssl_error(card->ctx);
r = SC_ERROR_INTERNAL; r = SC_ERROR_INTERNAL;
goto err; goto err;
@@ -1145,19 +1135,18 @@ int EstablishPACEChannel(struct sm_ctx *oldpacectx, sc_card_t *card,
r = pace_gen_auth_2_map_nonce(oldpacectx, card, (u8 *) mdata->data, mdata->length, r = pace_gen_auth_2_map_nonce(oldpacectx, card, (u8 *) mdata->data, mdata->length,
(u8 **) &mdata_opp->data, &mdata_opp->length); (u8 **) &mdata_opp->data, &mdata_opp->length);
if (r < 0) { if (r < 0) {
sc_error(card->ctx, "Could not exchange mapping data with card " sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Could not exchange mapping data with card "
"(General Authenticate step 2 failed)."); "(General Authenticate step 2 failed).");
goto err; goto err;
} }
mdata_opp->max = mdata_opp->length; mdata_opp->max = mdata_opp->length;
if (card->ctx->debug >= SC_LOG_TYPE_DEBUG) bin_log(card->ctx, SC_LOG_DEBUG_NORMAL, "Mapping data from MRTD", (u8 *) mdata_opp->data, mdata_opp->length);
bin_log(card->ctx, "Mapping data from MRTD", (u8 *) mdata_opp->data, mdata_opp->length);
eph_dp = PACE_STEP3A_map_dp(static_dp, pctx, nonce, mdata_opp); eph_dp = PACE_STEP3A_map_dp(static_dp, pctx, nonce, mdata_opp);
pub = PACE_STEP3B_generate_ephemeral_key(eph_dp, pctx); pub = PACE_STEP3B_generate_ephemeral_key(eph_dp, pctx);
pub_opp = BUF_MEM_new(); pub_opp = BUF_MEM_new();
if (!eph_dp || !pub || !pub_opp) { if (!eph_dp || !pub || !pub_opp) {
sc_error(card->ctx, "Could not generate ephemeral domain parameter or " sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Could not generate ephemeral domain parameter or "
"ephemeral key pair."); "ephemeral key pair.");
ssl_error(card->ctx); ssl_error(card->ctx);
r = SC_ERROR_INTERNAL; r = SC_ERROR_INTERNAL;
@@ -1166,18 +1155,17 @@ int EstablishPACEChannel(struct sm_ctx *oldpacectx, sc_card_t *card,
r = pace_gen_auth_3_perform_key_agreement(oldpacectx, card, (u8 *) pub->data, pub->length, r = pace_gen_auth_3_perform_key_agreement(oldpacectx, card, (u8 *) pub->data, pub->length,
(u8 **) &pub_opp->data, &pub_opp->length); (u8 **) &pub_opp->data, &pub_opp->length);
if (r < 0) { if (r < 0) {
sc_error(card->ctx, "Could not exchange ephemeral public key with card " sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Could not exchange ephemeral public key with card "
"(General Authenticate step 3 failed)."); "(General Authenticate step 3 failed).");
goto err; goto err;
} }
pub_opp->max = pub_opp->length; pub_opp->max = pub_opp->length;
if (card->ctx->debug >= SC_LOG_TYPE_DEBUG) bin_log(card->ctx, SC_LOG_DEBUG_NORMAL, "Ephemeral public key from MRTD", (u8 *) pub_opp->data, pub_opp->length);
bin_log(card->ctx, "Ephemeral public key from MRTD", (u8 *) pub_opp->data, pub_opp->length);
key = PACE_STEP3B_compute_ephemeral_key(eph_dp, pctx, pub_opp); key = PACE_STEP3B_compute_ephemeral_key(eph_dp, pctx, pub_opp);
if (!key || if (!key ||
!PACE_STEP3C_derive_keys(key, pctx, info, &k_mac, &k_enc)) { !PACE_STEP3C_derive_keys(key, pctx, info, &k_mac, &k_enc)) {
sc_error(card->ctx, "Could not compute ephemeral shared secret or " sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Could not compute ephemeral shared secret or "
"derive keys for encryption and authentication."); "derive keys for encryption and authentication.");
ssl_error(card->ctx); ssl_error(card->ctx);
r = SC_ERROR_INTERNAL; r = SC_ERROR_INTERNAL;
@@ -1187,7 +1175,7 @@ int EstablishPACEChannel(struct sm_ctx *oldpacectx, sc_card_t *card,
eph_dp, info, pub_opp, k_mac); eph_dp, info, pub_opp, k_mac);
token_opp = BUF_MEM_new(); token_opp = BUF_MEM_new();
if (!token || !token_opp) { if (!token || !token_opp) {
sc_error(card->ctx, "Could not compute authentication token."); sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Could not compute authentication token.");
ssl_error(card->ctx); ssl_error(card->ctx);
r = SC_ERROR_INTERNAL; r = SC_ERROR_INTERNAL;
goto err; goto err;
@@ -1198,7 +1186,7 @@ int EstablishPACEChannel(struct sm_ctx *oldpacectx, sc_card_t *card,
&pace_output->previous_car, &pace_output->previous_car_length); &pace_output->previous_car, &pace_output->previous_car_length);
if (r < 0) { if (r < 0) {
sc_error(card->ctx, "Could not exchange authentication token with card " sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Could not exchange authentication token with card "
"(General Authenticate step 4 failed)."); "(General Authenticate step 4 failed).");
goto err; goto err;
} }
@@ -1206,7 +1194,7 @@ int EstablishPACEChannel(struct sm_ctx *oldpacectx, sc_card_t *card,
if (!PACE_STEP3D_verify_authentication_token(pctx, if (!PACE_STEP3D_verify_authentication_token(pctx,
eph_dp, info, k_mac, token_opp)) { eph_dp, info, k_mac, token_opp)) {
sc_error(card->ctx, "Could not verify authentication token."); sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Could not verify authentication token.");
ssl_error(card->ctx); ssl_error(card->ctx);
r = SC_ERROR_INTERNAL; r = SC_ERROR_INTERNAL;
goto err; goto err;
@@ -1216,32 +1204,32 @@ int EstablishPACEChannel(struct sm_ctx *oldpacectx, sc_card_t *card,
comp_pub = PACE_Comp(eph_dp, pctx, pub); comp_pub = PACE_Comp(eph_dp, pctx, pub);
comp_pub_opp = PACE_Comp(eph_dp, pctx, pub_opp); comp_pub_opp = PACE_Comp(eph_dp, pctx, pub_opp);
if (!comp_pub || !comp_pub_opp) { if (!comp_pub || !comp_pub_opp) {
sc_error(card->ctx, "Could not compress public keys for identification."); sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Could not compress public keys for identification.");
ssl_error(card->ctx); ssl_error(card->ctx);
r = SC_ERROR_INTERNAL; r = SC_ERROR_INTERNAL;
goto err; goto err;
} }
p = realloc(pace_output->id_icc, comp_pub_opp->length); p = realloc(pace_output->id_icc, comp_pub_opp->length);
if (!p) { if (!p) {
sc_error(card->ctx, "Not enough memory for ID ICC.\n"); sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Not enough memory for ID ICC.\n");
return SC_ERROR_OUT_OF_MEMORY; return SC_ERROR_OUT_OF_MEMORY;
} }
pace_output->id_icc = p; pace_output->id_icc = p;
pace_output->id_icc_length = comp_pub_opp->length; pace_output->id_icc_length = comp_pub_opp->length;
/* Flawfinder: ignore */ /* Flawfinder: ignore */
memcpy(pace_output->id_icc, comp_pub_opp->data, comp_pub_opp->length); memcpy(pace_output->id_icc, comp_pub_opp->data, comp_pub_opp->length);
bin_log(card->ctx, "ID ICC", pace_output->id_icc, bin_log(card->ctx, SC_LOG_DEBUG_NORMAL, "ID ICC", pace_output->id_icc,
pace_output->id_icc_length); pace_output->id_icc_length);
p = realloc(pace_output->id_pcd, comp_pub->length); p = realloc(pace_output->id_pcd, comp_pub->length);
if (!p) { if (!p) {
sc_error(card->ctx, "Not enough memory for ID PCD.\n"); sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Not enough memory for ID PCD.\n");
return SC_ERROR_OUT_OF_MEMORY; return SC_ERROR_OUT_OF_MEMORY;
} }
pace_output->id_pcd = p; pace_output->id_pcd = p;
pace_output->id_pcd_length = comp_pub->length; pace_output->id_pcd_length = comp_pub->length;
/* Flawfinder: ignore */ /* Flawfinder: ignore */
memcpy(pace_output->id_pcd, comp_pub->data, comp_pub->length); memcpy(pace_output->id_pcd, comp_pub->data, comp_pub->length);
bin_log(card->ctx, "ID PCD", pace_output->id_pcd, bin_log(card->ctx, SC_LOG_DEBUG_NORMAL, "ID PCD", pace_output->id_pcd,
pace_output->id_pcd_length); pace_output->id_pcd_length);
sctx->authentication_ctx = pace_sm_ctx_create(k_mac, sctx->authentication_ctx = pace_sm_ctx_create(k_mac,
@@ -1392,7 +1380,7 @@ pace_sm_encrypt(sc_card_t *card, const struct sm_ctx *ctx,
databuf = BUF_MEM_create_init(data, datalen); databuf = BUF_MEM_create_init(data, datalen);
encbuf = PACE_encrypt(psmctx->ctx, psmctx->ssc, psmctx->key_enc, databuf); encbuf = PACE_encrypt(psmctx->ctx, psmctx->ssc, psmctx->key_enc, databuf);
if (!databuf || !encbuf) { if (!databuf || !encbuf) {
sc_error(card->ctx, "Could not encrypt data."); sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Could not encrypt data.");
ssl_error(card->ctx); ssl_error(card->ctx);
r = SC_ERROR_INTERNAL; r = SC_ERROR_INTERNAL;
goto err; goto err;
@@ -1436,7 +1424,7 @@ pace_sm_decrypt(sc_card_t *card, const struct sm_ctx *ctx,
encbuf = BUF_MEM_create_init(enc, enclen); encbuf = BUF_MEM_create_init(enc, enclen);
databuf = PACE_decrypt(psmctx->ctx, psmctx->ssc, psmctx->key_enc, encbuf); databuf = PACE_decrypt(psmctx->ctx, psmctx->ssc, psmctx->key_enc, encbuf);
if (!encbuf || !databuf) { if (!encbuf || !databuf) {
sc_error(card->ctx, "Could not decrypt data."); sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Could not decrypt data.");
ssl_error(card->ctx); ssl_error(card->ctx);
r = SC_ERROR_INTERNAL; r = SC_ERROR_INTERNAL;
goto err; goto err;
@@ -1480,8 +1468,8 @@ pace_sm_authenticate(sc_card_t *card, const struct sm_ctx *ctx,
macbuf = PACE_authenticate(psmctx->ctx, psmctx->ssc, psmctx->key_mac, macbuf = PACE_authenticate(psmctx->ctx, psmctx->ssc, psmctx->key_mac,
data, datalen); data, datalen);
if (!macbuf) { if (!macbuf) {
sc_error(card->ctx, "Could not compute message authentication code " sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE,
"(MAC)."); "Could not compute message authentication code (MAC).");
ssl_error(card->ctx); ssl_error(card->ctx);
r = SC_ERROR_INTERNAL; r = SC_ERROR_INTERNAL;
goto err; goto err;
@@ -1524,8 +1512,8 @@ pace_sm_verify_authentication(sc_card_t *card, const struct sm_ctx *ctx,
my_mac = PACE_authenticate(psmctx->ctx, psmctx->ssc, psmctx->key_mac, my_mac = PACE_authenticate(psmctx->ctx, psmctx->ssc, psmctx->key_mac,
macdata, macdatalen); macdata, macdatalen);
if (!my_mac) { if (!my_mac) {
sc_error(card->ctx, "Could not compute message authentication code " sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE,
"(MAC) for verification."); "Could not compute message authentication code (MAC) for verification.");
ssl_error(card->ctx); ssl_error(card->ctx);
r = SC_ERROR_INTERNAL; r = SC_ERROR_INTERNAL;
goto err; goto err;
@@ -1534,12 +1522,12 @@ pace_sm_verify_authentication(sc_card_t *card, const struct sm_ctx *ctx,
if (my_mac->length != maclen || if (my_mac->length != maclen ||
memcmp(my_mac->data, mac, maclen) != 0) { memcmp(my_mac->data, mac, maclen) != 0) {
r = SC_ERROR_OBJECT_NOT_VALID; r = SC_ERROR_OBJECT_NOT_VALID;
sc_error(card->ctx, "Authentication data not verified"); sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE,
"Authentication data not verified");
goto err; goto err;
} }
if (card->ctx->debug > SC_LOG_TYPE_DEBUG) sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "Authentication data verified");
sc_debug(card->ctx, "Authentication data verified");
r = SC_SUCCESS; r = SC_SUCCESS;
@@ -1554,13 +1542,13 @@ static int
pace_sm_pre_transmit(sc_card_t *card, const struct sm_ctx *ctx, pace_sm_pre_transmit(sc_card_t *card, const struct sm_ctx *ctx,
sc_apdu_t *apdu) sc_apdu_t *apdu)
{ {
SC_FUNC_RETURN(card->ctx, SC_LOG_TYPE_DEBUG, SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_NORMAL,
increment_ssc(ctx->cipher_ctx)); increment_ssc(ctx->cipher_ctx));
} }
static int pace_sm_post_transmit(sc_card_t *card, const struct sm_ctx *ctx, static int pace_sm_post_transmit(sc_card_t *card, const struct sm_ctx *ctx,
sc_apdu_t *sm_apdu) sc_apdu_t *sm_apdu)
{ {
SC_FUNC_RETURN(card->ctx, SC_LOG_TYPE_DEBUG, SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_NORMAL,
increment_ssc(ctx->cipher_ctx)); increment_ssc(ctx->cipher_ctx));
} }

View File

@@ -24,7 +24,7 @@
#include <pace/pace_lib.h> #include <pace/pace_lib.h>
#include <pace/sm.h> #include <pace/sm.h>
#include <opensc/opensc.h> #include <libopensc/opensc.h>
#include <openssl/bn.h> #include <openssl/bn.h>
#include <openssl/pace.h> #include <openssl/pace.h>

View File

@@ -22,7 +22,7 @@
#ifndef _CCID_SCUTIL_H #ifndef _CCID_SCUTIL_H
#define _CCID_SCUTIL_H #define _CCID_SCUTIL_H
#include <opensc/opensc.h> #include <libopensc/opensc.h>
/** /**
* @brief Initializes smart card context and reader * @brief Initializes smart card context and reader
@@ -68,8 +68,8 @@ int build_apdu(sc_context_t *ctx, const u8 *buf, size_t len, sc_apdu_t *apdu);
* @param[in] data Binary data * @param[in] data Binary data
* @param[in] len Length of \a data * @param[in] len Length of \a data
*/ */
#define bin_log(ctx, label, data, len) \ #define bin_log(ctx, level, label, data, len) \
_bin_log(ctx, SC_LOG_TYPE_DEBUG, __FILE__, __LINE__, __FUNCTION__, label, data, len, NULL) _bin_log(ctx, level, __FILE__, __LINE__, __FUNCTION__, label, data, len, NULL)
/** /**
* @brief Log binary data * @brief Log binary data
* *

View File

@@ -22,7 +22,7 @@
#ifndef _CCID_SM_H #ifndef _CCID_SM_H
#define _CCID_SM_H #define _CCID_SM_H
#include <opensc/opensc.h> #include <libopensc/opensc.h>
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {

View File

@@ -19,7 +19,7 @@
#include "scutil.h" #include "scutil.h"
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <opensc/log.h> #include <libopensc/log.h>
int initialize(int reader_id, const char *cdriver, int verbose, int initialize(int reader_id, const char *cdriver, int verbose,
sc_context_t **ctx, sc_reader_t **reader) sc_context_t **ctx, sc_reader_t **reader)
@@ -38,7 +38,7 @@ int initialize(int reader_id, const char *cdriver, int verbose,
if (cdriver != NULL) { if (cdriver != NULL) {
r = sc_set_card_driver(*ctx, cdriver); r = sc_set_card_driver(*ctx, cdriver);
if (r < 0) { if (r < 0) {
sc_error(*ctx, "Card driver '%s' not found!\n", cdriver); sc_debug(*ctx, SC_LOG_DEBUG_VERBOSE, "Card driver '%s' not found!\n", cdriver);
return r; return r;
} }
} }
@@ -54,14 +54,14 @@ int initialize(int reader_id, const char *cdriver, int verbose,
/* Automatically try to skip to a reader with a card if reader not specified */ /* Automatically try to skip to a reader with a card if reader not specified */
for (i = 0; i < reader_count; i++) { for (i = 0; i < reader_count; i++) {
*reader = sc_ctx_get_reader(*ctx, i); *reader = sc_ctx_get_reader(*ctx, i);
if (sc_detect_card_presence(*reader, 0) & SC_SLOT_CARD_PRESENT) { if (sc_detect_card_presence(*reader) & SC_READER_CARD_PRESENT) {
reader_id = i; reader_id = i;
sc_debug(*ctx, "Using the first reader with a card: %s", (*reader)->name); sc_debug(*ctx, SC_LOG_DEBUG_NORMAL, "Using the first reader with a card: %s", (*reader)->name);
break; break;
} }
} }
if (reader_id >= reader_count) { if (reader_id >= reader_count) {
sc_debug(*ctx, "No card found, using the first reader."); sc_debug(*ctx, SC_LOG_DEBUG_NORMAL, "No card found, using the first reader.");
reader_id = 0; reader_id = 0;
} }
} }
@@ -85,7 +85,7 @@ int build_apdu(sc_context_t *ctx, const u8 *buf, size_t len, sc_apdu_t *apdu)
len0 = len; len0 = len;
if (len < 4) { if (len < 4) {
sc_error(ctx, "APDU too short (must be at least 4 bytes)"); sc_debug(ctx, SC_LOG_DEBUG_VERBOSE, "APDU too short (must be at least 4 bytes)");
return SC_ERROR_INVALID_DATA; return SC_ERROR_INVALID_DATA;
} }
@@ -115,7 +115,7 @@ int build_apdu(sc_context_t *ctx, const u8 *buf, size_t len, sc_apdu_t *apdu)
apdu->lc += *p++; apdu->lc += *p++;
len -= 3; len -= 3;
if (len < apdu->lc) { if (len < apdu->lc) {
sc_error(ctx, "APDU too short (need %lu more bytes)\n", sc_debug(ctx, SC_LOG_DEBUG_VERBOSE, "APDU too short (need %lu more bytes)\n",
(unsigned long) apdu->lc - len); (unsigned long) apdu->lc - len);
return SC_ERROR_INVALID_DATA; return SC_ERROR_INVALID_DATA;
} }
@@ -128,7 +128,7 @@ int build_apdu(sc_context_t *ctx, const u8 *buf, size_t len, sc_apdu_t *apdu)
} else { } else {
/* at this point the apdu has a Lc, so Le is on 2 bytes */ /* at this point the apdu has a Lc, so Le is on 2 bytes */
if (len < 2) { if (len < 2) {
sc_error(ctx, "APDU too short (need 2 more bytes)\n"); sc_debug(ctx, SC_LOG_DEBUG_VERBOSE, "APDU too short (need 2 more bytes)\n");
return SC_ERROR_INVALID_DATA; return SC_ERROR_INVALID_DATA;
} }
apdu->le = (*p++)<<8; apdu->le = (*p++)<<8;
@@ -151,7 +151,7 @@ int build_apdu(sc_context_t *ctx, const u8 *buf, size_t len, sc_apdu_t *apdu)
apdu->lc = *p++; apdu->lc = *p++;
len--; len--;
if (len < apdu->lc) { if (len < apdu->lc) {
sc_error(ctx, "APDU too short (need %lu more bytes)\n", sc_debug(ctx, SC_LOG_DEBUG_VERBOSE, "APDU too short (need %lu more bytes)\n",
(unsigned long) apdu->lc - len); (unsigned long) apdu->lc - len);
return SC_ERROR_INVALID_DATA; return SC_ERROR_INVALID_DATA;
} }
@@ -172,7 +172,7 @@ int build_apdu(sc_context_t *ctx, const u8 *buf, size_t len, sc_apdu_t *apdu)
} }
} }
if (len) { if (len) {
sc_error(ctx, "APDU too long (%lu bytes extra)\n", sc_debug(ctx, SC_LOG_DEBUG_VERBOSE, "APDU too long (%lu bytes extra)\n",
(unsigned long) len); (unsigned long) len);
return SC_ERROR_INVALID_DATA; return SC_ERROR_INVALID_DATA;
} }
@@ -180,7 +180,7 @@ int build_apdu(sc_context_t *ctx, const u8 *buf, size_t len, sc_apdu_t *apdu)
apdu->flags = SC_APDU_FLAGS_NO_GET_RESP|SC_APDU_FLAGS_NO_RETRY_WL; apdu->flags = SC_APDU_FLAGS_NO_GET_RESP|SC_APDU_FLAGS_NO_RETRY_WL;
sc_debug(ctx, "Case %d %s APDU, %lu bytes:\tins=%02x p1=%02x p2=%02x lc=%04x le=%04x", sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "Case %d %s APDU, %lu bytes:\tins=%02x p1=%02x p2=%02x lc=%04x le=%04x",
apdu->cse & SC_APDU_SHORT_MASK, apdu->cse & SC_APDU_SHORT_MASK,
(apdu->cse & SC_APDU_EXT) != 0 ? "extended" : "short", (apdu->cse & SC_APDU_EXT) != 0 ? "extended" : "short",
(unsigned long) len0, apdu->ins, apdu->p1, apdu->p2, apdu->lc, apdu->le); (unsigned long) len0, apdu->ins, apdu->p1, apdu->p2, apdu->lc, apdu->le);
@@ -197,7 +197,7 @@ void _bin_log(sc_context_t *ctx, int type, const char *file, int line,
char buf[1800]; char buf[1800];
if (data) if (data)
sc_hex_dump(ctx, data, len, buf, sizeof buf); sc_hex_dump(ctx, SC_LOG_DEBUG_NORMAL, data, len, buf, sizeof buf);
else else
buf[0] = 0; buf[0] = 0;
if (!f) { if (!f) {

View File

@@ -19,8 +19,8 @@
#include "scutil.h" #include "scutil.h"
#include "sm.h" #include "sm.h"
#include <arpa/inet.h> #include <arpa/inet.h>
#include <opensc/asn1.h> #include <libopensc/asn1.h>
#include <opensc/log.h> #include <libopensc/log.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
@@ -201,25 +201,23 @@ static int format_data(sc_card_t *card, const struct sm_ctx *ctx,
r = add_padding(ctx, data, datalen, &pad_data); r = add_padding(ctx, data, datalen, &pad_data);
if (r < 0) { if (r < 0) {
sc_error(card->ctx, "Could not add padding to data: %s", sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Could not add padding to data: %s",
sc_strerror(r)); sc_strerror(r));
goto err; goto err;
} }
pad_data_len = r; pad_data_len = r;
if (card->ctx->debug > SC_LOG_TYPE_DEBUG) bin_log(card->ctx, SC_LOG_DEBUG_NORMAL, "Data to encrypt", pad_data, pad_data_len);
bin_log(card->ctx, "Data to encrypt", pad_data, pad_data_len);
r = ctx->encrypt(card, ctx, pad_data, pad_data_len, formatted_data); r = ctx->encrypt(card, ctx, pad_data, pad_data_len, formatted_data);
if (r < 0) { if (r < 0) {
sc_error(card->ctx, "Could not encrypt the data"); sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Could not encrypt the data");
goto err; goto err;
} }
if (card->ctx->debug > SC_LOG_TYPE_DEBUG) bin_log(card->ctx, SC_LOG_DEBUG_NORMAL, "Cryptogram", *formatted_data, r);
bin_log(card->ctx, "Cryptogram", *formatted_data, r);
r = prefix_buf(ctx->padding_indicator, *formatted_data, r, formatted_data); r = prefix_buf(ctx->padding_indicator, *formatted_data, r, formatted_data);
if (r < 0) { if (r < 0) {
sc_error(card->ctx, "Could not prepend padding indicator to formatted " sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Could not prepend padding indicator to formatted "
"data: %s", sc_strerror(r)); "data: %s", sc_strerror(r));
goto err; goto err;
} }
@@ -267,20 +265,19 @@ static int sm_encrypt(const struct sm_ctx *ctx, sc_card_t *card,
size_t sm_data_len, fdata_len, mac_data_len, asn1_len, mac_len, le_len; size_t sm_data_len, fdata_len, mac_data_len, asn1_len, mac_len, le_len;
int r; int r;
if (!apdu || !ctx || !card || !card->slot || !sm_apdu) { if (!apdu || !ctx || !card || !card->reader || !sm_apdu) {
r = SC_ERROR_INVALID_ARGUMENTS; r = SC_ERROR_INVALID_ARGUMENTS;
goto err; goto err;
} }
if ((apdu->cla & 0x0C) == 0x0C) { if ((apdu->cla & 0x0C) == 0x0C) {
r = SC_ERROR_INVALID_ARGUMENTS; r = SC_ERROR_INVALID_ARGUMENTS;
sc_error(card->ctx, "Given APDU is already protected with some secure messaging"); sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Given APDU is already protected with some secure messaging");
goto err; goto err;
} }
sc_copy_asn1_entry(c_sm_capdu, sm_capdu); sc_copy_asn1_entry(c_sm_capdu, sm_capdu);
sm_apdu->sensitive = 0;
sm_apdu->control = apdu->control; sm_apdu->control = apdu->control;
sm_apdu->flags = apdu->flags; sm_apdu->flags = apdu->flags;
sm_apdu->cla = apdu->cla|0x0C; sm_apdu->cla = apdu->cla|0x0C;
@@ -289,7 +286,7 @@ static int sm_encrypt(const struct sm_ctx *ctx, sc_card_t *card,
sm_apdu->p2 = apdu->p2; sm_apdu->p2 = apdu->p2;
r = format_head(ctx, sm_apdu, &mac_data); r = format_head(ctx, sm_apdu, &mac_data);
if (r < 0) { if (r < 0) {
sc_error(card->ctx, "Could not format header of SM apdu"); sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Could not format header of SM apdu");
goto err; goto err;
} }
mac_data_len = r; mac_data_len = r;
@@ -302,19 +299,18 @@ static int sm_encrypt(const struct sm_ctx *ctx, sc_card_t *card,
le_len = 1; le_len = 1;
r = format_le(apdu->le, sm_capdu + 1, &le, &le_len); r = format_le(apdu->le, sm_capdu + 1, &le, &le_len);
if (r < 0) { if (r < 0) {
sc_error(card->ctx, "Could not format Le of SM apdu"); sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Could not format Le of SM apdu");
goto err; goto err;
} }
if (card->ctx->debug > SC_LOG_TYPE_DEBUG) bin_log(card->ctx, SC_LOG_DEBUG_NORMAL, "Protected Le (plain)", le, le_len);
bin_log(card->ctx, "Protected Le (plain)", le, le_len);
break; break;
case SC_APDU_CASE_2_EXT: case SC_APDU_CASE_2_EXT:
if (card->slot->active_protocol == SC_PROTO_T0) { if (card->reader->active_protocol == SC_PROTO_T0) {
/* T0 extended APDUs look just like short APDUs */ /* T0 extended APDUs look just like short APDUs */
le_len = 1; le_len = 1;
r = format_le(apdu->le, sm_capdu + 1, &le, &le_len); r = format_le(apdu->le, sm_capdu + 1, &le, &le_len);
if (r < 0) { if (r < 0) {
sc_error(card->ctx, "Could not format Le of SM apdu"); sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Could not format Le of SM apdu");
goto err; goto err;
} }
} else { } else {
@@ -322,50 +318,46 @@ static int sm_encrypt(const struct sm_ctx *ctx, sc_card_t *card,
le_len = 3; le_len = 3;
r = format_le(apdu->le, sm_capdu + 1, &le, &le_len); r = format_le(apdu->le, sm_capdu + 1, &le, &le_len);
if (r < 0) { if (r < 0) {
sc_error(card->ctx, "Could not format Le of SM apdu"); sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Could not format Le of SM apdu");
goto err; goto err;
} }
} }
if (card->ctx->debug > SC_LOG_TYPE_DEBUG) bin_log(card->ctx, SC_LOG_DEBUG_NORMAL, "Protected Le (plain)", le, le_len);
bin_log(card->ctx, "Protected Le (plain)", le, le_len);
break; break;
case SC_APDU_CASE_3_SHORT: case SC_APDU_CASE_3_SHORT:
case SC_APDU_CASE_3_EXT: case SC_APDU_CASE_3_EXT:
r = format_data(card, ctx, apdu->data, apdu->datalen, r = format_data(card, ctx, apdu->data, apdu->datalen,
sm_capdu + 0, &fdata, &fdata_len); sm_capdu + 0, &fdata, &fdata_len);
if (r < 0) { if (r < 0) {
sc_error(card->ctx, "Could not format data of SM apdu"); sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Could not format data of SM apdu");
goto err; goto err;
} }
if (card->ctx->debug > SC_LOG_TYPE_DEBUG) bin_log(card->ctx, SC_LOG_DEBUG_NORMAL, "Padding-content indicator followed by cryptogram (plain)",
bin_log(card->ctx, "Padding-content indicator followed by cryptogram (plain)", fdata, fdata_len);
fdata, fdata_len);
break; break;
case SC_APDU_CASE_4_SHORT: case SC_APDU_CASE_4_SHORT:
/* in case of T0 no Le byte is added */ /* in case of T0 no Le byte is added */
if (card->slot->active_protocol != SC_PROTO_T0) { if (card->reader->active_protocol != SC_PROTO_T0) {
le_len = 1; le_len = 1;
r = format_le(apdu->le, sm_capdu + 1, &le, &le_len); r = format_le(apdu->le, sm_capdu + 1, &le, &le_len);
if (r < 0) { if (r < 0) {
sc_error(card->ctx, "Could not format Le of SM apdu"); sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Could not format Le of SM apdu");
goto err; goto err;
} }
if (card->ctx->debug > SC_LOG_TYPE_DEBUG) bin_log(card->ctx, SC_LOG_DEBUG_NORMAL, "Protected Le (plain)", le, le_len);
bin_log(card->ctx, "Protected Le (plain)", le, le_len);
} }
r = format_data(card, ctx, apdu->data, apdu->datalen, r = format_data(card, ctx, apdu->data, apdu->datalen,
sm_capdu + 0, &fdata, &fdata_len); sm_capdu + 0, &fdata, &fdata_len);
if (r < 0) { if (r < 0) {
sc_error(card->ctx, "Could not format data of SM apdu"); sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Could not format data of SM apdu");
goto err; goto err;
} }
if (card->ctx->debug > SC_LOG_TYPE_DEBUG) bin_log(card->ctx, SC_LOG_DEBUG_NORMAL, "Padding-content indicator followed by cryptogram (plain)",
bin_log(card->ctx, "Padding-content indicator followed by cryptogram (plain)", fdata, fdata_len);
fdata, fdata_len);
break; break;
case SC_APDU_CASE_4_EXT: case SC_APDU_CASE_4_EXT:
if (card->slot->active_protocol == SC_PROTO_T0) { if (card->reader->active_protocol == SC_PROTO_T0) {
/* again a T0 extended case 4 APDU looks just /* again a T0 extended case 4 APDU looks just
* like a short APDU, the additional data is * like a short APDU, the additional data is
* transferred using ENVELOPE and GET RESPONSE */ * transferred using ENVELOPE and GET RESPONSE */
@@ -375,25 +367,23 @@ static int sm_encrypt(const struct sm_ctx *ctx, sc_card_t *card,
le_len = 2; le_len = 2;
r = format_le(apdu->le, sm_capdu + 1, &le, &le_len); r = format_le(apdu->le, sm_capdu + 1, &le, &le_len);
if (r < 0) { if (r < 0) {
sc_error(card->ctx, "Could not format Le of SM apdu"); sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Could not format Le of SM apdu");
goto err; goto err;
} }
if (card->ctx->debug > SC_LOG_TYPE_DEBUG) bin_log(card->ctx, SC_LOG_DEBUG_NORMAL, "Protected Le (plain)", le, le_len);
bin_log(card->ctx, "Protected Le (plain)", le, le_len);
} }
r = format_data(card, ctx, apdu->data, apdu->datalen, r = format_data(card, ctx, apdu->data, apdu->datalen,
sm_capdu + 0, &fdata, &fdata_len); sm_capdu + 0, &fdata, &fdata_len);
if (r < 0) { if (r < 0) {
sc_error(card->ctx, "Could not format data of SM apdu"); sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Could not format data of SM apdu");
goto err; goto err;
} }
if (card->ctx->debug > SC_LOG_TYPE_DEBUG) bin_log(card->ctx, SC_LOG_DEBUG_NORMAL, "Padding-content indicator followed by cryptogram (plain)",
bin_log(card->ctx, "Padding-content indicator followed by cryptogram (plain)", fdata, fdata_len);
fdata, fdata_len);
break; break;
default: default:
sc_error(card->ctx, "Unhandled apdu case"); sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Unhandled apdu case");
r = SC_ERROR_INVALID_DATA; r = SC_ERROR_INVALID_DATA;
goto err; goto err;
} }
@@ -419,20 +409,18 @@ static int sm_encrypt(const struct sm_ctx *ctx, sc_card_t *card,
} }
mac_data_len = r; mac_data_len = r;
} }
if (card->ctx->debug > SC_LOG_TYPE_DEBUG) bin_log(card->ctx, SC_LOG_DEBUG_NORMAL, "Data to authenticate", mac_data, mac_data_len);
bin_log(card->ctx, "Data to authenticate", mac_data, mac_data_len);
r = ctx->authenticate(card, ctx, mac_data, mac_data_len, r = ctx->authenticate(card, ctx, mac_data, mac_data_len,
&mac); &mac);
if (r < 0) { if (r < 0) {
sc_error(card->ctx, "Could not get authentication code"); sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Could not get authentication code");
goto err; goto err;
} }
mac_len = r; mac_len = r;
sc_format_asn1_entry(sm_capdu + 2, mac, &mac_len, sc_format_asn1_entry(sm_capdu + 2, mac, &mac_len,
SC_ASN1_PRESENT); SC_ASN1_PRESENT);
if (card->ctx->debug > SC_LOG_TYPE_DEBUG) bin_log(card->ctx, SC_LOG_DEBUG_NORMAL, "Cryptographic Checksum (plain)", mac, mac_len);
bin_log(card->ctx, "Cryptographic Checksum (plain)", mac, mac_len);
/* format SM apdu */ /* format SM apdu */
@@ -440,7 +428,7 @@ static int sm_encrypt(const struct sm_ctx *ctx, sc_card_t *card,
if (r < 0) if (r < 0)
goto err; goto err;
if (sm_apdu->datalen < sm_data_len) { if (sm_apdu->datalen < sm_data_len) {
sc_error(card->ctx, "Data for SM APDU too long"); sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Data for SM APDU too long");
r = SC_ERROR_OUT_OF_MEMORY; r = SC_ERROR_OUT_OF_MEMORY;
goto err; goto err;
} }
@@ -450,8 +438,7 @@ static int sm_encrypt(const struct sm_ctx *ctx, sc_card_t *card,
sm_apdu->lc = sm_apdu->datalen; sm_apdu->lc = sm_apdu->datalen;
sm_apdu->le = 0; sm_apdu->le = 0;
sm_apdu->cse = SC_APDU_CASE_4; sm_apdu->cse = SC_APDU_CASE_4;
if (card->ctx->debug >= SC_LOG_TYPE_DEBUG) bin_log(card->ctx, SC_LOG_DEBUG_NORMAL, "ASN.1 encoded encrypted APDU data", sm_apdu->data, sm_apdu->datalen);
bin_log(card->ctx, "ASN.1 encoded encrypted APDU data", sm_apdu->data, sm_apdu->datalen);
err: err:
if (fdata) if (fdata)
@@ -515,7 +502,7 @@ static int sm_decrypt(const struct sm_ctx *ctx, sc_card_t *card,
if (r < 0) if (r < 0)
goto err; goto err;
} else { } else {
sc_error(card->ctx, "Cryptographic Checksum missing"); sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Cryptographic Checksum missing");
r = SC_ERROR_ASN1_OBJECT_NOT_FOUND; r = SC_ERROR_ASN1_OBJECT_NOT_FOUND;
goto err; goto err;
} }
@@ -533,12 +520,12 @@ static int sm_decrypt(const struct sm_ctx *ctx, sc_card_t *card,
r = no_padding(ctx->padding_indicator, data, buf_len); r = no_padding(ctx->padding_indicator, data, buf_len);
if (r < 0) { if (r < 0) {
sc_error(card->ctx, "Could not remove padding"); sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Could not remove padding");
goto err; goto err;
} }
if (apdu->resplen < r) { if (apdu->resplen < r) {
sc_error(card->ctx, "Response of SM APDU too long"); sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Response of SM APDU too long");
r = SC_ERROR_OUT_OF_MEMORY; r = SC_ERROR_OUT_OF_MEMORY;
goto err; goto err;
} }
@@ -551,24 +538,22 @@ static int sm_decrypt(const struct sm_ctx *ctx, sc_card_t *card,
if (sm_rapdu[1].flags & SC_ASN1_PRESENT) { if (sm_rapdu[1].flags & SC_ASN1_PRESENT) {
if (sw_len != 2) { if (sw_len != 2) {
sc_error(card->ctx, "Length of processing status bytes must be 2"); sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Length of processing status bytes must be 2");
r = SC_ERROR_ASN1_END_OF_CONTENTS; r = SC_ERROR_ASN1_END_OF_CONTENTS;
goto err; goto err;
} }
apdu->sw1 = sw[0]; apdu->sw1 = sw[0];
apdu->sw2 = sw[1]; apdu->sw2 = sw[1];
} else { } else {
sc_error(card->ctx, "Authenticated status bytes are missing"); sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Authenticated status bytes are missing");
r = SC_ERROR_ASN1_OBJECT_NOT_FOUND; r = SC_ERROR_ASN1_OBJECT_NOT_FOUND;
goto err; goto err;
} }
if (card->ctx->debug >= SC_LOG_TYPE_DEBUG) { sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "Decrypted APDU sw1=%02x sw2=%02x",
sc_debug(card->ctx, "Decrypted APDU sw1=%02x sw2=%02x", apdu->sw1, apdu->sw2);
apdu->sw1, apdu->sw2); bin_log(card->ctx, SC_LOG_DEBUG_NORMAL, "Decrypted APDU response data",
bin_log(card->ctx, "Decrypted APDU response data", apdu->resp, apdu->resplen);
apdu->resp, apdu->resplen);
}
r = SC_SUCCESS; r = SC_SUCCESS;
@@ -595,27 +580,27 @@ int sm_transmit_apdu(struct sm_ctx *sctx, sc_card_t *card,
sm_apdu.resplen = sizeof rbuf; sm_apdu.resplen = sizeof rbuf;
if (!sctx || !sctx->active) { if (!sctx || !sctx->active) {
sc_debug(card->ctx, "Secure messaging disabled."); sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Secure messaging disabled.");
return sc_transmit_apdu(card, apdu); return sc_transmit_apdu(card, apdu);
} }
if ((apdu->cla & 0x0C) == 0x0C) { if ((apdu->cla & 0x0C) == 0x0C) {
sc_debug(card->ctx, "Given APDU is already protected with some secure messaging. Deactivating own SM context."); sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Given APDU is already protected with some secure messaging. Deactivating own SM context.");
sctx->active = 0; sctx->active = 0;
return sc_transmit_apdu(card, apdu); return sc_transmit_apdu(card, apdu);
} }
if (sctx->pre_transmit) if (sctx->pre_transmit)
SC_TEST_RET(card->ctx, sctx->pre_transmit(card, sctx, apdu), SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, sctx->pre_transmit(card, sctx, apdu),
"Could not complete SM specific pre transmit routine"); "Could not complete SM specific pre transmit routine");
SC_TEST_RET(card->ctx, sm_encrypt(sctx, card, apdu, &sm_apdu), SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, sm_encrypt(sctx, card, apdu, &sm_apdu),
"Could not encrypt APDU"); "Could not encrypt APDU");
SC_TEST_RET(card->ctx, sc_transmit_apdu(card, &sm_apdu), SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, sc_transmit_apdu(card, &sm_apdu),
"Could not transmit SM APDU"); "Could not transmit SM APDU");
if (sctx->post_transmit) if (sctx->post_transmit)
SC_TEST_RET(card->ctx, sctx->post_transmit(card, sctx, &sm_apdu), SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, sctx->post_transmit(card, sctx, &sm_apdu),
"Could not complete SM specific post transmit routine"); "Could not complete SM specific post transmit routine");
SC_TEST_RET(card->ctx, sm_decrypt(sctx, card, &sm_apdu, apdu), SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, sm_decrypt(sctx, card, &sm_apdu, apdu),
"Could not decrypt APDU"); "Could not decrypt APDU");
return SC_SUCCESS; return SC_SUCCESS;