def send(self, addr, cSuite, nodeData): try: addrStr = sts_utility.addrToString(addr) if addrStr in STS.STSConnectionStates.keys(): if STS.STSConnectionStates[addrStr]['phase'] == 2: print('send data with the existing session') ECDH_DATA_EX = self.constructSTSResponse(2, addr, nodeData) self.sock.sendto(ECDH_DATA_EX, addr) # self.receive() else: self.terminate(addr) else: print('send data with the new session') # myCert, myCertStatus = sts_utility.decodeMyCertificate(self.sock, self.endpoint_address) # myEncrypKey, mySignKey = sts_utility.decodeSecretKey() if cSuite in [1, 2, 6]: # print('sending ECDH') myECDHPK, myECDHSK = pysodium.crypto_kx_keypair() propose = self.generateProposeECDH(cSuite, myECDHPK, self.mySignKey, self.myCert, self.myCertStatus) STS.STSConnectionStates[addrStr] = { 'session_key': None, 'phase': 0, 'init': True, 'data': nodeData, 'keys': (myECDHPK, myECDHSK), 'cSuite': cSuite, 'time': int(time.time()) } print('sending PROPOSE') sts_utility.decodeSTSMessage(propose) self.sock.sendto(propose, addr) elif cSuite in [3, 4, 5]: propose = self.generateProposeECDH(cSuite, (0).to_bytes( 32, byteorder='big'), self.mySignKey, self.myCert, self.myCertStatus) STS.STSConnectionStates[addrStr] = { 'session_key': None, 'phase': 0, 'init': True, 'data': nodeData, 'keys': None, 'cSuite': cSuite, 'time': int(time.time()) } print('sending PROPOSE') sts_utility.decodeSTSMessage(propose) self.sock.sendto(propose, addr) # while not STS.STSConnectionStates[addrStr]['phase'] == 2: # self.receive() # ECDH_DATA_EX = self.constructSTSResponse(2, addr, nodeData) # self.sock.sendto(ECDH_DATA_EX, addr) # self.receive() except: return None
def sendBlake2bResp(self, data, addr, cSuite): addrStr = sts_utility.addrToString(addr) # myCert, myCertStatus = sts_utility.decodeMyCertificate(self.sock, self.endpoint_address) # myEncrypKey, mySignKey = sts_utility.decodeSecretKey() if cSuite in [1, 2]: # print('sending ECDH') myECDHPK, myECDHSK = pysodium.crypto_kx_keypair() propose = self.generateProposeECDH(cSuite, myECDHPK, self.mySignKey, self.myCert, self.myCertStatus) # STS.STSConnectionStates[addrStr] = {'session_key': None, 'phase': 0, 'init': True, # 'keys': (myECDHPK, myECDHSK), # 'cSuite': cSuite, 'time': int(time.time())} STS.STSConnectionStates[addrStr]['keys'] = (myECDHPK, myECDHSK) self.blake2b(data, addr, server=True) print('Sending Propose') sts_utility.decodeSTSMessage(propose) self.sock.sendto(propose, addr) elif cSuite == 0: myECDHPK, myECDHSK = pysodium.crypto_kx_keypair() STS.STSConnectionStates[addrStr]['keys'] = (myECDHPK, myECDHSK) propose = self.generateProposeECDH(1, myECDHPK, self.mySignKey, self.myCert, self.myCertStatus) self.sock.sendto(propose, addr)
def receive(self): # print(STS.STSConnectionStates) data, addr = self.sock.recvfrom(1500) print('received STS message') sts_utility.decodeSTSMessage(data) # TODO Clean STSConnectionStates # TODO VALIDATE SUITE DOWNGRADE addrStr = sts_utility.addrToString(addr) # Received propose # Reply propose for actual suite when 0/3 used try: if addr == self.endpoint_address: self.setCertificateStatus(data) elif data[0] == 0: # propose received as server # print(self.verifySTSResponse(data, addr)) # CLIENT PROPOSE / MULTIPLE PROPOSE if addrStr in STS.STSConnectionStates.keys(): if self.verifyPropose(data, addr): if STS.STSConnectionStates[addrStr]['phase'] != 0: # pprint.pprint(STS.STSConnectionStates) self.terminate(addr) elif data[1] < STS.STSConnectionStates[addrStr][ 'cSuite']: self.terminate(addr) elif STS.STSConnectionStates[addrStr]['phase'] == 0: # TODO UPGRADE SUITE IS VALID, NEED TO FIX BELOW # if STS.STSConnectionStates[addrStr]['cSuite'] in [1, 2] and data[1] in [3, 4, 5]: # self.terminate(addr) if STS.STSConnectionStates[addrStr]['init']: if STS.STSConnectionStates[addrStr][ 'cSuite'] in [1, 2]: # LOWER SUITE CHECKED BEFORE if STS.STSConnectionStates[addrStr][ 'cSuite'] != data[1]: data = STS.STSConnectionStates[ addrStr]['data'] STS.STSConnectionStates.pop(addrStr) self.send(addr, data[1], data) return None, None elif STS.STSConnectionStates[addrStr][ 'cSuite'] == 3 and data[1] == 3: self.terminate(addr) else: if STS.STSConnectionStates[addrStr][ 'cSuite'] in [1, 2] and data[1] in [ 3, 4, 5 ]: self.terminate(addr) # if STS.STSConnectionStates[addrStr]['cSuite'] in [1 ,2]: # if STS.STSConnectionStates[addrStr]['cSuite'] != data[1]: # self.terminate(addr) else: STS.STSConnectionStates[addrStr]['cSuite'] = data[ 1] STS.STSConnectionStates[addrStr]['time'] = int( time.time()) else: print('=== VERIFICATION FAILED ===', addr) self.terminate(addr) # SERVER RECEIVE else: if self.verifyPropose(data, addr): # if data[1] == 0: # TODO PROPOSE EXPECTED SUITE if addrStr not in STS.STSConnectionStates.keys(): STS.STSConnectionStates[addrStr] = { 'session_key': None, 'phase': data[0], 'init': False, 'keys': None, 'cSuite': data[1], 'time': int(time.time()) } else: print('=== VERIFICATION FAILED ===', addr) self.terminate(addr) self.negotiate(data, addr) elif data[0] == 1: if addrStr not in STS.STSConnectionStates.keys(): self.terminate(addr) elif not self.deconstructSTSResponse(data, addr): self.terminate(addr) else: if STS.STSConnectionStates[addrStr]['init']: if STS.STSConnectionStates[addrStr]['phase'] == 1: STS.STSConnectionStates[addrStr]['phase'] = 2 ECDH_DATA_EX = self.constructSTSResponse( 2, addr, STS.STSConnectionStates[addrStr]['data']) self.sock.sendto(ECDH_DATA_EX, addr) else: self.terminate(addr) else: if STS.STSConnectionStates[addrStr][ 'phase'] == 0 and STS.STSConnectionStates[ addrStr]['cSuite'] in [1, 2]: STS.STSConnectionStates[addrStr]['phase'] = 1 self.negotiate(data, addr) elif STS.STSConnectionStates[addrStr][ 'phase'] == 0 and STS.STSConnectionStates[ addrStr]['cSuite'] in [4, 5]: STS.STSConnectionStates[addrStr]['phase'] = 1 self.negotiate(data, addr) else: self.terminate(addr) elif data[0] == 2: # TODO VALID DATA EXCHANGE if addrStr not in STS.STSConnectionStates.keys(): self.terminate(addr) elif not self.deconstructSTSResponse(data, addr): self.terminate(addr) else: if addrStr in STS.STSConnectionStates.keys(): if STS.STSConnectionStates[addrStr]['init']: if STS.STSConnectionStates[addrStr]['phase'] == 2: data_ex_resp = self.deconstructSTSResponse( data, addr) sts_utility.decodeDHTMessage(data_ex_resp) return data_ex_resp, addr else: self.terminate(addr) else: if STS.STSConnectionStates[addrStr]['phase'] == 2: date_ex_resp = self.deconstructSTSResponse( data, addr) response = packet.pingResponse(date_ex_resp) ECDH_DATA_EX = self.constructSTSResponse( 2, addr, response) self.sock.sendto(ECDH_DATA_EX, addr) else: self.terminate(addr) elif data[0] == 3: print('=== TERMINATE RECEIVED ===', addr) sts_utility.decodeSTSMessage(data) if addrStr in STS.STSConnectionStates.keys(): STS.STSConnectionStates.pop(addrStr) except: self.terminate(addr) return None, None return None, None
def negotiate(self, data, addr): addrStr = sts_utility.addrToString(addr) if addrStr in STS.STSConnectionStates.keys(): # SERVER LOGIC if not STS.STSConnectionStates[addrStr]['init']: if STS.STSConnectionStates[addrStr]['cSuite'] in [ 0, 1, 2 ] and STS.STSConnectionStates[addrStr]['phase'] == 0: self.sendBlake2bResp( data, addr, STS.STSConnectionStates[addrStr]['cSuite']) elif STS.STSConnectionStates[addrStr]['cSuite'] in [ 1, 2 ] and STS.STSConnectionStates[addrStr]['phase'] == 1: # TODO verify accept # ACCEPT Verify ECDH_AED_accept = self.constructSTSResponse( 1, addr, sts_utility.timestampPacked()) sts_utility.decodeSTSMessage(ECDH_AED_accept) STS.STSConnectionStates[addrStr]['phase'] = 2 self.sock.sendto(ECDH_AED_accept, addr) # self.receive() elif STS.STSConnectionStates[addrStr]['cSuite'] in [ 3, 4, 5 ] and STS.STSConnectionStates[addrStr]['phase'] == 0: # print('=== GEN PROPOSE SALSA 4 ===') # print(binascii.hexlify(proposeResp['C']['K_E'])) salsaMsg = self.salsa20poly1305(data, addr, server=True) if not salsaMsg: self.terminate(addr) else: sts_utility.decodeSTSMessage(salsaMsg) # print(mySalsaSession) self.sock.sendto(salsaMsg, addr) # self.receive() elif STS.STSConnectionStates[addrStr]['cSuite'] in [ 4, 5 ] and STS.STSConnectionStates[addrStr]['phase'] == 1: STS.STSConnectionStates[addrStr]['phase'] = 2 SALSA_AED_accept = self.constructSTSResponse( 1, addr, sts_utility.timestampPacked()) sts_utility.decodeSTSMessage(SALSA_AED_accept) self.sock.sendto(SALSA_AED_accept, addr) # self.receive() else: self.terminate(addr) # CLIENT LOGIC else: if STS.STSConnectionStates[addrStr]['cSuite'] in [ 1, 2 ] and STS.STSConnectionStates[addrStr]['phase'] == 0: if STS.STSConnectionStates[addrStr]['session_key'] is None: self.blake2b(data, addr) ECDH_AED_accept = self.constructSTSResponse( 1, addr, sts_utility.timestampPacked()) print('Sending Accept') sts_utility.decodeSTSMessage(ECDH_AED_accept) STS.STSConnectionStates[addrStr]['phase'] = 1 self.sock.sendto(ECDH_AED_accept, addr) # self.receive() elif STS.STSConnectionStates[addrStr]['cSuite'] in [3, 4, 5]: # print('=== GEN PROPOSE SALSA 4 ===') # print(binascii.hexlify(proposeResp['C']['K_E'])) salsaMsg = self.salsa20poly1305(data, addr) sts_utility.decodeSTSMessage(salsaMsg) # print(mySalsaSession) self.sock.sendto(salsaMsg, addr) # self.receive() else: self.terminate(addr)