diff --git a/ccid/src/ccid-types.h b/ccid/src/ccid-types.h
new file mode 100644
index 0000000..62b2071
--- /dev/null
+++ b/ccid/src/ccid-types.h
@@ -0,0 +1,276 @@
+/*
+ * Copyright (C) 2009 Frank Morgner
+ *
+ * This file is part of ccid.
+ *
+ * ccid is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later
+ * version.
+ *
+ * ccid is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * ccid. If not, see .
+ */
+/**
+ * @file
+ */
+#ifndef _CCID_TYPES_H
+#define _CCID_TYPES_H
+
+#include
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define USB_REQ_CCID 0xA1
+
+#define CCID_CONTROL_ABORT 0x01
+#define CCID_CONTROL_GET_CLOCK_FREQUENCIES 0x02
+#define CCID_CONTROL_GET_DATA_RATES 0x03
+
+#define CCID_OPERATION_VERIFY 0x00;
+#define CCID_OPERATION_MODIFY 0x01;
+#define CCID_ENTRY_VALIDATE 0x02
+
+#define CCID_BERROR_CMD_ABORTED 0xff /** Host aborted the current activity */
+#define CCID_BERROR_ICC_MUTE 0xfe /** CCID timed out while talking to the ICC */
+#define CCID_BERROR_XFR_PARITY_ERROR 0xfd /** Parity error while talking to the ICC */
+#define CCID_BERROR_XFR_OVERRUN 0xfc /** Overrun error while talking to the ICC */
+#define CCID_BERROR_HW_ERROR 0xfb /** An all inclusive hardware error occurred */
+#define CCID_BERROR_BAD_ATR_TS 0xf
+#define CCID_BERROR_BAD_ATR_TCK 0xf
+#define CCID_BERROR_ICC_PROTOCOL_NOT_SUPPORTED 0xf6
+#define CCID_BERROR_ICC_CLASS_NOT_SUPPORTED 0xf5
+#define CCID_BERROR_PROCEDURE_BYTE_CONFLICT 0xf4
+#define CCID_BERROR_DEACTIVATED_PROTOCOL 0xf3
+#define CCID_BERROR_BUSY_WITH_AUTO_SEQUENCE 0xf2 /** Automatic Sequence Ongoing */
+#define CCID_BERROR_PIN_TIMEOUT 0xf0
+#define CCID_BERROR_PIN_CANCELLED 0xef
+#define CCID_BERROR_CMD_SLOT_BUSY 0xe0 /** A second command was sent to a slot which was already processing a command. */
+#define CCID_BERROR_CMD_NOT_SUPPORTED 0x00
+#define CCID_BERROR_OK 0x00
+
+#define CCID_BSTATUS_OK_ACTIVE 0x00 /** No error. An ICC is present and active */
+#define CCID_BSTATUS_OK_INACTIVE 0x01 /** No error. ICC is present and inactive */
+#define CCID_BSTATUS_OK_NOICC 0x02 /** No error. No ICC is present */
+#define CCID_BSTATUS_ERROR_ACTIVE 0x40 /** Failed. An ICC is present and active */
+#define CCID_BSTATUS_ERROR_INACTIVE 0x41 /** Failed. ICC is present and inactive */
+#define CCID_BSTATUS_ERROR_NOICC 0x42 /** Failed. No ICC is present */
+
+#define CCID_WLEVEL_DIRECT __constant_cpu_to_le16(0) /** APDU begins and ends with this command */
+#define CCID_WLEVEL_CHAIN_NEXT_XFRBLOCK __constant_cpu_to_le16(1) /** APDU begins with this command, and continue in the next PC_to_RDR_XfrBlock */
+#define CCID_WLEVEL_CHAIN_END __constant_cpu_to_le16(2) /** abData field continues a command APDU and ends the APDU command */
+#define CCID_WLEVEL_CHAIN_CONTINUE __constant_cpu_to_le16(3) /** abData field continues a command APDU and another block is to follow */
+#define CCID_WLEVEL_RESPONSE_IN_DATABLOCK __constant_cpu_to_le16(0x10) /** empty abData field, continuation of response APDU is expected in the next RDR_to_PC_DataBlock */
+
+#define CCID_PIN_ENCODING_BIN 0x00
+#define CCID_PIN_ENCODING_BCD 0x01
+#define CCID_PIN_ENCODING_ASCII 0x02
+#define CCID_PIN_UNITS_BYTES 0x80
+#define CCID_PIN_JUSTIFY_RIGHT 0x04
+#define CCID_PIN_CONFIRM_NEW 0x01
+#define CCID_PIN_INSERT_OLD 0x02
+#define CCID_PIN_NO_MSG 0x00
+#define CCID_PIN_MSG1 0x01
+#define CCID_PIN_MSG2 0x02
+#define CCID_PIN_MSG_REF 0x03
+#define CCID_PIN_MSG_DEFAULT 0xff
+
+#define CCID_SLOTS_UNCHANGED 0x00
+#define CCID_SLOT1_CARD_PRESENT 0x01
+#define CCID_SLOT1_CHANGED 0x02
+#define CCID_SLOT2_CARD_PRESENT 0x04
+#define CCID_SLOT2_CHANGED 0x08
+#define CCID_SLOT3_CARD_PRESENT 0x10
+#define CCID_SLOT3_CHANGED 0x20
+#define CCID_SLOT4_CARD_PRESENT 0x40
+#define CCID_SLOT4_CHANGED 0x80
+
+#define CCID_EXT_APDU_MAX (4 + 3 + 0xffff + 3)
+#define CCID_SHORT_APDU_MAX (4 + 1 + 0xff + 1)
+
+struct ccid_class_descriptor {
+ uint8_t bLength;
+ uint8_t bDescriptorType;
+ uint16_t bcdCCID;
+ uint8_t bMaxSlotIndex;
+ uint8_t bVoltageSupport;
+ uint32_t dwProtocols;
+ uint32_t dwDefaultClock;
+ uint32_t dwMaximumClock;
+ uint8_t bNumClockSupport;
+ uint32_t dwDataRate;
+ uint32_t dwMaxDataRate;
+ uint8_t bNumDataRatesSupported;
+ uint32_t dwMaxIFSD;
+ uint32_t dwSynchProtocols;
+ uint32_t dwMechanical;
+ uint32_t dwFeatures;
+ uint32_t dwMaxCCIDMessageLength;
+ uint8_t bClassGetResponse;
+ uint8_t bclassEnvelope;
+ uint16_t wLcdLayout;
+ uint8_t bPINSupport;
+ uint8_t bMaxCCIDBusySlots;
+} __attribute__ ((packed));
+
+typedef struct {
+ uint8_t bmFindexDindex;
+ uint8_t bmTCCKST0;
+ uint8_t bGuardTimeT0;
+ uint8_t bWaitingIntegerT0;
+ uint8_t bClockStop;
+} __attribute__ ((packed)) abProtocolDataStructure_T0_t;
+typedef struct {
+ uint8_t bmFindexDindex;
+ uint8_t bmTCCKST1;
+ uint8_t bGuardTimeT1;
+ uint8_t bWaitingIntegersT1;
+ uint8_t bClockStop;
+ uint8_t bIFSC;
+ uint8_t bNadValue;
+} __attribute__ ((packed)) abProtocolDataStructure_T1_t;
+
+typedef struct {
+ uint8_t bTimeOut;
+ uint8_t bmFormatString;
+ uint8_t bmPINBlockString;
+ uint8_t bmPINLengthFormat;
+ uint16_t wPINMaxExtraDigit;
+ uint8_t bEntryValidationCondition;
+ uint8_t bNumberMessage;
+ uint16_t wLangId;
+ uint8_t bMsgIndex;
+ uint8_t bTeoPrologue1;
+ uint16_t bTeoPrologue2;
+} __attribute__ ((packed)) abPINDataStucture_Verification_t;
+typedef struct {
+ uint8_t bTimeOut;
+ uint8_t bmFormatString;
+ uint8_t bmPINBlockString;
+ uint8_t bmPINLengthFormat;
+ uint8_t bInsertionOffsetOld;
+ uint8_t bInsertionOffsetNew;
+ uint16_t wPINMaxExtraDigit;
+ uint8_t bConfirmPIN;
+ uint8_t bEntryValidationCondition;
+ uint8_t bNumberMessage;
+ uint16_t wLangId;
+ uint8_t bMsgIndex1;
+} __attribute__ ((packed)) abPINDataStucture_Modification_t;
+
+typedef struct {
+ uint8_t bMessageType;
+ uint32_t dwLength;
+ uint8_t bSlot;
+ uint8_t bSeq;
+ uint8_t bBWI;
+ uint16_t wLevelParameter;
+} __attribute__ ((packed)) PC_to_RDR_XfrBlock_t;
+typedef struct {
+ uint8_t bMessageType;
+ uint32_t dwLength;
+ uint8_t bSlot;
+ uint8_t bSeq;
+ uint8_t abRFU1;
+ uint16_t abRFU2;
+} __attribute__ ((packed)) PC_to_RDR_IccPowerOff_t;
+typedef struct {
+ uint8_t bMessageType;
+ uint32_t dwLength;
+ uint8_t bSlot;
+ uint8_t bSeq;
+ uint8_t abRFU1;
+ uint16_t abRFU2;
+} __attribute__ ((packed)) PC_to_RDR_GetSlotStatus_t;
+typedef struct {
+ uint8_t bMessageType;
+ uint32_t dwLength;
+ uint8_t bSlot;
+ uint8_t bSeq;
+ uint8_t abRFU1;
+ uint16_t abRFU2;
+} __attribute__ ((packed)) PC_to_RDR_GetParameters_t;
+typedef struct {
+ uint8_t bMessageType;
+ uint32_t dwLength;
+ uint8_t bSlot;
+ uint8_t bSeq;
+ uint8_t abRFU1;
+ uint16_t abRFU2;
+} __attribute__ ((packed)) PC_to_RDR_ResetParameters_t;
+typedef struct {
+ uint8_t bMessageType;
+ uint32_t dwLength;
+ uint8_t bSlot;
+ uint8_t bSeq;
+ uint8_t bProtocolNum;
+ uint16_t abRFU;
+} __attribute__ ((packed)) PC_to_RDR_SetParameters_t;
+typedef struct {
+ uint8_t bMessageType;
+ uint32_t dwLength;
+ uint8_t bSlot;
+ uint8_t bSeq;
+ uint8_t bBWI;
+ uint16_t wLevelParameter;
+} __attribute__ ((packed)) PC_to_RDR_Secure_t;
+typedef struct {
+ uint8_t bMessageType;
+ uint32_t dwLength;
+ uint8_t bSlot;
+ uint8_t bSeq;
+ uint8_t bPowerSelect;
+ uint16_t abRFU;
+} __attribute__ ((packed)) PC_to_RDR_IccPowerOn_t;
+
+typedef struct {
+ uint8_t bMessageType;
+ uint32_t dwLength;
+ uint8_t bSlot;
+ uint8_t bSeq;
+ uint8_t bStatus;
+ uint8_t bError;
+ uint8_t bClockStatus;
+} __attribute__ ((packed)) RDR_to_PC_SlotStatus_t;
+typedef struct {
+ uint8_t bMessageType;
+ uint32_t dwLength;
+ uint8_t bSlot;
+ uint8_t bSeq;
+ uint8_t bStatus;
+ uint8_t bError;
+ uint8_t bChainParameter;
+} __attribute__ ((packed)) RDR_to_PC_DataBlock_t;
+typedef struct {
+ uint8_t bMessageType;
+ uint32_t dwLength;
+ uint8_t bSlot;
+ uint8_t bSeq;
+ uint8_t bStatus;
+ uint8_t bError;
+ uint8_t bProtocolNum;
+} __attribute__ ((packed)) RDR_to_PC_Parameters_t;
+typedef struct {
+ uint8_t bMessageType;
+ uint8_t bmSlotICCState; /* we support 1 slots, so we need 2*1 bits = 1 byte */
+} __attribute__ ((packed)) RDR_to_PC_NotifySlotChange_t;
+
+struct hid_class_descriptor {
+ uint8_t bLength;
+ uint8_t bDescriptorType;
+ uint16_t bcdHID;
+ uint32_t bCountryCode;
+ uint8_t bNumDescriptors;
+} __attribute__ ((packed));
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/ccid/src/ccid.h b/ccid/src/ccid.h
index 3c72766..9c9b006 100644
--- a/ccid/src/ccid.h
+++ b/ccid/src/ccid.h
@@ -24,249 +24,12 @@
#include
#include
+#include "ccid-types.h"
#ifdef __cplusplus
extern "C" {
#endif
-#define USB_REQ_CCID 0xA1
-
-#define CCID_CONTROL_ABORT 0x01
-#define CCID_CONTROL_GET_CLOCK_FREQUENCIES 0x02
-#define CCID_CONTROL_GET_DATA_RATES 0x03
-
-#define CCID_BERROR_CMD_ABORTED 0xff /** Host aborted the current activity */
-#define CCID_BERROR_ICC_MUTE 0xfe /** CCID timed out while talking to the ICC */
-#define CCID_BERROR_XFR_PARITY_ERROR 0xfd /** Parity error while talking to the ICC */
-#define CCID_BERROR_XFR_OVERRUN 0xfc /** Overrun error while talking to the ICC */
-#define CCID_BERROR_HW_ERROR 0xfb /** An all inclusive hardware error occurred */
-#define CCID_BERROR_BAD_ATR_TS 0xf
-#define CCID_BERROR_BAD_ATR_TCK 0xf
-#define CCID_BERROR_ICC_PROTOCOL_NOT_SUPPORTED 0xf6
-#define CCID_BERROR_ICC_CLASS_NOT_SUPPORTED 0xf5
-#define CCID_BERROR_PROCEDURE_BYTE_CONFLICT 0xf4
-#define CCID_BERROR_DEACTIVATED_PROTOCOL 0xf3
-#define CCID_BERROR_BUSY_WITH_AUTO_SEQUENCE 0xf2 /** Automatic Sequence Ongoing */
-#define CCID_BERROR_PIN_TIMEOUT 0xf0
-#define CCID_BERROR_PIN_CANCELLED 0xef
-#define CCID_BERROR_CMD_SLOT_BUSY 0xe0 /** A second command was sent to a slot which was already processing a command. */
-#define CCID_BERROR_CMD_NOT_SUPPORTED 0x00
-#define CCID_BERROR_OK 0x00
-
-#define CCID_BSTATUS_OK_ACTIVE 0x00 /** No error. An ICC is present and active */
-#define CCID_BSTATUS_OK_INACTIVE 0x01 /** No error. ICC is present and inactive */
-#define CCID_BSTATUS_OK_NOICC 0x02 /** No error. No ICC is present */
-#define CCID_BSTATUS_ERROR_ACTIVE 0x40 /** Failed. An ICC is present and active */
-#define CCID_BSTATUS_ERROR_INACTIVE 0x41 /** Failed. ICC is present and inactive */
-#define CCID_BSTATUS_ERROR_NOICC 0x42 /** Failed. No ICC is present */
-
-#define CCID_WLEVEL_DIRECT __constant_cpu_to_le16(0) /** APDU begins and ends with this command */
-#define CCID_WLEVEL_CHAIN_NEXT_XFRBLOCK __constant_cpu_to_le16(1) /** APDU begins with this command, and continue in the next PC_to_RDR_XfrBlock */
-#define CCID_WLEVEL_CHAIN_END __constant_cpu_to_le16(2) /** abData field continues a command APDU and ends the APDU command */
-#define CCID_WLEVEL_CHAIN_CONTINUE __constant_cpu_to_le16(3) /** abData field continues a command APDU and another block is to follow */
-#define CCID_WLEVEL_RESPONSE_IN_DATABLOCK __constant_cpu_to_le16(0x10) /** empty abData field, continuation of response APDU is expected in the next RDR_to_PC_DataBlock */
-
-#define CCID_PIN_ENCODING_BIN 0x00
-#define CCID_PIN_ENCODING_BCD 0x01
-#define CCID_PIN_ENCODING_ASCII 0x02
-#define CCID_PIN_UNITS_BYTES 0x80
-#define CCID_PIN_JUSTIFY_RIGHT 0x04
-#define CCID_PIN_CONFIRM_NEW 0x01
-#define CCID_PIN_INSERT_OLD 0x02
-#define CCID_PIN_NO_MSG 0x00
-#define CCID_PIN_MSG1 0x01
-#define CCID_PIN_MSG2 0x02
-#define CCID_PIN_MSG_REF 0x03
-#define CCID_PIN_MSG_DEFAULT 0xff
-
-#define CCID_SLOTS_UNCHANGED 0x00
-#define CCID_SLOT1_CARD_PRESENT 0x01
-#define CCID_SLOT1_CHANGED 0x02
-#define CCID_SLOT2_CARD_PRESENT 0x04
-#define CCID_SLOT2_CHANGED 0x08
-#define CCID_SLOT3_CARD_PRESENT 0x10
-#define CCID_SLOT3_CHANGED 0x20
-#define CCID_SLOT4_CARD_PRESENT 0x40
-#define CCID_SLOT4_CHANGED 0x80
-
-#define CCID_EXT_APDU_MAX (4 + 3 + 0xffff + 3)
-#define CCID_SHORT_APDU_MAX (4 + 1 + 0xff + 1)
-
-struct ccid_class_descriptor {
- __u8 bLength;
- __u8 bDescriptorType;
- __le16 bcdCCID;
- __u8 bMaxSlotIndex;
- __u8 bVoltageSupport;
- __le32 dwProtocols;
- __le32 dwDefaultClock;
- __le32 dwMaximumClock;
- __u8 bNumClockSupport;
- __le32 dwDataRate;
- __le32 dwMaxDataRate;
- __u8 bNumDataRatesSupported;
- __le32 dwMaxIFSD;
- __le32 dwSynchProtocols;
- __le32 dwMechanical;
- __le32 dwFeatures;
- __le32 dwMaxCCIDMessageLength;
- __u8 bClassGetResponse;
- __u8 bclassEnvelope;
- __le16 wLcdLayout;
- __u8 bPINSupport;
- __u8 bMaxCCIDBusySlots;
-} __attribute__ ((packed));
-
-typedef struct {
- __u8 bmFindexDindex;
- __u8 bmTCCKST0;
- __u8 bGuardTimeT0;
- __u8 bWaitingIntegerT0;
- __u8 bClockStop;
-} __attribute__ ((packed)) abProtocolDataStructure_T0_t;
-typedef struct {
- __u8 bmFindexDindex;
- __u8 bmTCCKST1;
- __u8 bGuardTimeT1;
- __u8 bWaitingIntegersT1;
- __u8 bClockStop;
- __u8 bIFSC;
- __u8 bNadValue;
-} __attribute__ ((packed)) abProtocolDataStructure_T1_t;
-
-typedef struct {
- __u8 bTimeOut;
- __u8 bmFormatString;
- __u8 bmPINBlockString;
- __u8 bmPINLengthFormat;
- __le16 wPINMaxExtraDigit;
- __u8 bEntryValidationCondition;
- __u8 bNumberMessage;
- __le16 wLangId;
- __u8 bMsgIndex;
- __u8 bTeoPrologue1;
- __le16 bTeoPrologue2;
-} __attribute__ ((packed)) abPINDataStucture_Verification_t;
-typedef struct {
- __u8 bTimeOut;
- __u8 bmFormatString;
- __u8 bmPINBlockString;
- __u8 bmPINLengthFormat;
- __u8 bInsertionOffsetOld;
- __u8 bInsertionOffsetNew;
- __le16 wPINMaxExtraDigit;
- __u8 bConfirmPIN;
- __u8 bEntryValidationCondition;
- __u8 bNumberMessage;
- __le16 wLangId;
- __u8 bMsgIndex1;
-} __attribute__ ((packed)) abPINDataStucture_Modification_t;
-
-typedef struct {
- __u8 bMessageType;
- __le32 dwLength;
- __u8 bSlot;
- __u8 bSeq;
- __u8 bBWI;
- __le16 wLevelParameter;
-} __attribute__ ((packed)) PC_to_RDR_XfrBlock_t;
-typedef struct {
- __u8 bMessageType;
- __le32 dwLength;
- __u8 bSlot;
- __u8 bSeq;
- __u8 abRFU1;
- __le16 abRFU2;
-} __attribute__ ((packed)) PC_to_RDR_IccPowerOff_t;
-typedef struct {
- __u8 bMessageType;
- __le32 dwLength;
- __u8 bSlot;
- __u8 bSeq;
- __u8 abRFU1;
- __le16 abRFU2;
-} __attribute__ ((packed)) PC_to_RDR_GetSlotStatus_t;
-typedef struct {
- __u8 bMessageType;
- __le32 dwLength;
- __u8 bSlot;
- __u8 bSeq;
- __u8 abRFU1;
- __le16 abRFU2;
-} __attribute__ ((packed)) PC_to_RDR_GetParameters_t;
-typedef struct {
- __u8 bMessageType;
- __le32 dwLength;
- __u8 bSlot;
- __u8 bSeq;
- __u8 abRFU1;
- __le16 abRFU2;
-} __attribute__ ((packed)) PC_to_RDR_ResetParameters_t;
-typedef struct {
- __u8 bMessageType;
- __le32 dwLength;
- __u8 bSlot;
- __u8 bSeq;
- __u8 bProtocolNum;
- __le16 abRFU;
-} __attribute__ ((packed)) PC_to_RDR_SetParameters_t;
-typedef struct {
- __u8 bMessageType;
- __le32 dwLength;
- __u8 bSlot;
- __u8 bSeq;
- __u8 bBWI;
- __le16 wLevelParameter;
-} __attribute__ ((packed)) PC_to_RDR_Secure_t;
-typedef struct {
- __u8 bMessageType;
- __le32 dwLength;
- __u8 bSlot;
- __u8 bSeq;
- __u8 bPowerSelect;
- __le16 abRFU;
-} __attribute__ ((packed)) PC_to_RDR_IccPowerOn_t;
-
-typedef struct {
- __u8 bMessageType;
- __le32 dwLength;
- __u8 bSlot;
- __u8 bSeq;
- __u8 bStatus;
- __u8 bError;
- __u8 bClockStatus;
-} __attribute__ ((packed)) RDR_to_PC_SlotStatus_t;
-typedef struct {
- __u8 bMessageType;
- __le32 dwLength;
- __u8 bSlot;
- __u8 bSeq;
- __u8 bStatus;
- __u8 bError;
- __u8 bChainParameter;
-} __attribute__ ((packed)) RDR_to_PC_DataBlock_t;
-typedef struct {
- __u8 bMessageType;
- __le32 dwLength;
- __u8 bSlot;
- __u8 bSeq;
- __u8 bStatus;
- __u8 bError;
- __u8 bProtocolNum;
-} __attribute__ ((packed)) RDR_to_PC_Parameters_t;
-typedef struct {
- __u8 bMessageType;
- __u8 bmSlotICCState; /* we support 1 slots, so we need 2*1 bits = 1 byte */
-} __attribute__ ((packed)) RDR_to_PC_NotifySlotChange_t;
-
-struct hid_class_descriptor {
- __u8 bLength;
- __u8 bDescriptorType;
- __le16 bcdHID;
- __le32 bCountryCode;
- __u8 bNumDescriptors;
-} __attribute__ ((packed));
-
/**
* @brief Initializes reader for relaying
*
diff --git a/npa/configure.ac b/npa/configure.ac
index f97c781..a7e9e18 100644
--- a/npa/configure.ac
+++ b/npa/configure.ac
@@ -61,6 +61,7 @@ AC_MSG_CHECKING([for iasecc_sm_external_authentication])
AC_TRY_LINK_FUNC(iasecc_sm_external_authentication,
[ AC_MSG_RESULT([yes]) ],
[ AC_MSG_ERROR([Cannot link against libopensc with SM]) ])
+AC_CHECK_FUNCS([sc_apdu_get_octets])
CPPFLAGS="$saved_CPPFLAGS"
LIBS="$saved_LIBS"
diff --git a/npa/src/Makefile.am b/npa/src/Makefile.am
index 2fe8dbb..00cb360 100644
--- a/npa/src/Makefile.am
+++ b/npa/src/Makefile.am
@@ -11,19 +11,19 @@ do_subst = $(SED) \
BUILT_SOURCES = cmdline.h cmdline.c
-EXTRA_DIST = npa-tool.ggo npa-tool.ggo.in
+EXTRA_DIST = npa-tool.ggo npa-tool.ggo.in opensc/src/libopensc/apdu.c
EXTRA_DIST += $(shell find -L $(top_srcdir)/src/opensc/src -path '*/.git' -prune -o -type f -a -name '*.h' -print)
MAINTAINERCLEANFILES = $(BUILT_SOURCES) npa-tool.ggo $(dist_man1_MANS)
dist_man1_MANS = npa-tool.1
libnpa_la_SOURCES = iso-sm.c scutil.c npa.c boxing.c
-libnpa_la_LIBADD = $(OPENSSL_LIBS) $(OPENPACE_LIBS) $(OPENSC_LIBS)
+libnpa_la_LIBADD = $(OPENSC_LIBS) $(OPENPACE_LIBS) $(OPENSSL_LIBS)
libnpa_la_CFLAGS = $(OPENSSL_CFLAGS) $(OPENPACE_CFLAGS) $(OPENSC_CFLAGS)
libnpa_la_LDFLAGS = -no-undefined
npa_tool_SOURCES = npa-tool.c $(BUILT_SOURCES)
-npa_tool_LDADD = $(OPENSSL_LIBS) $(OPENPACE_LIBS) $(OPENSC_LIBS) libnpa.la
+npa_tool_LDADD = libnpa.la $(OPENSC_LIBS) $(OPENPACE_LIBS) $(OPENSSL_LIBS)
npa_tool_CFLAGS = $(OPENSSL_CFLAGS) $(OPENPACE_CFLAGS) $(OPENSC_CFLAGS)
example_SOURCES = example.c
@@ -54,7 +54,8 @@ noinst_PROGRAMS = example
lib_LTLIBRARIES = libnpa.la
noinst_HEADERS = \
- sslutil.h
+ sslutil.h \
+ ccid-types.h
nobase_include_HEADERS = \
npa/iso-sm.h \
diff --git a/npa/src/boxing.c b/npa/src/boxing.c
index 79b048f..f654865 100644
--- a/npa/src/boxing.c
+++ b/npa/src/boxing.c
@@ -19,13 +19,33 @@
* libnpa. If not, see .
*/
+#include "ccid-types.h"
#include
#include
#include
#include
+#include
#include
#include
+#if _WIN32
+/* FIXME might not always work */
+#define htole16(x) (x)
+#define htole32(x) (x)
+#else
+#ifndef _BSD_SOURCE
+#define _BSD_SOURCE /* See feature_test_macros(7) */
+#endif
+#include
+#endif
+
+#if HAVE_SC_APDU_GET_OCTETS
+#include "libopensc/internal.h"
+#else
+/* Pull request for exporting sc_apdu_get_octets is pending. */
+#include "libopensc/apdu.c"
+#endif
+
static const u8 boxing_cla = 0xff;
static const u8 boxing_ins = 0x9a;
static const u8 boxing_p1 = 0x04;
@@ -209,9 +229,9 @@ int boxing_buf_to_pace_output(sc_context_t *ctx,
sc_copy_asn1_entry(g_EstablishPACEChannelOutput_data,
EstablishPACEChannelOutput_data);
sc_format_asn1_entry(EstablishPACEChannelOutput_data+0,
- &output->result, &result_len, 0);
+ &output->result, &result_len, 0);
sc_format_asn1_entry(EstablishPACEChannelOutput_data+1,
- &status_mse_set_at, &status_mse_set_at_len, 0);
+ &status_mse_set_at, &status_mse_set_at_len, 0);
sc_format_asn1_entry(EstablishPACEChannelOutput_data+2,
&output->ef_cardaccess, &output->ef_cardaccess_length, 0);
sc_format_asn1_entry(EstablishPACEChannelOutput_data+3,
@@ -236,9 +256,256 @@ int boxing_buf_to_pace_output(sc_context_t *ctx,
return SC_SUCCESS;
}
-static int boxing_perform_verify(struct sc_reader *reader, struct sc_pin_cmd_data *data)
+#define CCID_PIN_TIMEOUT 30
+#define CCID_DISPLAY_DEFAULT 0xff
+static int boxing_pin_cmd_to_buf(sc_context_t *ctx,
+ const struct sc_pin_cmd_data *data,
+ unsigned char **pc_to_rdr_secure, size_t *pc_to_rdr_secure_len)
{
- return SC_ERROR_NOT_SUPPORTED;
+ PC_to_RDR_Secure_t *secure;
+ abPINDataStucture_Modification_t *modify;
+ abPINDataStucture_Verification_t *verify;
+ uint16_t wLangId = 0,
+ bTeoPrologue2 = 0,
+ wPINMaxExtraDigit;
+ uint8_t bTimeOut = CCID_PIN_TIMEOUT,
+ bNumberMessage = CCID_DISPLAY_DEFAULT,
+ bTeoPrologue1 = 0,
+ bMsgIndex = 0,
+ bMessageType = 0x69,
+ bSlot = 0,
+ bSeq = 0,
+ bBWI = 0xff,
+ wLevelParameter = 0,
+ bEntryValidationCondition = CCID_ENTRY_VALIDATE,
+ bmFormatString, bmPINLengthFormat, bmPINBlockString;
+ const struct sc_pin_cmd_pin *pin_ref;
+ int r;
+ unsigned char *pinapdu = NULL;
+ size_t pinapdu_len = 0;
+
+ if (!data || !pc_to_rdr_secure || !pc_to_rdr_secure_len) {
+ r = SC_ERROR_INVALID_ARGUMENTS;
+ goto err;
+ }
+
+ pin_ref = data->flags & SC_PIN_CMD_IMPLICIT_CHANGE ?
+ &data->pin2 : &data->pin1;
+
+ wPINMaxExtraDigit = htole16(
+ (0xff & pin_ref->min_length) << 8)
+ | (pin_ref->max_length & 0xff);
+
+ bmFormatString = CCID_PIN_UNITS_BYTES
+ | ((pin_ref->offset & 0xf) << 3);
+ switch (pin_ref->encoding) {
+ case SC_PIN_ENCODING_ASCII:
+ bmFormatString |= CCID_PIN_ENCODING_ASCII;
+ break;
+ case SC_PIN_ENCODING_BCD:
+ bmFormatString |= CCID_PIN_ENCODING_BCD;
+ break;
+ default:
+ r = SC_ERROR_INVALID_ARGUMENTS;
+ goto err;
+ }
+
+ /* GLP PINs expect the effective PIN length from bit 4 */
+ bmPINLengthFormat = pin_ref->encoding == SC_PIN_ENCODING_GLP ?
+ 0x04 : 0x00;
+
+ if (pin_ref->encoding == SC_PIN_ENCODING_GLP) {
+ /* GLP PIN length is encoded in 4 bits and block size is always 8 bytes */
+ bmPINBlockString = 0x40 | 0x08;
+ } else if (pin_ref->encoding == SC_PIN_ENCODING_ASCII && data->flags & SC_PIN_CMD_NEED_PADDING) {
+ bmPINBlockString = pin_ref->pad_length;
+ } else {
+ bmPINBlockString = 0x00;
+ }
+
+ r = sc_apdu_get_octets(ctx, data->apdu, &pinapdu, &pinapdu_len,
+ SC_PROTO_T1);
+ if (r < 0)
+ goto err;
+
+ switch (data->cmd) {
+ case SC_PIN_CMD_VERIFY:
+ *pc_to_rdr_secure_len = sizeof *secure + 1
+ + sizeof *verify + pinapdu_len;
+ break;
+
+ case SC_PIN_CMD_CHANGE:
+ *pc_to_rdr_secure_len = sizeof *secure + 1
+ + sizeof *modify + 3 + pinapdu_len;
+ break;
+
+ default:
+ r = SC_ERROR_INVALID_ARGUMENTS;
+ goto err;
+ }
+
+ *pc_to_rdr_secure = malloc(*pc_to_rdr_secure_len);
+ if (!*pc_to_rdr_secure) {
+ r = SC_ERROR_OUT_OF_MEMORY;
+ goto err;
+ }
+ secure = (PC_to_RDR_Secure_t *) *pc_to_rdr_secure;
+ secure->bMessageType = bMessageType;
+ secure->dwLength = htole32((*pc_to_rdr_secure_len) - sizeof *secure);
+ secure->bSlot = bSlot;
+ secure->bSeq = bSeq;
+ secure->bBWI = bBWI;
+ secure->wLevelParameter = wLevelParameter;
+
+ switch (data->cmd) {
+ case SC_PIN_CMD_VERIFY:
+ /* bPINOperation */
+ *((*pc_to_rdr_secure) + sizeof *secure) = CCID_OPERATION_VERIFY;
+ verify = (abPINDataStucture_Verification_t *)
+ ((*pc_to_rdr_secure) + sizeof *secure + 1);
+ verify->bTimeOut = bTimeOut;
+ verify->bmFormatString = bmFormatString;
+ verify->bmPINBlockString = bmPINBlockString;
+ verify->bmPINLengthFormat = bmPINLengthFormat;
+ verify->wPINMaxExtraDigit = wPINMaxExtraDigit;
+ verify->bEntryValidationCondition = bEntryValidationCondition;
+ verify->bNumberMessage = bNumberMessage;
+ verify->wLangId = wLangId;
+ verify->bMsgIndex = bMsgIndex;
+ verify->bTeoPrologue1 = bTeoPrologue1;
+ verify->bTeoPrologue2 = bTeoPrologue2;
+
+ memcpy((*pc_to_rdr_secure) + sizeof *secure + 1 + sizeof *verify,
+ pinapdu, pinapdu_len);
+ break;
+
+ case SC_PIN_CMD_CHANGE:
+ /* bPINOperation */
+ *((*pc_to_rdr_secure) + sizeof *secure) = CCID_OPERATION_MODIFY;
+ modify = (abPINDataStucture_Modification_t *)
+ ((*pc_to_rdr_secure) + sizeof *secure + 1);
+ modify->bTimeOut = bTimeOut;
+ modify->bmFormatString = bmFormatString;
+ modify->bmPINBlockString = bmPINBlockString;
+ modify->bmPINLengthFormat = bmPINLengthFormat;
+ if (!(data->flags & SC_PIN_CMD_IMPLICIT_CHANGE)
+ && data->pin1.offset) {
+ modify->bInsertionOffsetOld = data->pin1.offset - 5;
+ } else {
+ modify->bInsertionOffsetOld = 0;
+ }
+ modify->bInsertionOffsetNew = data->pin2.offset ? data->pin2.offset - 5 : 0;
+ modify->wPINMaxExtraDigit = wPINMaxExtraDigit;
+ modify->bConfirmPIN = CCID_PIN_CONFIRM_NEW
+ | (data->flags & SC_PIN_CMD_IMPLICIT_CHANGE ? 0 : CCID_PIN_INSERT_OLD);
+ modify->bEntryValidationCondition = bEntryValidationCondition;
+ modify->bNumberMessage = bNumberMessage;
+ modify->wLangId = wLangId;
+ modify->bMsgIndex1 = bMsgIndex;
+ *((*pc_to_rdr_secure) + sizeof *secure + 1 + sizeof *modify + 0) =
+ bTeoPrologue1;
+ *((*pc_to_rdr_secure) + sizeof *secure + 1 + sizeof *modify + 1) =
+ bTeoPrologue1;
+ *((*pc_to_rdr_secure) + sizeof *secure + 1 + sizeof *modify + 2) =
+ bTeoPrologue1;
+
+ memcpy((*pc_to_rdr_secure) + sizeof *secure + 1 + sizeof *modify + 3,
+ pinapdu, pinapdu_len);
+ break;
+
+ default:
+ r = SC_ERROR_INVALID_ARGUMENTS;
+ goto err;
+ }
+
+ r = SC_SUCCESS;
+
+err:
+ free(pinapdu);
+ if (r < 0 && *pc_to_rdr_secure) {
+ free(*pc_to_rdr_secure);
+ *pc_to_rdr_secure = NULL;
+ }
+
+ return r;
+}
+
+#define CCID_BSTATUS_OK_ACTIVE 0x00 /** No error. An ICC is present and active */
+static int boxing_buf_to_verify_result(sc_context_t *ctx,
+ const unsigned char *rdr_to_pc_datablock,
+ size_t rdr_to_pc_datablock_len,
+ sc_apdu_t *apdu)
+{
+ RDR_to_PC_DataBlock_t *datablock =
+ (RDR_to_PC_DataBlock_t *) rdr_to_pc_datablock;
+
+ if (!rdr_to_pc_datablock
+ || rdr_to_pc_datablock_len < sizeof *datablock
+ || datablock->bMessageType != 0x80)
+ return SC_ERROR_UNKNOWN_DATA_RECEIVED;
+
+ if (datablock->bStatus != CCID_BSTATUS_OK_ACTIVE)
+ return SC_ERROR_TRANSMIT_FAILED;
+
+ return sc_apdu_set_resp(ctx, apdu,
+ rdr_to_pc_datablock + sizeof *datablock,
+ htole32(datablock->dwLength));
+}
+
+static int boxing_perform_verify(struct sc_reader *reader,
+ struct sc_pin_cmd_data *data)
+{
+ u8 rbuf[0xff];
+ sc_apdu_t apdu;
+ int r;
+
+ memset(&apdu, 0, sizeof(apdu));
+ apdu.cse = SC_APDU_CASE_4_SHORT;
+ apdu.cla = boxing_cla;
+ apdu.ins = boxing_ins;
+ apdu.p1 = boxing_p1;
+ apdu.p2 = boxing_p2_PC_to_RDR_Secure;
+ apdu.resp = rbuf;
+ apdu.resplen = sizeof rbuf;
+ apdu.le = sizeof rbuf;
+
+ if (!reader || !reader->ops || !reader->ops->transmit) {
+ r = SC_ERROR_NOT_SUPPORTED;
+ goto err;
+ }
+
+ r = boxing_pin_cmd_to_buf(reader->ctx, data,
+ (unsigned char **) &apdu.data, &apdu.datalen);
+ if (r < 0) {
+ sc_debug(reader->ctx, SC_LOG_DEBUG_NORMAL,
+ "Error encoding PC_to_RDR_Secure");
+ goto err;
+ }
+ apdu.lc = apdu.datalen;
+
+ r = SC_SUCCESS;
+
+ r = reader->ops->transmit(reader, &apdu);
+ if (r < 0) {
+ sc_debug(reader->ctx, SC_LOG_DEBUG_NORMAL,
+ "Error performing PC_to_RDR_Secure");
+ goto err;
+ }
+
+ if (apdu.sw1 != 0x90 && apdu.sw2 != 0x00) {
+ sc_debug(reader->ctx, SC_LOG_DEBUG_NORMAL,
+ "Error decoding PC_to_RDR_Secure");
+ r = SC_ERROR_NOT_SUPPORTED;
+ goto err;
+ }
+
+ r = boxing_buf_to_verify_result(reader->ctx, apdu.resp, apdu.resplen,
+ data->apdu);
+
+err:
+ free((unsigned char *) apdu.data);
+
+ return r;
}
static int boxing_perform_pace(struct sc_reader *reader,
@@ -416,7 +683,7 @@ int boxing_pace_capabilities_to_buf(sc_context_t *ctx,
return sc_asn1_encode(ctx, PACECapabilities, asn1, asn1_len);
}
-#ifdef DISABLE_GLOBAL_BOXING_INITIALIZATION
+#ifndef DISABLE_GLOBAL_BOXING_INITIALIZATION
static
#endif
void sc_detect_boxing_cmds(sc_reader_t *reader)
@@ -464,7 +731,7 @@ void sc_detect_boxing_cmds(sc_reader_t *reader)
}
}
-#ifdef DISABLE_GLOBAL_BOXING_INITIALIZATION
+#ifndef DISABLE_GLOBAL_BOXING_INITIALIZATION
void sc_initialize_boxing_cmds(sc_context_t *ctx)
{
sc_reader_t *reader;
diff --git a/npa/src/ccid-types.h b/npa/src/ccid-types.h
new file mode 120000
index 0000000..0e46797
--- /dev/null
+++ b/npa/src/ccid-types.h
@@ -0,0 +1 @@
+../../ccid/src/ccid-types.h
\ No newline at end of file