fix gnuk_put_binary

This commit is contained in:
NIIBE Yutaka
2012-06-05 11:18:41 +09:00
parent bfa4952f31
commit 37b1992f10
3 changed files with 56 additions and 55 deletions

View File

@@ -1,5 +1,12 @@
2012-06-05 Niibe Yutaka <gniibe@fsij.org>
Firmware update key handling.
* tool/gnuk_put_binary.py (GnukToken.cmd_get_response): Handle
larger data such as card holder certificate.
(GnukToken.cmd_write_binary): Bug fix for cert do write.
(GnukToken.cmd_read_binary): New.
(main): Support firmware update key.
Take advantage of the Thumb-2 "rbit" instruction.
* regnual/regnual.c (fetch): Reverse bits.
* src/usb_ctrl.c (rbit): New. Deleted reverse32.

View File

@@ -4,7 +4,7 @@
gnuk_put_binary.py - a tool to put binary to Gnuk Token
This tool is for importing certificate, updating random number, etc.
Copyright (C) 2011 Free Software Initiative of Japan
Copyright (C) 2011, 2012 Free Software Initiative of Japan
Author: NIIBE Yutaka <gniibe@fsij.org>
This file is a part of Gnuk, a GnuPG USB Token implementation.
@@ -44,11 +44,17 @@ class GnukToken(object):
self.connection = cardservice.connection
def cmd_get_response(self, expected_len):
apdu = [0x00, 0xc0, 0x00, 0x00, expected_len]
response, sw1, sw2 = self.connection.transmit(apdu)
if not (sw1 == 0x90 and sw2 == 0x00):
raise ValueError, ("%02x%02x" % (sw1, sw2))
return response
result = []
while True:
apdu = [0x00, 0xc0, 0x00, 0x00, expected_len]
response, sw1, sw2 = self.connection.transmit(apdu)
result += response
if sw1 == 0x90 and sw2 == 0x00:
return result
elif sw1 != 0x61:
raise ValueError, ("%02x%02x" % (sw1, sw2))
else:
expected_len = sw2
def cmd_verify(self, who, passwd):
apdu = [0x00, 0x20, 0x00, 0x80+who, len(passwd)] + s2l(passwd)
@@ -56,6 +62,15 @@ class GnukToken(object):
if not (sw1 == 0x90 and sw2 == 0x00):
raise ValueError, ("%02x%02x" % (sw1, sw2))
def cmd_read_binary(self, fileid):
apdu = [0x00, 0xb0, 0x80+fileid, 0x00]
response, sw1, sw2 = self.connection.transmit(apdu)
if sw1 == 0x61:
response = self.cmd_get_response(sw2)
elif not (sw1 == 0x90 and sw2 == 0x00):
raise ValueError, ("%02x%02x" % (sw1, sw2))
return response
def cmd_write_binary(self, fileid, data, is_update):
count = 0
data_len = len(data)
@@ -66,7 +81,7 @@ class GnukToken(object):
while count*256 < data_len:
if count == 0:
d = data[:256]
if len(d) <= 255:
if len(d) <= 255:
apdu = [0x00, ins, 0x80+fileid, 0x00, len(d)] + s2l(d)
else:
apdu0 = [0x10, ins, 0x80+fileid, 0x00, 255] + s2l(d[:255])
@@ -74,18 +89,18 @@ class GnukToken(object):
apdu = [0x00, ins, 0x80+fileid, 0x00, 1 ] + s2l(d[255:])
else:
d = data[256*count:256*(count+1)]
if len(d) <= 255:
if len(d) <= 255:
apdu = [0x00, ins, count, 0x00, len(d)] + s2l(d)
else:
apdu0 = [0x10, ins, count, 0x00, 255] + s2l(d[:255])
response, sw1, sw2 = self.connection.transmit(apdu0)
apdu = [0x00, ins, 0x80+fileid, 0x00, 1] + s2l(d[255:])
apdu = [0x00, ins, count, 0x00, 1] + s2l(d[255:])
response, sw1, sw2 = self.connection.transmit(apdu)
if not (sw1 == 0x90 and sw2 == 0x00):
if is_update:
raise ValueError, ("%02x%02x" % (sw1, sw2))
raise ValueError, ("update failure: %02x%02x" % (sw1, sw2))
else:
raise ValueError, ("%02x%02x" % (sw1, sw2))
raise ValueError, ("write failure: %02x%02x" % (sw1, sw2))
count += 1
def cmd_select_openpgp(self):
@@ -124,15 +139,17 @@ def main(fileid, is_update, data, passwd):
gnuk.cmd_verify(BY_ADMIN, passwd)
gnuk.cmd_write_binary(fileid, data, is_update)
gnuk.cmd_select_openpgp()
if fileid == 0:
gnuk.cmd_select_openpgp()
data_in_device = gnuk.cmd_get_data(0x00, 0x4f)
for d in data_in_device:
print "%02x" % d,
print
compare(data, data_in_device[8:])
elif fileid >= 1 and fileid <= 4:
data_in_device = gnuk.cmd_read_binary(fileid)
compare(data, data_in_device)
elif fileid == 5:
gnuk.cmd_select_openpgp()
data_in_device = gnuk.cmd_get_data(0x7f, 0x21)
compare(data, data_in_device)
@@ -167,6 +184,13 @@ if __name__ == '__main__':
exit(1)
print "Writing serial number"
data = binascii.unhexlify(serial_data_hex)
elif sys.argv[1] == '-k': # firmware update key
keyno = sys.argv[2]
fileid = 1 + int(keyno)
filename = sys.argv[3]
f = open(filename)
data = f.read()
f.close()
else:
fileid = 5 # Card holder certificate
filename = sys.argv[1]

