From b735c02ec21f397b068d45b8fbd614a8e6f17c3e Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Thu, 2 Nov 2017 10:59:17 +0900 Subject: [PATCH] Implement use of KDF data object. --- ChangeLog | 6 ++++++ src/ac.c | 17 ++++++++++------- src/gnuk.h | 3 ++- src/openpgp-do.c | 40 ++++++++++++++++++++++++++++++++++++---- src/openpgp.c | 6 ++++-- 5 files changed, 58 insertions(+), 14 deletions(-) diff --git a/ChangeLog b/ChangeLog index 859216c..673a76e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,6 +1,12 @@ 2017-11-02 NIIBE Yutaka * 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 diff --git a/src/ac.c b/src/ac.c index f5c2fb3..21bf244 100644 --- a/src/ac.c +++ b/src/ac.c @@ -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 * * 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; diff --git a/src/gnuk.h b/src/gnuk.h index 91cbf40..b10d538 100644 --- a/src/gnuk.h +++ b/src/gnuk.h @@ -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 diff --git a/src/openpgp-do.c b/src/openpgp-do.c index c886aa8..b78be72 100644 --- a/src/openpgp-do.c +++ b/src/openpgp-do.c @@ -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 diff --git a/src/openpgp.c b/src/openpgp.c index f0d8d7b..a26e05e 100644 --- a/src/openpgp.c +++ b/src/openpgp.c @@ -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; }