OLD | NEW |
| 1 # Authors: |
| 2 # Trevor Perrin |
| 3 # Google - added reqCAs parameter |
| 4 # Google (adapted by Sam Rushing and Marcelo Fernandez) - NPN support |
| 5 # Dimitris Moraitis - Anon ciphersuites |
| 6 # Martin von Loewis - python 3 port |
| 7 # |
| 8 # See the LICENSE file for legal information regarding use of this file. |
| 9 |
1 """ | 10 """ |
2 MAIN CLASS FOR TLS LITE (START HERE!). | 11 MAIN CLASS FOR TLS LITE (START HERE!). |
3 """ | 12 """ |
4 from __future__ import generators | |
5 | 13 |
6 import socket | 14 import socket |
7 from utils.compat import formatExceptionTrace | 15 from .utils.compat import formatExceptionTrace |
8 from tlsrecordlayer import TLSRecordLayer | 16 from .tlsrecordlayer import TLSRecordLayer |
9 from session import Session | 17 from .session import Session |
10 from constants import * | 18 from .constants import * |
11 from utils.cryptomath import getRandomBytes | 19 from .utils.cryptomath import getRandomBytes |
12 from errors import * | 20 from .errors import * |
13 from messages import * | 21 from .messages import * |
14 from mathtls import * | 22 from .mathtls import * |
15 from handshakesettings import HandshakeSettings | 23 from .handshakesettings import HandshakeSettings |
| 24 from .utils.tackwrapper import * |
16 | 25 |
17 | 26 |
18 class TLSConnection(TLSRecordLayer): | 27 class TLSConnection(TLSRecordLayer): |
19 """ | 28 """ |
20 This class wraps a socket and provides TLS handshaking and data | 29 This class wraps a socket and provides TLS handshaking and data |
21 transfer. | 30 transfer. |
22 | 31 |
23 To use this class, create a new instance, passing a connected | 32 To use this class, create a new instance, passing a connected |
24 socket into the constructor. Then call some handshake function. | 33 socket into the constructor. Then call some handshake function. |
25 If the handshake completes without raising an exception, then a TLS | 34 If the handshake completes without raising an exception, then a TLS |
26 connection has been negotiated. You can transfer data over this | 35 connection has been negotiated. You can transfer data over this |
27 connection as if it were a socket. | 36 connection as if it were a socket. |
28 | 37 |
29 This class provides both synchronous and asynchronous versions of | 38 This class provides both synchronous and asynchronous versions of |
30 its key functions. The synchronous versions should be used when | 39 its key functions. The synchronous versions should be used when |
31 writing single-or multi-threaded code using blocking sockets. The | 40 writing single-or multi-threaded code using blocking sockets. The |
32 asynchronous versions should be used when performing asynchronous, | 41 asynchronous versions should be used when performing asynchronous, |
33 event-based I/O with non-blocking sockets. | 42 event-based I/O with non-blocking sockets. |
34 | 43 |
35 Asynchronous I/O is a complicated subject; typically, you should | 44 Asynchronous I/O is a complicated subject; typically, you should |
36 not use the asynchronous functions directly, but should use some | 45 not use the asynchronous functions directly, but should use some |
37 framework like asyncore or Twisted which TLS Lite integrates with | 46 framework like asyncore or Twisted which TLS Lite integrates with |
38 (see | 47 (see |
39 L{tlslite.integration.TLSAsyncDispatcherMixIn.TLSAsyncDispatcherMixIn} or | 48 L{tlslite.integration.tlsasyncdispatchermixin.TLSAsyncDispatcherMixIn}). |
40 L{tlslite.integration.TLSTwistedProtocolWrapper.TLSTwistedProtocolWrapper}). | |
41 """ | 49 """ |
42 | 50 |
43 | |
44 def __init__(self, sock): | 51 def __init__(self, sock): |
45 """Create a new TLSConnection instance. | 52 """Create a new TLSConnection instance. |
46 | 53 |
47 @param sock: The socket data will be transmitted on. The | 54 @param sock: The socket data will be transmitted on. The |
48 socket should already be connected. It may be in blocking or | 55 socket should already be connected. It may be in blocking or |
49 non-blocking mode. | 56 non-blocking mode. |
50 | 57 |
51 @type sock: L{socket.socket} | 58 @type sock: L{socket.socket} |
52 """ | 59 """ |
53 TLSRecordLayer.__init__(self, sock) | 60 TLSRecordLayer.__init__(self, sock) |
54 | 61 |
55 def handshakeClientSRP(self, username, password, session=None, | 62 #********************************************************* |
56 settings=None, checker=None, async=False): | 63 # Client Handshake Functions |
57 """Perform an SRP handshake in the role of client. | 64 #********************************************************* |
58 | 65 |
59 This function performs a TLS/SRP handshake. SRP mutually | 66 def handshakeClientAnonymous(self, session=None, settings=None, |
60 authenticates both parties to each other using only a | 67 checker=None, serverName="", |
61 username and password. This function may also perform a | 68 async=False): |
62 combined SRP and server-certificate handshake, if the server | 69 """Perform an anonymous handshake in the role of client. |
63 chooses to authenticate itself with a certificate chain in | |
64 addition to doing SRP. | |
65 | 70 |
66 TLS/SRP is non-standard. Most TLS implementations don't | 71 This function performs an SSL or TLS handshake using an |
67 support it. See | 72 anonymous Diffie Hellman ciphersuite. |
68 U{http://www.ietf.org/html.charters/tls-charter.html} or | 73 |
69 U{http://trevp.net/tlssrp/} for the latest information on | |
70 TLS/SRP. | |
71 | |
72 Like any handshake function, this can be called on a closed | 74 Like any handshake function, this can be called on a closed |
73 TLS connection, or on a TLS connection that is already open. | 75 TLS connection, or on a TLS connection that is already open. |
74 If called on an open connection it performs a re-handshake. | 76 If called on an open connection it performs a re-handshake. |
75 | 77 |
76 If the function completes without raising an exception, the | 78 If the function completes without raising an exception, the |
77 TLS connection will be open and available for data transfer. | 79 TLS connection will be open and available for data transfer. |
78 | 80 |
79 If an exception is raised, the connection will have been | 81 If an exception is raised, the connection will have been |
80 automatically closed (if it was ever open). | 82 automatically closed (if it was ever open). |
81 | 83 |
82 @type username: str | |
83 @param username: The SRP username. | |
84 | |
85 @type password: str | |
86 @param password: The SRP password. | |
87 | |
88 @type session: L{tlslite.Session.Session} | 84 @type session: L{tlslite.Session.Session} |
89 @param session: A TLS session to attempt to resume. This | 85 @param session: A TLS session to attempt to resume. If the |
90 session must be an SRP session performed with the same username | 86 resumption does not succeed, a full handshake will be |
91 and password as were passed in. If the resumption does not | 87 performed. |
92 succeed, a full SRP handshake will be performed. | |
93 | 88 |
94 @type settings: L{tlslite.HandshakeSettings.HandshakeSettings} | 89 @type settings: L{tlslite.HandshakeSettings.HandshakeSettings} |
95 @param settings: Various settings which can be used to control | 90 @param settings: Various settings which can be used to control |
96 the ciphersuites, certificate types, and SSL/TLS versions | 91 the ciphersuites, certificate types, and SSL/TLS versions |
97 offered by the client. | 92 offered by the client. |
98 | 93 |
99 @type checker: L{tlslite.Checker.Checker} | 94 @type checker: L{tlslite.Checker.Checker} |
100 @param checker: A Checker instance. This instance will be | 95 @param checker: A Checker instance. This instance will be |
101 invoked to examine the other party's authentication | 96 invoked to examine the other party's authentication |
102 credentials, if the handshake completes succesfully. | 97 credentials, if the handshake completes succesfully. |
| 98 |
| 99 @type serverName: string |
| 100 @param serverName: The ServerNameIndication TLS Extension. |
103 | 101 |
104 @type async: bool | 102 @type async: bool |
105 @param async: If False, this function will block until the | 103 @param async: If False, this function will block until the |
106 handshake is completed. If True, this function will return a | 104 handshake is completed. If True, this function will return a |
107 generator. Successive invocations of the generator will | 105 generator. Successive invocations of the generator will |
108 return 0 if it is waiting to read from the socket, 1 if it is | 106 return 0 if it is waiting to read from the socket, 1 if it is |
109 waiting to write to the socket, or will raise StopIteration if | 107 waiting to write to the socket, or will raise StopIteration if |
110 the handshake operation is completed. | 108 the handshake operation is completed. |
111 | 109 |
112 @rtype: None or an iterable | 110 @rtype: None or an iterable |
113 @return: If 'async' is True, a generator object will be | 111 @return: If 'async' is True, a generator object will be |
114 returned. | 112 returned. |
115 | 113 |
116 @raise socket.error: If a socket error occurs. | 114 @raise socket.error: If a socket error occurs. |
117 @raise tlslite.errors.TLSAbruptCloseError: If the socket is closed | 115 @raise tlslite.errors.TLSAbruptCloseError: If the socket is closed |
118 without a preceding alert. | 116 without a preceding alert. |
119 @raise tlslite.errors.TLSAlert: If a TLS alert is signalled. | 117 @raise tlslite.errors.TLSAlert: If a TLS alert is signalled. |
120 @raise tlslite.errors.TLSAuthenticationError: If the checker | 118 @raise tlslite.errors.TLSAuthenticationError: If the checker |
121 doesn't like the other party's authentication credentials. | 119 doesn't like the other party's authentication credentials. |
122 """ | 120 """ |
123 handshaker = self._handshakeClientAsync(srpParams=(username, password), | 121 handshaker = self._handshakeClientAsync(anonParams=(True), |
124 session=session, settings=settings, checker=checker) | 122 session=session, |
| 123 settings=settings, |
| 124 checker=checker, |
| 125 serverName=serverName) |
125 if async: | 126 if async: |
126 return handshaker | 127 return handshaker |
127 for result in handshaker: | 128 for result in handshaker: |
128 pass | 129 pass |
129 | 130 |
130 def handshakeClientCert(self, certChain=None, privateKey=None, | 131 def handshakeClientSRP(self, username, password, session=None, |
131 session=None, settings=None, checker=None, | 132 settings=None, checker=None, |
132 async=False): | 133 reqTack=True, serverName="", |
133 """Perform a certificate-based handshake in the role of client. | 134 async=False): |
| 135 """Perform an SRP handshake in the role of client. |
134 | 136 |
135 This function performs an SSL or TLS handshake. The server | 137 This function performs a TLS/SRP handshake. SRP mutually |
136 will authenticate itself using an X.509 or cryptoID certificate | 138 authenticates both parties to each other using only a |
137 chain. If the handshake succeeds, the server's certificate | 139 username and password. This function may also perform a |
138 chain will be stored in the session's serverCertChain attribute. | 140 combined SRP and server-certificate handshake, if the server |
139 Unless a checker object is passed in, this function does no | 141 chooses to authenticate itself with a certificate chain in |
140 validation or checking of the server's certificate chain. | 142 addition to doing SRP. |
141 | |
142 If the server requests client authentication, the | |
143 client will send the passed-in certificate chain, and use the | |
144 passed-in private key to authenticate itself. If no | |
145 certificate chain and private key were passed in, the client | |
146 will attempt to proceed without client authentication. The | |
147 server may or may not allow this. | |
148 | |
149 Like any handshake function, this can be called on a closed | |
150 TLS connection, or on a TLS connection that is already open. | |
151 If called on an open connection it performs a re-handshake. | |
152 | 143 |
153 If the function completes without raising an exception, the | 144 If the function completes without raising an exception, the |
154 TLS connection will be open and available for data transfer. | 145 TLS connection will be open and available for data transfer. |
155 | 146 |
156 If an exception is raised, the connection will have been | 147 If an exception is raised, the connection will have been |
157 automatically closed (if it was ever open). | 148 automatically closed (if it was ever open). |
158 | 149 |
159 @type certChain: L{tlslite.X509CertChain.X509CertChain} or | 150 @type username: str |
160 L{cryptoIDlib.CertChain.CertChain} | 151 @param username: The SRP username. |
161 @param certChain: The certificate chain to be used if the | |
162 server requests client authentication. | |
163 | 152 |
164 @type privateKey: L{tlslite.utils.RSAKey.RSAKey} | 153 @type password: str |
165 @param privateKey: The private key to be used if the server | 154 @param password: The SRP password. |
166 requests client authentication. | |
167 | 155 |
168 @type session: L{tlslite.Session.Session} | 156 @type session: L{tlslite.session.Session} |
169 @param session: A TLS session to attempt to resume. If the | 157 @param session: A TLS session to attempt to resume. This |
170 resumption does not succeed, a full handshake will be | 158 session must be an SRP session performed with the same username |
171 performed. | 159 and password as were passed in. If the resumption does not |
| 160 succeed, a full SRP handshake will be performed. |
172 | 161 |
173 @type settings: L{tlslite.HandshakeSettings.HandshakeSettings} | 162 @type settings: L{tlslite.handshakesettings.HandshakeSettings} |
174 @param settings: Various settings which can be used to control | 163 @param settings: Various settings which can be used to control |
175 the ciphersuites, certificate types, and SSL/TLS versions | 164 the ciphersuites, certificate types, and SSL/TLS versions |
176 offered by the client. | 165 offered by the client. |
177 | 166 |
178 @type checker: L{tlslite.Checker.Checker} | 167 @type checker: L{tlslite.checker.Checker} |
179 @param checker: A Checker instance. This instance will be | 168 @param checker: A Checker instance. This instance will be |
180 invoked to examine the other party's authentication | 169 invoked to examine the other party's authentication |
181 credentials, if the handshake completes succesfully. | 170 credentials, if the handshake completes succesfully. |
182 | 171 |
| 172 @type reqTack: bool |
| 173 @param reqTack: Whether or not to send a "tack" TLS Extension, |
| 174 requesting the server return a TackExtension if it has one. |
| 175 |
| 176 @type serverName: string |
| 177 @param serverName: The ServerNameIndication TLS Extension. |
| 178 |
183 @type async: bool | 179 @type async: bool |
184 @param async: If False, this function will block until the | 180 @param async: If False, this function will block until the |
185 handshake is completed. If True, this function will return a | 181 handshake is completed. If True, this function will return a |
186 generator. Successive invocations of the generator will | 182 generator. Successive invocations of the generator will |
187 return 0 if it is waiting to read from the socket, 1 if it is | 183 return 0 if it is waiting to read from the socket, 1 if it is |
188 waiting to write to the socket, or will raise StopIteration if | 184 waiting to write to the socket, or will raise StopIteration if |
189 the handshake operation is completed. | 185 the handshake operation is completed. |
190 | 186 |
191 @rtype: None or an iterable | 187 @rtype: None or an iterable |
192 @return: If 'async' is True, a generator object will be | 188 @return: If 'async' is True, a generator object will be |
193 returned. | 189 returned. |
194 | 190 |
195 @raise socket.error: If a socket error occurs. | 191 @raise socket.error: If a socket error occurs. |
196 @raise tlslite.errors.TLSAbruptCloseError: If the socket is closed | 192 @raise tlslite.errors.TLSAbruptCloseError: If the socket is closed |
197 without a preceding alert. | 193 without a preceding alert. |
198 @raise tlslite.errors.TLSAlert: If a TLS alert is signalled. | 194 @raise tlslite.errors.TLSAlert: If a TLS alert is signalled. |
199 @raise tlslite.errors.TLSAuthenticationError: If the checker | 195 @raise tlslite.errors.TLSAuthenticationError: If the checker |
200 doesn't like the other party's authentication credentials. | 196 doesn't like the other party's authentication credentials. |
201 """ | 197 """ |
202 handshaker = self._handshakeClientAsync(certParams=(certChain, | 198 handshaker = self._handshakeClientAsync(srpParams=(username, password), |
203 privateKey), session=session, settings=settings, | 199 session=session, settings=settings, checker=checker, |
204 checker=checker) | 200 reqTack=reqTack, serverName=serverName) |
| 201 # The handshaker is a Python Generator which executes the handshake. |
| 202 # It allows the handshake to be run in a "piecewise", asynchronous |
| 203 # fashion, returning 1 when it is waiting to able to write, 0 when |
| 204 # it is waiting to read. |
| 205 # |
| 206 # If 'async' is True, the generator is returned to the caller, |
| 207 # otherwise it is executed to completion here. |
205 if async: | 208 if async: |
206 return handshaker | 209 return handshaker |
207 for result in handshaker: | 210 for result in handshaker: |
208 pass | 211 pass |
209 | 212 |
210 def handshakeClientUnknown(self, srpCallback=None, certCallback=None, | 213 def handshakeClientCert(self, certChain=None, privateKey=None, |
211 session=None, settings=None, checker=None, | 214 session=None, settings=None, checker=None, |
212 async=False): | 215 nextProtos=None, reqTack=True, serverName="", |
213 """Perform a to-be-determined type of handshake in the role of client. | 216 async=False): |
| 217 """Perform a certificate-based handshake in the role of client. |
214 | 218 |
215 This function performs an SSL or TLS handshake. If the server | 219 This function performs an SSL or TLS handshake. The server |
216 requests client certificate authentication, the | 220 will authenticate itself using an X.509 certificate |
217 certCallback will be invoked and should return a (certChain, | 221 chain. If the handshake succeeds, the server's certificate |
218 privateKey) pair. If the callback returns None, the library | 222 chain will be stored in the session's serverCertChain attribute. |
| 223 Unless a checker object is passed in, this function does no |
| 224 validation or checking of the server's certificate chain. |
| 225 |
| 226 If the server requests client authentication, the |
| 227 client will send the passed-in certificate chain, and use the |
| 228 passed-in private key to authenticate itself. If no |
| 229 certificate chain and private key were passed in, the client |
219 will attempt to proceed without client authentication. The | 230 will attempt to proceed without client authentication. The |
220 server may or may not allow this. | 231 server may or may not allow this. |
221 | 232 |
222 If the server requests SRP authentication, the srpCallback | |
223 will be invoked and should return a (username, password) pair. | |
224 If the callback returns None, the local implementation will | |
225 signal a user_canceled error alert. | |
226 | |
227 After the handshake completes, the client can inspect the | |
228 connection's session attribute to determine what type of | |
229 authentication was performed. | |
230 | |
231 Like any handshake function, this can be called on a closed | |
232 TLS connection, or on a TLS connection that is already open. | |
233 If called on an open connection it performs a re-handshake. | |
234 | |
235 If the function completes without raising an exception, the | 233 If the function completes without raising an exception, the |
236 TLS connection will be open and available for data transfer. | 234 TLS connection will be open and available for data transfer. |
237 | 235 |
238 If an exception is raised, the connection will have been | 236 If an exception is raised, the connection will have been |
239 automatically closed (if it was ever open). | 237 automatically closed (if it was ever open). |
240 | 238 |
241 @type srpCallback: callable | 239 @type certChain: L{tlslite.x509certchain.X509CertChain} |
242 @param srpCallback: The callback to be used if the server | 240 @param certChain: The certificate chain to be used if the |
243 requests SRP authentication. If None, the client will not | 241 server requests client authentication. |
244 offer support for SRP ciphersuites. | |
245 | 242 |
246 @type certCallback: callable | 243 @type privateKey: L{tlslite.utils.rsakey.RSAKey} |
247 @param certCallback: The callback to be used if the server | 244 @param privateKey: The private key to be used if the server |
248 requests client certificate authentication. | 245 requests client authentication. |
249 | 246 |
250 @type session: L{tlslite.Session.Session} | 247 @type session: L{tlslite.session.Session} |
251 @param session: A TLS session to attempt to resume. If the | 248 @param session: A TLS session to attempt to resume. If the |
252 resumption does not succeed, a full handshake will be | 249 resumption does not succeed, a full handshake will be |
253 performed. | 250 performed. |
254 | 251 |
255 @type settings: L{tlslite.HandshakeSettings.HandshakeSettings} | 252 @type settings: L{tlslite.handshakesettings.HandshakeSettings} |
256 @param settings: Various settings which can be used to control | 253 @param settings: Various settings which can be used to control |
257 the ciphersuites, certificate types, and SSL/TLS versions | 254 the ciphersuites, certificate types, and SSL/TLS versions |
258 offered by the client. | 255 offered by the client. |
259 | 256 |
260 @type checker: L{tlslite.Checker.Checker} | 257 @type checker: L{tlslite.checker.Checker} |
261 @param checker: A Checker instance. This instance will be | 258 @param checker: A Checker instance. This instance will be |
262 invoked to examine the other party's authentication | 259 invoked to examine the other party's authentication |
263 credentials, if the handshake completes succesfully. | 260 credentials, if the handshake completes succesfully. |
| 261 |
| 262 @type nextProtos: list of strings. |
| 263 @param nextProtos: A list of upper layer protocols ordered by |
| 264 preference, to use in the Next-Protocol Negotiation Extension. |
| 265 |
| 266 @type reqTack: bool |
| 267 @param reqTack: Whether or not to send a "tack" TLS Extension, |
| 268 requesting the server return a TackExtension if it has one. |
| 269 |
| 270 @type serverName: string |
| 271 @param serverName: The ServerNameIndication TLS Extension. |
264 | 272 |
265 @type async: bool | 273 @type async: bool |
266 @param async: If False, this function will block until the | 274 @param async: If False, this function will block until the |
267 handshake is completed. If True, this function will return a | 275 handshake is completed. If True, this function will return a |
268 generator. Successive invocations of the generator will | 276 generator. Successive invocations of the generator will |
269 return 0 if it is waiting to read from the socket, 1 if it is | 277 return 0 if it is waiting to read from the socket, 1 if it is |
270 waiting to write to the socket, or will raise StopIteration if | 278 waiting to write to the socket, or will raise StopIteration if |
271 the handshake operation is completed. | 279 the handshake operation is completed. |
272 | 280 |
273 @rtype: None or an iterable | 281 @rtype: None or an iterable |
274 @return: If 'async' is True, a generator object will be | 282 @return: If 'async' is True, a generator object will be |
275 returned. | 283 returned. |
276 | 284 |
277 @raise socket.error: If a socket error occurs. | 285 @raise socket.error: If a socket error occurs. |
278 @raise tlslite.errors.TLSAbruptCloseError: If the socket is closed | 286 @raise tlslite.errors.TLSAbruptCloseError: If the socket is closed |
279 without a preceding alert. | 287 without a preceding alert. |
280 @raise tlslite.errors.TLSAlert: If a TLS alert is signalled. | 288 @raise tlslite.errors.TLSAlert: If a TLS alert is signalled. |
281 @raise tlslite.errors.TLSAuthenticationError: If the checker | 289 @raise tlslite.errors.TLSAuthenticationError: If the checker |
282 doesn't like the other party's authentication credentials. | 290 doesn't like the other party's authentication credentials. |
283 """ | 291 """ |
284 handshaker = self._handshakeClientAsync(unknownParams=(srpCallback, | 292 handshaker = self._handshakeClientAsync(certParams=(certChain, |
285 certCallback), session=session, settings=settings, | 293 privateKey), session=session, settings=settings, |
286 checker=checker) | 294 checker=checker, serverName=serverName, |
| 295 nextProtos=nextProtos, reqTack=reqTack) |
| 296 # The handshaker is a Python Generator which executes the handshake. |
| 297 # It allows the handshake to be run in a "piecewise", asynchronous |
| 298 # fashion, returning 1 when it is waiting to able to write, 0 when |
| 299 # it is waiting to read. |
| 300 # |
| 301 # If 'async' is True, the generator is returned to the caller, |
| 302 # otherwise it is executed to completion here. |
287 if async: | 303 if async: |
288 return handshaker | 304 return handshaker |
289 for result in handshaker: | 305 for result in handshaker: |
290 pass | 306 pass |
291 | 307 |
292 def handshakeClientSharedKey(self, username, sharedKey, settings=None, | 308 |
293 checker=None, async=False): | 309 def _handshakeClientAsync(self, srpParams=(), certParams=(), anonParams=(), |
294 """Perform a shared-key handshake in the role of client. | |
295 | |
296 This function performs a shared-key handshake. Using shared | |
297 symmetric keys of high entropy (128 bits or greater) mutually | |
298 authenticates both parties to each other. | |
299 | |
300 TLS with shared-keys is non-standard. Most TLS | |
301 implementations don't support it. See | |
302 U{http://www.ietf.org/html.charters/tls-charter.html} for the | |
303 latest information on TLS with shared-keys. If the shared-keys | |
304 Internet-Draft changes or is superceded, TLS Lite will track | |
305 those changes, so the shared-key support in later versions of | |
306 TLS Lite may become incompatible with this version. | |
307 | |
308 Like any handshake function, this can be called on a closed | |
309 TLS connection, or on a TLS connection that is already open. | |
310 If called on an open connection it performs a re-handshake. | |
311 | |
312 If the function completes without raising an exception, the | |
313 TLS connection will be open and available for data transfer. | |
314 | |
315 If an exception is raised, the connection will have been | |
316 automatically closed (if it was ever open). | |
317 | |
318 @type username: str | |
319 @param username: The shared-key username. | |
320 | |
321 @type sharedKey: str | |
322 @param sharedKey: The shared key. | |
323 | |
324 @type settings: L{tlslite.HandshakeSettings.HandshakeSettings} | |
325 @param settings: Various settings which can be used to control | |
326 the ciphersuites, certificate types, and SSL/TLS versions | |
327 offered by the client. | |
328 | |
329 @type checker: L{tlslite.Checker.Checker} | |
330 @param checker: A Checker instance. This instance will be | |
331 invoked to examine the other party's authentication | |
332 credentials, if the handshake completes succesfully. | |
333 | |
334 @type async: bool | |
335 @param async: If False, this function will block until the | |
336 handshake is completed. If True, this function will return a | |
337 generator. Successive invocations of the generator will | |
338 return 0 if it is waiting to read from the socket, 1 if it is | |
339 waiting to write to the socket, or will raise StopIteration if | |
340 the handshake operation is completed. | |
341 | |
342 @rtype: None or an iterable | |
343 @return: If 'async' is True, a generator object will be | |
344 returned. | |
345 | |
346 @raise socket.error: If a socket error occurs. | |
347 @raise tlslite.errors.TLSAbruptCloseError: If the socket is closed | |
348 without a preceding alert. | |
349 @raise tlslite.errors.TLSAlert: If a TLS alert is signalled. | |
350 @raise tlslite.errors.TLSAuthenticationError: If the checker | |
351 doesn't like the other party's authentication credentials. | |
352 """ | |
353 handshaker = self._handshakeClientAsync(sharedKeyParams=(username, | |
354 sharedKey), settings=settings, checker=checker) | |
355 if async: | |
356 return handshaker | |
357 for result in handshaker: | |
358 pass | |
359 | |
360 def _handshakeClientAsync(self, srpParams=(), certParams=(), | |
361 unknownParams=(), sharedKeyParams=(), | |
362 session=None, settings=None, checker=None, | 310 session=None, settings=None, checker=None, |
363 recursive=False): | 311 nextProtos=None, serverName="", reqTack=True): |
364 | 312 |
365 handshaker = self._handshakeClientAsyncHelper(srpParams=srpParams, | 313 handshaker = self._handshakeClientAsyncHelper(srpParams=srpParams, |
366 certParams=certParams, unknownParams=unknownParams, | 314 certParams=certParams, |
367 sharedKeyParams=sharedKeyParams, session=session, | 315 anonParams=anonParams, |
368 settings=settings, recursive=recursive) | 316 session=session, |
| 317 settings=settings, |
| 318 serverName=serverName, |
| 319 nextProtos=nextProtos, |
| 320 reqTack=reqTack) |
369 for result in self._handshakeWrapperAsync(handshaker, checker): | 321 for result in self._handshakeWrapperAsync(handshaker, checker): |
370 yield result | 322 yield result |
371 | 323 |
372 | 324 |
373 def _handshakeClientAsyncHelper(self, srpParams, certParams, unknownParams, | 325 def _handshakeClientAsyncHelper(self, srpParams, certParams, anonParams, |
374 sharedKeyParams, session, settings, recursive): | 326 session, settings, serverName, nextProtos, reqTac
k): |
375 if not recursive: | 327 |
376 self._handshakeStart(client=True) | 328 self._handshakeStart(client=True) |
377 | 329 |
378 #Unpack parameters | 330 #Unpack parameters |
379 srpUsername = None # srpParams | 331 srpUsername = None # srpParams[0] |
380 password = None # srpParams | 332 password = None # srpParams[1] |
381 clientCertChain = None # certParams | 333 clientCertChain = None # certParams[0] |
382 privateKey = None # certParams | 334 privateKey = None # certParams[1] |
383 srpCallback = None # unknownParams | 335 |
384 certCallback = None # unknownParams | 336 # Allow only one of (srpParams, certParams, anonParams) |
385 #session # sharedKeyParams (or session) | |
386 #settings # settings | |
387 | |
388 if srpParams: | 337 if srpParams: |
| 338 assert(not certParams) |
| 339 assert(not anonParams) |
389 srpUsername, password = srpParams | 340 srpUsername, password = srpParams |
390 elif certParams: | 341 if certParams: |
| 342 assert(not srpParams) |
| 343 assert(not anonParams) |
391 clientCertChain, privateKey = certParams | 344 clientCertChain, privateKey = certParams |
392 elif unknownParams: | 345 if anonParams: |
393 srpCallback, certCallback = unknownParams | 346 assert(not srpParams) |
394 elif sharedKeyParams: | 347 assert(not certParams) |
395 session = Session()._createSharedKey(*sharedKeyParams) | |
396 | |
397 if not settings: | |
398 settings = HandshakeSettings() | |
399 settings = settings._filter() | |
400 | 348 |
401 #Validate parameters | 349 #Validate parameters |
402 if srpUsername and not password: | 350 if srpUsername and not password: |
403 raise ValueError("Caller passed a username but no password") | 351 raise ValueError("Caller passed a username but no password") |
404 if password and not srpUsername: | 352 if password and not srpUsername: |
405 raise ValueError("Caller passed a password but no username") | 353 raise ValueError("Caller passed a password but no username") |
406 | |
407 if clientCertChain and not privateKey: | 354 if clientCertChain and not privateKey: |
408 raise ValueError("Caller passed a certChain but no privateKey") | 355 raise ValueError("Caller passed a certChain but no privateKey") |
409 if privateKey and not clientCertChain: | 356 if privateKey and not clientCertChain: |
410 raise ValueError("Caller passed a privateKey but no certChain") | 357 raise ValueError("Caller passed a privateKey but no certChain") |
| 358 if reqTack: |
| 359 if not tackpyLoaded: |
| 360 reqTack = False |
| 361 if not settings or not settings.useExperimentalTackExtension: |
| 362 reqTack = False |
| 363 if nextProtos is not None: |
| 364 if len(nextProtos) == 0: |
| 365 raise ValueError("Caller passed no nextProtos") |
| 366 |
| 367 # Validates the settings and filters out any unsupported ciphers |
| 368 # or crypto libraries that were requested |
| 369 if not settings: |
| 370 settings = HandshakeSettings() |
| 371 settings = settings._filter() |
411 | 372 |
412 if clientCertChain: | 373 if clientCertChain: |
413 foundType = False | 374 if not isinstance(clientCertChain, X509CertChain): |
414 try: | |
415 import cryptoIDlib.CertChain | |
416 if isinstance(clientCertChain, cryptoIDlib.CertChain.CertChain): | |
417 if "cryptoID" not in settings.certificateTypes: | |
418 raise ValueError("Client certificate doesn't "\ | |
419 "match Handshake Settings") | |
420 settings.certificateTypes = ["cryptoID"] | |
421 foundType = True | |
422 except ImportError: | |
423 pass | |
424 if not foundType and isinstance(clientCertChain, | |
425 X509CertChain): | |
426 if "x509" not in settings.certificateTypes: | |
427 raise ValueError("Client certificate doesn't match "\ | |
428 "Handshake Settings") | |
429 settings.certificateTypes = ["x509"] | |
430 foundType = True | |
431 if not foundType: | |
432 raise ValueError("Unrecognized certificate type") | 375 raise ValueError("Unrecognized certificate type") |
433 | 376 if "x509" not in settings.certificateTypes: |
434 | 377 raise ValueError("Client certificate doesn't match "\ |
| 378 "Handshake Settings") |
| 379 |
435 if session: | 380 if session: |
| 381 # session.valid() ensures session is resumable and has |
| 382 # non-empty sessionID |
436 if not session.valid(): | 383 if not session.valid(): |
437 session = None #ignore non-resumable sessions... | 384 session = None #ignore non-resumable sessions... |
438 elif session.resumable and \ | 385 elif session.resumable: |
439 (session.srpUsername != srpUsername): | 386 if session.srpUsername != srpUsername: |
440 raise ValueError("Session username doesn't match") | 387 raise ValueError("Session username doesn't match") |
| 388 if session.serverName != serverName: |
| 389 raise ValueError("Session servername doesn't match") |
441 | 390 |
442 #Add Faults to parameters | 391 #Add Faults to parameters |
443 if srpUsername and self.fault == Fault.badUsername: | 392 if srpUsername and self.fault == Fault.badUsername: |
444 srpUsername += "GARBAGE" | 393 srpUsername += "GARBAGE" |
445 if password and self.fault == Fault.badPassword: | 394 if password and self.fault == Fault.badPassword: |
446 password += "GARBAGE" | 395 password += "GARBAGE" |
447 if sharedKeyParams: | |
448 identifier = sharedKeyParams[0] | |
449 sharedKey = sharedKeyParams[1] | |
450 if self.fault == Fault.badIdentifier: | |
451 identifier += "GARBAGE" | |
452 session = Session()._createSharedKey(identifier, sharedKey) | |
453 elif self.fault == Fault.badSharedKey: | |
454 sharedKey += "GARBAGE" | |
455 session = Session()._createSharedKey(identifier, sharedKey) | |
456 | |
457 | |
458 #Initialize locals | |
459 serverCertChain = None | |
460 cipherSuite = 0 | |
461 certificateType = CertificateType.x509 | |
462 premasterSecret = None | |
463 | |
464 #Get client nonce | |
465 clientRandom = getRandomBytes(32) | |
466 | |
467 #Initialize acceptable ciphersuites | |
468 cipherSuites = [] | |
469 if srpParams: | |
470 cipherSuites += CipherSuite.getSrpRsaSuites(settings.cipherNames) | |
471 cipherSuites += CipherSuite.getSrpSuites(settings.cipherNames) | |
472 elif certParams: | |
473 cipherSuites += CipherSuite.getRsaSuites(settings.cipherNames) | |
474 elif unknownParams: | |
475 if srpCallback: | |
476 cipherSuites += \ | |
477 CipherSuite.getSrpRsaSuites(settings.cipherNames) | |
478 cipherSuites += \ | |
479 CipherSuite.getSrpSuites(settings.cipherNames) | |
480 cipherSuites += CipherSuite.getRsaSuites(settings.cipherNames) | |
481 elif sharedKeyParams: | |
482 cipherSuites += CipherSuite.getRsaSuites(settings.cipherNames) | |
483 else: | |
484 cipherSuites += CipherSuite.getRsaSuites(settings.cipherNames) | |
485 | |
486 #Initialize acceptable certificate types | |
487 certificateTypes = settings._getCertificateTypes() | |
488 | 396 |
489 #Tentatively set the version to the client's minimum version. | 397 #Tentatively set the version to the client's minimum version. |
490 #We'll use this for the ClientHello, and if an error occurs | 398 #We'll use this for the ClientHello, and if an error occurs |
491 #parsing the Server Hello, we'll use this version for the response | 399 #parsing the Server Hello, we'll use this version for the response |
492 self.version = settings.maxVersion | 400 self.version = settings.maxVersion |
493 | 401 |
| 402 # OK Start sending messages! |
| 403 # ***************************** |
| 404 |
| 405 # Send the ClientHello. |
| 406 for result in self._clientSendClientHello(settings, session, |
| 407 srpUsername, srpParams, certParams, |
| 408 anonParams, serverName, nextProtos, |
| 409 reqTack): |
| 410 if result in (0,1): yield result |
| 411 else: break |
| 412 clientHello = result |
| 413 |
| 414 #Get the ServerHello. |
| 415 for result in self._clientGetServerHello(settings, clientHello): |
| 416 if result in (0,1): yield result |
| 417 else: break |
| 418 serverHello = result |
| 419 cipherSuite = serverHello.cipher_suite |
| 420 |
| 421 # Choose a matching Next Protocol from server list against ours |
| 422 # (string or None) |
| 423 nextProto = self._clientSelectNextProto(nextProtos, serverHello) |
| 424 |
| 425 #If the server elected to resume the session, it is handled here. |
| 426 for result in self._clientResume(session, serverHello, |
| 427 clientHello.random, |
| 428 settings.cipherImplementations, |
| 429 nextProto): |
| 430 if result in (0,1): yield result |
| 431 else: break |
| 432 if result == "resumed_and_finished": |
| 433 self._handshakeDone(resumed=True) |
| 434 return |
| 435 |
| 436 #If the server selected an SRP ciphersuite, the client finishes |
| 437 #reading the post-ServerHello messages, then derives a |
| 438 #premasterSecret and sends a corresponding ClientKeyExchange. |
| 439 if cipherSuite in CipherSuite.srpAllSuites: |
| 440 for result in self._clientSRPKeyExchange(\ |
| 441 settings, cipherSuite, serverHello.certificate_type, |
| 442 srpUsername, password, |
| 443 clientHello.random, serverHello.random, |
| 444 serverHello.tackExt): |
| 445 if result in (0,1): yield result |
| 446 else: break |
| 447 (premasterSecret, serverCertChain, tackExt) = result |
| 448 |
| 449 #If the server selected an anonymous ciphersuite, the client |
| 450 #finishes reading the post-ServerHello messages. |
| 451 elif cipherSuite in CipherSuite.anonSuites: |
| 452 for result in self._clientAnonKeyExchange(settings, cipherSuite, |
| 453 clientHello.random, serverHello.random): |
| 454 if result in (0,1): yield result |
| 455 else: break |
| 456 (premasterSecret, serverCertChain, tackExt) = result |
| 457 |
| 458 #If the server selected a certificate-based RSA ciphersuite, |
| 459 #the client finishes reading the post-ServerHello messages. If |
| 460 #a CertificateRequest message was sent, the client responds with |
| 461 #a Certificate message containing its certificate chain (if any), |
| 462 #and also produces a CertificateVerify message that signs the |
| 463 #ClientKeyExchange. |
| 464 else: |
| 465 for result in self._clientRSAKeyExchange(settings, cipherSuite, |
| 466 clientCertChain, privateKey, |
| 467 serverHello.certificate_type, |
| 468 clientHello.random, serverHello.random, |
| 469 serverHello.tackExt): |
| 470 if result in (0,1): yield result |
| 471 else: break |
| 472 (premasterSecret, serverCertChain, clientCertChain, |
| 473 tackExt) = result |
| 474 |
| 475 #After having previously sent a ClientKeyExchange, the client now |
| 476 #initiates an exchange of Finished messages. |
| 477 for result in self._clientFinished(premasterSecret, |
| 478 clientHello.random, |
| 479 serverHello.random, |
| 480 cipherSuite, settings.cipherImplementations, |
| 481 nextProto): |
| 482 if result in (0,1): yield result |
| 483 else: break |
| 484 masterSecret = result |
| 485 |
| 486 # Create the session object which is used for resumptions |
| 487 self.session = Session() |
| 488 self.session.create(masterSecret, serverHello.session_id, cipherSuite, |
| 489 srpUsername, clientCertChain, serverCertChain, |
| 490 tackExt, serverHello.tackExt!=None, serverName) |
| 491 self._handshakeDone(resumed=False) |
| 492 |
| 493 |
| 494 def _clientSendClientHello(self, settings, session, srpUsername, |
| 495 srpParams, certParams, anonParams, |
| 496 serverName, nextProtos, reqTack): |
| 497 #Initialize acceptable ciphersuites |
| 498 cipherSuites = [CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV] |
| 499 if srpParams: |
| 500 cipherSuites += CipherSuite.getSrpAllSuites(settings) |
| 501 elif certParams: |
| 502 cipherSuites += CipherSuite.getCertSuites(settings) |
| 503 elif anonParams: |
| 504 cipherSuites += CipherSuite.getAnonSuites(settings) |
| 505 else: |
| 506 assert(False) |
| 507 |
| 508 #Initialize acceptable certificate types |
| 509 certificateTypes = settings._getCertificateTypes() |
| 510 |
494 #Either send ClientHello (with a resumable session)... | 511 #Either send ClientHello (with a resumable session)... |
495 if session: | 512 if session and session.sessionID: |
496 #If it's a resumable (i.e. not a shared-key session), then its | 513 #If it's resumable, then its |
497 #ciphersuite must be one of the acceptable ciphersuites | 514 #ciphersuite must be one of the acceptable ciphersuites |
498 if (not sharedKeyParams) and \ | 515 if session.cipherSuite not in cipherSuites: |
499 session.cipherSuite not in cipherSuites: | |
500 raise ValueError("Session's cipher suite not consistent "\ | 516 raise ValueError("Session's cipher suite not consistent "\ |
501 "with parameters") | 517 "with parameters") |
502 else: | 518 else: |
503 clientHello = ClientHello() | 519 clientHello = ClientHello() |
504 clientHello.create(settings.maxVersion, clientRandom, | 520 clientHello.create(settings.maxVersion, getRandomBytes(32), |
505 session.sessionID, cipherSuites, | 521 session.sessionID, cipherSuites, |
506 certificateTypes, session.srpUsername) | 522 certificateTypes, |
| 523 session.srpUsername, |
| 524 reqTack, nextProtos is not None, |
| 525 session.serverName) |
507 | 526 |
508 #Or send ClientHello (without) | 527 #Or send ClientHello (without) |
509 else: | 528 else: |
510 clientHello = ClientHello() | 529 clientHello = ClientHello() |
511 clientHello.create(settings.maxVersion, clientRandom, | 530 clientHello.create(settings.maxVersion, getRandomBytes(32), |
512 createByteArraySequence([]), cipherSuites, | 531 bytearray(0), cipherSuites, |
513 certificateTypes, srpUsername) | 532 certificateTypes, |
| 533 srpUsername, |
| 534 reqTack, nextProtos is not None, |
| 535 serverName) |
514 for result in self._sendMsg(clientHello): | 536 for result in self._sendMsg(clientHello): |
515 yield result | 537 yield result |
516 | 538 yield clientHello |
517 #Get ServerHello (or missing_srp_username) | 539 |
518 for result in self._getMsg((ContentType.handshake, | 540 |
519 ContentType.alert), | 541 def _clientGetServerHello(self, settings, clientHello): |
| 542 for result in self._getMsg(ContentType.handshake, |
520 HandshakeType.server_hello): | 543 HandshakeType.server_hello): |
521 if result in (0,1): | 544 if result in (0,1): yield result |
522 yield result | 545 else: break |
523 else: | 546 serverHello = result |
524 break | |
525 msg = result | |
526 | |
527 if isinstance(msg, ServerHello): | |
528 serverHello = msg | |
529 elif isinstance(msg, Alert): | |
530 alert = msg | |
531 | |
532 #If it's not a missing_srp_username, re-raise | |
533 if alert.description != AlertDescription.missing_srp_username: | |
534 self._shutdown(False) | |
535 raise TLSRemoteAlert(alert) | |
536 | |
537 #If we're not in SRP callback mode, we won't have offered SRP | |
538 #without a username, so we shouldn't get this alert | |
539 if not srpCallback: | |
540 for result in self._sendError(\ | |
541 AlertDescription.unexpected_message): | |
542 yield result | |
543 srpParams = srpCallback() | |
544 #If the callback returns None, cancel the handshake | |
545 if srpParams == None: | |
546 for result in self._sendError(AlertDescription.user_canceled): | |
547 yield result | |
548 | |
549 #Recursively perform handshake | |
550 for result in self._handshakeClientAsyncHelper(srpParams, | |
551 None, None, None, None, settings, True): | |
552 yield result | |
553 return | |
554 | 547 |
555 #Get the server version. Do this before anything else, so any | 548 #Get the server version. Do this before anything else, so any |
556 #error alerts will use the server's version | 549 #error alerts will use the server's version |
557 self.version = serverHello.server_version | 550 self.version = serverHello.server_version |
558 | 551 |
559 #Future responses from server must use this version | 552 #Future responses from server must use this version |
560 self._versionCheck = True | 553 self._versionCheck = True |
561 | 554 |
562 #Check ServerHello | 555 #Check ServerHello |
563 if serverHello.server_version < settings.minVersion: | 556 if serverHello.server_version < settings.minVersion: |
564 for result in self._sendError(\ | 557 for result in self._sendError(\ |
565 AlertDescription.protocol_version, | 558 AlertDescription.protocol_version, |
566 "Too old version: %s" % str(serverHello.server_version)): | 559 "Too old version: %s" % str(serverHello.server_version)): |
567 yield result | 560 yield result |
568 if serverHello.server_version > settings.maxVersion: | 561 if serverHello.server_version > settings.maxVersion: |
569 for result in self._sendError(\ | 562 for result in self._sendError(\ |
570 AlertDescription.protocol_version, | 563 AlertDescription.protocol_version, |
571 "Too new version: %s" % str(serverHello.server_version)): | 564 "Too new version: %s" % str(serverHello.server_version)): |
572 yield result | 565 yield result |
573 if serverHello.cipher_suite not in cipherSuites: | 566 if serverHello.cipher_suite not in clientHello.cipher_suites: |
574 for result in self._sendError(\ | 567 for result in self._sendError(\ |
575 AlertDescription.illegal_parameter, | 568 AlertDescription.illegal_parameter, |
576 "Server responded with incorrect ciphersuite"): | 569 "Server responded with incorrect ciphersuite"): |
577 yield result | 570 yield result |
578 if serverHello.certificate_type not in certificateTypes: | 571 if serverHello.certificate_type not in clientHello.certificate_types: |
579 for result in self._sendError(\ | 572 for result in self._sendError(\ |
580 AlertDescription.illegal_parameter, | 573 AlertDescription.illegal_parameter, |
581 "Server responded with incorrect certificate type"): | 574 "Server responded with incorrect certificate type"): |
582 yield result | 575 yield result |
583 if serverHello.compression_method != 0: | 576 if serverHello.compression_method != 0: |
584 for result in self._sendError(\ | 577 for result in self._sendError(\ |
585 AlertDescription.illegal_parameter, | 578 AlertDescription.illegal_parameter, |
586 "Server responded with incorrect compression method"): | 579 "Server responded with incorrect compression method"): |
587 yield result | 580 yield result |
588 | 581 if serverHello.tackExt: |
589 #Get the server nonce | 582 if not clientHello.tack: |
590 serverRandom = serverHello.random | 583 for result in self._sendError(\ |
591 | 584 AlertDescription.illegal_parameter, |
| 585 "Server responded with unrequested Tack Extension"): |
| 586 yield result |
| 587 if serverHello.next_protos and not clientHello.supports_npn: |
| 588 for result in self._sendError(\ |
| 589 AlertDescription.illegal_parameter, |
| 590 "Server responded with unrequested NPN Extension"): |
| 591 yield result |
| 592 if not serverHello.tackExt.verifySignatures(): |
| 593 for result in self._sendError(\ |
| 594 AlertDescription.decrypt_error, |
| 595 "TackExtension contains an invalid signature"): |
| 596 yield result |
| 597 yield serverHello |
| 598 |
| 599 def _clientSelectNextProto(self, nextProtos, serverHello): |
| 600 # nextProtos is None or non-empty list of strings |
| 601 # serverHello.next_protos is None or possibly-empty list of strings |
| 602 # |
| 603 # !!! We assume the client may have specified nextProtos as a list of |
| 604 # strings so we convert them to bytearrays (it's awkward to require |
| 605 # the user to specify a list of bytearrays or "bytes", and in |
| 606 # Python 2.6 bytes() is just an alias for str() anyways... |
| 607 if nextProtos is not None and serverHello.next_protos is not None: |
| 608 for p in nextProtos: |
| 609 if bytearray(p) in serverHello.next_protos: |
| 610 return bytearray(p) |
| 611 else: |
| 612 # If the client doesn't support any of server's protocols, |
| 613 # or the server doesn't advertise any (next_protos == []) |
| 614 # the client SHOULD select the first protocol it supports. |
| 615 return bytearray(nextProtos[0]) |
| 616 return None |
| 617 |
| 618 def _clientResume(self, session, serverHello, clientRandom, |
| 619 cipherImplementations, nextProto): |
592 #If the server agrees to resume | 620 #If the server agrees to resume |
593 if session and session.sessionID and \ | 621 if session and session.sessionID and \ |
594 serverHello.session_id == session.sessionID: | 622 serverHello.session_id == session.sessionID: |
595 | 623 |
596 #If a shared-key, we're flexible about suites; otherwise the | 624 if serverHello.cipher_suite != session.cipherSuite: |
597 #server-chosen suite has to match the session's suite | |
598 if sharedKeyParams: | |
599 session.cipherSuite = serverHello.cipher_suite | |
600 elif serverHello.cipher_suite != session.cipherSuite: | |
601 for result in self._sendError(\ | 625 for result in self._sendError(\ |
602 AlertDescription.illegal_parameter,\ | 626 AlertDescription.illegal_parameter,\ |
603 "Server's ciphersuite doesn't match session"): | 627 "Server's ciphersuite doesn't match session"): |
604 yield result | 628 yield result |
605 | 629 |
| 630 #Calculate pending connection states |
| 631 self._calcPendingStates(session.cipherSuite, |
| 632 session.masterSecret, |
| 633 clientRandom, serverHello.random, |
| 634 cipherImplementations)
|
| 635 |
| 636 #Exchange ChangeCipherSpec and Finished messages |
| 637 for result in self._getFinished(session.masterSecret): |
| 638 yield result |
| 639 for result in self._sendFinished(session.masterSecret, nextProto): |
| 640 yield result |
| 641 |
606 #Set the session for this connection | 642 #Set the session for this connection |
607 self.session = session | 643 self.session = session |
608 | 644 yield "resumed_and_finished" |
609 #Calculate pending connection states | 645 |
610 self._calcPendingStates(clientRandom, serverRandom, | 646 def _clientSRPKeyExchange(self, settings, cipherSuite, certificateType, |
611 settings.cipherImplementations) | 647 srpUsername, password, |
612 | 648 clientRandom, serverRandom, tackExt): |
613 #Exchange ChangeCipherSpec and Finished messages | 649 |
614 for result in self._getChangeCipherSpec(): | 650 #If the server chose an SRP+RSA suite... |
615 yield result | 651 if cipherSuite in CipherSuite.srpCertSuites: |
616 for result in self._getFinished(): | 652 #Get Certificate, ServerKeyExchange, ServerHelloDone |
617 yield result | 653 for result in self._getMsg(ContentType.handshake, |
618 for result in self._sendFinished(): | 654 HandshakeType.certificate, certificateType): |
619 yield result | 655 if result in (0,1): yield result |
620 | 656 else: break |
621 #Mark the connection as open | 657 serverCertificate = result |
622 self._handshakeDone(resumed=True) | |
623 | |
624 #If server DOES NOT agree to resume | |
625 else: | 658 else: |
626 | 659 serverCertificate = None |
627 if sharedKeyParams: | 660 |
| 661 for result in self._getMsg(ContentType.handshake, |
| 662 HandshakeType.server_key_exchange, cipherSuite): |
| 663 if result in (0,1): yield result |
| 664 else: break |
| 665 serverKeyExchange = result |
| 666 |
| 667 for result in self._getMsg(ContentType.handshake, |
| 668 HandshakeType.server_hello_done): |
| 669 if result in (0,1): yield result |
| 670 else: break |
| 671 serverHelloDone = result |
| 672 |
| 673 #Calculate SRP premaster secret |
| 674 #Get and check the server's group parameters and B value |
| 675 N = serverKeyExchange.srp_N |
| 676 g = serverKeyExchange.srp_g |
| 677 s = serverKeyExchange.srp_s |
| 678 B = serverKeyExchange.srp_B |
| 679 |
| 680 if (g,N) not in goodGroupParameters: |
| 681 for result in self._sendError(\ |
| 682 AlertDescription.insufficient_security, |
| 683 "Unknown group parameters"): |
| 684 yield result |
| 685 if numBits(N) < settings.minKeySize: |
| 686 for result in self._sendError(\ |
| 687 AlertDescription.insufficient_security, |
| 688 "N value is too small: %d" % numBits(N)): |
| 689 yield result |
| 690 if numBits(N) > settings.maxKeySize: |
| 691 for result in self._sendError(\ |
| 692 AlertDescription.insufficient_security, |
| 693 "N value is too large: %d" % numBits(N)): |
| 694 yield result |
| 695 if B % N == 0: |
| 696 for result in self._sendError(\ |
| 697 AlertDescription.illegal_parameter, |
| 698 "Suspicious B value"): |
| 699 yield result |
| 700 |
| 701 #Check the server's signature, if server chose an |
| 702 #SRP+RSA suite |
| 703 serverCertChain = None |
| 704 if cipherSuite in CipherSuite.srpCertSuites: |
| 705 #Hash ServerKeyExchange/ServerSRPParams |
| 706 hashBytes = serverKeyExchange.hash(clientRandom, serverRandom) |
| 707 |
| 708 #Extract signature bytes from ServerKeyExchange |
| 709 sigBytes = serverKeyExchange.signature |
| 710 if len(sigBytes) == 0: |
628 for result in self._sendError(\ | 711 for result in self._sendError(\ |
629 AlertDescription.user_canceled, | 712 AlertDescription.illegal_parameter, |
630 "Was expecting a shared-key resumption"): | 713 "Server sent an SRP ServerKeyExchange "\ |
| 714 "message without a signature"): |
631 yield result | 715 yield result |
632 | 716 |
633 #We've already validated these | 717 # Get server's public key from the Certificate message |
634 cipherSuite = serverHello.cipher_suite | 718 # Also validate the chain against the ServerHello's TACKext (if any) |
635 certificateType = serverHello.certificate_type | 719 # If none, and a TACK cert is present, return its TACKext |
636 | 720 for result in self._clientGetKeyFromChain(serverCertificate, |
637 #If the server chose an SRP suite... | 721 settings, tackExt): |
638 if cipherSuite in CipherSuite.srpSuites: | 722 if result in (0,1): yield result |
639 #Get ServerKeyExchange, ServerHelloDone | 723 else: break |
640 for result in self._getMsg(ContentType.handshake, | 724 publicKey, serverCertChain, tackExt = result |
641 HandshakeType.server_key_exchange, cipherSuite): | 725 |
642 if result in (0,1): | 726 #Verify signature |
| 727 if not publicKey.verify(sigBytes, hashBytes): |
| 728 for result in self._sendError(\ |
| 729 AlertDescription.decrypt_error, |
| 730 "Signature failed to verify"): |
| 731 yield result |
| 732 |
| 733 #Calculate client's ephemeral DH values (a, A) |
| 734 a = bytesToNumber(getRandomBytes(32)) |
| 735 A = powMod(g, a, N) |
| 736 |
| 737 #Calculate client's static DH values (x, v) |
| 738 x = makeX(s, bytearray(srpUsername, "utf-8"), |
| 739 bytearray(password, "utf-8")) |
| 740 v = powMod(g, x, N) |
| 741 |
| 742 #Calculate u |
| 743 u = makeU(N, A, B) |
| 744 |
| 745 #Calculate premaster secret |
| 746 k = makeK(N, g) |
| 747 S = powMod((B - (k*v)) % N, a+(u*x), N) |
| 748 |
| 749 if self.fault == Fault.badA: |
| 750 A = N |
| 751 S = 0 |
| 752 |
| 753 premasterSecret = numberToByteArray(S) |
| 754 |
| 755 #Send ClientKeyExchange |
| 756 for result in self._sendMsg(\ |
| 757 ClientKeyExchange(cipherSuite).createSRP(A)): |
| 758 yield result |
| 759 yield (premasterSecret, serverCertChain, tackExt) |
| 760 |
| 761 |
| 762 def _clientRSAKeyExchange(self, settings, cipherSuite, |
| 763 clientCertChain, privateKey, |
| 764 certificateType, |
| 765 clientRandom, serverRandom, |
| 766 tackExt): |
| 767 |
| 768 #Get Certificate[, CertificateRequest], ServerHelloDone |
| 769 for result in self._getMsg(ContentType.handshake, |
| 770 HandshakeType.certificate, certificateType): |
| 771 if result in (0,1): yield result |
| 772 else: break |
| 773 serverCertificate = result |
| 774 |
| 775 # Get CertificateRequest or ServerHelloDone |
| 776 for result in self._getMsg(ContentType.handshake, |
| 777 (HandshakeType.server_hello_done, |
| 778 HandshakeType.certificate_request)): |
| 779 if result in (0,1): yield result |
| 780 else: break |
| 781 msg = result |
| 782 certificateRequest = None |
| 783 if isinstance(msg, CertificateRequest): |
| 784 certificateRequest = msg |
| 785 # We got CertificateRequest, so this must be ServerHelloDone |
| 786 for result in self._getMsg(ContentType.handshake, |
| 787 HandshakeType.server_hello_done): |
| 788 if result in (0,1): yield result |
| 789 else: break |
| 790 serverHelloDone = result |
| 791 elif isinstance(msg, ServerHelloDone): |
| 792 serverHelloDone = msg |
| 793 |
| 794 # Get server's public key from the Certificate message |
| 795 # Also validate the chain against the ServerHello's TACKext (if any) |
| 796 # If none, and a TACK cert is present, return its TACKext |
| 797 for result in self._clientGetKeyFromChain(serverCertificate, |
| 798 settings, tackExt): |
| 799 if result in (0,1): yield result |
| 800 else: break |
| 801 publicKey, serverCertChain, tackExt = result |
| 802 |
| 803 #Calculate premaster secret |
| 804 premasterSecret = getRandomBytes(48) |
| 805 premasterSecret[0] = settings.maxVersion[0] |
| 806 premasterSecret[1] = settings.maxVersion[1] |
| 807 |
| 808 if self.fault == Fault.badPremasterPadding: |
| 809 premasterSecret[0] = 5 |
| 810 if self.fault == Fault.shortPremasterSecret: |
| 811 premasterSecret = premasterSecret[:-1] |
| 812 |
| 813 #Encrypt premaster secret to server's public key |
| 814 encryptedPreMasterSecret = publicKey.encrypt(premasterSecret) |
| 815 |
| 816 #If client authentication was requested, send Certificate |
| 817 #message, either with certificates or empty |
| 818 if certificateRequest: |
| 819 clientCertificate = Certificate(certificateType) |
| 820 |
| 821 if clientCertChain: |
| 822 #Check to make sure we have the same type of |
| 823 #certificates the server requested |
| 824 wrongType = False |
| 825 if certificateType == CertificateType.x509: |
| 826 if not isinstance(clientCertChain, X509CertChain): |
| 827 wrongType = True |
| 828 if wrongType: |
| 829 for result in self._sendError(\ |
| 830 AlertDescription.handshake_failure, |
| 831 "Client certificate is of wrong type"): |
643 yield result | 832 yield result |
644 else: | 833 |
645 break | 834 clientCertificate.create(clientCertChain) |
646 serverKeyExchange = result | 835 for result in self._sendMsg(clientCertificate): |
647 | 836 yield result |
648 for result in self._getMsg(ContentType.handshake, | 837 else: |
649 HandshakeType.server_hello_done): | 838 #The server didn't request client auth, so we |
650 if result in (0,1): | 839 #zeroize these so the clientCertChain won't be |
651 yield result | 840 #stored in the session. |
652 else: | 841 privateKey = None |
653 break | 842 clientCertChain = None |
654 serverHelloDone = result | 843 |
655 | 844 #Send ClientKeyExchange |
656 #If the server chose an SRP+RSA suite... | 845 clientKeyExchange = ClientKeyExchange(cipherSuite, |
657 elif cipherSuite in CipherSuite.srpRsaSuites: | 846 self.version) |
658 #Get Certificate, ServerKeyExchange, ServerHelloDone | 847 clientKeyExchange.createRSA(encryptedPreMasterSecret) |
659 for result in self._getMsg(ContentType.handshake, | 848 for result in self._sendMsg(clientKeyExchange): |
660 HandshakeType.certificate, certificateType): | 849 yield result |
661 if result in (0,1): | 850 |
662 yield result | 851 #If client authentication was requested and we have a |
663 else: | 852 #private key, send CertificateVerify |
664 break | 853 if certificateRequest and privateKey: |
665 serverCertificate = result | 854 if self.version == (3,0): |
666 | 855 masterSecret = calcMasterSecret(self.version, |
667 for result in self._getMsg(ContentType.handshake, | 856 premasterSecret, |
668 HandshakeType.server_key_exchange, cipherSuite): | 857 clientRandom, |
669 if result in (0,1): | 858 serverRandom) |
670 yield result | 859 verifyBytes = self._calcSSLHandshakeHash(masterSecret, b"") |
671 else: | 860 elif self.version in ((3,1), (3,2)): |
672 break | 861 verifyBytes = self._handshake_md5.digest() + \ |
673 serverKeyExchange = result | 862 self._handshake_sha.digest() |
674 | 863 if self.fault == Fault.badVerifyMessage: |
675 for result in self._getMsg(ContentType.handshake, | 864 verifyBytes[0] = ((verifyBytes[0]+1) % 256) |
676 HandshakeType.server_hello_done): | 865 signedBytes = privateKey.sign(verifyBytes) |
677 if result in (0,1): | 866 certificateVerify = CertificateVerify() |
678 yield result | 867 certificateVerify.create(signedBytes) |
679 else: | 868 for result in self._sendMsg(certificateVerify): |
680 break | 869 yield result |
681 serverHelloDone = result | 870 yield (premasterSecret, serverCertChain, clientCertChain, tackExt) |
682 | 871 |
683 #If the server chose an RSA suite... | 872 def _clientAnonKeyExchange(self, settings, cipherSuite, clientRandom, |
684 elif cipherSuite in CipherSuite.rsaSuites: | 873 serverRandom): |
685 #Get Certificate[, CertificateRequest], ServerHelloDone | 874 for result in self._getMsg(ContentType.handshake, |
686 for result in self._getMsg(ContentType.handshake, | 875 HandshakeType.server_key_exchange, cipherSuite): |
687 HandshakeType.certificate, certificateType): | 876 if result in (0,1): yield result |
688 if result in (0,1): | 877 else: break |
689 yield result | 878 serverKeyExchange = result |
690 else: | 879 |
691 break | 880 for result in self._getMsg(ContentType.handshake, |
692 serverCertificate = result | 881 HandshakeType.server_hello_done): |
693 | 882 if result in (0,1): yield result |
694 for result in self._getMsg(ContentType.handshake, | 883 else: break |
695 (HandshakeType.server_hello_done, | 884 serverHelloDone = result |
696 HandshakeType.certificate_request)): | 885 |
697 if result in (0,1): | 886 #calculate Yc |
698 yield result | 887 dh_p = serverKeyExchange.dh_p |
699 else: | 888 dh_g = serverKeyExchange.dh_g |
700 break | 889 dh_Xc = bytesToNumber(getRandomBytes(32)) |
701 msg = result | 890 dh_Ys = serverKeyExchange.dh_Ys |
702 | 891 dh_Yc = powMod(dh_g, dh_Xc, dh_p) |
703 certificateRequest = None | 892 |
704 if isinstance(msg, CertificateRequest): | 893 #Send ClientKeyExchange |
705 certificateRequest = msg | 894 for result in self._sendMsg(\ |
706 for result in self._getMsg(ContentType.handshake, | 895 ClientKeyExchange(cipherSuite, self.version).createDH(dh_Yc)): |
707 HandshakeType.server_hello_done): | 896 yield result |
708 if result in (0,1): | 897 |
709 yield result | 898 #Calculate premaster secret |
710 else: | 899 S = powMod(dh_Ys, dh_Xc, dh_p) |
711 break | 900 premasterSecret = numberToByteArray(S) |
712 serverHelloDone = result | 901 |
713 elif isinstance(msg, ServerHelloDone): | 902 yield (premasterSecret, None, None) |
714 serverHelloDone = msg | 903 |
715 else: | 904 def _clientFinished(self, premasterSecret, clientRandom, serverRandom, |
716 raise AssertionError() | 905 cipherSuite, cipherImplementations, nextProto): |
717 | 906 |
718 | 907 masterSecret = calcMasterSecret(self.version, premasterSecret, |
719 #Calculate SRP premaster secret, if server chose an SRP or | 908 clientRandom, serverRandom) |
720 #SRP+RSA suite | 909 self._calcPendingStates(cipherSuite, masterSecret, |
721 if cipherSuite in CipherSuite.srpSuites + \ | 910 clientRandom, serverRandom, |
722 CipherSuite.srpRsaSuites: | 911 cipherImplementations) |
723 #Get and check the server's group parameters and B value | 912 |
724 N = serverKeyExchange.srp_N | 913 #Exchange ChangeCipherSpec and Finished messages |
725 g = serverKeyExchange.srp_g | 914 for result in self._sendFinished(masterSecret, nextProto): |
726 s = serverKeyExchange.srp_s | 915 yield result |
727 B = serverKeyExchange.srp_B | 916 for result in self._getFinished(masterSecret, nextProto=nextProto): |
728 | 917 yield result |
729 if (g,N) not in goodGroupParameters: | 918 yield masterSecret |
730 for result in self._sendError(\ | 919 |
731 AlertDescription.untrusted_srp_parameters, | 920 def _clientGetKeyFromChain(self, certificate, settings, tackExt=None): |
732 "Unknown group parameters"): | 921 #Get and check cert chain from the Certificate message |
733 yield result | 922 certChain = certificate.certChain |
734 if numBits(N) < settings.minKeySize: | 923 if not certChain or certChain.getNumCerts() == 0: |
735 for result in self._sendError(\ | 924 for result in self._sendError(AlertDescription.illegal_parameter, |
736 AlertDescription.untrusted_srp_parameters, | 925 "Other party sent a Certificate message without "\ |
737 "N value is too small: %d" % numBits(N)): | 926 "certificates"): |
738 yield result | 927 yield result |
739 if numBits(N) > settings.maxKeySize: | 928 |
740 for result in self._sendError(\ | 929 #Get and check public key from the cert chain |
741 AlertDescription.untrusted_srp_parameters, | 930 publicKey = certChain.getEndEntityPublicKey() |
742 "N value is too large: %d" % numBits(N)): | 931 if len(publicKey) < settings.minKeySize: |
743 yield result | 932 for result in self._sendError(AlertDescription.handshake_failure, |
744 if B % N == 0: | 933 "Other party's public key too small: %d" % len(publicKey)): |
745 for result in self._sendError(\ | 934 yield result |
746 AlertDescription.illegal_parameter, | 935 if len(publicKey) > settings.maxKeySize: |
747 "Suspicious B value"): | 936 for result in self._sendError(AlertDescription.handshake_failure, |
748 yield result | 937 "Other party's public key too large: %d" % len(publicKey)): |
749 | 938 yield result |
750 #Check the server's signature, if server chose an | 939 |
751 #SRP+RSA suite | 940 # If there's no TLS Extension, look for a TACK cert |
752 if cipherSuite in CipherSuite.srpRsaSuites: | 941 if tackpyLoaded: |
753 #Hash ServerKeyExchange/ServerSRPParams | 942 if not tackExt: |
754 hashBytes = serverKeyExchange.hash(clientRandom, | 943 tackExt = certChain.getTackExt() |
755 serverRandom) | 944 |
756 | 945 # If there's a TACK (whether via TLS or TACK Cert), check that it |
757 #Extract signature bytes from ServerKeyExchange | 946 # matches the cert chain |
758 sigBytes = serverKeyExchange.signature | 947 if tackExt and tackExt.tacks: |
759 if len(sigBytes) == 0: | 948 for tack in tackExt.tacks: |
760 for result in self._sendError(\ | 949 if not certChain.checkTack(tack): |
| 950 for result in self._sendError( |
761 AlertDescription.illegal_parameter, | 951 AlertDescription.illegal_parameter, |
762 "Server sent an SRP ServerKeyExchange "\ | 952 "Other party's TACK doesn't match their public k
ey"): |
763 "message without a signature"): | |
764 yield result | |
765 | |
766 #Get server's public key from the Certificate message | |
767 for result in self._getKeyFromChain(serverCertificate, | |
768 settings): | |
769 if result in (0,1): | |
770 yield result | |
771 else: | |
772 break | |
773 publicKey, serverCertChain = result | |
774 | |
775 #Verify signature | |
776 if not publicKey.verify(sigBytes, hashBytes): | |
777 for result in self._sendError(\ | |
778 AlertDescription.decrypt_error, | |
779 "Signature failed to verify"): | |
780 yield result | |
781 | |
782 | |
783 #Calculate client's ephemeral DH values (a, A) | |
784 a = bytesToNumber(getRandomBytes(32)) | |
785 A = powMod(g, a, N) | |
786 | |
787 #Calculate client's static DH values (x, v) | |
788 x = makeX(bytesToString(s), srpUsername, password) | |
789 v = powMod(g, x, N) | |
790 | |
791 #Calculate u | |
792 u = makeU(N, A, B) | |
793 | |
794 #Calculate premaster secret | |
795 k = makeK(N, g) | |
796 S = powMod((B - (k*v)) % N, a+(u*x), N) | |
797 | |
798 if self.fault == Fault.badA: | |
799 A = N | |
800 S = 0 | |
801 premasterSecret = numberToBytes(S) | |
802 | |
803 #Send ClientKeyExchange | |
804 for result in self._sendMsg(\ | |
805 ClientKeyExchange(cipherSuite).createSRP(A)): | |
806 yield result | |
807 | |
808 | |
809 #Calculate RSA premaster secret, if server chose an RSA suite | |
810 elif cipherSuite in CipherSuite.rsaSuites: | |
811 | |
812 #Handle the presence of a CertificateRequest | |
813 if certificateRequest: | |
814 if unknownParams and certCallback: | |
815 certParamsNew = certCallback() | |
816 if certParamsNew: | |
817 clientCertChain, privateKey = certParamsNew | |
818 | |
819 #Get server's public key from the Certificate message | |
820 for result in self._getKeyFromChain(serverCertificate, | |
821 settings): | |
822 if result in (0,1): | |
823 yield result | |
824 else: | |
825 break | |
826 publicKey, serverCertChain = result | |
827 | |
828 | |
829 #Calculate premaster secret | |
830 premasterSecret = getRandomBytes(48) | |
831 premasterSecret[0] = settings.maxVersion[0] | |
832 premasterSecret[1] = settings.maxVersion[1] | |
833 | |
834 if self.fault == Fault.badPremasterPadding: | |
835 premasterSecret[0] = 5 | |
836 if self.fault == Fault.shortPremasterSecret: | |
837 premasterSecret = premasterSecret[:-1] | |
838 | |
839 #Encrypt premaster secret to server's public key | |
840 encryptedPreMasterSecret = publicKey.encrypt(premasterSecret) | |
841 | |
842 #If client authentication was requested, send Certificate | |
843 #message, either with certificates or empty | |
844 if certificateRequest: | |
845 clientCertificate = Certificate(certificateType) | |
846 | |
847 if clientCertChain: | |
848 #Check to make sure we have the same type of | |
849 #certificates the server requested | |
850 wrongType = False | |
851 if certificateType == CertificateType.x509: | |
852 if not isinstance(clientCertChain, X509CertChain): | |
853 wrongType = True | |
854 elif certificateType == CertificateType.cryptoID: | |
855 if not isinstance(clientCertChain, | |
856 cryptoIDlib.CertChain.CertChain): | |
857 wrongType = True | |
858 if wrongType: | |
859 for result in self._sendError(\ | |
860 AlertDescription.handshake_failure, | |
861 "Client certificate is of wrong type"): | |
862 yield result | 953 yield result |
863 | 954 |
864 clientCertificate.create(clientCertChain) | 955 yield publicKey, certChain, tackExt |
865 | 956 |
866 for result in self._sendMsg(clientCertificate): | 957 |
867 yield result | 958 #********************************************************* |
868 else: | 959 # Server Handshake Functions |
869 #The server didn't request client auth, so we | 960 #********************************************************* |
870 #zeroize these so the clientCertChain won't be | 961 |
871 #stored in the session. | 962 |
872 privateKey = None | 963 def handshakeServer(self, verifierDB=None, |
873 clientCertChain = None | |
874 | |
875 #Send ClientKeyExchange | |
876 clientKeyExchange = ClientKeyExchange(cipherSuite, | |
877 self.version) | |
878 clientKeyExchange.createRSA(encryptedPreMasterSecret) | |
879 for result in self._sendMsg(clientKeyExchange): | |
880 yield result | |
881 | |
882 #If client authentication was requested and we have a | |
883 #private key, send CertificateVerify | |
884 if certificateRequest and privateKey: | |
885 if self.version == (3,0): | |
886 #Create a temporary session object, just for the | |
887 #purpose of creating the CertificateVerify | |
888 session = Session() | |
889 session._calcMasterSecret(self.version, | |
890 premasterSecret, | |
891 clientRandom, | |
892 serverRandom) | |
893 verifyBytes = self._calcSSLHandshakeHash(\ | |
894 session.masterSecret, "") | |
895 elif self.version in ((3,1), (3,2)): | |
896 verifyBytes = stringToBytes(\ | |
897 self._handshake_md5.digest() + \ | |
898 self._handshake_sha.digest()) | |
899 if self.fault == Fault.badVerifyMessage: | |
900 verifyBytes[0] = ((verifyBytes[0]+1) % 256) | |
901 signedBytes = privateKey.sign(verifyBytes) | |
902 certificateVerify = CertificateVerify() | |
903 certificateVerify.create(signedBytes) | |
904 for result in self._sendMsg(certificateVerify): | |
905 yield result | |
906 | |
907 | |
908 #Create the session object | |
909 self.session = Session() | |
910 self.session._calcMasterSecret(self.version, premasterSecret, | |
911 clientRandom, serverRandom) | |
912 self.session.sessionID = serverHello.session_id | |
913 self.session.cipherSuite = cipherSuite | |
914 self.session.srpUsername = srpUsername | |
915 self.session.clientCertChain = clientCertChain | |
916 self.session.serverCertChain = serverCertChain | |
917 | |
918 #Calculate pending connection states | |
919 self._calcPendingStates(clientRandom, serverRandom, | |
920 settings.cipherImplementations) | |
921 | |
922 #Exchange ChangeCipherSpec and Finished messages | |
923 for result in self._sendFinished(): | |
924 yield result | |
925 for result in self._getChangeCipherSpec(): | |
926 yield result | |
927 for result in self._getFinished(): | |
928 yield result | |
929 | |
930 #Mark the connection as open | |
931 self.session._setResumable(True) | |
932 self._handshakeDone(resumed=False) | |
933 | |
934 | |
935 | |
936 def handshakeServer(self, sharedKeyDB=None, verifierDB=None, | |
937 certChain=None, privateKey=None, reqCert=False, | 964 certChain=None, privateKey=None, reqCert=False, |
938 sessionCache=None, settings=None, checker=None, | 965 sessionCache=None, settings=None, checker=None, |
939 reqCAs=None, tlsIntolerant=0, | 966 reqCAs = None, |
940 signedCertTimestamps=None, fallbackSCSV=False, | 967 tacks=None, activationFlags=0, |
941 ocspResponse=None): | 968 nextProtos=None, anon=False, |
| 969 tlsIntolerant=None, signedCertTimestamps=None, |
| 970 fallbackSCSV=False, ocspResponse=None): |
942 """Perform a handshake in the role of server. | 971 """Perform a handshake in the role of server. |
943 | 972 |
944 This function performs an SSL or TLS handshake. Depending on | 973 This function performs an SSL or TLS handshake. Depending on |
945 the arguments and the behavior of the client, this function can | 974 the arguments and the behavior of the client, this function can |
946 perform a shared-key, SRP, or certificate-based handshake. It | 975 perform an SRP, or certificate-based handshake. It |
947 can also perform a combined SRP and server-certificate | 976 can also perform a combined SRP and server-certificate |
948 handshake. | 977 handshake. |
949 | 978 |
950 Like any handshake function, this can be called on a closed | 979 Like any handshake function, this can be called on a closed |
951 TLS connection, or on a TLS connection that is already open. | 980 TLS connection, or on a TLS connection that is already open. |
952 If called on an open connection it performs a re-handshake. | 981 If called on an open connection it performs a re-handshake. |
953 This function does not send a Hello Request message before | 982 This function does not send a Hello Request message before |
954 performing the handshake, so if re-handshaking is required, | 983 performing the handshake, so if re-handshaking is required, |
955 the server must signal the client to begin the re-handshake | 984 the server must signal the client to begin the re-handshake |
956 through some other means. | 985 through some other means. |
957 | 986 |
958 If the function completes without raising an exception, the | 987 If the function completes without raising an exception, the |
959 TLS connection will be open and available for data transfer. | 988 TLS connection will be open and available for data transfer. |
960 | 989 |
961 If an exception is raised, the connection will have been | 990 If an exception is raised, the connection will have been |
962 automatically closed (if it was ever open). | 991 automatically closed (if it was ever open). |
963 | 992 |
964 @type sharedKeyDB: L{tlslite.SharedKeyDB.SharedKeyDB} | 993 @type verifierDB: L{tlslite.verifierdb.VerifierDB} |
965 @param sharedKeyDB: A database of shared symmetric keys | |
966 associated with usernames. If the client performs a | |
967 shared-key handshake, the session's sharedKeyUsername | |
968 attribute will be set. | |
969 | |
970 @type verifierDB: L{tlslite.VerifierDB.VerifierDB} | |
971 @param verifierDB: A database of SRP password verifiers | 994 @param verifierDB: A database of SRP password verifiers |
972 associated with usernames. If the client performs an SRP | 995 associated with usernames. If the client performs an SRP |
973 handshake, the session's srpUsername attribute will be set. | 996 handshake, the session's srpUsername attribute will be set. |
974 | 997 |
975 @type certChain: L{tlslite.X509CertChain.X509CertChain} or | 998 @type certChain: L{tlslite.x509certchain.X509CertChain} |
976 L{cryptoIDlib.CertChain.CertChain} | |
977 @param certChain: The certificate chain to be used if the | 999 @param certChain: The certificate chain to be used if the |
978 client requests server certificate authentication. | 1000 client requests server certificate authentication. |
979 | 1001 |
980 @type privateKey: L{tlslite.utils.RSAKey.RSAKey} | 1002 @type privateKey: L{tlslite.utils.rsakey.RSAKey} |
981 @param privateKey: The private key to be used if the client | 1003 @param privateKey: The private key to be used if the client |
982 requests server certificate authentication. | 1004 requests server certificate authentication. |
983 | 1005 |
984 @type reqCert: bool | 1006 @type reqCert: bool |
985 @param reqCert: Whether to request client certificate | 1007 @param reqCert: Whether to request client certificate |
986 authentication. This only applies if the client chooses server | 1008 authentication. This only applies if the client chooses server |
987 certificate authentication; if the client chooses SRP or | 1009 certificate authentication; if the client chooses SRP |
988 shared-key authentication, this will be ignored. If the client | 1010 authentication, this will be ignored. If the client |
989 performs a client certificate authentication, the sessions's | 1011 performs a client certificate authentication, the sessions's |
990 clientCertChain attribute will be set. | 1012 clientCertChain attribute will be set. |
991 | 1013 |
992 @type sessionCache: L{tlslite.SessionCache.SessionCache} | 1014 @type sessionCache: L{tlslite.sessioncache.SessionCache} |
993 @param sessionCache: An in-memory cache of resumable sessions. | 1015 @param sessionCache: An in-memory cache of resumable sessions. |
994 The client can resume sessions from this cache. Alternatively, | 1016 The client can resume sessions from this cache. Alternatively, |
995 if the client performs a full handshake, a new session will be | 1017 if the client performs a full handshake, a new session will be |
996 added to the cache. | 1018 added to the cache. |
997 | 1019 |
998 @type settings: L{tlslite.HandshakeSettings.HandshakeSettings} | 1020 @type settings: L{tlslite.handshakesettings.HandshakeSettings} |
999 @param settings: Various settings which can be used to control | 1021 @param settings: Various settings which can be used to control |
1000 the ciphersuites and SSL/TLS version chosen by the server. | 1022 the ciphersuites and SSL/TLS version chosen by the server. |
1001 | 1023 |
1002 @type checker: L{tlslite.Checker.Checker} | 1024 @type checker: L{tlslite.checker.Checker} |
1003 @param checker: A Checker instance. This instance will be | 1025 @param checker: A Checker instance. This instance will be |
1004 invoked to examine the other party's authentication | 1026 invoked to examine the other party's authentication |
1005 credentials, if the handshake completes succesfully. | 1027 credentials, if the handshake completes succesfully. |
1006 | 1028 |
1007 @type reqCAs: list of L{array.array} of unsigned bytes | 1029 @type reqCAs: list of L{bytearray} of unsigned bytes |
1008 @param reqCAs: A collection of DER-encoded DistinguishedNames that | 1030 @param reqCAs: A collection of DER-encoded DistinguishedNames that |
1009 will be sent along with a certificate request. This does not affect | 1031 will be sent along with a certificate request. This does not affect |
1010 verification. | 1032 verification. |
| 1033 |
| 1034 @type nextProtos: list of strings. |
| 1035 @param nextProtos: A list of upper layer protocols to expose to the |
| 1036 clients through the Next-Protocol Negotiation Extension, |
| 1037 if they support it. |
| 1038 |
| 1039 @type tlsIntolerant: (int, int) or None |
| 1040 @param tlsIntolerant: If tlsIntolerant is not None, the server will |
| 1041 simulate TLS version intolerance by returning a fatal handshake_failure |
| 1042 alert to all TLS versions tlsIntolerant or higher. |
1011 | 1043 |
1012 @type signedCertTimestamps: str | 1044 @type signedCertTimestamps: str |
1013 @param signedCertTimestamps: A SignedCertificateTimestampList (as a | 1045 @param signedCertTimestamps: A SignedCertificateTimestampList (as a |
1014 binary 8-bit string) that will be sent as a TLS extension whenever | 1046 binary 8-bit string) that will be sent as a TLS extension whenever |
1015 the client announces support for the extension. | 1047 the client announces support for the extension. |
1016 | 1048 |
1017 @type tlsIntolerant: int | |
1018 @param tlsIntolerant: if non-zero, the server will simulate TLS | |
1019 version intolerance by returning a fatal, handshake_failure alert. | |
1020 The versions to which it's intolerant vary depending on the value: | |
1021 1: reject all TLS versions. | |
1022 2: reject TLS 1.1 or higher. | |
1023 3: reject TLS 1.2 or higher. | |
1024 | |
1025 @type fallbackSCSV: bool | 1049 @type fallbackSCSV: bool |
1026 @param fallbackSCSV: if true, the server will implement | 1050 @param fallbackSCSV: if true, the server will implement |
1027 TLS_FALLBACK_SCSV and thus reject connections using less than the | 1051 TLS_FALLBACK_SCSV and thus reject connections using less than the |
1028 server's maximum TLS version that include this cipher suite. | 1052 server's maximum TLS version that include this cipher suite. |
1029 | 1053 |
1030 @type ocspResponse: str | 1054 @type ocspResponse: str |
1031 @param ocspResponse: An OCSP response (as a binary 8-bit string) that | 1055 @param ocspResponse: An OCSP response (as a binary 8-bit string) that |
1032 will be sent stapled in the handshake whenever the client announces | 1056 will be sent stapled in the handshake whenever the client announces |
1033 support for the status_request extension. | 1057 support for the status_request extension. |
1034 Note that the response is sent independent of the ClientHello | 1058 Note that the response is sent independent of the ClientHello |
1035 status_request extension contents, and is thus only meant for testing | 1059 status_request extension contents, and is thus only meant for testing |
1036 environments. Real OCSP stapling is more complicated as it requires | 1060 environments. Real OCSP stapling is more complicated as it requires |
1037 choosing a suitable response based on the ClientHello status_request | 1061 choosing a suitable response based on the ClientHello status_request |
1038 extension contents. | 1062 extension contents. |
1039 | 1063 |
1040 @raise socket.error: If a socket error occurs. | 1064 @raise socket.error: If a socket error occurs. |
1041 @raise tlslite.errors.TLSAbruptCloseError: If the socket is closed | 1065 @raise tlslite.errors.TLSAbruptCloseError: If the socket is closed |
1042 without a preceding alert. | 1066 without a preceding alert. |
1043 @raise tlslite.errors.TLSAlert: If a TLS alert is signalled. | 1067 @raise tlslite.errors.TLSAlert: If a TLS alert is signalled. |
1044 @raise tlslite.errors.TLSAuthenticationError: If the checker | 1068 @raise tlslite.errors.TLSAuthenticationError: If the checker |
1045 doesn't like the other party's authentication credentials. | 1069 doesn't like the other party's authentication credentials. |
1046 """ | 1070 """ |
1047 for result in self.handshakeServerAsync(sharedKeyDB, verifierDB, | 1071 for result in self.handshakeServerAsync(verifierDB, |
1048 certChain, privateKey, reqCert, sessionCache, settings, | 1072 certChain, privateKey, reqCert, sessionCache, settings, |
1049 checker, reqCAs, tlsIntolerant, signedCertTimestamps, | 1073 checker, reqCAs, |
1050 fallbackSCSV, ocspResponse): | 1074 tacks=tacks, activationFlags=activationFlags, |
| 1075 nextProtos=nextProtos, anon=anon, tlsIntolerant=tlsIntolerant, |
| 1076 signedCertTimestamps=signedCertTimestamps, |
| 1077 fallbackSCSV=fallbackSCSV, ocspResponse=ocspResponse): |
1051 pass | 1078 pass |
1052 | 1079 |
1053 | 1080 |
1054 def handshakeServerAsync(self, sharedKeyDB=None, verifierDB=None, | 1081 def handshakeServerAsync(self, verifierDB=None, |
1055 certChain=None, privateKey=None, reqCert=False, | 1082 certChain=None, privateKey=None, reqCert=False, |
1056 sessionCache=None, settings=None, checker=None, | 1083 sessionCache=None, settings=None, checker=None, |
1057 reqCAs=None, tlsIntolerant=0, | 1084 reqCAs=None, |
| 1085 tacks=None, activationFlags=0, |
| 1086 nextProtos=None, anon=False, |
| 1087 tlsIntolerant=None, |
1058 signedCertTimestamps=None, | 1088 signedCertTimestamps=None, |
1059 fallbackSCSV=False, ocspResponse=None): | 1089 fallbackSCSV=False, |
| 1090 ocspResponse=None |
| 1091 ): |
1060 """Start a server handshake operation on the TLS connection. | 1092 """Start a server handshake operation on the TLS connection. |
1061 | 1093 |
1062 This function returns a generator which behaves similarly to | 1094 This function returns a generator which behaves similarly to |
1063 handshakeServer(). Successive invocations of the generator | 1095 handshakeServer(). Successive invocations of the generator |
1064 will return 0 if it is waiting to read from the socket, 1 if it is | 1096 will return 0 if it is waiting to read from the socket, 1 if it is |
1065 waiting to write to the socket, or it will raise StopIteration | 1097 waiting to write to the socket, or it will raise StopIteration |
1066 if the handshake operation is complete. | 1098 if the handshake operation is complete. |
1067 | 1099 |
1068 @rtype: iterable | 1100 @rtype: iterable |
1069 @return: A generator; see above for details. | 1101 @return: A generator; see above for details. |
1070 """ | 1102 """ |
1071 handshaker = self._handshakeServerAsyncHelper(\ | 1103 handshaker = self._handshakeServerAsyncHelper(\ |
1072 sharedKeyDB=sharedKeyDB, | |
1073 verifierDB=verifierDB, certChain=certChain, | 1104 verifierDB=verifierDB, certChain=certChain, |
1074 privateKey=privateKey, reqCert=reqCert, | 1105 privateKey=privateKey, reqCert=reqCert, |
1075 sessionCache=sessionCache, settings=settings, | 1106 sessionCache=sessionCache, settings=settings, |
1076 reqCAs=reqCAs, | 1107 reqCAs=reqCAs, |
| 1108 tacks=tacks, activationFlags=activationFlags, |
| 1109 nextProtos=nextProtos, anon=anon, |
1077 tlsIntolerant=tlsIntolerant, | 1110 tlsIntolerant=tlsIntolerant, |
1078 signedCertTimestamps=signedCertTimestamps, | 1111 signedCertTimestamps=signedCertTimestamps, |
1079 fallbackSCSV=fallbackSCSV, ocspResponse=ocspResponse) | 1112 fallbackSCSV=fallbackSCSV, |
1080 | 1113 ocspResponse=ocspResponse) |
1081 for result in self._handshakeWrapperAsync(handshaker, checker): | 1114 for result in self._handshakeWrapperAsync(handshaker, checker): |
1082 yield result | 1115 yield result |
1083 | 1116 |
1084 | 1117 |
1085 def _handshakeServerAsyncHelper(self, sharedKeyDB, verifierDB, | 1118 def _handshakeServerAsyncHelper(self, verifierDB, |
1086 certChain, privateKey, reqCert, | 1119 certChain, privateKey, reqCert, sessionCache, |
1087 sessionCache, settings, reqCAs, | 1120 settings, reqCAs, |
1088 tlsIntolerant, signedCertTimestamps, | 1121 tacks, activationFlags, |
1089 fallbackSCSV, ocspResponse): | 1122 nextProtos, anon, |
| 1123 tlsIntolerant, signedCertTimestamps, fallbackSCSV, |
| 1124 ocspResponse): |
1090 | 1125 |
1091 self._handshakeStart(client=False) | 1126 self._handshakeStart(client=False) |
1092 | 1127 |
1093 if (not sharedKeyDB) and (not verifierDB) and (not certChain): | 1128 if (not verifierDB) and (not certChain) and not anon: |
1094 raise ValueError("Caller passed no authentication credentials") | 1129 raise ValueError("Caller passed no authentication credentials") |
1095 if certChain and not privateKey: | 1130 if certChain and not privateKey: |
1096 raise ValueError("Caller passed a certChain but no privateKey") | 1131 raise ValueError("Caller passed a certChain but no privateKey") |
1097 if privateKey and not certChain: | 1132 if privateKey and not certChain: |
1098 raise ValueError("Caller passed a privateKey but no certChain") | 1133 raise ValueError("Caller passed a privateKey but no certChain") |
1099 if reqCAs and not reqCert: | 1134 if reqCAs and not reqCert: |
1100 raise ValueError("Caller passed reqCAs but not reqCert") | 1135 raise ValueError("Caller passed reqCAs but not reqCert") |
| 1136 if certChain and not isinstance(certChain, X509CertChain): |
| 1137 raise ValueError("Unrecognized certificate type") |
| 1138 if activationFlags and not tacks: |
| 1139 raise ValueError("Nonzero activationFlags requires tacks") |
| 1140 if tacks: |
| 1141 if not tackpyLoaded: |
| 1142 raise ValueError("tackpy is not loaded") |
| 1143 if not settings or not settings.useExperimentalTackExtension: |
| 1144 raise ValueError("useExperimentalTackExtension not enabled") |
1101 if signedCertTimestamps and not certChain: | 1145 if signedCertTimestamps and not certChain: |
1102 raise ValueError("Caller passed signedCertTimestamps but no " | 1146 raise ValueError("Caller passed signedCertTimestamps but no " |
1103 "certChain") | 1147 "certChain") |
1104 | 1148 |
1105 if not settings: | 1149 if not settings: |
1106 settings = HandshakeSettings() | 1150 settings = HandshakeSettings() |
1107 settings = settings._filter() | 1151 settings = settings._filter() |
| 1152 |
| 1153 # OK Start exchanging messages |
| 1154 # ****************************** |
| 1155 |
| 1156 # Handle ClientHello and resumption |
| 1157 for result in self._serverGetClientHello(settings, certChain,\ |
| 1158 verifierDB, sessionCache, |
| 1159 anon, tlsIntolerant, fallbackSCSV): |
| 1160 if result in (0,1): yield result |
| 1161 elif result == None: |
| 1162 self._handshakeDone(resumed=True) |
| 1163 return # Handshake was resumed, we're done |
| 1164 else: break |
| 1165 (clientHello, cipherSuite) = result |
| 1166 |
| 1167 #If not a resumption... |
1108 | 1168 |
| 1169 # Create the ServerHello message |
| 1170 if sessionCache: |
| 1171 sessionID = getRandomBytes(32) |
| 1172 else: |
| 1173 sessionID = bytearray(0) |
| 1174 |
| 1175 if not clientHello.supports_npn: |
| 1176 nextProtos = None |
| 1177 |
| 1178 # If not doing a certificate-based suite, discard the TACK |
| 1179 if not cipherSuite in CipherSuite.certAllSuites: |
| 1180 tacks = None |
| 1181 |
| 1182 # Prepare a TACK Extension if requested |
| 1183 if clientHello.tack: |
| 1184 tackExt = TackExtension.create(tacks, activationFlags) |
| 1185 else: |
| 1186 tackExt = None |
| 1187 serverHello = ServerHello() |
| 1188 serverHello.create(self.version, getRandomBytes(32), sessionID, \ |
| 1189 cipherSuite, CertificateType.x509, tackExt, |
| 1190 nextProtos) |
| 1191 serverHello.channel_id = clientHello.channel_id |
| 1192 if clientHello.support_signed_cert_timestamps: |
| 1193 serverHello.signed_cert_timestamps = signedCertTimestamps |
| 1194 if clientHello.status_request: |
| 1195 serverHello.status_request = ocspResponse |
| 1196 |
| 1197 # Perform the SRP key exchange |
| 1198 clientCertChain = None |
| 1199 if cipherSuite in CipherSuite.srpAllSuites: |
| 1200 for result in self._serverSRPKeyExchange(clientHello, serverHello, |
| 1201 verifierDB, cipherSuite, |
| 1202 privateKey, certChain): |
| 1203 if result in (0,1): yield result |
| 1204 else: break |
| 1205 premasterSecret = result |
| 1206 |
| 1207 # Perform the RSA key exchange |
| 1208 elif cipherSuite in CipherSuite.certSuites: |
| 1209 for result in self._serverCertKeyExchange(clientHello, serverHello, |
| 1210 certChain, privateKey, |
| 1211 reqCert, reqCAs, cipherSuite, |
| 1212 settings, ocspResponse): |
| 1213 if result in (0,1): yield result |
| 1214 else: break |
| 1215 (premasterSecret, clientCertChain) = result |
| 1216 |
| 1217 # Perform anonymous Diffie Hellman key exchange |
| 1218 elif cipherSuite in CipherSuite.anonSuites: |
| 1219 for result in self._serverAnonKeyExchange(clientHello, serverHello, |
| 1220 cipherSuite, settings): |
| 1221 if result in (0,1): yield result |
| 1222 else: break |
| 1223 premasterSecret = result |
| 1224 |
| 1225 else: |
| 1226 assert(False) |
| 1227 |
| 1228 # Exchange Finished messages |
| 1229 for result in self._serverFinished(premasterSecret, |
| 1230 clientHello.random, serverHello.random, |
| 1231 cipherSuite, settings.cipherImplementations, |
| 1232 nextProtos, clientHello.channel_id): |
| 1233 if result in (0,1): yield result |
| 1234 else: break |
| 1235 masterSecret = result |
| 1236 |
| 1237 #Create the session object |
| 1238 self.session = Session() |
| 1239 if cipherSuite in CipherSuite.certAllSuites: |
| 1240 serverCertChain = certChain |
| 1241 else: |
| 1242 serverCertChain = None |
| 1243 srpUsername = None |
| 1244 serverName = None |
| 1245 if clientHello.srp_username: |
| 1246 srpUsername = clientHello.srp_username.decode("utf-8") |
| 1247 if clientHello.server_name: |
| 1248 serverName = clientHello.server_name.decode("utf-8") |
| 1249 self.session.create(masterSecret, serverHello.session_id, cipherSuite, |
| 1250 srpUsername, clientCertChain, serverCertChain, |
| 1251 tackExt, serverHello.tackExt!=None, serverName) |
| 1252 |
| 1253 #Add the session object to the session cache |
| 1254 if sessionCache and sessionID: |
| 1255 sessionCache[sessionID] = self.session |
| 1256 |
| 1257 self._handshakeDone(resumed=False) |
| 1258 |
| 1259 |
| 1260 def _serverGetClientHello(self, settings, certChain, verifierDB, |
| 1261 sessionCache, anon, tlsIntolerant, fallbackSCSV)
: |
1109 #Initialize acceptable cipher suites | 1262 #Initialize acceptable cipher suites |
1110 cipherSuites = [] | 1263 cipherSuites = [] |
1111 if verifierDB: | 1264 if verifierDB: |
1112 if certChain: | 1265 if certChain: |
1113 cipherSuites += \ | 1266 cipherSuites += \ |
1114 CipherSuite.getSrpRsaSuites(settings.cipherNames) | 1267 CipherSuite.getSrpCertSuites(settings) |
1115 cipherSuites += CipherSuite.getSrpSuites(settings.cipherNames) | 1268 cipherSuites += CipherSuite.getSrpSuites(settings) |
1116 if sharedKeyDB or certChain: | 1269 elif certChain: |
1117 cipherSuites += CipherSuite.getRsaSuites(settings.cipherNames) | 1270 cipherSuites += CipherSuite.getCertSuites(settings) |
1118 | 1271 elif anon: |
1119 #Initialize acceptable certificate type | 1272 cipherSuites += CipherSuite.getAnonSuites(settings) |
1120 certificateType = None | 1273 else: |
1121 if certChain: | 1274 assert(False) |
1122 try: | |
1123 import cryptoIDlib.CertChain | |
1124 if isinstance(certChain, cryptoIDlib.CertChain.CertChain): | |
1125 certificateType = CertificateType.cryptoID | |
1126 except ImportError: | |
1127 pass | |
1128 if isinstance(certChain, X509CertChain): | |
1129 certificateType = CertificateType.x509 | |
1130 if certificateType == None: | |
1131 raise ValueError("Unrecognized certificate type") | |
1132 | |
1133 #Initialize locals | |
1134 clientCertChain = None | |
1135 serverCertChain = None #We may set certChain to this later | |
1136 postFinishedError = None | |
1137 doingChannelID = False | |
1138 | 1275 |
1139 #Tentatively set version to most-desirable version, so if an error | 1276 #Tentatively set version to most-desirable version, so if an error |
1140 #occurs parsing the ClientHello, this is what we'll use for the | 1277 #occurs parsing the ClientHello, this is what we'll use for the |
1141 #error alert | 1278 #error alert |
1142 self.version = settings.maxVersion | 1279 self.version = settings.maxVersion |
1143 | 1280 |
1144 #Get ClientHello | 1281 #Get ClientHello |
1145 for result in self._getMsg(ContentType.handshake, | 1282 for result in self._getMsg(ContentType.handshake, |
1146 HandshakeType.client_hello): | 1283 HandshakeType.client_hello): |
1147 if result in (0,1): | 1284 if result in (0,1): yield result |
1148 yield result | 1285 else: break |
1149 else: | |
1150 break | |
1151 clientHello = result | 1286 clientHello = result |
1152 | 1287 |
1153 #If client's version is too low, reject it | 1288 #If client's version is too low, reject it |
1154 if clientHello.client_version < settings.minVersion: | 1289 if clientHello.client_version < settings.minVersion: |
1155 self.version = settings.minVersion | 1290 self.version = settings.minVersion |
1156 for result in self._sendError(\ | 1291 for result in self._sendError(\ |
1157 AlertDescription.protocol_version, | 1292 AlertDescription.protocol_version, |
1158 "Too old version: %s" % str(clientHello.client_version)): | 1293 "Too old version: %s" % str(clientHello.client_version)): |
1159 yield result | 1294 yield result |
1160 | 1295 |
1161 #If tlsIntolerant is nonzero, reject certain TLS versions. | 1296 #If simulating TLS intolerance, reject certain TLS versions. |
1162 #1: reject all TLS versions. | 1297 elif (tlsIntolerant is not None and |
1163 #2: reject TLS 1.1 or higher. | 1298 clientHello.client_version >= tlsIntolerant): |
1164 #3: reject TLS 1.2 or higher. | |
1165 if (tlsIntolerant == 1 and clientHello.client_version > (3, 0) or | |
1166 tlsIntolerant == 2 and clientHello.client_version > (3, 1) or | |
1167 tlsIntolerant == 3 and clientHello.client_version > (3, 2)): | |
1168 for result in self._sendError(\ | 1299 for result in self._sendError(\ |
1169 AlertDescription.handshake_failure): | 1300 AlertDescription.handshake_failure): |
1170 yield result | 1301 yield result |
1171 | 1302 |
1172 #If client's version is too high, propose my highest version | 1303 #If client's version is too high, propose my highest version |
1173 if clientHello.client_version > settings.maxVersion: | 1304 elif clientHello.client_version > settings.maxVersion: |
1174 self.version = settings.maxVersion | 1305 self.version = settings.maxVersion |
| 1306 |
| 1307 #Detect if the client performed an inappropriate fallback. |
| 1308 elif fallbackSCSV and clientHello.client_version < settings.maxVersion: |
| 1309 if CipherSuite.TLS_FALLBACK_SCSV in clientHello.cipher_suites: |
| 1310 for result in self._sendError(\ |
| 1311 AlertDescription.inappropriate_fallback): |
| 1312 yield result |
| 1313 |
1175 else: | 1314 else: |
1176 #Set the version to the client's version | 1315 #Set the version to the client's version |
1177 self.version = clientHello.client_version | 1316 self.version = clientHello.client_version |
1178 if (fallbackSCSV and | |
1179 clientHello.client_version < settings.maxVersion): | |
1180 for cipherSuite in clientHello.cipher_suites: | |
1181 if cipherSuite == 0x5600: | |
1182 for result in self._sendError(\ | |
1183 AlertDescription.inappropriate_fallback): | |
1184 yield result | |
1185 | 1317 |
1186 #Get the client nonce; create server nonce | 1318 #If resumption was requested and we have a session cache... |
1187 clientRandom = clientHello.random | 1319 if clientHello.session_id and sessionCache: |
1188 serverRandom = getRandomBytes(32) | |
1189 | |
1190 #Calculate the first cipher suite intersection. | |
1191 #This is the 'privileged' ciphersuite. We'll use it if we're | |
1192 #doing a shared-key resumption or a new negotiation. In fact, | |
1193 #the only time we won't use it is if we're resuming a non-sharedkey | |
1194 #session, in which case we use the ciphersuite from the session. | |
1195 # | |
1196 #Given the current ciphersuite ordering, this means we prefer SRP | |
1197 #over non-SRP. | |
1198 for cipherSuite in cipherSuites: | |
1199 if cipherSuite in clientHello.cipher_suites: | |
1200 break | |
1201 else: | |
1202 for result in self._sendError(\ | |
1203 AlertDescription.handshake_failure): | |
1204 yield result | |
1205 | |
1206 #If resumption was requested... | |
1207 if clientHello.session_id and (sharedKeyDB or sessionCache): | |
1208 session = None | 1320 session = None |
1209 | 1321 |
1210 #Check in the sharedKeys container | 1322 #Check in the session cache |
1211 if sharedKeyDB and len(clientHello.session_id)==16: | |
1212 try: | |
1213 #Trim off zero padding, if any | |
1214 for x in range(16): | |
1215 if clientHello.session_id[x]==0: | |
1216 break | |
1217 self.allegedSharedKeyUsername = bytesToString(\ | |
1218 clientHello.session_id[:x]) | |
1219 session = sharedKeyDB[self.allegedSharedKeyUsername] | |
1220 if not session.sharedKey: | |
1221 raise AssertionError() | |
1222 #use privileged ciphersuite | |
1223 session.cipherSuite = cipherSuite | |
1224 except KeyError: | |
1225 pass | |
1226 | |
1227 #Then check in the session cache | |
1228 if sessionCache and not session: | 1323 if sessionCache and not session: |
1229 try: | 1324 try: |
1230 session = sessionCache[bytesToString(\ | 1325 session = sessionCache[clientHello.session_id] |
1231 clientHello.session_id)] | |
1232 if session.sharedKey: | |
1233 raise AssertionError() | |
1234 if not session.resumable: | 1326 if not session.resumable: |
1235 raise AssertionError() | 1327 raise AssertionError() |
1236 #Check for consistency with ClientHello | 1328 #Check for consistency with ClientHello |
1237 if session.cipherSuite not in cipherSuites: | 1329 if session.cipherSuite not in cipherSuites: |
1238 for result in self._sendError(\ | 1330 for result in self._sendError(\ |
1239 AlertDescription.handshake_failure): | 1331 AlertDescription.handshake_failure): |
1240 yield result | 1332 yield result |
1241 if session.cipherSuite not in clientHello.cipher_suites: | 1333 if session.cipherSuite not in clientHello.cipher_suites: |
1242 for result in self._sendError(\ | 1334 for result in self._sendError(\ |
1243 AlertDescription.handshake_failure): | 1335 AlertDescription.handshake_failure): |
1244 yield result | 1336 yield result |
1245 if clientHello.srp_username: | 1337 if clientHello.srp_username: |
1246 if clientHello.srp_username != session.srpUsername: | 1338 if not session.srpUsername or \ |
| 1339 clientHello.srp_username != bytearray(session.srpUse
rname, "utf-8"): |
1247 for result in self._sendError(\ | 1340 for result in self._sendError(\ |
1248 AlertDescription.handshake_failure): | 1341 AlertDescription.handshake_failure): |
1249 yield result | 1342 yield result |
| 1343 if clientHello.server_name: |
| 1344 if not session.serverName or \ |
| 1345 clientHello.server_name != bytearray(session.serverN
ame, "utf-8"): |
| 1346 for result in self._sendError(\ |
| 1347 AlertDescription.handshake_failure): |
| 1348 yield result |
1250 except KeyError: | 1349 except KeyError: |
1251 pass | 1350 pass |
1252 | 1351 |
1253 #If a session is found.. | 1352 #If a session is found.. |
1254 if session: | 1353 if session: |
| 1354 #Send ServerHello |
| 1355 serverHello = ServerHello() |
| 1356 serverHello.create(self.version, getRandomBytes(32), |
| 1357 session.sessionID, session.cipherSuite, |
| 1358 CertificateType.x509, None, None) |
| 1359 for result in self._sendMsg(serverHello): |
| 1360 yield result |
| 1361 |
| 1362 #From here on, the client's messages must have right version |
| 1363 self._versionCheck = True |
| 1364 |
| 1365 #Calculate pending connection states |
| 1366 self._calcPendingStates(session.cipherSuite, |
| 1367 session.masterSecret, |
| 1368 clientHello.random, |
| 1369 serverHello.random, |
| 1370 settings.cipherImplementations) |
| 1371 |
| 1372 #Exchange ChangeCipherSpec and Finished messages |
| 1373 for result in self._sendFinished(session.masterSecret): |
| 1374 yield result |
| 1375 for result in self._getFinished(session.masterSecret): |
| 1376 yield result |
| 1377 |
1255 #Set the session | 1378 #Set the session |
1256 self.session = session | 1379 self.session = session |
1257 | 1380 |
1258 #Send ServerHello | 1381 yield None # Handshake done! |
1259 serverHello = ServerHello() | 1382 |
1260 serverHello.create(self.version, serverRandom, | 1383 #Calculate the first cipher suite intersection. |
1261 session.sessionID, session.cipherSuite, | 1384 #This is the 'privileged' ciphersuite. We'll use it if we're |
1262 certificateType) | 1385 #doing a new negotiation. In fact, |
1263 serverHello.channel_id = clientHello.channel_id | 1386 #the only time we won't use it is if we're resuming a |
1264 doingChannelID = clientHello.channel_id | 1387 #session, in which case we use the ciphersuite from the session. |
1265 for result in self._sendMsg(serverHello): | 1388 # |
1266 yield result | 1389 #Use the client's preferences for now. |
1267 | 1390 for cipherSuite in clientHello.cipher_suites: |
1268 #From here on, the client's messages must have the right version | 1391 if cipherSuite in cipherSuites: |
1269 self._versionCheck = True | 1392 break |
1270 | 1393 else: |
1271 #Calculate pending connection states | |
1272 self._calcPendingStates(clientRandom, serverRandom, | |
1273 settings.cipherImplementations) | |
1274 | |
1275 #Exchange ChangeCipherSpec and Finished messages | |
1276 for result in self._sendFinished(): | |
1277 yield result | |
1278 for result in self._getChangeCipherSpec(): | |
1279 yield result | |
1280 if doingChannelID: | |
1281 for result in self._getEncryptedExtensions(): | |
1282 yield result | |
1283 for result in self._getFinished(): | |
1284 yield result | |
1285 | |
1286 #Mark the connection as open | |
1287 self._handshakeDone(resumed=True) | |
1288 return | |
1289 | |
1290 | |
1291 #If not a resumption... | |
1292 | |
1293 #TRICKY: we might have chosen an RSA suite that was only deemed | |
1294 #acceptable because of the shared-key resumption. If the shared- | |
1295 #key resumption failed, because the identifier wasn't recognized, | |
1296 #we might fall through to here, where we have an RSA suite | |
1297 #chosen, but no certificate. | |
1298 if cipherSuite in CipherSuite.rsaSuites and not certChain: | |
1299 for result in self._sendError(\ | 1394 for result in self._sendError(\ |
1300 AlertDescription.handshake_failure): | 1395 AlertDescription.handshake_failure, |
1301 yield result | 1396 "No mutual ciphersuite"): |
1302 | 1397 yield result |
| 1398 if cipherSuite in CipherSuite.srpAllSuites and \ |
| 1399 not clientHello.srp_username: |
| 1400 for result in self._sendError(\ |
| 1401 AlertDescription.unknown_psk_identity, |
| 1402 "Client sent a hello, but without the SRP username"): |
| 1403 yield result |
| 1404 |
1303 #If an RSA suite is chosen, check for certificate type intersection | 1405 #If an RSA suite is chosen, check for certificate type intersection |
1304 #(We do this check down here because if the mismatch occurs but the | 1406 if cipherSuite in CipherSuite.certAllSuites and CertificateType.x509 \ |
1305 # client is using a shared-key session, it's okay) | 1407 not in clientHello.certificate_types: |
1306 if cipherSuite in CipherSuite.rsaSuites + \ | 1408 for result in self._sendError(\ |
1307 CipherSuite.srpRsaSuites: | 1409 AlertDescription.handshake_failure, |
1308 if certificateType not in clientHello.certificate_types: | 1410 "the client doesn't support my certificate type"): |
1309 for result in self._sendError(\ | 1411 yield result |
1310 AlertDescription.handshake_failure, | 1412 |
1311 "the client doesn't support my certificate type"): | 1413 # If resumption was not requested, or |
1312 yield result | 1414 # we have no session cache, or |
1313 | 1415 # the client's session_id was not found in cache: |
1314 #Move certChain -> serverCertChain, now that we're using it | 1416 yield (clientHello, cipherSuite) |
1315 serverCertChain = certChain | 1417 |
1316 | 1418 def _serverSRPKeyExchange(self, clientHello, serverHello, verifierDB, |
1317 | 1419 cipherSuite, privateKey, serverCertChain): |
1318 #Create sessionID | 1420 |
1319 if sessionCache: | 1421 srpUsername = clientHello.srp_username.decode("utf-8") |
1320 sessionID = getRandomBytes(32) | 1422 self.allegedSrpUsername = srpUsername |
1321 else: | 1423 #Get parameters from username |
1322 sessionID = createByteArraySequence([]) | 1424 try: |
1323 | 1425 entry = verifierDB[srpUsername] |
1324 #If we've selected an SRP suite, exchange keys and calculate | 1426 except KeyError: |
1325 #premaster secret: | 1427 for result in self._sendError(\ |
1326 if cipherSuite in CipherSuite.srpSuites + CipherSuite.srpRsaSuites: | 1428 AlertDescription.unknown_psk_identity): |
1327 | 1429 yield result |
1328 #If there's no SRP username... | 1430 (N, g, s, v) = entry |
1329 if not clientHello.srp_username: | 1431 |
1330 | 1432 #Calculate server's ephemeral DH values (b, B) |
1331 #Ask the client to re-send ClientHello with one | 1433 b = bytesToNumber(getRandomBytes(32)) |
1332 for result in self._sendMsg(Alert().create(\ | 1434 k = makeK(N, g) |
1333 AlertDescription.missing_srp_username, | 1435 B = (powMod(g, b, N) + (k*v)) % N |
1334 AlertLevel.warning)): | 1436 |
1335 yield result | 1437 #Create ServerKeyExchange, signing it if necessary |
1336 | 1438 serverKeyExchange = ServerKeyExchange(cipherSuite) |
1337 #Get ClientHello | 1439 serverKeyExchange.createSRP(N, g, s, B) |
1338 for result in self._getMsg(ContentType.handshake, | 1440 if cipherSuite in CipherSuite.srpCertSuites: |
1339 HandshakeType.client_hello): | 1441 hashBytes = serverKeyExchange.hash(clientHello.random, |
1340 if result in (0,1): | 1442 serverHello.random) |
1341 yield result | 1443 serverKeyExchange.signature = privateKey.sign(hashBytes) |
1342 else: | 1444 |
1343 break | 1445 #Send ServerHello[, Certificate], ServerKeyExchange, |
1344 clientHello = result | 1446 #ServerHelloDone |
1345 | 1447 msgs = [] |
1346 #Check ClientHello | 1448 msgs.append(serverHello) |
1347 #If client's version is too low, reject it (COPIED CODE; BAD!) | 1449 if cipherSuite in CipherSuite.srpCertSuites: |
1348 if clientHello.client_version < settings.minVersion: | 1450 certificateMsg = Certificate(CertificateType.x509) |
1349 self.version = settings.minVersion | 1451 certificateMsg.create(serverCertChain) |
1350 for result in self._sendError(\ | 1452 msgs.append(certificateMsg) |
1351 AlertDescription.protocol_version, | 1453 msgs.append(serverKeyExchange) |
1352 "Too old version: %s" % str(clientHello.client_version
)): | 1454 msgs.append(ServerHelloDone()) |
1353 yield result | 1455 for result in self._sendMsgs(msgs): |
1354 | 1456 yield result |
1355 #If client's version is too high, propose my highest version | 1457 |
1356 elif clientHello.client_version > settings.maxVersion: | 1458 #From here on, the client's messages must have the right version |
1357 self.version = settings.maxVersion | 1459 self._versionCheck = True |
1358 | 1460 |
1359 else: | 1461 #Get and check ClientKeyExchange |
1360 #Set the version to the client's version | 1462 for result in self._getMsg(ContentType.handshake, |
1361 self.version = clientHello.client_version | 1463 HandshakeType.client_key_exchange, |
1362 | 1464 cipherSuite): |
1363 #Recalculate the privileged cipher suite, making sure to | 1465 if result in (0,1): yield result |
1364 #pick an SRP suite | 1466 else: break |
1365 cipherSuites = [c for c in cipherSuites if c in \ | 1467 clientKeyExchange = result |
1366 CipherSuite.srpSuites + \ | 1468 A = clientKeyExchange.srp_A |
1367 CipherSuite.srpRsaSuites] | 1469 if A % N == 0: |
1368 for cipherSuite in cipherSuites: | 1470 for result in self._sendError(AlertDescription.illegal_parameter, |
1369 if cipherSuite in clientHello.cipher_suites: | 1471 "Suspicious A value"): |
1370 break | 1472 yield result |
1371 else: | 1473 assert(False) # Just to ensure we don't fall through somehow |
1372 for result in self._sendError(\ | 1474 |
1373 AlertDescription.handshake_failure): | 1475 #Calculate u |
1374 yield result | 1476 u = makeU(N, A, B) |
1375 | 1477 |
1376 #Get the client nonce; create server nonce | 1478 #Calculate premaster secret |
1377 clientRandom = clientHello.random | 1479 S = powMod((A * powMod(v,u,N)) % N, b, N) |
1378 serverRandom = getRandomBytes(32) | 1480 premasterSecret = numberToByteArray(S) |
1379 | 1481 |
1380 #The username better be there, this time | 1482 yield premasterSecret |
1381 if not clientHello.srp_username: | 1483 |
1382 for result in self._sendError(\ | 1484 |
1383 AlertDescription.illegal_parameter, | 1485 def _serverCertKeyExchange(self, clientHello, serverHello, |
1384 "Client resent a hello, but without the SRP"\ | 1486 serverCertChain, privateKey, |
1385 " username"): | 1487 reqCert, reqCAs, cipherSuite, |
1386 yield result | 1488 settings, ocspResponse): |
1387 | 1489 #Send ServerHello, Certificate[, CertificateRequest], |
1388 | 1490 #ServerHelloDone |
1389 #Get username | 1491 msgs = [] |
1390 self.allegedSrpUsername = clientHello.srp_username | 1492 |
1391 | 1493 # If we verify a client cert chain, return it |
1392 #Get parameters from username | 1494 clientCertChain = None |
1393 try: | 1495 |
1394 entry = verifierDB[self.allegedSrpUsername] | 1496 msgs.append(serverHello) |
1395 except KeyError: | 1497 msgs.append(Certificate(CertificateType.x509).create(serverCertChain)) |
1396 for result in self._sendError(\ | 1498 if serverHello.status_request: |
1397 AlertDescription.unknown_srp_username): | 1499 msgs.append(CertificateStatus().create(ocspResponse)) |
1398 yield result | 1500 if reqCert and reqCAs: |
1399 (N, g, s, v) = entry | 1501 msgs.append(CertificateRequest().create(\ |
1400 | 1502 [ClientCertificateType.rsa_sign], reqCAs)) |
1401 #Calculate server's ephemeral DH values (b, B) | 1503 elif reqCert: |
1402 b = bytesToNumber(getRandomBytes(32)) | 1504 msgs.append(CertificateRequest()) |
1403 k = makeK(N, g) | 1505 msgs.append(ServerHelloDone()) |
1404 B = (powMod(g, b, N) + (k*v)) % N | 1506 for result in self._sendMsgs(msgs): |
1405 | 1507 yield result |
1406 #Create ServerKeyExchange, signing it if necessary | 1508 |
1407 serverKeyExchange = ServerKeyExchange(cipherSuite) | 1509 #From here on, the client's messages must have the right version |
1408 serverKeyExchange.createSRP(N, g, stringToBytes(s), B) | 1510 self._versionCheck = True |
1409 if cipherSuite in CipherSuite.srpRsaSuites: | 1511 |
1410 hashBytes = serverKeyExchange.hash(clientRandom, | 1512 #Get [Certificate,] (if was requested) |
1411 serverRandom) | 1513 if reqCert: |
1412 serverKeyExchange.signature = privateKey.sign(hashBytes) | 1514 if self.version == (3,0): |
1413 | 1515 for result in self._getMsg((ContentType.handshake, |
1414 #Send ServerHello[, Certificate], ServerKeyExchange, | 1516 ContentType.alert), |
1415 #ServerHelloDone | 1517 HandshakeType.certificate, |
1416 msgs = [] | 1518 CertificateType.x509): |
1417 serverHello = ServerHello() | 1519 if result in (0,1): yield result |
1418 serverHello.create(self.version, serverRandom, sessionID, | 1520 else: break |
1419 cipherSuite, certificateType) | 1521 msg = result |
1420 msgs.append(serverHello) | 1522 |
1421 if cipherSuite in CipherSuite.srpRsaSuites: | 1523 if isinstance(msg, Alert): |
1422 certificateMsg = Certificate(certificateType) | 1524 #If it's not a no_certificate alert, re-raise |
1423 certificateMsg.create(serverCertChain) | 1525 alert = msg |
1424 msgs.append(certificateMsg) | 1526 if alert.description != \ |
1425 msgs.append(serverKeyExchange) | 1527 AlertDescription.no_certificate: |
1426 msgs.append(ServerHelloDone()) | 1528 self._shutdown(False) |
1427 for result in self._sendMsgs(msgs): | 1529 raise TLSRemoteAlert(alert) |
1428 yield result | 1530 elif isinstance(msg, Certificate): |
1429 | 1531 clientCertificate = msg |
1430 #From here on, the client's messages must have the right version | |
1431 self._versionCheck = True | |
1432 | |
1433 #Get and check ClientKeyExchange | |
1434 for result in self._getMsg(ContentType.handshake, | |
1435 HandshakeType.client_key_exchange, | |
1436 cipherSuite): | |
1437 if result in (0,1): | |
1438 yield result | |
1439 else: | |
1440 break | |
1441 clientKeyExchange = result | |
1442 A = clientKeyExchange.srp_A | |
1443 if A % N == 0: | |
1444 postFinishedError = (AlertDescription.illegal_parameter, | |
1445 "Suspicious A value") | |
1446 #Calculate u | |
1447 u = makeU(N, A, B) | |
1448 | |
1449 #Calculate premaster secret | |
1450 S = powMod((A * powMod(v,u,N)) % N, b, N) | |
1451 premasterSecret = numberToBytes(S) | |
1452 | |
1453 | |
1454 #If we've selected an RSA suite, exchange keys and calculate | |
1455 #premaster secret: | |
1456 elif cipherSuite in CipherSuite.rsaSuites: | |
1457 | |
1458 #Send ServerHello, Certificate[, CertificateRequest], | |
1459 #ServerHelloDone | |
1460 msgs = [] | |
1461 serverHello = ServerHello().create( | |
1462 self.version, serverRandom, | |
1463 sessionID, cipherSuite, certificateType) | |
1464 serverHello.channel_id = clientHello.channel_id | |
1465 if clientHello.support_signed_cert_timestamps: | |
1466 serverHello.signed_cert_timestamps = signedCertTimestamps | |
1467 serverHello.status_request = (clientHello.status_request and | |
1468 ocspResponse) | |
1469 doingChannelID = clientHello.channel_id | |
1470 msgs.append(serverHello) | |
1471 msgs.append(Certificate(certificateType).create(serverCertChain)) | |
1472 if serverHello.status_request: | |
1473 msgs.append(CertificateStatus().create(ocspResponse)) | |
1474 if reqCert and reqCAs: | |
1475 msgs.append(CertificateRequest().create([], reqCAs)) | |
1476 elif reqCert: | |
1477 msgs.append(CertificateRequest()) | |
1478 msgs.append(ServerHelloDone()) | |
1479 for result in self._sendMsgs(msgs): | |
1480 yield result | |
1481 | |
1482 #From here on, the client's messages must have the right version | |
1483 self._versionCheck = True | |
1484 | |
1485 #Get [Certificate,] (if was requested) | |
1486 if reqCert: | |
1487 if self.version == (3,0): | |
1488 for result in self._getMsg((ContentType.handshake, | |
1489 ContentType.alert), | |
1490 HandshakeType.certificate, | |
1491 certificateType): | |
1492 if result in (0,1): | |
1493 yield result | |
1494 else: | |
1495 break | |
1496 msg = result | |
1497 | |
1498 if isinstance(msg, Alert): | |
1499 #If it's not a no_certificate alert, re-raise | |
1500 alert = msg | |
1501 if alert.description != \ | |
1502 AlertDescription.no_certificate: | |
1503 self._shutdown(False) | |
1504 raise TLSRemoteAlert(alert) | |
1505 elif isinstance(msg, Certificate): | |
1506 clientCertificate = msg | |
1507 if clientCertificate.certChain and \ | |
1508 clientCertificate.certChain.getNumCerts()!=0: | |
1509 clientCertChain = clientCertificate.certChain | |
1510 else: | |
1511 raise AssertionError() | |
1512 elif self.version in ((3,1), (3,2)): | |
1513 for result in self._getMsg(ContentType.handshake, | |
1514 HandshakeType.certificate, | |
1515 certificateType): | |
1516 if result in (0,1): | |
1517 yield result | |
1518 else: | |
1519 break | |
1520 clientCertificate = result | |
1521 if clientCertificate.certChain and \ | 1532 if clientCertificate.certChain and \ |
1522 clientCertificate.certChain.getNumCerts()!=0: | 1533 clientCertificate.certChain.getNumCerts()!=0: |
1523 clientCertChain = clientCertificate.certChain | 1534 clientCertChain = clientCertificate.certChain |
1524 else: | 1535 else: |
1525 raise AssertionError() | 1536 raise AssertionError() |
1526 | 1537 elif self.version in ((3,1), (3,2)): |
1527 #Get ClientKeyExchange | 1538 for result in self._getMsg(ContentType.handshake, |
| 1539 HandshakeType.certificate, |
| 1540 CertificateType.x509): |
| 1541 if result in (0,1): yield result |
| 1542 else: break |
| 1543 clientCertificate = result |
| 1544 if clientCertificate.certChain and \ |
| 1545 clientCertificate.certChain.getNumCerts()!=0: |
| 1546 clientCertChain = clientCertificate.certChain |
| 1547 else: |
| 1548 raise AssertionError() |
| 1549 |
| 1550 #Get ClientKeyExchange |
| 1551 for result in self._getMsg(ContentType.handshake, |
| 1552 HandshakeType.client_key_exchange, |
| 1553 cipherSuite): |
| 1554 if result in (0,1): yield result |
| 1555 else: break |
| 1556 clientKeyExchange = result |
| 1557 |
| 1558 #Decrypt ClientKeyExchange |
| 1559 premasterSecret = privateKey.decrypt(\ |
| 1560 clientKeyExchange.encryptedPreMasterSecret) |
| 1561 |
| 1562 # On decryption failure randomize premaster secret to avoid |
| 1563 # Bleichenbacher's "million message" attack |
| 1564 randomPreMasterSecret = getRandomBytes(48) |
| 1565 versionCheck = (premasterSecret[0], premasterSecret[1]) |
| 1566 if not premasterSecret: |
| 1567 premasterSecret = randomPreMasterSecret |
| 1568 elif len(premasterSecret)!=48: |
| 1569 premasterSecret = randomPreMasterSecret |
| 1570 elif versionCheck != clientHello.client_version: |
| 1571 if versionCheck != self.version: #Tolerate buggy IE clients |
| 1572 premasterSecret = randomPreMasterSecret |
| 1573 |
| 1574 #Get and check CertificateVerify, if relevant |
| 1575 if clientCertChain: |
| 1576 if self.version == (3,0): |
| 1577 masterSecret = calcMasterSecret(self.version, premasterSecret, |
| 1578 clientHello.random, serverHello.random) |
| 1579 verifyBytes = self._calcSSLHandshakeHash(masterSecret, b"") |
| 1580 elif self.version in ((3,1), (3,2)): |
| 1581 verifyBytes = self._handshake_md5.digest() + \ |
| 1582 self._handshake_sha.digest() |
1528 for result in self._getMsg(ContentType.handshake, | 1583 for result in self._getMsg(ContentType.handshake, |
1529 HandshakeType.client_key_exchange, | 1584 HandshakeType.certificate_verify): |
1530 cipherSuite): | 1585 if result in (0,1): yield result |
| 1586 else: break |
| 1587 certificateVerify = result |
| 1588 publicKey = clientCertChain.getEndEntityPublicKey() |
| 1589 if len(publicKey) < settings.minKeySize: |
| 1590 for result in self._sendError(\ |
| 1591 AlertDescription.handshake_failure, |
| 1592 "Client's public key too small: %d" % len(publicKey)): |
| 1593 yield result |
| 1594 |
| 1595 if len(publicKey) > settings.maxKeySize: |
| 1596 for result in self._sendError(\ |
| 1597 AlertDescription.handshake_failure, |
| 1598 "Client's public key too large: %d" % len(publicKey)): |
| 1599 yield result |
| 1600 |
| 1601 if not publicKey.verify(certificateVerify.signature, verifyBytes): |
| 1602 for result in self._sendError(\ |
| 1603 AlertDescription.decrypt_error, |
| 1604 "Signature failed to verify"): |
| 1605 yield result |
| 1606 yield (premasterSecret, clientCertChain) |
| 1607 |
| 1608 |
| 1609 def _serverAnonKeyExchange(self, clientHello, serverHello, cipherSuite, |
| 1610 settings): |
| 1611 # Calculate DH p, g, Xs, Ys |
| 1612 dh_p = getRandomSafePrime(32, False) |
| 1613 dh_g = getRandomNumber(2, dh_p) |
| 1614 dh_Xs = bytesToNumber(getRandomBytes(32)) |
| 1615 dh_Ys = powMod(dh_g, dh_Xs, dh_p) |
| 1616 |
| 1617 #Create ServerKeyExchange |
| 1618 serverKeyExchange = ServerKeyExchange(cipherSuite) |
| 1619 serverKeyExchange.createDH(dh_p, dh_g, dh_Ys) |
| 1620 |
| 1621 #Send ServerHello[, Certificate], ServerKeyExchange, |
| 1622 #ServerHelloDone |
| 1623 msgs = [] |
| 1624 msgs.append(serverHello) |
| 1625 msgs.append(serverKeyExchange) |
| 1626 msgs.append(ServerHelloDone()) |
| 1627 for result in self._sendMsgs(msgs): |
| 1628 yield result |
| 1629 |
| 1630 #From here on, the client's messages must have the right version |
| 1631 self._versionCheck = True |
| 1632 |
| 1633 #Get and check ClientKeyExchange |
| 1634 for result in self._getMsg(ContentType.handshake, |
| 1635 HandshakeType.client_key_exchange, |
| 1636 cipherSuite): |
| 1637 if result in (0,1): |
| 1638 yield result |
| 1639 else: |
| 1640 break |
| 1641 clientKeyExchange = result |
| 1642 dh_Yc = clientKeyExchange.dh_Yc |
| 1643 |
| 1644 if dh_Yc % dh_p == 0: |
| 1645 for result in self._sendError(AlertDescription.illegal_parameter, |
| 1646 "Suspicious dh_Yc value"): |
| 1647 yield result |
| 1648 assert(False) # Just to ensure we don't fall through somehow
|
| 1649 |
| 1650 #Calculate premaster secre |
| 1651 S = powMod(dh_Yc,dh_Xs,dh_p) |
| 1652 premasterSecret = numberToByteArray(S) |
| 1653 |
| 1654 yield premasterSecret |
| 1655 |
| 1656 |
| 1657 def _serverFinished(self, premasterSecret, clientRandom, serverRandom, |
| 1658 cipherSuite, cipherImplementations, nextProtos, |
| 1659 doingChannelID): |
| 1660 masterSecret = calcMasterSecret(self.version, premasterSecret, |
| 1661 clientRandom, serverRandom) |
| 1662 |
| 1663 #Calculate pending connection states |
| 1664 self._calcPendingStates(cipherSuite, masterSecret, |
| 1665 clientRandom, serverRandom, |
| 1666 cipherImplementations) |
| 1667 |
| 1668 #Exchange ChangeCipherSpec and Finished messages |
| 1669 for result in self._getFinished(masterSecret, |
| 1670 expect_next_protocol=nextProtos is not None, |
| 1671 expect_channel_id=doingChannelID): |
| 1672 yield result |
| 1673 |
| 1674 for result in self._sendFinished(masterSecret): |
| 1675 yield result |
| 1676 |
| 1677 yield masterSecret |
| 1678 |
| 1679 |
| 1680 #********************************************************* |
| 1681 # Shared Handshake Functions |
| 1682 #********************************************************* |
| 1683 |
| 1684 |
| 1685 def _sendFinished(self, masterSecret, nextProto=None): |
| 1686 #Send ChangeCipherSpec |
| 1687 for result in self._sendMsg(ChangeCipherSpec()): |
| 1688 yield result |
| 1689 |
| 1690 #Switch to pending write state |
| 1691 self._changeWriteState() |
| 1692 |
| 1693 if nextProto is not None: |
| 1694 nextProtoMsg = NextProtocol().create(nextProto) |
| 1695 for result in self._sendMsg(nextProtoMsg): |
| 1696 yield result |
| 1697 |
| 1698 #Calculate verification data |
| 1699 verifyData = self._calcFinished(masterSecret, True) |
| 1700 if self.fault == Fault.badFinished: |
| 1701 verifyData[0] = (verifyData[0]+1)%256 |
| 1702 |
| 1703 #Send Finished message under new state |
| 1704 finished = Finished(self.version).create(verifyData) |
| 1705 for result in self._sendMsg(finished): |
| 1706 yield result |
| 1707 |
| 1708 def _getFinished(self, masterSecret, expect_next_protocol=False, nextProto=N
one, |
| 1709 expect_channel_id=False): |
| 1710 #Get and check ChangeCipherSpec |
| 1711 for result in self._getMsg(ContentType.change_cipher_spec): |
| 1712 if result in (0,1): |
| 1713 yield result |
| 1714 changeCipherSpec = result |
| 1715 |
| 1716 if changeCipherSpec.type != 1: |
| 1717 for result in self._sendError(AlertDescription.illegal_parameter, |
| 1718 "ChangeCipherSpec type incorrect"): |
| 1719 yield result |
| 1720 |
| 1721 #Switch to pending read state |
| 1722 self._changeReadState() |
| 1723 |
| 1724 #Server Finish - Are we waiting for a next protocol echo? |
| 1725 if expect_next_protocol: |
| 1726 for result in self._getMsg(ContentType.handshake, HandshakeType.next
_protocol): |
1531 if result in (0,1): | 1727 if result in (0,1): |
1532 yield result | 1728 yield result |
1533 else: | 1729 if result is None: |
1534 break | 1730 for result in self._sendError(AlertDescription.unexpected_messag
e, |
1535 clientKeyExchange = result | 1731 "Didn't get NextProtocol message"): |
1536 | 1732 yield result |
1537 #Decrypt ClientKeyExchange | 1733 |
1538 premasterSecret = privateKey.decrypt(\ | 1734 self.next_proto = result.next_proto |
1539 clientKeyExchange.encryptedPreMasterSecret) | 1735 else: |
1540 | 1736 self.next_proto = None |
1541 randomPreMasterSecret = getRandomBytes(48) | 1737 |
1542 versionCheck = (premasterSecret[0], premasterSecret[1]) | 1738 #Client Finish - Only set the next_protocol selected in the connection |
1543 if not premasterSecret: | 1739 if nextProto: |
1544 premasterSecret = randomPreMasterSecret | 1740 self.next_proto = nextProto |
1545 elif len(premasterSecret)!=48: | 1741 |
1546 premasterSecret = randomPreMasterSecret | 1742 #Server Finish - Are we waiting for a EncryptedExtensions? |
1547 elif versionCheck != clientHello.client_version: | 1743 if expect_channel_id: |
1548 if versionCheck != self.version: #Tolerate buggy IE clients | 1744 for result in self._getMsg(ContentType.handshake, HandshakeType.encr
ypted_extensions): |
1549 premasterSecret = randomPreMasterSecret | 1745 if result in (0,1): |
1550 | 1746 yield result |
1551 #Get and check CertificateVerify, if relevant | 1747 if result is None: |
1552 if clientCertChain: | 1748 for result in self._sendError(AlertDescription.unexpected_messag
e, |
1553 if self.version == (3,0): | 1749 "Didn't get EncryptedExtensions mes
sage"): |
1554 #Create a temporary session object, just for the purpose | 1750 yield result |
1555 #of checking the CertificateVerify | 1751 encrypted_extensions = result |
1556 session = Session() | 1752 self.channel_id = result.channel_id_key |
1557 session._calcMasterSecret(self.version, premasterSecret, | 1753 else: |
1558 clientRandom, serverRandom) | 1754 self.channel_id = None |
1559 verifyBytes = self._calcSSLHandshakeHash(\ | 1755 |
1560 session.masterSecret, "") | 1756 #Calculate verification data |
1561 elif self.version in ((3,1), (3,2)): | 1757 verifyData = self._calcFinished(masterSecret, False) |
1562 verifyBytes = stringToBytes(self._handshake_md5.digest() +\ | 1758 |
1563 self._handshake_sha.digest()) | 1759 #Get and check Finished message under new state |
1564 for result in self._getMsg(ContentType.handshake, | 1760 for result in self._getMsg(ContentType.handshake, |
1565 HandshakeType.certificate_verify): | 1761 HandshakeType.finished): |
1566 if result in (0,1): | 1762 if result in (0,1): |
1567 yield result | 1763 yield result |
1568 else: | 1764 finished = result |
1569 break | 1765 if finished.verify_data != verifyData: |
1570 certificateVerify = result | 1766 for result in self._sendError(AlertDescription.decrypt_error, |
1571 publicKey = clientCertChain.getEndEntityPublicKey() | 1767 "Finished message is incorrect"): |
1572 if len(publicKey) < settings.minKeySize: | 1768 yield result |
1573 postFinishedError = (AlertDescription.handshake_failure, | 1769 |
1574 "Client's public key too small: %d" % len(publicKey)) | 1770 def _calcFinished(self, masterSecret, send=True): |
1575 if len(publicKey) > settings.maxKeySize: | 1771 if self.version == (3,0): |
1576 postFinishedError = (AlertDescription.handshake_failure, | 1772 if (self._client and send) or (not self._client and not send): |
1577 "Client's public key too large: %d" % len(publicKey)) | 1773 senderStr = b"\x43\x4C\x4E\x54" |
1578 | 1774 else: |
1579 if not publicKey.verify(certificateVerify.signature, | 1775 senderStr = b"\x53\x52\x56\x52" |
1580 verifyBytes): | 1776 |
1581 postFinishedError = (AlertDescription.decrypt_error, | 1777 verifyData = self._calcSSLHandshakeHash(masterSecret, senderStr) |
1582 "Signature failed to verify") | 1778 return verifyData |
1583 | 1779 |
1584 | 1780 elif self.version in ((3,1), (3,2)): |
1585 #Create the session object | 1781 if (self._client and send) or (not self._client and not send): |
1586 self.session = Session() | 1782 label = b"client finished" |
1587 self.session._calcMasterSecret(self.version, premasterSecret, | 1783 else: |
1588 clientRandom, serverRandom) | 1784 label = b"server finished" |
1589 self.session.sessionID = sessionID | 1785 |
1590 self.session.cipherSuite = cipherSuite | 1786 handshakeHashes = self._handshake_md5.digest() + \ |
1591 self.session.srpUsername = self.allegedSrpUsername | 1787 self._handshake_sha.digest() |
1592 self.session.clientCertChain = clientCertChain | 1788 verifyData = PRF(masterSecret, label, handshakeHashes, 12) |
1593 self.session.serverCertChain = serverCertChain | 1789 return verifyData |
1594 | 1790 else: |
1595 #Calculate pending connection states | 1791 raise AssertionError() |
1596 self._calcPendingStates(clientRandom, serverRandom, | |
1597 settings.cipherImplementations) | |
1598 | |
1599 #Exchange ChangeCipherSpec and Finished messages | |
1600 for result in self._getChangeCipherSpec(): | |
1601 yield result | |
1602 if doingChannelID: | |
1603 for result in self._getEncryptedExtensions(): | |
1604 yield result | |
1605 for result in self._getFinished(): | |
1606 yield result | |
1607 | |
1608 #If we were holding a post-finished error until receiving the client | |
1609 #finished message, send it now. We delay the call until this point | |
1610 #because calling sendError() throws an exception, and our caller might | |
1611 #shut down the socket upon receiving the exception. If he did, and the | |
1612 #client was still sending its ChangeCipherSpec or Finished messages, it | |
1613 #would cause a socket error on the client side. This is a lot of | |
1614 #consideration to show to misbehaving clients, but this would also | |
1615 #cause problems with fault-testing. | |
1616 if postFinishedError: | |
1617 for result in self._sendError(*postFinishedError): | |
1618 yield result | |
1619 | |
1620 for result in self._sendFinished(): | |
1621 yield result | |
1622 | |
1623 #Add the session object to the session cache | |
1624 if sessionCache and sessionID: | |
1625 sessionCache[bytesToString(sessionID)] = self.session | |
1626 | |
1627 #Mark the connection as open | |
1628 self.session._setResumable(True) | |
1629 self._handshakeDone(resumed=False) | |
1630 | 1792 |
1631 | 1793 |
1632 def _handshakeWrapperAsync(self, handshaker, checker): | 1794 def _handshakeWrapperAsync(self, handshaker, checker): |
1633 if not self.fault: | 1795 if not self.fault: |
1634 try: | 1796 try: |
1635 for result in handshaker: | 1797 for result in handshaker: |
1636 yield result | 1798 yield result |
1637 if checker: | 1799 if checker: |
1638 try: | 1800 try: |
1639 checker(self) | 1801 checker(self) |
1640 except TLSAuthenticationError: | 1802 except TLSAuthenticationError: |
1641 alert = Alert().create(AlertDescription.close_notify, | 1803 alert = Alert().create(AlertDescription.close_notify, |
1642 AlertLevel.fatal) | 1804 AlertLevel.fatal) |
1643 for result in self._sendMsg(alert): | 1805 for result in self._sendMsg(alert): |
1644 yield result | 1806 yield result |
1645 raise | 1807 raise |
1646 except: | 1808 except GeneratorExit: |
1647 self._shutdown(False) | 1809 raise |
| 1810 except TLSAlert as alert: |
| 1811 if not self.fault: |
1648 raise | 1812 raise |
1649 else: | |
1650 try: | |
1651 for result in handshaker: | |
1652 yield result | |
1653 if checker: | |
1654 try: | |
1655 checker(self) | |
1656 except TLSAuthenticationError: | |
1657 alert = Alert().create(AlertDescription.close_notify, | |
1658 AlertLevel.fatal) | |
1659 for result in self._sendMsg(alert): | |
1660 yield result | |
1661 raise | |
1662 except socket.error, e: | |
1663 raise TLSFaultError("socket error!") | |
1664 except TLSAbruptCloseError, e: | |
1665 raise TLSFaultError("abrupt close error!") | |
1666 except TLSAlert, alert: | |
1667 if alert.description not in Fault.faultAlerts[self.fault]: | 1813 if alert.description not in Fault.faultAlerts[self.fault]: |
1668 raise TLSFaultError(str(alert)) | 1814 raise TLSFaultError(str(alert)) |
1669 else: | 1815 else: |
1670 pass | 1816 pass |
1671 except: | 1817 except: |
1672 self._shutdown(False) | 1818 self._shutdown(False) |
1673 raise | 1819 raise |
1674 else: | |
1675 raise TLSFaultError("No error!") | |
1676 | |
1677 | |
1678 def _getKeyFromChain(self, certificate, settings): | |
1679 #Get and check cert chain from the Certificate message | |
1680 certChain = certificate.certChain | |
1681 if not certChain or certChain.getNumCerts() == 0: | |
1682 for result in self._sendError(AlertDescription.illegal_parameter, | |
1683 "Other party sent a Certificate message without "\ | |
1684 "certificates"): | |
1685 yield result | |
1686 | |
1687 #Get and check public key from the cert chain | |
1688 publicKey = certChain.getEndEntityPublicKey() | |
1689 if len(publicKey) < settings.minKeySize: | |
1690 for result in self._sendError(AlertDescription.handshake_failure, | |
1691 "Other party's public key too small: %d" % len(publicKey)): | |
1692 yield result | |
1693 if len(publicKey) > settings.maxKeySize: | |
1694 for result in self._sendError(AlertDescription.handshake_failure, | |
1695 "Other party's public key too large: %d" % len(publicKey)): | |
1696 yield result | |
1697 | |
1698 yield publicKey, certChain | |
OLD | NEW |