external authenticate incompatible change to SHA256

This commit is contained in:
NIIBE Yutaka
2012-06-16 14:33:22 +09:00
parent e0282629e3
commit c61a63dbb6
6 changed files with 50 additions and 33 deletions

View File

@@ -1,3 +1,12 @@
2012-06-16 Niibe Yutaka <gniibe@fsij.org>
Use SHA256 format for "external authenticate".
* tool/gnuk_upgrade.py (gpg_sign): SHA256 sign by "SCD PKAUTH".
(main): Not specify keygrip, but always use key for authentication.
* src/call-rsa.c (rsa_verify): It is SHA256 format (was: SHA1).
* src/openpgp.c (cmd_get_challenge): Don't add chip-id prefix.
(cmd_external_authenticate): Likewise.
2012-06-15 Niibe Yutaka <gniibe@fsij.org>
* src/random.c (random_bytes_free): Clear out random bytes.

11
NEWS
View File

@@ -5,14 +5,19 @@ Gnuk NEWS - User visible changes
Released 2012-XX-XX, by NIIBE Yutaka
** Key generation feature added
Finally, key generation is supported. Note that it is very slow. It
will take a few minutes (or more) to generate two or three keys, when
you are unlucky.
Finally, key generation is supported. Note that it may be very slow.
It will take a few minutes (or more) to generate two or three keys,
when you are unlucky.
** DnD pinentry support is deprecated
Once, DnD pinentry was considered a great feature, but it found that
it is difficult to remember moves of folders.
** gnuk_upgrade.py assumes using another token for authentication
Use of another token for authentication is assumed now. This is
incompatible change. Note that when you upgrade a token of version
0.19 to 0.20 (or later), you need gnuk_upgrade.py of version 0.19.
** KDF (Key Derivation Function) is now SHA-256
Keystring is now computed by SHA-256 (it was SHA1 before).

View File

@@ -8,7 +8,6 @@ Note that updating firmware, all data objects and keys will be
removed. There is _no way_ to preserve those data.
Preparation
===========
@@ -96,9 +95,9 @@ Then, we can put the data of public key into token by::
Invoking firmware update
========================
We specify the keygrip to authenticate, reGNUal binary, and Gnuk binary.
We specify reGNUal binary and Gnuk binary.
$ ../tool/gnuk_upgrade.py 5D6C89682D07CCFC034AF508420BF2276D8018ED ../regnual/regnual.bin gnuk.bin
$ ../tool/gnuk_upgrade.py ../regnual/regnual.bin gnuk.bin
Two or more tokens
@@ -107,9 +106,9 @@ Two or more tokens
Currently, GnuPG doesn't support multiple devices connected to the
host.
In order to update the firmware of a token TARGET, we use GnuPG to
authenticate with public key. If it is on another token AUTH, it is
somewhat complicated.
In order to update the firmware of a TARGET token, we use GnuPG to
authenticate with public key. It is assumed that you have another
AUTH token for this. This situation is somewhat complicated.
What I do is:
(1) Don't run PC/SC daemon::
@@ -120,9 +119,14 @@ What I do is:
$ killall -9 scdaemon
(3) Connect the token of AUTH, and use it::
(3) Insert the AUTH token to USB, and use it::
$ gpg --card-status
(4) Connect TARGET, and invoke gnuk_update.py
(4) Insert the TARGET token to USB (after scdaemon communicates AUTH
token), and invoke gnuk_upgrade.py.
In this situation, gnuk_upgrade.py tries to connect one of tokens,
but a connection to the AUTH token will fail because scdaemon is
connecting to that device, and will be expected to connect to the
TARGET token succesufully, instead.
--

View File

@@ -196,7 +196,7 @@ rsa_verify (const uint8_t *pubkey, const uint8_t *hash, const uint8_t *sig)
DEBUG_INFO ("RSA verify...");
r = rsa_pkcs1_verify (&rsa_ctx, RSA_PUBLIC, SIG_RSA_SHA1, 20, hash, sig);
r = rsa_pkcs1_verify (&rsa_ctx, RSA_PUBLIC, SIG_RSA_SHA256, 32, hash, sig);
rsa_free (&rsa_ctx);
if (r < 0)

View File

