mirror of
git://git.gnupg.org/gnupg.git
synced 2025-01-03 12:11:33 +01: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:
parent
d93797c8a7
commit
70bb5c7931
30
scd/apdu.c
30
scd/apdu.c
@ -3063,19 +3063,25 @@ apdu_send_simple (int slot, int extended_mode,
|
||||
|
||||
|
||||
/* This is a more generic version of the apdu sending routine. It
|
||||
takes an already formatted APDU in APDUDATA or length APDUDATALEN
|
||||
and returns with an APDU including the status word. With
|
||||
HANDLE_MORE set to true this function will handle the MORE DATA
|
||||
status and return all APDUs concatenated with one status word at
|
||||
the end. If EXTENDED_LENGTH is != 0 extended lengths are allowed
|
||||
with a max. result data length of EXTENDED_LENGTH bytes. The
|
||||
function does not return a regular status word but 0 on success.
|
||||
If the slot is locked, the function returns immediately with an
|
||||
error. */
|
||||
* takes an already formatted APDU in APDUDATA or length APDUDATALEN
|
||||
* and returns with an APDU including the status word. With
|
||||
* HANDLE_MORE set to true this function will handle the MORE DATA
|
||||
* status and return all APDUs concatenated with one status word at
|
||||
* the end. If EXTENDED_LENGTH is != 0 extended lengths are allowed
|
||||
* with a max. result data length of EXTENDED_LENGTH bytes. The
|
||||
* function does not return a regular status word but 0 on success.
|
||||
* If the slot is locked, the function returns immediately with an
|
||||
* error.
|
||||
*
|
||||
* Out of historical reasons the function returns 0 on success and
|
||||
* outs the status word at the end of the result to be able to get the
|
||||
* status word in the case of a not provided RETBUF, R_SW can be used
|
||||
* to store the SW. But note that R_SW qill only be set if the
|
||||
* function returns 0. */
|
||||
int
|
||||
apdu_send_direct (int slot, size_t extended_length,
|
||||
const unsigned char *apdudata, size_t apdudatalen,
|
||||
int handle_more,
|
||||
int handle_more, unsigned int *r_sw,
|
||||
unsigned char **retbuf, size_t *retbuflen)
|
||||
{
|
||||
#define SHORT_RESULT_BUFFER_SIZE 258
|
||||
@ -3282,9 +3288,13 @@ apdu_send_direct (int slot, size_t extended_length,
|
||||
(*retbuf)[(*retbuflen)++] = sw;
|
||||
}
|
||||
|
||||
if (r_sw)
|
||||
*r_sw = sw;
|
||||
|
||||
if (DBG_CARD_IO && retbuf)
|
||||
log_printhex (*retbuf, *retbuflen, " dump: ");
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -138,7 +138,7 @@ int apdu_send_le (int slot, int extended_mode,
|
||||
unsigned char **retbuf, size_t *retbuflen);
|
||||
int apdu_send_direct (int slot, size_t extended_length,
|
||||
const unsigned char *apdudata, size_t apdudatalen,
|
||||
int handle_more,
|
||||
int handle_more, unsigned int *r_sw,
|
||||
unsigned char **retbuf, size_t *retbuflen);
|
||||
const char *apdu_get_reader_name (int slot);
|
||||
|
||||
|
@ -273,7 +273,7 @@ get_chv_status (app_t app, int sigg, int pwid)
|
||||
command[3] = pwid;
|
||||
|
||||
if (apdu_send_direct (app->slot, 0, (unsigned char *)command,
|
||||
4, 0, &result, &resultlen))
|
||||
4, 0, NULL, &result, &resultlen))
|
||||
rc = -1; /* Error. */
|
||||
else if (resultlen < 2)
|
||||
rc = -1; /* Error. */
|
||||
@ -1300,7 +1300,7 @@ get_nks_version (int slot)
|
||||
int type;
|
||||
|
||||
if (iso7816_apdu_direct (slot, "\x80\xaa\x06\x00\x00", 5, 0,
|
||||
&result, &resultlen))
|
||||
NULL, &result, &resultlen))
|
||||
return 2; /* NKS 2 does not support this command. */
|
||||
|
||||
/* Example value: 04 11 19 22 21 6A 20 80 03 03 01 01 01 00 00 00
|
||||
|
@ -333,7 +333,7 @@ static const char hlp_learn[] =
|
||||
"or a \"CANCEL\" to force the function to terminate with a Cancel\n"
|
||||
"error message.\n"
|
||||
"\n"
|
||||
"With the option --keypairinfo only KEYPARIINFO lstatus lines are\n"
|
||||
"With the option --keypairinfo only KEYPARIINFO status lines are\n"
|
||||
"returned.\n"
|
||||
"\n"
|
||||
"The response of this command is a list of status lines formatted as\n"
|
||||
@ -346,6 +346,7 @@ static const char hlp_learn[] =
|
||||
" P15 = PKCS-15 structure used\n"
|
||||
" DINSIG = DIN SIG\n"
|
||||
" OPENPGP = OpenPGP card\n"
|
||||
" PIV = PIV card\n"
|
||||
" NKS = NetKey card\n"
|
||||
"\n"
|
||||
"are implemented. These strings are aliases for the AID\n"
|
||||
@ -1663,7 +1664,7 @@ cmd_apdu (assuan_context_t ctx, char *line)
|
||||
|
||||
rc = apdu_send_direct (app->slot, exlen,
|
||||
apdu, apdulen, handle_more,
|
||||
&result, &resultlen);
|
||||
NULL, &result, &resultlen);
|
||||
if (rc)
|
||||
log_error ("apdu_send_direct failed: %s\n", gpg_strerror (rc));
|
||||
else
|
||||
|
@ -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
|
||||
|
@ -63,7 +63,7 @@ gpg_error_t iso7816_list_directory (int slot, int list_dirs,
|
||||
unsigned char **result, size_t *resultlen);
|
||||
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);
|
||||
gpg_error_t iso7816_check_pinpad (int slot, int command,
|
||||
pininfo_t *pininfo);
|
||||
@ -104,6 +104,13 @@ gpg_error_t iso7816_internal_authenticate (int slot, int extended_mode,
|
||||
const unsigned char *data, size_t datalen,
|
||||
int le,
|
||||
unsigned char **result, size_t *resultlen);
|
||||
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);
|
||||
gpg_error_t iso7816_generate_keypair (int slot, int extended_mode,
|
||||
const char *data, size_t datalen,
|
||||
int le,
|
||||
|
Loading…
x
Reference in New Issue
Block a user