scd: Add two variants to the set of ISO7816 functions.

* scd/iso7816.c (iso7816_select_application_ext): New.
(iso7816_get_data_odd): New.

Signed-off-by: Werner Koch <wk@gnupg.org>
This commit is contained in:
Werner Koch 2019-01-03 15:18:15 +01:00
parent cca2b87e79
commit 405feca2bd
No known key found for this signature in database
GPG Key ID: E3FDFF218E45B72B
2 changed files with 86 additions and 0 deletions

View File

@ -138,6 +138,21 @@ iso7816_select_application (int slot, const char *aid, size_t aidlen,
}
/* This is the same as iso7816_select_application but may return data
* at RESULT,RESULTLEN). */
gpg_error_t
iso7816_select_application_ext (int slot, const char *aid, size_t aidlen,
unsigned int flags,
unsigned char **result, size_t *resultlen)
{
int sw;
sw = apdu_send (slot, 0, 0x00, CMD_SELECT_FILE, 4,
(flags&1)? 0:0x0c, aidlen, aid,
result, resultlen);
return map_sw (sw);
}
gpg_error_t
iso7816_select_file (int slot, int tag, int is_dir)
{
@ -396,6 +411,70 @@ iso7816_get_data (int slot, int extended_mode, int tag,
}
/* Perform a GET DATA command requesting TAG and storing the result in
* a newly allocated buffer at the address passed by RESULT. Return
* the length of this data at the address of RESULTLEN. This variant
* is needed for long (3 octet) tags. */
gpg_error_t
iso7816_get_data_odd (int slot, int extended_mode, unsigned int tag,
unsigned char **result, size_t *resultlen)
{
int sw;
int le;
int datalen;
unsigned char data[5];
if (!result || !resultlen)
return gpg_error (GPG_ERR_INV_VALUE);
*result = NULL;
*resultlen = 0;
if (extended_mode > 0 && extended_mode < 256)
le = 65534; /* Not 65535 in case it is used as some special flag. */
else if (extended_mode > 0)
le = extended_mode;
else
le = 256;
data[0] = 0x5c;
if (tag <= 0xff)
{
data[1] = 1;
data[2] = tag;
datalen = 3;
}
else if (tag <= 0xffff)
{
data[1] = 2;
data[2] = (tag >> 8);
data[3] = tag;
datalen = 4;
}
else
{
data[1] = 3;
data[2] = (tag >> 16);
data[3] = (tag >> 8);
data[4] = tag;
datalen = 5;
}
sw = apdu_send_le (slot, extended_mode, 0x00, CMD_GET_DATA + 1,
0x3f, 0xff, datalen, data, le,
result, resultlen);
if (sw != SW_SUCCESS)
{
/* Make sure that pending buffers are released. */
xfree (*result);
*result = NULL;
*resultlen = 0;
return map_sw (sw);
}
return 0;
}
/* Perform a PUT DATA command on card in SLOT. Write DATA of length
DATALEN to TAG. EXTENDED_MODE controls whether extended length
headers or command chaining is used instead of single length

View File

@ -51,6 +51,11 @@ gpg_error_t iso7816_map_sw (int sw);
gpg_error_t iso7816_select_application (int slot,
const char *aid, size_t aidlen,
unsigned int flags);
gpg_error_t iso7816_select_application_ext (int slot,
const char *aid, size_t aidlen,
unsigned int flags,
unsigned char **result,
size_t *resultlen);
gpg_error_t iso7816_select_file (int slot, int tag, int is_dir);
gpg_error_t iso7816_select_path (int slot,
const unsigned short *path, size_t pathlen);
@ -78,6 +83,8 @@ gpg_error_t iso7816_reset_retry_counter_with_rc (int slot, int chvno,
size_t datalen);
gpg_error_t iso7816_get_data (int slot, int extended_mode, int tag,
unsigned char **result, size_t *resultlen);
gpg_error_t iso7816_get_data_odd (int slot, int extended_mode, unsigned int tag,
unsigned char **result, size_t *resultlen);
gpg_error_t iso7816_put_data (int slot, int extended_mode, int tag,
const void *data, size_t datalen);
gpg_error_t iso7816_put_data_odd (int slot, int extended_mode, int tag,