Exemple #1
0
def clear_screens(user_input: 'UserInput', window: 'TxWindow',
                  settings: 'Settings', queues: 'QueueDict') -> None:
    """Clear/reset screen of Source, Destination, and Networked Computer.

    Only send an unencrypted command to Networked Computer if traffic
    masking is disabled.

    With clear command, sending only the command header is enough.
    However, as reset command removes the ephemeral message log on
    Receiver Program, Transmitter Program must define the window to
    reset (in case, e.g., previous window selection command packet
    dropped, and active window state is inconsistent between the
    TCB programs).
    """
    clear = user_input.plaintext.split()[0] == CLEAR

    command = CLEAR_SCREEN if clear else RESET_SCREEN + window.uid
    queue_command(command, settings, queues)

    clear_screen()

    if not settings.traffic_masking:
        pt_cmd = UNENCRYPTED_SCREEN_CLEAR if clear else UNENCRYPTED_SCREEN_RESET
        packet = UNENCRYPTED_DATAGRAM_HEADER + pt_cmd
        queue_to_nc(packet, queues[RELAY_PACKET_QUEUE])

    if not clear:
        readline.clear_history()
        reset_terminal()
Exemple #2
0
    def new_password(cls, purpose: str = "master password") -> str:
        """Prompt the user to enter and confirm a new password."""
        password_1 = pwd_prompt(f"Enter a new {purpose}: ")

        if password_1 == GENERATE:
            pwd_bit_strength, password_1 = MasterKey.generate_master_password()

            m_print([
                f"Generated a {pwd_bit_strength}-bit password:"******"Write down this password and dispose of the copy once you remember it.",
                "Press <Enter> to continue."
            ],
                    manual_proceed=True,
                    box=True,
                    head=1,
                    tail=1)
            reset_terminal()

            password_2 = password_1
        else:
            password_2 = pwd_prompt(f"Confirm the {purpose}: ", repeat=True)

        if password_1 == password_2:
            return password_1

        m_print("Error: Passwords did not match. Try again.", head=1, tail=1)
        print_on_previous_line(delay=1, reps=7)
        return cls.new_password(purpose)
Exemple #3
0
def wipe(exit_queue: 'Queue[str]') -> None:
    """\
    Reset terminals, wipe all TFC user data on Destination Computer and
    power off the system.

    No effective RAM overwriting tool currently exists, so as long as
    Source and Destination Computers use FDE and DDR3 memory, recovery
    of user data becomes impossible very fast:
        https://www1.cs.fau.de/filepool/projects/coldboot/fares_coldboot.pdf
    """
    reset_terminal()
    exit_queue.put(WIPE)
Exemple #4
0
def wipe(gateway: 'Gateway', queues: 'QueueDict') -> None:
    """Reset terminal, wipe all user data and power off the system.

    No effective RAM overwriting tool currently exists, so as long as Source and
    Destination Computers use FDE and DDR3 memory, recovery of user data becomes
    impossible very fast:
        https://www1.cs.fau.de/filepool/projects/coldboot/fares_coldboot.pdf

    The queue is read by
        relay.onion.onion_service()
    """
    reset_terminal()
    race_condition_delay(gateway)
    queues[ONION_CLOSE_QUEUE].put(WIPE)
Exemple #5
0
def protect_kdk(kdk: bytes) -> None:
    """Prevent leak of KDK via terminal history / clipboard."""
    readline.clear_history()
    reset_terminal()
    root = tkinter.Tk()
    root.withdraw()

    try:
        if root.clipboard_get() == b58encode(kdk):  # type: ignore
            root.clipboard_clear()  # type: ignore
    except tkinter.TclError:
        pass

    root.destroy()
