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

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

Issue 211173006: Perform tlslite 0.3.8 -> 0.4.6 renames ahead of time. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Drop the -B 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
(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
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