def receiveTicket(self, data): """ Extract and verify a potential session ticket. The given `data' is treated as a session ticket. The ticket is being decrypted and authenticated (yes, in that order). If all these steps succeed, `True' is returned. Otherwise, `False' is returned. """ if len(data) < (const.TICKET_LENGTH + const.MARK_LENGTH + const.HMAC_SHA256_128_LENGTH): return False potentialTicket = data.peek() # Now try to decrypt and parse the ticket. We need the master key # inside to verify the HMAC in the next step. if not self.decryptedTicket: newTicket = ticket.decrypt(potentialTicket[:const.TICKET_LENGTH], self.srvState) if newTicket != None and newTicket.isValid(): self.deriveSecrets(newTicket.masterKey) self.decryptedTicket = True else: return False # First, find the mark to efficiently locate the HMAC. mark = mycrypto.HMAC_SHA256_128(self.recvHMAC, potentialTicket[:const.TICKET_LENGTH]) index = util.locateMark(mark, potentialTicket) if not index: return False # Now, verify if the HMAC is valid. existingHMAC = potentialTicket[index + const.MARK_LENGTH:index + const.MARK_LENGTH + const.HMAC_SHA256_128_LENGTH] authenticated = False for epoch in util.expandedEpoch(): myHMAC = mycrypto.HMAC_SHA256_128(self.recvHMAC, potentialTicket[0:index + \ const.MARK_LENGTH] + epoch) if util.isValidHMAC(myHMAC, existingHMAC, self.recvHMAC): authenticated = True break log.debug("HMAC invalid. Trying next epoch value.") if not authenticated: log.warning("Could not verify the authentication message's HMAC.") return False # Do nothing if the ticket is replayed. Immediately closing the # connection would be suspicious. if self.srvState.isReplayed(existingHMAC): log.warning("The HMAC was already present in the replay table.") return False data.drain(index + const.MARK_LENGTH + const.HMAC_SHA256_128_LENGTH) log.debug("Adding the HMAC authenticating the ticket message to the " \ "replay table: %s." % existingHMAC.encode('hex')) self.srvState.registerKey(existingHMAC) log.debug("Switching to state ST_CONNECTED.") self.protoState = const.ST_CONNECTED return True
def receiveTicket( self, data ): """ Extract and verify a potential session ticket. The given `data' is treated as a session ticket. The ticket is being decrypted and authenticated (yes, in that order). If all these steps succeed, `True' is returned. Otherwise, `False' is returned. """ if len(data) < (const.TICKET_LENGTH + const.MARK_LENGTH + const.HMAC_SHA256_128_LENGTH): return False potentialTicket = data.peek() # Now try to decrypt and parse the ticket. We need the master key # inside to verify the HMAC in the next step. if not self.decryptedTicket: newTicket = ticket.decrypt(potentialTicket[:const.TICKET_LENGTH], self.srvState) if newTicket != None and newTicket.isValid(): self.deriveSecrets(newTicket.masterKey) self.decryptedTicket = True else: return False # First, find the mark to efficiently locate the HMAC. mark = mycrypto.HMAC_SHA256_128(self.recvHMAC, potentialTicket[:const.TICKET_LENGTH]) index = util.locateMark(mark, potentialTicket) if not index: return False # Now, verify if the HMAC is valid. existingHMAC = potentialTicket[index + const.MARK_LENGTH: index + const.MARK_LENGTH + const.HMAC_SHA256_128_LENGTH] authenticated = False for epoch in util.expandedEpoch(): myHMAC = mycrypto.HMAC_SHA256_128(self.recvHMAC, potentialTicket[0:index + \ const.MARK_LENGTH] + epoch) if util.isValidHMAC(myHMAC, existingHMAC, self.recvHMAC): authenticated = True break log.debug("HMAC invalid. Trying next epoch value.") if not authenticated: log.warning("Could not verify the authentication message's HMAC.") return False # Do nothing if the ticket is replayed. Immediately closing the # connection would be suspicious. if self.srvState.isReplayed(existingHMAC): log.warning("The HMAC was already present in the replay table.") return False data.drain(index + const.MARK_LENGTH + const.HMAC_SHA256_128_LENGTH) log.debug("Adding the HMAC authenticating the ticket message to the " \ "replay table: %s." % existingHMAC.encode('hex')) self.srvState.registerKey(existingHMAC) log.debug("Switching to state ST_CONNECTED.") self.protoState = const.ST_CONNECTED return True