예제 #1
0
    def __init__(self,
                 operation:  str,
                 local_test: bool,
                 dd_sockets: bool,
                 qubes:      bool,
                 ) -> None:
        """Create a new Gateway object."""
        self.settings   = GatewaySettings(operation, local_test, dd_sockets, qubes)
        self.tx_serial  = None  # type: Optional[serial.Serial]
        self.rx_serial  = None  # type: Optional[serial.Serial]
        self.rx_socket  = None  # type: Optional[multiprocessing.connection.Connection]
        self.tx_socket  = None  # type: Optional[multiprocessing.connection.Connection]

        # Initialize Reed-Solomon erasure code handler
        self.rs = RSCodec(2 * self.settings.session_serial_error_correction)

        # Set True when the serial interface is initially found so that
        # further interface searches know to announce disconnection.
        self.init_found = False

        if self.settings.local_testing_mode:
            if self.settings.software_operation in [TX, NC]:
                self.client_establish_socket()
            if self.settings.software_operation in [NC, RX]:
                self.server_establish_socket()
        elif not self.settings.qubes:
            self.establish_serial()
예제 #2
0
def receiver_loop(settings: 'Settings', queues: Dict[bytes, 'Queue']) -> None:
    """Decode and queue received packets."""
    rs       = RSCodec(2 * settings.session_ec_ratio)
    gw_queue = queues[GATEWAY_QUEUE]

    while True:
        try:
            if gw_queue.empty():
                time.sleep(0.001)

            packet = gw_queue.get()
            ts     = datetime.datetime.now()

            try:
                packet = bytes(rs.decode(bytearray(packet)))
            except ReedSolomonError:
                box_print(["Warning! Failed to correct errors in received packet."], head=1, tail=1)
                continue

            p_header = packet[:1]
            if p_header in [PUBLIC_KEY_PACKET_HEADER, MESSAGE_PACKET_HEADER,
                             LOCAL_KEY_PACKET_HEADER, COMMAND_PACKET_HEADER,
                             IMPORTED_FILE_CT_HEADER]:
                queues[p_header].put((ts, packet))

        except (KeyboardInterrupt, EOFError):
            pass
예제 #3
0
    def test_prim_fcr_long(self) -> None:
        nn          = 48
        kk          = 34
        tt          = nn - kk
        rs          = RSCodec(tt, fcr=120, prim=0x187)
        hex_enc_msg = ('08faa123555555c000000354064432c0280e1b4d090cfc04'
                       '887400000003500000000e1985ff9c6b33066ca9f43d12e8')
        strf        = str
        enc_msg     = bytearray.fromhex(strf(hex_enc_msg))
        dec_msg     = enc_msg[:kk]
        tem         = rs.encode(dec_msg)
        self.assertEqual(enc_msg, tem, msg="encoded does not match expected")

        tdm, rtem = rs.decode(tem)
        self.assertEqual(tdm, dec_msg, msg="decoded does not match original")
        self.assertEqual(rtem, tem,    msg="decoded mesecc does not match original")

        tem1    = bytearray(tem)
        num_errs = tt >> 1
        for i in sample(range(nn), num_errs):
            tem1[i] ^= 0xff
        tdm, rtem = rs.decode(tem1)
        self.assertEqual(tdm, dec_msg, msg="decoded with errors does not match original")
        self.assertEqual(rtem, tem,    msg="decoded mesecc with errors does not match original")

        tem1     = bytearray(tem)
        num_errs += 1
        for i in sample(range(nn), num_errs):
            tem1[i] ^= 0xff
        self.assertRaises(ReedSolomonError, rs.decode, tem1)
