def terminate(self, addr): print('=== SEND TERMINATE ===', addr) addrStr = sts_utility.addrToString(addr) if addrStr not in STS.STSConnectionStates.keys(): terminate = struct.pack( '>BI', 3, len((0).to_bytes( 8, byteorder='big'))) + (0).to_bytes(8, byteorder='big') self.sock.sendto(terminate, addr) elif STS.STSConnectionStates[addrStr]['session_key'] is not None: terminate = self.constructSTSResponse( 3, addr, sts_utility.timestampPacked()) self.sock.sendto(terminate, addr) STS.STSConnectionStates.pop(addrStr) else: terminate = struct.pack( '>BI', 3, len((0).to_bytes( 8, byteorder='big'))) + (0).to_bytes(8, byteorder='big') self.sock.sendto(terminate, addr) STS.STSConnectionStates.pop(addrStr)
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)
def salsa20poly1305(self, data, addr, server=False): salsaMsg = None addrStr = sts_utility.addrToString(addr) # myCert, myCertStatus = sts_utility.decodeMyCertificate(self.sock, self.endpoint_address) # myEncrypKey, mySignKey = sts_utility.decodeSecretKey() if not server: if STS.STSConnectionStates[addrStr]['cSuite'] == 3: mySalsaSession = pysodium.randombytes(32) proposeResp = sts_utility.deconstructPropose(data) salsaMsg = self.genProposeSalsa(proposeResp['P'], proposeResp['C']['K_E'], mySalsaSession, self.myEncrypKey, self.mySignKey, self.myCert, self.myCertStatus) STS.STSConnectionStates[addrStr][ 'session_key'] = mySalsaSession STS.STSConnectionStates[addrStr]['cSuite'] = proposeResp['P'] STS.STSConnectionStates[addrStr]['time'] = int(time.time()) elif STS.STSConnectionStates[addrStr]['cSuite'] in [4, 5]: STS.STSConnectionStates[addrStr]['phase'] = 1 salsaMsg = self.constructSTSResponse( 1, addr, sts_utility.timestampPacked()) else: proposeReq = sts_utility.deconstructPropose(data) if STS.STSConnectionStates[addrStr][ 'cSuite'] == 3 and STS.STSConnectionStates[addrStr][ 'phase'] == 0: # mySalsaSession = pysodium.randombytes(32) salsaMsg = self.genProposeSalsa(4, proposeReq['C']['K_E'], (0).to_bytes(32, byteorder='big'), self.myEncrypKey, self.mySignKey, self.myCert, self.myCertStatus) STS.STSConnectionStates[addrStr]['session_key'] = (0).to_bytes( 32, byteorder='big') STS.STSConnectionStates[addrStr]['cSuite'] = 4 STS.STSConnectionStates[addrStr]['time'] = int(time.time()) elif STS.STSConnectionStates[addrStr]['cSuite'] in [ 4, 5 ] and STS.STSConnectionStates[addrStr]['phase'] == 0: session_key = self.decryptSalsaSession(proposeReq, self.myEncrypKey) if not session_key: salsaMsg = self.genProposeSalsa( STS.STSConnectionStates[addrStr]['cSuite'], proposeReq['C']['K_E'], (0).to_bytes(32, byteorder='big'), self.myEncrypKey, self.mySignKey, self.myCert, self.myCertStatus) STS.STSConnectionStates[addrStr]['session_key'] = ( 0).to_bytes(32, byteorder='big') STS.STSConnectionStates[addrStr][ 'cSuite'] = STS.STSConnectionStates[addrStr]['cSuite'] STS.STSConnectionStates[addrStr]['time'] = int(time.time()) else: STS.STSConnectionStates[addrStr][ 'session_key'] = session_key # STS.STSConnectionStates[addrStr]['phase'] = 1 salsaMsg = self.genProposeSalsa( 4, proposeReq['C']['K_E'], (0).to_bytes(32, byteorder='big'), self.myEncrypKey, self.mySignKey, self.myCert, self.myCertStatus) STS.STSConnectionStates[addrStr]['cSuite'] = proposeReq[ 'P'] # STS.STSConnectionStates[addrStr]['phase'] = 1 STS.STSConnectionStates[addrStr]['time'] = int(time.time()) # elif STS.STSConnectionStates[addrStr]['cSuite'] in [4, 5] and STS.STSConnectionStates[addrStr][ # 'phase'] == 1: # STS.STSConnectionStates[addrStr]['phase'] = 2 # salsaMsg = self.constructSTSResponse(1, addr, sts_utility.timestampPacked()) # salsaMsg = self.constructSTSResponse(1, addr, sts_utility.timestampPacked()) return salsaMsg