mirror of
git://git.gnupg.org/gnupg.git
synced 2024-12-22 10:19:57 +01:00
* app-openpgp.c (do_check_pin): Add hack to allow verification of
CHV3. (get_public_key): Don't use gcry functions to create S-expressions. (do_deinit, do_readkey, do_genkey, send_keypair_info): Adjust for above change.
This commit is contained in:
parent
45eba6e5de
commit
6b002f0602
@ -1,3 +1,11 @@
|
||||
2005-04-07 Werner Koch <wk@g10code.com>
|
||||
|
||||
* app-openpgp.c (do_check_pin): Add hack to allow verification of
|
||||
CHV3.
|
||||
(get_public_key): Don't use gcry functions to create S-expressions.
|
||||
(do_deinit, do_readkey, do_genkey, send_keypair_info): Adjust for
|
||||
above change.
|
||||
|
||||
2005-03-29 Moritz Schulte <moritz@g10code.com>
|
||||
|
||||
* app-openpgp.c (retrieve_fpr_from_card): New function.
|
||||
@ -6,6 +14,19 @@
|
||||
(get_public_key): Implement retrival of key through expernal
|
||||
helper (gpg) in case the openpgp card is not cooperative enough.
|
||||
|
||||
2005-03-16 Werner Koch <wk@g10code.com>
|
||||
|
||||
* ccid-driver.c (parse_ccid_descriptor): Make SCM workaround
|
||||
reader type specific.
|
||||
(scan_or_find_devices): Do not check the interface subclass in the
|
||||
SPR532 kludge, as this depends on the firmware version.
|
||||
(ccid_get_atr): Get the Slot status first. This solves the
|
||||
problem with readers hanging on recent Linux 2.6.x.
|
||||
(bulk_in): Add argument TIMEOUT and changed all callers to pass an
|
||||
appropriate one. Change the standard timeout from 10 to 5 seconds.
|
||||
(ccid_slot_status): Add a retry code with an initial short timeout.
|
||||
(do_close_reader): Do an usb_reset before closing the reader.
|
||||
|
||||
2005-02-25 Werner Koch <wk@g10code.com>
|
||||
|
||||
* app-openpgp.c (get_public_key): Make sure not to return negative
|
||||
@ -42,6 +63,15 @@
|
||||
(reset_pcsc_reader, pcsc_get_status, pcsc_send_apdu)
|
||||
(open_pcsc_reader): Do proper error code mapping.
|
||||
|
||||
2005-03-16 Werner Koch <wk@g10code.com>
|
||||
|
||||
* ccid-driver.c (parse_ccid_descriptor): Make SCM workaround
|
||||
reader type specific.
|
||||
(scan_or_find_devices): Do not check the interface subclass in the
|
||||
SPR532 kludge, as this depends on the firmware version.
|
||||
(ccid_get_atr): Get the Slot status first. This solves the
|
||||
problem with readers hanging on recent Linux 2.6.x.
|
||||
|
||||
2005-02-22 Werner Koch <wk@g10code.com>
|
||||
|
||||
* app-openpgp.c (app_local_s): New field PK.
|
||||
|
@ -108,7 +108,14 @@ struct app_local_s {
|
||||
struct
|
||||
{
|
||||
int read_done; /* True if we have at least tried to read them. */
|
||||
gcry_sexp_t key; /* Might be NULL if key is not available. */
|
||||
unsigned char *key; /* This is a malloced buffer with a canonical
|
||||
encoded S-expression encoding a public
|
||||
key. Might be NULL if key is not
|
||||
available. */
|
||||
size_t keylen; /* The length of the above S-expression. Thsi
|
||||
is usullay only required for corss checks
|
||||
because the length of an S-expression is
|
||||
implicitly available. */
|
||||
} pk[3];
|
||||
|
||||
/* Keep track of card capabilities. */
|
||||
@ -156,7 +163,7 @@ do_deinit (app_t app)
|
||||
|
||||
for (i=0; i < DIM (app->app_local->pk); i++)
|
||||
{
|
||||
gcry_sexp_release (app->app_local->pk[i].key);
|
||||
xfree (app->app_local->pk[i].key);
|
||||
app->app_local->pk[i].read_done = 0;
|
||||
}
|
||||
xfree (app->app_local);
|
||||
@ -864,6 +871,10 @@ retrieve_key_material (FILE *fp, const char *fpr,
|
||||
mpi = NULL;
|
||||
ret = 0;
|
||||
|
||||
#warning This part should get rewritten for clarity
|
||||
/* We should use an algorithm similar to the one used by gpgme.
|
||||
This will reduce the size of the code at least by 50%. [wk] */
|
||||
|
||||
while (1)
|
||||
{
|
||||
/* FIXME? */
|
||||
@ -1041,7 +1052,9 @@ retrieve_key_material (FILE *fp, const char *fpr,
|
||||
presence of the app->app_local->pk[KEYNO-1].key field.
|
||||
|
||||
Note that GnuPG 1.x does not need this and it would be too time
|
||||
consuming to send it just for the fun of it. */
|
||||
consuming to send it just for the fun of it. However, given that we
|
||||
use the same code in gpg 1.4, we can't use the gcry S-expresion
|
||||
here but need to open encode it. */
|
||||
#if GNUPG_MAJOR_VERSION > 1
|
||||
static gpg_error_t
|
||||
get_public_key (app_t app, int keyno)
|
||||
@ -1050,9 +1063,10 @@ get_public_key (app_t app, int keyno)
|
||||
unsigned char *buffer;
|
||||
const unsigned char *keydata, *m, *e;
|
||||
size_t buflen, keydatalen, mlen, elen;
|
||||
gcry_sexp_t sexp;
|
||||
unsigned char *mbuf = NULL;
|
||||
unsigned char *ebuf = NULL;
|
||||
unsigned char *keybuf = NULL;
|
||||
unsigned char *keybuf_p;
|
||||
|
||||
if (keyno < 1 || keyno > 3)
|
||||
return gpg_error (GPG_ERR_INV_ID);
|
||||
@ -1062,8 +1076,9 @@ get_public_key (app_t app, int keyno)
|
||||
if (app->app_local->pk[keyno].read_done)
|
||||
return 0;
|
||||
|
||||
gcry_sexp_release (app->app_local->pk[keyno].key);
|
||||
xfree (app->app_local->pk[keyno].key);
|
||||
app->app_local->pk[keyno].key = NULL;
|
||||
app->app_local->pk[keyno].keylen = 0;
|
||||
|
||||
if (app->card_version > 0x0100)
|
||||
{
|
||||
@ -1191,16 +1206,29 @@ get_public_key (app_t app, int keyno)
|
||||
buffer = NULL;
|
||||
}
|
||||
|
||||
err = gcry_sexp_build (&sexp, NULL,
|
||||
"(public-key (rsa (n %b) (e %b)))",
|
||||
(int)mlen, m,(int)elen, e);
|
||||
if (err)
|
||||
/* Allocate a buffer to construct the S-expression. */
|
||||
/* FIXME: We should provide a generalized S-expression creation
|
||||
mechanism. */
|
||||
keybuf = xtrymalloc (50 + 2*35 + mlen + elen + 1);
|
||||
if (!keybuf)
|
||||
{
|
||||
log_error ("error formatting the key into an S-expression: %s\n",
|
||||
gpg_strerror (err));
|
||||
err = gpg_error_from_errno (errno);
|
||||
goto leave;
|
||||
}
|
||||
app->app_local->pk[keyno].key = sexp;
|
||||
|
||||
sprintf (keybuf, "(10:public-key(3:rsa(1:n%u", (unsigned int) mlen);
|
||||
keybuf_p = keybuf + strlen (keybuf);
|
||||
memcpy (keybuf_p, m, mlen);
|
||||
keybuf_p += mlen;
|
||||
sprintf (keybuf_p, ")(1:e%u", (unsigned int)elen);
|
||||
keybuf_p += strlen (keybuf_p);
|
||||
memcpy (keybuf_p, e, elen);
|
||||
keybuf_p += elen;
|
||||
strcpy (keybuf_p, ")))");
|
||||
keybuf_p += strlen (keybuf_p);
|
||||
|
||||
app->app_local->pk[keyno].key = keybuf;
|
||||
app->app_local->pk[keyno].keylen = (keybuf_p - keybuf);
|
||||
|
||||
leave:
|
||||
/* Set a flag to indicate that we tried to read the key. */
|
||||
@ -1224,7 +1252,6 @@ send_keypair_info (app_t app, ctrl_t ctrl, int keyno)
|
||||
/* Note that GnuPG 1.x does not need this and it would be too time
|
||||
consuming to send it just for the fun of it. */
|
||||
#if GNUPG_MAJOR_VERSION > 1
|
||||
gcry_sexp_t sexp;
|
||||
unsigned char grip[20];
|
||||
char gripstr[41];
|
||||
char idbuf[50];
|
||||
@ -1235,15 +1262,14 @@ send_keypair_info (app_t app, ctrl_t ctrl, int keyno)
|
||||
goto leave;
|
||||
|
||||
assert (keyno >= 1 && keyno <= 3);
|
||||
sexp = app->app_local->pk[keyno-1].key;
|
||||
if (!sexp)
|
||||
goto leave; /* No such key. */
|
||||
if (!app->app_local->pk[keyno-1].key)
|
||||
goto leave; /* No such key - ignore. */
|
||||
|
||||
if (!gcry_pk_get_keygrip (sexp, grip))
|
||||
{
|
||||
err = gpg_error (GPG_ERR_INTERNAL);
|
||||
err = keygrip_from_canon_sexp (app->app_local->pk[keyno-1].key,
|
||||
app->app_local->pk[keyno-1].keylen,
|
||||
grip);
|
||||
if (err)
|
||||
goto leave;
|
||||
}
|
||||
|
||||
for (i=0; i < 20; i++)
|
||||
sprintf (gripstr+i*2, "%02X", grip[i]);
|
||||
@ -1303,9 +1329,7 @@ do_readkey (app_t app, const char *keyid, unsigned char **pk, size_t *pklen)
|
||||
{
|
||||
gpg_error_t err;
|
||||
int keyno;
|
||||
size_t n;
|
||||
unsigned char *buf;
|
||||
gcry_sexp_t sexp;
|
||||
|
||||
if (!strcmp (keyid, "OPENPGP.1"))
|
||||
keyno = 1;
|
||||
@ -1320,24 +1344,11 @@ do_readkey (app_t app, const char *keyid, unsigned char **pk, size_t *pklen)
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
sexp = app->app_local->pk[keyno-1].key;
|
||||
if (!sexp)
|
||||
return gpg_error (GPG_ERR_NO_PUBKEY);
|
||||
|
||||
n = gcry_sexp_sprint (sexp, GCRYSEXP_FMT_CANON, NULL, 0);
|
||||
if (!n)
|
||||
return gpg_error (GPG_ERR_BUG);
|
||||
buf = xtrymalloc (n);
|
||||
buf = app->app_local->pk[keyno-1].key;
|
||||
if (!buf)
|
||||
return gpg_error_from_errno (errno);
|
||||
n = gcry_sexp_sprint (sexp, GCRYSEXP_FMT_CANON, buf, n);
|
||||
if (!n)
|
||||
{
|
||||
xfree (buf);
|
||||
return gpg_error (GPG_ERR_BUG);
|
||||
}
|
||||
return gpg_error (GPG_ERR_NO_PUBKEY);
|
||||
*pk = buf;
|
||||
*pklen = n;
|
||||
*pklen = app->app_local->pk[keyno-1].keylen;;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1590,7 +1601,7 @@ do_change_pin (app_t app, ctrl_t ctrl, const char *chvnostr, int reset_mode,
|
||||
else
|
||||
app->did_chv1 = app->did_chv2 = 0;
|
||||
|
||||
/* Note to translators: Do not translate the "|*|" prefixes but
|
||||
/* TRANSLATORS: Do not translate the "|*|" prefixes but
|
||||
keep it at the start of the string. We need this elsewhere
|
||||
to get some infos on the string. */
|
||||
rc = pincb (pincb_arg, chvno == 3? _("|AN|New Admin PIN") : _("|N|New PIN"),
|
||||
@ -1661,7 +1672,9 @@ do_genkey (app_t app, ctrl_t ctrl, const char *keynostr, unsigned int flags,
|
||||
flush_cache (app);
|
||||
|
||||
/* Obviously we need to remove the cached public key. */
|
||||
gcry_sexp_release (app->app_local->pk[keyno].key);
|
||||
xfree (app->app_local->pk[keyno].key);
|
||||
app->app_local->pk[keyno].key = NULL;
|
||||
app->app_local->pk[keyno].keylen = 0;
|
||||
app->app_local->pk[keyno].read_done = 0;
|
||||
|
||||
/* Check whether a key already exists. */
|
||||
@ -2142,7 +2155,11 @@ do_decipher (app_t app, const char *keyidstr,
|
||||
cheap check on the PIN: If there is something wrong with the PIN
|
||||
entry system, only the regular CHV will get blocked and not the
|
||||
dangerous CHV3. KEYIDSTR is the usual card's serial number; an
|
||||
optional fingerprint part will be ignored. */
|
||||
optional fingerprint part will be ignored.
|
||||
|
||||
There is a special mode if the keyidstr is "<serialno>[CHV3]" with
|
||||
the "[CHV3]" being a literal string: The Admin Pin is checked if
|
||||
and only if the retry counter is still at 3. */
|
||||
static int
|
||||
do_check_pin (app_t app, const char *keyidstr,
|
||||
int (pincb)(void*, const char *, char **),
|
||||
@ -2151,6 +2168,7 @@ do_check_pin (app_t app, const char *keyidstr,
|
||||
unsigned char tmp_sn[20];
|
||||
const char *s;
|
||||
int n;
|
||||
int admin_pin = 0;
|
||||
|
||||
if (!keyidstr || !*keyidstr)
|
||||
return gpg_error (GPG_ERR_INV_VALUE);
|
||||
@ -2167,6 +2185,8 @@ do_check_pin (app_t app, const char *keyidstr,
|
||||
; /* No fingerprint given: we allow this for now. */
|
||||
else if (*s == '/')
|
||||
; /* We ignore a fingerprint. */
|
||||
else if (!strcmp (s, "[CHV3]") )
|
||||
admin_pin = 1;
|
||||
else
|
||||
return gpg_error (GPG_ERR_INV_ID);
|
||||
|
||||
@ -2177,11 +2197,45 @@ do_check_pin (app_t app, const char *keyidstr,
|
||||
return gpg_error (GPG_ERR_INV_CARD);
|
||||
if (memcmp (app->serialno, tmp_sn, 16))
|
||||
return gpg_error (GPG_ERR_WRONG_CARD);
|
||||
|
||||
/* Yes, there is a race conditions: The user might pull the card
|
||||
right here and we won't notice that. However this is not a
|
||||
problem and the check above is merely for a graceful failure
|
||||
between operations. */
|
||||
|
||||
if (admin_pin)
|
||||
{
|
||||
void *relptr;
|
||||
unsigned char *value;
|
||||
size_t valuelen;
|
||||
int count;
|
||||
|
||||
relptr = get_one_do (app, 0x00C4, &value, &valuelen, NULL);
|
||||
if (!relptr || valuelen < 7)
|
||||
{
|
||||
log_error (_("error retrieving CHV status from card\n"));
|
||||
xfree (relptr);
|
||||
return gpg_error (GPG_ERR_CARD);
|
||||
}
|
||||
count = value[6];
|
||||
xfree (relptr);
|
||||
|
||||
if (!count)
|
||||
{
|
||||
log_info (_("card is permanently locked!\n"));
|
||||
return gpg_error (GPG_ERR_BAD_PIN);
|
||||
}
|
||||
else if (value[6] < 3)
|
||||
{
|
||||
log_info (_("verification of Admin PIN is currently prohibited "
|
||||
"through this command\n"));
|
||||
return gpg_error (GPG_ERR_GENERAL);
|
||||
}
|
||||
|
||||
app->did_chv3 = 0; /* Force verification. */
|
||||
return verify_chv3 (app, pincb, pincb_arg);
|
||||
}
|
||||
else
|
||||
return verify_chv2 (app, pincb, pincb_arg);
|
||||
}
|
||||
|
||||
@ -2415,7 +2469,9 @@ app_openpgp_storekey (app_t app, int keyno,
|
||||
|
||||
flush_cache (app);
|
||||
|
||||
gcry_sexp_release (app->app_local->pk[keyno].key);
|
||||
xfree (app->app_local->pk[keyno].key);
|
||||
app->app_local->pk[keyno].key = NULL;
|
||||
app->app_local->pk[keyno].keylen = 0;
|
||||
app->app_local->pk[keyno].read_done = 0;
|
||||
|
||||
rc = iso7816_put_data (app->slot,
|
||||
|
@ -489,7 +489,7 @@ app_change_pin (APP app, CTRL ctrl, const char *chvnostr, int reset_mode,
|
||||
|
||||
|
||||
/* Perform a VERIFY operation without doing anything lese. This may
|
||||
be used to initialze a the PION cache for long lasting other
|
||||
be used to initialze a the PIN cache for long lasting other
|
||||
operations. Its use is highly application dependent. */
|
||||
int
|
||||
app_check_pin (APP app, const char *keyidstr,
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* ccid-driver.c - USB ChipCardInterfaceDevices driver
|
||||
* Copyright (C) 2003, 2004 Free Software Foundation, Inc.
|
||||
* Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc.
|
||||
* Written by Werner Koch.
|
||||
*
|
||||
* This file is part of GnuPG.
|
||||
@ -52,7 +52,7 @@
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* $Id$
|
||||
* $Date$
|
||||
*/
|
||||
|
||||
|
||||
@ -223,7 +223,7 @@ static unsigned int compute_edc (const unsigned char *data, size_t datalen,
|
||||
int use_crc);
|
||||
static int bulk_out (ccid_driver_t handle, unsigned char *msg, size_t msglen);
|
||||
static int bulk_in (ccid_driver_t handle, unsigned char *buffer, size_t length,
|
||||
size_t *nread, int expected_type, int seqno);
|
||||
size_t *nread, int expected_type, int seqno, int timeout);
|
||||
|
||||
/* Convert a little endian stored 4 byte value into an unsigned
|
||||
integer. */
|
||||
@ -446,12 +446,20 @@ parse_ccid_descriptor (ccid_driver_t handle,
|
||||
send a frame of n*wMaxPacketSize back to us. Given that
|
||||
wMaxPacketSize is 64 for these readers we set the IFSD to a value
|
||||
lower than that:
|
||||
64 - 10 CCID header - 4 T1frame - 2 reserved = 48 */
|
||||
64 - 10 CCID header - 4 T1frame - 2 reserved = 48
|
||||
Product Ids:
|
||||
0xe001 - SCR 331
|
||||
0x5111 - SCR 331-DI
|
||||
0x5115 - SCR 335
|
||||
0xe003 - SPR 532
|
||||
*/
|
||||
if (handle->id_vendor == VENDOR_SCM
|
||||
/* FIXME: check whether it is the same
|
||||
firmware version for all drivers. */
|
||||
&& handle->bcd_device < 0x0519
|
||||
&& handle->max_ifsd > 48)
|
||||
&& handle->max_ifsd > 48
|
||||
&& ( (handle->id_product == 0xe001 && handle->bcd_device < 0x0516)
|
||||
||(handle->id_product == 0x5111 && handle->bcd_device < 0x0620)
|
||||
||(handle->id_product == 0x5115 && handle->bcd_device < 0x0519)
|
||||
||(handle->id_product == 0xe003 && handle->bcd_device < 0x0504)
|
||||
))
|
||||
{
|
||||
DEBUGOUT ("enabling workaround for buggy SCM readers\n");
|
||||
handle->max_ifsd = 48;
|
||||
@ -699,9 +707,7 @@ scan_or_find_devices (int readerno, const char *readerid,
|
||||
&& ifcdesc->bInterfaceProtocol == 0)
|
||||
|| (ifcdesc->bInterfaceClass == 255
|
||||
&& dev->descriptor.idVendor == 0x04e6
|
||||
&& dev->descriptor.idProduct == 0xe003
|
||||
&& ifcdesc->bInterfaceSubClass == 1
|
||||
&& ifcdesc->bInterfaceProtocol == 1)))
|
||||
&& dev->descriptor.idProduct == 0xe003)))
|
||||
{
|
||||
idev = usb_open (dev);
|
||||
if (!idev)
|
||||
@ -974,11 +980,13 @@ do_close_reader (ccid_driver_t handle)
|
||||
|
||||
rc = bulk_out (handle, msg, msglen);
|
||||
if (!rc)
|
||||
bulk_in (handle, msg, sizeof msg, &msglen, RDR_to_PC_SlotStatus,seqno);
|
||||
bulk_in (handle, msg, sizeof msg, &msglen, RDR_to_PC_SlotStatus,
|
||||
seqno, 2000);
|
||||
handle->powered_off = 1;
|
||||
}
|
||||
if (handle->idev)
|
||||
{
|
||||
usb_reset (handle->idev);
|
||||
usb_release_interface (handle->idev, handle->ifc_no);
|
||||
usb_close (handle->idev);
|
||||
handle->idev = NULL;
|
||||
@ -1102,10 +1110,10 @@ bulk_out (ccid_driver_t handle, unsigned char *msg, size_t msglen)
|
||||
BUFFER and return the actual read number if bytes in NREAD. SEQNO
|
||||
is the sequence number used to send the request and EXPECTED_TYPE
|
||||
the type of message we expect. Does checks on the ccid
|
||||
header. Returns 0 on success. */
|
||||
header. TIMEOUT is the timeout value in ms. Returns 0 on success. */
|
||||
static int
|
||||
bulk_in (ccid_driver_t handle, unsigned char *buffer, size_t length,
|
||||
size_t *nread, int expected_type, int seqno)
|
||||
size_t *nread, int expected_type, int seqno, int timeout)
|
||||
{
|
||||
int i, rc;
|
||||
size_t msglen;
|
||||
@ -1117,9 +1125,7 @@ bulk_in (ccid_driver_t handle, unsigned char *buffer, size_t length,
|
||||
rc = usb_bulk_read (handle->idev,
|
||||
handle->ep_bulk_in,
|
||||
buffer, length,
|
||||
10000 /* ms timeout */ );
|
||||
/* Fixme: instead of using a 10 second timeout we should better
|
||||
handle the timeout here and retry if appropriate. */
|
||||
timeout);
|
||||
if (rc < 0)
|
||||
{
|
||||
DEBUGOUT_1 ("usb_bulk_read error: %s\n", strerror (errno));
|
||||
@ -1175,7 +1181,7 @@ bulk_in (ccid_driver_t handle, unsigned char *buffer, size_t length,
|
||||
}
|
||||
|
||||
|
||||
/* Note that this fucntion won't return the error codes NO_CARD or
|
||||
/* Note that this function won't return the error codes NO_CARD or
|
||||
CARD_INACTIVE */
|
||||
static int
|
||||
send_escape_cmd (ccid_driver_t handle,
|
||||
@ -1206,7 +1212,8 @@ send_escape_cmd (ccid_driver_t handle,
|
||||
rc = bulk_out (handle, msg, msglen);
|
||||
if (rc)
|
||||
return rc;
|
||||
rc = bulk_in (handle, msg, sizeof msg, &msglen, RDR_to_PC_Escape, seqno);
|
||||
rc = bulk_in (handle, msg, sizeof msg, &msglen, RDR_to_PC_Escape,
|
||||
seqno, 5000);
|
||||
|
||||
return rc;
|
||||
}
|
||||
@ -1276,7 +1283,9 @@ ccid_slot_status (ccid_driver_t handle, int *statusbits)
|
||||
unsigned char msg[100];
|
||||
size_t msglen;
|
||||
unsigned char seqno;
|
||||
int retries = 0;
|
||||
|
||||
retry:
|
||||
msg[0] = PC_to_RDR_GetSlotStatus;
|
||||
msg[5] = 0; /* slot */
|
||||
msg[6] = seqno = handle->seqno++;
|
||||
@ -1288,7 +1297,21 @@ ccid_slot_status (ccid_driver_t handle, int *statusbits)
|
||||
rc = bulk_out (handle, msg, 10);
|
||||
if (rc)
|
||||
return rc;
|
||||
rc = bulk_in (handle, msg, sizeof msg, &msglen, RDR_to_PC_SlotStatus, seqno);
|
||||
rc = bulk_in (handle, msg, sizeof msg, &msglen, RDR_to_PC_SlotStatus,
|
||||
seqno, retries? 1000 : 200);
|
||||
if (rc == CCID_DRIVER_ERR_CARD_IO_ERROR && retries < 3)
|
||||
{
|
||||
if (!retries)
|
||||
{
|
||||
fprintf (stderr, "CALLING USB_CLEAR_HALT\n");
|
||||
usb_clear_halt (handle->idev, handle->ep_bulk_in);
|
||||
usb_clear_halt (handle->idev, handle->ep_bulk_out);
|
||||
}
|
||||
else
|
||||
fprintf (stderr, "RETRYING AGIAN\n");
|
||||
retries++;
|
||||
goto retry;
|
||||
}
|
||||
if (rc && rc != CCID_DRIVER_ERR_NO_CARD
|
||||
&& rc != CCID_DRIVER_ERR_CARD_INACTIVE)
|
||||
return rc;
|
||||
@ -1303,6 +1326,7 @@ ccid_get_atr (ccid_driver_t handle,
|
||||
unsigned char *atr, size_t maxatrlen, size_t *atrlen)
|
||||
{
|
||||
int rc;
|
||||
int statusbits;
|
||||
unsigned char msg[100];
|
||||
unsigned char *tpdu;
|
||||
size_t msglen, tpdulen;
|
||||
@ -1311,6 +1335,15 @@ ccid_get_atr (ccid_driver_t handle,
|
||||
unsigned int edc;
|
||||
int i;
|
||||
|
||||
/* First check whether a card is available. */
|
||||
rc = ccid_slot_status (handle, &statusbits);
|
||||
if (rc)
|
||||
return rc;
|
||||
if (statusbits == 2)
|
||||
return CCID_DRIVER_ERR_NO_CARD;
|
||||
|
||||
/* For an inactive and also for an active card, issue the PowerOn
|
||||
command to get the ATR. */
|
||||
msg[0] = PC_to_RDR_IccPowerOn;
|
||||
msg[5] = 0; /* slot */
|
||||
msg[6] = seqno = handle->seqno++;
|
||||
@ -1323,7 +1356,8 @@ ccid_get_atr (ccid_driver_t handle,
|
||||
rc = bulk_out (handle, msg, msglen);
|
||||
if (rc)
|
||||
return rc;
|
||||
rc = bulk_in (handle, msg, sizeof msg, &msglen, RDR_to_PC_DataBlock, seqno);
|
||||
rc = bulk_in (handle, msg, sizeof msg, &msglen, RDR_to_PC_DataBlock,
|
||||
seqno, 5000);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
@ -1367,7 +1401,8 @@ ccid_get_atr (ccid_driver_t handle,
|
||||
if (rc)
|
||||
return rc;
|
||||
/* Note that we ignore the error code on purpose. */
|
||||
bulk_in (handle, msg, sizeof msg, &msglen, RDR_to_PC_Parameters, seqno);
|
||||
bulk_in (handle, msg, sizeof msg, &msglen, RDR_to_PC_Parameters,
|
||||
seqno, 5000);
|
||||
|
||||
handle->t1_ns = 0;
|
||||
handle->t1_nr = 0;
|
||||
@ -1414,7 +1449,7 @@ ccid_get_atr (ccid_driver_t handle,
|
||||
|
||||
|
||||
rc = bulk_in (handle, msg, sizeof msg, &msglen,
|
||||
RDR_to_PC_DataBlock, seqno);
|
||||
RDR_to_PC_DataBlock, seqno, 5000);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
@ -1510,7 +1545,7 @@ ccid_transceive_apdu_level (ccid_driver_t handle,
|
||||
|
||||
msg = recv_buffer;
|
||||
rc = bulk_in (handle, msg, sizeof recv_buffer, &msglen,
|
||||
RDR_to_PC_DataBlock, seqno);
|
||||
RDR_to_PC_DataBlock, seqno, 5000);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
@ -1683,7 +1718,7 @@ ccid_transceive (ccid_driver_t handle,
|
||||
|
||||
msg = recv_buffer;
|
||||
rc = bulk_in (handle, msg, sizeof recv_buffer, &msglen,
|
||||
RDR_to_PC_DataBlock, seqno);
|
||||
RDR_to_PC_DataBlock, seqno, 5000);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
@ -1692,7 +1727,7 @@ ccid_transceive (ccid_driver_t handle,
|
||||
|
||||
if (tpdulen < 4)
|
||||
{
|
||||
usb_clear_halt (handle->idev, 0x82);
|
||||
usb_clear_halt (handle->idev, handle->ep_bulk_in);
|
||||
return CCID_DRIVER_ERR_ABORTED;
|
||||
}
|
||||
#ifdef DEBUG_T1
|
||||
@ -1960,7 +1995,7 @@ ccid_transceive_secure (ccid_driver_t handle,
|
||||
|
||||
msg = recv_buffer;
|
||||
rc = bulk_in (handle, msg, sizeof recv_buffer, &msglen,
|
||||
RDR_to_PC_DataBlock, seqno);
|
||||
RDR_to_PC_DataBlock, seqno, 5000);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
|
@ -108,7 +108,7 @@ do_reset (ctrl_t ctrl, int do_close)
|
||||
|
||||
|
||||
static void
|
||||
reset_notify (ASSUAN_CONTEXT ctx)
|
||||
reset_notify (assuan_context_t ctx)
|
||||
{
|
||||
CTRL ctrl = assuan_get_pointer (ctx);
|
||||
|
||||
@ -117,7 +117,7 @@ reset_notify (ASSUAN_CONTEXT ctx)
|
||||
|
||||
|
||||
static int
|
||||
option_handler (ASSUAN_CONTEXT ctx, const char *key, const char *value)
|
||||
option_handler (assuan_context_t ctx, const char *key, const char *value)
|
||||
{
|
||||
ctrl_t ctrl = assuan_get_pointer (ctx);
|
||||
|
||||
@ -248,6 +248,10 @@ cmd_serialno (assuan_context_t ctx, char *line)
|
||||
time_t stamp;
|
||||
|
||||
/* Clear the remove flag so that the open_card is able to reread it. */
|
||||
|
||||
/* FIXME: We can't do that if we are in a locked state. Retrun an
|
||||
appropriate erro r in that case. IF the card has not been
|
||||
removed we may very well continue. */
|
||||
if (ctrl->server_local->card_removed)
|
||||
do_reset (ctrl, 0);
|
||||
|
||||
@ -333,9 +337,10 @@ cmd_serialno (assuan_context_t ctx, char *line)
|
||||
|
||||
The URL to be used for locating the entire public key.
|
||||
|
||||
Note, that this function may be even be used on a locked card.
|
||||
*/
|
||||
static int
|
||||
cmd_learn (ASSUAN_CONTEXT ctx, char *line)
|
||||
cmd_learn (assuan_context_t ctx, char *line)
|
||||
{
|
||||
CTRL ctrl = assuan_get_pointer (ctx);
|
||||
int rc = 0;
|
||||
@ -481,9 +486,10 @@ cmd_learn (ASSUAN_CONTEXT ctx, char *line)
|
||||
|
||||
/* READCERT <hexified_certid>
|
||||
|
||||
Note, that this function may be even be used on a locked card.
|
||||
*/
|
||||
static int
|
||||
cmd_readcert (ASSUAN_CONTEXT ctx, char *line)
|
||||
cmd_readcert (assuan_context_t ctx, char *line)
|
||||
{
|
||||
CTRL ctrl = assuan_get_pointer (ctx);
|
||||
int rc;
|
||||
@ -524,7 +530,10 @@ cmd_readcert (ASSUAN_CONTEXT ctx, char *line)
|
||||
/* READKEY <hexified_certid>
|
||||
|
||||
Return the public key for the given cert or key ID as an standard
|
||||
S-Expression. */
|
||||
S-Expression.
|
||||
|
||||
Note, that this function may be even be used on a locked card.
|
||||
*/
|
||||
static int
|
||||
cmd_readkey (assuan_context_t ctx, char *line)
|
||||
{
|
||||
@ -619,14 +628,16 @@ cmd_readkey (assuan_context_t ctx, char *line)
|
||||
The client should use this command to tell us the data he want to
|
||||
sign. */
|
||||
static int
|
||||
cmd_setdata (ASSUAN_CONTEXT ctx, char *line)
|
||||
cmd_setdata (assuan_context_t ctx, char *line)
|
||||
{
|
||||
CTRL ctrl = assuan_get_pointer (ctx);
|
||||
int n;
|
||||
char *p;
|
||||
unsigned char *buf;
|
||||
|
||||
/* parse the hexstring */
|
||||
/* FIXME: If we are locked return an error. */
|
||||
|
||||
/* Parse the hexstring. */
|
||||
for (p=line,n=0; hexdigitp (p); p++, n++)
|
||||
;
|
||||
if (*p)
|
||||
@ -652,7 +663,7 @@ cmd_setdata (ASSUAN_CONTEXT ctx, char *line)
|
||||
static int
|
||||
pin_cb (void *opaque, const char *info, char **retstr)
|
||||
{
|
||||
ASSUAN_CONTEXT ctx = opaque;
|
||||
assuan_context_t ctx = opaque;
|
||||
char *command;
|
||||
int rc;
|
||||
unsigned char *value;
|
||||
@ -687,7 +698,7 @@ pin_cb (void *opaque, const char *info, char **retstr)
|
||||
|
||||
*/
|
||||
static int
|
||||
cmd_pksign (ASSUAN_CONTEXT ctx, char *line)
|
||||
cmd_pksign (assuan_context_t ctx, char *line)
|
||||
{
|
||||
CTRL ctrl = assuan_get_pointer (ctx);
|
||||
int rc;
|
||||
@ -695,6 +706,8 @@ cmd_pksign (ASSUAN_CONTEXT ctx, char *line)
|
||||
size_t outdatalen;
|
||||
char *keyidstr;
|
||||
|
||||
/* FIXME: If we are locked return an error. */
|
||||
|
||||
if ((rc = open_card (ctrl, NULL)))
|
||||
return rc;
|
||||
|
||||
@ -738,7 +751,7 @@ cmd_pksign (ASSUAN_CONTEXT ctx, char *line)
|
||||
|
||||
*/
|
||||
static int
|
||||
cmd_pkauth (ASSUAN_CONTEXT ctx, char *line)
|
||||
cmd_pkauth (assuan_context_t ctx, char *line)
|
||||
{
|
||||
CTRL ctrl = assuan_get_pointer (ctx);
|
||||
int rc;
|
||||
@ -746,6 +759,8 @@ cmd_pkauth (ASSUAN_CONTEXT ctx, char *line)
|
||||
size_t outdatalen;
|
||||
char *keyidstr;
|
||||
|
||||
/* FIXME: If we are locked return an error. */
|
||||
|
||||
if ((rc = open_card (ctrl, NULL)))
|
||||
return rc;
|
||||
|
||||
@ -785,7 +800,7 @@ cmd_pkauth (ASSUAN_CONTEXT ctx, char *line)
|
||||
|
||||
*/
|
||||
static int
|
||||
cmd_pkdecrypt (ASSUAN_CONTEXT ctx, char *line)
|
||||
cmd_pkdecrypt (assuan_context_t ctx, char *line)
|
||||
{
|
||||
CTRL ctrl = assuan_get_pointer (ctx);
|
||||
int rc;
|
||||
@ -793,6 +808,8 @@ cmd_pkdecrypt (ASSUAN_CONTEXT ctx, char *line)
|
||||
size_t outdatalen;
|
||||
char *keyidstr;
|
||||
|
||||
/* FIXME: If we are locked return an error. */
|
||||
|
||||
if ((rc = open_card (ctrl, NULL)))
|
||||
return rc;
|
||||
|
||||
@ -834,14 +851,15 @@ cmd_pkdecrypt (ASSUAN_CONTEXT ctx, char *line)
|
||||
This command is used to retrieve data from a smartcard. The
|
||||
allowed names depend on the currently selected smartcard
|
||||
application. NAME must be percent and '+' escaped. The value is
|
||||
returned through status message, see the LESRN command for details.
|
||||
returned through status message, see the LEARN command for details.
|
||||
|
||||
However, the current implementation assumes that Name is not escaped;
|
||||
this works as long as noone uses arbitrary escaping.
|
||||
|
||||
Note, that this function may even be used on a locked card.
|
||||
*/
|
||||
static int
|
||||
cmd_getattr (ASSUAN_CONTEXT ctx, char *line)
|
||||
cmd_getattr (assuan_context_t ctx, char *line)
|
||||
{
|
||||
CTRL ctrl = assuan_get_pointer (ctx);
|
||||
int rc;
|
||||
@ -858,6 +876,8 @@ cmd_getattr (ASSUAN_CONTEXT ctx, char *line)
|
||||
|
||||
/* (We ignore any garbage for now.) */
|
||||
|
||||
/* FIXME: Applications should not return sensistive data if the card
|
||||
is locked. */
|
||||
rc = app_getattr (ctrl->app_ctx, ctrl, keyword);
|
||||
|
||||
TEST_CARD_REMOVAL (ctrl, rc);
|
||||
@ -878,7 +898,7 @@ cmd_getattr (ASSUAN_CONTEXT ctx, char *line)
|
||||
setattr function of the actually used application (app-*.c) for
|
||||
details. */
|
||||
static int
|
||||
cmd_setattr (ASSUAN_CONTEXT ctx, char *orig_line)
|
||||
cmd_setattr (assuan_context_t ctx, char *orig_line)
|
||||
{
|
||||
CTRL ctrl = assuan_get_pointer (ctx);
|
||||
int rc;
|
||||
@ -887,6 +907,8 @@ cmd_setattr (ASSUAN_CONTEXT ctx, char *orig_line)
|
||||
size_t nbytes;
|
||||
char *line, *linebuf;
|
||||
|
||||
/* FIXME: If we are locked return an error. */
|
||||
|
||||
if ((rc = open_card (ctrl, NULL)))
|
||||
return rc;
|
||||
|
||||
@ -932,13 +954,15 @@ cmd_setattr (ASSUAN_CONTEXT ctx, char *orig_line)
|
||||
|
||||
*/
|
||||
static int
|
||||
cmd_genkey (ASSUAN_CONTEXT ctx, char *line)
|
||||
cmd_genkey (assuan_context_t ctx, char *line)
|
||||
{
|
||||
CTRL ctrl = assuan_get_pointer (ctx);
|
||||
int rc;
|
||||
char *keyno;
|
||||
int force = has_option (line, "--force");
|
||||
|
||||
/* FIXME: If we are locked return an error. */
|
||||
|
||||
/* Skip over options. */
|
||||
while ( *line == '-' && line[1] == '-' )
|
||||
{
|
||||
@ -974,9 +998,11 @@ cmd_genkey (ASSUAN_CONTEXT ctx, char *line)
|
||||
/* RANDOM <nbytes>
|
||||
|
||||
Get NBYTES of random from the card and send them back as data.
|
||||
|
||||
Note, that this function may be even be used on a locked card.
|
||||
*/
|
||||
static int
|
||||
cmd_random (ASSUAN_CONTEXT ctx, char *line)
|
||||
cmd_random (assuan_context_t ctx, char *line)
|
||||
{
|
||||
CTRL ctrl = assuan_get_pointer (ctx);
|
||||
int rc;
|
||||
@ -1016,13 +1042,15 @@ cmd_random (ASSUAN_CONTEXT ctx, char *line)
|
||||
Change the PIN or reset thye retry counter of the card holder
|
||||
verfication vector CHVNO. */
|
||||
static int
|
||||
cmd_passwd (ASSUAN_CONTEXT ctx, char *line)
|
||||
cmd_passwd (assuan_context_t ctx, char *line)
|
||||
{
|
||||
CTRL ctrl = assuan_get_pointer (ctx);
|
||||
int rc;
|
||||
char *chvnostr;
|
||||
int reset_mode = has_option (line, "--reset");
|
||||
|
||||
/* FIXME: If we are locked return an error. */
|
||||
|
||||
/* Skip over options. */
|
||||
while (*line == '-' && line[1] == '-')
|
||||
{
|
||||
@ -1061,12 +1089,14 @@ cmd_passwd (ASSUAN_CONTEXT ctx, char *line)
|
||||
|
||||
*/
|
||||
static int
|
||||
cmd_checkpin (ASSUAN_CONTEXT ctx, char *line)
|
||||
cmd_checkpin (assuan_context_t ctx, char *line)
|
||||
{
|
||||
CTRL ctrl = assuan_get_pointer (ctx);
|
||||
int rc;
|
||||
char *keyidstr;
|
||||
|
||||
/* FIXME: If we are locked return an error. */
|
||||
|
||||
if ((rc = open_card (ctrl, NULL)))
|
||||
return rc;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user