Updated card stuff to support T=0 cards.

This commit is contained in:
Werner Koch 2005-09-07 17:05:42 +00:00
parent 9a2a2904cc
commit b4b9f891e2
9 changed files with 394 additions and 459 deletions

2
README
View File

@ -307,7 +307,7 @@
certify that they know the owner of the keys they sign. If you then
trust all the introducers to have correctly signed other keys, you
can be be sure that the other key really belongs to the one who
claims to own it..
claims to own it.
There are 2 steps to validate a key:
1. First check that there is a complete chain

View File

@ -782,7 +782,7 @@ The format of this file is as follows:
Handle: <string>
This is an optional parameter only used with the status lines
KEY_CREATED and KEY_NOT_CREATED. STRING may be up to 100
characters and should not contauin spaces. It is useful for
characters and should not contain spaces. It is useful for
batch key generation to associate a key parameter block with a
status line.

View File

@ -1,5 +1,20 @@
2005-09-07 Werner Koch <wk@g10code.com>
* cardglue.h (GPG_ERR_TOO_LARGE): New.
* apdu.c, apdu.h, iso7816.c, iso7816.h
* ccid-driver.c, ccid-driver.h: Updated from GnuPG 1.9 source.
Changes are:
* iso7816.c (iso7816_select_path): New.
* iso7816.c (iso7816_read_binary): Use Le=0 when reading all
data. Handle 6C00 error and take 6B00 as indication for EOF.
* apdu.h (SW_EXACT_LENGTH_P): New.
* apdu.c (new_reader_slot, reset_pcsc_reader, pcsc_get_status)
(open_pcsc_reader): Set new reader state IS_T0.
(apdu_send_le): When doing T=0 make sure not to send Lc and Le.
Problem reported by Carl Meijer.
(apdu_send_direct): Initialize RESULTLEN.
* misc.c (parse_options): Allow meta option "help" to list all
options and to exit the program.

File diff suppressed because it is too large Load Diff

View File