View File

@@ -180,24 +180,28 @@ class gnuk_token:
raise ValueError, ("%02x%02x" % (sw[0], sw[1]))
return self.cmd_get_response(sw[1])
def cmd_write_binary(self, fileid, data):
def cmd_write_binary(self, fileid, data, is_update):
count = 0
data_len = len(data)
if is_update:
ins = 0xd6
else:
ins = 0xd0
while count*256 < data_len:
if count == 0:
if len(data) < 128:
cmd_data0 = iso7816_compose(0xd0, 0x80+fileid, 0x00, data[:128])
cmd_data0 = iso7816_compose(ins, 0x80+fileid, 0x00, data[:128])
cmd_data1 = None
else:
cmd_data0 = iso7816_compose(0xd0, 0x80+fileid, 0x00, data[:128], 0x10)
cmd_data1 = iso7816_compose(0xd0, 0x80+fileid, 0x00, data[128:256])
cmd_data0 = iso7816_compose(ins, 0x80+fileid, 0x00, data[:128], 0x10)
cmd_data1 = iso7816_compose(ins, 0x80+fileid, 0x00, data[128:256])
else:
if len(data[256*count:256*count+128]) < 128:
cmd_data0 = iso7816_compose(0xd0, count, 0x00, data[256*count:256*count+128])
cmd_data0 = iso7816_compose(ins, count, 0x00, data[256*count:256*count+128])
cmd_data1 = None
else:
cmd_data0 = iso7816_compose(0xd0, count, 0x00, data[256*count:256*count+128], 0x10)
cmd_data1 = iso7816_compose(0xd0, count, 0x00, data[256*count+128:256*(count+1)])
cmd_data0 = iso7816_compose(ins, count, 0x00, data[256*count:256*count+128], 0x10)
cmd_data1 = iso7816_compose(ins, count, 0x00, data[256*count+128:256*(count+1)])
sw = self.icc_send_cmd(cmd_data0)
if len(sw) != 2:
raise ValueError, "cmd_write_binary 0"
@@ -211,37 +215,6 @@ class gnuk_token:
raise ValueError, "cmd_write_binary 1"
count += 1
def cmd_update_binary(self, fileid, data):
count = 0
data_len = len(data)
while count*256 < data_len:
if count == 0:
if len(data) < 128:
cmd_data0 = iso7816_compose(0xd6, 0x80+fileid, 0x00, data[:128])
cmd_data1 = None
else:
cmd_data0 = iso7816_compose(0xd6, 0x80+fileid, 0x00, data[:128], 0x10)
cmd_data1 = iso7816_compose(0xd6, 0x80+fileid, 0x00, data[128:256])
else:
if len(data[256*count:256*count+128]) < 128:
cmd_data0 = iso7816_compose(0xd6, count, 0x00, data[256*count:256*count+128])
cmd_data1 = None
else:
cmd_data0 = iso7816_compose(0xd6, count, 0x00, data[256*count:256*count+128], 0x10)
cmd_data1 = iso7816_compose(0xd6, count, 0x00, data[256*count+128:256*(count+1)])
sw = self.icc_send_cmd(cmd_data0)
if len(sw) != 2:
raise ValueError, "cmd_update_binary 0"
if not (sw[0] == 0x90 and sw[1] == 0x00):
raise ValueError, "cmd_update_binary 0"
if cmd_data1:
sw = self.icc_send_cmd(cmd_data1)
if len(sw) != 2:
raise ValueError, "cmd_update_binary 1"
if not (sw[0] == 0x90 and sw[1] == 0x00):
raise ValueError, "cmd_update_binary 1"
count += 1
def cmd_select_openpgp(self):
cmd_data = iso7816_compose(0xa4, 0x04, 0x0c, "\xD2\x76\x00\x01\x24\x01")
sw = self.icc_send_cmd(cmd_data)
@@ -298,10 +271,7 @@ def main(fileid, is_update, data, passwd):
elif icc.icc_get_status() == 1:
icc.icc_power_on()
icc.cmd_verify(BY_ADMIN, passwd)
if is_update:
icc.cmd_update_binary(fileid, data)
else:
icc.cmd_write_binary(fileid, data)
icc.cmd_write_binary(fileid, data, is_update)
icc.cmd_select_openpgp()
if fileid == 0:
data_in_device = icc.cmd_get_data(0x00, 0x4f)