def decrypt_frame(self, encrypted_frame):
        """ Decrypt a frame.
        """
        id = encrypted_frame[0:HEADER_ID_SIZE]
        cipher_text = encrypted_frame[HEADER_ID_SIZE:]

        # check if 'id; is correct for link
        # note - AD maintains two links, for simplicity this is not shown
        # AD also supports a pairing discovery mode. In pairing
        # discovery the frame is not rejected, but used to discover
        # the peer's UDI and retrieve the UDS from the Key Dispenser (KD)
        # This is not yet shown and code only represents Operational link
        if id != self.udi[0:HEADER_ID_SIZE]:
            # reject the frame
            raise Exception("Wrong id on frame, not for this device")

        # decrypt the frame using the 'id' as an authenticated attribute
        # the SIV mode extracts the siv and raises an exception on
        # any integrity check failure
        plain_text = siv_decrypt(self._uds, cipher_text, [id])

        # parse fields in decrypted frame
        rt = plain_text[
            0:REPLAY_VALUE_SIZE]  # peer transmitted replay protection value
        rr = plain_text[REPLAY_VALUE_SIZE:2 *
                        REPLAY_VALUE_SIZE]  # echo of self's value
        message_data = plain_text[2 * REPLAY_VALUE_SIZE:]

        # validate if replay values are correct
        if rr == self.my_replay_value:
            # correct echoed 'rr' for syncronized operational link
            # if this is the first time recived change state
            if self.my_replay_value_state == NEW:
                self.my_replay_value_state = ECHOED

            if rt == self.peer_replay_value:
                # expected peer value - normal operation
                return message_data
            else:
                # change in peer replay value
                # adopt new value and echo on subsequent transmissions
                self.peer_replay_value = rt
                return message_data
        elif rr == ZERO_REPLAY_FIELD:
            # peer has reset so adopt the new rt value
            self.peer_replay_value = rt
            # creat new local replay value
            self.my_replay_value = os.urandom(REPLAY_VALUE_SIZE)
            # reset the transmitted frame count (actually count for a replay value)
            self.transmitted_frame_count = 0
            # note any message_data sent in a reset frame (rr==0's) is subject to a
            # replay attack and should be restricted to static link setup information
            return message_data
        else:  # possible replay attack
            # on replay errors the frame is dropped by rasing an exception
            raise Exception("Bad peer replay value - likely replay attack")
Example #2
0
 def test_Edges(self):
     """ Test edge conditions - zero lengths """
     # zero length plian text, multiple ad
     key = '7f7e7d7c7b7a79787776757473727170404142434445464748494a4b4c4d4e4f'.decode('hex')
     pt = ''
     ad1 = 'abcd'.decode('hex')
     ad2 = 'beef'.decode('hex')
     nonce = '09f911029d74e35bd84156c5635688c0'.decode('hex')
     ad = [ad1, ad2, nonce]
     
     iv_ct = siv_encrypt(key, pt, ad)
     pt2 = siv_decrypt(key, iv_ct, ad)
     
     self.assertEqual(  pt, pt2 )
     
     # no ad
     iv_ct = siv_encrypt(key, 'a', [])
     pt2 = siv_decrypt(key, iv_ct, [])
     self.assertEqual(  'a', pt2 )
Example #3
0
    def test_Edges(self):
        """ Test edge conditions - zero lengths """
        # zero length plian text, multiple ad
        key = "7f7e7d7c7b7a79787776757473727170404142434445464748494a4b4c4d4e4f".decode("hex")
        pt = ""
        ad1 = "abcd".decode("hex")
        ad2 = "beef".decode("hex")
        nonce = "09f911029d74e35bd84156c5635688c0".decode("hex")
        ad = [ad1, ad2, nonce]

        iv_ct = siv_encrypt(key, pt, ad)
        pt2 = siv_decrypt(key, iv_ct, ad)

        self.assertEqual(pt, pt2)

        # no ad
        iv_ct = siv_encrypt(key, "a", [])
        pt2 = siv_decrypt(key, iv_ct, [])
        self.assertEqual("a", pt2)
Example #4
0
 def test_A1(self):
     """ A.1. Deterministic Authenticated Encryption Example """
     key = 'fffefdfcfbfaf9f8f7f6f5f4f3f2f1f0f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff'.decode('hex')
     ad  = '101112131415161718191a1b1c1d1e1f2021222324252627'.decode('hex')
     pt  = '112233445566778899aabbccddee'.decode('hex')
     iv_ct = siv_encrypt(key, pt, [ad])
     known_ct = '85632d07c6e8f37f950acd320a2ecc9340c02b9690c4dc04daef7f6afe5c'.decode('hex') 
     
     self.assertEqual( iv_ct, known_ct )
    
     pt2 = siv_decrypt(key, iv_ct, [ad])
     self.assertEqual(  pt, pt2 )
Example #5
0
    def decrypt_frame(self, encrypted_frame):
        """ Decrypt a frame.
        """
        id = encrypted_frame[0:HEADER_ID_SIZE]
        cipher_text = encrypted_frame[HEADER_ID_SIZE:]

        # check if 'id; is correct for link
        # note - AD maintains two links, for simplicity this is not shown
        # AD also supports a pairing discovery mode. In pairing
        # discovery the frame is not rejected, but used to discover
        # the peer's UDI and retrieve the UDS from the Key Dispenser (KD)
        # This is not yet shown and code only represents Operational link
        if id != self.udi[0:HEADER_ID_SIZE]:
            # reject the frame
            raise Exception("Wrong id on frame, not for this device")

        # decrypt the frame using the 'id' as an authenticated attribute
        # the SIV mode extracts the siv and raises an exception on
        # any integrity check failure
        plain_text = siv_decrypt(self._uds, cipher_text, [id])

        # parse fields in decrypted frame
        rt = unpack("I", plain_text[0:REPLAY_VALUE_SIZE]
                    )  # peer transmitted replay protection value
        rr = unpack("I", plain_text[REPLAY_VALUE_SIZE:2 *
                                    REPLAY_VALUE_SIZE])  # echo of self's value
        message_data = plain_text[2 * REPLAY_VALUE_SIZE:]

        # validate if replay values are correct using a window for recived replay value
        # the recived
        if self.my_replay_value >= rr >= self.my_replay_value - REPLAY_CTR_WINDOW:
            # acceptable echoed 'rr' within window range (peer may have not recived frames)
            # check if rt is within it's window (frames may have been lost from peer)
            if self.peer_replay_value <= rt <= self.peer_replay_value + REPLAY_CTR_WINDOW:
                return message_data
            else:
                # peer replay values outside of allowed window
                # possible replay attack or long burst of lost data, reset replay
                self.reset()
                return ''  # discard message_data and quitely return null frame data
        elif rr == ZERO_REPLAY_FIELD:
            # peer has reset so adopt the new rt value
            self.peer_replay_value = rt

            # note any message_data sent in a reset frame (rr==0's) is subject to a
            # replay attack and should be restricted to static link setup information
            return message_data
        else:  # possible replay attack or long burst of peer losing frames
            # on replay errors the frame is dropped by rasing an exception
            raise Exception("Bad peer replay value - likely replay attack")
Example #6
0
 def test_A2(self):
     """ A.2. Nonce-based Authenticated Encryption Example """
     key = '7f7e7d7c7b7a79787776757473727170404142434445464748494a4b4c4d4e4f'.decode('hex')
     ad1 = '00112233445566778899aabbccddeeffdeaddadadeaddadaffeeddccbbaa99887766554433221100'.decode('hex')
     ad2 = '102030405060708090a0'.decode('hex')
     nonce = '09f911029d74e35bd84156c5635688c0'.decode('hex')
     ad = [ad1, ad2, nonce]
     pt = '7468697320697320736f6d6520706c61696e7465787420746f20656e6372797074207573696e67205349562d414553'.decode('hex')
     iv_ct = siv_encrypt(key, pt, ad)
     known_ct = '7bdb6e3b432667eb06f4d14bff2fbd0fcb900f2fddbe404326601965c889bf17dba77ceb094fa663b7a3f748ba8af829ea64ad544a272e9c485b62a3fd5c0d'.decode('hex') 
     
     self.assertEqual(  iv_ct, known_ct )
     
     pt2 = siv_decrypt(key, iv_ct, ad)  
     self.assertEqual(  pt, pt2 )