Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(2)

Side by Side Diff: third_party/tlslite/tlslite/tlsconnection.py

Issue 210323002: Update tlslite to 0.4.6. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Executable bit and --similarity=80 Created 6 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
OLDNEW
« no previous file with comments | « third_party/tlslite/tlslite/sharedkeydb.py ('k') | third_party/tlslite/tlslite/tlsrecordlayer.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698