예제 #4
0
    def test_prim_fcr_basic(self) -> None:
        nn          = 30
        kk          = 18
        tt          = nn - kk
        rs          = RSCodec(tt, fcr=120, prim=0x187)
        hex_enc_msg = ('00faa123555555c000000354064432'
                     'c02800fe97c434e1ff5365cf8fafe4')
        strf        = str
        enc_msg     = bytearray.fromhex(strf(hex_enc_msg))
        dec_msg     = enc_msg[:kk]
        tem         = rs.encode(dec_msg)
        self.assertEqual(enc_msg, tem, msg="encoded does not match expected")

        tdm, rtem = rs.decode(tem)
        self.assertEqual(tdm, dec_msg, msg="decoded does not match original")
        self.assertEqual(rtem, tem,    msg="decoded mesecc does not match original")

        tem1 = bytearray(tem)  # Clone a copy

        # Encoding and decoding intact message seem OK, so test errors
        num_errs = tt >> 1  # Inject tt/2 errors (expected to recover fully)
        for i in sample(range(nn), num_errs):  # inject errors in random places
            tem1[i] ^= 0xff  # flip all 8 bits
        tdm, _ = rs.decode(tem1)
        self.assertEqual(tdm, dec_msg, msg="decoded with errors does not match original")

        tem1 = bytearray(tem)  # Clone another copy
        num_errs += 1  # Inject tt/2 + 1 errors (expected to fail and detect it)
        for i in sample(range(nn), num_errs):  # Inject errors in random places
            tem1[i] ^= 0xff  # Flip all 8 bits
        # If this fails, it means excessive errors not detected
        self.assertRaises(ReedSolomonError, rs.decode, tem1)
예제 #5
0
 def test_simple(self) -> None:
     rs           = RSCodec()
     msg          = bytearray("hello world " * 10, "latin1")
     enc          = rs.encode(msg)
     dec, dec_enc = rs.decode(enc)
     self.assertEqual(dec, msg)
     self.assertEqual(dec_enc, enc)
예제 #6
0
파일: tcb.py 프로젝트: AJMartel/tfc
def rxm_outgoing(queues: Dict[bytes, 'Queue'],
                 settings: 'Settings',
                 gateway: 'Gateway',
                 unittest: bool = False) -> None:
    """Loop that outputs packets from queues to RxM.

    Commands (and local keys) from TxM to RxM have higher priority
    than messages and public keys from contacts. This prevents
    contact from doing DoS on RxM by filling queue with packets.
    """
    rs = RSCodec(2 * settings.session_serial_error_correction)
    c_queue = queues[TXM_TO_RXM_QUEUE]
    m_queue = queues[RXM_OUTGOING_QUEUE]

    while True:
        try:
            time.sleep(0.01)

            while c_queue.qsize() != 0:
                packet = rs.encode(bytearray(c_queue.get()))
                gateway.write(packet)

            if m_queue.qsize() != 0:
                packet = rs.encode(bytearray(m_queue.get()))
                gateway.write(packet)

            if unittest:
                break
        except (EOFError, KeyboardInterrupt):
            pass
예제 #7
0
파일: test_tcb.py 프로젝트: gtog/tfc
 def setUp(self):
     self.settings = Settings()
     self.unittest_dir = cd_unittest()
     self.gateway = Gateway()
     self.rs = RSCodec(2 * self.gateway.settings.serial_error_correction)
     self.ts = datetime.now()
     self.queues = gen_queue_dict()
     self.args = self.queues, self.gateway
예제 #8
0
 def setUp(self) -> None:
     """Pre-test actions."""
     self.settings = Settings()
     self.unit_test_dir = cd_unit_test()
     self.gateway = Gateway()
     self.rs = RSCodec(2 * self.gateway.settings.serial_error_correction)
     self.ts = datetime.now()
     self.queues = gen_queue_dict()
     self.args = self.queues, self.gateway
     self.queues[TX_BUF_KEY_QUEUE].put(SYMMETRIC_KEY_LENGTH * b'a')
예제 #9
0
파일: packet.py 프로젝트: barleyj/tfc
def transmit(packet: bytes, settings: 'Settings', gateway: 'Gateway') -> None:
    """Add Reed-Solomon erasure code and output packet via gateway."""
    rs     = RSCodec(2 * settings.session_ec_ratio)
    packet = rs.encode(packet)
    gateway.write(packet)

    if not settings.session_trickle:
        if settings.long_packet_rand_d:
            random_delay = random.SystemRandom().uniform(0, settings.max_val_for_rand_d)
            time.sleep(random_delay)
