added PACE features to ccid-emulator (untested)
git-svn-id: https://vsmartcard.svn.sourceforge.net/svnroot/vsmartcard@152 96b47cad-a561-4643-ad3b-153ac7d7599c
This commit is contained in:
@@ -88,6 +88,7 @@ fi
|
||||
AC_SUBST(OPENSSL_CFLAGS)
|
||||
AC_SUBST(OPENSSL_LIBS)
|
||||
AM_CONDITIONAL(WITH_PACE, test "${enable_pace}" != "no")
|
||||
AM_COND_IF(WITH_PACE, [AC_DEFINE(WITH_PACE, 1, [enable PACE support])])
|
||||
|
||||
|
||||
# Checks for header files.
|
||||
|
||||
234
ccid/pcsclite_trunk.patch
Normal file
234
ccid/pcsclite_trunk.patch
Normal file
@@ -0,0 +1,234 @@
|
||||
Index: PCSC/src/PCSC/reader.h.in
|
||||
===================================================================
|
||||
--- PCSC/src/PCSC/reader.h.in (Revision 4999)
|
||||
+++ PCSC/src/PCSC/reader.h.in (Arbeitskopie)
|
||||
@@ -121,6 +121,7 @@
|
||||
#define FEATURE_IFD_DISPLAY_PROPERTIES 0x11
|
||||
#define FEATURE_GET_TLV_PROPERTIES 0x12
|
||||
#define FEATURE_CCID_ESC_COMMAND 0x13
|
||||
+#define FEATURE_EXECUTE_PACE 0x20
|
||||
|
||||
/* structures used (but not defined) in PC/SC Part 10:
|
||||
* "IFDs with Secure Pin Entry Capabilities" */
|
||||
Index: Drivers/ccid/src/ifdhandler.c
|
||||
===================================================================
|
||||
--- Drivers/ccid/src/ifdhandler.c (Revision 4999)
|
||||
+++ Drivers/ccid/src/ifdhandler.c (Arbeitskopie)
|
||||
@@ -1384,6 +1384,16 @@
|
||||
iBytesReturned += sizeof(PCSC_TLV_STRUCTURE);
|
||||
}
|
||||
|
||||
+ if (ccid_descriptor -> bPINSupport & CCID_CLASS_PIN_SPECIAL)
|
||||
+ {
|
||||
+ pcsc_tlv -> tag = FEATURE_EXECUTE_PACE;
|
||||
+ pcsc_tlv -> length = 0x04; /* always 0x04 */
|
||||
+ pcsc_tlv -> value = htonl(IOCTL_FEATURE_EXECUTE_PACE);
|
||||
+
|
||||
+ pcsc_tlv++;
|
||||
+ iBytesReturned += sizeof(PCSC_TLV_STRUCTURE);
|
||||
+ }
|
||||
+
|
||||
/* We can always forward wLcdLayout */
|
||||
pcsc_tlv -> tag = FEATURE_IFD_PIN_PROPERTIES;
|
||||
pcsc_tlv -> length = 0x04; /* always 0x04 */
|
||||
@@ -1548,6 +1558,16 @@
|
||||
}
|
||||
}
|
||||
|
||||
+ if (IOCTL_FEATURE_EXECUTE_PACE == dwControlCode)
|
||||
+ {
|
||||
+ unsigned int iBytesReturned;
|
||||
+
|
||||
+ iBytesReturned = RxLength;
|
||||
+ return_value = SecurePINSpecialVerify(reader_index, TxBuffer, TxLength,
|
||||
+ RxBuffer, &iBytesReturned);
|
||||
+ *pdwBytesReturned = iBytesReturned;
|
||||
+ }
|
||||
+
|
||||
if (IFD_SUCCESS != return_value)
|
||||
*pdwBytesReturned = 0;
|
||||
|
||||
Index: Drivers/ccid/src/commands.c
|
||||
===================================================================
|
||||
--- Drivers/ccid/src/commands.c (Revision 4999)
|
||||
+++ Drivers/ccid/src/commands.c (Arbeitskopie)
|
||||
@@ -68,7 +68,13 @@
|
||||
unsigned int tx_length, unsigned char tx_buffer[], unsigned int *rx_length,
|
||||
unsigned char rx_buffer[]);
|
||||
|
||||
+static RESPONSECODE SecurePINSpecial(unsigned int reader_index,
|
||||
+ const unsigned char TxBuffer[], unsigned int TxLength,
|
||||
+ unsigned char RxBuffer[], unsigned int *RxLength,
|
||||
+ unsigned char bPINOperation);
|
||||
+
|
||||
static void i2dw(int value, unsigned char *buffer);
|
||||
+static void i2w(int value, unsigned char *buffer);
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
@@ -712,7 +718,96 @@
|
||||
return ret;
|
||||
} /* SecurePINModify */
|
||||
|
||||
+RESPONSECODE SecurePINSpecialVerify(unsigned int reader_index,
|
||||
+ const unsigned char TxBuffer[], unsigned int TxLength,
|
||||
+ unsigned char RxBuffer[], unsigned int *RxLength)
|
||||
+{
|
||||
+ /* bPINOperation: PIN Special Capabilities */
|
||||
+ return SecurePINSpecial(reader_index, TxBuffer, TxLength, RxBuffer,
|
||||
+ RxLength, 0x11);
|
||||
+}
|
||||
|
||||
+RESPONSECODE SecurePINSpecialCapabilities(unsigned int reader_index,
|
||||
+ const unsigned char TxBuffer[], unsigned int TxLength,
|
||||
+ unsigned char RxBuffer[], unsigned int *RxLength)
|
||||
+{
|
||||
+ /* bPINOperation: PIN Special Capabilities */
|
||||
+ return SecurePINSpecial(reader_index, TxBuffer, TxLength, RxBuffer,
|
||||
+ RxLength, 0x10);
|
||||
+}
|
||||
+
|
||||
+static RESPONSECODE SecurePINSpecial(unsigned int reader_index,
|
||||
+ const unsigned char TxBuffer[], unsigned int TxLength,
|
||||
+ unsigned char RxBuffer[], unsigned int *RxLength,
|
||||
+ unsigned char bPINOperation)
|
||||
+{
|
||||
+ unsigned char cmd[11+CMD_BUF_SIZE];
|
||||
+ int length;
|
||||
+ _ccid_descriptor *ccid_descriptor = get_ccid_descriptor(reader_index);
|
||||
+ status_t res;
|
||||
+
|
||||
+ cmd[0] = 0x69; /* Secure */
|
||||
+ i2dw(TxLength, cmd+1); /* dwLength */
|
||||
+ cmd[5] = ccid_descriptor->bCurrentSlotIndex; /* slot number */
|
||||
+ cmd[6] = (*ccid_descriptor->pbSeq)++;
|
||||
+ cmd[7] = 0; /* bBWI */
|
||||
+ cmd[8] = 0; /* wLevelParameter */
|
||||
+ cmd[9] = 0;
|
||||
+ cmd[10] = bPINOperation;
|
||||
+
|
||||
+ memcpy(cmd + 11, TxBuffer, TxLength);
|
||||
+
|
||||
+ res = WritePort(reader_index, 11 + TxLength, cmd);
|
||||
+ if (res != STATUS_SUCCESS)
|
||||
+ {
|
||||
+ if (STATUS_NO_SUCH_DEVICE == res)
|
||||
+ return IFD_NO_SUCH_DEVICE;
|
||||
+ return IFD_COMMUNICATION_ERROR;
|
||||
+ }
|
||||
+
|
||||
+ length = sizeof(cmd);
|
||||
+ res = ReadPort(reader_index, &length, cmd);
|
||||
+ if (res != STATUS_SUCCESS)
|
||||
+ {
|
||||
+ if (STATUS_NO_SUCH_DEVICE == res)
|
||||
+ return IFD_NO_SUCH_DEVICE;
|
||||
+ return IFD_COMMUNICATION_ERROR;
|
||||
+ }
|
||||
+
|
||||
+ if (length < STATUS_OFFSET+1)
|
||||
+ {
|
||||
+ DEBUG_CRITICAL2("Not enough data received: %d bytes", length);
|
||||
+ return IFD_COMMUNICATION_ERROR;
|
||||
+ }
|
||||
+
|
||||
+ if (cmd[STATUS_OFFSET] & CCID_COMMAND_FAILED)
|
||||
+ {
|
||||
+ ccid_error(cmd[ERROR_OFFSET], __FILE__, __LINE__, __FUNCTION__); /* bError */
|
||||
+ return IFD_COMMUNICATION_ERROR;
|
||||
+ }
|
||||
+
|
||||
+ /* we have read less (or more) data than the CCID frame says to contain */
|
||||
+ if (length-10 != dw2i(cmd, 1))
|
||||
+ {
|
||||
+ DEBUG_CRITICAL3("Can't read all data (%d out of %d expected)",
|
||||
+ length-10, dw2i(cmd, 1));
|
||||
+ return IFD_COMMUNICATION_ERROR;
|
||||
+ }
|
||||
+
|
||||
+ length = dw2i(cmd, 1);
|
||||
+ if (length <= *RxLength)
|
||||
+ *RxLength = length;
|
||||
+ else
|
||||
+ {
|
||||
+ DEBUG_CRITICAL2("overrun by %d bytes", length - *RxLength);
|
||||
+ length = *RxLength;
|
||||
+ return IFD_ERROR_INSUFFICIENT_BUFFER;
|
||||
+ }
|
||||
+
|
||||
+ return IFD_SUCCESS;
|
||||
+}
|
||||
+
|
||||
+
|
||||
/*****************************************************************************
|
||||
*
|
||||
* Escape
|
||||
@@ -729,7 +824,7 @@
|
||||
int old_read_timeout;
|
||||
_ccid_descriptor *ccid_descriptor = get_ccid_descriptor(reader_index);
|
||||
|
||||
- old_read_timeout = ccid_descriptor -> readTimeout;
|
||||
+ old_read_timeout= ccid_descriptor -> readTimeout;
|
||||
ccid_descriptor -> readTimeout = 30*1000; /* 30 seconds */
|
||||
|
||||
again:
|
||||
@@ -2113,3 +2208,15 @@
|
||||
buffer[3] = (value >> 24) & 0xFF;
|
||||
} /* i2dw */
|
||||
|
||||
+
|
||||
+/*****************************************************************************
|
||||
+ *
|
||||
+ * i2w
|
||||
+ *
|
||||
+ ****************************************************************************/
|
||||
+static void i2w(int value, unsigned char buffer[])
|
||||
+{
|
||||
+ buffer[0] = value & 0xFF;
|
||||
+ buffer[1] = (value >> 8) & 0xFF;
|
||||
+} /* i2w */
|
||||
+
|
||||
Index: Drivers/ccid/src/commands.h
|
||||
===================================================================
|
||||
--- Drivers/ccid/src/commands.h (Revision 4999)
|
||||
+++ Drivers/ccid/src/commands.h (Arbeitskopie)
|
||||
@@ -37,6 +37,14 @@
|
||||
unsigned char TxBuffer[], unsigned int TxLength,
|
||||
unsigned char RxBuffer[], unsigned int *RxLength);
|
||||
|
||||
+RESPONSECODE SecurePINSpecialCapabilities(unsigned int reader_index,
|
||||
+ const unsigned char TxBuffer[], unsigned int TxLength,
|
||||
+ unsigned char RxBuffer[], unsigned int *RxLength);
|
||||
+
|
||||
+RESPONSECODE SecurePINSpecialVerify(unsigned int reader_index,
|
||||
+ const unsigned char TxBuffer[], unsigned int TxLength,
|
||||
+ unsigned char RxBuffer[], unsigned int *RxLength);
|
||||
+
|
||||
RESPONSECODE CmdEscape(unsigned int reader_index,
|
||||
const unsigned char TxBuffer[], unsigned int TxLength,
|
||||
unsigned char RxBuffer[], unsigned int *RxLength);
|
||||
Index: Drivers/ccid/src/ccid.h
|
||||
===================================================================
|
||||
--- Drivers/ccid/src/ccid.h (Revision 4999)
|
||||
+++ Drivers/ccid/src/ccid.h (Arbeitskopie)
|
||||
@@ -144,6 +144,7 @@
|
||||
/* Features from bPINSupport */
|
||||
#define CCID_CLASS_PIN_VERIFY 0x01
|
||||
#define CCID_CLASS_PIN_MODIFY 0x02
|
||||
+#define CCID_CLASS_PIN_SPECIAL 0x10
|
||||
|
||||
/* See CCID specs ch. 4.2.1 */
|
||||
#define CCID_ICC_PRESENT_ACTIVE 0x00 /* 00 0000 00 */
|
||||
Index: Drivers/ccid/src/ccid_ifdhandler.h
|
||||
===================================================================
|
||||
--- Drivers/ccid/src/ccid_ifdhandler.h (Revision 4999)
|
||||
+++ Drivers/ccid/src/ccid_ifdhandler.h (Arbeitskopie)
|
||||
@@ -37,6 +37,8 @@
|
||||
SCARD_CTL_CODE(FEATURE_IFD_PIN_PROPERTIES + CLASS2_IOCTL_MAGIC)
|
||||
#define IOCTL_FEATURE_GET_TLV_PROPERTIES \
|
||||
SCARD_CTL_CODE(FEATURE_GET_TLV_PROPERTIES + CLASS2_IOCTL_MAGIC)
|
||||
+#define IOCTL_FEATURE_EXECUTE_PACE \
|
||||
+ SCARD_CTL_CODE(FEATURE_EXECUTE_PACE + CLASS2_IOCTL_MAGIC)
|
||||
|
||||
#define DRIVER_OPTION_CCID_EXCHANGE_AUTHORIZED 1
|
||||
#define DRIVER_OPTION_GEMPC_TWIN_KEY_APDU 2
|
||||
@@ -1,13 +1,5 @@
|
||||
IFDNFC_LIB = libifdnfc.$(DYN_LIB_EXT)
|
||||
|
||||
bin_PROGRAMS =
|
||||
if WITH_CCID
|
||||
bin_PROGRAMS += ccid-emulator
|
||||
endif
|
||||
if WITH_PACE
|
||||
bin_PROGRAMS += pace-tool
|
||||
endif
|
||||
|
||||
ccid_emulator_SOURCES = ccid.c usbstring.c usb.c binutil.c scutil.c
|
||||
ccid_emulator_LDADD = $(OPENSC_LIBS) $(PTHREAD_LIBS)
|
||||
ccid_emulator_CFLAGS = $(OPENSC_CFLAGS) $(PTHREAD_CFLAGS)
|
||||
@@ -16,4 +8,16 @@ pace_tool_SOURCES = sm.c pace-tool.c binutil.c scutil.c pace.c pace_lib.c
|
||||
pace_tool_LDADD = $(OPENSC_LIBS) $(OPENSSL_LIBS)
|
||||
pace_tool_CFLAGS = $(OPENSC_CFLAGS) $(OPENSSL_CFLAGS)
|
||||
|
||||
bin_PROGRAMS =
|
||||
if WITH_CCID
|
||||
bin_PROGRAMS += ccid-emulator
|
||||
endif
|
||||
if WITH_PACE
|
||||
bin_PROGRAMS += pace-tool
|
||||
|
||||
ccid_emulator_SOURCES += sm.c pace.c pace_lib.c
|
||||
ccid_emulator_LDADD += $(OPENSSL_LIBS)
|
||||
ccid_emulator_CFLAGS += $(OPENSSL_CFLAGS)
|
||||
endif
|
||||
|
||||
noinst_HEADERS = binutil.h ccid.h pace.h pace_lib.h scutil.h sm.h usbstring.h
|
||||
|
||||
@@ -28,6 +28,14 @@
|
||||
|
||||
#include "ccid.h"
|
||||
#include "scutil.h"
|
||||
#include "config.h"
|
||||
|
||||
#ifdef WITH_PACE
|
||||
#include "pace.h"
|
||||
#include "sm.h"
|
||||
|
||||
struct sm_ctx sctx;
|
||||
#endif
|
||||
|
||||
static sc_context_t *ctx = NULL;
|
||||
static sc_card_t *card_in_slot[SC_MAX_SLOTS];
|
||||
@@ -127,6 +135,10 @@ int ccid_initialize(int reader_id, const char *cdriver, int verbose)
|
||||
|
||||
ccid_desc.bMaxSlotIndex = reader->slot_count - 1;
|
||||
|
||||
#ifdef WITH_PACE
|
||||
memset(&sctx, 0, sizeof(sctx));
|
||||
#endif
|
||||
|
||||
return SC_SUCCESS;
|
||||
}
|
||||
|
||||
@@ -140,6 +152,11 @@ void ccid_shutdown()
|
||||
}
|
||||
if (ctx)
|
||||
sc_release_context(ctx);
|
||||
|
||||
#ifdef WITH_PACE
|
||||
pace_sm_ctx_clear_free(sctx.cipher_ctx);
|
||||
memset(&sctx, 0, sizeof(sctx));
|
||||
#endif
|
||||
}
|
||||
|
||||
static int get_rapdu(sc_apdu_t *apdu, size_t slot, __u8 **buf, size_t *resplen)
|
||||
@@ -153,13 +170,18 @@ static int get_rapdu(sc_apdu_t *apdu, size_t slot, __u8 **buf, size_t *resplen)
|
||||
|
||||
apdu->resplen = apdu->le;
|
||||
/* Get two more bytes to later use as return buffer including sw1 and sw2 */
|
||||
apdu->resp = malloc(apdu->resplen + sizeof(__u8) + sizeof(__u8));
|
||||
apdu->resp = realloc(*buf, apdu->resplen + sizeof(__u8) + sizeof(__u8));
|
||||
if (!apdu->resp) {
|
||||
sc_result = SC_ERROR_OUT_OF_MEMORY;
|
||||
goto err;
|
||||
}
|
||||
*buf = apdu->resp;
|
||||
|
||||
#ifdef WITH_PACE
|
||||
sc_result = sm_transmit_apdu(&sctx, card_in_slot[slot], apdu);
|
||||
#else
|
||||
sc_result = sc_transmit_apdu(card_in_slot[slot], apdu);
|
||||
#endif
|
||||
if (sc_result < 0) {
|
||||
goto err;
|
||||
}
|
||||
@@ -179,13 +201,9 @@ static int get_rapdu(sc_apdu_t *apdu, size_t slot, __u8 **buf, size_t *resplen)
|
||||
(unsigned int) *resplen, !*resplen ? "" : "s",
|
||||
apdu->sw1, apdu->sw2);
|
||||
|
||||
SC_FUNC_RETURN(ctx, SC_LOG_TYPE_VERBOSE, SC_SUCCESS);
|
||||
sc_result = SC_SUCCESS;
|
||||
|
||||
err:
|
||||
if (apdu->resp) {
|
||||
free(apdu->resp);
|
||||
}
|
||||
|
||||
SC_FUNC_RETURN(ctx, SC_LOG_TYPE_VERBOSE, sc_result);
|
||||
}
|
||||
|
||||
@@ -425,7 +443,7 @@ perform_PC_to_RDR_XfrBlock(const u8 *in, __u8** out, size_t *outlen)
|
||||
int sc_result, r;
|
||||
size_t resplen = 0;
|
||||
sc_apdu_t apdu;
|
||||
__u8 *abDataOut;
|
||||
__u8 *abDataOut = NULL;
|
||||
RDR_to_PC_DataBlock_t *result;
|
||||
|
||||
if (!in || !out || !outlen)
|
||||
@@ -739,7 +757,7 @@ perform_PC_to_RDR_Secure(const __u8 *in, __u8** out, size_t *outlen)
|
||||
sc_ui_hints_t hints;
|
||||
const PC_to_RDR_Secure_t *request = (PC_to_RDR_Secure_t *) in;
|
||||
const __u8* abData = in + sizeof *request;
|
||||
u8 *abDataOut;
|
||||
u8 *abDataOut = NULL;
|
||||
size_t resplen = 0;
|
||||
RDR_to_PC_DataBlock_t *result;
|
||||
|
||||
@@ -792,6 +810,20 @@ perform_PC_to_RDR_Secure(const __u8 *in, __u8** out, size_t *outlen)
|
||||
abPINApdu = (__u8*) modify + sizeof(*modify);
|
||||
apdulen = __le32_to_cpu(request->dwLength) - sizeof(*modify) - sizeof(__u8);
|
||||
break;
|
||||
#ifdef WITH_PACE
|
||||
case 0x10:
|
||||
sc_result =
|
||||
GetReadersPACECapabilities(card_in_slot[request->bSlot],
|
||||
abData + 1, &abDataOut, &resplen);
|
||||
goto err;
|
||||
break;
|
||||
case 0x11:
|
||||
sc_result = EstablishPACEChannel(&sctx,
|
||||
card_in_slot[request->bSlot], abData + 1, &abDataOut,
|
||||
&resplen, &sctx);
|
||||
goto err;
|
||||
break;
|
||||
#endif
|
||||
case 0x04:
|
||||
// Cancel PIN function
|
||||
default:
|
||||
|
||||
@@ -869,6 +869,9 @@ int EstablishPACEChannel(const struct sm_ctx *oldpacectx, sc_card_t *card,
|
||||
r = SC_ERROR_OUT_OF_MEMORY;
|
||||
goto err;
|
||||
}
|
||||
r = reset_ssc(sctx->authentication_ctx);
|
||||
if (r < 0)
|
||||
goto err;
|
||||
sctx->cipher_ctx = sctx->authentication_ctx;
|
||||
sctx->authenticate = pace_sm_authenticate;
|
||||
sctx->encrypt = pace_sm_encrypt;
|
||||
@@ -878,8 +881,7 @@ int EstablishPACEChannel(const struct sm_ctx *oldpacectx, sc_card_t *card,
|
||||
sctx->post_transmit = pace_sm_post_transmit;
|
||||
sctx->padding_indicator = SM_ISO_PADDING;
|
||||
sctx->block_length = EVP_CIPHER_block_size(pctx->cipher);
|
||||
|
||||
r = reset_ssc(sctx->authentication_ctx);
|
||||
sctx->active = 1;
|
||||
|
||||
err:
|
||||
if (ef_cardaccess && !second_execution)
|
||||
|
||||
@@ -583,6 +583,11 @@ int sm_transmit_apdu(const struct sm_ctx *sctx, sc_card_t *card,
|
||||
SC_FUNC_RETURN(card->ctx, SC_LOG_TYPE_DEBUG, sc_transmit_apdu(card, apdu));
|
||||
}
|
||||
|
||||
if (!sctx || !sctx->active) {
|
||||
sc_debug(card->ctx, "Secure messaging disabled.");
|
||||
SC_FUNC_RETURN(card->ctx, SC_LOG_TYPE_DEBUG, sc_transmit_apdu(card, apdu));
|
||||
}
|
||||
|
||||
if (sctx->pre_transmit)
|
||||
SC_TEST_RET(card->ctx, sctx->pre_transmit(card, sctx, apdu),
|
||||
"Could not complete SM specific pre transmit routine");
|
||||
|
||||
@@ -29,6 +29,8 @@ extern "C" {
|
||||
#define SM_NO_PADDING 0x02
|
||||
|
||||
struct sm_ctx {
|
||||
unsigned char active;
|
||||
|
||||
u8 padding_indicator;
|
||||
size_t block_length;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user