OLD | NEW |
| (Empty) |
1 """ | |
2 MAIN CLASS FOR TLS LITE (START HERE!). | |
3 """ | |
4 from __future__ import generators | |
5 | |
6 import socket | |
7 from utils.compat import formatExceptionTrace | |
8 from TLSRecordLayer import TLSRecordLayer | |
9 from Session import Session | |
10 from constants import * | |
11 from utils.cryptomath import getRandomBytes | |
12 from errors import * | |
13 from messages import * | |
14 from mathtls import * | |
15 from HandshakeSettings import HandshakeSettings | |
16 | |
17 | |
18 class TLSConnection(TLSRecordLayer): | |
19 """ | |
20 This class wraps a socket and provides TLS handshaking and data | |
21 transfer. | |
22 | |
23 To use this class, create a new instance, passing a connected | |
24 socket into the constructor. Then call some handshake function. | |
25 If the handshake completes without raising an exception, then a TLS | |
26 connection has been negotiated. You can transfer data over this | |
27 connection as if it were a socket. | |
28 | |
29 This class provides both synchronous and asynchronous versions of | |
30 its key functions. The synchronous versions should be used when | |
31 writing single-or multi-threaded code using blocking sockets. The | |
32 asynchronous versions should be used when performing asynchronous, | |
33 event-based I/O with non-blocking sockets. | |
34 | |
35 Asynchronous I/O is a complicated subject; typically, you should | |
36 not use the asynchronous functions directly, but should use some | |
37 framework like asyncore or Twisted which TLS Lite integrates with | |
38 (see | |
39 L{tlslite.integration.TLSAsyncDispatcherMixIn.TLSAsyncDispatcherMixIn} or | |
40 L{tlslite.integration.TLSTwistedProtocolWrapper.TLSTwistedProtocolWrapper}). | |
41 """ | |
42 | |
43 | |
44 def __init__(self, sock): | |
45 """Create a new TLSConnection instance. | |
46 | |
47 @param sock: The socket data will be transmitted on. The | |
48 socket should already be connected. It may be in blocking or | |
49 non-blocking mode. | |
50 | |
51 @type sock: L{socket.socket} | |
52 """ | |
53 TLSRecordLayer.__init__(self, sock) | |
54 | |
55 def handshakeClientSRP(self, username, password, session=None, | |
56 settings=None, checker=None, async=False): | |
57 """Perform an SRP handshake in the role of client. | |
58 | |
59 This function performs a TLS/SRP handshake. SRP mutually | |
60 authenticates both parties to each other using only a | |
61 username and password. This function may also perform a | |
62 combined SRP and server-certificate handshake, if the server | |
63 chooses to authenticate itself with a certificate chain in | |
64 addition to doing SRP. | |
65 | |
66 TLS/SRP is non-standard. Most TLS implementations don't | |
67 support it. See | |
68 U{http://www.ietf.org/html.charters/tls-charter.html} or | |
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 | |
73 TLS connection, or on a TLS connection that is already open. | |
74 If called on an open connection it performs a re-handshake. | |
75 | |
76 If the function completes without raising an exception, the | |
77 TLS connection will be open and available for data transfer. | |
78 | |
79 If an exception is raised, the connection will have been | |
80 automatically closed (if it was ever open). | |
81 | |
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} | |
89 @param session: A TLS session to attempt to resume. This | |
90 session must be an SRP session performed with the same username | |
91 and password as were passed in. If the resumption does not | |
92 succeed, a full SRP handshake will be performed. | |
93 | |
94 @type settings: L{tlslite.HandshakeSettings.HandshakeSettings} | |
95 @param settings: Various settings which can be used to control | |
96 the ciphersuites, certificate types, and SSL/TLS versions | |
97 offered by the client. | |
98 | |
99 @type checker: L{tlslite.Checker.Checker} | |
100 @param checker: A Checker instance. This instance will be | |
101 invoked to examine the other party's authentication | |
102 credentials, if the handshake completes succesfully. | |
103 | |
104 @type async: bool | |
105 @param async: If False, this function will block until the | |
106 handshake is completed. If True, this function will return a | |
107 generator. Successive invocations of the generator will | |
108 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 | |
110 the handshake operation is completed. | |
111 | |
112 @rtype: None or an iterable | |
113 @return: If 'async' is True, a generator object will be | |
114 returned. | |
115 | |
116 @raise socket.error: If a socket error occurs. | |
117 @raise tlslite.errors.TLSAbruptCloseError: If the socket is closed | |
118 without a preceding alert. | |
119 @raise tlslite.errors.TLSAlert: If a TLS alert is signalled. | |
120 @raise tlslite.errors.TLSAuthenticationError: If the checker | |
121 doesn't like the other party's authentication credentials. | |
122 """ | |
123 handshaker = self._handshakeClientAsync(srpParams=(username, password), | |
124 session=session, settings=settings, checker=checker) | |
125 if async: | |
126 return handshaker | |
127 for result in handshaker: | |
128 pass | |
129 | |
130 def handshakeClientCert(self, certChain=None, privateKey=None, | |
131 session=None, settings=None, checker=None, | |
132 async=False): | |
133 """Perform a certificate-based handshake in the role of client. | |
134 | |
135 This function performs an SSL or TLS handshake. The server | |
136 will authenticate itself using an X.509 or cryptoID certificate | |
137 chain. If the handshake succeeds, the server's certificate | |
138 chain will be stored in the session's serverCertChain attribute. | |
139 Unless a checker object is passed in, this function does no | |
140 validation or checking of the server's certificate chain. | |
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 | |
153 If the function completes without raising an exception, the | |
154 TLS connection will be open and available for data transfer. | |
155 | |
156 If an exception is raised, the connection will have been | |
157 automatically closed (if it was ever open). | |
158 | |
159 @type certChain: L{tlslite.X509CertChain.X509CertChain} or | |
160 L{cryptoIDlib.CertChain.CertChain} | |
161 @param certChain: The certificate chain to be used if the | |
162 server requests client authentication. | |
163 | |
164 @type privateKey: L{tlslite.utils.RSAKey.RSAKey} | |
165 @param privateKey: The private key to be used if the server | |
166 requests client authentication. | |
167 | |
168 @type session: L{tlslite.Session.Session} | |
169 @param session: A TLS session to attempt to resume. If the | |
170 resumption does not succeed, a full handshake will be | |
171 performed. | |
172 | |
173 @type settings: L{tlslite.HandshakeSettings.HandshakeSettings} | |
174 @param settings: Various settings which can be used to control | |
175 the ciphersuites, certificate types, and SSL/TLS versions | |
176 offered by the client. | |
177 | |
178 @type checker: L{tlslite.Checker.Checker} | |
179 @param checker: A Checker instance. This instance will be | |
180 invoked to examine the other party's authentication | |
181 credentials, if the handshake completes succesfully. | |
182 | |
183 @type async: bool | |
184 @param async: If False, this function will block until the | |
185 handshake is completed. If True, this function will return a | |
186 generator. Successive invocations of the generator will | |
187 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 | |
189 the handshake operation is completed. | |
190 | |
191 @rtype: None or an iterable | |
192 @return: If 'async' is True, a generator object will be | |
193 returned. | |
194 | |
195 @raise socket.error: If a socket error occurs. | |
196 @raise tlslite.errors.TLSAbruptCloseError: If the socket is closed | |
197 without a preceding alert. | |
198 @raise tlslite.errors.TLSAlert: If a TLS alert is signalled. | |
199 @raise tlslite.errors.TLSAuthenticationError: If the checker | |
200 doesn't like the other party's authentication credentials. | |
201 """ | |
202 handshaker = self._handshakeClientAsync(certParams=(certChain, | |
203 privateKey), session=session, settings=settings, | |
204 checker=checker) | |
205 if async: | |
206 return handshaker | |
207 for result in handshaker: | |
208 pass | |
209 | |
210 def handshakeClientUnknown(self, srpCallback=None, certCallback=None, | |
211 session=None, settings=None, checker=None, | |
212 async=False): | |
213 """Perform a to-be-determined type of handshake in the role of client. | |
214 | |
215 This function performs an SSL or TLS handshake. If the server | |
216 requests client certificate authentication, the | |
217 certCallback will be invoked and should return a (certChain, | |
218 privateKey) pair. If the callback returns None, the library | |
219 will attempt to proceed without client authentication. The | |
220 server may or may not allow this. | |
221 | |
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 | |
236 TLS connection will be open and available for data transfer. | |
237 | |
238 If an exception is raised, the connection will have been | |
239 automatically closed (if it was ever open). | |
240 | |
241 @type srpCallback: callable | |
242 @param srpCallback: The callback to be used if the server | |
243 requests SRP authentication. If None, the client will not | |
244 offer support for SRP ciphersuites. | |
245 | |
246 @type certCallback: callable | |
247 @param certCallback: The callback to be used if the server | |
248 requests client certificate authentication. | |
249 | |
250 @type session: L{tlslite.Session.Session} | |
251 @param session: A TLS session to attempt to resume. If the | |
252 resumption does not succeed, a full handshake will be | |
253 performed. | |
254 | |
255 @type settings: L{tlslite.HandshakeSettings.HandshakeSettings} | |
256 @param settings: Various settings which can be used to control | |
257 the ciphersuites, certificate types, and SSL/TLS versions | |
258 offered by the client. | |
259 | |
260 @type checker: L{tlslite.Checker.Checker} | |
261 @param checker: A Checker instance. This instance will be | |
262 invoked to examine the other party's authentication | |
263 credentials, if the handshake completes succesfully. | |
264 | |
265 @type async: bool | |
266 @param async: If False, this function will block until the | |
267 handshake is completed. If True, this function will return a | |
268 generator. Successive invocations of the generator will | |
269 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 | |
271 the handshake operation is completed. | |
272 | |
273 @rtype: None or an iterable | |
274 @return: If 'async' is True, a generator object will be | |
275 returned. | |
276 | |
277 @raise socket.error: If a socket error occurs. | |
278 @raise tlslite.errors.TLSAbruptCloseError: If the socket is closed | |
279 without a preceding alert. | |
280 @raise tlslite.errors.TLSAlert: If a TLS alert is signalled. | |
281 @raise tlslite.errors.TLSAuthenticationError: If the checker | |
282 doesn't like the other party's authentication credentials. | |
283 """ | |
284 handshaker = self._handshakeClientAsync(unknownParams=(srpCallback, | |
285 certCallback), session=session, settings=settings, | |
286 checker=checker) | |
287 if async: | |
288 return handshaker | |
289 for result in handshaker: | |
290 pass | |
291 | |
292 def handshakeClientSharedKey(self, username, sharedKey, settings=None, | |
293 checker=None, async=False): | |
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, | |
363 recursive=False): | |
364 | |
365 handshaker = self._handshakeClientAsyncHelper(srpParams=srpParams, | |
366 certParams=certParams, unknownParams=unknownParams, | |
367 sharedKeyParams=sharedKeyParams, session=session, | |
368 settings=settings, recursive=recursive) | |
369 for result in self._handshakeWrapperAsync(handshaker, checker): | |
370 yield result | |
371 | |
372 | |
373 def _handshakeClientAsyncHelper(self, srpParams, certParams, unknownParams, | |
374 sharedKeyParams, session, settings, recursive): | |
375 if not recursive: | |
376 self._handshakeStart(client=True) | |
377 | |
378 #Unpack parameters | |
379 srpUsername = None # srpParams | |
380 password = None # srpParams | |
381 clientCertChain = None # certParams | |
382 privateKey = None # certParams | |
383 srpCallback = None # unknownParams | |
384 certCallback = None # unknownParams | |
385 #session # sharedKeyParams (or session) | |
386 #settings # settings | |
387 | |
388 if srpParams: | |
389 srpUsername, password = srpParams | |
390 elif certParams: | |
391 clientCertChain, privateKey = certParams | |
392 elif unknownParams: | |
393 srpCallback, certCallback = unknownParams | |
394 elif sharedKeyParams: | |
395 session = Session()._createSharedKey(*sharedKeyParams) | |
396 | |
397 if not settings: | |
398 settings = HandshakeSettings() | |
399 settings = settings._filter() | |
400 | |
401 #Validate parameters | |
402 if srpUsername and not password: | |
403 raise ValueError("Caller passed a username but no password") | |
404 if password and not srpUsername: | |
405 raise ValueError("Caller passed a password but no username") | |
406 | |
407 if clientCertChain and not privateKey: | |
408 raise ValueError("Caller passed a certChain but no privateKey") | |
409 if privateKey and not clientCertChain: | |
410 raise ValueError("Caller passed a privateKey but no certChain") | |
411 | |
412 if clientCertChain: | |
413 foundType = False | |
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") | |
433 | |
434 | |
435 if session: | |
436 if not session.valid(): | |
437 session = None #ignore non-resumable sessions... | |
438 elif session.resumable and \ | |
439 (session.srpUsername != srpUsername): | |
440 raise ValueError("Session username doesn't match") | |
441 | |
442 #Add Faults to parameters | |
443 if srpUsername and self.fault == Fault.badUsername: | |
444 srpUsername += "GARBAGE" | |
445 if password and self.fault == Fault.badPassword: | |
446 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 | |
489 #Tentatively set the version to the client's minimum version. | |
490 #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 | |
492 self.version = settings.maxVersion | |
493 | |
494 #Either send ClientHello (with a resumable session)... | |
495 if session: | |
496 #If it's a resumable (i.e. not a shared-key session), then its | |
497 #ciphersuite must be one of the acceptable ciphersuites | |
498 if (not sharedKeyParams) and \ | |
499 session.cipherSuite not in cipherSuites: | |
500 raise ValueError("Session's cipher suite not consistent "\ | |
501 "with parameters") | |
502 else: | |
503 clientHello = ClientHello() | |
504 clientHello.create(settings.maxVersion, clientRandom, | |
505 session.sessionID, cipherSuites, | |
506 certificateTypes, session.srpUsername) | |
507 | |
508 #Or send ClientHello (without) | |
509 else: | |
510 clientHello = ClientHello() | |
511 clientHello.create(settings.maxVersion, clientRandom, | |
512 createByteArraySequence([]), cipherSuites, | |
513 certificateTypes, srpUsername) | |
514 for result in self._sendMsg(clientHello): | |
515 yield result | |
516 | |
517 #Get ServerHello (or missing_srp_username) | |
518 for result in self._getMsg((ContentType.handshake, | |
519 ContentType.alert), | |
520 HandshakeType.server_hello): | |
521 if result in (0,1): | |
522 yield result | |
523 else: | |
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 | |
555 #Get the server version. Do this before anything else, so any | |
556 #error alerts will use the server's version | |
557 self.version = serverHello.server_version | |
558 | |
559 #Future responses from server must use this version | |
560 self._versionCheck = True | |
561 | |
562 #Check ServerHello | |
563 if serverHello.server_version < settings.minVersion: | |
564 for result in self._sendError(\ | |
565 AlertDescription.protocol_version, | |
566 "Too old version: %s" % str(serverHello.server_version)): | |
567 yield result | |
568 if serverHello.server_version > settings.maxVersion: | |
569 for result in self._sendError(\ | |
570 AlertDescription.protocol_version, | |
571 "Too new version: %s" % str(serverHello.server_version)): | |
572 yield result | |
573 if serverHello.cipher_suite not in cipherSuites: | |
574 for result in self._sendError(\ | |
575 AlertDescription.illegal_parameter, | |
576 "Server responded with incorrect ciphersuite"): | |
577 yield result | |
578 if serverHello.certificate_type not in certificateTypes: | |
579 for result in self._sendError(\ | |
580 AlertDescription.illegal_parameter, | |
581 "Server responded with incorrect certificate type"): | |
582 yield result | |
583 if serverHello.compression_method != 0: | |
584 for result in self._sendError(\ | |
585 AlertDescription.illegal_parameter, | |
586 "Server responded with incorrect compression method"): | |
587 yield result | |
588 | |
589 #Get the server nonce | |
590 serverRandom = serverHello.random | |
591 | |
592 #If the server agrees to resume | |
593 if session and session.sessionID and \ | |
594 serverHello.session_id == session.sessionID: | |
595 | |
596 #If a shared-key, we're flexible about suites; otherwise the | |
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(\ | |
602 AlertDescription.illegal_parameter,\ | |
603 "Server's ciphersuite doesn't match session"): | |
604 yield result | |
605 | |
606 #Set the session for this connection | |
607 self.session = session | |
608 | |
609 #Calculate pending connection states | |
610 self._calcPendingStates(clientRandom, serverRandom, | |
611 settings.cipherImplementations) | |
612 | |
613 #Exchange ChangeCipherSpec and Finished messages | |
614 for result in self._getChangeCipherSpec(): | |
615 yield result | |
616 for result in self._getFinished(): | |
617 yield result | |
618 for result in self._sendFinished(): | |
619 yield result | |
620 | |
621 #Mark the connection as open | |
622 self._handshakeDone(resumed=True) | |
623 | |
624 #If server DOES NOT agree to resume | |
625 else: | |
626 | |
627 if sharedKeyParams: | |
628 for result in self._sendError(\ | |
629 AlertDescription.user_canceled, | |
630 "Was expecting a shared-key resumption"): | |
631 yield result | |
632 | |
633 #We've already validated these | |
634 cipherSuite = serverHello.cipher_suite | |
635 certificateType = serverHello.certificate_type | |
636 | |
637 #If the server chose an SRP suite... | |
638 if cipherSuite in CipherSuite.srpSuites: | |
639 #Get ServerKeyExchange, ServerHelloDone | |
640 for result in self._getMsg(ContentType.handshake, | |
641 HandshakeType.server_key_exchange, cipherSuite): | |
642 if result in (0,1): | |
643 yield result | |
644 else: | |
645 break | |
646 serverKeyExchange = result | |
647 | |
648 for result in self._getMsg(ContentType.handshake, | |
649 HandshakeType.server_hello_done): | |
650 if result in (0,1): | |
651 yield result | |
652 else: | |
653 break | |
654 serverHelloDone = result | |
655 | |
656 #If the server chose an SRP+RSA suite... | |
657 elif cipherSuite in CipherSuite.srpRsaSuites: | |
658 #Get Certificate, ServerKeyExchange, ServerHelloDone | |
659 for result in self._getMsg(ContentType.handshake, | |
660 HandshakeType.certificate, certificateType): | |
661 if result in (0,1): | |
662 yield result | |
663 else: | |
664 break | |
665 serverCertificate = result | |
666 | |
667 for result in self._getMsg(ContentType.handshake, | |
668 HandshakeType.server_key_exchange, cipherSuite): | |
669 if result in (0,1): | |
670 yield result | |
671 else: | |
672 break | |
673 serverKeyExchange = result | |
674 | |
675 for result in self._getMsg(ContentType.handshake, | |
676 HandshakeType.server_hello_done): | |
677 if result in (0,1): | |
678 yield result | |
679 else: | |
680 break | |
681 serverHelloDone = result | |
682 | |
683 #If the server chose an RSA suite... | |
684 elif cipherSuite in CipherSuite.rsaSuites: | |
685 #Get Certificate[, CertificateRequest], ServerHelloDone | |
686 for result in self._getMsg(ContentType.handshake, | |
687 HandshakeType.certificate, certificateType): | |
688 if result in (0,1): | |
689 yield result | |
690 else: | |
691 break | |
692 serverCertificate = result | |
693 | |
694 for result in self._getMsg(ContentType.handshake, | |
695 (HandshakeType.server_hello_done, | |
696 HandshakeType.certificate_request)): | |
697 if result in (0,1): | |
698 yield result | |
699 else: | |
700 break | |
701 msg = result | |
702 | |
703 certificateRequest = None | |
704 if isinstance(msg, CertificateRequest): | |
705 certificateRequest = msg | |
706 for result in self._getMsg(ContentType.handshake, | |
707 HandshakeType.server_hello_done): | |
708 if result in (0,1): | |
709 yield result | |
710 else: | |
711 break | |
712 serverHelloDone = result | |
713 elif isinstance(msg, ServerHelloDone): | |
714 serverHelloDone = msg | |
715 else: | |
716 raise AssertionError() | |
717 | |
718 | |
719 #Calculate SRP premaster secret, if server chose an SRP or | |
720 #SRP+RSA suite | |
721 if cipherSuite in CipherSuite.srpSuites + \ | |
722 CipherSuite.srpRsaSuites: | |
723 #Get and check the server's group parameters and B value | |
724 N = serverKeyExchange.srp_N | |
725 g = serverKeyExchange.srp_g | |
726 s = serverKeyExchange.srp_s | |
727 B = serverKeyExchange.srp_B | |
728 | |
729 if (g,N) not in goodGroupParameters: | |
730 for result in self._sendError(\ | |
731 AlertDescription.untrusted_srp_parameters, | |
732 "Unknown group parameters"): | |
733 yield result | |
734 if numBits(N) < settings.minKeySize: | |
735 for result in self._sendError(\ | |
736 AlertDescription.untrusted_srp_parameters, | |
737 "N value is too small: %d" % numBits(N)): | |
738 yield result | |
739 if numBits(N) > settings.maxKeySize: | |
740 for result in self._sendError(\ | |
741 AlertDescription.untrusted_srp_parameters, | |
742 "N value is too large: %d" % numBits(N)): | |
743 yield result | |
744 if B % N == 0: | |
745 for result in self._sendError(\ | |
746 AlertDescription.illegal_parameter, | |
747 "Suspicious B value"): | |
748 yield result | |
749 | |
750 #Check the server's signature, if server chose an | |
751 #SRP+RSA suite | |
752 if cipherSuite in CipherSuite.srpRsaSuites: | |
753 #Hash ServerKeyExchange/ServerSRPParams | |
754 hashBytes = serverKeyExchange.hash(clientRandom, | |
755 serverRandom) | |
756 | |
757 #Extract signature bytes from ServerKeyExchange | |
758 sigBytes = serverKeyExchange.signature | |
759 if len(sigBytes) == 0: | |
760 for result in self._sendError(\ | |
761 AlertDescription.illegal_parameter, | |
762 "Server sent an SRP ServerKeyExchange "\ | |
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 | |
863 | |
864 clientCertificate.create(clientCertChain) | |
865 | |
866 for result in self._sendMsg(clientCertificate): | |
867 yield result | |
868 else: | |
869 #The server didn't request client auth, so we | |
870 #zeroize these so the clientCertChain won't be | |
871 #stored in the session. | |
872 privateKey = 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, | |
938 sessionCache=None, settings=None, checker=None, | |
939 reqCAs=None, tlsIntolerant=0, | |
940 signedCertTimestamps=None, fallbackSCSV=False, | |
941 ocspResponse=None): | |
942 """Perform a handshake in the role of server. | |
943 | |
944 This function performs an SSL or TLS handshake. Depending on | |
945 the arguments and the behavior of the client, this function can | |
946 perform a shared-key, SRP, or certificate-based handshake. It | |
947 can also perform a combined SRP and server-certificate | |
948 handshake. | |
949 | |
950 Like any handshake function, this can be called on a closed | |
951 TLS connection, or on a TLS connection that is already open. | |
952 If called on an open connection it performs a re-handshake. | |
953 This function does not send a Hello Request message before | |
954 performing the handshake, so if re-handshaking is required, | |
955 the server must signal the client to begin the re-handshake | |
956 through some other means. | |
957 | |
958 If the function completes without raising an exception, the | |
959 TLS connection will be open and available for data transfer. | |
960 | |
961 If an exception is raised, the connection will have been | |
962 automatically closed (if it was ever open). | |
963 | |
964 @type sharedKeyDB: L{tlslite.SharedKeyDB.SharedKeyDB} | |
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 | |
972 associated with usernames. If the client performs an SRP | |
973 handshake, the session's srpUsername attribute will be set. | |
974 | |
975 @type certChain: L{tlslite.X509CertChain.X509CertChain} or | |
976 L{cryptoIDlib.CertChain.CertChain} | |
977 @param certChain: The certificate chain to be used if the | |
978 client requests server certificate authentication. | |
979 | |
980 @type privateKey: L{tlslite.utils.RSAKey.RSAKey} | |
981 @param privateKey: The private key to be used if the client | |
982 requests server certificate authentication. | |
983 | |
984 @type reqCert: bool | |
985 @param reqCert: Whether to request client certificate | |
986 authentication. This only applies if the client chooses server | |
987 certificate authentication; if the client chooses SRP or | |
988 shared-key authentication, this will be ignored. If the client | |
989 performs a client certificate authentication, the sessions's | |
990 clientCertChain attribute will be set. | |
991 | |
992 @type sessionCache: L{tlslite.SessionCache.SessionCache} | |
993 @param sessionCache: An in-memory cache of resumable sessions. | |
994 The client can resume sessions from this cache. Alternatively, | |
995 if the client performs a full handshake, a new session will be | |
996 added to the cache. | |
997 | |
998 @type settings: L{tlslite.HandshakeSettings.HandshakeSettings} | |
999 @param settings: Various settings which can be used to control | |
1000 the ciphersuites and SSL/TLS version chosen by the server. | |
1001 | |
1002 @type checker: L{tlslite.Checker.Checker} | |
1003 @param checker: A Checker instance. This instance will be | |
1004 invoked to examine the other party's authentication | |
1005 credentials, if the handshake completes succesfully. | |
1006 | |
1007 @type reqCAs: list of L{array.array} of unsigned bytes | |
1008 @param reqCAs: A collection of DER-encoded DistinguishedNames that | |
1009 will be sent along with a certificate request. This does not affect | |
1010 verification. | |
1011 | |
1012 @type signedCertTimestamps: str | |
1013 @param signedCertTimestamps: A SignedCertificateTimestampList (as a | |
1014 binary 8-bit string) that will be sent as a TLS extension whenever | |
1015 the client announces support for the extension. | |
1016 | |
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 | |
1026 @param fallbackSCSV: if true, the server will implement | |
1027 TLS_FALLBACK_SCSV and thus reject connections using less than the | |
1028 server's maximum TLS version that include this cipher suite. | |
1029 | |
1030 @type ocspResponse: str | |
1031 @param ocspResponse: An OCSP response (as a binary 8-bit string) that | |
1032 will be sent stapled in the handshake whenever the client announces | |
1033 support for the status_request extension. | |
1034 Note that the response is sent independent of the ClientHello | |
1035 status_request extension contents, and is thus only meant for testing | |
1036 environments. Real OCSP stapling is more complicated as it requires | |
1037 choosing a suitable response based on the ClientHello status_request | |
1038 extension contents. | |
1039 | |
1040 @raise socket.error: If a socket error occurs. | |
1041 @raise tlslite.errors.TLSAbruptCloseError: If the socket is closed | |
1042 without a preceding alert. | |
1043 @raise tlslite.errors.TLSAlert: If a TLS alert is signalled. | |
1044 @raise tlslite.errors.TLSAuthenticationError: If the checker | |
1045 doesn't like the other party's authentication credentials. | |
1046 """ | |
1047 for result in self.handshakeServerAsync(sharedKeyDB, verifierDB, | |
1048 certChain, privateKey, reqCert, sessionCache, settings, | |
1049 checker, reqCAs, tlsIntolerant, signedCertTimestamps, | |
1050 fallbackSCSV, ocspResponse): | |
1051 pass | |
1052 | |
1053 | |
1054 def handshakeServerAsync(self, sharedKeyDB=None, verifierDB=None, | |
1055 certChain=None, privateKey=None, reqCert=False, | |
1056 sessionCache=None, settings=None, checker=None, | |
1057 reqCAs=None, tlsIntolerant=0, | |
1058 signedCertTimestamps=None, | |
1059 fallbackSCSV=False, ocspResponse=None): | |
1060 """Start a server handshake operation on the TLS connection. | |
1061 | |
1062 This function returns a generator which behaves similarly to | |
1063 handshakeServer(). Successive invocations of the generator | |
1064 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 | |
1066 if the handshake operation is complete. | |
1067 | |
1068 @rtype: iterable | |
1069 @return: A generator; see above for details. | |
1070 """ | |
1071 handshaker = self._handshakeServerAsyncHelper(\ | |
1072 sharedKeyDB=sharedKeyDB, | |
1073 verifierDB=verifierDB, certChain=certChain, | |
1074 privateKey=privateKey, reqCert=reqCert, | |
1075 sessionCache=sessionCache, settings=settings, | |
1076 reqCAs=reqCAs, | |
1077 tlsIntolerant=tlsIntolerant, | |
1078 signedCertTimestamps=signedCertTimestamps, | |
1079 fallbackSCSV=fallbackSCSV, ocspResponse=ocspResponse) | |
1080 | |
1081 for result in self._handshakeWrapperAsync(handshaker, checker): | |
1082 yield result | |
1083 | |
1084 | |
1085 def _handshakeServerAsyncHelper(self, sharedKeyDB, verifierDB, | |
1086 certChain, privateKey, reqCert, | |
1087 sessionCache, settings, reqCAs, | |
1088 tlsIntolerant, signedCertTimestamps, | |
1089 fallbackSCSV, ocspResponse): | |
1090 | |
1091 self._handshakeStart(client=False) | |
1092 | |
1093 if (not sharedKeyDB) and (not verifierDB) and (not certChain): | |
1094 raise ValueError("Caller passed no authentication credentials") | |
1095 if certChain and not privateKey: | |
1096 raise ValueError("Caller passed a certChain but no privateKey") | |
1097 if privateKey and not certChain: | |
1098 raise ValueError("Caller passed a privateKey but no certChain") | |
1099 if reqCAs and not reqCert: | |
1100 raise ValueError("Caller passed reqCAs but not reqCert") | |
1101 if signedCertTimestamps and not certChain: | |
1102 raise ValueError("Caller passed signedCertTimestamps but no " | |
1103 "certChain") | |
1104 | |
1105 if not settings: | |
1106 settings = HandshakeSettings() | |
1107 settings = settings._filter() | |
1108 | |
1109 #Initialize acceptable cipher suites | |
1110 cipherSuites = [] | |
1111 if verifierDB: | |
1112 if certChain: | |
1113 cipherSuites += \ | |
1114 CipherSuite.getSrpRsaSuites(settings.cipherNames) | |
1115 cipherSuites += CipherSuite.getSrpSuites(settings.cipherNames) | |
1116 if sharedKeyDB or certChain: | |
1117 cipherSuites += CipherSuite.getRsaSuites(settings.cipherNames) | |
1118 | |
1119 #Initialize acceptable certificate type | |
1120 certificateType = None | |
1121 if certChain: | |
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 | |
1139 #Tentatively set version to most-desirable version, so if an error | |
1140 #occurs parsing the ClientHello, this is what we'll use for the | |
1141 #error alert | |
1142 self.version = settings.maxVersion | |
1143 | |
1144 #Get ClientHello | |
1145 for result in self._getMsg(ContentType.handshake, | |
1146 HandshakeType.client_hello): | |
1147 if result in (0,1): | |
1148 yield result | |
1149 else: | |
1150 break | |
1151 clientHello = result | |
1152 | |
1153 #If client's version is too low, reject it | |
1154 if clientHello.client_version < settings.minVersion: | |
1155 self.version = settings.minVersion | |
1156 for result in self._sendError(\ | |
1157 AlertDescription.protocol_version, | |
1158 "Too old version: %s" % str(clientHello.client_version)): | |
1159 yield result | |
1160 | |
1161 #If tlsIntolerant is nonzero, reject certain TLS versions. | |
1162 #1: reject all TLS versions. | |
1163 #2: reject TLS 1.1 or higher. | |
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(\ | |
1169 AlertDescription.handshake_failure): | |
1170 yield result | |
1171 | |
1172 #If client's version is too high, propose my highest version | |
1173 if clientHello.client_version > settings.maxVersion: | |
1174 self.version = settings.maxVersion | |
1175 else: | |
1176 #Set the version to the client's version | |
1177 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 | |
1186 #Get the client nonce; create server nonce | |
1187 clientRandom = clientHello.random | |
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 | |
1209 | |
1210 #Check in the sharedKeys container | |
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: | |
1229 try: | |
1230 session = sessionCache[bytesToString(\ | |
1231 clientHello.session_id)] | |
1232 if session.sharedKey: | |
1233 raise AssertionError() | |
1234 if not session.resumable: | |
1235 raise AssertionError() | |
1236 #Check for consistency with ClientHello | |
1237 if session.cipherSuite not in cipherSuites: | |
1238 for result in self._sendError(\ | |
1239 AlertDescription.handshake_failure): | |
1240 yield result | |
1241 if session.cipherSuite not in clientHello.cipher_suites: | |
1242 for result in self._sendError(\ | |
1243 AlertDescription.handshake_failure): | |
1244 yield result | |
1245 if clientHello.srp_username: | |
1246 if clientHello.srp_username != session.srpUsername: | |
1247 for result in self._sendError(\ | |
1248 AlertDescription.handshake_failure): | |
1249 yield result | |
1250 except KeyError: | |
1251 pass | |
1252 | |
1253 #If a session is found.. | |
1254 if session: | |
1255 #Set the session | |
1256 self.session = session | |
1257 | |
1258 #Send ServerHello | |
1259 serverHello = ServerHello() | |
1260 serverHello.create(self.version, serverRandom, | |
1261 session.sessionID, session.cipherSuite, | |
1262 certificateType) | |
1263 serverHello.channel_id = clientHello.channel_id | |
1264 doingChannelID = clientHello.channel_id | |
1265 for result in self._sendMsg(serverHello): | |
1266 yield result | |
1267 | |
1268 #From here on, the client's messages must have the right version | |
1269 self._versionCheck = True | |
1270 | |
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(\ | |
1300 AlertDescription.handshake_failure): | |
1301 yield result | |
1302 | |
1303 #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 | |
1305 # client is using a shared-key session, it's okay) | |
1306 if cipherSuite in CipherSuite.rsaSuites + \ | |
1307 CipherSuite.srpRsaSuites: | |
1308 if certificateType not in clientHello.certificate_types: | |
1309 for result in self._sendError(\ | |
1310 AlertDescription.handshake_failure, | |
1311 "the client doesn't support my certificate type"): | |
1312 yield result | |
1313 | |
1314 #Move certChain -> serverCertChain, now that we're using it | |
1315 serverCertChain = certChain | |
1316 | |
1317 | |
1318 #Create sessionID | |
1319 if sessionCache: | |
1320 sessionID = getRandomBytes(32) | |
1321 else: | |
1322 sessionID = createByteArraySequence([]) | |
1323 | |
1324 #If we've selected an SRP suite, exchange keys and calculate | |
1325 #premaster secret: | |
1326 if cipherSuite in CipherSuite.srpSuites + CipherSuite.srpRsaSuites: | |
1327 | |
1328 #If there's no SRP username... | |
1329 if not clientHello.srp_username: | |
1330 | |
1331 #Ask the client to re-send ClientHello with one | |
1332 for result in self._sendMsg(Alert().create(\ | |
1333 AlertDescription.missing_srp_username, | |
1334 AlertLevel.warning)): | |
1335 yield result | |
1336 | |
1337 #Get ClientHello | |
1338 for result in self._getMsg(ContentType.handshake, | |
1339 HandshakeType.client_hello): | |
1340 if result in (0,1): | |
1341 yield result | |
1342 else: | |
1343 break | |
1344 clientHello = result | |
1345 | |
1346 #Check ClientHello | |
1347 #If client's version is too low, reject it (COPIED CODE; BAD!) | |
1348 if clientHello.client_version < settings.minVersion: | |
1349 self.version = settings.minVersion | |
1350 for result in self._sendError(\ | |
1351 AlertDescription.protocol_version, | |
1352 "Too old version: %s" % str(clientHello.client_version
)): | |
1353 yield result | |
1354 | |
1355 #If client's version is too high, propose my highest version | |
1356 elif clientHello.client_version > settings.maxVersion: | |
1357 self.version = settings.maxVersion | |
1358 | |
1359 else: | |
1360 #Set the version to the client's version | |
1361 self.version = clientHello.client_version | |
1362 | |
1363 #Recalculate the privileged cipher suite, making sure to | |
1364 #pick an SRP suite | |
1365 cipherSuites = [c for c in cipherSuites if c in \ | |
1366 CipherSuite.srpSuites + \ | |
1367 CipherSuite.srpRsaSuites] | |
1368 for cipherSuite in cipherSuites: | |
1369 if cipherSuite in clientHello.cipher_suites: | |
1370 break | |
1371 else: | |
1372 for result in self._sendError(\ | |
1373 AlertDescription.handshake_failure): | |
1374 yield result | |
1375 | |
1376 #Get the client nonce; create server nonce | |
1377 clientRandom = clientHello.random | |
1378 serverRandom = getRandomBytes(32) | |
1379 | |
1380 #The username better be there, this time | |
1381 if not clientHello.srp_username: | |
1382 for result in self._sendError(\ | |
1383 AlertDescription.illegal_parameter, | |
1384 "Client resent a hello, but without the SRP"\ | |
1385 " username"): | |
1386 yield result | |
1387 | |
1388 | |
1389 #Get username | |
1390 self.allegedSrpUsername = clientHello.srp_username | |
1391 | |
1392 #Get parameters from username | |
1393 try: | |
1394 entry = verifierDB[self.allegedSrpUsername] | |
1395 except KeyError: | |
1396 for result in self._sendError(\ | |
1397 AlertDescription.unknown_srp_username): | |
1398 yield result | |
1399 (N, g, s, v) = entry | |
1400 | |
1401 #Calculate server's ephemeral DH values (b, B) | |
1402 b = bytesToNumber(getRandomBytes(32)) | |
1403 k = makeK(N, g) | |
1404 B = (powMod(g, b, N) + (k*v)) % N | |
1405 | |
1406 #Create ServerKeyExchange, signing it if necessary | |
1407 serverKeyExchange = ServerKeyExchange(cipherSuite) | |
1408 serverKeyExchange.createSRP(N, g, stringToBytes(s), B) | |
1409 if cipherSuite in CipherSuite.srpRsaSuites: | |
1410 hashBytes = serverKeyExchange.hash(clientRandom, | |
1411 serverRandom) | |
1412 serverKeyExchange.signature = privateKey.sign(hashBytes) | |
1413 | |
1414 #Send ServerHello[, Certificate], ServerKeyExchange, | |
1415 #ServerHelloDone | |
1416 msgs = [] | |
1417 serverHello = ServerHello() | |
1418 serverHello.create(self.version, serverRandom, sessionID, | |
1419 cipherSuite, certificateType) | |
1420 msgs.append(serverHello) | |
1421 if cipherSuite in CipherSuite.srpRsaSuites: | |
1422 certificateMsg = Certificate(certificateType) | |
1423 certificateMsg.create(serverCertChain) | |
1424 msgs.append(certificateMsg) | |
1425 msgs.append(serverKeyExchange) | |
1426 msgs.append(ServerHelloDone()) | |
1427 for result in self._sendMsgs(msgs): | |
1428 yield result | |
1429 | |
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 \ | |
1522 clientCertificate.certChain.getNumCerts()!=0: | |
1523 clientCertChain = clientCertificate.certChain | |
1524 else: | |
1525 raise AssertionError() | |
1526 | |
1527 #Get ClientKeyExchange | |
1528 for result in self._getMsg(ContentType.handshake, | |
1529 HandshakeType.client_key_exchange, | |
1530 cipherSuite): | |
1531 if result in (0,1): | |
1532 yield result | |
1533 else: | |
1534 break | |
1535 clientKeyExchange = result | |
1536 | |
1537 #Decrypt ClientKeyExchange | |
1538 premasterSecret = privateKey.decrypt(\ | |
1539 clientKeyExchange.encryptedPreMasterSecret) | |
1540 | |
1541 randomPreMasterSecret = getRandomBytes(48) | |
1542 versionCheck = (premasterSecret[0], premasterSecret[1]) | |
1543 if not premasterSecret: | |
1544 premasterSecret = randomPreMasterSecret | |
1545 elif len(premasterSecret)!=48: | |
1546 premasterSecret = randomPreMasterSecret | |
1547 elif versionCheck != clientHello.client_version: | |
1548 if versionCheck != self.version: #Tolerate buggy IE clients | |
1549 premasterSecret = randomPreMasterSecret | |
1550 | |
1551 #Get and check CertificateVerify, if relevant | |
1552 if clientCertChain: | |
1553 if self.version == (3,0): | |
1554 #Create a temporary session object, just for the purpose | |
1555 #of checking the CertificateVerify | |
1556 session = Session() | |
1557 session._calcMasterSecret(self.version, premasterSecret, | |
1558 clientRandom, serverRandom) | |
1559 verifyBytes = self._calcSSLHandshakeHash(\ | |
1560 session.masterSecret, "") | |
1561 elif self.version in ((3,1), (3,2)): | |
1562 verifyBytes = stringToBytes(self._handshake_md5.digest() +\ | |
1563 self._handshake_sha.digest()) | |
1564 for result in self._getMsg(ContentType.handshake, | |
1565 HandshakeType.certificate_verify): | |
1566 if result in (0,1): | |
1567 yield result | |
1568 else: | |
1569 break | |
1570 certificateVerify = result | |
1571 publicKey = clientCertChain.getEndEntityPublicKey() | |
1572 if len(publicKey) < settings.minKeySize: | |
1573 postFinishedError = (AlertDescription.handshake_failure, | |
1574 "Client's public key too small: %d" % len(publicKey)) | |
1575 if len(publicKey) > settings.maxKeySize: | |
1576 postFinishedError = (AlertDescription.handshake_failure, | |
1577 "Client's public key too large: %d" % len(publicKey)) | |
1578 | |
1579 if not publicKey.verify(certificateVerify.signature, | |
1580 verifyBytes): | |
1581 postFinishedError = (AlertDescription.decrypt_error, | |
1582 "Signature failed to verify") | |
1583 | |
1584 | |
1585 #Create the session object | |
1586 self.session = Session() | |
1587 self.session._calcMasterSecret(self.version, premasterSecret, | |
1588 clientRandom, serverRandom) | |
1589 self.session.sessionID = sessionID | |
1590 self.session.cipherSuite = cipherSuite | |
1591 self.session.srpUsername = self.allegedSrpUsername | |
1592 self.session.clientCertChain = clientCertChain | |
1593 self.session.serverCertChain = serverCertChain | |
1594 | |
1595 #Calculate pending connection states | |
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 | |
1631 | |
1632 def _handshakeWrapperAsync(self, handshaker, checker): | |
1633 if not self.fault: | |
1634 try: | |
1635 for result in handshaker: | |
1636 yield result | |
1637 if checker: | |
1638 try: | |
1639 checker(self) | |
1640 except TLSAuthenticationError: | |
1641 alert = Alert().create(AlertDescription.close_notify, | |
1642 AlertLevel.fatal) | |
1643 for result in self._sendMsg(alert): | |
1644 yield result | |
1645 raise | |
1646 except: | |
1647 self._shutdown(False) | |
1648 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]: | |
1668 raise TLSFaultError(str(alert)) | |
1669 else: | |
1670 pass | |
1671 except: | |
1672 self._shutdown(False) | |
1673 raise | |
1674 else: | |
1675 raise TLSFaultError("No error!") | |
1676 | |
1677 | |
1678 def _getKeyFromChain(self, certificate, settings): | |
1679 #Get and check cert chain from the Certificate message | |
1680 certChain = certificate.certChain | |
1681 if not certChain or certChain.getNumCerts() == 0: | |
1682 for result in self._sendError(AlertDescription.illegal_parameter, | |
1683 "Other party sent a Certificate message without "\ | |
1684 "certificates"): | |
1685 yield result | |
1686 | |
1687 #Get and check public key from the cert chain | |
1688 publicKey = certChain.getEndEntityPublicKey() | |
1689 if len(publicKey) < settings.minKeySize: | |
1690 for result in self._sendError(AlertDescription.handshake_failure, | |
1691 "Other party's public key too small: %d" % len(publicKey)): | |
1692 yield result | |
1693 if len(publicKey) > settings.maxKeySize: | |
1694 for result in self._sendError(AlertDescription.handshake_failure, | |
1695 "Other party's public key too large: %d" % len(publicKey)): | |
1696 yield result | |
1697 | |
1698 yield publicKey, certChain | |
OLD | NEW |