diff options
author | Werner Koch <[email protected]> | 2018-03-27 06:48:00 +0000 |
---|---|---|
committer | Werner Koch <[email protected]> | 2018-03-27 06:48:00 +0000 |
commit | d4dc4245bf0221d2db4118718fc2528ecf43b97b (patch) | |
tree | 5912abc9b9ba056a882bcd933105ba4dde73c560 /g10/card-util.c | |
parent | Change license of argparse.c back to LGPLv2.1 (diff) | |
parent | agent: Make the request origin a part of the cache items. (diff) | |
download | gnupg-d4dc4245bf0221d2db4118718fc2528ecf43b97b.tar.gz gnupg-d4dc4245bf0221d2db4118718fc2528ecf43b97b.zip |
Merge branch 'STABLE-BRANCH-2-2' into master
Diffstat (limited to 'g10/card-util.c')
-rw-r--r-- | g10/card-util.c | 132 |
1 files changed, 125 insertions, 7 deletions
diff --git a/g10/card-util.c b/g10/card-util.c index f8a1bb831..9b99751ee 100644 --- a/g10/card-util.c +++ b/g10/card-util.c @@ -659,7 +659,7 @@ current_card_status (ctrl_t ctrl, estream_t fp, /* Print all available information for specific card with SERIALNO. Print all available information for current card when SERIALNO is NULL. - Or print llfor all cards when SERIALNO is "all". */ + Or print for all cards when SERIALNO is "all". */ void card_status (ctrl_t ctrl, estream_t fp, const char *serialno) { @@ -1797,6 +1797,7 @@ factory_reset (void) scd apdu 00 20 00 83 08 40 40 40 40 40 40 40 40 scd apdu 00 e6 00 00 scd apdu 00 44 00 00 + scd reset /echo Card has been reset to factory defaults but tries to find out something about the card first. @@ -1809,7 +1810,7 @@ factory_reset (void) else if (err) { log_error (_("OpenPGP card not available: %s\n"), gpg_strerror (err)); - return; + goto leave; } if (!termstate) @@ -1859,10 +1860,16 @@ factory_reset (void) command because there is no machinery in scdaemon to catch the verify command and ask for the PIN when the "APDU" command is used. */ + /* Here, the length of dummy wrong PIN is 32-byte, also + supporting authentication with KDF DO. */ for (i=0; i < 4; i++) - send_apdu ("00200081084040404040404040", "VERIFY", 0xffff); + send_apdu ("0020008120" + "40404040404040404040404040404040" + "40404040404040404040404040404040", "VERIFY", 0xffff); for (i=0; i < 4; i++) - send_apdu ("00200083084040404040404040", "VERIFY", 0xffff); + send_apdu ("0020008320" + "40404040404040404040404040404040" + "40404040404040404040404040404040", "VERIFY", 0xffff); /* Send terminate datafile command. */ err = send_apdu ("00e60000", "TERMINATE DF", 0x6985); @@ -1878,8 +1885,16 @@ factory_reset (void) /* Finally we reset the card reader once more. */ err = send_apdu (NULL, "RESET", 0); - if (err) - goto leave; + + /* Then, connect the card again. */ + if (!err) + { + char *serialno0; + + err = agent_scd_serialno (&serialno0, NULL); + if (!err) + xfree (serialno0); + } leave: xfree (answer); @@ -1887,6 +1902,104 @@ factory_reset (void) } +#define USER_PIN_DEFAULT "123456" +#define ADMIN_PIN_DEFAULT "12345678" +#define KDF_DATA_LENGTH 110 + +/* Generate KDF data. */ +static gpg_error_t +gen_kdf_data (unsigned char *data) +{ + const unsigned char h0[] = { 0x81, 0x01, 0x03, + 0x82, 0x01, 0x08, + 0x83, 0x04 }; + const unsigned char h1[] = { 0x84, 0x08 }; + const unsigned char h2[] = { 0x85, 0x08 }; + const unsigned char h3[] = { 0x86, 0x08 }; + const unsigned char h4[] = { 0x87, 0x20 }; + const unsigned char h5[] = { 0x88, 0x20 }; + unsigned char *p, *salt_user, *salt_admin; + unsigned char s2k_char; + unsigned int iterations; + unsigned char count_4byte[4]; + gpg_error_t err = 0; + + p = data; + + s2k_char = encode_s2k_iterations (0); + iterations = S2K_DECODE_COUNT (s2k_char); + count_4byte[0] = (iterations >> 24) & 0xff; + count_4byte[1] = (iterations >> 16) & 0xff; + count_4byte[2] = (iterations >> 8) & 0xff; + count_4byte[3] = (iterations & 0xff); + + memcpy (p, h0, sizeof h0); + p += sizeof h0; + memcpy (p, count_4byte, sizeof count_4byte); + p += sizeof count_4byte; + memcpy (p, h1, sizeof h1); + salt_user = (p += sizeof h1); + gcry_randomize (p, 8, GCRY_STRONG_RANDOM); + p += 8; + memcpy (p, h2, sizeof h2); + p += sizeof h2; + gcry_randomize (p, 8, GCRY_STRONG_RANDOM); + 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); + p += sizeof h4; + err = gcry_kdf_derive (USER_PIN_DEFAULT, strlen (USER_PIN_DEFAULT), + GCRY_KDF_ITERSALTED_S2K, DIGEST_ALGO_SHA256, + salt_user, 8, iterations, 32, p); + p += 32; + if (!err) + { + memcpy (p, h5, sizeof h5); + p += sizeof h5; + err = gcry_kdf_derive (ADMIN_PIN_DEFAULT, strlen (ADMIN_PIN_DEFAULT), + GCRY_KDF_ITERSALTED_S2K, DIGEST_ALGO_SHA256, + salt_admin, 8, iterations, 32, p); + } + + return err; +} + +/* Setup KDF data object which is used for PIN authentication. */ +static void +kdf_setup (void) +{ + struct agent_card_info_s info; + gpg_error_t err; + unsigned char kdf_data[KDF_DATA_LENGTH]; + + memset (&info, 0, sizeof info); + + err = agent_scd_getattr ("EXTCAP", &info); + if (err) + { + log_error (_("error getting card info: %s\n"), gpg_strerror (err)); + return; + } + + if (!info.extcap.kdf) + { + log_error (_("This command is not supported by this card\n")); + goto leave; + } + + if (!(err = gen_kdf_data (kdf_data)) + && !(err = agent_scd_setattr ("KDF", kdf_data, KDF_DATA_LENGTH, NULL))) + err = agent_scd_getattr ("KDF", &info); + + if (err) + log_error (_("error for setup KDF: %s\n"), gpg_strerror (err)); + + leave: + agent_release_card_info (&info); +} /* Data used by the command parser. This needs to be outside of the function scope to allow readline based command completion. */ @@ -1896,7 +2009,7 @@ enum cmdids cmdQUIT, cmdADMIN, cmdHELP, cmdLIST, cmdDEBUG, cmdVERIFY, cmdNAME, cmdURL, cmdFETCH, cmdLOGIN, cmdLANG, cmdSEX, cmdCAFPR, cmdFORCESIG, cmdGENERATE, cmdPASSWD, cmdPRIVATEDO, cmdWRITECERT, - cmdREADCERT, cmdUNBLOCK, cmdFACTORYRESET, + cmdREADCERT, cmdUNBLOCK, cmdFACTORYRESET, cmdKDFSETUP, cmdINVCMD }; @@ -1930,6 +2043,7 @@ static struct { "verify" , cmdVERIFY, 0, N_("verify the PIN and list all data")}, { "unblock" , cmdUNBLOCK,0, N_("unblock the PIN using a Reset Code") }, { "factory-reset", cmdFACTORYRESET, 1, N_("destroy all keys and data")}, + { "kdf-setup", cmdKDFSETUP, 1, N_("setup KDF for PIN authentication")}, /* Note, that we do not announce these command yet. */ { "privatedo", cmdPRIVATEDO, 0, NULL }, { "readcert", cmdREADCERT, 0, NULL }, @@ -2213,6 +2327,10 @@ card_edit (ctrl_t ctrl, strlist_t commands) factory_reset (); break; + case cmdKDFSETUP: + kdf_setup (); + break; + case cmdQUIT: goto leave; |