aboutsummaryrefslogtreecommitdiffstats
path: root/scd/app-openpgp.c
diff options
context:
space:
mode:
authorNIIBE Yutaka <[email protected]>2018-03-30 03:48:04 +0000
committerNIIBE Yutaka <[email protected]>2018-03-30 03:48:04 +0000
commit0c097575a9cd923f648fb5bb695893d46400c3ad (patch)
treebe4d7beaf86b965ea4102285510104e85fc52d8a /scd/app-openpgp.c
parentg10: Add "key-attr" command for --card-edit. (diff)
downloadgnupg-0c097575a9cd923f648fb5bb695893d46400c3ad.tar.gz
gnupg-0c097575a9cd923f648fb5bb695893d46400c3ad.zip
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 <[email protected]>
Diffstat (limited to 'scd/app-openpgp.c')
-rw-r--r--scd/app-openpgp.c29
1 files changed, 22 insertions, 7 deletions
diff --git a/scd/app-openpgp.c b/scd/app-openpgp.c
index 7bbec03ac..ab57d90e6 100644
--- a/scd/app-openpgp.c
+++ b/scd/app-openpgp.c
@@ -2061,6 +2061,9 @@ get_prompt_info (app_t app, int chvno, unsigned long sigcount, int remaining)
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
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)
{
gpg_error_t err = 0;
- void *relptr;
+ void *relptr = NULL;
unsigned char *buffer;
size_t buflen;
if (app->app_local->extcap.kdf_do
&& (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;
char dek[32];
+ int salt_index;
- salt = &buffer[(chvno==3 ? 34 : (chvno==0 ? 24 : 14))];
s2k_count = (((unsigned int)buffer[8] << 24)
| (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),
GCRY_KDF_ITERSALTED_S2K,
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);
wipememory (dek, *r_pinlen);
}
-
- xfree (relptr);
- }
+ }
else
*r_pinlen = strlen (pinvalue);
+ leave:
+ xfree (relptr);
return err;
}