예제 #10
0
파일: tcb.py 프로젝트: barleyj/tfc
def txm_incoming(settings: 'Settings', q_to_tip: 'Queue', q_to_rxm: 'Queue',
                 q_to_im: 'Queue', q_to_nh: 'Queue') -> None:
    """Load messages from TxM and forward them to appropriate process via queue."""
    rs = RSCodec(2 * settings.session_ec_ratio)

    while True:
        try:
            if q_to_tip.empty():
                time.sleep(0.001)
            packet = q_to_tip.get()

            try:
                packet = bytes(rs.decode(packet))
            except ReedSolomonError:
                box_print(
                    ["Warning! Failed to correct errors in received packet."],
                    head=1,
                    tail=1)
                continue

            ts = datetime.datetime.now().strftime(settings.t_fmt)
            header = packet[:1]

            if header == UNENCRYPTED_PACKET_HEADER:
                q_to_nh.put(packet[1:])

            elif header in [LOCAL_KEY_PACKET_HEADER, COMMAND_PACKET_HEADER]:
                p_type = 'local key' if header == LOCAL_KEY_PACKET_HEADER else 'command'
                print("{} - {} TxM > RxM".format(ts, p_type))
                q_to_rxm.put(packet)

            elif header in [MESSAGE_PACKET_HEADER, PUBLIC_KEY_PACKET_HEADER]:
                payload_len, p_type = (
                    32, 'pub key') if header == PUBLIC_KEY_PACKET_HEADER else (
                        344, 'message')
                payload = packet[1:1 + payload_len]
                trailer = packet[1 + payload_len:]
                user, contact = trailer.split(US_BYTE)

                print("{} - {} TxM > {} > {}".format(ts, p_type, user.decode(),
                                                     contact.decode()))
                q_to_im.put((header, payload, user, contact))
                q_to_rxm.put(header + payload + ORIGIN_USER_HEADER + contact)

            elif header == EXPORTED_FILE_CT_HEADER:
                payload = packet[1:]
                file_name = os.urandom(16).hex()
                with open(file_name, 'wb+') as f:
                    f.write(payload)
                print("{} - Exported file from TxM as {}".format(
                    ts, file_name))

        except (EOFError, KeyboardInterrupt):
            pass
예제 #11
0
파일: test_tcb.py 프로젝트: AJMartel/tfc
 def setUp(self):
     self.settings  = Settings()
     self.rs        = RSCodec(2 * self.settings.serial_error_correction)
     self.o_urandom = os.urandom
     self.queues    = {TXM_INCOMING_QUEUE: Queue(),
                       RXM_OUTGOING_QUEUE: Queue(),
                       TXM_TO_IM_QUEUE:    Queue(),
                       TXM_TO_NH_QUEUE:    Queue(),
                       TXM_TO_RXM_QUEUE:   Queue(),
                       NH_TO_IM_QUEUE:     Queue(),
                       EXIT_QUEUE:         Queue()}
예제 #12
0
 def test_correction(self) -> None:
     rs         = RSCodec()
     msg        = bytearray("hello world " * 10, "latin1")
     enc        = rs.encode(msg)
     rmsg, renc = rs.decode(enc)
     self.assertEqual(rmsg, msg)
     self.assertEqual(renc, enc)
     for i in [27, -3, -9, 7, 0]:
         enc[i]     = 99
         rmsg, renc = rs.decode(enc)
         self.assertEqual(rmsg, msg)
     enc[82] = 99
     self.assertRaises(ReedSolomonError, rs.decode, enc)