Exemple #6
0
def wipe(settings: 'Settings', queues: 'QueueDict',
         gateway: 'Gateway') -> None:
    """\
    Reset terminals, wipe all TFC user data from Source, Networked, and
    Destination Computer, and power all three systems off.

    The purpose of the wipe command is to provide additional protection
    against physical attackers, e.g. in situation where a dissident gets
    a knock on their door. By overwriting and deleting user data the
    program prevents access to encrypted databases. Additional security
    should be sought with full disk encryption (FDE).

    Unfortunately, no effective tool for overwriting RAM currently exists.
    However, as long as Source and Destination Computers use FDE and
    DDR3 memory, recovery of sensitive data becomes impossible very fast:
        https://www1.cs.fau.de/filepool/projects/coldboot/fares_coldboot.pdf
    """
    if not yes("Wipe all user data and power off systems?", abort=False):
        raise SoftError("Wipe command aborted.", head_clear=True)

    clear_screen()

    for q in [COMMAND_PACKET_QUEUE, RELAY_PACKET_QUEUE]:
        while queues[q].qsize() != 0:
            queues[q].get()

    queue_command(WIPE_USR_DATA, settings, queues)

    if not settings.traffic_masking:
        if settings.local_testing_mode:
            time.sleep(0.8)
            time.sleep(gateway.settings.data_diode_sockets * 2.2)
        else:
            time.sleep(gateway.settings.race_condition_delay)

    relay_command = UNENCRYPTED_DATAGRAM_HEADER + UNENCRYPTED_WIPE_COMMAND
    queue_to_nc(relay_command, queues[RELAY_PACKET_QUEUE])

    reset_terminal()
Exemple #7
0
def reset_windows(gateway: 'Gateway') -> None:
    """Reset Relay Program screen."""
    race_condition_delay(gateway)
    reset_terminal()
Exemple #8
0
def new_local_key(contact_list: 'ContactList', settings: 'Settings',
                  queues: 'QueueDict') -> None:
    """Run local key exchange protocol.

    Local key encrypts commands and data sent from Source Computer to
    user's Destination Computer. The key is delivered to Destination
    Computer in packet encrypted with an ephemeral, symmetric, key
    encryption key.

    The check-summed Base58 format key decryption key is typed to
    Receiver Program manually. This prevents local key leak in following
    scenarios:

        1. CT is intercepted by an adversary on compromised Networked
           Computer, but no visual eavesdropping takes place.

        2. CT is not intercepted by an adversary on Networked Computer,
           but visual eavesdropping records key decryption key.

        3. CT is delivered from Source Computer to Destination Computer
           directly (bypassing compromised Networked Computer), and
           visual eavesdropping records key decryption key.

    Once the correct key decryption key is entered to Receiver Program,
    it will display the 2-hexadecimal confirmation code generated by
    the Transmitter Program. The code will be entered back to
    Transmitter Program to confirm the user has successfully delivered
    the key decryption key.

    The protocol is completed with Transmitter Program sending
    LOCAL_KEY_RDY signal to the Receiver Program, that then moves to
    wait for public keys from contact.
    """
    try:
        if settings.traffic_masking and contact_list.has_local_contact():
            raise SoftError(
                "Error: Command is disabled during traffic masking.",
                head_clear=True)

        m_print("Local key setup", bold=True, head_clear=True, head=1, tail=1)

        if not contact_list.has_local_contact():
            time.sleep(0.5)

        key = csprng()
        hek = csprng()
        kek = csprng()
        c_code = os.urandom(CONFIRM_CODE_LENGTH)

        local_key_packet = LOCAL_KEY_DATAGRAM_HEADER + encrypt_and_sign(
            plaintext=key + hek + c_code, key=kek)

        deliver_local_key(local_key_packet, kek, c_code, settings, queues)

        # Add local contact to contact list database
        contact_list.add_contact(LOCAL_PUBKEY, LOCAL_NICK,
                                 blake2b(b58encode(kek).encode()),
                                 bytes(FINGERPRINT_LENGTH),
                                 KEX_STATUS_LOCAL_KEY, False, False, False)

        # Add local contact to keyset database
        queues[KEY_MANAGEMENT_QUEUE].put(
            (KDB_ADD_ENTRY_HEADER, LOCAL_PUBKEY, key, csprng(), hek, csprng()))

        # Notify Receiver Program that confirmation code was successfully entered
        queue_command(LOCAL_KEY_RDY, settings, queues)

        m_print("Successfully completed the local key exchange.",
                bold=True,
                tail_clear=True,
                delay=1,
                head=1)
        reset_terminal()

    except (EOFError, KeyboardInterrupt):
        raise SoftError("Local key setup aborted.",
                        tail_clear=True,
                        delay=1,
                        head=2)
Exemple #9
0
 def test_reset_terminal(self, oss):
     self.assertIsNone(reset_terminal())
     oss.assert_called_with(RESET)
Exemple #10
0
def reset_screen(win_uid: bytes, window_list: 'WindowList') -> None:
    """Reset window specified by the Transmitter Program."""
    window = window_list.get_window(win_uid)
    window.reset_window()
    reset_terminal()