mirror of
git://git.gnupg.org/gnupg.git
synced 2025-01-22 14:57:02 +01:00
scd: Skip S/N reading for the "undefined" application.
* scd/app.c (select_application): Skip serial number reading. -- (cherry picked from commit 792e137ec7997a0ff5c54ff970611238d28d4ba8) Resolved conflicts: scd/app.c: Take care of already changed geldkarte/dinsig order.
This commit is contained in:
parent
3ae90ff28c
commit
dc941bdaec
141
scd/app.c
141
scd/app.c
@ -69,7 +69,7 @@ print_progress_line (void *opaque, const char *what, int pc, int cur, int tot)
|
|||||||
never shares a reader (while performing one command). Returns 0 on
|
never shares a reader (while performing one command). Returns 0 on
|
||||||
success; only then the unlock_reader function must be called after
|
success; only then the unlock_reader function must be called after
|
||||||
returning from the handler. */
|
returning from the handler. */
|
||||||
static gpg_error_t
|
static gpg_error_t
|
||||||
lock_reader (int slot, ctrl_t ctrl)
|
lock_reader (int slot, ctrl_t ctrl)
|
||||||
{
|
{
|
||||||
gpg_error_t err;
|
gpg_error_t err;
|
||||||
@ -89,7 +89,7 @@ lock_reader (int slot, ctrl_t ctrl)
|
|||||||
lock_table[slot].app = NULL;
|
lock_table[slot].app = NULL;
|
||||||
lock_table[slot].last_app = NULL;
|
lock_table[slot].last_app = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!pth_mutex_acquire (&lock_table[slot].lock, 0, NULL))
|
if (!pth_mutex_acquire (&lock_table[slot].lock, 0, NULL))
|
||||||
{
|
{
|
||||||
err = gpg_error_from_syserror ();
|
err = gpg_error_from_syserror ();
|
||||||
@ -188,7 +188,7 @@ application_notify_card_reset (int slot)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
/* FIXME: We are ignoring any error value here. */
|
/* FIXME: We are ignoring any error value here. */
|
||||||
lock_reader (slot, NULL);
|
lock_reader (slot, NULL);
|
||||||
|
|
||||||
/* Mark application as non-reusable. */
|
/* Mark application as non-reusable. */
|
||||||
if (lock_table[slot].app)
|
if (lock_table[slot].app)
|
||||||
@ -204,10 +204,10 @@ application_notify_card_reset (int slot)
|
|||||||
lock_table[slot].last_app = NULL;
|
lock_table[slot].last_app = NULL;
|
||||||
deallocate_app (app);
|
deallocate_app (app);
|
||||||
}
|
}
|
||||||
unlock_reader (slot);
|
unlock_reader (slot);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* This function is used by the serialno command to check for an
|
/* This function is used by the serialno command to check for an
|
||||||
application conflict which may appear if the serialno command is
|
application conflict which may appear if the serialno command is
|
||||||
used to request a specific application and the connection has
|
used to request a specific application and the connection has
|
||||||
@ -241,11 +241,14 @@ select_application (ctrl_t ctrl, int slot, const char *name, app_t *r_app)
|
|||||||
app_t app = NULL;
|
app_t app = NULL;
|
||||||
unsigned char *result = NULL;
|
unsigned char *result = NULL;
|
||||||
size_t resultlen;
|
size_t resultlen;
|
||||||
|
int want_undefined;
|
||||||
|
|
||||||
(void)ctrl;
|
(void)ctrl;
|
||||||
|
|
||||||
*r_app = NULL;
|
*r_app = NULL;
|
||||||
|
|
||||||
|
want_undefined = (name && !strcmp (name, "undefined"));
|
||||||
|
|
||||||
err = lock_reader (slot, ctrl);
|
err = lock_reader (slot, ctrl);
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
@ -287,7 +290,7 @@ select_application (ctrl_t ctrl, int slot, const char *name, app_t *r_app)
|
|||||||
lock_table[slot].app = app;
|
lock_table[slot].app = app;
|
||||||
lock_table[slot].last_app = NULL;
|
lock_table[slot].last_app = NULL;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* No, this saved application can't be used - deallocate it. */
|
/* No, this saved application can't be used - deallocate it. */
|
||||||
lock_table[slot].last_app = NULL;
|
lock_table[slot].last_app = NULL;
|
||||||
@ -309,7 +312,7 @@ select_application (ctrl_t ctrl, int slot, const char *name, app_t *r_app)
|
|||||||
unlock_reader (slot);
|
unlock_reader (slot);
|
||||||
return 0; /* Okay: We share that one. */
|
return 0; /* Okay: We share that one. */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Need to allocate a new one. */
|
/* Need to allocate a new one. */
|
||||||
app = xtrycalloc (1, sizeof *app);
|
app = xtrycalloc (1, sizeof *app);
|
||||||
if (!app)
|
if (!app)
|
||||||
@ -325,54 +328,66 @@ select_application (ctrl_t ctrl, int slot, const char *name, app_t *r_app)
|
|||||||
/* Fixme: We should now first check whether a card is at all
|
/* Fixme: We should now first check whether a card is at all
|
||||||
present. */
|
present. */
|
||||||
|
|
||||||
/* Try to read the GDO file first to get a default serial number. */
|
/* Try to read the GDO file first to get a default serial number.
|
||||||
err = iso7816_select_file (slot, 0x3F00, 1, NULL, NULL);
|
We skip this if the undefined application has been requested. */
|
||||||
if (!err)
|
if (!want_undefined)
|
||||||
err = iso7816_select_file (slot, 0x2F02, 0, NULL, NULL);
|
|
||||||
if (!err)
|
|
||||||
err = iso7816_read_binary (slot, 0, 0, &result, &resultlen);
|
|
||||||
if (!err)
|
|
||||||
{
|
{
|
||||||
size_t n;
|
err = iso7816_select_file (slot, 0x3F00, 1, NULL, NULL);
|
||||||
const unsigned char *p;
|
if (!err)
|
||||||
|
err = iso7816_select_file (slot, 0x2F02, 0, NULL, NULL);
|
||||||
p = find_tlv_unchecked (result, resultlen, 0x5A, &n);
|
if (!err)
|
||||||
if (p)
|
err = iso7816_read_binary (slot, 0, 0, &result, &resultlen);
|
||||||
resultlen -= (p-result);
|
if (!err)
|
||||||
if (p && n > resultlen && n == 0x0d && resultlen+1 == n)
|
|
||||||
{
|
{
|
||||||
/* The object it does not fit into the buffer. This is an
|
size_t n;
|
||||||
invalid encoding (or the buffer is too short. However, I
|
const unsigned char *p;
|
||||||
have some test cards with such an invalid encoding and
|
|
||||||
therefore I use this ugly workaround to return something
|
|
||||||
I can further experiment with. */
|
|
||||||
log_info ("enabling BMI testcard workaround\n");
|
|
||||||
n--;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (p && n <= resultlen)
|
p = find_tlv_unchecked (result, resultlen, 0x5A, &n);
|
||||||
{
|
if (p)
|
||||||
/* The GDO file is pretty short, thus we simply reuse it for
|
resultlen -= (p-result);
|
||||||
storing the serial number. */
|
if (p && n > resultlen && n == 0x0d && resultlen+1 == n)
|
||||||
memmove (result, p, n);
|
{
|
||||||
app->serialno = result;
|
/* The object it does not fit into the buffer. This is an
|
||||||
app->serialnolen = n;
|
invalid encoding (or the buffer is too short. However, I
|
||||||
err = app_munge_serialno (app);
|
have some test cards with such an invalid encoding and
|
||||||
if (err)
|
therefore I use this ugly workaround to return something
|
||||||
goto leave;
|
I can further experiment with. */
|
||||||
|
log_info ("enabling BMI testcard workaround\n");
|
||||||
|
n--;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (p && n <= resultlen)
|
||||||
|
{
|
||||||
|
/* The GDO file is pretty short, thus we simply reuse it for
|
||||||
|
storing the serial number. */
|
||||||
|
memmove (result, p, n);
|
||||||
|
app->serialno = result;
|
||||||
|
app->serialnolen = n;
|
||||||
|
err = app_munge_serialno (app);
|
||||||
|
if (err)
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
xfree (result);
|
||||||
|
result = NULL;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
xfree (result);
|
|
||||||
result = NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* For certain error codes, there is no need to try more. */
|
/* For certain error codes, there is no need to try more. */
|
||||||
if (gpg_err_code (err) == GPG_ERR_CARD_NOT_PRESENT
|
if (gpg_err_code (err) == GPG_ERR_CARD_NOT_PRESENT
|
||||||
|| gpg_err_code (err) == GPG_ERR_ENODEV)
|
|| gpg_err_code (err) == GPG_ERR_ENODEV)
|
||||||
goto leave;
|
goto leave;
|
||||||
|
|
||||||
/* Figure out the application to use. */
|
/* Figure out the application to use. */
|
||||||
err = gpg_error (GPG_ERR_NOT_FOUND);
|
if (want_undefined)
|
||||||
|
{
|
||||||
|
/* We switch to the "undefined" application only if explicitly
|
||||||
|
requested. */
|
||||||
|
app->apptype = "UNDEFINED";
|
||||||
|
err = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
err = gpg_error (GPG_ERR_NOT_FOUND);
|
||||||
|
|
||||||
if (err && is_app_allowed ("openpgp")
|
if (err && is_app_allowed ("openpgp")
|
||||||
&& (!name || !strcmp (name, "openpgp")))
|
&& (!name || !strcmp (name, "openpgp")))
|
||||||
@ -428,10 +443,10 @@ get_supported_applications (void)
|
|||||||
int idx;
|
int idx;
|
||||||
size_t nbytes;
|
size_t nbytes;
|
||||||
char *buffer, *p;
|
char *buffer, *p;
|
||||||
|
|
||||||
for (nbytes=1, idx=0; list[idx]; idx++)
|
for (nbytes=1, idx=0; list[idx]; idx++)
|
||||||
nbytes += strlen (list[idx]) + 1 + 1;
|
nbytes += strlen (list[idx]) + 1 + 1;
|
||||||
|
|
||||||
buffer = xtrymalloc (nbytes);
|
buffer = xtrymalloc (nbytes);
|
||||||
if (!buffer)
|
if (!buffer)
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -508,22 +523,22 @@ release_application (app_t app)
|
|||||||
|
|
||||||
/* The serial number may need some cosmetics. Do it here. This
|
/* The serial number may need some cosmetics. Do it here. This
|
||||||
function shall only be called once after a new serial number has
|
function shall only be called once after a new serial number has
|
||||||
been put into APP->serialno.
|
been put into APP->serialno.
|
||||||
|
|
||||||
Prefixes we use:
|
Prefixes we use:
|
||||||
|
|
||||||
FF 00 00 = For serial numbers starting with an FF
|
FF 00 00 = For serial numbers starting with an FF
|
||||||
FF 01 00 = Some german p15 cards return an empty serial number so the
|
FF 01 00 = Some german p15 cards return an empty serial number so the
|
||||||
serial number from the EF(TokenInfo) is used instead.
|
serial number from the EF(TokenInfo) is used instead.
|
||||||
FF 7F 00 = No serialno.
|
FF 7F 00 = No serialno.
|
||||||
|
|
||||||
All other serial number not starting with FF are used as they are.
|
All other serial number not starting with FF are used as they are.
|
||||||
*/
|
*/
|
||||||
gpg_error_t
|
gpg_error_t
|
||||||
app_munge_serialno (app_t app)
|
app_munge_serialno (app_t app)
|
||||||
{
|
{
|
||||||
if (app->serialnolen && app->serialno[0] == 0xff)
|
if (app->serialnolen && app->serialno[0] == 0xff)
|
||||||
{
|
{
|
||||||
/* The serial number starts with our special prefix. This
|
/* The serial number starts with our special prefix. This
|
||||||
requires that we put our default prefix "FF0000" in front. */
|
requires that we put our default prefix "FF0000" in front. */
|
||||||
unsigned char *p = xtrymalloc (app->serialnolen + 3);
|
unsigned char *p = xtrymalloc (app->serialnolen + 3);
|
||||||
@ -536,7 +551,7 @@ app_munge_serialno (app_t app)
|
|||||||
app->serialno = p;
|
app->serialno = p;
|
||||||
}
|
}
|
||||||
else if (!app->serialnolen)
|
else if (!app->serialnolen)
|
||||||
{
|
{
|
||||||
unsigned char *p = xtrymalloc (3);
|
unsigned char *p = xtrymalloc (3);
|
||||||
if (!p)
|
if (!p)
|
||||||
return gpg_error_from_syserror ();
|
return gpg_error_from_syserror ();
|
||||||
@ -556,7 +571,7 @@ app_munge_serialno (app_t app)
|
|||||||
no update time is available the returned value is 0. Caller must
|
no update time is available the returned value is 0. Caller must
|
||||||
free SERIAL unless the function returns an error. If STAMP is not
|
free SERIAL unless the function returns an error. If STAMP is not
|
||||||
of interest, NULL may be passed. */
|
of interest, NULL may be passed. */
|
||||||
gpg_error_t
|
gpg_error_t
|
||||||
app_get_serial_and_stamp (app_t app, char **serial, time_t *stamp)
|
app_get_serial_and_stamp (app_t app, char **serial, time_t *stamp)
|
||||||
{
|
{
|
||||||
char *buf;
|
char *buf;
|
||||||
@ -639,7 +654,7 @@ app_readcert (app_t app, const char *certid,
|
|||||||
code returned.
|
code returned.
|
||||||
|
|
||||||
This function might not be supported by all applications. */
|
This function might not be supported by all applications. */
|
||||||
gpg_error_t
|
gpg_error_t
|
||||||
app_readkey (app_t app, const char *keyid, unsigned char **pk, size_t *pklen)
|
app_readkey (app_t app, const char *keyid, unsigned char **pk, size_t *pklen)
|
||||||
{
|
{
|
||||||
gpg_error_t err;
|
gpg_error_t err;
|
||||||
@ -665,7 +680,7 @@ app_readkey (app_t app, const char *keyid, unsigned char **pk, size_t *pklen)
|
|||||||
|
|
||||||
|
|
||||||
/* Perform a GETATTR operation. */
|
/* Perform a GETATTR operation. */
|
||||||
gpg_error_t
|
gpg_error_t
|
||||||
app_getattr (app_t app, ctrl_t ctrl, const char *name)
|
app_getattr (app_t app, ctrl_t ctrl, const char *name)
|
||||||
{
|
{
|
||||||
gpg_error_t err;
|
gpg_error_t err;
|
||||||
@ -686,7 +701,7 @@ app_getattr (app_t app, ctrl_t ctrl, const char *name)
|
|||||||
char *serial;
|
char *serial;
|
||||||
time_t stamp;
|
time_t stamp;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
rc = app_get_serial_and_stamp (app, &serial, &stamp);
|
rc = app_get_serial_and_stamp (app, &serial, &stamp);
|
||||||
if (rc)
|
if (rc)
|
||||||
return rc;
|
return rc;
|
||||||
@ -706,7 +721,7 @@ app_getattr (app_t app, ctrl_t ctrl, const char *name)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Perform a SETATTR operation. */
|
/* Perform a SETATTR operation. */
|
||||||
gpg_error_t
|
gpg_error_t
|
||||||
app_setattr (app_t app, const char *name,
|
app_setattr (app_t app, const char *name,
|
||||||
gpg_error_t (*pincb)(void*, const char *, char **),
|
gpg_error_t (*pincb)(void*, const char *, char **),
|
||||||
void *pincb_arg,
|
void *pincb_arg,
|
||||||
@ -731,7 +746,7 @@ app_setattr (app_t app, const char *name,
|
|||||||
/* Create the signature and return the allocated result in OUTDATA.
|
/* Create the signature and return the allocated result in OUTDATA.
|
||||||
If a PIN is required the PINCB will be used to ask for the PIN; it
|
If a PIN is required the PINCB will be used to ask for the PIN; it
|
||||||
should return the PIN in an allocated buffer and put it into PIN. */
|
should return the PIN in an allocated buffer and put it into PIN. */
|
||||||
gpg_error_t
|
gpg_error_t
|
||||||
app_sign (app_t app, const char *keyidstr, int hashalgo,
|
app_sign (app_t app, const char *keyidstr, int hashalgo,
|
||||||
gpg_error_t (*pincb)(void*, const char *, char **),
|
gpg_error_t (*pincb)(void*, const char *, char **),
|
||||||
void *pincb_arg,
|
void *pincb_arg,
|
||||||
@ -763,7 +778,7 @@ app_sign (app_t app, const char *keyidstr, int hashalgo,
|
|||||||
return the allocated result in OUTDATA. If a PIN is required the
|
return the allocated result in OUTDATA. If a PIN is required the
|
||||||
PINCB will be used to ask for the PIN; it should return the PIN in
|
PINCB will be used to ask for the PIN; it should return the PIN in
|
||||||
an allocated buffer and put it into PIN. */
|
an allocated buffer and put it into PIN. */
|
||||||
gpg_error_t
|
gpg_error_t
|
||||||
app_auth (app_t app, const char *keyidstr,
|
app_auth (app_t app, const char *keyidstr,
|
||||||
gpg_error_t (*pincb)(void*, const char *, char **),
|
gpg_error_t (*pincb)(void*, const char *, char **),
|
||||||
void *pincb_arg,
|
void *pincb_arg,
|
||||||
@ -795,7 +810,7 @@ app_auth (app_t app, const char *keyidstr,
|
|||||||
/* Decrypt the data in INDATA and return the allocated result in OUTDATA.
|
/* Decrypt the data in INDATA and return the allocated result in OUTDATA.
|
||||||
If a PIN is required the PINCB will be used to ask for the PIN; it
|
If a PIN is required the PINCB will be used to ask for the PIN; it
|
||||||
should return the PIN in an allocated buffer and put it into PIN. */
|
should return the PIN in an allocated buffer and put it into PIN. */
|
||||||
gpg_error_t
|
gpg_error_t
|
||||||
app_decipher (app_t app, const char *keyidstr,
|
app_decipher (app_t app, const char *keyidstr,
|
||||||
gpg_error_t (*pincb)(void*, const char *, char **),
|
gpg_error_t (*pincb)(void*, const char *, char **),
|
||||||
void *pincb_arg,
|
void *pincb_arg,
|
||||||
@ -881,7 +896,7 @@ app_writekey (app_t app, ctrl_t ctrl,
|
|||||||
|
|
||||||
|
|
||||||
/* Perform a SETATTR operation. */
|
/* Perform a SETATTR operation. */
|
||||||
gpg_error_t
|
gpg_error_t
|
||||||
app_genkey (app_t app, ctrl_t ctrl, const char *keynostr, unsigned int flags,
|
app_genkey (app_t app, ctrl_t ctrl, const char *keynostr, unsigned int flags,
|
||||||
time_t createtime,
|
time_t createtime,
|
||||||
gpg_error_t (*pincb)(void*, const char *, char **),
|
gpg_error_t (*pincb)(void*, const char *, char **),
|
||||||
@ -898,7 +913,7 @@ app_genkey (app_t app, ctrl_t ctrl, const char *keynostr, unsigned int flags,
|
|||||||
err = lock_reader (app->slot, ctrl);
|
err = lock_reader (app->slot, ctrl);
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
err = app->fnc.genkey (app, ctrl, keynostr, flags,
|
err = app->fnc.genkey (app, ctrl, keynostr, flags,
|
||||||
createtime, pincb, pincb_arg);
|
createtime, pincb, pincb_arg);
|
||||||
unlock_reader (app->slot);
|
unlock_reader (app->slot);
|
||||||
if (opt.verbose)
|
if (opt.verbose)
|
||||||
@ -930,7 +945,7 @@ app_get_challenge (app_t app, size_t nbytes, unsigned char *buffer)
|
|||||||
|
|
||||||
|
|
||||||
/* Perform a CHANGE REFERENCE DATA or RESET RETRY COUNTER operation. */
|
/* Perform a CHANGE REFERENCE DATA or RESET RETRY COUNTER operation. */
|
||||||
gpg_error_t
|
gpg_error_t
|
||||||
app_change_pin (app_t app, ctrl_t ctrl, const char *chvnostr, int reset_mode,
|
app_change_pin (app_t app, ctrl_t ctrl, const char *chvnostr, int reset_mode,
|
||||||
gpg_error_t (*pincb)(void*, const char *, char **),
|
gpg_error_t (*pincb)(void*, const char *, char **),
|
||||||
void *pincb_arg)
|
void *pincb_arg)
|
||||||
@ -958,7 +973,7 @@ app_change_pin (app_t app, ctrl_t ctrl, const char *chvnostr, int reset_mode,
|
|||||||
/* Perform a VERIFY operation without doing anything lese. This may
|
/* Perform a VERIFY operation without doing anything lese. This may
|
||||||
be used to initialze a the PIN cache for long lasting other
|
be used to initialze a the PIN cache for long lasting other
|
||||||
operations. Its use is highly application dependent. */
|
operations. Its use is highly application dependent. */
|
||||||
gpg_error_t
|
gpg_error_t
|
||||||
app_check_pin (app_t app, const char *keyidstr,
|
app_check_pin (app_t app, const char *keyidstr,
|
||||||
gpg_error_t (*pincb)(void*, const char *, char **),
|
gpg_error_t (*pincb)(void*, const char *, char **),
|
||||||
void *pincb_arg)
|
void *pincb_arg)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user