예제 #13
0
 def test_long(self) -> None:
     rs           = RSCodec()
     msg          = bytearray("a" * 10000, "latin1")
     enc          = rs.encode(msg)
     dec, dec_enc = rs.decode(enc)
     self.assertEqual(dec, msg)
     self.assertEqual(dec_enc, enc)
     enc2           = list(enc)
     enc2[177]      = 99
     enc2[2212]     = 88
     dec2, dec_enc2 = rs.decode(bytes(enc2))
     self.assertEqual(dec2, msg)
     self.assertEqual(dec_enc2, enc)
예제 #14
0
파일: tcb.py 프로젝트: barleyj/tfc
def rxm_outgoing(settings: 'Settings', q_to_rxm: 'Queue',
                 gateway: 'Gateway') -> None:
    """Output packets from RxM-queue to RxM."""
    rs = RSCodec(2 * settings.session_ec_ratio)
    while True:
        try:
            if q_to_rxm.empty():
                time.sleep(0.001)
                continue
            from_q = q_to_rxm.get()
            packet = rs.encode(bytearray(from_q))
            gateway.write(packet)
        except (EOFError, KeyboardInterrupt):
            pass
예제 #15
0
 def test_check(self) -> None:
     rs         = RSCodec()
     msg        = bytearray("hello world " * 10, "latin1")
     enc        = rs.encode(msg)
     rmsg, renc = rs.decode(enc)
     self.assertEqual(rs.check(enc), [True])
     self.assertEqual(rs.check(renc), [True])
     for i in [27, -3, -9, 7, 0]:
         enc[i]     = 99
         rmsg, renc = rs.decode(enc)
         self.assertEqual(rs.check(enc), [False])
         self.assertEqual(rs.check(renc), [True])
예제 #16
0
파일: test_gateway.py 프로젝트: xprog12/tfc
    def test_detect_errors(self, *_: Any) -> None:
        gateway = Gateway(operation=RX, local_test=False, dd_sockets=False)
        packet = b'packet'

        # Test BLAKE2b based checksum
        gateway.settings.session_serial_error_correction = 0
        self.assertEqual(
            gateway.detect_errors(gateway.add_error_correction(packet)),
            packet)

        # Test unrecoverable error raises FR
        self.assert_se("Warning! Received packet had an invalid checksum.",
                       gateway.detect_errors, 300 * b'a')

        # Test Reed-Solomon erasure code
        gateway.settings.session_serial_error_correction = 5
        gateway.rs = RSCodec(gateway.settings.session_serial_error_correction)
        self.assertEqual(
            gateway.detect_errors(gateway.add_error_correction(packet)),
            packet)

        # Test unrecoverable error raises FR
        self.assert_se(
            "Error: Reed-Solomon failed to correct errors in the received packet.",
            gateway.detect_errors, 300 * b'a')
예제 #17
0
파일: test_tcb.py 프로젝트: AJMartel/tfc
class TestRxMOutGoing(unittest.TestCase):

    def setUp(self):
        self.settings = Settings()
        self.gateway  = Gateway()
        self.rs       = RSCodec(2 * self.settings.serial_error_correction)
        self.queues   = {TXM_INCOMING_QUEUE: Queue(),
                         RXM_OUTGOING_QUEUE: Queue(),
                         TXM_TO_IM_QUEUE:    Queue(),
                         TXM_TO_NH_QUEUE:    Queue(),
                         TXM_TO_RXM_QUEUE:   Queue(),
                         NH_TO_IM_QUEUE:     Queue(),
                         EXIT_QUEUE:         Queue()}

    def tearDown(self):
        for k in self.queues:
            while not self.queues[k].empty():
                self.queues[k].get()
            time.sleep(0.1)
            self.queues[k].close()

    def test_loop(self):
        # Setup
        packet = b'testpacket'
        self.queues[TXM_TO_RXM_QUEUE].put(packet)
        self.queues[RXM_OUTGOING_QUEUE].put(packet)
        time.sleep(0.1)

        # Test
        self.assertIsNone(rxm_outgoing(self.queues, self.settings, self.gateway, unittest=True))
        self.assertEqual(packet, self.rs.decode(self.gateway.packets[0]))