@ -42,6 +42,7 @@ enum {
SW_RECORD_NOT_FOUND = 0x6a83,
SW_REF_NOT_FOUND = 0x6a88,
SW_BAD_P0_P1 = 0x6b00,
SW_EXACT_LENGTH = 0x6c00,
SW_INS_NOT_SUP = 0x6d00,
SW_CLA_NOT_SUP = 0x6e00,
SW_SUCCESS = 0x9000,
@ -66,6 +67,8 @@ enum {
};
#define SW_EXACT_LENGTH_P(a) (((a)&~0xff) == SW_EXACT_LENGTH)
/* Note , that apdu_open_reader returns no status word but -1 on error. */
int apdu_open_reader (const char *portstr);

View File

@ -112,6 +112,7 @@ typedef struct ctrl_ctx_s *ctrl_t;
#define GPG_ERR_UNKNOWN_SEXP G10ERR_INV_ARG
#define GPG_ERR_DUP_VALUE G10ERR_INV_ARG
#define GPG_ERR_BAD_SECKEY G10ERR_BAD_SECKEY
#define GPG_ERR_TOO_LARGE G10ERR_GENERAL
#define GPG_ERR_EBUSY G10ERR_GENERAL
#define GPG_ERR_ENOENT G10ERR_OPEN_FILE

View File

@ -556,7 +556,7 @@ get_escaped_usb_string (usb_dev_handle *idev, int idx,
all in a 2 bute Unicode encoding using little endian. */
rc = usb_control_msg (idev, USB_ENDPOINT_IN, USB_REQ_GET_DESCRIPTOR,
(USB_DT_STRING << 8), 0,
buf, sizeof buf, 1000 /* ms timeout */);
(char*)buf, sizeof buf, 1000 /* ms timeout */);
if (rc < 4)
langid = 0x0409; /* English. */
else
@ -564,7 +564,7 @@ get_escaped_usb_string (usb_dev_handle *idev, int idx,
rc = usb_control_msg (idev, USB_ENDPOINT_IN, USB_REQ_GET_DESCRIPTOR,
(USB_DT_STRING << 8) + idx, langid,
buf, sizeof buf, 1000 /* ms timeout */);
(char*)buf, sizeof buf, 1000 /* ms timeout */);
if (rc < 2 || buf[1] != USB_DT_STRING)
return NULL; /* Error or not a string. */
len = buf[0];
@ -1156,7 +1156,7 @@ bulk_out (ccid_driver_t handle, unsigned char *msg, size_t msglen)
rc = usb_bulk_write (handle->idev,
handle->ep_bulk_out,
msg, msglen,
(char*)msg, msglen,
1000 /* ms timeout */);
if (rc == msglen)
return 0;
@ -1189,7 +1189,7 @@ bulk_in (ccid_driver_t handle, unsigned char *buffer, size_t length,
retry:
rc = usb_bulk_read (handle->idev,
handle->ep_bulk_in,
buffer, length,
(char*)buffer, length,
timeout);
if (rc < 0)
{
@ -1301,7 +1301,7 @@ ccid_poll (ccid_driver_t handle)
rc = usb_bulk_read (handle->idev,
handle->ep_intr,
msg, sizeof msg,
(char*)msg, sizeof msg,
0 /* ms timeout */ );
if (rc < 0 && errno == ETIMEDOUT)
return 0;
@ -1445,7 +1445,7 @@ ccid_get_atr (ccid_driver_t handle,
{
tried_iso = 1;
/* Try switching to ISO mode. */
if (!send_escape_cmd (handle, "\xF1\x01", 2))
if (!send_escape_cmd (handle, (const unsigned char*)"\xF1\x01", 2))
goto again;
}
else if (CCID_COMMAND_FAILED (msg))
@ -2027,7 +2027,7 @@ ccid_transceive_secure (ccid_driver_t handle,
if (handle->id_vendor == VENDOR_SCM)
{
DEBUGOUT ("sending escape sequence to switch to a case 1 APDU\n");
rc = send_escape_cmd (handle, "\x80\x02\x00", 3);
rc = send_escape_cmd (handle, (const unsigned char*)"\x80\x02\x00", 3);
if (rc)
return rc;
}

View File

@ -78,6 +78,7 @@ map_sw (int sw)
case SW_RECORD_NOT_FOUND:ec= GPG_ERR_NOT_FOUND; break;
case SW_REF_NOT_FOUND: ec = GPG_ERR_NO_OBJ; break;
case SW_BAD_P0_P1: ec = GPG_ERR_INV_VALUE; break;
case SW_EXACT_LENGTH: ec = GPG_ERR_INV_VALUE; break;
case SW_INS_NOT_SUP: ec = GPG_ERR_CARD; break;
case SW_CLA_NOT_SUP: ec = GPG_ERR_CARD; break;
case SW_SUCCESS: ec = 0; break;
@ -154,7 +155,7 @@ iso7816_select_file (int slot, int tag, int is_dir,
p0 = (tag == 0x3F00)? 0: is_dir? 1:2;
p1 = 0x0c; /* No FC return. */
sw = apdu_send_simple (slot, 0x00, CMD_SELECT_FILE,
p0, p1, 2, tagbuf );
p0, p1, 2, (char*)tagbuf );
return map_sw (sw);
}
@ -162,6 +163,39 @@ iso7816_select_file (int slot, int tag, int is_dir,
}
/* Do a select file command with a direct path. */
gpg_error_t
iso7816_select_path (int slot, const unsigned short *path, size_t pathlen,
unsigned char **result, size_t *resultlen)
{
int sw, p0, p1;
unsigned char buffer[100];
int buflen;
if (result || resultlen)
{
*result = NULL;
*resultlen = 0;
return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
}
if (pathlen/2 >= sizeof buffer)
return gpg_error (GPG_ERR_TOO_LARGE);
for (buflen = 0; pathlen; pathlen--, path++)
{
buffer[buflen++] = (*path >> 8);
buffer[buflen++] = *path;
}
p0 = 0x08;
p1 = 0x0c; /* No FC return. */
sw = apdu_send_simple (slot, 0x00, CMD_SELECT_FILE,
p0, p1, buflen, (char*)buffer );
return map_sw (sw);
}
/* This is a private command currently only working for TCOS cards. */
gpg_error_t
iso7816_list_directory (int slot, int list_dirs,
@ -286,7 +320,7 @@ iso7816_put_data (int slot, int tag,
sw = apdu_send_simple (slot, 0x00, CMD_PUT_DATA,
((tag >> 8) & 0xff), (tag & 0xff),
datalen, data);
datalen, (const char*)data);
return map_sw (sw);
}
@ -300,10 +334,11 @@ iso7816_manage_security_env (int slot, int p1, int p2,
{
int sw;
if (p1 < 0 || p1 > 255 || p2 < 0 || p2 > 255 || !data || !datalen)
if (p1 < 0 || p1 > 255 || p2 < 0 || p2 > 255 )
return gpg_error (GPG_ERR_INV_VALUE);
sw = apdu_send_simple (slot, 0x00, CMD_MSE, p1, p2, datalen, data);
sw = apdu_send_simple (slot, 0x00, CMD_MSE, p1, p2,
data? datalen : -1, (const char*)data);
return map_sw (sw);
}
@ -323,7 +358,7 @@ iso7816_compute_ds (int slot, const unsigned char *data, size_t datalen,
*result = NULL;
*resultlen = 0;
sw = apdu_send (slot, 0x00, CMD_PSO, 0x9E, 0x9A, datalen, data,
sw = apdu_send (slot, 0x00, CMD_PSO, 0x9E, 0x9A, datalen, (const char*)data,
result, resultlen);
if (sw != SW_SUCCESS)
{
@ -364,13 +399,15 @@ iso7816_decipher (int slot, const unsigned char *data, size_t datalen,
*buf = padind; /* Padding indicator. */
memcpy (buf+1, data, datalen);
sw = apdu_send (slot, 0x00, CMD_PSO, 0x80, 0x86, datalen+1, buf,
sw = apdu_send (slot, 0x00, CMD_PSO, 0x80, 0x86,
datalen+1, (char*)buf,
result, resultlen);
xfree (buf);
}
else
{
sw = apdu_send (slot, 0x00, CMD_PSO, 0x80, 0x86, datalen, data,
sw = apdu_send (slot, 0x00, CMD_PSO, 0x80, 0x86,
datalen, (const char *)data,
result, resultlen);
}
if (sw != SW_SUCCESS)
@ -399,7 +436,7 @@ iso7816_internal_authenticate (int slot,
*resultlen = 0;
sw = apdu_send (slot, 0x00, CMD_INTERNAL_AUTHENTICATE, 0, 0,
datalen, data, result, resultlen);
datalen, (const char*)data, result, resultlen);
if (sw != SW_SUCCESS)
{
/* Make sure that pending buffers are released. */
@ -426,7 +463,7 @@ do_generate_keypair (int slot, int readonly,
*resultlen = 0;
sw = apdu_send (slot, 0x00, CMD_GENERATE_KEYPAIR, readonly? 0x81:0x80, 0,
datalen, data, result, resultlen);
datalen, (const char*)data, result, resultlen);
if (sw != SW_SUCCESS)
{
/* Make sure that pending buffers are released. */
@ -522,8 +559,10 @@ iso7816_read_binary (int slot, size_t offset, size_t nmax,
{
buffer = NULL;
bufferlen = 0;
/* Fixme: Either the ccid driver or the TCOS cards have problems
with an Le of 0. */
/* Note, that we to set N to 254 due to problems either with the
ccid driver or some TCOS cards. It actually should be 0
which is the official ISO value to read a variable length
object. */
if (read_all || nmax > 254)
n = 254;
else
@ -531,6 +570,21 @@ iso7816_read_binary (int slot, size_t offset, size_t nmax,
sw = apdu_send_le (slot, 0x00, CMD_READ_BINARY,
((offset>>8) & 0xff), (offset & 0xff) , -1, NULL,
n, &buffer, &bufferlen);
if ( SW_EXACT_LENGTH_P(sw) )
{
n = (sw & 0x00ff);
sw = apdu_send_le (slot, 0x00, CMD_READ_BINARY,
((offset>>8) & 0xff), (offset & 0xff) , -1, NULL,
n, &buffer, &bufferlen);
}
if (*result && sw == SW_BAD_P0_P1)
{
/* Bad Parameter means that the offset is outside of the
EF. When reading all data we take this as an indication
for EOF. */
break;
}
if (sw != SW_SUCCESS && sw != SW_EOF_REACHED)
{
@ -606,7 +660,7 @@ iso7816_read_record (int slot, int recno, int reccount, int short_ef,
buffer = NULL;
bufferlen = 0;
/* Fixme: Either the ccid driver of the TCOS cards have problems
/* Fixme: Either the ccid driver or the TCOS cards have problems
with an Le of 0. */
sw = apdu_send_le (slot, 0x00, CMD_READ_RECORD,
recno,

View File

@ -34,6 +34,9 @@ gpg_error_t iso7816_select_application (int slot,
const char *aid, size_t aidlen);
gpg_error_t iso7816_select_file (int slot, int tag, int is_dir,
unsigned char **result, size_t *resultlen);
gpg_error_t iso7816_select_path (int slot,
const unsigned short *path, size_t pathlen,
unsigned char **result, size_t *resultlen);
gpg_error_t iso7816_list_directory (int slot, int list_dirs,
unsigned char **result, size_t *resultlen);
gpg_error_t iso7816_verify (int slot,