mirror of
git://git.gnupg.org/gnupg.git
synced 2025-03-28 22:49:59 +01:00
g10,scd: Support single salt for KDF data object.
* g10/card-util.c (gen_kdf_data): Support single salt. (kdf_setup): Can have argument for single salt. * scd/app-openpgp.c (pin2hash_if_kdf): Support single salt. -- Gnuk has "admin-less" mode. To support "admin-less" mode with KDF feature, salt should be same for user and admin. Thus, I introduce a valid use of single salt. Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
This commit is contained in:
parent
820380335a
commit
0c097575a9
@ -1978,11 +1978,12 @@ factory_reset (void)
|
|||||||
|
|
||||||
#define USER_PIN_DEFAULT "123456"
|
#define USER_PIN_DEFAULT "123456"
|
||||||
#define ADMIN_PIN_DEFAULT "12345678"
|
#define ADMIN_PIN_DEFAULT "12345678"
|
||||||
#define KDF_DATA_LENGTH 110
|
#define KDF_DATA_LENGTH_MIN 90
|
||||||
|
#define KDF_DATA_LENGTH_MAX 110
|
||||||
|
|
||||||
/* Generate KDF data. */
|
/* Generate KDF data. */
|
||||||
static gpg_error_t
|
static gpg_error_t
|
||||||
gen_kdf_data (unsigned char *data)
|
gen_kdf_data (unsigned char *data, int single_salt)
|
||||||
{
|
{
|
||||||
const unsigned char h0[] = { 0x81, 0x01, 0x03,
|
const unsigned char h0[] = { 0x81, 0x01, 0x03,
|
||||||
0x82, 0x01, 0x08,
|
0x82, 0x01, 0x08,
|
||||||
@ -2015,14 +2016,19 @@ gen_kdf_data (unsigned char *data)
|
|||||||
salt_user = (p += sizeof h1);
|
salt_user = (p += sizeof h1);
|
||||||
gcry_randomize (p, 8, GCRY_STRONG_RANDOM);
|
gcry_randomize (p, 8, GCRY_STRONG_RANDOM);
|
||||||
p += 8;
|
p += 8;
|
||||||
memcpy (p, h2, sizeof h2);
|
|
||||||
p += sizeof h2;
|
if (!single_salt)
|
||||||
gcry_randomize (p, 8, GCRY_STRONG_RANDOM);
|
{
|
||||||
p += 8;
|
memcpy (p, h2, sizeof h2);
|
||||||
memcpy (p, h3, sizeof h3);
|
p += sizeof h2;
|
||||||
salt_admin = (p += sizeof h3);
|
gcry_randomize (p, 8, GCRY_STRONG_RANDOM);
|
||||||
gcry_randomize (p, 8, GCRY_STRONG_RANDOM);
|
p += 8;
|
||||||
p += 8;
|
memcpy (p, h3, sizeof h3);
|
||||||
|
salt_admin = (p += sizeof h3);
|
||||||
|
gcry_randomize (p, 8, GCRY_STRONG_RANDOM);
|
||||||
|
p += 8;
|
||||||
|
}
|
||||||
|
|
||||||
memcpy (p, h4, sizeof h4);
|
memcpy (p, h4, sizeof h4);
|
||||||
p += sizeof h4;
|
p += sizeof h4;
|
||||||
err = gcry_kdf_derive (USER_PIN_DEFAULT, strlen (USER_PIN_DEFAULT),
|
err = gcry_kdf_derive (USER_PIN_DEFAULT, strlen (USER_PIN_DEFAULT),
|
||||||
@ -2043,11 +2049,12 @@ gen_kdf_data (unsigned char *data)
|
|||||||
|
|
||||||
/* Setup KDF data object which is used for PIN authentication. */
|
/* Setup KDF data object which is used for PIN authentication. */
|
||||||
static void
|
static void
|
||||||
kdf_setup (void)
|
kdf_setup (const char *args)
|
||||||
{
|
{
|
||||||
struct agent_card_info_s info;
|
struct agent_card_info_s info;
|
||||||
gpg_error_t err;
|
gpg_error_t err;
|
||||||
unsigned char kdf_data[KDF_DATA_LENGTH];
|
unsigned char kdf_data[KDF_DATA_LENGTH_MAX];
|
||||||
|
int single = (*args != 0);
|
||||||
|
|
||||||
memset (&info, 0, sizeof info);
|
memset (&info, 0, sizeof info);
|
||||||
|
|
||||||
@ -2064,10 +2071,19 @@ kdf_setup (void)
|
|||||||
goto leave;
|
goto leave;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(err = gen_kdf_data (kdf_data))
|
err = gen_kdf_data (kdf_data, single);
|
||||||
&& !(err = agent_scd_setattr ("KDF", kdf_data, KDF_DATA_LENGTH, NULL)))
|
if (err)
|
||||||
err = agent_scd_getattr ("KDF", &info);
|
goto leave_error;
|
||||||
|
|
||||||
|
err = agent_scd_setattr ("KDF", kdf_data,
|
||||||
|
single ? KDF_DATA_LENGTH_MIN : KDF_DATA_LENGTH_MAX,
|
||||||
|
NULL);
|
||||||
|
if (err)
|
||||||
|
goto leave_error;
|
||||||
|
|
||||||
|
err = agent_scd_getattr ("KDF", &info);
|
||||||
|
|
||||||
|
leave_error:
|
||||||
if (err)
|
if (err)
|
||||||
log_error (_("error for setup KDF: %s\n"), gpg_strerror (err));
|
log_error (_("error for setup KDF: %s\n"), gpg_strerror (err));
|
||||||
|
|
||||||
@ -2403,7 +2419,7 @@ card_edit (ctrl_t ctrl, strlist_t commands)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case cmdKDFSETUP:
|
case cmdKDFSETUP:
|
||||||
kdf_setup ();
|
kdf_setup (arg_string);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case cmdKEYATTR:
|
case cmdKEYATTR:
|
||||||
|
@ -2061,6 +2061,9 @@ get_prompt_info (app_t app, int chvno, unsigned long sigcount, int remaining)
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define KDF_DATA_LENGTH_MIN 90
|
||||||
|
#define KDF_DATA_LENGTH_MAX 110
|
||||||
|
|
||||||
/* Compute hash if KDF-DO is available. CHVNO must be 0 for reset
|
/* Compute hash if KDF-DO is available. CHVNO must be 0 for reset
|
||||||
code, 1 or 2 for user pin and 3 for admin pin.
|
code, 1 or 2 for user pin and 3 for admin pin.
|
||||||
*/
|
*/
|
||||||
@ -2068,21 +2071,33 @@ static gpg_error_t
|
|||||||
pin2hash_if_kdf (app_t app, int chvno, char *pinvalue, int *r_pinlen)
|
pin2hash_if_kdf (app_t app, int chvno, char *pinvalue, int *r_pinlen)
|
||||||
{
|
{
|
||||||
gpg_error_t err = 0;
|
gpg_error_t err = 0;
|
||||||
void *relptr;
|
void *relptr = NULL;
|
||||||
unsigned char *buffer;
|
unsigned char *buffer;
|
||||||
size_t buflen;
|
size_t buflen;
|
||||||
|
|
||||||
if (app->app_local->extcap.kdf_do
|
if (app->app_local->extcap.kdf_do
|
||||||
&& (relptr = get_one_do (app, 0x00F9, &buffer, &buflen, NULL))
|
&& (relptr = get_one_do (app, 0x00F9, &buffer, &buflen, NULL))
|
||||||
&& buflen == 110 && (buffer[2] == 0x03))
|
&& buflen >= KDF_DATA_LENGTH_MIN && (buffer[2] == 0x03))
|
||||||
{
|
{
|
||||||
char *salt;
|
const char *salt;
|
||||||
unsigned long s2k_count;
|
unsigned long s2k_count;
|
||||||
char dek[32];
|
char dek[32];
|
||||||
|
int salt_index;
|
||||||
|
|
||||||
salt = &buffer[(chvno==3 ? 34 : (chvno==0 ? 24 : 14))];
|
|
||||||
s2k_count = (((unsigned int)buffer[8] << 24)
|
s2k_count = (((unsigned int)buffer[8] << 24)
|
||||||
| (buffer[9] << 16) | (buffer[10] << 8) | buffer[11]);
|
| (buffer[9] << 16) | (buffer[10] << 8) | buffer[11]);
|
||||||
|
|
||||||
|
if (buflen == KDF_DATA_LENGTH_MIN)
|
||||||
|
salt_index =14;
|
||||||
|
else if (buflen == KDF_DATA_LENGTH_MAX)
|
||||||
|
salt_index = (chvno==3 ? 34 : (chvno==0 ? 24 : 14));
|
||||||
|
else
|
||||||
|
{
|
||||||
|
err = gpg_error (GPG_ERR_INV_DATA);
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
|
||||||
|
salt = &buffer[salt_index];
|
||||||
err = gcry_kdf_derive (pinvalue, strlen (pinvalue),
|
err = gcry_kdf_derive (pinvalue, strlen (pinvalue),
|
||||||
GCRY_KDF_ITERSALTED_S2K,
|
GCRY_KDF_ITERSALTED_S2K,
|
||||||
DIGEST_ALGO_SHA256, salt, 8,
|
DIGEST_ALGO_SHA256, salt, 8,
|
||||||
@ -2094,12 +2109,12 @@ pin2hash_if_kdf (app_t app, int chvno, char *pinvalue, int *r_pinlen)
|
|||||||
memcpy (pinvalue, dek, *r_pinlen);
|
memcpy (pinvalue, dek, *r_pinlen);
|
||||||
wipememory (dek, *r_pinlen);
|
wipememory (dek, *r_pinlen);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
xfree (relptr);
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
*r_pinlen = strlen (pinvalue);
|
*r_pinlen = strlen (pinvalue);
|
||||||
|
|
||||||
|
leave:
|
||||||
|
xfree (relptr);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user