1
0
Fork 0
mirror of git://git.gnupg.org/gnupg.git synced 2025-07-02 22:46:30 +02:00

Merge branch 'STABLE-BRANCH-2-2' into master

This commit is contained in:
Werner Koch 2018-03-27 08:48:00 +02:00
commit d4dc4245bf
No known key found for this signature in database
GPG key ID: E3FDFF218E45B72B
36 changed files with 516 additions and 135 deletions

View file

@ -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;