132 lines
4.6 KiB
Python
132 lines
4.6 KiB
Python
|
"""Class representing a TLS session."""
|
||
|
|
||
|
from utils.compat import *
|
||
|
from mathtls import *
|
||
|
from constants import *
|
||
|
|
||
|
class Session:
|
||
|
"""
|
||
|
This class represents a TLS session.
|
||
|
|
||
|
TLS distinguishes between connections and sessions. A new
|
||
|
handshake creates both a connection and a session. Data is
|
||
|
transmitted over the connection.
|
||
|
|
||
|
The session contains a more permanent record of the handshake. The
|
||
|
session can be inspected to determine handshake results. The
|
||
|
session can also be used to create a new connection through
|
||
|
"session resumption". If the client and server both support this,
|
||
|
they can create a new connection based on an old session without
|
||
|
the overhead of a full handshake.
|
||
|
|
||
|
The session for a L{tlslite.TLSConnection.TLSConnection} can be
|
||
|
retrieved from the connection's 'session' attribute.
|
||
|
|
||
|
@type srpUsername: str
|
||
|
@ivar srpUsername: The client's SRP username (or None).
|
||
|
|
||
|
@type sharedKeyUsername: str
|
||
|
@ivar sharedKeyUsername: The client's shared-key username (or
|
||
|
None).
|
||
|
|
||
|
@type clientCertChain: L{tlslite.X509CertChain.X509CertChain} or
|
||
|
L{cryptoIDlib.CertChain.CertChain}
|
||
|
@ivar clientCertChain: The client's certificate chain (or None).
|
||
|
|
||
|
@type serverCertChain: L{tlslite.X509CertChain.X509CertChain} or
|
||
|
L{cryptoIDlib.CertChain.CertChain}
|
||
|
@ivar serverCertChain: The server's certificate chain (or None).
|
||
|
"""
|
||
|
|
||
|
def __init__(self):
|
||
|
self.masterSecret = createByteArraySequence([])
|
||
|
self.sessionID = createByteArraySequence([])
|
||
|
self.cipherSuite = 0
|
||
|
self.srpUsername = None
|
||
|
self.sharedKeyUsername = None
|
||
|
self.clientCertChain = None
|
||
|
self.serverCertChain = None
|
||
|
self.resumable = False
|
||
|
self.sharedKey = False
|
||
|
|
||
|
def _clone(self):
|
||
|
other = Session()
|
||
|
other.masterSecret = self.masterSecret
|
||
|
other.sessionID = self.sessionID
|
||
|
other.cipherSuite = self.cipherSuite
|
||
|
other.srpUsername = self.srpUsername
|
||
|
other.sharedKeyUsername = self.sharedKeyUsername
|
||
|
other.clientCertChain = self.clientCertChain
|
||
|
other.serverCertChain = self.serverCertChain
|
||
|
other.resumable = self.resumable
|
||
|
other.sharedKey = self.sharedKey
|
||
|
return other
|
||
|
|
||
|
def _calcMasterSecret(self, version, premasterSecret, clientRandom,
|
||
|
serverRandom):
|
||
|
if version == (3,0):
|
||
|
self.masterSecret = PRF_SSL(premasterSecret,
|
||
|
concatArrays(clientRandom, serverRandom), 48)
|
||
|
elif version in ((3,1), (3,2)):
|
||
|
self.masterSecret = PRF(premasterSecret, "master secret",
|
||
|
concatArrays(clientRandom, serverRandom), 48)
|
||
|
else:
|
||
|
raise AssertionError()
|
||
|
|
||
|
def valid(self):
|
||
|
"""If this session can be used for session resumption.
|
||
|
|
||
|
@rtype: bool
|
||
|
@return: If this session can be used for session resumption.
|
||
|
"""
|
||
|
return self.resumable or self.sharedKey
|
||
|
|
||
|
def _setResumable(self, boolean):
|
||
|
#Only let it be set if this isn't a shared key
|
||
|
if not self.sharedKey:
|
||
|
#Only let it be set to True if the sessionID is non-null
|
||
|
if (not boolean) or (boolean and self.sessionID):
|
||
|
self.resumable = boolean
|
||
|
|
||
|
def getCipherName(self):
|
||
|
"""Get the name of the cipher used with this connection.
|
||
|
|
||
|
@rtype: str
|
||
|
@return: The name of the cipher used with this connection.
|
||
|
Either 'aes128', 'aes256', 'rc4', or '3des'.
|
||
|
"""
|
||
|
if self.cipherSuite in CipherSuite.aes128Suites:
|
||
|
return "aes128"
|
||
|
elif self.cipherSuite in CipherSuite.aes256Suites:
|
||
|
return "aes256"
|
||
|
elif self.cipherSuite in CipherSuite.rc4Suites:
|
||
|
return "rc4"
|
||
|
elif self.cipherSuite in CipherSuite.tripleDESSuites:
|
||
|
return "3des"
|
||
|
else:
|
||
|
return None
|
||
|
|
||
|
def _createSharedKey(self, sharedKeyUsername, sharedKey):
|
||
|
if len(sharedKeyUsername)>16:
|
||
|
raise ValueError()
|
||
|
if len(sharedKey)>47:
|
||
|
raise ValueError()
|
||
|
|
||
|
self.sharedKeyUsername = sharedKeyUsername
|
||
|
|
||
|
self.sessionID = createByteArrayZeros(16)
|
||
|
for x in range(len(sharedKeyUsername)):
|
||
|
self.sessionID[x] = ord(sharedKeyUsername[x])
|
||
|
|
||
|
premasterSecret = createByteArrayZeros(48)
|
||
|
sharedKey = chr(len(sharedKey)) + sharedKey
|
||
|
for x in range(48):
|
||
|
premasterSecret[x] = ord(sharedKey[x % len(sharedKey)])
|
||
|
|
||
|
self.masterSecret = PRF(premasterSecret, "shared secret",
|
||
|
createByteArraySequence([]), 48)
|
||
|
self.sharedKey = True
|
||
|
return self
|
||
|
|
||
|
|