@@ -50,7 +50,7 @@
#define INS_PUT_DATA 0xda
#define INS_PUT_DATA_ODD 0xdb /* For key import */
#define CHALLENGE_LEN 16
#define CHALLENGE_LEN 32
static const uint8_t *challenge; /* Random bytes */
static const uint8_t
@@ -938,9 +938,9 @@ cmd_external_authenticate (void)
{
const uint8_t *pubkey;
const uint8_t *signature = apdu.cmd_apdu_data;
uint8_t *hash = apdu.cmd_apdu_data + 256;
int len = apdu.cmd_apdu_data_len;
uint8_t keyno = P2 (apdu);
int r;
DEBUG_INFO (" - EXTERNAL AUTHENTICATE\r\n");
@@ -958,13 +958,12 @@ cmd_external_authenticate (void)
GPG_CONDITION_NOT_SATISFIED ();
return;
}
memcpy (hash, unique_device_id (), 4);
memcpy (hash+4, challenge, CHALLENGE_LEN);
r = rsa_verify (pubkey, challenge, signature);
random_bytes_free (challenge);
challenge = NULL;
if (rsa_verify (pubkey, hash, signature) < 0)
if (r < 0)
{
GPG_SECURITY_FAILURE ();
return;
@@ -984,9 +983,8 @@ cmd_get_challenge (void)
random_bytes_free (challenge);
challenge = random_bytes_get ();
memcpy (res_APDU, unique_device_id (), 4);
memcpy (res_APDU+4, challenge, CHALLENGE_LEN);
res_APDU_size = CHALLENGE_LEN + 4;
memcpy (res_APDU, challenge, CHALLENGE_LEN);
res_APDU_size = CHALLENGE_LEN;
GPG_SUCCESS ();
DEBUG_INFO ("GET CHALLENGE done.\r\n");
}

View File

@@ -389,11 +389,13 @@ def to_string(t):
from subprocess import check_output
def gpg_sign(keygrip, hash):
SHA256_OID_PREFIX="3031300d060960864801650304020105000420"
def gpg_sign(hash):
result = check_output(["gpg-connect-agent",
"SIGKEY %s" % keygrip,
"SETHASH --hash=sha1 %s" % hash,
"PKSIGN", "/bye"])
"SCD SETDATA " + SHA256_OID_PREFIX + hash,
"SCD PKAUTH OPENPGP.3",
"/bye"])
signed = ""
while True:
i = result.find('%')
@@ -405,8 +407,8 @@ def gpg_sign(keygrip, hash):
signed += chr(int(hex_str,16))
result = result[i+3:]
pos = signed.index("D (7:sig-val(3:rsa(1:s256:") + 26
signed = signed[pos:-7]
pos = signed.index("D ") + 2
signed = signed[pos:-4] # \nOK\n
if len(signed) != 256:
raise ValueError, binascii.hexlify(signed)
return signed
@@ -418,7 +420,7 @@ def crc32(bytestr):
crc = binascii.crc32(bytestr)
return UNSIGNED(crc)
def main(keygrip, data_regnual, data_upgrade):
def main(data_regnual, data_upgrade):
l = len(data_regnual)
if (l & 0x03) != 0:
data_regnual = data_regnual.ljust(l + 4 - (l & 0x03), chr(0))
@@ -440,7 +442,7 @@ def main(keygrip, data_regnual, data_upgrade):
icc.icc_power_on()
icc.cmd_select_openpgp()
challenge = icc.cmd_get_challenge()
signed = gpg_sign(keygrip, binascii.hexlify(to_string(challenge)))
signed = gpg_sign(binascii.hexlify(to_string(challenge)))
icc.cmd_external_authenticate(signed)
icc.stop_gnuk()
mem_info = icc.mem_info()
@@ -477,9 +479,8 @@ def main(keygrip, data_regnual, data_upgrade):
if __name__ == '__main__':
keygrip = sys.argv[1]
filename_regnual = sys.argv[2]
filename_upgrade = sys.argv[3]
filename_regnual = sys.argv[1]
filename_upgrade = sys.argv[2]
f = open(filename_regnual)
data_regnual = f.read()
f.close()
@@ -488,4 +489,4 @@ if __name__ == '__main__':
data_upgrade = f.read()
f.close()
print "%s: %d" % (filename_upgrade, len(data_upgrade))
main(keygrip, data_regnual, data_upgrade[4096:])
main(data_regnual, data_upgrade[4096:])