1
0
mirror of git://git.gnupg.org/gnupg.git synced 2024-06-14 00:19:50 +02:00

Added command APDU

This commit is contained in:
Werner Koch 2006-04-11 13:53:21 +00:00
parent 76cb368202
commit c664309a0a
6 changed files with 189 additions and 4 deletions

View File

@ -347,6 +347,8 @@ syncronizing access to a token between sessions.
* Scdaemon RANDOM:: Return random bytes generate on-card. * Scdaemon RANDOM:: Return random bytes generate on-card.
* Scdaemon PASSWD:: Change PINs. * Scdaemon PASSWD:: Change PINs.
* Scdaemon CHECKPIN:: Perform a VERIFY operation. * Scdaemon CHECKPIN:: Perform a VERIFY operation.
* Scdaemon RESTART:: Restart connection
* Scdaemon APDU:: Send a verbatim APDU to the card
@end menu @end menu
@node Scdaemon SERIALNO @node Scdaemon SERIALNO
@ -553,3 +555,47 @@ and only if the retry counter is still at 3.
@end table @end table
@node Scdaemon RESTART
@subsection Perform a RESTART operation.
@example
RESTART
@end example
Restart the current connection; this is a kind of warm reset. It
deletes the context used by this connection but does not actually
reset the card.
This is used by gpg-agent to reuse a primary pipe connection and
may be used by clients to backup from a conflict in the serial
command; i.e. to select another application.
@node Scdaemon APDU
@subsection Send a verbatim APDU to the card.
@example
APDU [--atr] [--more] [@var{hexstring}]
@end example
Send an APDU to the current reader. This command bypasses the high
level functions and sends the data directly to the card.
@var{hexstring} is expected to be a proper APDU. If @var{hexstring} is
not given no commands are send to the card; However the command will
implictly check whether the card is ready for use.
Using the option @code{--atr} returns the ATR of the card as a status
message before any data like this:
@example
S CARD-ATR 3BFA1300FF813180450031C173C00100009000B1
@end example
Using the option @code{--more} handles the card status word MORE_DATA
(61xx) and concatenate all reponses to one block.

View File

@ -1,3 +1,12 @@
2006-04-11 Werner Koch <wk@g10code.com>
* command.c (hex_to_buffer): New.
(cmd_apdu): New.
2006-04-03 Werner Koch <wk@g10code.com>
* scdaemon.c [__GLIBC__]: Default to libpcsclite.so.1.
2006-03-21 Werner Koch <wk@g10code.com> 2006-03-21 Werner Koch <wk@g10code.com>
* command.c (cmd_pksign): Add --hash option. * command.c (cmd_pksign): Add --hash option.

View File

