mirror of
git://git.gnupg.org/gnupg.git
synced 2025-04-13 22:21:09 +02: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>
|
2005-03-29 Moritz Schulte <moritz@g10code.com>
|
||||||
|
|
||||||
* app-openpgp.c (retrieve_fpr_from_card): New function.
|
* app-openpgp.c (retrieve_fpr_from_card): New function.
|
||||||
@ -6,6 +14,19 @@
|
|||||||
(get_public_key): Implement retrival of key through expernal
|
(get_public_key): Implement retrival of key through expernal
|
||||||
helper (gpg) in case the openpgp card is not cooperative enough.
|
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>
|
2005-02-25 Werner Koch <wk@g10code.com>
|
||||||
|
|
||||||
* app-openpgp.c (get_public_key): Make sure not to return negative
|
* 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)
|
(reset_pcsc_reader, pcsc_get_status, pcsc_send_apdu)
|
||||||
(open_pcsc_reader): Do proper error code mapping.
|
(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>
|
2005-02-22 Werner Koch <wk@g10code.com>
|
||||||
|
|
||||||
* app-openpgp.c (app_local_s): New field PK.
|
* app-openpgp.c (app_local_s): New field PK.
|
||||||
|
@ -108,7 +108,14 @@ struct app_local_s {
|
|||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
int read_done; /* True if we have at least tried to read them. */
|
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];
|
} pk[3];
|
||||||
|
|
||||||
/* Keep track of card capabilities. */
|
/* Keep track of card capabilities. */
|
||||||
@ -156,7 +163,7 @@ do_deinit (app_t app)
|
|||||||
|
|
||||||
for (i=0; i < DIM (app->app_local->pk); i++)
|
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;
|
app->app_local->pk[i].read_done = 0;
|
||||||
}
|
}
|
||||||
xfree (app->app_local);
|
xfree (app->app_local);
|
||||||
@ -864,6 +871,10 @@ retrieve_key_material (FILE *fp, const char *fpr,
|
|||||||
mpi = NULL;
|
mpi = NULL;
|
||||||
ret = 0;
|
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)
|
while (1)
|
||||||
{
|
{
|
||||||
/* FIXME? */
|
/* FIXME? */
|
||||||
@ -1041,7 +1052,9 @@ retrieve_key_material (FILE *fp, const char *fpr,
|
|||||||
presence of the app->app_local->pk[KEYNO-1].key field.
|
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
|
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
|
#if GNUPG_MAJOR_VERSION > 1
|
||||||
static gpg_error_t
|
static gpg_error_t
|
||||||
get_public_key (app_t app, int keyno)
|
get_public_key (app_t app, int keyno)
|
||||||
@ -1050,9 +1063,10 @@ get_public_key (app_t app, int keyno)
|
|||||||
unsigned char *buffer;
|
unsigned char *buffer;
|
||||||
const unsigned char *keydata, *m, *e;
|
const unsigned char *keydata, *m, *e;
|
||||||
size_t buflen, keydatalen, mlen, elen;
|
size_t buflen, keydatalen, mlen, elen;
|
||||||
gcry_sexp_t sexp;
|
|
||||||
unsigned char *mbuf = NULL;
|
unsigned char *mbuf = NULL;
|
||||||
unsigned char *ebuf = NULL;
|
unsigned char *ebuf = NULL;
|
||||||
|
unsigned char *keybuf = NULL;
|
||||||
|
unsigned char *keybuf_p;
|
||||||
|
|
||||||
if (keyno < 1 || keyno > 3)
|
if (keyno < 1 || keyno > 3)
|
||||||
return gpg_error (GPG_ERR_INV_ID);
|
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)
|
if (app->app_local->pk[keyno].read_done)
|
||||||
return 0;
|
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].key = NULL;
|
||||||
|
app->app_local->pk[keyno].keylen = 0;
|
||||||
|
|
||||||
if (app->card_version > 0x0100)
|
if (app->card_version > 0x0100)
|
||||||
{
|
{
|
||||||
@ -1191,16 +1206,29 @@ get_public_key (app_t app, int keyno)
|
|||||||
buffer = NULL;
|
buffer = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
err = gcry_sexp_build (&sexp, NULL,
|
/* Allocate a buffer to construct the S-expression. */
|
||||||
"(public-key (rsa (n %b) (e %b)))",
|
/* FIXME: We should provide a generalized S-expression creation
|
||||||
(int)mlen, m,(int)elen, e);
|
mechanism. */
|
||||||
if (err)
|
keybuf = xtrymalloc (50 + 2*35 + mlen + elen + 1);
|
||||||
|
if (!keybuf)
|
||||||
{
|
{
|
||||||
log_error ("error formatting the key into an S-expression: %s\n",
|
err = gpg_error_from_errno (errno);
|
||||||
gpg_strerror (err));
|
|
||||||
goto leave;
|
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:
|
leave:
|
||||||
/* Set a flag to indicate that we tried to read the key. */
|
/* 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
|
/* 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. */
|
||||||
#if GNUPG_MAJOR_VERSION > 1
|
#if GNUPG_MAJOR_VERSION > 1
|
||||||
gcry_sexp_t sexp;
|
|
||||||
unsigned char grip[20];
|
unsigned char grip[20];
|
||||||
char gripstr[41];
|
char gripstr[41];
|
||||||
char idbuf[50];
|
char idbuf[50];
|
||||||
@ -1235,15 +1262,14 @@ send_keypair_info (app_t app, ctrl_t ctrl, int keyno)
|
|||||||
goto leave;
|
goto leave;
|
||||||
|
|
||||||
assert (keyno >= 1 && keyno <= 3);
|
assert (keyno >= 1 && keyno <= 3);
|
||||||
sexp = app->app_local->pk[keyno-1].key;
|
if (!app->app_local->pk[keyno-1].key)
|
||||||
if (!sexp)
|
goto leave; /* No such key - ignore. */
|
||||||
goto leave; /* No such key. */
|
|
||||||
|
|
||||||
if (!gcry_pk_get_keygrip (sexp, grip))
|
err = keygrip_from_canon_sexp (app->app_local->pk[keyno-1].key,
|
||||||
{
|
app->app_local->pk[keyno-1].keylen,
|
||||||
err = gpg_error (GPG_ERR_INTERNAL);
|
grip);
|
||||||
goto leave;
|
if (err)
|
||||||
}
|
goto leave;
|
||||||
|
|
||||||
for (i=0; i < 20; i++)
|
for (i=0; i < 20; i++)
|
||||||
sprintf (gripstr+i*2, "%02X", grip[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;
|
gpg_error_t err;
|
||||||
int keyno;
|
int keyno;
|
||||||
size_t n;
|
|
||||||
unsigned char *buf;
|
unsigned char *buf;
|
||||||
gcry_sexp_t sexp;
|
|
||||||
|
|
||||||
if (!strcmp (keyid, "OPENPGP.1"))
|
if (!strcmp (keyid, "OPENPGP.1"))
|
||||||
keyno = 1;
|
keyno = 1;
|
||||||
@ -1320,24 +1344,11 @@ do_readkey (app_t app, const char *keyid, unsigned char **pk, size_t *pklen)
|
|||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
sexp = app->app_local->pk[keyno-1].key;
|
buf = 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);
|
|
||||||
if (!buf)
|
if (!buf)
|
||||||
return gpg_error_from_errno (errno);
|
return gpg_error (GPG_ERR_NO_PUBKEY);
|
||||||
n = gcry_sexp_sprint (sexp, GCRYSEXP_FMT_CANON, buf, n);
|
|
||||||
if (!n)
|
|
||||||
{
|
|
||||||
xfree (buf);
|
|
||||||
return gpg_error (GPG_ERR_BUG);
|
|
||||||
}
|
|
||||||
*pk = buf;
|
*pk = buf;
|
||||||
*pklen = n;
|
*pklen = app->app_local->pk[keyno-1].keylen;;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1590,7 +1601,7 @@ do_change_pin (app_t app, ctrl_t ctrl, const char *chvnostr, int reset_mode,
|
|||||||
else
|
else
|
||||||
app->did_chv1 = app->did_chv2 = 0;
|
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
|
keep it at the start of the string. We need this elsewhere
|
||||||
to get some infos on the string. */
|
to get some infos on the string. */
|
||||||
rc = pincb (pincb_arg, chvno == 3? _("|AN|New Admin PIN") : _("|N|New PIN"),
|
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);
|
flush_cache (app);
|
||||||
|
|
||||||
/* Obviously we need to remove the cached public key. */
|
/* 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;
|
app->app_local->pk[keyno].read_done = 0;
|
||||||
|
|
||||||
/* Check whether a key already exists. */
|
/* 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
|
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
|
entry system, only the regular CHV will get blocked and not the
|
||||||
dangerous CHV3. KEYIDSTR is the usual card's serial number; an
|
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
|
static int
|
||||||
do_check_pin (app_t app, const char *keyidstr,
|
do_check_pin (app_t app, const char *keyidstr,
|
||||||
int (pincb)(void*, const char *, char **),
|
int (pincb)(void*, const char *, char **),
|
||||||
@ -2151,6 +2168,7 @@ do_check_pin (app_t app, const char *keyidstr,
|
|||||||
unsigned char tmp_sn[20];
|
unsigned char tmp_sn[20];
|
||||||
const char *s;
|
const char *s;
|
||||||
int n;
|
int n;
|
||||||
|
int admin_pin = 0;
|
||||||
|
|
||||||
if (!keyidstr || !*keyidstr)
|
if (!keyidstr || !*keyidstr)
|
||||||
return gpg_error (GPG_ERR_INV_VALUE);
|
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. */
|
; /* No fingerprint given: we allow this for now. */
|
||||||
else if (*s == '/')
|
else if (*s == '/')
|
||||||
; /* We ignore a fingerprint. */
|
; /* We ignore a fingerprint. */
|
||||||
|
else if (!strcmp (s, "[CHV3]") )
|
||||||
|
admin_pin = 1;
|
||||||
else
|
else
|
||||||
return gpg_error (GPG_ERR_INV_ID);
|
return gpg_error (GPG_ERR_INV_ID);
|
||||||
|
|
||||||
@ -2177,12 +2197,46 @@ do_check_pin (app_t app, const char *keyidstr,
|
|||||||
return gpg_error (GPG_ERR_INV_CARD);
|
return gpg_error (GPG_ERR_INV_CARD);
|
||||||
if (memcmp (app->serialno, tmp_sn, 16))
|
if (memcmp (app->serialno, tmp_sn, 16))
|
||||||
return gpg_error (GPG_ERR_WRONG_CARD);
|
return gpg_error (GPG_ERR_WRONG_CARD);
|
||||||
|
|
||||||
/* Yes, there is a race conditions: The user might pull the 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
|
right here and we won't notice that. However this is not a
|
||||||
problem and the check above is merely for a graceful failure
|
problem and the check above is merely for a graceful failure
|
||||||
between operations. */
|
between operations. */
|
||||||
|
|
||||||
return verify_chv2 (app, pincb, pincb_arg);
|
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);
|
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;
|
app->app_local->pk[keyno].read_done = 0;
|
||||||
|
|
||||||
rc = iso7816_put_data (app->slot,
|
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
|
/* 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. */
|
operations. Its use is highly application dependent. */
|
||||||
int
|
int
|
||||||
app_check_pin (APP app, const char *keyidstr,
|
app_check_pin (APP app, const char *keyidstr,
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* ccid-driver.c - USB ChipCardInterfaceDevices driver
|
/* 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.
|
* Written by Werner Koch.
|
||||||
*
|
*
|
||||||
* This file is part of GnuPG.
|
* This file is part of GnuPG.
|
||||||
@ -52,7 +52,7 @@
|
|||||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
* 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);
|
int use_crc);
|
||||||
static int bulk_out (ccid_driver_t handle, unsigned char *msg, size_t msglen);
|
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,
|
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
|
/* Convert a little endian stored 4 byte value into an unsigned
|
||||||
integer. */
|
integer. */
|
||||||
@ -446,12 +446,20 @@ parse_ccid_descriptor (ccid_driver_t handle,
|
|||||||
send a frame of n*wMaxPacketSize back to us. Given that
|
send a frame of n*wMaxPacketSize back to us. Given that
|
||||||
wMaxPacketSize is 64 for these readers we set the IFSD to a value
|
wMaxPacketSize is 64 for these readers we set the IFSD to a value
|
||||||
lower than that:
|
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
|
if (handle->id_vendor == VENDOR_SCM
|
||||||
/* FIXME: check whether it is the same
|
&& handle->max_ifsd > 48
|
||||||
firmware version for all drivers. */
|
&& ( (handle->id_product == 0xe001 && handle->bcd_device < 0x0516)
|
||||||
&& handle->bcd_device < 0x0519
|
||(handle->id_product == 0x5111 && handle->bcd_device < 0x0620)
|
||||||
&& handle->max_ifsd > 48)
|
||(handle->id_product == 0x5115 && handle->bcd_device < 0x0519)
|
||||||
|
||(handle->id_product == 0xe003 && handle->bcd_device < 0x0504)
|
||||||
|
))
|
||||||
{
|
{
|
||||||
DEBUGOUT ("enabling workaround for buggy SCM readers\n");
|
DEBUGOUT ("enabling workaround for buggy SCM readers\n");
|
||||||
handle->max_ifsd = 48;
|
handle->max_ifsd = 48;
|
||||||
@ -699,9 +707,7 @@ scan_or_find_devices (int readerno, const char *readerid,
|
|||||||
&& ifcdesc->bInterfaceProtocol == 0)
|
&& ifcdesc->bInterfaceProtocol == 0)
|
||||||
|| (ifcdesc->bInterfaceClass == 255
|
|| (ifcdesc->bInterfaceClass == 255
|
||||||
&& dev->descriptor.idVendor == 0x04e6
|
&& dev->descriptor.idVendor == 0x04e6
|
||||||
&& dev->descriptor.idProduct == 0xe003
|
&& dev->descriptor.idProduct == 0xe003)))
|
||||||
&& ifcdesc->bInterfaceSubClass == 1
|
|
||||||
&& ifcdesc->bInterfaceProtocol == 1)))
|
|
||||||
{
|
{
|
||||||
idev = usb_open (dev);
|
idev = usb_open (dev);
|
||||||
if (!idev)
|
if (!idev)
|
||||||
@ -974,11 +980,13 @@ do_close_reader (ccid_driver_t handle)
|
|||||||
|
|
||||||
rc = bulk_out (handle, msg, msglen);
|
rc = bulk_out (handle, msg, msglen);
|
||||||
if (!rc)
|
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;
|
handle->powered_off = 1;
|
||||||
}
|
}
|
||||||
if (handle->idev)
|
if (handle->idev)
|
||||||
{
|
{
|
||||||
|
usb_reset (handle->idev);
|
||||||
usb_release_interface (handle->idev, handle->ifc_no);
|
usb_release_interface (handle->idev, handle->ifc_no);
|
||||||
usb_close (handle->idev);
|
usb_close (handle->idev);
|
||||||
handle->idev = NULL;
|
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
|
BUFFER and return the actual read number if bytes in NREAD. SEQNO
|
||||||
is the sequence number used to send the request and EXPECTED_TYPE
|
is the sequence number used to send the request and EXPECTED_TYPE
|
||||||
the type of message we expect. Does checks on the ccid
|
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
|
static int
|
||||||
bulk_in (ccid_driver_t handle, unsigned char *buffer, size_t length,
|
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;
|
int i, rc;
|
||||||
size_t msglen;
|
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,
|
rc = usb_bulk_read (handle->idev,
|
||||||
handle->ep_bulk_in,
|
handle->ep_bulk_in,
|
||||||
buffer, length,
|
buffer, length,
|
||||||
10000 /* ms timeout */ );
|
timeout);
|
||||||
/* Fixme: instead of using a 10 second timeout we should better
|
|
||||||
handle the timeout here and retry if appropriate. */
|
|
||||||
if (rc < 0)
|
if (rc < 0)
|
||||||
{
|
{
|
||||||
DEBUGOUT_1 ("usb_bulk_read error: %s\n", strerror (errno));
|
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 */
|
CARD_INACTIVE */
|
||||||
static int
|
static int
|
||||||
send_escape_cmd (ccid_driver_t handle,
|
send_escape_cmd (ccid_driver_t handle,
|
||||||
@ -1206,7 +1212,8 @@ send_escape_cmd (ccid_driver_t handle,
|
|||||||
rc = bulk_out (handle, msg, msglen);
|
rc = bulk_out (handle, msg, msglen);
|
||||||
if (rc)
|
if (rc)
|
||||||
return 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;
|
return rc;
|
||||||
}
|
}
|
||||||
@ -1276,7 +1283,9 @@ ccid_slot_status (ccid_driver_t handle, int *statusbits)
|
|||||||
unsigned char msg[100];
|
unsigned char msg[100];
|
||||||
size_t msglen;
|
size_t msglen;
|
||||||
unsigned char seqno;
|
unsigned char seqno;
|
||||||
|
int retries = 0;
|
||||||
|
|
||||||
|
retry:
|
||||||
msg[0] = PC_to_RDR_GetSlotStatus;
|
msg[0] = PC_to_RDR_GetSlotStatus;
|
||||||
msg[5] = 0; /* slot */
|
msg[5] = 0; /* slot */
|
||||||
msg[6] = seqno = handle->seqno++;
|
msg[6] = seqno = handle->seqno++;
|
||||||
@ -1288,7 +1297,21 @@ ccid_slot_status (ccid_driver_t handle, int *statusbits)
|
|||||||
rc = bulk_out (handle, msg, 10);
|
rc = bulk_out (handle, msg, 10);
|
||||||
if (rc)
|
if (rc)
|
||||||
return 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
|
if (rc && rc != CCID_DRIVER_ERR_NO_CARD
|
||||||
&& rc != CCID_DRIVER_ERR_CARD_INACTIVE)
|
&& rc != CCID_DRIVER_ERR_CARD_INACTIVE)
|
||||||
return rc;
|
return rc;
|
||||||
@ -1303,6 +1326,7 @@ ccid_get_atr (ccid_driver_t handle,
|
|||||||
unsigned char *atr, size_t maxatrlen, size_t *atrlen)
|
unsigned char *atr, size_t maxatrlen, size_t *atrlen)
|
||||||
{
|
{
|
||||||
int rc;
|
int rc;
|
||||||
|
int statusbits;
|
||||||
unsigned char msg[100];
|
unsigned char msg[100];
|
||||||
unsigned char *tpdu;
|
unsigned char *tpdu;
|
||||||
size_t msglen, tpdulen;
|
size_t msglen, tpdulen;
|
||||||
@ -1311,6 +1335,15 @@ ccid_get_atr (ccid_driver_t handle,
|
|||||||
unsigned int edc;
|
unsigned int edc;
|
||||||
int i;
|
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[0] = PC_to_RDR_IccPowerOn;
|
||||||
msg[5] = 0; /* slot */
|
msg[5] = 0; /* slot */
|
||||||
msg[6] = seqno = handle->seqno++;
|
msg[6] = seqno = handle->seqno++;
|
||||||
@ -1323,7 +1356,8 @@ ccid_get_atr (ccid_driver_t handle,
|
|||||||
rc = bulk_out (handle, msg, msglen);
|
rc = bulk_out (handle, msg, msglen);
|
||||||
if (rc)
|
if (rc)
|
||||||
return 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)
|
if (rc)
|
||||||
return rc;
|
return rc;
|
||||||
|
|
||||||
@ -1367,7 +1401,8 @@ ccid_get_atr (ccid_driver_t handle,
|
|||||||
if (rc)
|
if (rc)
|
||||||
return rc;
|
return rc;
|
||||||
/* Note that we ignore the error code on purpose. */
|
/* 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_ns = 0;
|
||||||
handle->t1_nr = 0;
|
handle->t1_nr = 0;
|
||||||
@ -1414,7 +1449,7 @@ ccid_get_atr (ccid_driver_t handle,
|
|||||||
|
|
||||||
|
|
||||||
rc = bulk_in (handle, msg, sizeof msg, &msglen,
|
rc = bulk_in (handle, msg, sizeof msg, &msglen,
|
||||||
RDR_to_PC_DataBlock, seqno);
|
RDR_to_PC_DataBlock, seqno, 5000);
|
||||||
if (rc)
|
if (rc)
|
||||||
return rc;
|
return rc;
|
||||||
|
|
||||||
@ -1510,7 +1545,7 @@ ccid_transceive_apdu_level (ccid_driver_t handle,
|
|||||||
|
|
||||||
msg = recv_buffer;
|
msg = recv_buffer;
|
||||||
rc = bulk_in (handle, msg, sizeof recv_buffer, &msglen,
|
rc = bulk_in (handle, msg, sizeof recv_buffer, &msglen,
|
||||||
RDR_to_PC_DataBlock, seqno);
|
RDR_to_PC_DataBlock, seqno, 5000);
|
||||||
if (rc)
|
if (rc)
|
||||||
return rc;
|
return rc;
|
||||||
|
|
||||||
@ -1683,7 +1718,7 @@ ccid_transceive (ccid_driver_t handle,
|
|||||||
|
|
||||||
msg = recv_buffer;
|
msg = recv_buffer;
|
||||||
rc = bulk_in (handle, msg, sizeof recv_buffer, &msglen,
|
rc = bulk_in (handle, msg, sizeof recv_buffer, &msglen,
|
||||||
RDR_to_PC_DataBlock, seqno);
|
RDR_to_PC_DataBlock, seqno, 5000);
|
||||||
if (rc)
|
if (rc)
|
||||||
return rc;
|
return rc;
|
||||||
|
|
||||||
@ -1692,7 +1727,7 @@ ccid_transceive (ccid_driver_t handle,
|
|||||||
|
|
||||||
if (tpdulen < 4)
|
if (tpdulen < 4)
|
||||||
{
|
{
|
||||||
usb_clear_halt (handle->idev, 0x82);
|
usb_clear_halt (handle->idev, handle->ep_bulk_in);
|
||||||
return CCID_DRIVER_ERR_ABORTED;
|
return CCID_DRIVER_ERR_ABORTED;
|
||||||
}
|
}
|
||||||
#ifdef DEBUG_T1
|
#ifdef DEBUG_T1
|
||||||
@ -1960,7 +1995,7 @@ ccid_transceive_secure (ccid_driver_t handle,
|
|||||||
|
|
||||||
msg = recv_buffer;
|
msg = recv_buffer;
|
||||||
rc = bulk_in (handle, msg, sizeof recv_buffer, &msglen,
|
rc = bulk_in (handle, msg, sizeof recv_buffer, &msglen,
|
||||||
RDR_to_PC_DataBlock, seqno);
|
RDR_to_PC_DataBlock, seqno, 5000);
|
||||||
if (rc)
|
if (rc)
|
||||||
return rc;
|
return rc;
|
||||||
|
|
||||||
|
@ -108,7 +108,7 @@ do_reset (ctrl_t ctrl, int do_close)
|
|||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
reset_notify (ASSUAN_CONTEXT ctx)
|
reset_notify (assuan_context_t ctx)
|
||||||
{
|
{
|
||||||
CTRL ctrl = assuan_get_pointer (ctx);
|
CTRL ctrl = assuan_get_pointer (ctx);
|
||||||
|
|
||||||
@ -117,7 +117,7 @@ reset_notify (ASSUAN_CONTEXT ctx)
|
|||||||
|
|
||||||
|
|
||||||
static int
|
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);
|
ctrl_t ctrl = assuan_get_pointer (ctx);
|
||||||
|
|
||||||
@ -248,6 +248,10 @@ cmd_serialno (assuan_context_t ctx, char *line)
|
|||||||
time_t stamp;
|
time_t stamp;
|
||||||
|
|
||||||
/* Clear the remove flag so that the open_card is able to reread it. */
|
/* 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)
|
if (ctrl->server_local->card_removed)
|
||||||
do_reset (ctrl, 0);
|
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.
|
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
|
static int
|
||||||
cmd_learn (ASSUAN_CONTEXT ctx, char *line)
|
cmd_learn (assuan_context_t ctx, char *line)
|
||||||
{
|
{
|
||||||
CTRL ctrl = assuan_get_pointer (ctx);
|
CTRL ctrl = assuan_get_pointer (ctx);
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
@ -481,9 +486,10 @@ cmd_learn (ASSUAN_CONTEXT ctx, char *line)
|
|||||||
|
|
||||||
/* READCERT <hexified_certid>
|
/* READCERT <hexified_certid>
|
||||||
|
|
||||||
|
Note, that this function may be even be used on a locked card.
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
cmd_readcert (ASSUAN_CONTEXT ctx, char *line)
|
cmd_readcert (assuan_context_t ctx, char *line)
|
||||||
{
|
{
|
||||||
CTRL ctrl = assuan_get_pointer (ctx);
|
CTRL ctrl = assuan_get_pointer (ctx);
|
||||||
int rc;
|
int rc;
|
||||||
@ -524,7 +530,10 @@ cmd_readcert (ASSUAN_CONTEXT ctx, char *line)
|
|||||||
/* READKEY <hexified_certid>
|
/* READKEY <hexified_certid>
|
||||||
|
|
||||||
Return the public key for the given cert or key ID as an standard
|
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
|
static int
|
||||||
cmd_readkey (assuan_context_t ctx, char *line)
|
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
|
The client should use this command to tell us the data he want to
|
||||||
sign. */
|
sign. */
|
||||||
static int
|
static int
|
||||||
cmd_setdata (ASSUAN_CONTEXT ctx, char *line)
|
cmd_setdata (assuan_context_t ctx, char *line)
|
||||||
{
|
{
|
||||||
CTRL ctrl = assuan_get_pointer (ctx);
|
CTRL ctrl = assuan_get_pointer (ctx);
|
||||||
int n;
|
int n;
|
||||||
char *p;
|
char *p;
|
||||||
unsigned char *buf;
|
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++)
|
for (p=line,n=0; hexdigitp (p); p++, n++)
|
||||||
;
|
;
|
||||||
if (*p)
|
if (*p)
|
||||||
@ -652,7 +663,7 @@ cmd_setdata (ASSUAN_CONTEXT ctx, char *line)
|
|||||||
static int
|
static int
|
||||||
pin_cb (void *opaque, const char *info, char **retstr)
|
pin_cb (void *opaque, const char *info, char **retstr)
|
||||||
{
|
{
|
||||||
ASSUAN_CONTEXT ctx = opaque;
|
assuan_context_t ctx = opaque;
|
||||||
char *command;
|
char *command;
|
||||||
int rc;
|
int rc;
|
||||||
unsigned char *value;
|
unsigned char *value;
|
||||||
@ -687,7 +698,7 @@ pin_cb (void *opaque, const char *info, char **retstr)
|
|||||||
|
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
cmd_pksign (ASSUAN_CONTEXT ctx, char *line)
|
cmd_pksign (assuan_context_t ctx, char *line)
|
||||||
{
|
{
|
||||||
CTRL ctrl = assuan_get_pointer (ctx);
|
CTRL ctrl = assuan_get_pointer (ctx);
|
||||||
int rc;
|
int rc;
|
||||||
@ -695,6 +706,8 @@ cmd_pksign (ASSUAN_CONTEXT ctx, char *line)
|
|||||||
size_t outdatalen;
|
size_t outdatalen;
|
||||||
char *keyidstr;
|
char *keyidstr;
|
||||||
|
|
||||||
|
/* FIXME: If we are locked return an error. */
|
||||||
|
|
||||||
if ((rc = open_card (ctrl, NULL)))
|
if ((rc = open_card (ctrl, NULL)))
|
||||||
return rc;
|
return rc;
|
||||||
|
|
||||||
@ -738,7 +751,7 @@ cmd_pksign (ASSUAN_CONTEXT ctx, char *line)
|
|||||||
|
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
cmd_pkauth (ASSUAN_CONTEXT ctx, char *line)
|
cmd_pkauth (assuan_context_t ctx, char *line)
|
||||||
{
|
{
|
||||||
CTRL ctrl = assuan_get_pointer (ctx);
|
CTRL ctrl = assuan_get_pointer (ctx);
|
||||||
int rc;
|
int rc;
|
||||||
@ -746,6 +759,8 @@ cmd_pkauth (ASSUAN_CONTEXT ctx, char *line)
|
|||||||
size_t outdatalen;
|
size_t outdatalen;
|
||||||
char *keyidstr;
|
char *keyidstr;
|
||||||
|
|
||||||
|
/* FIXME: If we are locked return an error. */
|
||||||
|
|
||||||
if ((rc = open_card (ctrl, NULL)))
|
if ((rc = open_card (ctrl, NULL)))
|
||||||
return rc;
|
return rc;
|
||||||
|
|
||||||
@ -785,7 +800,7 @@ cmd_pkauth (ASSUAN_CONTEXT ctx, char *line)
|
|||||||
|
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
cmd_pkdecrypt (ASSUAN_CONTEXT ctx, char *line)
|
cmd_pkdecrypt (assuan_context_t ctx, char *line)
|
||||||
{
|
{
|
||||||
CTRL ctrl = assuan_get_pointer (ctx);
|
CTRL ctrl = assuan_get_pointer (ctx);
|
||||||
int rc;
|
int rc;
|
||||||
@ -793,6 +808,8 @@ cmd_pkdecrypt (ASSUAN_CONTEXT ctx, char *line)
|
|||||||
size_t outdatalen;
|
size_t outdatalen;
|
||||||
char *keyidstr;
|
char *keyidstr;
|
||||||
|
|
||||||
|
/* FIXME: If we are locked return an error. */
|
||||||
|
|
||||||
if ((rc = open_card (ctrl, NULL)))
|
if ((rc = open_card (ctrl, NULL)))
|
||||||
return rc;
|
return rc;
|
||||||
|
|
||||||
@ -834,14 +851,15 @@ cmd_pkdecrypt (ASSUAN_CONTEXT ctx, char *line)
|
|||||||
This command is used to retrieve data from a smartcard. The
|
This command is used to retrieve data from a smartcard. The
|
||||||
allowed names depend on the currently selected smartcard
|
allowed names depend on the currently selected smartcard
|
||||||
application. NAME must be percent and '+' escaped. The value is
|
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;
|
However, the current implementation assumes that Name is not escaped;
|
||||||
this works as long as noone uses arbitrary escaping.
|
this works as long as noone uses arbitrary escaping.
|
||||||
|
|
||||||
|
Note, that this function may even be used on a locked card.
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
cmd_getattr (ASSUAN_CONTEXT ctx, char *line)
|
cmd_getattr (assuan_context_t ctx, char *line)
|
||||||
{
|
{
|
||||||
CTRL ctrl = assuan_get_pointer (ctx);
|
CTRL ctrl = assuan_get_pointer (ctx);
|
||||||
int rc;
|
int rc;
|
||||||
@ -858,6 +876,8 @@ cmd_getattr (ASSUAN_CONTEXT ctx, char *line)
|
|||||||
|
|
||||||
/* (We ignore any garbage for now.) */
|
/* (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);
|
rc = app_getattr (ctrl->app_ctx, ctrl, keyword);
|
||||||
|
|
||||||
TEST_CARD_REMOVAL (ctrl, rc);
|
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
|
setattr function of the actually used application (app-*.c) for
|
||||||
details. */
|
details. */
|
||||||
static int
|
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);
|
CTRL ctrl = assuan_get_pointer (ctx);
|
||||||
int rc;
|
int rc;
|
||||||
@ -887,6 +907,8 @@ cmd_setattr (ASSUAN_CONTEXT ctx, char *orig_line)
|
|||||||
size_t nbytes;
|
size_t nbytes;
|
||||||
char *line, *linebuf;
|
char *line, *linebuf;
|
||||||
|
|
||||||
|
/* FIXME: If we are locked return an error. */
|
||||||
|
|
||||||
if ((rc = open_card (ctrl, NULL)))
|
if ((rc = open_card (ctrl, NULL)))
|
||||||
return rc;
|
return rc;
|
||||||
|
|
||||||
@ -932,13 +954,15 @@ cmd_setattr (ASSUAN_CONTEXT ctx, char *orig_line)
|
|||||||
|
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
cmd_genkey (ASSUAN_CONTEXT ctx, char *line)
|
cmd_genkey (assuan_context_t ctx, char *line)
|
||||||
{
|
{
|
||||||
CTRL ctrl = assuan_get_pointer (ctx);
|
CTRL ctrl = assuan_get_pointer (ctx);
|
||||||
int rc;
|
int rc;
|
||||||
char *keyno;
|
char *keyno;
|
||||||
int force = has_option (line, "--force");
|
int force = has_option (line, "--force");
|
||||||
|
|
||||||
|
/* FIXME: If we are locked return an error. */
|
||||||
|
|
||||||
/* Skip over options. */
|
/* Skip over options. */
|
||||||
while ( *line == '-' && line[1] == '-' )
|
while ( *line == '-' && line[1] == '-' )
|
||||||
{
|
{
|
||||||
@ -974,9 +998,11 @@ cmd_genkey (ASSUAN_CONTEXT ctx, char *line)
|
|||||||
/* RANDOM <nbytes>
|
/* RANDOM <nbytes>
|
||||||
|
|
||||||
Get NBYTES of random from the card and send them back as data.
|
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
|
static int
|
||||||
cmd_random (ASSUAN_CONTEXT ctx, char *line)
|
cmd_random (assuan_context_t ctx, char *line)
|
||||||
{
|
{
|
||||||
CTRL ctrl = assuan_get_pointer (ctx);
|
CTRL ctrl = assuan_get_pointer (ctx);
|
||||||
int rc;
|
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
|
Change the PIN or reset thye retry counter of the card holder
|
||||||
verfication vector CHVNO. */
|
verfication vector CHVNO. */
|
||||||
static int
|
static int
|
||||||
cmd_passwd (ASSUAN_CONTEXT ctx, char *line)
|
cmd_passwd (assuan_context_t ctx, char *line)
|
||||||
{
|
{
|
||||||
CTRL ctrl = assuan_get_pointer (ctx);
|
CTRL ctrl = assuan_get_pointer (ctx);
|
||||||
int rc;
|
int rc;
|
||||||
char *chvnostr;
|
char *chvnostr;
|
||||||
int reset_mode = has_option (line, "--reset");
|
int reset_mode = has_option (line, "--reset");
|
||||||
|
|
||||||
|
/* FIXME: If we are locked return an error. */
|
||||||
|
|
||||||
/* Skip over options. */
|
/* Skip over options. */
|
||||||
while (*line == '-' && line[1] == '-')
|
while (*line == '-' && line[1] == '-')
|
||||||
{
|
{
|
||||||
@ -1061,12 +1089,14 @@ cmd_passwd (ASSUAN_CONTEXT ctx, char *line)
|
|||||||
|
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
cmd_checkpin (ASSUAN_CONTEXT ctx, char *line)
|
cmd_checkpin (assuan_context_t ctx, char *line)
|
||||||
{
|
{
|
||||||
CTRL ctrl = assuan_get_pointer (ctx);
|
CTRL ctrl = assuan_get_pointer (ctx);
|
||||||
int rc;
|
int rc;
|
||||||
char *keyidstr;
|
char *keyidstr;
|
||||||
|
|
||||||
|
/* FIXME: If we are locked return an error. */
|
||||||
|
|
||||||
if ((rc = open_card (ctrl, NULL)))
|
if ((rc = open_card (ctrl, NULL)))
|
||||||
return rc;
|
return rc;
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user