mirror of
git://git.gnupg.org/gnupg.git
synced 2025-07-02 22:46:30 +02:00
Preparing an interim release
This commit is contained in:
parent
000a38ccf2
commit
6a13cf2c3d
32 changed files with 785 additions and 171 deletions
|
@ -1,8 +1,63 @@
|
|||
2005-11-23 Werner Koch <wk@g10code.com>
|
||||
|
||||
* app-nks.c (verify_pin): Give a special error message for a Nullpin.
|
||||
|
||||
2005-10-29 Werner Koch <wk@g10code.com>
|
||||
|
||||
* ccid-driver.c (send_escape_cmd): New args RESULT, RESULTLEN and
|
||||
RESULTMAX. Changed all callers.
|
||||
(ccid_transceive_escape): New.
|
||||
|
||||
2005-10-27 Werner Koch <wk@g10code.com>
|
||||
|
||||
* apdu.c [__CYGWIN__]: Make cygwin environment similar to _WIN32.
|
||||
Suggested by John P. Clizbe.
|
||||
* scdaemon.c [__CYGWIN__]: Set default PC/SC driver to winscard.dll.
|
||||
|
||||
2005-10-19 Werner Koch <wk@g10code.com>
|
||||
|
||||
* ccid-driver.h (CCID_DRIVER_ERR_NO_KEYPAD): New.
|
||||
* apdu.h (SW_HOST_NO_KEYPAD): New.
|
||||
* iso7816.h (struct iso7816_pininfo_s): New.
|
||||
* iso7816.c (map_sw): Support new code.
|
||||
(iso7816_check_keypad): New.
|
||||
(iso7816_verify_kp, iso7816_change_reference_data_kp)
|
||||
(iso7816_reset_retry_counter_kp): New. Extended versions of the
|
||||
original functions.
|
||||
* apdu.c (host_sw_string): Support new code.
|
||||
(reader_table_s): New field CHECK_KEYPAD.
|
||||
(new_reader_slot, open_ct_reader, open_pcsc_reader)
|
||||
(open_ccid_reader, open_rapdu_reader): Initialize it.
|
||||
(check_ccid_keypad): New.
|
||||
(apdu_check_keypad): New.
|
||||
(apdu_send_le): Factored all code out to ...
|
||||
(send_le): .. new. Takes an additional arg; changed all callers
|
||||
of the orginal function to use this one with a NULL for the new
|
||||
arg.
|
||||
(apdu_send_simple_kp): New.
|
||||
(ct_send_apdu, pcsc_send_apdu, my_rapdu_send_apdu)
|
||||
(send_apdu_ccid): New arg PININFO.
|
||||
(send_apdu_ccid): Use the new arg.
|
||||
|
||||
* scdaemon.c: New option --disable-keypad.
|
||||
|
||||
2005-10-08 Marcus Brinkmann <marcus@g10code.de>
|
||||
|
||||
* Makefile.am (scdaemon_LDADD): Add ../gl/libgnu.a after
|
||||
../common/libcommon.a.
|
||||
|
||||
2005-09-20 Werner Koch <wk@g10code.com>
|
||||
|
||||
* app-dinsig.c (verify_pin): Try ISO 9564 BCD encoding.
|
||||
|
||||
* iso7816.c (iso7816_select_application): Add arg FLAGS. Changed
|
||||
all callers to pass 0.
|
||||
* app-openpgp.c (app_select_openpgp): But this one requires a
|
||||
special flag.
|
||||
|
||||
* app-p15.c (app_select_p15): Don't use select application for the
|
||||
BELPIC.
|
||||
|
||||
2005-09-09 Werner Koch <wk@g10code.com>
|
||||
|
||||
* pcsc-wrapper.c (main): Removed bogus free.
|
||||
|
|
176
scd/apdu.c
176
scd/apdu.c
|
@ -66,10 +66,10 @@
|
|||
#include "ccid-driver.h"
|
||||
|
||||
|
||||
/* To to conflicting use of threading libraries we usually can't link
|
||||
/* Due to conflicting use of threading libraries we usually can't link
|
||||
against libpcsclite. Instead we use a wrapper program. */
|
||||
#ifdef USE_GNU_PTH
|
||||
#ifndef HAVE_W32_SYSTEM
|
||||
#if !defined(HAVE_W32_SYSTEM) && !defined(__CYGWIN__)
|
||||
#define NEED_PCSC_WRAPPER 1
|
||||
#endif
|
||||
#endif
|
||||
|
@ -78,7 +78,7 @@
|
|||
#define MAX_READER 4 /* Number of readers we support concurrently. */
|
||||
|
||||
|
||||
#ifdef _WIN32
|
||||
#if defined(_WIN32) || defined(__CYGWIN__)
|
||||
#define DLSTDCALL __stdcall
|
||||
#else
|
||||
#define DLSTDCALL
|
||||
|
@ -90,6 +90,14 @@
|
|||
#define MAX_OPEN_FDS 20
|
||||
#endif
|
||||
|
||||
/* Helper to pass patrameters related to keypad based operations. */
|
||||
struct pininfo_s
|
||||
{
|
||||
int mode;
|
||||
int minlen;
|
||||
int maxlen;
|
||||
int padlen;
|
||||
};
|
||||
|
||||
/* A structure to collect information pertaining to one reader
|
||||
slot. */
|
||||
|
@ -103,7 +111,8 @@ struct reader_table_s {
|
|||
int (*reset_reader)(int);
|
||||
int (*get_status_reader)(int, unsigned int *);
|
||||
int (*send_apdu_reader)(int,unsigned char *,size_t,
|
||||
unsigned char *, size_t *);
|
||||
unsigned char *, size_t *, struct pininfo_s *);
|
||||
int (*check_keypad)(int, int, int, int, int, int);
|
||||
void (*dump_status_reader)(int);
|
||||
|
||||
struct {
|
||||
|
@ -320,6 +329,7 @@ new_reader_slot (void)
|
|||
reader_table[reader].reset_reader = NULL;
|
||||
reader_table[reader].get_status_reader = NULL;
|
||||
reader_table[reader].send_apdu_reader = NULL;
|
||||
reader_table[reader].check_keypad = NULL;
|
||||
reader_table[reader].dump_status_reader = NULL;
|
||||
|
||||
reader_table[reader].used = 1;
|
||||
|
@ -372,6 +382,7 @@ host_sw_string (long err)
|
|||
case SW_HOST_GENERAL_ERROR: return "general error";
|
||||
case SW_HOST_NO_READER: return "no reader";
|
||||
case SW_HOST_ABORTED: return "aborted";
|
||||
case SW_HOST_NO_KEYPAD: return "no keypad";
|
||||
default: return "unknown host status error";
|
||||
}
|
||||
}
|
||||
|
@ -533,7 +544,7 @@ ct_get_status (int slot, unsigned int *status)
|
|||
set to BUFLEN. Returns: CT API error code. */
|
||||
static int
|
||||
ct_send_apdu (int slot, unsigned char *apdu, size_t apdulen,
|
||||
unsigned char *buffer, size_t *buflen)
|
||||
unsigned char *buffer, size_t *buflen, struct pininfo_s *pininfo)
|
||||
{
|
||||
int rc;
|
||||
unsigned char dad[1], sad[1];
|
||||
|
@ -596,6 +607,7 @@ open_ct_reader (int port)
|
|||
reader_table[reader].reset_reader = reset_ct_reader;
|
||||
reader_table[reader].get_status_reader = ct_get_status;
|
||||
reader_table[reader].send_apdu_reader = ct_send_apdu;
|
||||
reader_table[reader].check_keypad = NULL;
|
||||
reader_table[reader].dump_status_reader = ct_dump_reader_status;
|
||||
|
||||
dump_reader_status (reader);
|
||||
|
@ -1082,7 +1094,8 @@ pcsc_get_status (int slot, unsigned int *status)
|
|||
set to BUFLEN. Returns: CT API error code. */
|
||||
static int
|
||||
pcsc_send_apdu (int slot, unsigned char *apdu, size_t apdulen,
|
||||
unsigned char *buffer, size_t *buflen)
|
||||
unsigned char *buffer, size_t *buflen,
|
||||
struct pininfo_s *pininfo)
|
||||
{
|
||||
#ifdef NEED_PCSC_WRAPPER
|
||||
long err;
|
||||
|
@ -1479,6 +1492,7 @@ open_pcsc_reader (const char *portstr)
|
|||
reader_table[slot].reset_reader = reset_pcsc_reader;
|
||||
reader_table[slot].get_status_reader = pcsc_get_status;
|
||||
reader_table[slot].send_apdu_reader = pcsc_send_apdu;
|
||||
reader_table[slot].check_keypad = NULL;
|
||||
reader_table[slot].dump_status_reader = dump_pcsc_reader_status;
|
||||
|
||||
/* Read the status so that IS_T0 will be set. */
|
||||
|
@ -1625,6 +1639,7 @@ open_pcsc_reader (const char *portstr)
|
|||
reader_table[slot].reset_reader = reset_pcsc_reader;
|
||||
reader_table[slot].get_status_reader = pcsc_get_status;
|
||||
reader_table[slot].send_apdu_reader = pcsc_send_apdu;
|
||||
reader_table[slot].check_keypad = NULL;
|
||||
reader_table[slot].dump_status_reader = dump_pcsc_reader_status;
|
||||
|
||||
/* log_debug ("state from pcsc_status: 0x%lx\n", card_state); */
|
||||
|
@ -1713,7 +1728,8 @@ get_status_ccid (int slot, unsigned int *status)
|
|||
set to BUFLEN. Returns: Internal CCID driver error code. */
|
||||
static int
|
||||
send_apdu_ccid (int slot, unsigned char *apdu, size_t apdulen,
|
||||
unsigned char *buffer, size_t *buflen)
|
||||
unsigned char *buffer, size_t *buflen,
|
||||
struct pininfo_s *pininfo)
|
||||
{
|
||||
long err;
|
||||
size_t maxbuflen;
|
||||
|
@ -1727,9 +1743,18 @@ send_apdu_ccid (int slot, unsigned char *apdu, size_t apdulen,
|
|||
log_printhex (" APDU_data:", apdu, apdulen);
|
||||
|
||||
maxbuflen = *buflen;
|
||||
err = ccid_transceive (reader_table[slot].ccid.handle,
|
||||
apdu, apdulen,
|
||||
buffer, maxbuflen, buflen);
|
||||
if (pininfo)
|
||||
err = ccid_transceive_secure (reader_table[slot].ccid.handle,
|
||||
apdu, apdulen,
|
||||
pininfo->mode,
|
||||
pininfo->minlen,
|
||||
pininfo->maxlen,
|
||||
pininfo->padlen,
|
||||
buffer, maxbuflen, buflen);
|
||||
else
|
||||
err = ccid_transceive (reader_table[slot].ccid.handle,
|
||||
apdu, apdulen,
|
||||
buffer, maxbuflen, buflen);
|
||||
if (err)
|
||||
log_error ("ccid_transceive failed: (0x%lx)\n",
|
||||
err);
|
||||
|
@ -1737,6 +1762,24 @@ send_apdu_ccid (int slot, unsigned char *apdu, size_t apdulen,
|
|||
return err;
|
||||
}
|
||||
|
||||
|
||||
/* Check whether the CCID reader supports the ISO command code COMMAND
|
||||
on the keypad. Return 0 on success. For a description of the pin
|
||||
parameters, see ccid-driver.c */
|
||||
static int
|
||||
check_ccid_keypad (int slot, int command, int pin_mode,
|
||||
int pinlen_min, int pinlen_max, int pin_padlen)
|
||||
{
|
||||
unsigned char apdu[] = { 0, 0, 0, 0x81 };
|
||||
|
||||
apdu[1] = command;
|
||||
return ccid_transceive_secure (reader_table[slot].ccid.handle,
|
||||
apdu, sizeof apdu,
|
||||
pin_mode, pinlen_min, pinlen_max, pin_padlen,
|
||||
NULL, 0, NULL);
|
||||
}
|
||||
|
||||
|
||||
/* Open the reader and try to read an ATR. */
|
||||
static int
|
||||
open_ccid_reader (const char *portstr)
|
||||
|
@ -1776,6 +1819,7 @@ open_ccid_reader (const char *portstr)
|
|||
reader_table[slot].reset_reader = reset_ccid_reader;
|
||||
reader_table[slot].get_status_reader = get_status_ccid;
|
||||
reader_table[slot].send_apdu_reader = send_apdu_ccid;
|
||||
reader_table[slot].check_keypad = check_ccid_keypad;
|
||||
reader_table[slot].dump_status_reader = dump_ccid_reader_status;
|
||||
|
||||
dump_reader_status (slot);
|
||||
|
@ -1932,7 +1976,8 @@ my_rapdu_get_status (int slot, unsigned int *status)
|
|||
set to BUFLEN. Returns: APDU error code. */
|
||||
static int
|
||||
my_rapdu_send_apdu (int slot, unsigned char *apdu, size_t apdulen,
|
||||
unsigned char *buffer, size_t *buflen)
|
||||
unsigned char *buffer, size_t *buflen,
|
||||
struct pininfo_s *pininfo)
|
||||
{
|
||||
int err;
|
||||
reader_table_t slotp;
|
||||
|
@ -2063,6 +2108,7 @@ open_rapdu_reader (int portno,
|
|||
reader_table[slot].reset_reader = reset_rapdu_reader;
|
||||
reader_table[slot].get_status_reader = my_rapdu_get_status;
|
||||
reader_table[slot].send_apdu_reader = my_rapdu_send_apdu;
|
||||
reader_table[slot].check_keypad = NULL;
|
||||
reader_table[slot].dump_status_reader = NULL;
|
||||
|
||||
dump_reader_status (slot);
|
||||
|
@ -2198,28 +2244,28 @@ apdu_open_reader (const char *portstr)
|
|||
pcsc_establish_context = dlsym (handle, "SCardEstablishContext");
|
||||
pcsc_release_context = dlsym (handle, "SCardReleaseContext");
|
||||
pcsc_list_readers = dlsym (handle, "SCardListReaders");
|
||||
#ifdef _WIN32
|
||||
#if defined(_WIN32) || defined(__CYGWIN__)
|
||||
if (!pcsc_list_readers)
|
||||
pcsc_list_readers = dlsym (handle, "SCardListReadersA");
|
||||
#endif
|
||||
pcsc_get_status_change = dlsym (handle, "SCardGetStatusChange");
|
||||
#ifdef _WIN32
|
||||
#if defined(_WIN32) || defined(__CYGWIN__)
|
||||
if (!pcsc_get_status_change)
|
||||
pcsc_get_status_change = dlsym (handle, "SCardGetStatusChangeA");
|
||||
#endif
|
||||
pcsc_connect = dlsym (handle, "SCardConnect");
|
||||
#ifdef _WIN32
|
||||
#if defined(_WIN32) || defined(__CYGWIN__)
|
||||
if (!pcsc_connect)
|
||||
pcsc_connect = dlsym (handle, "SCardConnectA");
|
||||
#endif
|
||||
pcsc_reconnect = dlsym (handle, "SCardReconnect");
|
||||
#ifdef _WIN32
|
||||
#if defined(_WIN32) || defined(__CYGWIN__)
|
||||
if (!pcsc_reconnect)
|
||||
pcsc_reconnect = dlsym (handle, "SCardReconnectA");
|
||||
#endif
|
||||
pcsc_disconnect = dlsym (handle, "SCardDisconnect");
|
||||
pcsc_status = dlsym (handle, "SCardStatus");
|
||||
#ifdef _WIN32
|
||||
#if defined(_WIN32) || defined(__CYGWIN__)
|
||||
if (!pcsc_status)
|
||||
pcsc_status = dlsym (handle, "SCardStatusA");
|
||||
#endif
|
||||
|
@ -2492,11 +2538,30 @@ apdu_get_status (int slot, int hang,
|
|||
}
|
||||
|
||||
|
||||
/* Check whether the reader supports the ISO command code COMMAND on
|
||||
the keypad. Return 0 on success. For a description of the pin
|
||||
parameters, see ccid-driver.c */
|
||||
int
|
||||
apdu_check_keypad (int slot, int command, int pin_mode,
|
||||
int pinlen_min, int pinlen_max, int pin_padlen)
|
||||
{
|
||||
if (slot < 0 || slot >= MAX_READER || !reader_table[slot].used )
|
||||
return SW_HOST_NO_DRIVER;
|
||||
|
||||
if (reader_table[slot].check_keypad)
|
||||
return reader_table[slot].check_keypad (slot, command,
|
||||
pin_mode, pinlen_min, pinlen_max,
|
||||
pin_padlen);
|
||||
else
|
||||
return SW_HOST_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
|
||||
/* Dispatcher for the actual send_apdu function. Note, that this
|
||||
function should be called in locked state. */
|
||||
static int
|
||||
send_apdu (int slot, unsigned char *apdu, size_t apdulen,
|
||||
unsigned char *buffer, size_t *buflen)
|
||||
unsigned char *buffer, size_t *buflen, struct pininfo_s *pininfo)
|
||||
{
|
||||
if (slot < 0 || slot >= MAX_READER || !reader_table[slot].used )
|
||||
return SW_HOST_NO_DRIVER;
|
||||
|
@ -2504,24 +2569,20 @@ send_apdu (int slot, unsigned char *apdu, size_t apdulen,
|
|||
if (reader_table[slot].send_apdu_reader)
|
||||
return reader_table[slot].send_apdu_reader (slot,
|
||||
apdu, apdulen,
|
||||
buffer, buflen);
|
||||
buffer, buflen, pininfo);
|
||||
else
|
||||
return SW_HOST_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
/* Send an APDU to the card in SLOT. The APDU is created from all
|
||||
given parameters: CLASS, INS, P0, P1, LC, DATA, LE. A value of -1
|
||||
for LC won't sent this field and the data field; in this case DATA
|
||||
must also be passed as NULL. The return value is the status word
|
||||
or -1 for an invalid SLOT or other non card related error. If
|
||||
RETBUF is not NULL, it will receive an allocated buffer with the
|
||||
returned data. The length of that data will be put into
|
||||
*RETBUFLEN. The caller is reponsible for releasing the buffer even
|
||||
in case of errors. */
|
||||
int
|
||||
apdu_send_le(int slot, int class, int ins, int p0, int p1,
|
||||
int lc, const char *data, int le,
|
||||
unsigned char **retbuf, size_t *retbuflen)
|
||||
|
||||
/* Core APDU trabceiver function. Parameters are described at
|
||||
apdu_send_le with the exception of PININFO which indicates keypad
|
||||
related operations if not NULL. */
|
||||
static int
|
||||
send_le (int slot, int class, int ins, int p0, int p1,
|
||||
int lc, const char *data, int le,
|
||||
unsigned char **retbuf, size_t *retbuflen,
|
||||
struct pininfo_s *pininfo)
|
||||
{
|
||||
#define RESULTLEN 256
|
||||
unsigned char result[RESULTLEN+10]; /* 10 extra in case of bugs in
|
||||
|
@ -2570,7 +2631,7 @@ apdu_send_le(int slot, int class, int ins, int p0, int p1,
|
|||
/* As safeguard don't pass any garbage from the stack to the driver. */
|
||||
memset (apdu+apdulen, 0, sizeof (apdu) - apdulen);
|
||||
resultlen = RESULTLEN;
|
||||
rc = send_apdu (slot, apdu, apdulen, result, &resultlen);
|
||||
rc = send_apdu (slot, apdu, apdulen, result, &resultlen, pininfo);
|
||||
if (rc || resultlen < 2)
|
||||
{
|
||||
log_error ("apdu_send_simple(%d) failed: %s\n",
|
||||
|
@ -2638,7 +2699,7 @@ apdu_send_le(int slot, int class, int ins, int p0, int p1,
|
|||
apdu[apdulen++] = len;
|
||||
memset (apdu+apdulen, 0, sizeof (apdu) - apdulen);
|
||||
resultlen = RESULTLEN;
|
||||
rc = send_apdu (slot, apdu, apdulen, result, &resultlen);
|
||||
rc = send_apdu (slot, apdu, apdulen, result, &resultlen, NULL);
|
||||
if (rc || resultlen < 2)
|
||||
{
|
||||
log_error ("apdu_send_simple(%d) for get response failed: %s\n",
|
||||
|
@ -2703,6 +2764,27 @@ apdu_send_le(int slot, int class, int ins, int p0, int p1,
|
|||
#undef RESULTLEN
|
||||
}
|
||||
|
||||
/* Send an APDU to the card in SLOT. The APDU is created from all
|
||||
given parameters: CLASS, INS, P0, P1, LC, DATA, LE. A value of -1
|
||||
for LC won't sent this field and the data field; in this case DATA
|
||||
must also be passed as NULL. The return value is the status word
|
||||
or -1 for an invalid SLOT or other non card related error. If
|
||||
RETBUF is not NULL, it will receive an allocated buffer with the
|
||||
returned data. The length of that data will be put into
|
||||
*RETBUFLEN. The caller is reponsible for releasing the buffer even
|
||||
in case of errors. */
|
||||
int
|
||||
apdu_send_le(int slot, int class, int ins, int p0, int p1,
|
||||
int lc, const char *data, int le,
|
||||
unsigned char **retbuf, size_t *retbuflen)
|
||||
{
|
||||
return send_le (slot, class, ins, p0, p1,
|
||||
lc, data, le,
|
||||
retbuf, retbuflen,
|
||||
NULL);
|
||||
}
|
||||
|
||||
|
||||
/* Send an APDU to the card in SLOT. The APDU is created from all
|
||||
given parameters: CLASS, INS, P0, P1, LC, DATA. A value of -1 for
|
||||
LC won't sent this field and the data field; in this case DATA must
|
||||
|
@ -2716,8 +2798,8 @@ int
|
|||
apdu_send (int slot, int class, int ins, int p0, int p1,
|
||||
int lc, const char *data, unsigned char **retbuf, size_t *retbuflen)
|
||||
{
|
||||
return apdu_send_le (slot, class, ins, p0, p1, lc, data, 256,
|
||||
retbuf, retbuflen);
|
||||
return send_le (slot, class, ins, p0, p1, lc, data, 256,
|
||||
retbuf, retbuflen, NULL);
|
||||
}
|
||||
|
||||
/* Send an APDU to the card in SLOT. The APDU is created from all
|
||||
|
@ -2730,7 +2812,25 @@ int
|
|||
apdu_send_simple (int slot, int class, int ins, int p0, int p1,
|
||||
int lc, const char *data)
|
||||
{
|
||||
return apdu_send_le (slot, class, ins, p0, p1, lc, data, -1, NULL, NULL);
|
||||
return send_le (slot, class, ins, p0, p1, lc, data, -1, NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
|
||||
/* Same as apdu_send_simple but uses the keypad of the reader. */
|
||||
int
|
||||
apdu_send_simple_kp (int slot, int class, int ins, int p0, int p1,
|
||||
int lc, const char *data,
|
||||
int pin_mode,
|
||||
int pinlen_min, int pinlen_max, int pin_padlen)
|
||||
{
|
||||
struct pininfo_s pininfo;
|
||||
|
||||
pininfo.mode = pin_mode;
|
||||
pininfo.minlen = pinlen_min;
|
||||
pininfo.maxlen = pinlen_max;
|
||||
pininfo.padlen = pin_padlen;
|
||||
return send_le (slot, class, ins, p0, p1, lc, data, -1,
|
||||
NULL, NULL, &pininfo);
|
||||
}
|
||||
|
||||
|
||||
|
@ -2771,7 +2871,7 @@ apdu_send_direct (int slot, const unsigned char *apdudata, size_t apdudatalen,
|
|||
class = apdulen? *apdu : 0;
|
||||
|
||||
resultlen = RESULTLEN;
|
||||
rc = send_apdu (slot, apdu, apdulen, result, &resultlen);
|
||||
rc = send_apdu (slot, apdu, apdulen, result, &resultlen, NULL);
|
||||
if (rc || resultlen < 2)
|
||||
{
|
||||
log_error ("apdu_send_direct(%d) failed: %s\n",
|
||||
|
@ -2825,7 +2925,7 @@ apdu_send_direct (int slot, const unsigned char *apdudata, size_t apdudatalen,
|
|||
apdu[apdulen++] = len;
|
||||
memset (apdu+apdulen, 0, sizeof (apdu) - apdulen);
|
||||
resultlen = RESULTLEN;
|
||||
rc = send_apdu (slot, apdu, apdulen, result, &resultlen);
|
||||
rc = send_apdu (slot, apdu, apdulen, result, &resultlen, NULL);
|
||||
if (rc || resultlen < 2)
|
||||
{
|
||||
log_error ("apdu_send_direct(%d) for get response failed: %s\n",
|
||||
|
|
|
@ -63,7 +63,8 @@ enum {
|
|||
SW_HOST_CARD_IO_ERROR = 0x1000a,
|
||||
SW_HOST_GENERAL_ERROR = 0x1000b,
|
||||
SW_HOST_NO_READER = 0x1000c,
|
||||
SW_HOST_ABORTED = 0x1000d
|
||||
SW_HOST_ABORTED = 0x1000d,
|
||||
SW_HOST_NO_KEYPAD = 0x1000e
|
||||
};
|
||||
|
||||
|
||||
|
@ -96,8 +97,14 @@ int apdu_activate (int slot);
|
|||
int apdu_reset (int slot);
|
||||
int apdu_get_status (int slot, int hang,
|
||||
unsigned int *status, unsigned int *changed);
|
||||
int apdu_check_keypad (int slot, int command, int pin_mode,
|
||||
int pinlen_min, int pinlen_max, int pin_padlen);
|
||||
int apdu_send_simple (int slot, int class, int ins, int p0, int p1,
|
||||
int lc, const char *data);
|
||||
int apdu_send_simple_kp (int slot, int class, int ins, int p0, int p1,
|
||||
int lc, const char *data,
|
||||
int pin_mode,
|
||||
int pinlen_min, int pinlen_max, int pin_padlen);
|
||||
int apdu_send (int slot, int class, int ins, int p0, int p1,
|
||||
int lc, const char *data,
|
||||
unsigned char **retbuf, size_t *retbuflen);
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/* app-dinsig.c - The DINSIG (DIN V 66291-1) card application.
|
||||
* Copyright (C) 2002, 2004 Free Software Foundation, Inc.
|
||||
* Copyright (C) 2002, 2004, 2005 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of GnuPG.
|
||||
*
|
||||
|
@ -280,10 +280,11 @@ verify_pin (app_t app,
|
|||
{
|
||||
if (!app->did_chv1 || app->force_chv1 )
|
||||
{
|
||||
const char *s;
|
||||
char *pinvalue;
|
||||
int rc;
|
||||
|
||||
rc = pincb (pincb_arg, "PIN", &pinvalue);
|
||||
rc = pincb (pincb_arg, "PIN", &pinvalue);
|
||||
if (rc)
|
||||
{
|
||||
log_info ("PIN callback returned error: %s\n", gpg_strerror (rc));
|
||||
|
@ -291,8 +292,16 @@ verify_pin (app_t app,
|
|||
}
|
||||
|
||||
/* We require the PIN to be at least 6 and at max 8 bytes.
|
||||
According to the specs, this should all be ASCII but we don't
|
||||
check this. */
|
||||
According to the specs, this should all be ASCII. */
|
||||
for (s=pinvalue; digitp (s); s++)
|
||||
;
|
||||
if (*s)
|
||||
{
|
||||
log_error ("Non-numeric digits found in PIN\n");
|
||||
xfree (pinvalue);
|
||||
return gpg_error (GPG_ERR_BAD_PIN);
|
||||
}
|
||||
|
||||
if (strlen (pinvalue) < 6)
|
||||
{
|
||||
log_error ("PIN is too short; minimum length is 6\n");
|
||||
|
@ -307,6 +316,28 @@ verify_pin (app_t app,
|
|||
}
|
||||
|
||||
rc = iso7816_verify (app->slot, 0x81, pinvalue, strlen (pinvalue));
|
||||
if (gpg_err_code (rc) == GPG_ERR_INV_VALUE)
|
||||
{
|
||||
/* We assume that ISO 9564-1 encoding is used and we failed
|
||||
because the first nibble we passed was 3 and not 2. DIN
|
||||
says something about looking up such an encoding in the
|
||||
SSD but I was not able to find any tag relevant to
|
||||
this. */
|
||||
char paddedpin[8];
|
||||
int i, ndigits;
|
||||
|
||||
for (ndigits=0, s=pinvalue; *s; ndigits++, s++)
|
||||
;
|
||||
i = 0;
|
||||
paddedpin[i++] = 0x20 | (ndigits & 0x0f);
|
||||
for (s=pinvalue; i < sizeof paddedpin && *s && s[1]; s = s+2 )
|
||||
paddedpin[i++] = (((*s - '0') << 4) | ((s[1] - '0') & 0x0f));
|
||||
if (i < sizeof paddedpin && *s)
|
||||
paddedpin[i++] = (((*s - '0') << 4) | 0x0f);
|
||||
while (i < sizeof paddedpin)
|
||||
paddedpin[i++] = 0xff;
|
||||
rc = iso7816_verify (app->slot, 0x81, paddedpin, sizeof paddedpin);
|
||||
}
|
||||
if (rc)
|
||||
{
|
||||
log_error ("verify PIN failed\n");
|
||||
|
@ -404,7 +435,7 @@ app_select_dinsig (APP app)
|
|||
int slot = app->slot;
|
||||
int rc;
|
||||
|
||||
rc = iso7816_select_application (slot, aid, sizeof aid);
|
||||
rc = iso7816_select_application (slot, aid, sizeof aid, 0);
|
||||
if (!rc)
|
||||
{
|
||||
app->apptype = "DINSIG";
|
||||
|
|
|
@ -27,7 +27,7 @@
|
|||
#include <time.h>
|
||||
|
||||
#include "scdaemon.h"
|
||||
|
||||
#include "i18n.h"
|
||||
#include "iso7816.h"
|
||||
#include "app-common.h"
|
||||
#include "tlv.h"
|
||||
|
@ -320,7 +320,7 @@ verify_pin (app_t app,
|
|||
return rc;
|
||||
}
|
||||
|
||||
/* The follwoing limits are due to TCOS but also defined in the
|
||||
/* The following limits are due to TCOS but also defined in the
|
||||
NKS specs. */
|
||||
if (strlen (pinvalue) < 6)
|
||||
{
|
||||
|
@ -340,7 +340,10 @@ verify_pin (app_t app,
|
|||
rc = iso7816_verify (app->slot, 0, pinvalue, strlen (pinvalue));
|
||||
if (rc)
|
||||
{
|
||||
log_error ("verify PIN failed\n");
|
||||
if ( gpg_error (rc) == GPG_ERR_USE_CONDITIONS )
|
||||
log_error (_("the NullPIN has not yet been changed\n"));
|
||||
else
|
||||
log_error ("verify PIN failed\n");
|
||||
xfree (pinvalue);
|
||||
return rc;
|
||||
}
|
||||
|
@ -492,7 +495,7 @@ app_select_nks (APP app)
|
|||
int slot = app->slot;
|
||||
int rc;
|
||||
|
||||
rc = iso7816_select_application (slot, aid, sizeof aid);
|
||||
rc = iso7816_select_application (slot, aid, sizeof aid, 0);
|
||||
if (!rc)
|
||||
{
|
||||
app->apptype = "NKS";
|
||||
|
|
|
@ -1284,6 +1284,11 @@ verify_chv2 (app_t app,
|
|||
if (!app->did_chv2)
|
||||
{
|
||||
char *pinvalue;
|
||||
iso7816_pininfo_t pininfo;
|
||||
|
||||
memset (&pininfo, 0, sizeof pininfo);
|
||||
pininfo.mode = 1;
|
||||
pininfo.minlen = 6;
|
||||
|
||||
rc = pincb (pincb_arg, "PIN", &pinvalue);
|
||||
if (rc)
|
||||
|
@ -2455,7 +2460,9 @@ app_select_openpgp (app_t app)
|
|||
size_t buflen;
|
||||
void *relptr;
|
||||
|
||||
rc = iso7816_select_application (slot, aid, sizeof aid);
|
||||
/* Note that the card can't cope with P2=0xCO, thus we need to pass a
|
||||
special flag value. */
|
||||
rc = iso7816_select_application (slot, aid, sizeof aid, 0x0001);
|
||||
if (!rc)
|
||||
{
|
||||
unsigned int manufacturer;
|
||||
|
|
|
@ -3268,18 +3268,15 @@ app_select_p15 (app_t app)
|
|||
int direct = 0;
|
||||
int is_belpic = 0;
|
||||
|
||||
rc = iso7816_select_application (slot, pkcs15_aid, sizeof pkcs15_aid);
|
||||
if (rc)
|
||||
{
|
||||
rc = iso7816_select_application (slot, pkcs15be_aid,sizeof pkcs15be_aid);
|
||||
if (!rc)
|
||||
is_belpic = 1;
|
||||
}
|
||||
rc = iso7816_select_application (slot, pkcs15_aid, sizeof pkcs15_aid, 0);
|
||||
if (rc)
|
||||
{ /* Not found: Try to locate it from 2F00. We use direct path
|
||||
selection here because it seems that the Belgian eID card
|
||||
does only allow for that. Many other cards supports this
|
||||
selection method too. */
|
||||
selection method too. Note, that we don't use
|
||||
select_application above for the Belgian card - the call
|
||||
works but it seems that it did not switch to the correct DF.
|
||||
Using the 2f02 just works. */
|
||||
unsigned short path[1] = { 0x2f00 };
|
||||
|
||||
rc = iso7816_select_path (app->slot, path, 1, NULL, NULL);
|
||||
|
|
|
@ -1240,7 +1240,9 @@ bulk_in (ccid_driver_t handle, unsigned char *buffer, size_t length,
|
|||
if (CCID_COMMAND_FAILED (buffer))
|
||||
print_command_failed (buffer);
|
||||
|
||||
/* Check whether a card is at all available. */
|
||||
/* Check whether a card is at all available. Note: If you add new
|
||||
error codes here, check whether they need to be ignored in
|
||||
send_escape_cmd. */
|
||||
switch ((buffer[7] & 0x03))
|
||||
{
|
||||
case 0: /* no error */ break;
|
||||
|
@ -1253,16 +1255,23 @@ bulk_in (ccid_driver_t handle, unsigned char *buffer, size_t length,
|
|||
|
||||
|
||||
/* Note that this function won't return the error codes NO_CARD or
|
||||
CARD_INACTIVE */
|
||||
CARD_INACTIVE. IF RESULT is not NULL, the result from the
|
||||
operation will get returned in RESULT and its length in RESULTLEN.
|
||||
If the response is larger than RESULTMAX, an error is returned and
|
||||
the required buffer length returned in RESULTLEN. */
|
||||
static int
|
||||
send_escape_cmd (ccid_driver_t handle,
|
||||
const unsigned char *data, size_t datalen)
|
||||
const unsigned char *data, size_t datalen,
|
||||
unsigned char *result, size_t resultmax, size_t *resultlen)
|
||||
{
|
||||
int i, rc;
|
||||
unsigned char msg[100];
|
||||
size_t msglen;
|
||||
unsigned char seqno;
|
||||
|
||||
if (resultlen)
|
||||
*resultlen = 0;
|
||||
|
||||
if (datalen > sizeof msg - 10)
|
||||
return CCID_DRIVER_ERR_INV_VALUE; /* Escape data too large. */
|
||||
|
||||
|
@ -1285,11 +1294,42 @@ send_escape_cmd (ccid_driver_t handle,
|
|||
return rc;
|
||||
rc = bulk_in (handle, msg, sizeof msg, &msglen, RDR_to_PC_Escape,
|
||||
seqno, 5000, 0);
|
||||
|
||||
if (result)
|
||||
switch (rc)
|
||||
{
|
||||
/* We need to ignore certain errorcode here. */
|
||||
case 0:
|
||||
case CCID_DRIVER_ERR_CARD_INACTIVE:
|
||||
case CCID_DRIVER_ERR_NO_CARD:
|
||||
{
|
||||
if (msglen > resultmax)
|
||||
rc = CCID_DRIVER_ERR_INV_VALUE; /* Response too large. */
|
||||
else
|
||||
{
|
||||
memcpy (result, msg, msglen);
|
||||
*resultlen = msglen;
|
||||
}
|
||||
rc = 0;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
ccid_transceive_escape (ccid_driver_t handle,
|
||||
const unsigned char *data, size_t datalen,
|
||||
unsigned char *resp, size_t maxresplen, size_t *nresp)
|
||||
{
|
||||
return send_escape_cmd (handle, data, datalen, resp, maxresplen, nresp);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* experimental */
|
||||
int
|
||||
ccid_poll (ccid_driver_t handle)
|
||||
|
@ -1445,7 +1485,8 @@ ccid_get_atr (ccid_driver_t handle,
|
|||
{
|
||||
tried_iso = 1;
|
||||
/* Try switching to ISO mode. */
|
||||
if (!send_escape_cmd (handle, (const unsigned char*)"\xF1\x01", 2))
|
||||
if (!send_escape_cmd (handle, (const unsigned char*)"\xF1\x01", 2,
|
||||
NULL, 0, NULL))
|
||||
goto again;
|
||||
}
|
||||
else if (CCID_COMMAND_FAILED (msg))
|
||||
|
@ -1957,14 +1998,16 @@ ccid_transceive (ccid_driver_t handle,
|
|||
}
|
||||
|
||||
|
||||
/* Send the CCID Secure command to the reader. APDU_BUF should contain the APDU template. PIN_MODE defines now the pin gets formatted:
|
||||
/* Send the CCID Secure command to the reader. APDU_BUF should
|
||||
contain the APDU template. PIN_MODE defines how the pin gets
|
||||
formatted:
|
||||
|
||||
1 := The PIN is ASCII encoded and of variable length. The
|
||||
length of the PIN entered will be put into Lc by the reader.
|
||||
The APDU should me made up of 4 bytes without Lc.
|
||||
|
||||
PINLEN_MIN and PINLEN_MAX define the limits for the pin length. 0
|
||||
may be used t enable usbale defaults. PIN_PADLEN should be 0
|
||||
may be used t enable reasonable defaults. PIN_PADLEN should be 0.
|
||||
|
||||
When called with RESP and NRESP set to NULL, the function will
|
||||
merely check whether the reader supports the secure command for the
|
||||
|
@ -1996,7 +2039,7 @@ ccid_transceive_secure (ccid_driver_t handle,
|
|||
else if (apdu_buflen >= 4 && apdu_buf[1] == 0x24 && (handle->has_pinpad & 2))
|
||||
return CCID_DRIVER_ERR_NOT_SUPPORTED; /* Not yet by our code. */
|
||||
else
|
||||
return CCID_DRIVER_ERR_NOT_SUPPORTED;
|
||||
return CCID_DRIVER_ERR_NO_KEYPAD;
|
||||
|
||||
if (pin_mode != 1)
|
||||
return CCID_DRIVER_ERR_NOT_SUPPORTED;
|
||||
|
@ -2027,7 +2070,8 @@ ccid_transceive_secure (ccid_driver_t handle,
|
|||
if (handle->id_vendor == VENDOR_SCM)
|
||||
{
|
||||
DEBUGOUT ("sending escape sequence to switch to a case 1 APDU\n");
|
||||
rc = send_escape_cmd (handle, (const unsigned char*)"\x80\x02\x00", 3);
|
||||
rc = send_escape_cmd (handle, (const unsigned char*)"\x80\x02\x00", 3,
|
||||
NULL, 0, NULL);
|
||||
if (rc)
|
||||
return rc;
|
||||
}
|
||||
|
@ -2044,7 +2088,7 @@ ccid_transceive_secure (ccid_driver_t handle,
|
|||
if (handle->id_vendor == VENDOR_SCM)
|
||||
{
|
||||
/* For the SPR532 the next 2 bytes need to be zero. We do this
|
||||
for all SCM product. Kudos to to Martin Paljak for this
|
||||
for all SCM product. Kudos to Martin Paljak for this
|
||||
hint. */
|
||||
msg[13] = msg[14] = 0;
|
||||
}
|
||||
|
|
|
@ -58,7 +58,7 @@
|
|||
#ifndef CCID_DRIVER_H
|
||||
#define CCID_DRIVER_H
|
||||
|
||||
/* The CID driver returns the same error codes as the statsu words
|
||||
/* The CID driver returns the same error codes as the status words
|
||||
used by GnuPG's apdu.h. For ease of maintenance they should always
|
||||
match. */
|
||||
#define CCID_DRIVER_ERR_OUT_OF_CORE 0x10001
|
||||
|
@ -74,6 +74,7 @@
|
|||
#define CCID_DRIVER_ERR_GENERAL_ERROR 0x1000b
|
||||
#define CCID_DRIVER_ERR_NO_READER 0x1000c
|
||||
#define CCID_DRIVER_ERR_ABORTED 0x1000d
|
||||
#define CCID_DRIVER_ERR_NO_KEYPAD 0x1000e
|
||||
|
||||
struct ccid_driver_s;
|
||||
typedef struct ccid_driver_s *ccid_driver_t;
|
||||
|
@ -94,6 +95,10 @@ int ccid_transceive_secure (ccid_driver_t handle,
|
|||
int pin_mode,
|
||||
int pinlen_min, int pinlen_max, int pin_padlen,
|
||||
unsigned char *resp, size_t maxresplen, size_t *nresp);
|
||||
int ccid_transceive_escape (ccid_driver_t handle,
|
||||
const unsigned char *data, size_t datalen,
|
||||
unsigned char *resp, size_t maxresplen,
|
||||
size_t *nresp);
|
||||
|
||||
|
||||
|
||||
|
|
117
scd/iso7816.c
117
scd/iso7816.c
|
@ -47,9 +47,9 @@
|
|||
|
||||
|
||||
#define CMD_SELECT_FILE 0xA4
|
||||
#define CMD_VERIFY 0x20
|
||||
#define CMD_CHANGE_REFERENCE_DATA 0x24
|
||||
#define CMD_RESET_RETRY_COUNTER 0x2C
|
||||
#define CMD_VERIFY ISO7816_VERIFY
|
||||
#define CMD_CHANGE_REFERENCE_DATA ISO7816_CHANGE_REFERENCE_DATA
|
||||
#define CMD_RESET_RETRY_COUNTER ISO7816_RESET_RETRY_COUNTER
|
||||
#define CMD_GET_DATA 0xCA
|
||||
#define CMD_PUT_DATA 0xDA
|
||||
#define CMD_MSE 0x22
|
||||
|
@ -95,6 +95,7 @@ map_sw (int sw)
|
|||
case SW_HOST_GENERAL_ERROR: ec = GPG_ERR_GENERAL; break;
|
||||
case SW_HOST_NO_READER: ec = GPG_ERR_ENODEV; break;
|
||||
case SW_HOST_ABORTED: ec = GPG_ERR_CANCELED; break;
|
||||
case SW_HOST_NO_KEYPAD: ec = GPG_ERR_NOT_SUPPORTED; break;
|
||||
|
||||
default:
|
||||
if ((sw & 0x010000))
|
||||
|
@ -124,12 +125,15 @@ iso7816_map_sw (int sw)
|
|||
requested application ID. The function can't be used to enumerate
|
||||
AIDs and won't return the AID on success. The return value is 0
|
||||
for okay or a GPG error code. Note that ISO error codes are
|
||||
internally mapped. */
|
||||
internally mapped. Bit 0 of FLAGS should be set if the card does
|
||||
not understand P2=0xC0. */
|
||||
gpg_error_t
|
||||
iso7816_select_application (int slot, const char *aid, size_t aidlen)
|
||||
iso7816_select_application (int slot, const char *aid, size_t aidlen,
|
||||
unsigned int flags)
|
||||
{
|
||||
int sw;
|
||||
sw = apdu_send_simple (slot, 0x00, CMD_SELECT_FILE, 4, 0, aidlen, aid);
|
||||
sw = apdu_send_simple (slot, 0x00, CMD_SELECT_FILE, 4,
|
||||
(flags&1)? 0 :0x0c, aidlen, aid);
|
||||
return map_sw (sw);
|
||||
}
|
||||
|
||||
|
@ -221,27 +225,59 @@ iso7816_list_directory (int slot, int list_dirs,
|
|||
}
|
||||
|
||||
|
||||
/* Check whether the reader supports the ISO command code COMMAND on
|
||||
the keypad. Returns 0 on success. */
|
||||
gpg_error_t
|
||||
iso7816_check_keypad (int slot, int command, iso7816_pininfo_t *pininfo)
|
||||
{
|
||||
int sw;
|
||||
|
||||
sw = apdu_check_keypad (slot, command,
|
||||
pininfo->mode, pininfo->minlen, pininfo->maxlen,
|
||||
pininfo->padlen);
|
||||
return map_sw (sw);
|
||||
}
|
||||
|
||||
|
||||
/* Perform a VERIFY command on SLOT using the card holder verification
|
||||
vector CHVNO with a CHV of lenght CHVLEN. With PININFO non-NULL
|
||||
the keypad of the reader will be used. Returns 0 on success. */
|
||||
gpg_error_t
|
||||
iso7816_verify_kp (int slot, int chvno, const char *chv, size_t chvlen,
|
||||
iso7816_pininfo_t *pininfo)
|
||||
{
|
||||
int sw;
|
||||
|
||||
if (pininfo && pininfo->mode)
|
||||
sw = apdu_send_simple_kp (slot, 0x00, CMD_VERIFY, 0, chvno, chvlen, chv,
|
||||
pininfo->mode,
|
||||
pininfo->minlen,
|
||||
pininfo->maxlen,
|
||||
pininfo->padlen);
|
||||
else
|
||||
sw = apdu_send_simple (slot, 0x00, CMD_VERIFY, 0, chvno, chvlen, chv);
|
||||
return map_sw (sw);
|
||||
}
|
||||
|
||||
/* Perform a VERIFY command on SLOT using the card holder verification
|
||||
vector CHVNO with a CHV of lenght CHVLEN. Returns 0 on success. */
|
||||
gpg_error_t
|
||||
iso7816_verify (int slot, int chvno, const char *chv, size_t chvlen)
|
||||
{
|
||||
int sw;
|
||||
|
||||
sw = apdu_send_simple (slot, 0x00, CMD_VERIFY, 0, chvno, chvlen, chv);
|
||||
return map_sw (sw);
|
||||
return iso7816_verify_kp (slot, chvno, chv, chvlen, NULL);
|
||||
}
|
||||
|
||||
/* Perform a CHANGE_REFERENCE_DATA command on SLOT for the card holder
|
||||
verification vector CHVNO. If the OLDCHV is NULL (and OLDCHVLEN
|
||||
0), a "change reference data" is done, otherwise an "exchange
|
||||
reference data". The new reference data is expected in NEWCHV of
|
||||
length NEWCHVLEN. */
|
||||
length NEWCHVLEN. With PININFO non-NULL the keypad of the reader
|
||||
will be used. */
|
||||
gpg_error_t
|
||||
iso7816_change_reference_data (int slot, int chvno,
|
||||
const char *oldchv, size_t oldchvlen,
|
||||
const char *newchv, size_t newchvlen)
|
||||
iso7816_change_reference_data_kp (int slot, int chvno,
|
||||
const char *oldchv, size_t oldchvlen,
|
||||
const char *newchv, size_t newchvlen,
|
||||
iso7816_pininfo_t *pininfo)
|
||||
{
|
||||
int sw;
|
||||
char *buf;
|
||||
|
@ -258,28 +294,69 @@ iso7816_change_reference_data (int slot, int chvno,
|
|||
memcpy (buf, oldchv, oldchvlen);
|
||||
memcpy (buf+oldchvlen, newchv, newchvlen);
|
||||
|
||||
sw = apdu_send_simple (slot, 0x00, CMD_CHANGE_REFERENCE_DATA,
|
||||
oldchvlen? 0 : 1, chvno, oldchvlen+newchvlen, buf);
|
||||
if (pininfo && pininfo->mode)
|
||||
sw = apdu_send_simple_kp (slot, 0x00, CMD_CHANGE_REFERENCE_DATA,
|
||||
oldchvlen? 0 : 1, chvno, oldchvlen+newchvlen, buf,
|
||||
pininfo->mode,
|
||||
pininfo->minlen,
|
||||
pininfo->maxlen,
|
||||
pininfo->padlen);
|
||||
else
|
||||
sw = apdu_send_simple (slot, 0x00, CMD_CHANGE_REFERENCE_DATA,
|
||||
oldchvlen? 0 : 1, chvno, oldchvlen+newchvlen, buf);
|
||||
xfree (buf);
|
||||
return map_sw (sw);
|
||||
|
||||
}
|
||||
|
||||
/* Perform a CHANGE_REFERENCE_DATA command on SLOT for the card holder
|
||||
verification vector CHVNO. If the OLDCHV is NULL (and OLDCHVLEN
|
||||
0), a "change reference data" is done, otherwise an "exchange
|
||||
reference data". The new reference data is expected in NEWCHV of
|
||||
length NEWCHVLEN. */
|
||||
gpg_error_t
|
||||
iso7816_reset_retry_counter (int slot, int chvno,
|
||||
const char *newchv, size_t newchvlen)
|
||||
iso7816_change_reference_data (int slot, int chvno,
|
||||
const char *oldchv, size_t oldchvlen,
|
||||
const char *newchv, size_t newchvlen)
|
||||
{
|
||||
return iso7816_change_reference_data_kp (slot, chvno, oldchv, oldchvlen,
|
||||
newchv, newchvlen, NULL);
|
||||
}
|
||||
|
||||
|
||||
gpg_error_t
|
||||
iso7816_reset_retry_counter_kp (int slot, int chvno,
|
||||
const char *newchv, size_t newchvlen,
|
||||
iso7816_pininfo_t *pininfo)
|
||||
{
|
||||
int sw;
|
||||
|
||||
if (!newchv || !newchvlen )
|
||||
return gpg_error (GPG_ERR_INV_VALUE);
|
||||
|
||||
sw = apdu_send_simple (slot, 0x00, CMD_RESET_RETRY_COUNTER,
|
||||
2, chvno, newchvlen, newchv);
|
||||
if (pininfo && pininfo->mode)
|
||||
sw = apdu_send_simple_kp (slot, 0x00, CMD_RESET_RETRY_COUNTER,
|
||||
2, chvno, newchvlen, newchv,
|
||||
pininfo->mode,
|
||||
pininfo->minlen,
|
||||
pininfo->maxlen,
|
||||
pininfo->padlen);
|
||||
else
|
||||
sw = apdu_send_simple (slot, 0x00, CMD_RESET_RETRY_COUNTER,
|
||||
2, chvno, newchvlen, newchv);
|
||||
return map_sw (sw);
|
||||
}
|
||||
|
||||
|
||||
gpg_error_t
|
||||
iso7816_reset_retry_counter (int slot, int chvno,
|
||||
const char *newchv, size_t newchvlen)
|
||||
{
|
||||
return iso7816_reset_retry_counter_kp (slot, chvno, newchv, newchvlen, NULL);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Perform a GET DATA command requesting TAG and storing the result in
|
||||
a newly allocated buffer at the address passed by RESULT. Return
|
||||
the length of this data at the address of RESULTLEN. */
|
||||
|
|
|
@ -28,10 +28,30 @@
|
|||
#include "cardglue.h"
|
||||
#endif
|
||||
|
||||
/* Command codes used by iso7816_check_keypad. */
|
||||
#define ISO7816_VERIFY 0x20
|
||||
#define ISO7816_CHANGE_REFERENCE_DATA 0x24
|
||||
#define ISO7816_RESET_RETRY_COUNTER 0x2C
|
||||
|
||||
|
||||
/* Information to be passed to keypad equipped readers. See
|
||||
ccid-driver.c for details. */
|
||||
struct iso7816_pininfo_s
|
||||
{
|
||||
int mode; /* A mode of 0 means: Do not use the keypad. */
|
||||
int minlen;
|
||||
int maxlen;
|
||||
int padlen;
|
||||
int padchar;
|
||||
};
|
||||
typedef struct iso7816_pininfo_s iso7816_pininfo_t;
|
||||
|
||||
|
||||
gpg_error_t iso7816_map_sw (int sw);
|
||||
|
||||
gpg_error_t iso7816_select_application (int slot,
|
||||
const char *aid, size_t aidlen);
|
||||
const char *aid, size_t aidlen,
|
||||
unsigned int flags);
|
||||
gpg_error_t iso7816_select_file (int slot, int tag, int is_dir,
|
||||
unsigned char **result, size_t *resultlen);
|
||||
gpg_error_t iso7816_select_path (int slot,
|
||||
|
@ -39,13 +59,26 @@ gpg_error_t iso7816_select_path (int slot,
|
|||
unsigned char **result, size_t *resultlen);
|
||||
gpg_error_t iso7816_list_directory (int slot, int list_dirs,
|
||||
unsigned char **result, size_t *resultlen);
|
||||
gpg_error_t iso7816_check_keypad (int slot, int command,
|
||||
iso7816_pininfo_t *pininfo);
|
||||
gpg_error_t iso7816_verify (int slot,
|
||||
int chvno, const char *chv, size_t chvlen);
|
||||
gpg_error_t iso7816_verify_kp (int slot,
|
||||
int chvno, const char *chv, size_t chvlen,
|
||||
iso7816_pininfo_t *pininfo);
|
||||
gpg_error_t iso7816_change_reference_data (int slot, int chvno,
|
||||
const char *oldchv, size_t oldchvlen,
|
||||
const char *newchv, size_t newchvlen);
|
||||
gpg_error_t iso7816_change_reference_data_kp (int slot, int chvno,
|
||||
const char *oldchv, size_t oldchvlen,
|
||||
const char *newchv, size_t newchvlen,
|
||||
iso7816_pininfo_t *pininfo);
|
||||
gpg_error_t iso7816_reset_retry_counter (int slot, int chvno,
|
||||
const char *newchv, size_t newchvlen);
|
||||
gpg_error_t iso7816_reset_retry_counter_kp (int slot, int chvno,
|
||||
const char *newchv,
|
||||
size_t newchvlen,
|
||||
iso7816_pininfo_t *pininfo);
|
||||
gpg_error_t iso7816_get_data (int slot, int tag,
|
||||
unsigned char **result, size_t *resultlen);
|
||||
gpg_error_t iso7816_put_data (int slot, int tag,
|
||||
|
|
|
@ -84,6 +84,7 @@ enum cmd_and_opt_values
|
|||
opcscDriver,
|
||||
oDisableCCID,
|
||||
oDisableOpenSC,
|
||||
oDisableKeypad,
|
||||
oAllowAdmin,
|
||||
oDenyAdmin,
|
||||
oDisableApplication,
|
||||
|
@ -126,6 +127,7 @@ static ARGPARSE_OPTS opts[] = {
|
|||
"@"
|
||||
#endif
|
||||
/* end --disable-ccid */},
|
||||
{ oDisableKeypad, "disable-keypad", 0, N_("do not use a reader's keypad")},
|
||||
{ oAllowAdmin, "allow-admin", 0, N_("allow the use of admin card commands")},
|
||||
{ oDenyAdmin, "deny-admin", 0, "@" },
|
||||
{ oDisableApplication, "disable-application", 2, "@"},
|
||||
|
@ -135,7 +137,7 @@ static ARGPARSE_OPTS opts[] = {
|
|||
|
||||
|
||||
/* The card dirver we use by default for PC/SC. */
|
||||
#ifdef HAVE_W32_SYSTEM
|
||||
#if defined(HAVE_W32_SYSTEM) || defined(__CYGWIN__)
|
||||
#define DEFAULT_PCSC_DRIVER "winscard.dll"
|
||||
#else
|
||||
#define DEFAULT_PCSC_DRIVER "libpcsclite.so"
|
||||
|
@ -489,6 +491,8 @@ main (int argc, char **argv )
|
|||
case oDisableCCID: opt.disable_ccid = 1; break;
|
||||
case oDisableOpenSC: break;
|
||||
|
||||
case oDisableKeypad: opt.disable_keypad = 1; break;
|
||||
|
||||
case oAllowAdmin: opt.allow_admin = 1; break;
|
||||
case oDenyAdmin: opt.allow_admin = 0; break;
|
||||
|
||||
|
|
|
@ -39,21 +39,22 @@
|
|||
|
||||
#define MAX_DIGEST_LEN 24
|
||||
|
||||
/* A large struct name "opt" to keep global flags */
|
||||
/* A large struct name "opt" to keep global flags. */
|
||||
struct {
|
||||
unsigned int debug; /* debug flags (DBG_foo_VALUE) */
|
||||
int verbose; /* verbosity level */
|
||||
int quiet; /* be as quiet as possible */
|
||||
int dry_run; /* don't change any persistent data */
|
||||
int batch; /* batch mode */
|
||||
const char *homedir; /* configuration directory name */
|
||||
unsigned int debug; /* Debug flags (DBG_foo_VALUE). */
|
||||
int verbose; /* Verbosity level. */
|
||||
int quiet; /* Be as quiet as possible. */
|
||||
int dry_run; /* Don't change any persistent data. */
|
||||
int batch; /* Batch mode. */
|
||||
const char *homedir; /* Configuration directory name. */
|
||||
const char *ctapi_driver; /* Library to access the ctAPI. */
|
||||
const char *pcsc_driver; /* Library to access the PC/SC system. */
|
||||
const char *reader_port; /* NULL or reder port to use. */
|
||||
int disable_ccid; /* Disable the use of the internal CCID driver. */
|
||||
int disable_keypad; /* Do not use a keypad. */
|
||||
int allow_admin; /* Allow the use of admin commands for certain
|
||||
cards. */
|
||||
strlist_t disabled_applications; /* card applications we do not
|
||||
strlist_t disabled_applications; /* Card applications we do not
|
||||
want to use. */
|
||||
} opt;
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue