implemented boxing commands for verify/modify
separates type definitions into ccid-types.h to be accessible in libnpa
This commit is contained in:
276
ccid/src/ccid-types.h
Normal file
276
ccid/src/ccid-types.h
Normal file
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
/**
|
||||
* @file
|
||||
*/
|
||||
#ifndef _CCID_TYPES_H
|
||||
#define _CCID_TYPES_H
|
||||
|
||||
#include <stdint.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_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
|
||||
239
ccid/src/ccid.h
239
ccid/src/ccid.h
@@ -24,249 +24,12 @@
|
||||
|
||||
#include <linux/usb/ch9.h>
|
||||
#include <libopensc/opensc.h>
|
||||
#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
|
||||
*
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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 \
|
||||
|
||||
279
npa/src/boxing.c
279
npa/src/boxing.c
@@ -19,13 +19,33 @@
|
||||
* libnpa. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "ccid-types.h"
|
||||
#include <libopensc/asn1.h>
|
||||
#include <libopensc/log.h>
|
||||
#include <libopensc/opensc.h>
|
||||
#include <libopensc/pace.h>
|
||||
#include <npa/boxing.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#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 <endian.h>
|
||||
#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;
|
||||
|
||||
1
npa/src/ccid-types.h
Symbolic link
1
npa/src/ccid-types.h
Symbolic link
@@ -0,0 +1 @@
|
||||
../../ccid/src/ccid-types.h
|
||||
Reference in New Issue
Block a user