* 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:
Werner Koch 2005-04-11 16:20:10 +00:00
parent 45eba6e5de
commit 6b002f0602
5 changed files with 241 additions and 90 deletions

View File

@ -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.

View File

@ -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);
goto leave;
}
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,12 +2197,46 @@ 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. */
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);
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,

View File

@ -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,

View File

@ -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;

View File

@ -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;