mirror of
git://git.gnupg.org/gnupg.git
synced 2025-01-31 16:23:02 +01:00
SCD: handle keypad request on the card.
* scd/app-openpgp.c: Add 2013. (struct app_local_s): Add keypad structure. (parse_login_data): Add parsing keypad request on the card. (check_keypad_request): New. (verify_a_chv, verify_chv3, do_change_pin): Call check_keypad_request to determine use of keypad.
This commit is contained in:
parent
f42f1404b9
commit
d1db6bb510
@ -1,6 +1,6 @@
|
|||||||
/* app-openpgp.c - The OpenPGP card application.
|
/* app-openpgp.c - The OpenPGP card application.
|
||||||
* Copyright (C) 2003, 2004, 2005, 2007, 2008,
|
* Copyright (C) 2003, 2004, 2005, 2007, 2008,
|
||||||
* 2009 Free Software Foundation, Inc.
|
* 2009, 2013 Free Software Foundation, Inc.
|
||||||
*
|
*
|
||||||
* This file is part of GnuPG.
|
* This file is part of GnuPG.
|
||||||
*
|
*
|
||||||
@ -191,6 +191,15 @@ struct app_local_s {
|
|||||||
unsigned int def_chv2:1; /* Use 123456 for CHV2. */
|
unsigned int def_chv2:1; /* Use 123456 for CHV2. */
|
||||||
} flags;
|
} flags;
|
||||||
|
|
||||||
|
/* Keypad request specified on card. */
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
unsigned int specified:1;
|
||||||
|
unsigned int varlen:1;
|
||||||
|
int fixedlen_user;
|
||||||
|
int fixedlen_admin;
|
||||||
|
} keypad;
|
||||||
|
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
unsigned int n_bits; /* Size of the modulus in bits. The rest
|
unsigned int n_bits; /* Size of the modulus in bits. The rest
|
||||||
@ -581,17 +590,23 @@ count_bits (const unsigned char *a, size_t len)
|
|||||||
Everything up to a LF is considered a mailbox or account name. If
|
Everything up to a LF is considered a mailbox or account name. If
|
||||||
the first LF is followed by DC4 (0x14) control sequence are
|
the first LF is followed by DC4 (0x14) control sequence are
|
||||||
expected up to the next LF. Control sequences are separated by FS
|
expected up to the next LF. Control sequences are separated by FS
|
||||||
(0x18) and consist of key=value pairs. There is one key defined:
|
(0x18) and consist of key=value pairs. There are two keys defined:
|
||||||
|
|
||||||
F=<flags>
|
F=<flags>
|
||||||
|
|
||||||
Were FLAGS is a plain hexadecimal number representing flag values.
|
Where FLAGS is a plain hexadecimal number representing flag values.
|
||||||
The lsb is here the rightmost bit. Defined flags bits are:
|
The lsb is here the rightmost bit. Defined flags bits are:
|
||||||
|
|
||||||
Bit 0 = CHV1 and CHV2 are not syncronized
|
Bit 0 = CHV1 and CHV2 are not syncronized
|
||||||
Bit 1 = CHV2 has been been set to the default PIN of "123456"
|
Bit 1 = CHV2 has been been set to the default PIN of "123456"
|
||||||
(this implies that bit 0 is also set).
|
(this implies that bit 0 is also set).
|
||||||
|
|
||||||
|
P=<keypad-request>
|
||||||
|
|
||||||
|
Where KEYPAD_REQUEST is 0 or a pair of two integers: <n>,<m>.
|
||||||
|
0 means use keypad with variable length input. <n>,<m> means use
|
||||||
|
keypad with fixed length input. N for user PIN, M for admin PIN.
|
||||||
|
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
parse_login_data (app_t app)
|
parse_login_data (app_t app)
|
||||||
@ -603,6 +618,10 @@ parse_login_data (app_t app)
|
|||||||
/* Set defaults. */
|
/* Set defaults. */
|
||||||
app->app_local->flags.no_sync = 0;
|
app->app_local->flags.no_sync = 0;
|
||||||
app->app_local->flags.def_chv2 = 0;
|
app->app_local->flags.def_chv2 = 0;
|
||||||
|
app->app_local->keypad.specified = 0;
|
||||||
|
app->app_local->keypad.varlen = 0;
|
||||||
|
app->app_local->keypad.fixedlen_user = 6;
|
||||||
|
app->app_local->keypad.fixedlen_admin = 8;
|
||||||
|
|
||||||
/* Read the DO. */
|
/* Read the DO. */
|
||||||
relptr = get_one_do (app, 0x005E, &buffer, &buflen, NULL);
|
relptr = get_one_do (app, 0x005E, &buffer, &buflen, NULL);
|
||||||
@ -628,11 +647,56 @@ parse_login_data (app_t app)
|
|||||||
any leading digits but bail out on invalid characters. */
|
any leading digits but bail out on invalid characters. */
|
||||||
for (p=buffer+2, len = buflen-2; len && hexdigitp (p); p++, len--)
|
for (p=buffer+2, len = buflen-2; len && hexdigitp (p); p++, len--)
|
||||||
lastdig = xtoi_1 (p);
|
lastdig = xtoi_1 (p);
|
||||||
|
buffer = p;
|
||||||
|
buflen = len;
|
||||||
if (len && !(*p == '\n' || *p == '\x18'))
|
if (len && !(*p == '\n' || *p == '\x18'))
|
||||||
goto next; /* Invalid characters in field. */
|
goto next; /* Invalid characters in field. */
|
||||||
app->app_local->flags.no_sync = !!(lastdig & 1);
|
app->app_local->flags.no_sync = !!(lastdig & 1);
|
||||||
app->app_local->flags.def_chv2 = (lastdig & 3) == 3;
|
app->app_local->flags.def_chv2 = (lastdig & 3) == 3;
|
||||||
}
|
}
|
||||||
|
else if (buflen > 1 && *buffer == 'P' && buffer[1] == '=')
|
||||||
|
{
|
||||||
|
/* Keypad request control sequence found. */
|
||||||
|
buffer += 2;
|
||||||
|
buflen -= 2;
|
||||||
|
|
||||||
|
if (buflen)
|
||||||
|
{
|
||||||
|
if (*buffer == '0')
|
||||||
|
{
|
||||||
|
buffer++;
|
||||||
|
buflen--;
|
||||||
|
if (buflen && !(*buffer == '\n' || *buffer == '\x18'))
|
||||||
|
goto next;
|
||||||
|
app->app_local->keypad.specified = 1;
|
||||||
|
app->app_local->keypad.varlen = 1;
|
||||||
|
}
|
||||||
|
else if (digitp (buffer))
|
||||||
|
{
|
||||||
|
char *q;
|
||||||
|
int n, m;
|
||||||
|
|
||||||
|
n = strtol (buffer, &q, 10);
|
||||||
|
if (*q++ != ',' || !digitp (q))
|
||||||
|
goto next;
|
||||||
|
m = strtol (q, &q, 10);
|
||||||
|
buffer = q;
|
||||||
|
if (buflen < ((unsigned char *)q - buffer))
|
||||||
|
{
|
||||||
|
buflen = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
buflen -= ((unsigned char *)q - buffer);
|
||||||
|
|
||||||
|
if (buflen && !(*buffer == '\n' || *buffer == '\x18'))
|
||||||
|
goto next;
|
||||||
|
app->app_local->keypad.specified = 1;
|
||||||
|
app->app_local->keypad.fixedlen_user = n;
|
||||||
|
app->app_local->keypad.fixedlen_admin = m;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
next:
|
next:
|
||||||
for (; buflen && *buffer != '\x18'; buflen--, buffer++)
|
for (; buflen && *buffer != '\x18'; buflen--, buffer++)
|
||||||
if (*buffer == '\n')
|
if (*buffer == '\n')
|
||||||
@ -1470,6 +1534,37 @@ do_readcert (app_t app, const char *certid,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Decide if we use keypad of reader for PIN input according to the
|
||||||
|
user preference on the card. Returns 0 if we use keypad, 1 otherwise. */
|
||||||
|
static int
|
||||||
|
check_keypad_request (app_t app, pininfo_t *pininfo, int admin_pin)
|
||||||
|
{
|
||||||
|
/* User specifies no preference on card, then, use pinentry. */
|
||||||
|
if (app->app_local->keypad.specified == 0)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
if (app->app_local->keypad.varlen)
|
||||||
|
if (pininfo->fixedlen == 0)
|
||||||
|
return 0;
|
||||||
|
else
|
||||||
|
/* On card, user specifies varlen but reader doesn't have the feature. */
|
||||||
|
return 1;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (admin_pin)
|
||||||
|
pininfo->fixedlen = app->app_local->keypad.fixedlen_admin;
|
||||||
|
else
|
||||||
|
pininfo->fixedlen = app->app_local->keypad.fixedlen_user;
|
||||||
|
|
||||||
|
if (pininfo->fixedlen < pininfo->minlen
|
||||||
|
|| pininfo->fixedlen > pininfo->maxlen)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Verify a CHV either using using the pinentry or if possibile by
|
/* Verify a CHV either using using the pinentry or if possibile by
|
||||||
using a keypad. PINCB and PINCB_ARG describe the usual callback
|
using a keypad. PINCB and PINCB_ARG describe the usual callback
|
||||||
for the pinentry. CHVNO must be either 1 or 2. SIGCOUNT is only
|
for the pinentry. CHVNO must be either 1 or 2. SIGCOUNT is only
|
||||||
@ -1537,7 +1632,8 @@ verify_a_chv (app_t app,
|
|||||||
|
|
||||||
|
|
||||||
if (!opt.disable_keypad
|
if (!opt.disable_keypad
|
||||||
&& !iso7816_check_keypad (app->slot, ISO7816_VERIFY, &pininfo) )
|
&& !iso7816_check_keypad (app->slot, ISO7816_VERIFY, &pininfo)
|
||||||
|
&& !check_keypad_request (app, &pininfo, 0))
|
||||||
{
|
{
|
||||||
/* The reader supports the verify command through the keypad.
|
/* The reader supports the verify command through the keypad.
|
||||||
Note that the pincb appends a text to the prompt telling the
|
Note that the pincb appends a text to the prompt telling the
|
||||||
@ -1720,7 +1816,8 @@ verify_chv3 (app_t app,
|
|||||||
return rc;
|
return rc;
|
||||||
|
|
||||||
if (!opt.disable_keypad
|
if (!opt.disable_keypad
|
||||||
&& !iso7816_check_keypad (app->slot, ISO7816_VERIFY, &pininfo) )
|
&& !iso7816_check_keypad (app->slot, ISO7816_VERIFY, &pininfo)
|
||||||
|
&& !check_keypad_request (app, &pininfo, 1))
|
||||||
{
|
{
|
||||||
/* The reader supports the verify command through the keypad. */
|
/* The reader supports the verify command through the keypad. */
|
||||||
rc = pincb (pincb_arg, prompt, NULL);
|
rc = pincb (pincb_arg, prompt, NULL);
|
||||||
@ -1970,7 +2067,8 @@ do_change_pin (app_t app, ctrl_t ctrl, const char *chvnostr,
|
|||||||
|
|
||||||
if (!opt.disable_keypad
|
if (!opt.disable_keypad
|
||||||
&& !iso7816_check_keypad (app->slot,
|
&& !iso7816_check_keypad (app->slot,
|
||||||
ISO7816_CHANGE_REFERENCE_DATA, &pininfo))
|
ISO7816_CHANGE_REFERENCE_DATA, &pininfo)
|
||||||
|
&& !check_keypad_request (app, &pininfo, chvno == 3))
|
||||||
use_keypad = 1;
|
use_keypad = 1;
|
||||||
|
|
||||||
if (reset_mode)
|
if (reset_mode)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user