Implement use of KDF data object.

This commit is contained in:
NIIBE Yutaka 2017-11-02 10:59:17 +09:00
parent 2ecb104ae4
commit b735c02ec2
5 changed files with 58 additions and 14 deletions

View File

@ -1,6 +1,12 @@
2017-11-02 NIIBE Yutaka <gniibe@fsij.org>
* src/openpgp-do.c (rw_kdf): Only writable when no keys.
(gpg_do_get_initial_pw_setting): New.
(gpg_do_write_prvkey): Use gpg_do_get_initial_pw_setting.
(gpg_do_keygen): Likewise.
* src/openpgp.c (cmd_change_password): Use
gpg_do_get_initial_pw_setting.
* src/ac.c (verify_user_0, verify_admin_0): Likewise.
2017-11-01 NIIBE Yutaka <gniibe@fsij.org>

View File

@ -1,7 +1,7 @@
/*
* ac.c -- Check access condition
*
* Copyright (C) 2010, 2012, 2013 Free Software Initiative of Japan
* Copyright (C) 2010, 2012, 2013, 2017 Free Software Initiative of Japan
* Author: NIIBE Yutaka <gniibe@fsij.org>
*
* This file is a part of Gnuk, a GnuPG USB Token implementation.
@ -73,12 +73,14 @@ verify_user_0 (uint8_t access, const uint8_t *pw, int buf_len, int pw_len_known,
if (ks_pw1 == NULL)
{
pw_len = strlen (OPENPGP_CARD_INITIAL_PW1);
const uint8_t *initial_pw;
salt = NULL;
salt_len = 0;
gpg_do_get_initial_pw_setting (0, &pw_len, &initial_pw);
if ((pw_len_known >= 0 && pw_len_known != pw_len)
|| buf_len < pw_len
|| strncmp ((const char *)pw, OPENPGP_CARD_INITIAL_PW1, pw_len))
|| memcmp (pw, initial_pw, pw_len))
goto failure;
}
else
@ -220,6 +222,7 @@ verify_admin_0 (const uint8_t *pw, int buf_len, int pw_len_known,
}
else
{
const uint8_t *initial_pw;
const uint8_t *ks_pw1 = gpg_do_read_simple (NR_DO_KEYSTRING_PW1);
if (ks_pw1 != NULL)
@ -237,13 +240,13 @@ verify_admin_0 (const uint8_t *pw, int buf_len, int pw_len_known,
return 0;
/*
* For the case of empty PW3 (with empty PW1), pass phrase
* should be OPENPGP_CARD_INITIAL_PW3
* For the case of empty PW3 (with empty PW1), passphrase is
* OPENPGP_CARD_INITIAL_PW3, or defined by KDF DO.
*/
pw_len = strlen (OPENPGP_CARD_INITIAL_PW3);
gpg_do_get_initial_pw_setting (1, &pw_len, &initial_pw);
if ((pw_len_known >=0 && pw_len_known != pw_len)
|| buf_len < pw_len
|| strncmp ((const char *)pw, OPENPGP_CARD_INITIAL_PW3, pw_len))
|| memcmp (pw, initial_pw, pw_len))
goto failure;
admin_authorized = BY_ADMIN;

View File

@ -296,7 +296,8 @@ int ecdh_decrypt_curve25519 (const uint8_t *input, uint8_t *output,
const uint8_t *gpg_do_read_simple (uint8_t);
void gpg_do_write_simple (uint8_t, const uint8_t *, int);
void gpg_increment_digital_signature_counter (void);
void gpg_do_get_initial_pw_setting (int is_pw3, int *r_len,
const uint8_t **r_p);
void fatal (uint8_t code) __attribute__ ((noreturn));
#define FATAL_FLASH 1

View File

@ -863,6 +863,34 @@ rw_kdf (uint16_t tag, int with_tag, const uint8_t *data, int len, int is_write)
}
}
void
gpg_do_get_initial_pw_setting (int is_pw3, int *r_len, const uint8_t **r_p)
{
const uint8_t *kdf_spec = gpg_do_read_simple (NR_DO_KDF);
if (kdf_spec)
{
*r_len = 32;
if (is_pw3)
*r_p = kdf_spec + 78;
else
*r_p = kdf_spec + 44;
}
else
{
if (is_pw3)
{
*r_len = strlen (OPENPGP_CARD_INITIAL_PW3);
*r_p = (const uint8_t *)OPENPGP_CARD_INITIAL_PW3;
}
else
{
*r_len = strlen (OPENPGP_CARD_INITIAL_PW1);
*r_p = (const uint8_t *)OPENPGP_CARD_INITIAL_PW1;
}
}
}
static int
proc_resetting_code (const uint8_t *data, int len)
{
@ -1155,6 +1183,8 @@ gpg_do_write_prvkey (enum kind_of_key kk, const uint8_t *key_data,
int pubkey_len;
uint8_t ks[KEYSTRING_MD_SIZE];
enum kind_of_key kk0;
int pw_len;
const uint8_t *initial_pw;
DEBUG_INFO ("Key import\r\n");
DEBUG_SHORT (prvkey_len);
@ -1212,8 +1242,8 @@ gpg_do_write_prvkey (enum kind_of_key kk, const uint8_t *key_data,
memcpy (pd->dek_encrypted_2, dek, DATA_ENCRYPTION_KEY_SIZE);
memcpy (pd->dek_encrypted_3, dek, DATA_ENCRYPTION_KEY_SIZE);
s2k (NULL, 0, (const uint8_t *)OPENPGP_CARD_INITIAL_PW1,
strlen (OPENPGP_CARD_INITIAL_PW1), ks);
gpg_do_get_initial_pw_setting (0, &pw_len, &initial_pw);
s2k (NULL, 0, initial_pw, pw_len, ks);
/* Handle existing keys and keystring DOs. */
gpg_do_write_simple (NR_DO_KEYSTRING_PW1, NULL, 0);
@ -2240,14 +2270,16 @@ gpg_do_keygen (uint8_t *buf)
if (kk == GPG_KEY_FOR_SIGNING)
{
const uint8_t *pw = (const uint8_t *)OPENPGP_CARD_INITIAL_PW1;
int pw_len;
const uint8_t *initial_pw;
uint8_t keystring[KEYSTRING_MD_SIZE];
/* GnuPG expects it's ready for signing. */
/* Don't call ac_reset_pso_cds here, but load the private key */
gpg_reset_digital_signature_counter ();
s2k (NULL, 0, pw, strlen (OPENPGP_CARD_INITIAL_PW1), keystring);
gpg_do_get_initial_pw_setting (0, &pw_len, &initial_pw);
s2k (NULL, 0, initial_pw, pw_len, keystring);
gpg_do_load_prvkey (GPG_KEY_FOR_SIGNING, BY_USER, keystring);
}
else

View File

@ -378,8 +378,10 @@ cmd_change_password (void)
newpw_len = len - pw_len;
if (newpw_len == 0 && admin_authorized == BY_ADMIN)
{
newpw_len = strlen (OPENPGP_CARD_INITIAL_PW3);
memcpy (newpw, OPENPGP_CARD_INITIAL_PW3, newpw_len);
const uint8_t *initial_pw;
gpg_do_get_initial_pw_setting (1, &newpw_len, &initial_pw);
memcpy (newpw, initial_pw, newpw_len);
newsalt_len = 0;
pw3_null = 1;
}