Пример #1
0
    def address_and_version_check(self, pck: CP1Package) -> bool:
        """
        Checks whether a pck is meant for this client: Does the address and version number match?
        :param pck: The package to check
        :return: True in case it is meant for this client, False otherwise.
        """
        init_field = pck.get_field(self.init_pck_field)
        init_field = init_field[self.init_pck_field.length() -
                                8:self.init_pck_field.length()]
        received_address_bits_hashed = init_field[0:6]
        own_address_bits_hashed = generate_address_hash(
            pck.hash_nonce(), self._address)

        if received_address_bits_hashed != own_address_bits_hashed:
            self.log.debug('The received address hash did not match: ' +
                           received_address_bits_hashed)
            return False

        received_version_bits_hashed = init_field[6:8]
        own_version_bits_hashed = generate_version_hash(
            pck.hash_nonce(), _PROTOCOL_VERSION)

        if received_version_bits_hashed != own_version_bits_hashed:
            self.log.debug(
                'The received version hash did not match the expected value: '
                + str(received_version_bits_hashed))
            return False

        return True
Пример #2
0
    def test_add_next_pck_successfully_added(self):
        # Arrange
        session = CP1ClientSession(KEY_BITS_192, CP1Package())
        payload_pck = CP1Package()
        payload = '1010101010111011'
        payload_pck.add_payload(payload)

        # Act
        session.add_next_pck(payload_pck)

        # Assert
        self.assertEqual(session.secret_received_in_bits, payload)
Пример #3
0
 def next_pck(self, cp1_pck: CP1Package):
     """
     Handles the next NTP package, extracts the payload and adds it to the session storage.
     :param cp1_pck:
     :return:
     """
     self.secret_received += cp1_pck.extract_payload()
Пример #4
0
    def generate_init_pck(self, address: str) -> NTP:
        """
        Creates a new init package containing the hashed version number and address information.
        Also stores the AES nonce in the session.
        :param address: The address to hash and insert into the package.
        :return: the NTP package filled with address and version information.
        """
        ntp = init_ntp_pck()

        raw_ntp = CP1Package(ntp)
        self.log.debug("Init pck field: " + str(self.init_pck_field))
        self.log.debug('Value of init-package-field before transformation: ' +
                       str(raw_ntp.get_field(self.init_pck_field)))

        self.aes_nonce = raw_ntp.aes_nonce_bits()
        address_hashed = generate_address_hash(raw_ntp.hash_nonce(), address)
        self.log.debug('Address hash: ' + str(address_hashed))
        version_hashed = generate_version_hash(raw_ntp.hash_nonce(),
                                               _PROTOCOL_VERSION)

        field_value = raw_ntp.get_field(self.init_pck_field)
        field_value = field_value[:len(field_value) -
                                  8] + address_hashed + version_hashed
        assert len(field_value) == 64
        raw_ntp.set_field(field_value, self.init_pck_field)
        self.log.debug('Value of init-package-field after transformation: ' +
                       str(raw_ntp.get_field(self.init_pck_field)))

        ntp = raw_ntp.ntp()
        return ntp
Пример #5
0
    def send_next_pck(self, ip_address, ntp_mode: NTPMode = NTPMode.CLIENT) -> Packet:
        """
        Sends the next chunk of payload bits to the destination.
        :param ip_address:
        :param ntp_mode: the mode of the ntp package to send.
        :return: the bits just send.
        """
        next_bits_to_send = self.send_session.secret_to_send.next_bits(self.payload_size)
        self.log.debug("Next payload bits to send: " + str(next_bits_to_send))

        ntp_pck = CP1Package(ntp_pck=init_ntp_client_pck())
        ntp_pck.add_payload(next_bits_to_send)
        ntp_pck_ntp = ntp_pck.ntp()
        ntp_pck_ntp.orig = None
        ntp_pck_ntp.recv = None
        ntp_pck_ntp.mode = 5
        pck_to_send = IP(dst=ip_address) / UDP() / ntp_pck_ntp
        send(pck_to_send)

        self.log.debug("Payload package successfully send to " + str(ip_address))

        if not self.send_session.secret_to_send.has_next_bits():
            self.log.debug("Sending complete. Terminating sending session.")

        return pck_to_send
Пример #6
0
    def handle_incoming_ntp_pck(self, ntp_pck: NTP):
        cp1_pck = CP1Package(ntp_pck)
        self.log.info('Received pck bits: ' + str(cp1_pck._raw))
        if self.listen_session is None:
            if not self.address_and_version_check(cp1_pck):
                self.log.info(
                    'Package did not contain matching address or version')
            else:
                self.log.info("Init pck. Creating new session")
                self.listen_session = CP1ClientSession(self.static_key_bits,
                                                       cp1_pck)
            return

        self.listen_session.add_next_pck(cp1_pck)

        if self.listen_session.is_complete():
            self.log.info("Payload completely received: " +
                          str(self.listen_session.secret_received_in_bits))
            self.log.info("Using key to decrypt: " +
                          str(self.listen_session.get_decryption_key_bytes()))
            decoded_bits = decrypt_bits_raw(
                encrypted_bits=self.listen_session.secret_received_in_bits,
                decryption_key_bytes=self.listen_session.
                get_decryption_key_bytes())
            self.log.info("DECRYPTED Payload: " + str(decoded_bits))
            self.listen_session = None
