OLD | NEW |
| 1 # Authors: |
| 2 # Trevor Perrin |
| 3 # Dave Baggett (Arcode Corporation) - canonicalCipherName |
| 4 # |
| 5 # See the LICENSE file for legal information regarding use of this file. |
| 6 |
1 """Class representing a TLS session.""" | 7 """Class representing a TLS session.""" |
2 | 8 |
3 from utils.compat import * | 9 from .utils.compat import * |
4 from mathtls import * | 10 from .mathtls import * |
5 from constants import * | 11 from .constants import * |
6 | 12 |
7 class Session: | 13 class Session(object): |
8 """ | 14 """ |
9 This class represents a TLS session. | 15 This class represents a TLS session. |
10 | 16 |
11 TLS distinguishes between connections and sessions. A new | 17 TLS distinguishes between connections and sessions. A new |
12 handshake creates both a connection and a session. Data is | 18 handshake creates both a connection and a session. Data is |
13 transmitted over the connection. | 19 transmitted over the connection. |
14 | 20 |
15 The session contains a more permanent record of the handshake. The | 21 The session contains a more permanent record of the handshake. The |
16 session can be inspected to determine handshake results. The | 22 session can be inspected to determine handshake results. The |
17 session can also be used to create a new connection through | 23 session can also be used to create a new connection through |
18 "session resumption". If the client and server both support this, | 24 "session resumption". If the client and server both support this, |
19 they can create a new connection based on an old session without | 25 they can create a new connection based on an old session without |
20 the overhead of a full handshake. | 26 the overhead of a full handshake. |
21 | 27 |
22 The session for a L{tlslite.TLSConnection.TLSConnection} can be | 28 The session for a L{tlslite.TLSConnection.TLSConnection} can be |
23 retrieved from the connection's 'session' attribute. | 29 retrieved from the connection's 'session' attribute. |
24 | 30 |
25 @type srpUsername: str | 31 @type srpUsername: str |
26 @ivar srpUsername: The client's SRP username (or None). | 32 @ivar srpUsername: The client's SRP username (or None). |
27 | 33 |
28 @type sharedKeyUsername: str | 34 @type clientCertChain: L{tlslite.x509certchain.X509CertChain} |
29 @ivar sharedKeyUsername: The client's shared-key username (or | |
30 None). | |
31 | |
32 @type clientCertChain: L{tlslite.X509CertChain.X509CertChain} or | |
33 L{cryptoIDlib.CertChain.CertChain} | |
34 @ivar clientCertChain: The client's certificate chain (or None). | 35 @ivar clientCertChain: The client's certificate chain (or None). |
35 | 36 |
36 @type serverCertChain: L{tlslite.X509CertChain.X509CertChain} or | 37 @type serverCertChain: L{tlslite.x509certchain.X509CertChain} |
37 L{cryptoIDlib.CertChain.CertChain} | |
38 @ivar serverCertChain: The server's certificate chain (or None). | 38 @ivar serverCertChain: The server's certificate chain (or None). |
| 39 |
| 40 @type tackExt: L{tack.structures.TackExtension.TackExtension} |
| 41 @ivar tackExt: The server's TackExtension (or None). |
| 42 |
| 43 @type tackInHelloExt: L{bool} |
| 44 @ivar tackInHelloExt: True if a TACK was presented via TLS Extension. |
39 """ | 45 """ |
40 | 46 |
41 def __init__(self): | 47 def __init__(self): |
42 self.masterSecret = createByteArraySequence([]) | 48 self.masterSecret = bytearray(0) |
43 self.sessionID = createByteArraySequence([]) | 49 self.sessionID = bytearray(0) |
44 self.cipherSuite = 0 | 50 self.cipherSuite = 0 |
45 self.srpUsername = None | 51 self.srpUsername = "" |
46 self.sharedKeyUsername = None | |
47 self.clientCertChain = None | 52 self.clientCertChain = None |
48 self.serverCertChain = None | 53 self.serverCertChain = None |
| 54 self.tackExt = None |
| 55 self.tackInHelloExt = False |
| 56 self.serverName = "" |
49 self.resumable = False | 57 self.resumable = False |
50 self.sharedKey = False | 58 |
| 59 def create(self, masterSecret, sessionID, cipherSuite, |
| 60 srpUsername, clientCertChain, serverCertChain, |
| 61 tackExt, tackInHelloExt, serverName, resumable=True): |
| 62 self.masterSecret = masterSecret |
| 63 self.sessionID = sessionID |
| 64 self.cipherSuite = cipherSuite |
| 65 self.srpUsername = srpUsername |
| 66 self.clientCertChain = clientCertChain |
| 67 self.serverCertChain = serverCertChain |
| 68 self.tackExt = tackExt |
| 69 self.tackInHelloExt = tackInHelloExt |
| 70 self.serverName = serverName |
| 71 self.resumable = resumable |
51 | 72 |
52 def _clone(self): | 73 def _clone(self): |
53 other = Session() | 74 other = Session() |
54 other.masterSecret = self.masterSecret | 75 other.masterSecret = self.masterSecret |
55 other.sessionID = self.sessionID | 76 other.sessionID = self.sessionID |
56 other.cipherSuite = self.cipherSuite | 77 other.cipherSuite = self.cipherSuite |
57 other.srpUsername = self.srpUsername | 78 other.srpUsername = self.srpUsername |
58 other.sharedKeyUsername = self.sharedKeyUsername | |
59 other.clientCertChain = self.clientCertChain | 79 other.clientCertChain = self.clientCertChain |
60 other.serverCertChain = self.serverCertChain | 80 other.serverCertChain = self.serverCertChain |
| 81 other.tackExt = self.tackExt |
| 82 other.tackInHelloExt = self.tackInHelloExt |
| 83 other.serverName = self.serverName |
61 other.resumable = self.resumable | 84 other.resumable = self.resumable |
62 other.sharedKey = self.sharedKey | |
63 return other | 85 return other |
64 | 86 |
65 def _calcMasterSecret(self, version, premasterSecret, clientRandom, | |
66 serverRandom): | |
67 if version == (3,0): | |
68 self.masterSecret = PRF_SSL(premasterSecret, | |
69 concatArrays(clientRandom, serverRandom), 48) | |
70 elif version in ((3,1), (3,2)): | |
71 self.masterSecret = PRF(premasterSecret, "master secret", | |
72 concatArrays(clientRandom, serverRandom), 48) | |
73 else: | |
74 raise AssertionError() | |
75 | |
76 def valid(self): | 87 def valid(self): |
77 """If this session can be used for session resumption. | 88 """If this session can be used for session resumption. |
78 | 89 |
79 @rtype: bool | 90 @rtype: bool |
80 @return: If this session can be used for session resumption. | 91 @return: If this session can be used for session resumption. |
81 """ | 92 """ |
82 return self.resumable or self.sharedKey | 93 return self.resumable and self.sessionID |
83 | 94 |
84 def _setResumable(self, boolean): | 95 def _setResumable(self, boolean): |
85 #Only let it be set if this isn't a shared key | 96 #Only let it be set to True if the sessionID is non-null |
86 if not self.sharedKey: | 97 if (not boolean) or (boolean and self.sessionID): |
87 #Only let it be set to True if the sessionID is non-null | 98 self.resumable = boolean |
88 if (not boolean) or (boolean and self.sessionID): | 99 |
89 self.resumable = boolean | 100 def getTackId(self): |
| 101 if self.tackExt and self.tackExt.tack: |
| 102 return self.tackExt.tack.getTackId() |
| 103 else: |
| 104 return None |
| 105 |
| 106 def getBreakSigs(self): |
| 107 if self.tackExt and self.tackExt.break_sigs: |
| 108 return self.tackExt.break_sigs |
| 109 else: |
| 110 return None |
90 | 111 |
91 def getCipherName(self): | 112 def getCipherName(self): |
92 """Get the name of the cipher used with this connection. | 113 """Get the name of the cipher used with this connection. |
93 | 114 |
94 @rtype: str | 115 @rtype: str |
95 @return: The name of the cipher used with this connection. | 116 @return: The name of the cipher used with this connection. |
96 Either 'aes128', 'aes256', 'rc4', or '3des'. | |
97 """ | 117 """ |
98 if self.cipherSuite in CipherSuite.aes128Suites: | 118 return CipherSuite.canonicalCipherName(self.cipherSuite) |
99 return "aes128" | 119 |
100 elif self.cipherSuite in CipherSuite.aes256Suites: | 120 def getMacName(self): |
101 return "aes256" | 121 """Get the name of the HMAC hash algo used with this connection. |
102 elif self.cipherSuite in CipherSuite.rc4Suites: | |
103 return "rc4" | |
104 elif self.cipherSuite in CipherSuite.tripleDESSuites: | |
105 return "3des" | |
106 else: | |
107 return None | |
108 | 122 |
109 def _createSharedKey(self, sharedKeyUsername, sharedKey): | 123 @rtype: str |
110 if len(sharedKeyUsername)>16: | 124 @return: The name of the HMAC hash algo used with this connection. |
111 raise ValueError() | 125 """ |
112 if len(sharedKey)>47: | 126 return CipherSuite.canonicalMacName(self.cipherSuite) |
113 raise ValueError() | |
114 | |
115 self.sharedKeyUsername = sharedKeyUsername | |
116 | |
117 self.sessionID = createByteArrayZeros(16) | |
118 for x in range(len(sharedKeyUsername)): | |
119 self.sessionID[x] = ord(sharedKeyUsername[x]) | |
120 | |
121 premasterSecret = createByteArrayZeros(48) | |
122 sharedKey = chr(len(sharedKey)) + sharedKey | |
123 for x in range(48): | |
124 premasterSecret[x] = ord(sharedKey[x % len(sharedKey)]) | |
125 | |
126 self.masterSecret = PRF(premasterSecret, "shared secret", | |
127 createByteArraySequence([]), 48) | |
128 self.sharedKey = True | |
129 return self | |
130 | |
131 | |
OLD | NEW |