3 # Google - added reqCAs parameter
4 # Google (adapted by Sam Rushing and Marcelo Fernandez) - NPN support
5 # Dimitris Moraitis - Anon ciphersuites
6 # Martin von Loewis - python 3 port
8 # See the LICENSE file for legal information regarding use of this file.
11 MAIN CLASS FOR TLS LITE (START HERE!).
15 from .utils.compat import formatExceptionTrace
16 from .tlsrecordlayer import TLSRecordLayer
17 from .session import Session
18 from .constants import *
19 from .utils.cryptomath import getRandomBytes
21 from .messages import *
22 from .mathtls import *
23 from .handshakesettings import HandshakeSettings
24 from .utils.tackwrapper import *
26 class KeyExchange(object):
27 def __init__(self, cipherSuite, clientHello, serverHello, privateKey):
29 Initializes the KeyExchange. privateKey is the signing private key.
31 self.cipherSuite = cipherSuite
32 self.clientHello = clientHello
33 self.serverHello = serverHello
34 self.privateKey = privateKey
36 def makeServerKeyExchange():
38 Returns a ServerKeyExchange object for the server's initial leg in the
39 handshake. If the key exchange method does not send ServerKeyExchange
40 (e.g. RSA), it returns None.
42 raise NotImplementedError()
44 def processClientKeyExchange(clientKeyExchange):
46 Processes the client's ClientKeyExchange message and returns the
47 premaster secret. Raises TLSLocalAlert on error.
49 raise NotImplementedError()
51 class RSAKeyExchange(KeyExchange):
52 def makeServerKeyExchange(self):
55 def processClientKeyExchange(self, clientKeyExchange):
56 premasterSecret = self.privateKey.decrypt(\
57 clientKeyExchange.encryptedPreMasterSecret)
59 # On decryption failure randomize premaster secret to avoid
60 # Bleichenbacher's "million message" attack
61 randomPreMasterSecret = getRandomBytes(48)
62 if not premasterSecret:
63 premasterSecret = randomPreMasterSecret
64 elif len(premasterSecret)!=48:
65 premasterSecret = randomPreMasterSecret
67 versionCheck = (premasterSecret[0], premasterSecret[1])
68 if versionCheck != self.clientHello.client_version:
69 #Tolerate buggy IE clients
70 if versionCheck != self.serverHello.server_version:
71 premasterSecret = randomPreMasterSecret
72 return premasterSecret
74 def _hexStringToNumber(s):
75 s = s.replace(" ", "").replace("\n", "")
77 raise ValueError("Length is not even")
78 return bytesToNumber(bytearray(s.decode("hex")))
80 class DHE_RSAKeyExchange(KeyExchange):
81 # 2048-bit MODP Group (RFC 3526, Section 3)
82 dh_p = _hexStringToNumber("""
83 FFFFFFFF FFFFFFFF C90FDAA2 2168C234 C4C6628B 80DC1CD1
84 29024E08 8A67CC74 020BBEA6 3B139B22 514A0879 8E3404DD
85 EF9519B3 CD3A431B 302B0A6D F25F1437 4FE1356D 6D51C245
86 E485B576 625E7EC6 F44C42E9 A637ED6B 0BFF5CB6 F406B7ED
87 EE386BFB 5A899FA5 AE9F2411 7C4B1FE6 49286651 ECE45B3D
88 C2007CB8 A163BF05 98DA4836 1C55D39A 69163FA8 FD24CF5F
89 83655D23 DCA3AD96 1C62F356 208552BB 9ED52907 7096966D
90 670C354E 4ABC9804 F1746C08 CA18217C 32905E46 2E36CE3B
91 E39E772C 180E8603 9B2783A2 EC07A28F B5C55DF0 6F4C52C9
92 DE2BCBF6 95581718 3995497C EA956AE5 15D22618 98FA0510
93 15728E5A 8AACAA68 FFFFFFFF FFFFFFFF""")
96 # RFC 3526, Section 8.
99 def makeServerKeyExchange(self):
100 # Per RFC 3526, Section 1, the exponent should have double the entropy
101 # of the strength of the curve.
102 self.dh_Xs = bytesToNumber(getRandomBytes(self.strength * 2 / 8))
103 dh_Ys = powMod(self.dh_g, self.dh_Xs, self.dh_p)
105 serverKeyExchange = ServerKeyExchange(self.cipherSuite)
106 serverKeyExchange.createDH(self.dh_p, self.dh_g, dh_Ys)
107 serverKeyExchange.signature = self.privateKey.sign(
108 serverKeyExchange.hash(self.clientHello.random,
109 self.serverHello.random))
110 return serverKeyExchange
112 def processClientKeyExchange(self, clientKeyExchange):
113 dh_Yc = clientKeyExchange.dh_Yc
115 # First half of RFC 2631, Section 2.1.5. Validate the client's public
117 if not 2 <= dh_Yc <= self.dh_p - 1:
118 raise TLSLocalAlert(AlertDescription.illegal_parameter,
119 "Invalid dh_Yc value")
121 S = powMod(dh_Yc, self.dh_Xs, self.dh_p)
122 return numberToByteArray(S)
124 class TLSConnection(TLSRecordLayer):
126 This class wraps a socket and provides TLS handshaking and data
129 To use this class, create a new instance, passing a connected
130 socket into the constructor. Then call some handshake function.
131 If the handshake completes without raising an exception, then a TLS
132 connection has been negotiated. You can transfer data over this
133 connection as if it were a socket.
135 This class provides both synchronous and asynchronous versions of
136 its key functions. The synchronous versions should be used when
137 writing single-or multi-threaded code using blocking sockets. The
138 asynchronous versions should be used when performing asynchronous,
139 event-based I/O with non-blocking sockets.
141 Asynchronous I/O is a complicated subject; typically, you should
142 not use the asynchronous functions directly, but should use some
143 framework like asyncore or Twisted which TLS Lite integrates with
145 L{tlslite.integration.tlsasyncdispatchermixin.TLSAsyncDispatcherMixIn}).
148 def __init__(self, sock):
149 """Create a new TLSConnection instance.
151 @param sock: The socket data will be transmitted on. The
152 socket should already be connected. It may be in blocking or
155 @type sock: L{socket.socket}
157 TLSRecordLayer.__init__(self, sock)
159 #*********************************************************
160 # Client Handshake Functions
161 #*********************************************************
163 def handshakeClientAnonymous(self, session=None, settings=None,
164 checker=None, serverName="",
166 """Perform an anonymous handshake in the role of client.
168 This function performs an SSL or TLS handshake using an
169 anonymous Diffie Hellman ciphersuite.
171 Like any handshake function, this can be called on a closed
172 TLS connection, or on a TLS connection that is already open.
173 If called on an open connection it performs a re-handshake.
175 If the function completes without raising an exception, the
176 TLS connection will be open and available for data transfer.
178 If an exception is raised, the connection will have been
179 automatically closed (if it was ever open).
181 @type session: L{tlslite.Session.Session}
182 @param session: A TLS session to attempt to resume. If the
183 resumption does not succeed, a full handshake will be
186 @type settings: L{tlslite.HandshakeSettings.HandshakeSettings}
187 @param settings: Various settings which can be used to control
188 the ciphersuites, certificate types, and SSL/TLS versions
189 offered by the client.
191 @type checker: L{tlslite.Checker.Checker}
192 @param checker: A Checker instance. This instance will be
193 invoked to examine the other party's authentication
194 credentials, if the handshake completes succesfully.
196 @type serverName: string
197 @param serverName: The ServerNameIndication TLS Extension.
200 @param async: If False, this function will block until the
201 handshake is completed. If True, this function will return a
202 generator. Successive invocations of the generator will
203 return 0 if it is waiting to read from the socket, 1 if it is
204 waiting to write to the socket, or will raise StopIteration if
205 the handshake operation is completed.
207 @rtype: None or an iterable
208 @return: If 'async' is True, a generator object will be
211 @raise socket.error: If a socket error occurs.
212 @raise tlslite.errors.TLSAbruptCloseError: If the socket is closed
213 without a preceding alert.
214 @raise tlslite.errors.TLSAlert: If a TLS alert is signalled.
215 @raise tlslite.errors.TLSAuthenticationError: If the checker
216 doesn't like the other party's authentication credentials.
218 handshaker = self._handshakeClientAsync(anonParams=(True),
222 serverName=serverName)
225 for result in handshaker:
228 def handshakeClientSRP(self, username, password, session=None,
229 settings=None, checker=None,
230 reqTack=True, serverName="",
232 """Perform an SRP handshake in the role of client.
234 This function performs a TLS/SRP handshake. SRP mutually
235 authenticates both parties to each other using only a
236 username and password. This function may also perform a
237 combined SRP and server-certificate handshake, if the server
238 chooses to authenticate itself with a certificate chain in
239 addition to doing SRP.
241 If the function completes without raising an exception, the
242 TLS connection will be open and available for data transfer.
244 If an exception is raised, the connection will have been
245 automatically closed (if it was ever open).
248 @param username: The SRP username.
251 @param password: The SRP password.
253 @type session: L{tlslite.session.Session}
254 @param session: A TLS session to attempt to resume. This
255 session must be an SRP session performed with the same username
256 and password as were passed in. If the resumption does not
257 succeed, a full SRP handshake will be performed.
259 @type settings: L{tlslite.handshakesettings.HandshakeSettings}
260 @param settings: Various settings which can be used to control
261 the ciphersuites, certificate types, and SSL/TLS versions
262 offered by the client.
264 @type checker: L{tlslite.checker.Checker}
265 @param checker: A Checker instance. This instance will be
266 invoked to examine the other party's authentication
267 credentials, if the handshake completes succesfully.
270 @param reqTack: Whether or not to send a "tack" TLS Extension,
271 requesting the server return a TackExtension if it has one.
273 @type serverName: string
274 @param serverName: The ServerNameIndication TLS Extension.
277 @param async: If False, this function will block until the
278 handshake is completed. If True, this function will return a
279 generator. Successive invocations of the generator will
280 return 0 if it is waiting to read from the socket, 1 if it is
281 waiting to write to the socket, or will raise StopIteration if
282 the handshake operation is completed.
284 @rtype: None or an iterable
285 @return: If 'async' is True, a generator object will be
288 @raise socket.error: If a socket error occurs.
289 @raise tlslite.errors.TLSAbruptCloseError: If the socket is closed
290 without a preceding alert.
291 @raise tlslite.errors.TLSAlert: If a TLS alert is signalled.
292 @raise tlslite.errors.TLSAuthenticationError: If the checker
293 doesn't like the other party's authentication credentials.
295 handshaker = self._handshakeClientAsync(srpParams=(username, password),
296 session=session, settings=settings, checker=checker,
297 reqTack=reqTack, serverName=serverName)
298 # The handshaker is a Python Generator which executes the handshake.
299 # It allows the handshake to be run in a "piecewise", asynchronous
300 # fashion, returning 1 when it is waiting to able to write, 0 when
301 # it is waiting to read.
303 # If 'async' is True, the generator is returned to the caller,
304 # otherwise it is executed to completion here.
307 for result in handshaker:
310 def handshakeClientCert(self, certChain=None, privateKey=None,
311 session=None, settings=None, checker=None,
312 nextProtos=None, reqTack=True, serverName="",
314 """Perform a certificate-based handshake in the role of client.
316 This function performs an SSL or TLS handshake. The server
317 will authenticate itself using an X.509 certificate
318 chain. If the handshake succeeds, the server's certificate
319 chain will be stored in the session's serverCertChain attribute.
320 Unless a checker object is passed in, this function does no
321 validation or checking of the server's certificate chain.
323 If the server requests client authentication, the
324 client will send the passed-in certificate chain, and use the
325 passed-in private key to authenticate itself. If no
326 certificate chain and private key were passed in, the client
327 will attempt to proceed without client authentication. The
328 server may or may not allow this.
330 If the function completes without raising an exception, the
331 TLS connection will be open and available for data transfer.
333 If an exception is raised, the connection will have been
334 automatically closed (if it was ever open).
336 @type certChain: L{tlslite.x509certchain.X509CertChain}
337 @param certChain: The certificate chain to be used if the
338 server requests client authentication.
340 @type privateKey: L{tlslite.utils.rsakey.RSAKey}
341 @param privateKey: The private key to be used if the server
342 requests client authentication.
344 @type session: L{tlslite.session.Session}
345 @param session: A TLS session to attempt to resume. If the
346 resumption does not succeed, a full handshake will be
349 @type settings: L{tlslite.handshakesettings.HandshakeSettings}
350 @param settings: Various settings which can be used to control
351 the ciphersuites, certificate types, and SSL/TLS versions
352 offered by the client.
354 @type checker: L{tlslite.checker.Checker}
355 @param checker: A Checker instance. This instance will be
356 invoked to examine the other party's authentication
357 credentials, if the handshake completes succesfully.
359 @type nextProtos: list of strings.
360 @param nextProtos: A list of upper layer protocols ordered by
361 preference, to use in the Next-Protocol Negotiation Extension.
364 @param reqTack: Whether or not to send a "tack" TLS Extension,
365 requesting the server return a TackExtension if it has one.
367 @type serverName: string
368 @param serverName: The ServerNameIndication TLS Extension.
371 @param async: If False, this function will block until the
372 handshake is completed. If True, this function will return a
373 generator. Successive invocations of the generator will
374 return 0 if it is waiting to read from the socket, 1 if it is
375 waiting to write to the socket, or will raise StopIteration if
376 the handshake operation is completed.
378 @rtype: None or an iterable
379 @return: If 'async' is True, a generator object will be
382 @raise socket.error: If a socket error occurs.
383 @raise tlslite.errors.TLSAbruptCloseError: If the socket is closed
384 without a preceding alert.
385 @raise tlslite.errors.TLSAlert: If a TLS alert is signalled.
386 @raise tlslite.errors.TLSAuthenticationError: If the checker
387 doesn't like the other party's authentication credentials.
389 handshaker = self._handshakeClientAsync(certParams=(certChain,
390 privateKey), session=session, settings=settings,
391 checker=checker, serverName=serverName,
392 nextProtos=nextProtos, reqTack=reqTack)
393 # The handshaker is a Python Generator which executes the handshake.
394 # It allows the handshake to be run in a "piecewise", asynchronous
395 # fashion, returning 1 when it is waiting to able to write, 0 when
396 # it is waiting to read.
398 # If 'async' is True, the generator is returned to the caller,
399 # otherwise it is executed to completion here.
402 for result in handshaker:
406 def _handshakeClientAsync(self, srpParams=(), certParams=(), anonParams=(),
407 session=None, settings=None, checker=None,
408 nextProtos=None, serverName="", reqTack=True):
410 handshaker = self._handshakeClientAsyncHelper(srpParams=srpParams,
411 certParams=certParams,
412 anonParams=anonParams,
415 serverName=serverName,
416 nextProtos=nextProtos,
418 for result in self._handshakeWrapperAsync(handshaker, checker):
422 def _handshakeClientAsyncHelper(self, srpParams, certParams, anonParams,
423 session, settings, serverName, nextProtos, reqTack):
425 self._handshakeStart(client=True)
428 srpUsername = None # srpParams[0]
429 password = None # srpParams[1]
430 clientCertChain = None # certParams[0]
431 privateKey = None # certParams[1]
433 # Allow only one of (srpParams, certParams, anonParams)
435 assert(not certParams)
436 assert(not anonParams)
437 srpUsername, password = srpParams
439 assert(not srpParams)
440 assert(not anonParams)
441 clientCertChain, privateKey = certParams
443 assert(not srpParams)
444 assert(not certParams)
447 if srpUsername and not password:
448 raise ValueError("Caller passed a username but no password")
449 if password and not srpUsername:
450 raise ValueError("Caller passed a password but no username")
451 if clientCertChain and not privateKey:
452 raise ValueError("Caller passed a certChain but no privateKey")
453 if privateKey and not clientCertChain:
454 raise ValueError("Caller passed a privateKey but no certChain")
458 if not settings or not settings.useExperimentalTackExtension:
460 if nextProtos is not None:
461 if len(nextProtos) == 0:
462 raise ValueError("Caller passed no nextProtos")
464 # Validates the settings and filters out any unsupported ciphers
465 # or crypto libraries that were requested
467 settings = HandshakeSettings()
468 settings = settings._filter()
471 if not isinstance(clientCertChain, X509CertChain):
472 raise ValueError("Unrecognized certificate type")
473 if "x509" not in settings.certificateTypes:
474 raise ValueError("Client certificate doesn't match "\
475 "Handshake Settings")
478 # session.valid() ensures session is resumable and has
479 # non-empty sessionID
480 if not session.valid():
481 session = None #ignore non-resumable sessions...
482 elif session.resumable:
483 if session.srpUsername != srpUsername:
484 raise ValueError("Session username doesn't match")
485 if session.serverName != serverName:
486 raise ValueError("Session servername doesn't match")
488 #Add Faults to parameters
489 if srpUsername and self.fault == Fault.badUsername:
490 srpUsername += "GARBAGE"
491 if password and self.fault == Fault.badPassword:
492 password += "GARBAGE"
494 #Tentatively set the version to the client's minimum version.
495 #We'll use this for the ClientHello, and if an error occurs
496 #parsing the Server Hello, we'll use this version for the response
497 self.version = settings.maxVersion
499 # OK Start sending messages!
500 # *****************************
502 # Send the ClientHello.
503 for result in self._clientSendClientHello(settings, session,
504 srpUsername, srpParams, certParams,
505 anonParams, serverName, nextProtos,
507 if result in (0,1): yield result
511 #Get the ServerHello.
512 for result in self._clientGetServerHello(settings, clientHello):
513 if result in (0,1): yield result
516 cipherSuite = serverHello.cipher_suite
518 # Choose a matching Next Protocol from server list against ours
520 nextProto = self._clientSelectNextProto(nextProtos, serverHello)
522 #If the server elected to resume the session, it is handled here.
523 for result in self._clientResume(session, serverHello,
525 settings.cipherImplementations,
527 if result in (0,1): yield result
529 if result == "resumed_and_finished":
530 self._handshakeDone(resumed=True)
533 #If the server selected an SRP ciphersuite, the client finishes
534 #reading the post-ServerHello messages, then derives a
535 #premasterSecret and sends a corresponding ClientKeyExchange.
536 if cipherSuite in CipherSuite.srpAllSuites:
537 for result in self._clientSRPKeyExchange(\
538 settings, cipherSuite, serverHello.certificate_type,
539 srpUsername, password,
540 clientHello.random, serverHello.random,
541 serverHello.tackExt):
542 if result in (0,1): yield result
544 (premasterSecret, serverCertChain, tackExt) = result
546 #If the server selected an anonymous ciphersuite, the client
547 #finishes reading the post-ServerHello messages.
548 elif cipherSuite in CipherSuite.anonSuites:
549 for result in self._clientAnonKeyExchange(settings, cipherSuite,
550 clientHello.random, serverHello.random):
551 if result in (0,1): yield result
553 (premasterSecret, serverCertChain, tackExt) = result
555 #If the server selected a certificate-based RSA ciphersuite,
556 #the client finishes reading the post-ServerHello messages. If
557 #a CertificateRequest message was sent, the client responds with
558 #a Certificate message containing its certificate chain (if any),
559 #and also produces a CertificateVerify message that signs the
562 for result in self._clientRSAKeyExchange(settings, cipherSuite,
563 clientCertChain, privateKey,
564 serverHello.certificate_type,
565 clientHello.random, serverHello.random,
566 serverHello.tackExt):
567 if result in (0,1): yield result
569 (premasterSecret, serverCertChain, clientCertChain,
572 #After having previously sent a ClientKeyExchange, the client now
573 #initiates an exchange of Finished messages.
574 for result in self._clientFinished(premasterSecret,
577 cipherSuite, settings.cipherImplementations,
579 if result in (0,1): yield result
581 masterSecret = result
583 # Create the session object which is used for resumptions
584 self.session = Session()
585 self.session.create(masterSecret, serverHello.session_id, cipherSuite,
586 srpUsername, clientCertChain, serverCertChain,
587 tackExt, serverHello.tackExt!=None, serverName)
588 self._handshakeDone(resumed=False)
591 def _clientSendClientHello(self, settings, session, srpUsername,
592 srpParams, certParams, anonParams,
593 serverName, nextProtos, reqTack):
594 #Initialize acceptable ciphersuites
595 cipherSuites = [CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV]
597 cipherSuites += CipherSuite.getSrpAllSuites(settings)
599 cipherSuites += CipherSuite.getCertSuites(settings)
600 # TODO: Client DHE_RSA not supported.
601 # cipherSuites += CipherSuite.getDheCertSuites(settings)
603 cipherSuites += CipherSuite.getAnonSuites(settings)
607 #Initialize acceptable certificate types
608 certificateTypes = settings._getCertificateTypes()
610 #Either send ClientHello (with a resumable session)...
611 if session and session.sessionID:
612 #If it's resumable, then its
613 #ciphersuite must be one of the acceptable ciphersuites
614 if session.cipherSuite not in cipherSuites:
615 raise ValueError("Session's cipher suite not consistent "\
618 clientHello = ClientHello()
619 clientHello.create(settings.maxVersion, getRandomBytes(32),
620 session.sessionID, cipherSuites,
623 reqTack, nextProtos is not None,
626 #Or send ClientHello (without)
628 clientHello = ClientHello()
629 clientHello.create(settings.maxVersion, getRandomBytes(32),
630 bytearray(0), cipherSuites,
633 reqTack, nextProtos is not None,
635 for result in self._sendMsg(clientHello):
640 def _clientGetServerHello(self, settings, clientHello):
641 for result in self._getMsg(ContentType.handshake,
642 HandshakeType.server_hello):
643 if result in (0,1): yield result
647 #Get the server version. Do this before anything else, so any
648 #error alerts will use the server's version
649 self.version = serverHello.server_version
651 #Future responses from server must use this version
652 self._versionCheck = True
655 if serverHello.server_version < settings.minVersion:
656 for result in self._sendError(\
657 AlertDescription.protocol_version,
658 "Too old version: %s" % str(serverHello.server_version)):
660 if serverHello.server_version > settings.maxVersion:
661 for result in self._sendError(\
662 AlertDescription.protocol_version,
663 "Too new version: %s" % str(serverHello.server_version)):
665 if serverHello.cipher_suite not in clientHello.cipher_suites:
666 for result in self._sendError(\
667 AlertDescription.illegal_parameter,
668 "Server responded with incorrect ciphersuite"):
670 if serverHello.certificate_type not in clientHello.certificate_types:
671 for result in self._sendError(\
672 AlertDescription.illegal_parameter,
673 "Server responded with incorrect certificate type"):
675 if serverHello.compression_method != 0:
676 for result in self._sendError(\
677 AlertDescription.illegal_parameter,
678 "Server responded with incorrect compression method"):
680 if serverHello.tackExt:
681 if not clientHello.tack:
682 for result in self._sendError(\
683 AlertDescription.illegal_parameter,
684 "Server responded with unrequested Tack Extension"):
686 if serverHello.next_protos and not clientHello.supports_npn:
687 for result in self._sendError(\
688 AlertDescription.illegal_parameter,
689 "Server responded with unrequested NPN Extension"):
691 if not serverHello.tackExt.verifySignatures():
692 for result in self._sendError(\
693 AlertDescription.decrypt_error,
694 "TackExtension contains an invalid signature"):
698 def _clientSelectNextProto(self, nextProtos, serverHello):
699 # nextProtos is None or non-empty list of strings
700 # serverHello.next_protos is None or possibly-empty list of strings
702 # !!! We assume the client may have specified nextProtos as a list of
703 # strings so we convert them to bytearrays (it's awkward to require
704 # the user to specify a list of bytearrays or "bytes", and in
705 # Python 2.6 bytes() is just an alias for str() anyways...
706 if nextProtos is not None and serverHello.next_protos is not None:
708 if bytearray(p) in serverHello.next_protos:
711 # If the client doesn't support any of server's protocols,
712 # or the server doesn't advertise any (next_protos == [])
713 # the client SHOULD select the first protocol it supports.
714 return bytearray(nextProtos[0])
717 def _clientResume(self, session, serverHello, clientRandom,
718 cipherImplementations, nextProto):
719 #If the server agrees to resume
720 if session and session.sessionID and \
721 serverHello.session_id == session.sessionID:
723 if serverHello.cipher_suite != session.cipherSuite:
724 for result in self._sendError(\
725 AlertDescription.illegal_parameter,\
726 "Server's ciphersuite doesn't match session"):
729 #Calculate pending connection states
730 self._calcPendingStates(session.cipherSuite,
731 session.masterSecret,
732 clientRandom, serverHello.random,
733 cipherImplementations)
735 #Exchange ChangeCipherSpec and Finished messages
736 for result in self._getFinished(session.masterSecret):
738 for result in self._sendFinished(session.masterSecret, nextProto):
741 #Set the session for this connection
742 self.session = session
743 yield "resumed_and_finished"
745 def _clientSRPKeyExchange(self, settings, cipherSuite, certificateType,
746 srpUsername, password,
747 clientRandom, serverRandom, tackExt):
749 #If the server chose an SRP+RSA suite...
750 if cipherSuite in CipherSuite.srpCertSuites:
751 #Get Certificate, ServerKeyExchange, ServerHelloDone
752 for result in self._getMsg(ContentType.handshake,
753 HandshakeType.certificate, certificateType):
754 if result in (0,1): yield result
756 serverCertificate = result
758 serverCertificate = None
760 for result in self._getMsg(ContentType.handshake,
761 HandshakeType.server_key_exchange, cipherSuite):
762 if result in (0,1): yield result
764 serverKeyExchange = result
766 for result in self._getMsg(ContentType.handshake,
767 HandshakeType.server_hello_done):
768 if result in (0,1): yield result
770 serverHelloDone = result
772 #Calculate SRP premaster secret
773 #Get and check the server's group parameters and B value
774 N = serverKeyExchange.srp_N
775 g = serverKeyExchange.srp_g
776 s = serverKeyExchange.srp_s
777 B = serverKeyExchange.srp_B
779 if (g,N) not in goodGroupParameters:
780 for result in self._sendError(\
781 AlertDescription.insufficient_security,
782 "Unknown group parameters"):
784 if numBits(N) < settings.minKeySize:
785 for result in self._sendError(\
786 AlertDescription.insufficient_security,
787 "N value is too small: %d" % numBits(N)):
789 if numBits(N) > settings.maxKeySize:
790 for result in self._sendError(\
791 AlertDescription.insufficient_security,
792 "N value is too large: %d" % numBits(N)):
795 for result in self._sendError(\
796 AlertDescription.illegal_parameter,
797 "Suspicious B value"):
800 #Check the server's signature, if server chose an
802 serverCertChain = None
803 if cipherSuite in CipherSuite.srpCertSuites:
804 #Hash ServerKeyExchange/ServerSRPParams
805 hashBytes = serverKeyExchange.hash(clientRandom, serverRandom)
807 #Extract signature bytes from ServerKeyExchange
808 sigBytes = serverKeyExchange.signature
809 if len(sigBytes) == 0:
810 for result in self._sendError(\
811 AlertDescription.illegal_parameter,
812 "Server sent an SRP ServerKeyExchange "\
813 "message without a signature"):
816 # Get server's public key from the Certificate message
817 # Also validate the chain against the ServerHello's TACKext (if any)
818 # If none, and a TACK cert is present, return its TACKext
819 for result in self._clientGetKeyFromChain(serverCertificate,
821 if result in (0,1): yield result
823 publicKey, serverCertChain, tackExt = result
826 if not publicKey.verify(sigBytes, hashBytes):
827 for result in self._sendError(\
828 AlertDescription.decrypt_error,
829 "Signature failed to verify"):
832 #Calculate client's ephemeral DH values (a, A)
833 a = bytesToNumber(getRandomBytes(32))
836 #Calculate client's static DH values (x, v)
837 x = makeX(s, bytearray(srpUsername, "utf-8"),
838 bytearray(password, "utf-8"))
844 #Calculate premaster secret
846 S = powMod((B - (k*v)) % N, a+(u*x), N)
848 if self.fault == Fault.badA:
852 premasterSecret = numberToByteArray(S)
854 #Send ClientKeyExchange
855 for result in self._sendMsg(\
856 ClientKeyExchange(cipherSuite).createSRP(A)):
858 yield (premasterSecret, serverCertChain, tackExt)
861 def _clientRSAKeyExchange(self, settings, cipherSuite,
862 clientCertChain, privateKey,
864 clientRandom, serverRandom,
867 #Get Certificate[, CertificateRequest], ServerHelloDone
868 for result in self._getMsg(ContentType.handshake,
869 HandshakeType.certificate, certificateType):
870 if result in (0,1): yield result
872 serverCertificate = result
874 # Get CertificateRequest or ServerHelloDone
875 for result in self._getMsg(ContentType.handshake,
876 (HandshakeType.server_hello_done,
877 HandshakeType.certificate_request)):
878 if result in (0,1): yield result
881 certificateRequest = None
882 if isinstance(msg, CertificateRequest):
883 certificateRequest = msg
884 # We got CertificateRequest, so this must be ServerHelloDone
885 for result in self._getMsg(ContentType.handshake,
886 HandshakeType.server_hello_done):
887 if result in (0,1): yield result
889 serverHelloDone = result
890 elif isinstance(msg, ServerHelloDone):
891 serverHelloDone = msg
893 # Get server's public key from the Certificate message
894 # Also validate the chain against the ServerHello's TACKext (if any)
895 # If none, and a TACK cert is present, return its TACKext
896 for result in self._clientGetKeyFromChain(serverCertificate,
898 if result in (0,1): yield result
900 publicKey, serverCertChain, tackExt = result
902 #Calculate premaster secret
903 premasterSecret = getRandomBytes(48)
904 premasterSecret[0] = settings.maxVersion[0]
905 premasterSecret[1] = settings.maxVersion[1]
907 if self.fault == Fault.badPremasterPadding:
908 premasterSecret[0] = 5
909 if self.fault == Fault.shortPremasterSecret:
910 premasterSecret = premasterSecret[:-1]
912 #Encrypt premaster secret to server's public key
913 encryptedPreMasterSecret = publicKey.encrypt(premasterSecret)
915 #If client authentication was requested, send Certificate
916 #message, either with certificates or empty
917 if certificateRequest:
918 clientCertificate = Certificate(certificateType)
921 #Check to make sure we have the same type of
922 #certificates the server requested
924 if certificateType == CertificateType.x509:
925 if not isinstance(clientCertChain, X509CertChain):
928 for result in self._sendError(\
929 AlertDescription.handshake_failure,
930 "Client certificate is of wrong type"):
933 clientCertificate.create(clientCertChain)
934 for result in self._sendMsg(clientCertificate):
937 #The server didn't request client auth, so we
938 #zeroize these so the clientCertChain won't be
939 #stored in the session.
941 clientCertChain = None
943 #Send ClientKeyExchange
944 clientKeyExchange = ClientKeyExchange(cipherSuite,
946 clientKeyExchange.createRSA(encryptedPreMasterSecret)
947 for result in self._sendMsg(clientKeyExchange):
950 #If client authentication was requested and we have a
951 #private key, send CertificateVerify
952 if certificateRequest and privateKey:
953 if self.version == (3,0):
954 masterSecret = calcMasterSecret(self.version,
958 verifyBytes = self._calcSSLHandshakeHash(masterSecret, b"")
959 elif self.version in ((3,1), (3,2)):
960 verifyBytes = self._handshake_md5.digest() + \
961 self._handshake_sha.digest()
962 if self.fault == Fault.badVerifyMessage:
963 verifyBytes[0] = ((verifyBytes[0]+1) % 256)
964 signedBytes = privateKey.sign(verifyBytes)
965 certificateVerify = CertificateVerify()
966 certificateVerify.create(signedBytes)
967 for result in self._sendMsg(certificateVerify):
969 yield (premasterSecret, serverCertChain, clientCertChain, tackExt)
971 def _clientAnonKeyExchange(self, settings, cipherSuite, clientRandom,
973 for result in self._getMsg(ContentType.handshake,
974 HandshakeType.server_key_exchange, cipherSuite):
975 if result in (0,1): yield result
977 serverKeyExchange = result
979 for result in self._getMsg(ContentType.handshake,
980 HandshakeType.server_hello_done):
981 if result in (0,1): yield result
983 serverHelloDone = result
986 dh_p = serverKeyExchange.dh_p
987 dh_g = serverKeyExchange.dh_g
988 dh_Xc = bytesToNumber(getRandomBytes(32))
989 dh_Ys = serverKeyExchange.dh_Ys
990 dh_Yc = powMod(dh_g, dh_Xc, dh_p)
992 #Send ClientKeyExchange
993 for result in self._sendMsg(\
994 ClientKeyExchange(cipherSuite, self.version).createDH(dh_Yc)):
997 #Calculate premaster secret
998 S = powMod(dh_Ys, dh_Xc, dh_p)
999 premasterSecret = numberToByteArray(S)
1001 yield (premasterSecret, None, None)
1003 def _clientFinished(self, premasterSecret, clientRandom, serverRandom,
1004 cipherSuite, cipherImplementations, nextProto):
1006 masterSecret = calcMasterSecret(self.version, premasterSecret,
1007 clientRandom, serverRandom)
1008 self._calcPendingStates(cipherSuite, masterSecret,
1009 clientRandom, serverRandom,
1010 cipherImplementations)
1012 #Exchange ChangeCipherSpec and Finished messages
1013 for result in self._sendFinished(masterSecret, nextProto):
1015 for result in self._getFinished(masterSecret, nextProto=nextProto):
1019 def _clientGetKeyFromChain(self, certificate, settings, tackExt=None):
1020 #Get and check cert chain from the Certificate message
1021 certChain = certificate.certChain
1022 if not certChain or certChain.getNumCerts() == 0:
1023 for result in self._sendError(AlertDescription.illegal_parameter,
1024 "Other party sent a Certificate message without "\
1028 #Get and check public key from the cert chain
1029 publicKey = certChain.getEndEntityPublicKey()
1030 if len(publicKey) < settings.minKeySize:
1031 for result in self._sendError(AlertDescription.handshake_failure,
1032 "Other party's public key too small: %d" % len(publicKey)):
1034 if len(publicKey) > settings.maxKeySize:
1035 for result in self._sendError(AlertDescription.handshake_failure,
1036 "Other party's public key too large: %d" % len(publicKey)):
1039 # If there's no TLS Extension, look for a TACK cert
1042 tackExt = certChain.getTackExt()
1044 # If there's a TACK (whether via TLS or TACK Cert), check that it
1045 # matches the cert chain
1046 if tackExt and tackExt.tacks:
1047 for tack in tackExt.tacks:
1048 if not certChain.checkTack(tack):
1049 for result in self._sendError(
1050 AlertDescription.illegal_parameter,
1051 "Other party's TACK doesn't match their public key"):
1054 yield publicKey, certChain, tackExt
1057 #*********************************************************
1058 # Server Handshake Functions
1059 #*********************************************************
1062 def handshakeServer(self, verifierDB=None,
1063 certChain=None, privateKey=None, reqCert=False,
1064 sessionCache=None, settings=None, checker=None,
1065 reqCAs = None, reqCertTypes = None,
1066 tacks=None, activationFlags=0,
1067 nextProtos=None, anon=False,
1068 signedCertTimestamps=None,
1069 fallbackSCSV=False, ocspResponse=None):
1070 """Perform a handshake in the role of server.
1072 This function performs an SSL or TLS handshake. Depending on
1073 the arguments and the behavior of the client, this function can
1074 perform an SRP, or certificate-based handshake. It
1075 can also perform a combined SRP and server-certificate
1078 Like any handshake function, this can be called on a closed
1079 TLS connection, or on a TLS connection that is already open.
1080 If called on an open connection it performs a re-handshake.
1081 This function does not send a Hello Request message before
1082 performing the handshake, so if re-handshaking is required,
1083 the server must signal the client to begin the re-handshake
1084 through some other means.
1086 If the function completes without raising an exception, the
1087 TLS connection will be open and available for data transfer.
1089 If an exception is raised, the connection will have been
1090 automatically closed (if it was ever open).
1092 @type verifierDB: L{tlslite.verifierdb.VerifierDB}
1093 @param verifierDB: A database of SRP password verifiers
1094 associated with usernames. If the client performs an SRP
1095 handshake, the session's srpUsername attribute will be set.
1097 @type certChain: L{tlslite.x509certchain.X509CertChain}
1098 @param certChain: The certificate chain to be used if the
1099 client requests server certificate authentication.
1101 @type privateKey: L{tlslite.utils.rsakey.RSAKey}
1102 @param privateKey: The private key to be used if the client
1103 requests server certificate authentication.
1106 @param reqCert: Whether to request client certificate
1107 authentication. This only applies if the client chooses server
1108 certificate authentication; if the client chooses SRP
1109 authentication, this will be ignored. If the client
1110 performs a client certificate authentication, the sessions's
1111 clientCertChain attribute will be set.
1113 @type sessionCache: L{tlslite.sessioncache.SessionCache}
1114 @param sessionCache: An in-memory cache of resumable sessions.
1115 The client can resume sessions from this cache. Alternatively,
1116 if the client performs a full handshake, a new session will be
1119 @type settings: L{tlslite.handshakesettings.HandshakeSettings}
1120 @param settings: Various settings which can be used to control
1121 the ciphersuites and SSL/TLS version chosen by the server.
1123 @type checker: L{tlslite.checker.Checker}
1124 @param checker: A Checker instance. This instance will be
1125 invoked to examine the other party's authentication
1126 credentials, if the handshake completes succesfully.
1128 @type reqCAs: list of L{bytearray} of unsigned bytes
1129 @param reqCAs: A collection of DER-encoded DistinguishedNames that
1130 will be sent along with a certificate request. This does not affect
1133 @type reqCertTypes: list of int
1134 @param reqCertTypes: A list of certificate_type values to be sent
1135 along with a certificate request. This does not affect verification.
1137 @type nextProtos: list of strings.
1138 @param nextProtos: A list of upper layer protocols to expose to the
1139 clients through the Next-Protocol Negotiation Extension,
1142 @type signedCertTimestamps: str
1143 @param signedCertTimestamps: A SignedCertificateTimestampList (as a
1144 binary 8-bit string) that will be sent as a TLS extension whenever
1145 the client announces support for the extension.
1147 @type fallbackSCSV: bool
1148 @param fallbackSCSV: if true, the server will implement
1149 TLS_FALLBACK_SCSV and thus reject connections using less than the
1150 server's maximum TLS version that include this cipher suite.
1152 @type ocspResponse: str
1153 @param ocspResponse: An OCSP response (as a binary 8-bit string) that
1154 will be sent stapled in the handshake whenever the client announces
1155 support for the status_request extension.
1156 Note that the response is sent independent of the ClientHello
1157 status_request extension contents, and is thus only meant for testing
1158 environments. Real OCSP stapling is more complicated as it requires
1159 choosing a suitable response based on the ClientHello status_request
1162 @raise socket.error: If a socket error occurs.
1163 @raise tlslite.errors.TLSAbruptCloseError: If the socket is closed
1164 without a preceding alert.
1165 @raise tlslite.errors.TLSAlert: If a TLS alert is signalled.
1166 @raise tlslite.errors.TLSAuthenticationError: If the checker
1167 doesn't like the other party's authentication credentials.
1169 for result in self.handshakeServerAsync(verifierDB,
1170 certChain, privateKey, reqCert, sessionCache, settings,
1171 checker, reqCAs, reqCertTypes,
1172 tacks=tacks, activationFlags=activationFlags,
1173 nextProtos=nextProtos, anon=anon,
1174 signedCertTimestamps=signedCertTimestamps,
1175 fallbackSCSV=fallbackSCSV, ocspResponse=ocspResponse):
1179 def handshakeServerAsync(self, verifierDB=None,
1180 certChain=None, privateKey=None, reqCert=False,
1181 sessionCache=None, settings=None, checker=None,
1182 reqCAs=None, reqCertTypes=None,
1183 tacks=None, activationFlags=0,
1184 nextProtos=None, anon=False,
1185 signedCertTimestamps=None,
1189 """Start a server handshake operation on the TLS connection.
1191 This function returns a generator which behaves similarly to
1192 handshakeServer(). Successive invocations of the generator
1193 will return 0 if it is waiting to read from the socket, 1 if it is
1194 waiting to write to the socket, or it will raise StopIteration
1195 if the handshake operation is complete.
1198 @return: A generator; see above for details.
1200 handshaker = self._handshakeServerAsyncHelper(\
1201 verifierDB=verifierDB, certChain=certChain,
1202 privateKey=privateKey, reqCert=reqCert,
1203 sessionCache=sessionCache, settings=settings,
1204 reqCAs=reqCAs, reqCertTypes=reqCertTypes,
1205 tacks=tacks, activationFlags=activationFlags,
1206 nextProtos=nextProtos, anon=anon,
1207 signedCertTimestamps=signedCertTimestamps,
1208 fallbackSCSV=fallbackSCSV,
1209 ocspResponse=ocspResponse)
1210 for result in self._handshakeWrapperAsync(handshaker, checker):
1214 def _handshakeServerAsyncHelper(self, verifierDB,
1215 certChain, privateKey, reqCert, sessionCache,
1216 settings, reqCAs, reqCertTypes,
1217 tacks, activationFlags,
1219 signedCertTimestamps, fallbackSCSV,
1222 self._handshakeStart(client=False)
1224 if (not verifierDB) and (not certChain) and not anon:
1225 raise ValueError("Caller passed no authentication credentials")
1226 if certChain and not privateKey:
1227 raise ValueError("Caller passed a certChain but no privateKey")
1228 if privateKey and not certChain:
1229 raise ValueError("Caller passed a privateKey but no certChain")
1230 if reqCAs and not reqCert:
1231 raise ValueError("Caller passed reqCAs but not reqCert")
1232 if reqCertTypes and not reqCert:
1233 raise ValueError("Caller passed reqCertTypes but not reqCert")
1234 if certChain and not isinstance(certChain, X509CertChain):
1235 raise ValueError("Unrecognized certificate type")
1236 if activationFlags and not tacks:
1237 raise ValueError("Nonzero activationFlags requires tacks")
1239 if not tackpyLoaded:
1240 raise ValueError("tackpy is not loaded")
1241 if not settings or not settings.useExperimentalTackExtension:
1242 raise ValueError("useExperimentalTackExtension not enabled")
1243 if signedCertTimestamps and not certChain:
1244 raise ValueError("Caller passed signedCertTimestamps but no "
1248 settings = HandshakeSettings()
1249 settings = settings._filter()
1251 # OK Start exchanging messages
1252 # ******************************
1254 # Handle ClientHello and resumption
1255 for result in self._serverGetClientHello(settings, certChain,\
1256 verifierDB, sessionCache,
1257 anon, fallbackSCSV):
1258 if result in (0,1): yield result
1259 elif result == None:
1260 self._handshakeDone(resumed=True)
1261 return # Handshake was resumed, we're done
1263 (clientHello, cipherSuite) = result
1265 # Save the ClientHello for external code to query.
1266 self.clientHello = clientHello
1268 #If not a resumption...
1270 # Create the ServerHello message
1272 sessionID = getRandomBytes(32)
1274 sessionID = bytearray(0)
1276 if not clientHello.supports_npn:
1279 # If not doing a certificate-based suite, discard the TACK
1280 if not cipherSuite in CipherSuite.certAllSuites:
1283 # Prepare a TACK Extension if requested
1284 if clientHello.tack:
1285 tackExt = TackExtension.create(tacks, activationFlags)
1288 serverHello = ServerHello()
1289 serverHello.create(self.version, getRandomBytes(32), sessionID, \
1290 cipherSuite, CertificateType.x509, tackExt,
1292 serverHello.channel_id = clientHello.channel_id
1293 if clientHello.support_signed_cert_timestamps:
1294 serverHello.signed_cert_timestamps = signedCertTimestamps
1295 if clientHello.status_request:
1296 serverHello.status_request = ocspResponse
1298 # Perform the SRP key exchange
1299 clientCertChain = None
1300 if cipherSuite in CipherSuite.srpAllSuites:
1301 for result in self._serverSRPKeyExchange(clientHello, serverHello,
1302 verifierDB, cipherSuite,
1303 privateKey, certChain):
1304 if result in (0,1): yield result
1306 premasterSecret = result
1308 # Perform the RSA or DHE_RSA key exchange
1309 elif (cipherSuite in CipherSuite.certSuites or
1310 cipherSuite in CipherSuite.dheCertSuites):
1311 if cipherSuite in CipherSuite.certSuites:
1312 keyExchange = RSAKeyExchange(cipherSuite,
1316 elif cipherSuite in CipherSuite.dheCertSuites:
1317 keyExchange = DHE_RSAKeyExchange(cipherSuite,
1323 for result in self._serverCertKeyExchange(clientHello, serverHello,
1324 certChain, keyExchange,
1325 reqCert, reqCAs, reqCertTypes, cipherSuite,
1326 settings, ocspResponse):
1327 if result in (0,1): yield result
1329 (premasterSecret, clientCertChain) = result
1331 # Perform anonymous Diffie Hellman key exchange
1332 elif cipherSuite in CipherSuite.anonSuites:
1333 for result in self._serverAnonKeyExchange(clientHello, serverHello,
1334 cipherSuite, settings):
1335 if result in (0,1): yield result
1337 premasterSecret = result
1342 # Exchange Finished messages
1343 for result in self._serverFinished(premasterSecret,
1344 clientHello.random, serverHello.random,
1345 cipherSuite, settings.cipherImplementations,
1346 nextProtos, clientHello.channel_id):
1347 if result in (0,1): yield result
1349 masterSecret = result
1351 #Create the session object
1352 self.session = Session()
1353 if cipherSuite in CipherSuite.certAllSuites:
1354 serverCertChain = certChain
1356 serverCertChain = None
1359 if clientHello.srp_username:
1360 srpUsername = clientHello.srp_username.decode("utf-8")
1361 if clientHello.server_name:
1362 serverName = clientHello.server_name.decode("utf-8")
1363 self.session.create(masterSecret, serverHello.session_id, cipherSuite,
1364 srpUsername, clientCertChain, serverCertChain,
1365 tackExt, serverHello.tackExt!=None, serverName)
1367 #Add the session object to the session cache
1368 if sessionCache and sessionID:
1369 sessionCache[sessionID] = self.session
1371 self._handshakeDone(resumed=False)
1374 def _serverGetClientHello(self, settings, certChain, verifierDB,
1375 sessionCache, anon, fallbackSCSV):
1376 #Initialize acceptable cipher suites
1381 CipherSuite.getSrpCertSuites(settings)
1382 cipherSuites += CipherSuite.getSrpSuites(settings)
1384 cipherSuites += CipherSuite.getCertSuites(settings)
1385 cipherSuites += CipherSuite.getDheCertSuites(settings)
1387 cipherSuites += CipherSuite.getAnonSuites(settings)
1391 #Tentatively set version to most-desirable version, so if an error
1392 #occurs parsing the ClientHello, this is what we'll use for the
1394 self.version = settings.maxVersion
1397 for result in self._getMsg(ContentType.handshake,
1398 HandshakeType.client_hello):
1399 if result in (0,1): yield result
1401 clientHello = result
1403 #If client's version is too low, reject it
1404 if clientHello.client_version < settings.minVersion:
1405 self.version = settings.minVersion
1406 for result in self._sendError(\
1407 AlertDescription.protocol_version,
1408 "Too old version: %s" % str(clientHello.client_version)):
1411 #If simulating TLS intolerance, reject certain TLS versions.
1412 elif (settings.tlsIntolerant is not None and
1413 clientHello.client_version >= settings.tlsIntolerant):
1414 if settings.tlsIntoleranceType == "alert":
1415 for result in self._sendError(\
1416 AlertDescription.handshake_failure):
1418 elif settings.tlsIntoleranceType == "close":
1420 raise TLSUnsupportedError("Simulating version intolerance")
1421 elif settings.tlsIntoleranceType == "reset":
1422 self._abruptClose(reset=True)
1423 raise TLSUnsupportedError("Simulating version intolerance")
1425 raise ValueError("Unknown intolerance type: '%s'" %
1426 settings.tlsIntoleranceType)
1428 #If client's version is too high, propose my highest version
1429 elif clientHello.client_version > settings.maxVersion:
1430 self.version = settings.maxVersion
1432 #Detect if the client performed an inappropriate fallback.
1433 elif fallbackSCSV and clientHello.client_version < settings.maxVersion:
1434 self.version = clientHello.client_version
1435 if CipherSuite.TLS_FALLBACK_SCSV in clientHello.cipher_suites:
1436 for result in self._sendError(\
1437 AlertDescription.inappropriate_fallback):
1441 #Set the version to the client's version
1442 self.version = clientHello.client_version
1444 #If resumption was requested and we have a session cache...
1445 if clientHello.session_id and sessionCache:
1448 #Check in the session cache
1449 if sessionCache and not session:
1451 session = sessionCache[clientHello.session_id]
1452 if not session.resumable:
1453 raise AssertionError()
1454 #Check for consistency with ClientHello
1455 if session.cipherSuite not in cipherSuites:
1456 for result in self._sendError(\
1457 AlertDescription.handshake_failure):
1459 if session.cipherSuite not in clientHello.cipher_suites:
1460 for result in self._sendError(\
1461 AlertDescription.handshake_failure):
1463 if clientHello.srp_username:
1464 if not session.srpUsername or \
1465 clientHello.srp_username != bytearray(session.srpUsername, "utf-8"):
1466 for result in self._sendError(\
1467 AlertDescription.handshake_failure):
1469 if clientHello.server_name:
1470 if not session.serverName or \
1471 clientHello.server_name != bytearray(session.serverName, "utf-8"):
1472 for result in self._sendError(\
1473 AlertDescription.handshake_failure):
1478 #If a session is found..
1481 serverHello = ServerHello()
1482 serverHello.create(self.version, getRandomBytes(32),
1483 session.sessionID, session.cipherSuite,
1484 CertificateType.x509, None, None)
1485 for result in self._sendMsg(serverHello):
1488 #From here on, the client's messages must have right version
1489 self._versionCheck = True
1491 #Calculate pending connection states
1492 self._calcPendingStates(session.cipherSuite,
1493 session.masterSecret,
1496 settings.cipherImplementations)
1498 #Exchange ChangeCipherSpec and Finished messages
1499 for result in self._sendFinished(session.masterSecret):
1501 for result in self._getFinished(session.masterSecret):
1505 self.session = session
1507 yield None # Handshake done!
1509 #Calculate the first cipher suite intersection.
1510 #This is the 'privileged' ciphersuite. We'll use it if we're
1511 #doing a new negotiation. In fact,
1512 #the only time we won't use it is if we're resuming a
1513 #session, in which case we use the ciphersuite from the session.
1515 #Use the client's preferences for now.
1516 for cipherSuite in clientHello.cipher_suites:
1517 if cipherSuite in cipherSuites:
1520 for result in self._sendError(\
1521 AlertDescription.handshake_failure,
1522 "No mutual ciphersuite"):
1524 if cipherSuite in CipherSuite.srpAllSuites and \
1525 not clientHello.srp_username:
1526 for result in self._sendError(\
1527 AlertDescription.unknown_psk_identity,
1528 "Client sent a hello, but without the SRP username"):
1531 #If an RSA suite is chosen, check for certificate type intersection
1532 if cipherSuite in CipherSuite.certAllSuites and CertificateType.x509 \
1533 not in clientHello.certificate_types:
1534 for result in self._sendError(\
1535 AlertDescription.handshake_failure,
1536 "the client doesn't support my certificate type"):
1539 # If resumption was not requested, or
1540 # we have no session cache, or
1541 # the client's session_id was not found in cache:
1542 yield (clientHello, cipherSuite)
1544 def _serverSRPKeyExchange(self, clientHello, serverHello, verifierDB,
1545 cipherSuite, privateKey, serverCertChain):
1547 srpUsername = clientHello.srp_username.decode("utf-8")
1548 self.allegedSrpUsername = srpUsername
1549 #Get parameters from username
1551 entry = verifierDB[srpUsername]
1553 for result in self._sendError(\
1554 AlertDescription.unknown_psk_identity):
1556 (N, g, s, v) = entry
1558 #Calculate server's ephemeral DH values (b, B)
1559 b = bytesToNumber(getRandomBytes(32))
1561 B = (powMod(g, b, N) + (k*v)) % N
1563 #Create ServerKeyExchange, signing it if necessary
1564 serverKeyExchange = ServerKeyExchange(cipherSuite)
1565 serverKeyExchange.createSRP(N, g, s, B)
1566 if cipherSuite in CipherSuite.srpCertSuites:
1567 hashBytes = serverKeyExchange.hash(clientHello.random,
1569 serverKeyExchange.signature = privateKey.sign(hashBytes)
1571 #Send ServerHello[, Certificate], ServerKeyExchange,
1574 msgs.append(serverHello)
1575 if cipherSuite in CipherSuite.srpCertSuites:
1576 certificateMsg = Certificate(CertificateType.x509)
1577 certificateMsg.create(serverCertChain)
1578 msgs.append(certificateMsg)
1579 msgs.append(serverKeyExchange)
1580 msgs.append(ServerHelloDone())
1581 for result in self._sendMsgs(msgs):
1584 #From here on, the client's messages must have the right version
1585 self._versionCheck = True
1587 #Get and check ClientKeyExchange
1588 for result in self._getMsg(ContentType.handshake,
1589 HandshakeType.client_key_exchange,
1591 if result in (0,1): yield result
1593 clientKeyExchange = result
1594 A = clientKeyExchange.srp_A
1596 for result in self._sendError(AlertDescription.illegal_parameter,
1597 "Suspicious A value"):
1599 assert(False) # Just to ensure we don't fall through somehow
1604 #Calculate premaster secret
1605 S = powMod((A * powMod(v,u,N)) % N, b, N)
1606 premasterSecret = numberToByteArray(S)
1608 yield premasterSecret
1611 def _serverCertKeyExchange(self, clientHello, serverHello,
1612 serverCertChain, keyExchange,
1613 reqCert, reqCAs, reqCertTypes, cipherSuite,
1614 settings, ocspResponse):
1615 #Send ServerHello, Certificate[, ServerKeyExchange]
1616 #[, CertificateRequest], ServerHelloDone
1619 # If we verify a client cert chain, return it
1620 clientCertChain = None
1622 msgs.append(serverHello)
1623 msgs.append(Certificate(CertificateType.x509).create(serverCertChain))
1624 if serverHello.status_request:
1625 msgs.append(CertificateStatus().create(ocspResponse))
1626 serverKeyExchange = keyExchange.makeServerKeyExchange()
1627 if serverKeyExchange is not None:
1628 msgs.append(serverKeyExchange)
1630 reqCAs = reqCAs or []
1631 #Apple's Secure Transport library rejects empty certificate_types,
1632 #so default to rsa_sign.
1633 reqCertTypes = reqCertTypes or [ClientCertificateType.rsa_sign]
1634 msgs.append(CertificateRequest().create(reqCertTypes, reqCAs))
1635 msgs.append(ServerHelloDone())
1636 for result in self._sendMsgs(msgs):
1639 #From here on, the client's messages must have the right version
1640 self._versionCheck = True
1642 #Get [Certificate,] (if was requested)
1644 if self.version == (3,0):
1645 for result in self._getMsg((ContentType.handshake,
1647 HandshakeType.certificate,
1648 CertificateType.x509):
1649 if result in (0,1): yield result
1653 if isinstance(msg, Alert):
1654 #If it's not a no_certificate alert, re-raise
1656 if alert.description != \
1657 AlertDescription.no_certificate:
1658 self._shutdown(False)
1659 raise TLSRemoteAlert(alert)
1660 elif isinstance(msg, Certificate):
1661 clientCertificate = msg
1662 if clientCertificate.certChain and \
1663 clientCertificate.certChain.getNumCerts()!=0:
1664 clientCertChain = clientCertificate.certChain
1666 raise AssertionError()
1667 elif self.version in ((3,1), (3,2)):
1668 for result in self._getMsg(ContentType.handshake,
1669 HandshakeType.certificate,
1670 CertificateType.x509):
1671 if result in (0,1): yield result
1673 clientCertificate = result
1674 if clientCertificate.certChain and \
1675 clientCertificate.certChain.getNumCerts()!=0:
1676 clientCertChain = clientCertificate.certChain
1678 raise AssertionError()
1680 #Get ClientKeyExchange
1681 for result in self._getMsg(ContentType.handshake,
1682 HandshakeType.client_key_exchange,
1684 if result in (0,1): yield result
1686 clientKeyExchange = result
1688 #Process ClientKeyExchange
1691 keyExchange.processClientKeyExchange(clientKeyExchange)
1692 except TLSLocalAlert, alert:
1693 for result in self._sendError(alert.description, alert.message):
1696 #Get and check CertificateVerify, if relevant
1698 if self.version == (3,0):
1699 masterSecret = calcMasterSecret(self.version, premasterSecret,
1700 clientHello.random, serverHello.random)
1701 verifyBytes = self._calcSSLHandshakeHash(masterSecret, b"")
1702 elif self.version in ((3,1), (3,2)):
1703 verifyBytes = self._handshake_md5.digest() + \
1704 self._handshake_sha.digest()
1705 for result in self._getMsg(ContentType.handshake,
1706 HandshakeType.certificate_verify):
1707 if result in (0,1): yield result
1709 certificateVerify = result
1710 publicKey = clientCertChain.getEndEntityPublicKey()
1711 if len(publicKey) < settings.minKeySize:
1712 for result in self._sendError(\
1713 AlertDescription.handshake_failure,
1714 "Client's public key too small: %d" % len(publicKey)):
1717 if len(publicKey) > settings.maxKeySize:
1718 for result in self._sendError(\
1719 AlertDescription.handshake_failure,
1720 "Client's public key too large: %d" % len(publicKey)):
1723 if not publicKey.verify(certificateVerify.signature, verifyBytes):
1724 for result in self._sendError(\
1725 AlertDescription.decrypt_error,
1726 "Signature failed to verify"):
1728 yield (premasterSecret, clientCertChain)
1731 def _serverAnonKeyExchange(self, clientHello, serverHello, cipherSuite,
1733 # Calculate DH p, g, Xs, Ys
1734 dh_p = getRandomSafePrime(32, False)
1735 dh_g = getRandomNumber(2, dh_p)
1736 dh_Xs = bytesToNumber(getRandomBytes(32))
1737 dh_Ys = powMod(dh_g, dh_Xs, dh_p)
1739 #Create ServerKeyExchange
1740 serverKeyExchange = ServerKeyExchange(cipherSuite)
1741 serverKeyExchange.createDH(dh_p, dh_g, dh_Ys)
1743 #Send ServerHello[, Certificate], ServerKeyExchange,
1746 msgs.append(serverHello)
1747 msgs.append(serverKeyExchange)
1748 msgs.append(ServerHelloDone())
1749 for result in self._sendMsgs(msgs):
1752 #From here on, the client's messages must have the right version
1753 self._versionCheck = True
1755 #Get and check ClientKeyExchange
1756 for result in self._getMsg(ContentType.handshake,
1757 HandshakeType.client_key_exchange,
1763 clientKeyExchange = result
1764 dh_Yc = clientKeyExchange.dh_Yc
1766 if dh_Yc % dh_p == 0:
1767 for result in self._sendError(AlertDescription.illegal_parameter,
1768 "Suspicious dh_Yc value"):
1770 assert(False) # Just to ensure we don't fall through somehow
1772 #Calculate premaster secre
1773 S = powMod(dh_Yc,dh_Xs,dh_p)
1774 premasterSecret = numberToByteArray(S)
1776 yield premasterSecret
1779 def _serverFinished(self, premasterSecret, clientRandom, serverRandom,
1780 cipherSuite, cipherImplementations, nextProtos,
1782 masterSecret = calcMasterSecret(self.version, premasterSecret,
1783 clientRandom, serverRandom)
1785 #Calculate pending connection states
1786 self._calcPendingStates(cipherSuite, masterSecret,
1787 clientRandom, serverRandom,
1788 cipherImplementations)
1790 #Exchange ChangeCipherSpec and Finished messages
1791 for result in self._getFinished(masterSecret,
1792 expect_next_protocol=nextProtos is not None,
1793 expect_channel_id=doingChannelID):
1796 for result in self._sendFinished(masterSecret):
1802 #*********************************************************
1803 # Shared Handshake Functions
1804 #*********************************************************
1807 def _sendFinished(self, masterSecret, nextProto=None):
1808 #Send ChangeCipherSpec
1809 for result in self._sendMsg(ChangeCipherSpec()):
1812 #Switch to pending write state
1813 self._changeWriteState()
1815 if nextProto is not None:
1816 nextProtoMsg = NextProtocol().create(nextProto)
1817 for result in self._sendMsg(nextProtoMsg):
1820 #Calculate verification data
1821 verifyData = self._calcFinished(masterSecret, True)
1822 if self.fault == Fault.badFinished:
1823 verifyData[0] = (verifyData[0]+1)%256
1825 #Send Finished message under new state
1826 finished = Finished(self.version).create(verifyData)
1827 for result in self._sendMsg(finished):
1830 def _getFinished(self, masterSecret, expect_next_protocol=False, nextProto=None,
1831 expect_channel_id=False):
1832 #Get and check ChangeCipherSpec
1833 for result in self._getMsg(ContentType.change_cipher_spec):
1836 changeCipherSpec = result
1838 if changeCipherSpec.type != 1:
1839 for result in self._sendError(AlertDescription.illegal_parameter,
1840 "ChangeCipherSpec type incorrect"):
1843 #Switch to pending read state
1844 self._changeReadState()
1846 #Server Finish - Are we waiting for a next protocol echo?
1847 if expect_next_protocol:
1848 for result in self._getMsg(ContentType.handshake, HandshakeType.next_protocol):
1852 for result in self._sendError(AlertDescription.unexpected_message,
1853 "Didn't get NextProtocol message"):
1856 self.next_proto = result.next_proto
1858 self.next_proto = None
1860 #Client Finish - Only set the next_protocol selected in the connection
1862 self.next_proto = nextProto
1864 #Server Finish - Are we waiting for a EncryptedExtensions?
1865 if expect_channel_id:
1866 for result in self._getMsg(ContentType.handshake, HandshakeType.encrypted_extensions):
1870 for result in self._sendError(AlertDescription.unexpected_message,
1871 "Didn't get EncryptedExtensions message"):
1873 encrypted_extensions = result
1874 self.channel_id = result.channel_id_key
1876 self.channel_id = None
1878 #Calculate verification data
1879 verifyData = self._calcFinished(masterSecret, False)
1881 #Get and check Finished message under new state
1882 for result in self._getMsg(ContentType.handshake,
1883 HandshakeType.finished):
1887 if finished.verify_data != verifyData:
1888 for result in self._sendError(AlertDescription.decrypt_error,
1889 "Finished message is incorrect"):
1892 def _calcFinished(self, masterSecret, send=True):
1893 if self.version == (3,0):
1894 if (self._client and send) or (not self._client and not send):
1895 senderStr = b"\x43\x4C\x4E\x54"
1897 senderStr = b"\x53\x52\x56\x52"
1899 verifyData = self._calcSSLHandshakeHash(masterSecret, senderStr)
1902 elif self.version in ((3,1), (3,2)):
1903 if (self._client and send) or (not self._client and not send):
1904 label = b"client finished"
1906 label = b"server finished"
1908 handshakeHashes = self._handshake_md5.digest() + \
1909 self._handshake_sha.digest()
1910 verifyData = PRF(masterSecret, label, handshakeHashes, 12)
1913 raise AssertionError()
1916 def _handshakeWrapperAsync(self, handshaker, checker):
1919 for result in handshaker:
1924 except TLSAuthenticationError:
1925 alert = Alert().create(AlertDescription.close_notify,
1927 for result in self._sendMsg(alert):
1930 except GeneratorExit:
1932 except TLSAlert as alert:
1935 if alert.description not in Fault.faultAlerts[self.fault]:
1936 raise TLSFaultError(str(alert))
1940 self._shutdown(False)