mirror of
git://git.gnupg.org/gnupg.git
synced 2025-01-18 14:17:03 +01:00
Updated card stuff to support T=0 cards.
This commit is contained in:
parent
9a2a2904cc
commit
b4b9f891e2
2
README
2
README
@ -307,7 +307,7 @@
|
|||||||
certify that they know the owner of the keys they sign. If you then
|
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
|
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
|
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:
|
There are 2 steps to validate a key:
|
||||||
1. First check that there is a complete chain
|
1. First check that there is a complete chain
|
||||||
|
@ -782,7 +782,7 @@ The format of this file is as follows:
|
|||||||
Handle: <string>
|
Handle: <string>
|
||||||
This is an optional parameter only used with the status lines
|
This is an optional parameter only used with the status lines
|
||||||
KEY_CREATED and KEY_NOT_CREATED. STRING may be up to 100
|
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
|
batch key generation to associate a key parameter block with a
|
||||||
status line.
|
status line.
|
||||||
|
|
||||||
|
@ -1,5 +1,20 @@
|
|||||||
2005-09-07 Werner Koch <wk@g10code.com>
|
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
|
* misc.c (parse_options): Allow meta option "help" to list all
|
||||||
options and to exit the program.
|
options and to exit the program.
|
||||||
|
|
||||||
|
735
g10/apdu.c
735
g10/apdu.c
File diff suppressed because it is too large
Load Diff
@ -42,6 +42,7 @@ enum {
|
|||||||
SW_RECORD_NOT_FOUND = 0x6a83,
|
SW_RECORD_NOT_FOUND = 0x6a83,
|
||||||
SW_REF_NOT_FOUND = 0x6a88,
|
SW_REF_NOT_FOUND = 0x6a88,
|
||||||
SW_BAD_P0_P1 = 0x6b00,
|
SW_BAD_P0_P1 = 0x6b00,
|
||||||
|
SW_EXACT_LENGTH = 0x6c00,
|
||||||
SW_INS_NOT_SUP = 0x6d00,
|
SW_INS_NOT_SUP = 0x6d00,
|
||||||
SW_CLA_NOT_SUP = 0x6e00,
|
SW_CLA_NOT_SUP = 0x6e00,
|
||||||
SW_SUCCESS = 0x9000,
|
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. */
|
/* Note , that apdu_open_reader returns no status word but -1 on error. */
|
||||||
int apdu_open_reader (const char *portstr);
|
int apdu_open_reader (const char *portstr);
|
||||||
|
@ -112,6 +112,7 @@ typedef struct ctrl_ctx_s *ctrl_t;
|
|||||||
#define GPG_ERR_UNKNOWN_SEXP G10ERR_INV_ARG
|
#define GPG_ERR_UNKNOWN_SEXP G10ERR_INV_ARG
|
||||||
#define GPG_ERR_DUP_VALUE G10ERR_INV_ARG
|
#define GPG_ERR_DUP_VALUE G10ERR_INV_ARG
|
||||||
#define GPG_ERR_BAD_SECKEY G10ERR_BAD_SECKEY
|
#define GPG_ERR_BAD_SECKEY G10ERR_BAD_SECKEY
|
||||||
|
#define GPG_ERR_TOO_LARGE G10ERR_GENERAL
|
||||||
|
|
||||||
#define GPG_ERR_EBUSY G10ERR_GENERAL
|
#define GPG_ERR_EBUSY G10ERR_GENERAL
|
||||||
#define GPG_ERR_ENOENT G10ERR_OPEN_FILE
|
#define GPG_ERR_ENOENT G10ERR_OPEN_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. */
|
all in a 2 bute Unicode encoding using little endian. */
|
||||||
rc = usb_control_msg (idev, USB_ENDPOINT_IN, USB_REQ_GET_DESCRIPTOR,
|
rc = usb_control_msg (idev, USB_ENDPOINT_IN, USB_REQ_GET_DESCRIPTOR,
|
||||||
(USB_DT_STRING << 8), 0,
|
(USB_DT_STRING << 8), 0,
|
||||||
buf, sizeof buf, 1000 /* ms timeout */);
|
(char*)buf, sizeof buf, 1000 /* ms timeout */);
|
||||||
if (rc < 4)
|
if (rc < 4)
|
||||||
langid = 0x0409; /* English. */
|
langid = 0x0409; /* English. */
|
||||||
else
|
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,
|
rc = usb_control_msg (idev, USB_ENDPOINT_IN, USB_REQ_GET_DESCRIPTOR,
|
||||||
(USB_DT_STRING << 8) + idx, langid,
|
(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)
|
if (rc < 2 || buf[1] != USB_DT_STRING)
|
||||||
return NULL; /* Error or not a string. */
|
return NULL; /* Error or not a string. */
|
||||||
len = buf[0];
|
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,
|
rc = usb_bulk_write (handle->idev,
|
||||||
handle->ep_bulk_out,
|
handle->ep_bulk_out,
|
||||||
msg, msglen,
|
(char*)msg, msglen,
|
||||||
1000 /* ms timeout */);
|
1000 /* ms timeout */);
|
||||||
if (rc == msglen)
|
if (rc == msglen)
|
||||||
return 0;
|
return 0;
|
||||||
@ -1189,7 +1189,7 @@ bulk_in (ccid_driver_t handle, unsigned char *buffer, size_t length,
|
|||||||
retry:
|
retry:
|
||||||
rc = usb_bulk_read (handle->idev,
|
rc = usb_bulk_read (handle->idev,
|
||||||
handle->ep_bulk_in,
|
handle->ep_bulk_in,
|
||||||
buffer, length,
|
(char*)buffer, length,
|
||||||
timeout);
|
timeout);
|
||||||
if (rc < 0)
|
if (rc < 0)
|
||||||
{
|
{
|
||||||
@ -1301,7 +1301,7 @@ ccid_poll (ccid_driver_t handle)
|
|||||||
|
|
||||||
rc = usb_bulk_read (handle->idev,
|
rc = usb_bulk_read (handle->idev,
|
||||||
handle->ep_intr,
|
handle->ep_intr,
|
||||||
msg, sizeof msg,
|
(char*)msg, sizeof msg,
|
||||||
0 /* ms timeout */ );
|
0 /* ms timeout */ );
|
||||||
if (rc < 0 && errno == ETIMEDOUT)
|
if (rc < 0 && errno == ETIMEDOUT)
|
||||||
return 0;
|
return 0;
|
||||||
@ -1445,7 +1445,7 @@ ccid_get_atr (ccid_driver_t handle,
|
|||||||
{
|
{
|
||||||
tried_iso = 1;
|
tried_iso = 1;
|
||||||
/* Try switching to ISO mode. */
|
/* 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;
|
goto again;
|
||||||
}
|
}
|
||||||
else if (CCID_COMMAND_FAILED (msg))
|
else if (CCID_COMMAND_FAILED (msg))
|
||||||
@ -2027,7 +2027,7 @@ ccid_transceive_secure (ccid_driver_t handle,
|
|||||||
if (handle->id_vendor == VENDOR_SCM)
|
if (handle->id_vendor == VENDOR_SCM)
|
||||||
{
|
{
|
||||||
DEBUGOUT ("sending escape sequence to switch to a case 1 APDU\n");
|
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)
|
if (rc)
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
@ -78,6 +78,7 @@ map_sw (int sw)
|
|||||||
case SW_RECORD_NOT_FOUND:ec= GPG_ERR_NOT_FOUND; break;
|
case SW_RECORD_NOT_FOUND:ec= GPG_ERR_NOT_FOUND; break;
|
||||||
case SW_REF_NOT_FOUND: ec = GPG_ERR_NO_OBJ; 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_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_INS_NOT_SUP: ec = GPG_ERR_CARD; break;
|
||||||
case SW_CLA_NOT_SUP: ec = GPG_ERR_CARD; break;
|
case SW_CLA_NOT_SUP: ec = GPG_ERR_CARD; break;
|
||||||
case SW_SUCCESS: ec = 0; 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;
|
p0 = (tag == 0x3F00)? 0: is_dir? 1:2;
|
||||||
p1 = 0x0c; /* No FC return. */
|
p1 = 0x0c; /* No FC return. */
|
||||||
sw = apdu_send_simple (slot, 0x00, CMD_SELECT_FILE,
|
sw = apdu_send_simple (slot, 0x00, CMD_SELECT_FILE,
|
||||||
p0, p1, 2, tagbuf );
|
p0, p1, 2, (char*)tagbuf );
|
||||||
return map_sw (sw);
|
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. */
|
/* This is a private command currently only working for TCOS cards. */
|
||||||
gpg_error_t
|
gpg_error_t
|
||||||
iso7816_list_directory (int slot, int list_dirs,
|
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,
|
sw = apdu_send_simple (slot, 0x00, CMD_PUT_DATA,
|
||||||
((tag >> 8) & 0xff), (tag & 0xff),
|
((tag >> 8) & 0xff), (tag & 0xff),
|
||||||
datalen, data);
|
datalen, (const char*)data);
|
||||||
return map_sw (sw);
|
return map_sw (sw);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -300,10 +334,11 @@ iso7816_manage_security_env (int slot, int p1, int p2,
|
|||||||
{
|
{
|
||||||
int sw;
|
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);
|
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);
|
return map_sw (sw);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -323,7 +358,7 @@ iso7816_compute_ds (int slot, const unsigned char *data, size_t datalen,
|
|||||||
*result = NULL;
|
*result = NULL;
|
||||||
*resultlen = 0;
|
*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);
|
result, resultlen);
|
||||||
if (sw != SW_SUCCESS)
|
if (sw != SW_SUCCESS)
|
||||||
{
|
{
|
||||||
@ -364,13 +399,15 @@ iso7816_decipher (int slot, const unsigned char *data, size_t datalen,
|
|||||||
|
|
||||||
*buf = padind; /* Padding indicator. */
|
*buf = padind; /* Padding indicator. */
|
||||||
memcpy (buf+1, data, datalen);
|
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);
|
result, resultlen);
|
||||||
xfree (buf);
|
xfree (buf);
|
||||||
}
|
}
|
||||||
else
|
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);
|
result, resultlen);
|
||||||
}
|
}
|
||||||
if (sw != SW_SUCCESS)
|
if (sw != SW_SUCCESS)
|
||||||
@ -399,7 +436,7 @@ iso7816_internal_authenticate (int slot,
|
|||||||
*resultlen = 0;
|
*resultlen = 0;
|
||||||
|
|
||||||
sw = apdu_send (slot, 0x00, CMD_INTERNAL_AUTHENTICATE, 0, 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)
|
if (sw != SW_SUCCESS)
|
||||||
{
|
{
|
||||||
/* Make sure that pending buffers are released. */
|
/* Make sure that pending buffers are released. */
|
||||||
@ -426,7 +463,7 @@ do_generate_keypair (int slot, int readonly,
|
|||||||
*resultlen = 0;
|
*resultlen = 0;
|
||||||
|
|
||||||
sw = apdu_send (slot, 0x00, CMD_GENERATE_KEYPAIR, readonly? 0x81:0x80, 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)
|
if (sw != SW_SUCCESS)
|
||||||
{
|
{
|
||||||
/* Make sure that pending buffers are released. */
|
/* Make sure that pending buffers are released. */
|
||||||
@ -522,8 +559,10 @@ iso7816_read_binary (int slot, size_t offset, size_t nmax,
|
|||||||
{
|
{
|
||||||
buffer = NULL;
|
buffer = NULL;
|
||||||
bufferlen = 0;
|
bufferlen = 0;
|
||||||
/* Fixme: Either the ccid driver or the TCOS cards have problems
|
/* Note, that we to set N to 254 due to problems either with the
|
||||||
with an Le of 0. */
|
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)
|
if (read_all || nmax > 254)
|
||||||
n = 254;
|
n = 254;
|
||||||
else
|
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,
|
sw = apdu_send_le (slot, 0x00, CMD_READ_BINARY,
|
||||||
((offset>>8) & 0xff), (offset & 0xff) , -1, NULL,
|
((offset>>8) & 0xff), (offset & 0xff) , -1, NULL,
|
||||||
n, &buffer, &bufferlen);
|
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)
|
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;
|
buffer = NULL;
|
||||||
bufferlen = 0;
|
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. */
|
with an Le of 0. */
|
||||||
sw = apdu_send_le (slot, 0x00, CMD_READ_RECORD,
|
sw = apdu_send_le (slot, 0x00, CMD_READ_RECORD,
|
||||||
recno,
|
recno,
|
||||||
|
@ -34,6 +34,9 @@ gpg_error_t iso7816_select_application (int slot,
|
|||||||
const char *aid, size_t aidlen);
|
const char *aid, size_t aidlen);
|
||||||
gpg_error_t iso7816_select_file (int slot, int tag, int is_dir,
|
gpg_error_t iso7816_select_file (int slot, int tag, int is_dir,
|
||||||
unsigned char **result, size_t *resultlen);
|
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,
|
gpg_error_t iso7816_list_directory (int slot, int list_dirs,
|
||||||
unsigned char **result, size_t *resultlen);
|
unsigned char **result, size_t *resultlen);
|
||||||
gpg_error_t iso7816_verify (int slot,
|
gpg_error_t iso7816_verify (int slot,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user