Example #1
0
def set_identity(identity):
    """set given identity (one of: 0, 1, 2)"""
    if not identity.isdigit():
        print("identity number must be a digit")
        sys.exit(1)
    identity = int(identity)
    if identity < 0 or identity > 2:
        print("identity must be 0, 1 or 2")
        sys.exit(1)
    print(f"Trying to set identity to {identity}")
    for x in range(3):
        try:
            gnuk = get_gnuk_device()
            gnuk.cmd_select_openpgp()
            try:
                gnuk.cmd_set_identity(identity)
            except USBError:
                print("device has reset, and should now have the new identity")
                sys.exit(0)

        except ValueError as e:
            if 'No ICC present' in str(e):
                print("Could not connect to device, trying to close scdaemon")
                result = check_output(
                    ["gpg-connect-agent", "SCD KILLSCD", "SCD BYE",
                     "/bye"])  # gpgconf --kill all might be better?
                sleep(3)
            else:
                print('*** Found error: {}'.format(str(e)))
Example #2
0
def set_identity(identity):
    """set given identity (one of: 0, 1, 2)"""
    if not identity.isdigit():
        local_critical("identity number must be a digit")

    identity = int(identity)
    if identity < 0 or identity > 2:
        local_print("identity must be 0, 1 or 2")

    local_print(f"Setting identity to {identity}")
    for x in range(3):
        try:
            gnuk = get_gnuk_device()
            gnuk.cmd_select_openpgp()
            try:
                gnuk.cmd_set_identity(identity)
            except USBError:
                local_print(f"reset done - now active identity: {identity}")
                break

        except ValueError as e:
            if "No ICC present" in str(e):
                local_print("Could not connect to device, trying to close scdaemon")
                result = check_output(["gpg-connect-agent",
                                       "SCD KILLSCD", "SCD BYE",
                                       "/bye"])  # gpgconf --kill all might be better?
                sleep(3)
            else:
                local_critical(e)
        except Exception as e:
            local_critical(e)
Example #3
0
def show_kdf_details(passwd):
    gnuk = None
    try:
        gnuk = get_gnuk_device(logger=logger, verbose=True)
    except ValueError as e:
        local_print("Connection error", 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:
                local_print("Error getting KDF", e)
        else:
            print("Provide password to calculate final hash")
Example #4
0
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')
Example #5
0
def main(wait_e,
         keyno,
         passwd,
         data_regnual,
         data_upgrade,
         skip_bootloader,
         verbosity=0):
    reg = None

    # @todo: this is constantly used: how about a consistent/generic solution?
    conn_retries = 3

    for i in range(conn_retries):
        if reg is not None:
            break

        local_print(".", end="", flush=True)
        time.sleep(1)

        for dev in gnuk_devices_by_vidpid():
            try:
                reg = regnual(dev)
                if dev.filename:
                    local_print(f"Device: {dev.filename}")
                reg.set_logger(logger)
                break
            except Exception as e:
                if str(e) != "Wrong interface class":
                    local_print(e)

    if reg is None and not skip_bootloader:
        local_print("", "Starting bootloader upload procedure")

        _l = len(data_regnual)
        if (_l & 0x03) != 0:
            data_regnual = data_regnual.ljust(_l + 4 - (_l & 0x03), chr(0))
        crc32code = crc32(data_regnual)

        # @todo: use global verbosity
        if verbosity:
            local_print("CRC32: %04x\n" % crc32code)
        data_regnual += pack("<I", crc32code)

        rsa_key = rsa.read_key_from_list(rsa_key_data)
        rsa_raw_pubkey = rsa.get_raw_pubkey(rsa_key)

        gnuk = get_gnuk_device(logger=logger)
        gnuk.cmd_select_openpgp()
        local_print("Connected to the device")

        # Compute passwd data
        try:
            kdf_data = gnuk.cmd_get_data(0x00, 0xF9).tobytes()
        except Exception as e:
            local_print("Note: KDF DO not found", e)
            kdf_data = b""

        if kdf_data == b"":
            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)

            salt = salt_admin if salt_admin else salt_user
            passwd_data = kdf_calc(passwd, salt, iters)

        # And authenticate with the passwd data
        gnuk.cmd_verify(BY_ADMIN, passwd_data)
        gnuk.cmd_write_binary(1 + keyno, rsa_raw_pubkey, False)

        gnuk.cmd_select_openpgp()
        challenge = gnuk.cmd_get_challenge().tobytes()
        digestinfo = binascii.unhexlify(SHA256_OID_PREFIX) + challenge
        signed = rsa.compute_signature(rsa_key, digestinfo)
        signed_bytes = rsa.integer_to_bytes_256(signed)
        gnuk.cmd_external_authenticate(keyno, signed_bytes)
        gnuk.stop_gnuk()

        mem_info = gnuk.mem_info()
        # @todo: use global verbosity
        if verbosity:
            local_print("%08x:%08x" % mem_info)

        local_print(
            "Running update!",
            "Do NOT remove the device from the USB slot, until further notice",
            "Downloading flash upgrade program...",
        )

        gnuk.download(
            mem_info[0],
            data_regnual,
            progress_func=progress_func,
            verbose=verbosity == 2,
        )

        local_print("Executing flash upgrade...")

        for i in range(conn_retries):
            time.sleep(1.5 * (i + 1))
            try:
                gnuk.execute(mem_info[0] + len(data_regnual) - 4)
                break
            except Exception as e:
                local_print(f"failed - trying again - retry: {i+1}", e)
                if i == conn_retries - 1:
                    raise e
                continue

        time.sleep(3)
        gnuk.reset_device()

        del gnuk
        gnuk = None

    if reg is None:
        local_print("Waiting for device to appear:")
        local_print(f"  Wait {wait_e} second{'s' if wait_e > 1 else ''}...",
                    end="")

        for i in range(wait_e):
            if reg is not None:
                break

            local_print(".", end="", flush=True)
            time.sleep(1)

            for dev in gnuk_devices_by_vidpid():
                try:
                    reg = regnual(dev)
                    if dev.filename:
                        local_print("Device: {dev.filename}")
                    break
                except Exception as e:
                    local_print(f"failed - trying again - retry: {i+1}", e)
                    # @todo: log exception to file: e

        local_print("", "")
        if reg is None:
            # @todo: replace with proper Exception
            raise RuntimeWarning("device not found - exiting")

    # Then, send upgrade program...
    mem_info = reg.mem_info()

    # @todo: use global verbosity
    if verbosity:
        local_print("%08x:%08x" % mem_info)

    local_print("Downloading the program")
    reg.download(mem_info[0],
                 data_upgrade,
                 progress_func=progress_func,
                 verbose=verbosity == 2)

    local_print("Protecting device")
    reg.protect()

    local_print("Finish flashing")
    reg.finish()

    local_print("Resetting device")
    reg.reset_device()

    local_print(
        "Update procedure finished. Device could be removed from USB slot.",
        "")

    return 0