예제 #18
0
def calculate_race_condition_delay(settings: Union['Settings', 'NHSettings'], txm: bool = False) -> float:
    """Calculate NH race condition delay.

    This value is the max time it takes for NH to deliver
    command received from TxM all the way to RxM.

    :param settings: Settings object
    :param txm:      When True, allocate time for command delivery from TxM to NH
    :return:         Time to wait to prevent race condition
    """
    rs                 = RSCodec(2 * settings.session_serial_error_correction)
    max_account_length = 254
    max_message_length = PACKET_LENGTH + 2 * max_account_length
    command_length     = 365*2 if txm else 365
    max_bytes          = (len(rs.encode(os.urandom(max_message_length)))
                          + len(rs.encode(os.urandom(command_length))))

    return (max_bytes * BAUDS_PER_BYTE) / settings.serial_baudrate
예제 #19
0
파일: files.py 프로젝트: AJMartel/tfc
    def update_delivery_time(self) -> None:
        """Calculate transmission time.

        Transmission time is based on average delays and settings.
        """
        no_packets = self.count_number_of_packets()

        if self.settings.session_traffic_masking:
            avg_delay = self.settings.traffic_masking_static_delay + (
                self.settings.traffic_masking_random_delay / 2)
            if self.settings.multi_packet_random_delay:
                avg_delay += (self.settings.max_duration_of_random_delay / 2)

            total_time = len(self.window) * no_packets * avg_delay
            total_time *= 2  # Accommodate command packets between file packets
            total_time += no_packets * TRAFFIC_MASKING_QUEUE_CHECK_DELAY

        else:
            # Determine total data to be transmitted over serial
            rs = RSCodec(2 * self.settings.session_serial_error_correction)
            total_data = 0
            for c in self.window:
                data = os.urandom(PACKET_LENGTH) + c.rx_account.encode(
                ) + c.tx_account.encode()
                enc_data = rs.encode(data)
                total_data += no_packets * len(enc_data)

            # Determine time required to send all data
            total_time = 0.0
            if self.settings.local_testing_mode:
                total_time += no_packets * LOCAL_TESTING_PACKET_DELAY
            else:
                total_bauds = total_data * BAUDS_PER_BYTE
                total_time += total_bauds / self.settings.session_serial_baudrate
                total_time += no_packets * self.settings.txm_inter_packet_delay

            if self.settings.multi_packet_random_delay:
                total_time += no_packets * (
                    self.settings.max_duration_of_random_delay / 2)

        # Update delivery time
        self.time_bytes = int_to_bytes(int(total_time))
        self.time_print = str(datetime.timedelta(seconds=int(total_time)))
예제 #20
0
    def test_receiver_loop(self) -> None:
        # Setup
        gateway = Gateway(local_test=False)
        rs = RSCodec(2 * gateway.settings.serial_error_correction)
        queues = {
            MESSAGE_DATAGRAM_HEADER: Queue(),
            FILE_DATAGRAM_HEADER: Queue(),
            COMMAND_DATAGRAM_HEADER: Queue(),
            LOCAL_KEY_DATAGRAM_HEADER: Queue()
        }

        all_q = dict(queues)
        all_q.update({GATEWAY_QUEUE: Queue()})

        ts = datetime.now()
        ts_bytes = int_to_bytes(int(ts.strftime('%Y%m%d%H%M%S%f')[:-4]))

        for key in queues:
            packet = key + ts_bytes + bytes(ONION_SERVICE_PUBLIC_KEY_LENGTH)
            encoded = rs.encode(packet)
            broken_p = key + bytes.fromhex('df9005313af4136d') + bytes(
                ONION_SERVICE_PUBLIC_KEY_LENGTH)
            broken_p += rs.encode(b'a')

            def queue_delayer() -> None:
                """Place datagrams into queue after delay."""
                time.sleep(0.01)
                all_q[GATEWAY_QUEUE].put(
                    (datetime.now(), rs.encode(8 * b'1' + b'undecodable')))
                all_q[GATEWAY_QUEUE].put((datetime.now(), broken_p))
                all_q[GATEWAY_QUEUE].put((datetime.now(), encoded))

            threading.Thread(target=queue_delayer).start()

            # Test
            self.assertIsNone(receiver_loop(all_q, gateway, unit_test=True))
            time.sleep(0.01)
            self.assertEqual(queues[key].qsize(), 1)

            # Teardown
            tear_queue(queues[key])
