diff --git a/pynitrokey/cli/start.py b/pynitrokey/cli/start.py index 6eb0f39d..7a3abb48 100644 --- a/pynitrokey/cli/start.py +++ b/pynitrokey/cli/start.py @@ -17,7 +17,7 @@ from pynitrokey.start.usb_strings import get_devices as get_devices_strings from pynitrokey.start.upgrade_by_passwd import validate_gnuk, validate_regnual, logger, \ - start_update, DEFAULT_WAIT_FOR_REENUMERATION, DEFAULT_PW3, IS_LINUX + start_update, DEFAULT_WAIT_FOR_REENUMERATION, DEFAULT_PW3, IS_LINUX, show_kdf_details from pynitrokey.start.threaded_log import ThreadLog from usb.core import USBError @@ -112,9 +112,18 @@ def update(regnual, gnuk, default_password, password, wait_e, keyno, verbose, ye start_update(*args) +@click.command() +@click.option( + '--passwd', default='', help='password' +) +def kdf_details(passwd): + return show_kdf_details(passwd) + + start.add_command(list) start.add_command(set_identity) start.add_command(update) +start.add_command(kdf_details) # start.add_command(rng) # start.add_command(reboot) # rng.add_command(hexbytes) diff --git a/pynitrokey/start/gnuk_token.py b/pynitrokey/start/gnuk_token.py index bea66283..b92643da 100644 --- a/pynitrokey/start/gnuk_token.py +++ b/pynitrokey/start/gnuk_token.py @@ -27,6 +27,8 @@ from array import array # Possible Gnuk Token products +from pynitrokey.start.usb_strings import get_dict_for_device + USB_PRODUCT_LIST=[ { 'vendor' : 0x234b, 'product' : 0x0000 }, # FSIJ Gnuk Token { 'vendor' : 0x20a0, 'product' : 0x4211 }, # Nitrokey Start @@ -661,9 +663,11 @@ def get_gnuk_device(verbose=True, logger: logging.Logger=None): if logger: logger.debug('{} {} {}'.format(dev.filename, config.value, intf.interfaceNumber)) if verbose: - print("Device: %s" % dev.filename) - print("Configuration: %d" % config.value) - print("Interface: %d" % intf.interfaceNumber) + try: + d = get_dict_for_device(dev) + print(f'Device: {d["Product"]} {d["Serial"]}') + except: + print(f'Device: name: "{dev.filename}", c/i: {config.value}/{intf.interfaceNumber}') break except: pass diff --git a/pynitrokey/start/upgrade_by_passwd.py b/pynitrokey/start/upgrade_by_passwd.py index 4b4f74cf..4c978568 100755 --- a/pynitrokey/start/upgrade_by_passwd.py +++ b/pynitrokey/start/upgrade_by_passwd.py @@ -25,6 +25,7 @@ along with this program. If not, see . """ import tempfile +from pprint import pprint IMPORT_ERROR_HELP = """ Some required modules are missing from this environment. @@ -352,6 +353,53 @@ def download_file_or_exit(url): return firmware_data +def show_kdf_details(passwd): + gnuk = None + try: + gnuk = get_gnuk_device(logger=logger, verbose=True) + except ValueError as e: + if 'No ICC present' in str(e): + print('Cannot connect to device. Closing other open connections.') + kill_smartcard_services() + return + else: + raise + gnuk.cmd_select_openpgp() + # Compute passwd data + try: + kdf_data = gnuk.cmd_get_data(0x00, 0xf9).tobytes() + except: + kdf_data = b"" + if kdf_data == b"": + print('KDF not set') + # passwd_data = passwd.encode('UTF-8') + else: + algo, subalgo, iters, salt_user, salt_reset, salt_admin, \ + hash_user, hash_admin = parse_kdf_data(kdf_data) + if salt_admin: + salt = salt_admin + else: + salt = salt_user + d = { + 'algo': algo, + 'subalgo': subalgo, + 'iters': iters, + 'salt_user': binascii.b2a_hex(salt_user), + 'salt_reset': binascii.b2a_hex(salt_reset), + 'salt_admin': binascii.b2a_hex(salt_admin), + 'hash_user': binascii.b2a_hex(hash_user), + 'hash_admin': binascii.b2a_hex(hash_admin), + } + pprint(d, width=100) + if passwd: + try: + passwd_data = kdf_calc(passwd, salt, iters) + print(f'passwd_data: {binascii.b2a_hex(passwd_data)}') + except ValueError as e: + print(str(e)) + else: + print('Provide password to calculate final hash') + def start_update(regnual, gnuk, default_password, password, wait_e, keyno, verbose, yes, skip_bootloader, green_led):