@ -2848,8 +2848,8 @@ apdu_send_simple_kp (int slot, int class, int ins, int p0, int p1,
HANDLE_MORE set to true this function will handle the MORE DATA HANDLE_MORE set to true this function will handle the MORE DATA
status and return all APDUs concatenated with one status word at status and return all APDUs concatenated with one status word at
the end. The function does not return a regular status word but 0 the end. The function does not return a regular status word but 0
on success. If the slot is locked, the fucntion returns on success. If the slot is locked, the function returns
immediately.*/ immediately with an error. */
int int
apdu_send_direct (int slot, const unsigned char *apdudata, size_t apdudatalen, apdu_send_direct (int slot, const unsigned char *apdudata, size_t apdudatalen,
int handle_more, int handle_more,

View File

@ -112,8 +112,8 @@ struct app_local_s {
encoded S-expression encoding a public encoded S-expression encoding a public
key. Might be NULL if key is not key. Might be NULL if key is not
available. */ available. */
size_t keylen; /* The length of the above S-expression. Thsi size_t keylen; /* The length of the above S-expression. This
is usullay only required for corss checks is usullay only required for cross checks
because the length of an S-expression is because the length of an S-expression is
implicitly available. */ implicitly available. */
} pk[3]; } pk[3];

View File

@ -156,6 +156,38 @@ has_option (const char *line, const char *name)
} }
/* Convert the STRING into a newly allocated buffer while translating
the hex numbers. Stops at the first invalid character. Blanks and
colons are allowed to separate the hex digits. Returns NULL on
error or a newly malloced buffer and its length in LENGTH. */
static unsigned char *
hex_to_buffer (const char *string, size_t *r_length)
{
unsigned char *buffer;
const char *s;
size_t n;
buffer = xtrymalloc (strlen (string)+1);
if (!buffer)
return NULL;
for (s=string, n=0; *s; s++)
{
if (spacep (s) || *s == ':')
continue;
if (hexdigitp (s) && hexdigitp (s+1))
{
buffer[n++] = xtoi_2 (s);
s++;
}
else
break;
}
*r_length = n;
return buffer;
}
/* Reset the card and free the application context. With SEND_RESET /* Reset the card and free the application context. With SEND_RESET
set to true actually send a RESET to the reader. */ set to true actually send a RESET to the reader. */
static void static void
@ -1372,6 +1404,101 @@ cmd_restart (assuan_context_t ctx, char *line)
} }
/* APDU [--atr] [--more] [hexstring]
Send an APDU to the current reader. This command bypasses the high
level functions and sends the data directly to the card. HEXSTRING
is expected to be a proper APDU. If HEXSTRING is not given no
commands are set to the card but the command will implictly check
whether the card is ready for use.
Using the option "--atr" returns the ATR of the card as a status
message before any data like this:
S CARD-ATR 3BFA1300FF813180450031C173C00100009000B1
Using the option --more handles the card status word MORE_DATA
(61xx) and concatenate all reponses to one block.
*/
static int
cmd_apdu (assuan_context_t ctx, char *line)
{
ctrl_t ctrl = assuan_get_pointer (ctx);
int rc;
int rc_is_assuan = 0;
unsigned char *apdu;
size_t apdulen;
int with_atr;
int handle_more;
with_atr = has_option (line, "--atr");
handle_more = has_option (line, "--more");
/* Skip over options. */
while ( *line == '-' && line[1] == '-' )
{
while (*line && !spacep (line))
line++;
while (spacep (line))
line++;
}
if ( IS_LOCKED (ctrl) )
return gpg_error (GPG_ERR_LOCKED);
if ((rc = open_card (ctrl, NULL)))
return rc;
if (with_atr)
{
unsigned char *atr;
size_t atrlen;
int i;
char hexbuf[400];
atr = apdu_get_atr (ctrl->reader_slot, &atrlen);
if (!atr || atrlen > sizeof hexbuf - 2 )
{
rc = gpg_error (GPG_ERR_INV_CARD);
goto leave;
}
for (i=0; i < atrlen; i++)
sprintf (hexbuf+2*i, "%02X", atr[i]);
xfree (atr);
send_status_info (ctrl, "CARD-ATR", hexbuf, strlen (hexbuf), NULL, 0);
}
apdu = hex_to_buffer (line, &apdulen);
if (!apdu)
{
rc = gpg_error_from_errno (errno);
goto leave;
}
if (apdulen)
{
unsigned char *result = NULL;
size_t resultlen;
rc = apdu_send_direct (ctrl->reader_slot, apdu, apdulen, handle_more,
&result, &resultlen);
if (rc)
log_error ("apdu_send_direct failed: %s\n", gpg_strerror (rc));
else
{
rc_is_assuan = 1;
rc = assuan_send_data (ctx, result, resultlen);
xfree (result);
}
}
xfree (apdu);
leave:
TEST_CARD_REMOVAL (ctrl, rc);
return rc_is_assuan? rc : map_to_assuan_status (rc);
}
/* Tell the assuan library about our commands */ /* Tell the assuan library about our commands */
@ -1403,6 +1530,7 @@ register_commands (assuan_context_t ctx)
{ "UNLOCK", cmd_unlock }, { "UNLOCK", cmd_unlock },
{ "GETINFO", cmd_getinfo }, { "GETINFO", cmd_getinfo },
{ "RESTART", cmd_restart }, { "RESTART", cmd_restart },
{ "APDU", cmd_apdu },
{ NULL } { NULL }
}; };
int i, rc; int i, rc;

View File

@ -139,6 +139,8 @@ static ARGPARSE_OPTS opts[] = {
/* The card dirver we use by default for PC/SC. */ /* The card dirver we use by default for PC/SC. */
#if defined(HAVE_W32_SYSTEM) || defined(__CYGWIN__) #if defined(HAVE_W32_SYSTEM) || defined(__CYGWIN__)
#define DEFAULT_PCSC_DRIVER "winscard.dll" #define DEFAULT_PCSC_DRIVER "winscard.dll"
#elif defined(__GLIBC__)
#define DEFAULT_PCSC_DRIVER "libpcsclite.so.1"
#else #else
#define DEFAULT_PCSC_DRIVER "libpcsclite.so" #define DEFAULT_PCSC_DRIVER "libpcsclite.so"
#endif #endif