예제 #21
0
파일: misc.py 프로젝트: otto-hermann/tfc
def calculate_race_condition_delay(serial_error_correction: int,
                                   serial_baudrate: int) -> float:
    """\
    Calculate the delay required to prevent Relay Program race condition.

    When Transmitter Program outputs a command to exit or wipe data,
    Relay program will also receive a copy of the command. If the Relay
    Program acts on the command too early, the Receiver Program will not
    receive the exit/wipe command at all.

    This function calculates the delay Transmitter Program should wait
    before outputting command to the Relay Program, to ensure the
    Receiver Program has received its encrypted command.
    """
    rs = RSCodec(2 * serial_error_correction)
    message_length = PACKET_LENGTH + ONION_ADDRESS_LENGTH
    enc_msg_length = len(rs.encode(os.urandom(message_length)))
    enc_cmd_length = len(rs.encode(os.urandom(COMMAND_LENGTH)))
    max_bytes = enc_msg_length + (2 * enc_cmd_length)

    return (max_bytes * BAUDS_PER_BYTE) / serial_baudrate
예제 #22
0
def transmit(packet:   bytes,
             settings: 'Settings',
             gateway:  'Gateway',
             delay:    bool = True) -> None:
    """Add Reed-Solomon erasure code and output packet via gateway.

    Note that random.SystemRandom() uses Kernel CSPRNG (/dev/urandom),
    not Python's weak RNG based on Mersenne Twister:
        https://docs.python.org/2/library/random.html#random.SystemRandom
    """
    rs     = RSCodec(2 * settings.session_serial_error_correction)
    packet = rs.encode(packet)
    gateway.write(packet)

    if settings.local_testing_mode:
        time.sleep(LOCAL_TESTING_PACKET_DELAY)

    if not settings.session_traffic_masking:
        if settings.multi_packet_random_delay and delay:
            random_delay = random.SystemRandom().uniform(0, settings.max_duration_of_random_delay)
            time.sleep(random_delay)
예제 #23
0
파일: test_gateway.py 프로젝트: dimwap/tfc
    def test_add_error_correction(self, *_) -> None:
        gateway = Gateway(operation=RX, local_test=False, dd_sockets=False, qubes=False)
        packet = b"packet"

        # Test BLAKE2b based checksum
        gateway.settings.session_serial_error_correction = 0
        self.assertEqual(gateway.add_error_correction(packet),
                         packet + blake2b(packet, digest_size=PACKET_CHECKSUM_LENGTH))

        # Test Reed-Solomon erasure code
        gateway.settings.session_serial_error_correction = 5
        gateway.rs = RSCodec(gateway.settings.session_serial_error_correction)
        self.assertEqual(gateway.add_error_correction(packet),
                         gateway.rs.encode(packet))
예제 #24
0
def receiver_loop(queues: Dict[bytes, 'Queue'],
                  settings: 'Settings',
                  unittest: bool = False) -> None:
    """Decode received packets and forward them to packet queues.

    This function also determines the timestamp for received message.
    """
    rs = RSCodec(2 * settings.session_serial_error_correction)
    gw_queue = queues[GATEWAY_QUEUE]

    while True:
        with ignored(EOFError, KeyboardInterrupt):
            if gw_queue.qsize() == 0:
                time.sleep(0.01)

            packet = gw_queue.get()
            timestamp = datetime.now()

            try:
                packet = bytes(rs.decode(packet))
            except ReedSolomonError:
                box_print(
                    "Error: Failed to correct errors in received packet.",
                    head=1,
                    tail=1)
                continue

            p_header = packet[:1]
            if p_header in [
                    PUBLIC_KEY_PACKET_HEADER, MESSAGE_PACKET_HEADER,
                    LOCAL_KEY_PACKET_HEADER, COMMAND_PACKET_HEADER,
                    IMPORTED_FILE_HEADER
            ]:
                queues[p_header].put((timestamp, packet))

            if unittest:
                break
예제 #25
0
    def test_receiver_loop(self):
        # Setup
        settings = Settings()
        rs = RSCodec(2 * settings.serial_error_correction)
        queues = {
            LOCAL_KEY_PACKET_HEADER: Queue(),
            PUBLIC_KEY_PACKET_HEADER: Queue(),
            MESSAGE_PACKET_HEADER: Queue(),
            COMMAND_PACKET_HEADER: Queue(),
            IMPORTED_FILE_HEADER: Queue()
        }

        all_q = dict(queues)
        all_q.update({GATEWAY_QUEUE: Queue()})

        for key in queues:
            packet = key + bytes(KEY_LENGTH)
            encoded = rs.encode(packet)

            def queue_delayer():
                time.sleep(0.1)
                all_q[GATEWAY_QUEUE].put(b'undecodable')
                all_q[GATEWAY_QUEUE].put(encoded)

            threading.Thread(target=queue_delayer).start()

            # Test
            self.assertIsNone(receiver_loop(all_q, settings, unittest=True))
            time.sleep(0.1)
            self.assertEqual(queues[key].qsize(), 1)

            # Teardown
            while not queues[key].empty():
                queues[key].get()
            time.sleep(0.1)
            queues[key].close()
예제 #26
0
    def test_c_exp_12(self) -> None:
        rsc  = RSCodec(12, c_exp=12)
        rsc2 = RSCodec(12, nsize=4095)
        self.assertEqual(rsc.c_exp, rsc2.c_exp)
        self.assertEqual(rsc.nsize, rsc2.nsize)

        mes           = 'a'*(4095-12)
        mesecc        = rsc.encode(mes)
        mesecc[2]     = 1
        mesecc[-1]    = 1
        rmes, rmesecc = rsc.decode(mesecc)
        self.assertEqual(rsc.check(mesecc),  [False])
        self.assertEqual(rsc.check(rmesecc), [True])
        self.assertEqual([x for x in rmes],  [ord(x) for x in mes])
예제 #27
0
    def test_c_exp_9(self):
        rsc = RSCodec(12, c_exp=9)
        rsc2 = RSCodec(12, nsize=511)
        self.assertEqual(rsc.c_exp, rsc2.c_exp)
        self.assertEqual(rsc.nsize, rsc2.nsize)

        mes = 'a' * ((511 - 12) * 2)
        mesecc = rsc.encode(mes)
        mesecc[2] = 1
        mesecc[-1] = 1
        rmes, rmesecc = rsc.decode(mesecc)
        self.assertEqual(rsc.check(mesecc), [False, False])
        self.assertEqual(rsc.check(rmesecc), [True, True])
        self.assertEqual([x for x in rmes], [ord(x) for x in mes])
예제 #28
0
    def test_detect_errors(self, *_: Any) -> None:
        gateway = Gateway(operation=RX,
                          local_test=False,
                          dd_sockets=False,
                          qubes=False)
        packet = b'packet'

        # Test BLAKE2b based checksum
        gateway.settings.session_serial_error_correction = 0
        self.assertEqual(
            gateway.detect_errors(gateway.add_error_correction(packet)),
            packet)

        # Test unrecoverable error raises SoftError
        self.assert_se("Warning! Received packet had an invalid checksum.",
                       gateway.detect_errors, 300 * b'a')

        # Test Reed-Solomon erasure code
        gateway.settings.session_serial_error_correction = 5
        gateway.rs = RSCodec(gateway.settings.session_serial_error_correction)
        self.assertEqual(
            gateway.detect_errors(gateway.add_error_correction(packet)),
            packet)

        # Test unrecoverable error raises SoftError
        self.assert_se(
            "Error: Reed-Solomon failed to correct errors in the received packet.",
            gateway.detect_errors, 300 * b'a')

        # Qubes

        # Test with B58 encoding
        gateway.settings.qubes = True
        packet_with_error_correction = base64.b85encode(
            gateway.add_error_correction(packet))
        self.assertEqual(gateway.detect_errors(packet_with_error_correction),
                         packet)

        # Test invalid B85 encoding raises SoftError
        packet_with_error_correction = base64.b85encode(
            gateway.add_error_correction(packet))
        packet_with_error_correction += b'\x00'
        self.assert_se("Error: Received packet had invalid Base85 encoding.",
                       gateway.detect_errors, packet_with_error_correction)
        gateway.settings.qubes = False
예제 #29
0
 def test_multiple_rs_codec(self) -> None:
     """Test multiple RSCodec instances with different parameters."""
     mes     = 'A' * 30
     rs_256  = RSCodec(102)
     rs_1024 = RSCodec(900, c_exp=10)
     bytearray(rs_1024.decode(rs_1024.encode(mes))[0])
     rs_256.encode(mes)
     rs_1024.encode(mes)
     bytearray(rs_256.decode(rs_256.encode(mes))[0])
예제 #30
0
파일: tcb.py 프로젝트: AJMartel/tfc
def txm_incoming(queues: Dict[bytes, 'Queue'],
                 settings: 'Settings',
                 unittest: bool = False) -> None:
    """Loop that places messages received from TxM to appropriate queues."""
    rs = RSCodec(2 * settings.session_serial_error_correction)

    q_to_tip = queues[TXM_INCOMING_QUEUE]
    m_to_rxm = queues[RXM_OUTGOING_QUEUE]
    c_to_rxm = queues[TXM_TO_RXM_QUEUE]
    q_to_im = queues[TXM_TO_IM_QUEUE]
    q_to_nh = queues[TXM_TO_NH_QUEUE]

    while True:
        with ignored(EOFError, KeyboardInterrupt):
            while q_to_tip.qsize() == 0:
                time.sleep(0.01)

            packet = q_to_tip.get()

            try:
                packet = bytes(rs.decode(packet))
            except ReedSolomonError:
                box_print(
                    "Warning! Failed to correct errors in received packet.",
                    head=1,
                    tail=1)
                continue

            ts = datetime.now().strftime("%m-%d / %H:%M:%S")
            header = packet[:1]

            if header == UNENCRYPTED_PACKET_HEADER:
                q_to_nh.put(packet[1:])

            elif header in [LOCAL_KEY_PACKET_HEADER, COMMAND_PACKET_HEADER]:
                p_type = 'local key' if header == LOCAL_KEY_PACKET_HEADER else 'command'
                print("{} - {} TxM > RxM".format(ts, p_type))
                c_to_rxm.put(packet)

            elif header in [MESSAGE_PACKET_HEADER, PUBLIC_KEY_PACKET_HEADER]:
                payload_len, p_type = {
                    PUBLIC_KEY_PACKET_HEADER: (KEY_LENGTH, 'pub key'),
                    MESSAGE_PACKET_HEADER: (MESSAGE_LENGTH, 'message')
                }[header]
                payload = packet[1:1 + payload_len]
                trailer = packet[1 + payload_len:]
                user, contact = trailer.split(US_BYTE)

                print("{} - {} TxM > {} > {}".format(ts, p_type, user.decode(),
                                                     contact.decode()))
                q_to_im.put((header, payload, user, contact))
                m_to_rxm.put(header + payload + ORIGIN_USER_HEADER + contact)

            elif header == EXPORTED_FILE_HEADER:
                payload = packet[1:]

                file_name = os.urandom(8).hex()
                while os.path.isfile(file_name):
                    file_name = os.urandom(8).hex()

                with open(file_name, 'wb+') as f:
                    f.write(payload)
                print("{} - Exported file from TxM as {}".format(
                    ts, file_name))

            if unittest:
                break