1
0
Fork 0
mirror of git://git.gnupg.org/gnupg.git synced 2025-07-03 22:56:33 +02:00

scd: One new and one improved 7816 function.

* scd/apdu.c (apdu_send_direct): New arg R_SW.
* scd/command.c (cmd_apdu): Ditto.
* scd/iso7816.c (iso7816_apdu_direct): New arg R_SW.
(iso7816_general_authenticate): New.
* scd/app-nks.c (get_chv_status, get_nks_version): Pass NULL for new
arg.
--

iso7816_general_authenticate will be used for the PIV card support.
The new arg to iso7816_apdu_direct and apdu_send_direct allows to get
the raw status word back without the need to handle an output buffer.

Signed-off-by: Werner Koch <wk@gnupg.org>
This commit is contained in:
Werner Koch 2019-01-20 11:41:23 +01:00
parent d93797c8a7
commit 70bb5c7931
No known key found for this signature in database
GPG key ID: E3FDFF218E45B72B
6 changed files with 90 additions and 27 deletions

View file

@ -50,6 +50,7 @@
#define CMD_PUT_DATA 0xDA
#define CMD_MSE 0x22
#define CMD_PSO 0x2A
#define CMD_GENERAL_AUTHENTICATE 0x87
#define CMD_INTERNAL_AUTHENTICATE 0x88
#define CMD_GENERATE_KEYPAIR 0x47
#define CMD_GET_CHALLENGE 0x84
@ -225,24 +226,28 @@ iso7816_list_directory (int slot, int list_dirs,
internally. The return value is a gpg error code (i.e. a mapped
status word). This is basically the same as apdu_send_direct but
it maps the status word and does not return it in the result
buffer. */
buffer. However, it R_SW is not NULL the status word is stored
R_SW for closer inspection. */
gpg_error_t
iso7816_apdu_direct (int slot, const void *apdudata, size_t apdudatalen,
int handle_more,
int handle_more, unsigned int *r_sw,
unsigned char **result, size_t *resultlen)
{
int sw;
int sw, sw2;
if (!result || !resultlen)
return gpg_error (GPG_ERR_INV_VALUE);
*result = NULL;
*resultlen = 0;
if (result)
{
*result = NULL;
*resultlen = 0;
}
sw = apdu_send_direct (slot, 0, apdudata, apdudatalen, handle_more,
result, resultlen);
&sw2, result, resultlen);
if (!sw)
{
if (*resultlen < 2)
if (!result)
sw = sw2;
else if (*resultlen < 2)
sw = SW_HOST_GENERAL_ERROR;
else
{
@ -251,13 +256,15 @@ iso7816_apdu_direct (int slot, const void *apdudata, size_t apdudatalen,
(*resultlen)--;
}
}
if (sw != SW_SUCCESS)
if (sw != SW_SUCCESS && result)
{
/* Make sure that pending buffers are released. */
xfree (*result);
*result = NULL;
*resultlen = 0;
}
if (r_sw)
*r_sw = sw;
return map_sw (sw);
}
@ -621,7 +628,7 @@ iso7816_decipher (int slot, int extended_mode,
}
/* For LE see do_generate_keypair. */
/* For LE see do_generate_keypair. */
gpg_error_t
iso7816_internal_authenticate (int slot, int extended_mode,
const unsigned char *data, size_t datalen,
@ -658,6 +665,44 @@ iso7816_internal_authenticate (int slot, int extended_mode,
}
/* For LE see do_generate_keypair. */
gpg_error_t
iso7816_general_authenticate (int slot, int extended_mode,
int algoref, int keyref,
const unsigned char *data, size_t datalen,
int le,
unsigned char **result, size_t *resultlen)
{
int sw;
if (!data || !datalen || !result || !resultlen)
return gpg_error (GPG_ERR_INV_VALUE);
*result = NULL;
*resultlen = 0;
if (!extended_mode)
le = 256; /* Ignore provided Le and use what apdu_send uses. */
else if (le >= 0 && le < 256)
le = 256;
sw = apdu_send_le (slot, extended_mode,
0x00, CMD_GENERAL_AUTHENTICATE, algoref, keyref,
datalen, (const char*)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;
}
/* LE is the expected return length. This is usually 0 except if
extended length mode is used and more than 256 byte will be
returned. In that case a value of -1 uses a large default