Пример #7
0
    def handle_incoming_pck(self, pck: Packet):
        ntp_pck = pck[NTP]
        cp1_pck = CP1Package(ntp_pck)
        self.log.info('Received pck bits: ' + str(cp1_pck._raw))

        if self.send_session is None:
            self.log.debug("Init new session (1).")
            self.send_session = CP1Session()
            next_pck = self.send_session.generate_init_pck(self.client_address)
            self.add_secret_payload(self.payload, self.static_key)

        else:
            next_bits_to_send = self.send_session.secret_to_send.next_bits(
                self.payload_size)
            self.log.debug("Next payload bits to send: " +
                           str(next_bits_to_send))
            new_cp1_pck = CP1Package(ntp_pck=init_ntp_client_pck())
            new_cp1_pck.add_payload(next_bits_to_send)
            next_pck = new_cp1_pck.ntp()

        upstream_pck = self.scapy_wrapper.get_upstream_ntp()

        upstream_pck[NTP].mode = 4
        # upstream_pck[NTP].orig = ntp_pck.sent
        upstream_pck[NTP].sent = next_pck[NTP].sent
        upstream_pck[NTP].ref = next_pck[NTP].ref
        upstream_pck[IP].src = pck[IP].dst
        upstream_pck[IP].dst = pck[IP].src
        upstream_pck[UDP].sport = pck[UDP].dport
        upstream_pck[UDP].dport = pck[UDP].sport

        up_raw = RawNTP(upstream_pck[NTP])
        pck_raw = RawNTP(ntp_pck)
        up_raw.set_origin_timestamp(pck_raw.transmit_timestamp())
        upstream_pck[NTP] = up_raw.ntp()

        self.log.debug("Created new CP1 packet to send...")

        upstream_pck.show()
        send(upstream_pck)

        if not self.has_next_pck():
            self.log.debug("Init new session (2).")
            self.send_session = None
Пример #8
0
    def test_add_payload_in_default_correctly_added(self):
        # Arrange
        payload = '1000101011010011'
        cp1_package = CP1Package()

        # Act
        cp1_package.add_payload(payload)

        # Assert
        self.assertTrue(cp1_package.transmit_timestamp()[40:56] == payload)
Пример #9
0
    def test_is_complete_payload_not_complete_false_returned(self):
        # Arrange
        session = CP1Session()
        pck = CP1Package()
        pck.add_payload('1010101010101010')
        session.next_pck(pck)

        # Act
        result = session.is_complete()

        # Assert
        self.assertFalse(result)
Пример #10
0
    def test_extract_payload_default_correctlyExtracted(self):
        # Arrange
        logging.basicConfig(level=logging.DEBUG)
        payload = '1000101011010011'
        cp1_package = CP1Package()
        cp1_package.add_payload(payload)

        # Act
        result = cp1_package.extract_payload()

        # Assert
        self.assertEqual(result, payload)
Пример #11
0
    def test_get_decryption_key_bytes(self):
        # Arrange
        cp1_pck = CP1Package()
        session = CP1ClientSession(KEY_BITS_192, cp1_pck)
        comparing_result = NTPCrypto().generate_aes_key_bytes(
            KEY_BITS_192, cp1_pck.aes_nonce_bits())

        # Act
        result = session.get_decryption_key_bytes()

        # Assert
        self.assertEqual(result, comparing_result)
Пример #12
0
    def test_is_complete_payload_is_complete_true_returned(self):
        # Arrange
        session = CP1Session()
        pck = CP1Package()
        pck.add_payload('1010101010101010')
        for x in range(8):
            session.next_pck(pck)

        # Act
        result = session.is_complete()

        # Assert
        self.assertTrue(result)
Пример #13
0
    def test_add_payload_different_field_and_length_correctly_added(self):
        # Arrange
        payload = '10001010100110111111'
        cp1_package = CP1Package()

        # Act
        cp1_package.add_payload(payload,
                                pos=5,
                                field=NTPField.RECEIVE_TIMESTAMP)

        # Assert
        self.assertTrue(
            cp1_package.receive_timestamp()[5:5 + len(payload)] == payload)
Пример #14
0
 def __init__(
     self,
     static_key_bits,
     init_pck: CP1Package,
     log: logging.Logger = logging.getLogger('CP1ClientSession-logger')):
     """
     A data container which stores session data of one CP1 Session from client perspective.
     :param static_key_bits: The static key to decrypt a received message.
     :param init_pck: The first package send to the client which holds the nonce for the aes key.
     :param log:
     """
     self.log = log
     self.crypto_tools = NTPCrypto()
     self._decryption_key_bytes = self.crypto_tools.generate_aes_key_bytes(
         static_key_bits, init_pck.aes_nonce_bits())
     self.secret_received_in_bits = ''