Added support for PIN commands via escape commands
As defined in BSI TR-03119 to issue SCardTransmit (with Uses Pseudo-APDU) instead of SCardControl (with FEATURE_VERIFY_PIN_DIRECT). It allows using a very basic PC/SC reader driver without special support for PIN verification or modification (such as the default CCID driver on Windows). Also gets IFD vendor information via escape commands. PC/SC's Get Uid command is now only triggered if enable_escape = true; was set by the user to allow disabling wrapped commands on broken readers (see https://github.com/OpenSC/OpenSC/issues/810)
This commit is contained in:
parent
a4f64d9439
commit
40acedcc21
|
@ -103,6 +103,12 @@ app default {
|
|||
# Default: true
|
||||
# enable_pinpad = false;
|
||||
#
|
||||
# Detect reader capabilities with escape commands (wrapped APDUs with
|
||||
# CLA=0xFF as defined by PC/SC pt. 3 and BSI TR-03119, e.g. for getting
|
||||
# the UID, escaped PIN commands and the reader's firmware version)
|
||||
# Default: false
|
||||
# enable_escape = true;
|
||||
#
|
||||
# Use specific pcsc provider.
|
||||
# Default: @DEFAULT_PCSC_PROVIDER@
|
||||
# provider_library = @DEFAULT_PCSC_PROVIDER@
|
||||
|
|
|
@ -12,7 +12,7 @@ noinst_HEADERS = cards.h ctbcs.h internal.h esteid.h muscle.h muscle-filesystem.
|
|||
errors.h types.h compression.h itacns.h iso7816.h \
|
||||
authentic.h iasecc.h iasecc-sdo.h sm.h card-sc-hsm.h \
|
||||
pace.h cwa14890.h cwa-dnie.h card-gids.h aux-data.h \
|
||||
jpki.h sc-ossl-compat.h card-npa.h
|
||||
jpki.h sc-ossl-compat.h card-npa.h ccid-types.h reader-tr03119.h
|
||||
|
||||
AM_CPPFLAGS = -DOPENSC_CONF_PATH=\"$(sysconfdir)/opensc.conf\" \
|
||||
-I$(top_srcdir)/src
|
||||
|
@ -30,7 +30,7 @@ libopensc_la_SOURCES = \
|
|||
\
|
||||
muscle.c muscle-filesystem.c \
|
||||
\
|
||||
ctbcs.c reader-ctapi.c reader-pcsc.c reader-openct.c \
|
||||
ctbcs.c reader-ctapi.c reader-pcsc.c reader-openct.c reader-tr03119.c \
|
||||
\
|
||||
card-setcos.c card-miocos.c card-flex.c card-gpk.c \
|
||||
card-cardos.c card-tcos.c card-default.c \
|
||||
|
|
|
@ -12,7 +12,7 @@ OBJECTS = \
|
|||
\
|
||||
muscle.obj muscle-filesystem.obj \
|
||||
\
|
||||
ctbcs.obj reader-ctapi.obj reader-pcsc.obj reader-openct.obj \
|
||||
ctbcs.obj reader-ctapi.obj reader-pcsc.obj reader-openct.obj reader-tr03119.obj \
|
||||
\
|
||||
card-setcos.obj card-miocos.obj card-flex.obj card-gpk.obj \
|
||||
card-cardos.obj card-tcos.obj card-default.obj \
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
#endif
|
||||
#include <string.h>
|
||||
|
||||
#include "reader-tr03119.h"
|
||||
#include "internal.h"
|
||||
#include "asn1.h"
|
||||
#include "common/compat_strlcpy.h"
|
||||
|
@ -204,6 +205,9 @@ int sc_connect_card(sc_reader_t *reader, sc_card_t **card_out)
|
|||
card->reader = reader;
|
||||
card->ctx = ctx;
|
||||
|
||||
if (reader->flags & SC_READER_ENABLE_ESCAPE)
|
||||
sc_detect_escape_cmds(reader);
|
||||
|
||||
memcpy(&card->atr, &reader->atr, sizeof(card->atr));
|
||||
memcpy(&card->uid, &reader->uid, sizeof(card->uid));
|
||||
|
||||
|
|
|
@ -0,0 +1,281 @@
|
|||
/*
|
||||
* Copyright (C) 2009-2015 Frank Morgner
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
/**
|
||||
* @file
|
||||
*/
|
||||
#ifndef _CCID_TYPES_H
|
||||
#define _CCID_TYPES_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#define PACKED
|
||||
#pragma pack(push,1)
|
||||
#elif defined(__GNUC__)
|
||||
#define PACKED __attribute__ ((__packed__))
|
||||
#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;
|
||||
} PACKED;
|
||||
|
||||
typedef struct {
|
||||
uint8_t bmFindexDindex;
|
||||
uint8_t bmTCCKST0;
|
||||
uint8_t bGuardTimeT0;
|
||||
uint8_t bWaitingIntegerT0;
|
||||
uint8_t bClockStop;
|
||||
} 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;
|
||||
} 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;
|
||||
} 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;
|
||||
} PACKED abPINDataStucture_Modification_t;
|
||||
|
||||
typedef struct {
|
||||
uint8_t bMessageType;
|
||||
uint32_t dwLength;
|
||||
uint8_t bSlot;
|
||||
uint8_t bSeq;
|
||||
uint8_t bBWI;
|
||||
uint16_t wLevelParameter;
|
||||
} 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;
|
||||
} 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;
|
||||
} 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;
|
||||
} 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;
|
||||
} 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;
|
||||
} 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;
|
||||
} 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;
|
||||
} 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;
|
||||
} 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;
|
||||
} 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;
|
||||
} 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 */
|
||||
} PACKED RDR_to_PC_NotifySlotChange_t;
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#undef PACKED
|
||||
#pragma pack(pop)
|
||||
#elif defined(__GNUC__)
|
||||
#undef PACKED
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
|
@ -353,3 +353,9 @@ perform_chip_authentication
|
|||
npa_default_flags
|
||||
npa_reset_retry_counter
|
||||
npa_pace_get_tries_left
|
||||
escape_pace_input_to_buf
|
||||
escape_buf_to_pace_input
|
||||
escape_pace_output_to_buf
|
||||
escape_buf_to_pace_output
|
||||
escape_pace_capabilities_to_buf
|
||||
escape_buf_to_pace_capabilities
|
||||
|
|
|
@ -287,6 +287,7 @@ struct sc_reader_driver {
|
|||
#define SC_READER_CARD_EXCLUSIVE 0x00000008
|
||||
#define SC_READER_HAS_WAITING_AREA 0x00000010
|
||||
#define SC_READER_REMOVED 0x00000020
|
||||
#define SC_READER_ENABLE_ESCAPE 0x00000040
|
||||
|
||||
/* reader capabilities */
|
||||
#define SC_READER_CAP_DISPLAY 0x00000001
|
||||
|
|
|
@ -397,6 +397,8 @@ static int ctapi_load_module(sc_context_t *ctx,
|
|||
if (conf_block) {
|
||||
reader->max_send_size = scconf_get_int(conf_block, "max_send_size", reader->max_send_size);
|
||||
reader->max_recv_size = scconf_get_int(conf_block, "max_recv_size", reader->max_recv_size);
|
||||
if (scconf_get_bool(conf_block, "enable_escape", 0))
|
||||
reader->flags |= SC_READER_ENABLE_ESCAPE;
|
||||
}
|
||||
|
||||
r = _sc_add_reader(ctx, reader);
|
||||
|
|
|
@ -138,6 +138,8 @@ openct_add_reader(sc_context_t *ctx, unsigned int num, ct_info_t *info)
|
|||
if (conf_block) {
|
||||
reader->max_send_size = scconf_get_int(conf_block, "max_send_size", reader->max_send_size);
|
||||
reader->max_recv_size = scconf_get_int(conf_block, "max_recv_size", reader->max_recv_size);
|
||||
if (scconf_get_bool(conf_block, "enable_escape", 0))
|
||||
reader->flags |= SC_READER_ENABLE_ESCAPE;
|
||||
}
|
||||
|
||||
if ((rc = _sc_add_reader(ctx, reader)) < 0) {
|
||||
|
|
|
@ -472,29 +472,31 @@ static int pcsc_reconnect(sc_reader_t * reader, DWORD action)
|
|||
|
||||
static void initialize_uid(sc_reader_t *reader)
|
||||
{
|
||||
sc_apdu_t apdu;
|
||||
/* though we only expect 10 bytes max, we want to set the Le to 0x00 to not
|
||||
* get 0x6282 as SW in case of a UID variant shorter than 10 bytes */
|
||||
u8 rbuf[256];
|
||||
if (reader->flags & SC_READER_ENABLE_ESCAPE) {
|
||||
sc_apdu_t apdu;
|
||||
/* though we only expect 10 bytes max, we want to set the Le to 0x00 to not
|
||||
* get 0x6282 as SW in case of a UID variant shorter than 10 bytes */
|
||||
u8 rbuf[256];
|
||||
|
||||
memset(&apdu, 0, sizeof(apdu));
|
||||
apdu.cse = SC_APDU_CASE_2_SHORT;
|
||||
apdu.cla = 0xFF;
|
||||
apdu.ins = 0xCA;
|
||||
apdu.p1 = 0x00;
|
||||
apdu.p2 = 0x00;
|
||||
apdu.le = 0x00;
|
||||
apdu.resp = rbuf;
|
||||
apdu.resplen = sizeof rbuf;
|
||||
memset(&apdu, 0, sizeof(apdu));
|
||||
apdu.cse = SC_APDU_CASE_2_SHORT;
|
||||
apdu.cla = 0xFF;
|
||||
apdu.ins = 0xCA;
|
||||
apdu.p1 = 0x00;
|
||||
apdu.p2 = 0x00;
|
||||
apdu.le = 0x00;
|
||||
apdu.resp = rbuf;
|
||||
apdu.resplen = sizeof rbuf;
|
||||
|
||||
if (SC_SUCCESS == pcsc_transmit(reader, &apdu)
|
||||
&& apdu.sw1 == 0x90 && apdu.sw2 == 0x00) {
|
||||
reader->uid.len = apdu.resplen;
|
||||
memcpy(reader->uid.value, apdu.resp, reader->uid.len);
|
||||
sc_debug_hex(reader->ctx, SC_LOG_DEBUG_NORMAL, "UID",
|
||||
reader->uid.value, reader->uid.len);
|
||||
} else {
|
||||
sc_debug(reader->ctx, SC_LOG_DEBUG_NORMAL, "unable to get UID");
|
||||
if (SC_SUCCESS == pcsc_transmit(reader, &apdu)
|
||||
&& apdu.sw1 == 0x90 && apdu.sw2 == 0x00) {
|
||||
reader->uid.len = apdu.resplen;
|
||||
memcpy(reader->uid.value, apdu.resp, reader->uid.len);
|
||||
sc_debug_hex(reader->ctx, SC_LOG_DEBUG_NORMAL, "UID",
|
||||
reader->uid.value, reader->uid.len);
|
||||
} else {
|
||||
sc_debug(reader->ctx, SC_LOG_DEBUG_NORMAL, "unable to get UID");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1306,6 +1308,8 @@ static int pcsc_detect_readers(sc_context_t *ctx)
|
|||
if (conf_block) {
|
||||
reader->max_send_size = scconf_get_int(conf_block, "max_send_size", reader->max_send_size);
|
||||
reader->max_recv_size = scconf_get_int(conf_block, "max_recv_size", reader->max_recv_size);
|
||||
if (scconf_get_bool(conf_block, "enable_escape", 0))
|
||||
reader->flags |= SC_READER_ENABLE_ESCAPE;
|
||||
}
|
||||
|
||||
sc_log(ctx, "reader's max-send-size: %i, max-recv-size: %i", reader->max_send_size, reader->max_recv_size);
|
||||
|
@ -2393,6 +2397,8 @@ int cardmod_use_reader(sc_context_t *ctx, void * pcsc_context_handle, void * pcs
|
|||
if (conf_block) {
|
||||
reader->max_send_size = scconf_get_int(conf_block, "max_send_size", reader->max_send_size);
|
||||
reader->max_recv_size = scconf_get_int(conf_block, "max_recv_size", reader->max_recv_size);
|
||||
if (scconf_get_bool(conf_block, "enable_escape", 0))
|
||||
reader->flags |= SC_READER_ENABLE_ESCAPE;
|
||||
}
|
||||
|
||||
/* attempt to detect protocol in use T0/T1/RAW */
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,57 @@
|
|||
/*
|
||||
* reader-tr03119.h: interface related to escape commands with pseudo APDUs
|
||||
*
|
||||
* Copyright (C) 2013-2015 Frank Morgner
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef _READER_TR03119_H
|
||||
#define _READER_TR03119_H
|
||||
|
||||
#include "libopensc/opensc.h"
|
||||
#include "libopensc/pace.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void sc_detect_escape_cmds(sc_reader_t *reader);
|
||||
|
||||
int escape_pace_input_to_buf(sc_context_t *ctx,
|
||||
const struct establish_pace_channel_input *input,
|
||||
unsigned char **asn1, size_t *asn1_len);
|
||||
int escape_buf_to_pace_input(sc_context_t *ctx,
|
||||
const unsigned char *asn1, size_t asn1_len,
|
||||
struct establish_pace_channel_input *input);
|
||||
int escape_pace_output_to_buf(sc_context_t *ctx,
|
||||
const struct establish_pace_channel_output *output,
|
||||
unsigned char **asn1, size_t *asn1_len);
|
||||
int escape_buf_to_pace_output(sc_context_t *ctx,
|
||||
const unsigned char *asn1, size_t asn1_len,
|
||||
struct establish_pace_channel_output *output);
|
||||
int escape_pace_capabilities_to_buf(sc_context_t *ctx,
|
||||
const unsigned long sc_reader_t_capabilities,
|
||||
unsigned char **asn1, size_t *asn1_len);
|
||||
int escape_buf_to_pace_capabilities(sc_context_t *ctx,
|
||||
const unsigned char *asn1, size_t asn1_len,
|
||||
unsigned long *sc_reader_t_capabilities);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
@ -50,13 +50,20 @@ static struct sc_pkcs11_slot * reader_get_slot(sc_reader_t *reader)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static void init_slot_info(CK_SLOT_INFO_PTR pInfo)
|
||||
static void init_slot_info(CK_SLOT_INFO_PTR pInfo, sc_reader_t *reader)
|
||||
{
|
||||
strcpy_bp(pInfo->slotDescription, "Virtual hotplug slot", 64);
|
||||
strcpy_bp(pInfo->manufacturerID, OPENSC_VS_FF_COMPANY_NAME, 32);
|
||||
if (reader) {
|
||||
strcpy_bp(pInfo->slotDescription, reader->name, 64);
|
||||
strcpy_bp(pInfo->manufacturerID, reader->vendor, 32);
|
||||
pInfo->hardwareVersion.major = reader->version_major;
|
||||
pInfo->hardwareVersion.minor = reader->version_minor;
|
||||
} else {
|
||||
strcpy_bp(pInfo->slotDescription, "Virtual hotplug slot", 64);
|
||||
strcpy_bp(pInfo->manufacturerID, OPENSC_VS_FF_COMPANY_NAME, 32);
|
||||
pInfo->hardwareVersion.major = OPENSC_VERSION_MAJOR;
|
||||
pInfo->hardwareVersion.minor = OPENSC_VERSION_MINOR;
|
||||
}
|
||||
pInfo->flags = CKF_REMOVABLE_DEVICE | CKF_HW_SLOT;
|
||||
pInfo->hardwareVersion.major = OPENSC_VERSION_MAJOR;
|
||||
pInfo->hardwareVersion.minor = OPENSC_VERSION_MINOR;
|
||||
pInfo->firmwareVersion.major = 0;
|
||||
pInfo->firmwareVersion.minor = 0;
|
||||
}
|
||||
|
@ -105,7 +112,7 @@ CK_RV create_slot(sc_reader_t *reader)
|
|||
|
||||
slot->login_user = -1;
|
||||
slot->id = (CK_SLOT_ID) list_locate(&virtual_slots, slot);
|
||||
init_slot_info(&slot->slot_info);
|
||||
init_slot_info(&slot->slot_info, reader);
|
||||
sc_log(context, "Initializing slot with id 0x%lx", slot->id);
|
||||
|
||||
if (reader != NULL) {
|
||||
|
@ -127,7 +134,7 @@ void empty_slot(struct sc_pkcs11_slot *slot)
|
|||
* already been reset by `slot_token_removed()`, lists have been
|
||||
* emptied. We replace the reader with a virtual hotplug slot. */
|
||||
slot->reader = NULL;
|
||||
init_slot_info(&slot->slot_info);
|
||||
init_slot_info(&slot->slot_info, NULL);
|
||||
} else {
|
||||
list_destroy(&slot->objects);
|
||||
list_destroy(&slot->logins);
|
||||
|
@ -273,6 +280,18 @@ again:
|
|||
return sc_to_cryptoki_error(rc, NULL);
|
||||
}
|
||||
|
||||
/* escape commands are only guaranteed to be working with a card
|
||||
* inserted. That's why by now, after sc_connect_card() the reader's
|
||||
* metadata may have changed. We re-initialize the metadata for every
|
||||
* slot of this reader here. */
|
||||
if (reader->flags & SC_READER_ENABLE_ESCAPE) {
|
||||
for (i = 0; i<list_size(&virtual_slots); i++) {
|
||||
sc_pkcs11_slot_t *slot = (sc_pkcs11_slot_t *) list_get_at(&virtual_slots, i);
|
||||
if (slot->reader == reader)
|
||||
init_slot_info(&slot->slot_info, reader);
|
||||
}
|
||||
}
|
||||
|
||||
sc_log(context, "%s: Connected SC card %p", reader->name, p11card->card);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue