| """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 |
| |
| |