2 MAIN CLASS FOR TLS LITE (START HERE!).
4 from __future__ import generators
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
13 from messages import *
15 from HandshakeSettings import HandshakeSettings
18 class TLSConnection(TLSRecordLayer):
20 This class wraps a socket and provides TLS handshaking and data
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.
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.
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
39 L{tlslite.integration.TLSAsyncDispatcherMixIn.TLSAsyncDispatcherMixIn} or
40 L{tlslite.integration.TLSTwistedProtocolWrapper.TLSTwistedProtocolWrapper}).
44 def __init__(self, sock):
45 """Create a new TLSConnection instance.
47 @param sock: The socket data will be transmitted on. The
48 socket should already be connected. It may be in blocking or
51 @type sock: L{socket.socket}
53 TLSRecordLayer.__init__(self, sock)
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.
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.
66 TLS/SRP is non-standard. Most TLS implementations don't
68 U{http://www.ietf.org/html.charters/tls-charter.html} or
69 U{http://trevp.net/tlssrp/} for the latest information on
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.
76 If the function completes without raising an exception, the
77 TLS connection will be open and available for data transfer.
79 If an exception is raised, the connection will have been
80 automatically closed (if it was ever open).
83 @param username: The SRP username.
86 @param password: The SRP password.
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.
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.
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.
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.
112 @rtype: None or an iterable
113 @return: If 'async' is True, a generator object will be
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.
123 handshaker = self._handshakeClientAsync(srpParams=(username, password),
124 session=session, settings=settings, checker=checker)
127 for result in handshaker:
130 def handshakeClientCert(self, certChain=None, privateKey=None,
131 session=None, settings=None, checker=None,
133 """Perform a certificate-based handshake in the role of client.
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.
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.
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.
153 If the function completes without raising an exception, the
154 TLS connection will be open and available for data transfer.
156 If an exception is raised, the connection will have been
157 automatically closed (if it was ever open).
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.
164 @type privateKey: L{tlslite.utils.RSAKey.RSAKey}
165 @param privateKey: The private key to be used if the server
166 requests client authentication.
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
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.
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.
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.
191 @rtype: None or an iterable
192 @return: If 'async' is True, a generator object will be
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.
202 handshaker = self._handshakeClientAsync(certParams=(certChain,
203 privateKey), session=session, settings=settings,
207 for result in handshaker:
210 def handshakeClientUnknown(self, srpCallback=None, certCallback=None,
211 session=None, settings=None, checker=None,
213 """Perform a to-be-determined type of handshake in the role of client.
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.
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.
227 After the handshake completes, the client can inspect the
228 connection's session attribute to determine what type of
229 authentication was performed.
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.
235 If the function completes without raising an exception, the
236 TLS connection will be open and available for data transfer.
238 If an exception is raised, the connection will have been
239 automatically closed (if it was ever open).
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.
246 @type certCallback: callable
247 @param certCallback: The callback to be used if the server
248 requests client certificate authentication.
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
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.
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.
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.
273 @rtype: None or an iterable
274 @return: If 'async' is True, a generator object will be
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.
284 handshaker = self._handshakeClientAsync(unknownParams=(srpCallback,
285 certCallback), session=session, settings=settings,
289 for result in handshaker:
292 def handshakeClientSharedKey(self, username, sharedKey, settings=None,
293 checker=None, async=False):
294 """Perform a shared-key handshake in the role of client.
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.
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.
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.
312 If the function completes without raising an exception, the
313 TLS connection will be open and available for data transfer.
315 If an exception is raised, the connection will have been
316 automatically closed (if it was ever open).
319 @param username: The shared-key username.
322 @param sharedKey: The shared key.
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.
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.
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.
342 @rtype: None or an iterable
343 @return: If 'async' is True, a generator object will be
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.
353 handshaker = self._handshakeClientAsync(sharedKeyParams=(username,
354 sharedKey), settings=settings, checker=checker)
357 for result in handshaker:
360 def _handshakeClientAsync(self, srpParams=(), certParams=(),
361 unknownParams=(), sharedKeyParams=(),
362 session=None, settings=None, checker=None,
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):
373 def _handshakeClientAsyncHelper(self, srpParams, certParams, unknownParams,
374 sharedKeyParams, session, settings, recursive):
376 self._handshakeStart(client=True)
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)
389 srpUsername, password = srpParams
391 clientCertChain, privateKey = certParams
393 srpCallback, certCallback = unknownParams
394 elif sharedKeyParams:
395 session = Session()._createSharedKey(*sharedKeyParams)
398 settings = HandshakeSettings()
399 settings = settings._filter()
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")
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")
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"]
424 if not foundType and isinstance(clientCertChain,
426 if "x509" not in settings.certificateTypes:
427 raise ValueError("Client certificate doesn't match "\
428 "Handshake Settings")
429 settings.certificateTypes = ["x509"]
432 raise ValueError("Unrecognized certificate type")
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")
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"
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)
459 serverCertChain = None
461 certificateType = CertificateType.x509
462 premasterSecret = None
465 clientRandom = getRandomBytes(32)
467 #Initialize acceptable ciphersuites
470 cipherSuites += CipherSuite.getSrpRsaSuites(settings.cipherNames)
471 cipherSuites += CipherSuite.getSrpSuites(settings.cipherNames)
473 cipherSuites += CipherSuite.getRsaSuites(settings.cipherNames)
477 CipherSuite.getSrpRsaSuites(settings.cipherNames)
479 CipherSuite.getSrpSuites(settings.cipherNames)
480 cipherSuites += CipherSuite.getRsaSuites(settings.cipherNames)
481 elif sharedKeyParams:
482 cipherSuites += CipherSuite.getRsaSuites(settings.cipherNames)
484 cipherSuites += CipherSuite.getRsaSuites(settings.cipherNames)
486 #Initialize acceptable certificate types
487 certificateTypes = settings._getCertificateTypes()
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
494 #Either send ClientHello (with a resumable 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 "\
503 clientHello = ClientHello()
504 clientHello.create(settings.maxVersion, clientRandom,
505 session.sessionID, cipherSuites,
506 certificateTypes, session.srpUsername)
508 #Or send ClientHello (without)
510 clientHello = ClientHello()
511 clientHello.create(settings.maxVersion, clientRandom,
512 createByteArraySequence([]), cipherSuites,
513 certificateTypes, srpUsername)
514 for result in self._sendMsg(clientHello):
517 #Get ServerHello (or missing_srp_username)
518 for result in self._getMsg((ContentType.handshake,
520 HandshakeType.server_hello):
527 if isinstance(msg, ServerHello):
529 elif isinstance(msg, Alert):
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)
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
540 for result in self._sendError(\
541 AlertDescription.unexpected_message):
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):
549 #Recursively perform handshake
550 for result in self._handshakeClientAsyncHelper(srpParams,
551 None, None, None, None, settings, True):
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
559 #Future responses from server must use this version
560 self._versionCheck = True
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)):
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)):
573 if serverHello.cipher_suite not in cipherSuites:
574 for result in self._sendError(\
575 AlertDescription.illegal_parameter,
576 "Server responded with incorrect ciphersuite"):
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"):
583 if serverHello.compression_method != 0:
584 for result in self._sendError(\
585 AlertDescription.illegal_parameter,
586 "Server responded with incorrect compression method"):
589 #Get the server nonce
590 serverRandom = serverHello.random
592 #If the server agrees to resume
593 if session and session.sessionID and \
594 serverHello.session_id == session.sessionID:
596 #If a shared-key, we're flexible about suites; otherwise the
597 #server-chosen suite has to match the session's suite
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"):
606 #Set the session for this connection
607 self.session = session
609 #Calculate pending connection states
610 self._calcPendingStates(clientRandom, serverRandom,
611 settings.cipherImplementations)
613 #Exchange ChangeCipherSpec and Finished messages
614 for result in self._getChangeCipherSpec():
616 for result in self._getFinished():
618 for result in self._sendFinished():
621 #Mark the connection as open
622 self._handshakeDone(resumed=True)
624 #If server DOES NOT agree to resume
628 for result in self._sendError(\
629 AlertDescription.user_canceled,
630 "Was expecting a shared-key resumption"):
633 #We've already validated these
634 cipherSuite = serverHello.cipher_suite
635 certificateType = serverHello.certificate_type
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):
646 serverKeyExchange = result
648 for result in self._getMsg(ContentType.handshake,
649 HandshakeType.server_hello_done):
654 serverHelloDone = result
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):
665 serverCertificate = result
667 for result in self._getMsg(ContentType.handshake,
668 HandshakeType.server_key_exchange, cipherSuite):
673 serverKeyExchange = result
675 for result in self._getMsg(ContentType.handshake,
676 HandshakeType.server_hello_done):
681 serverHelloDone = result
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):
692 serverCertificate = result
694 for result in self._getMsg(ContentType.handshake,
695 (HandshakeType.server_hello_done,
696 HandshakeType.certificate_request)):
703 certificateRequest = None
704 if isinstance(msg, CertificateRequest):
705 certificateRequest = msg
706 for result in self._getMsg(ContentType.handshake,
707 HandshakeType.server_hello_done):
712 serverHelloDone = result
713 elif isinstance(msg, ServerHelloDone):
714 serverHelloDone = msg
716 raise AssertionError()
719 #Calculate SRP premaster secret, if server chose an SRP or
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
729 if (g,N) not in goodGroupParameters:
730 for result in self._sendError(\
731 AlertDescription.untrusted_srp_parameters,
732 "Unknown group parameters"):
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)):
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)):
745 for result in self._sendError(\
746 AlertDescription.illegal_parameter,
747 "Suspicious B value"):
750 #Check the server's signature, if server chose an
752 if cipherSuite in CipherSuite.srpRsaSuites:
753 #Hash ServerKeyExchange/ServerSRPParams
754 hashBytes = serverKeyExchange.hash(clientRandom,
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"):
766 #Get server's public key from the Certificate message
767 for result in self._getKeyFromChain(serverCertificate,
773 publicKey, serverCertChain = result
776 if not publicKey.verify(sigBytes, hashBytes):
777 for result in self._sendError(\
778 AlertDescription.decrypt_error,
779 "Signature failed to verify"):
783 #Calculate client's ephemeral DH values (a, A)
784 a = bytesToNumber(getRandomBytes(32))
787 #Calculate client's static DH values (x, v)
788 x = makeX(bytesToString(s), srpUsername, password)
794 #Calculate premaster secret
796 S = powMod((B - (k*v)) % N, a+(u*x), N)
798 if self.fault == Fault.badA:
801 premasterSecret = numberToBytes(S)
803 #Send ClientKeyExchange
804 for result in self._sendMsg(\
805 ClientKeyExchange(cipherSuite).createSRP(A)):
809 #Calculate RSA premaster secret, if server chose an RSA suite
810 elif cipherSuite in CipherSuite.rsaSuites:
812 #Handle the presence of a CertificateRequest
813 if certificateRequest:
814 if unknownParams and certCallback:
815 certParamsNew = certCallback()
817 clientCertChain, privateKey = certParamsNew
819 #Get server's public key from the Certificate message
820 for result in self._getKeyFromChain(serverCertificate,
826 publicKey, serverCertChain = result
829 #Calculate premaster secret
830 premasterSecret = getRandomBytes(48)
831 premasterSecret[0] = settings.maxVersion[0]
832 premasterSecret[1] = settings.maxVersion[1]
834 if self.fault == Fault.badPremasterPadding:
835 premasterSecret[0] = 5
836 if self.fault == Fault.shortPremasterSecret:
837 premasterSecret = premasterSecret[:-1]
839 #Encrypt premaster secret to server's public key
840 encryptedPreMasterSecret = publicKey.encrypt(premasterSecret)
842 #If client authentication was requested, send Certificate
843 #message, either with certificates or empty
844 if certificateRequest:
845 clientCertificate = Certificate(certificateType)
848 #Check to make sure we have the same type of
849 #certificates the server requested
851 if certificateType == CertificateType.x509:
852 if not isinstance(clientCertChain, X509CertChain):
854 elif certificateType == CertificateType.cryptoID:
855 if not isinstance(clientCertChain,
856 cryptoIDlib.CertChain.CertChain):
859 for result in self._sendError(\
860 AlertDescription.handshake_failure,
861 "Client certificate is of wrong type"):
864 clientCertificate.create(clientCertChain)
866 for result in self._sendMsg(clientCertificate):
869 #The server didn't request client auth, so we
870 #zeroize these so the clientCertChain won't be
871 #stored in the session.
873 clientCertChain = None
875 #Send ClientKeyExchange
876 clientKeyExchange = ClientKeyExchange(cipherSuite,
878 clientKeyExchange.createRSA(encryptedPreMasterSecret)
879 for result in self._sendMsg(clientKeyExchange):
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
889 session._calcMasterSecret(self.version,
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):
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
918 #Calculate pending connection states
919 self._calcPendingStates(clientRandom, serverRandom,
920 settings.cipherImplementations)
922 #Exchange ChangeCipherSpec and Finished messages
923 for result in self._sendFinished():
925 for result in self._getChangeCipherSpec():
927 for result in self._getFinished():
930 #Mark the connection as open
931 self.session._setResumable(True)
932 self._handshakeDone(resumed=False)
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 """Perform a handshake in the role of server.
942 This function performs an SSL or TLS handshake. Depending on
943 the arguments and the behavior of the client, this function can
944 perform a shared-key, SRP, or certificate-based handshake. It
945 can also perform a combined SRP and server-certificate
948 Like any handshake function, this can be called on a closed
949 TLS connection, or on a TLS connection that is already open.
950 If called on an open connection it performs a re-handshake.
951 This function does not send a Hello Request message before
952 performing the handshake, so if re-handshaking is required,
953 the server must signal the client to begin the re-handshake
954 through some other means.
956 If the function completes without raising an exception, the
957 TLS connection will be open and available for data transfer.
959 If an exception is raised, the connection will have been
960 automatically closed (if it was ever open).
962 @type sharedKeyDB: L{tlslite.SharedKeyDB.SharedKeyDB}
963 @param sharedKeyDB: A database of shared symmetric keys
964 associated with usernames. If the client performs a
965 shared-key handshake, the session's sharedKeyUsername
966 attribute will be set.
968 @type verifierDB: L{tlslite.VerifierDB.VerifierDB}
969 @param verifierDB: A database of SRP password verifiers
970 associated with usernames. If the client performs an SRP
971 handshake, the session's srpUsername attribute will be set.
973 @type certChain: L{tlslite.X509CertChain.X509CertChain} or
974 L{cryptoIDlib.CertChain.CertChain}
975 @param certChain: The certificate chain to be used if the
976 client requests server certificate authentication.
978 @type privateKey: L{tlslite.utils.RSAKey.RSAKey}
979 @param privateKey: The private key to be used if the client
980 requests server certificate authentication.
983 @param reqCert: Whether to request client certificate
984 authentication. This only applies if the client chooses server
985 certificate authentication; if the client chooses SRP or
986 shared-key authentication, this will be ignored. If the client
987 performs a client certificate authentication, the sessions's
988 clientCertChain attribute will be set.
990 @type sessionCache: L{tlslite.SessionCache.SessionCache}
991 @param sessionCache: An in-memory cache of resumable sessions.
992 The client can resume sessions from this cache. Alternatively,
993 if the client performs a full handshake, a new session will be
996 @type settings: L{tlslite.HandshakeSettings.HandshakeSettings}
997 @param settings: Various settings which can be used to control
998 the ciphersuites and SSL/TLS version chosen by the server.
1000 @type checker: L{tlslite.Checker.Checker}
1001 @param checker: A Checker instance. This instance will be
1002 invoked to examine the other party's authentication
1003 credentials, if the handshake completes succesfully.
1005 @type reqCAs: list of L{array.array} of unsigned bytes
1006 @param reqCAs: A collection of DER-encoded DistinguishedNames that
1007 will be sent along with a certificate request. This does not affect
1010 @raise socket.error: If a socket error occurs.
1011 @raise tlslite.errors.TLSAbruptCloseError: If the socket is closed
1012 without a preceding alert.
1013 @raise tlslite.errors.TLSAlert: If a TLS alert is signalled.
1014 @raise tlslite.errors.TLSAuthenticationError: If the checker
1015 doesn't like the other party's authentication credentials.
1017 for result in self.handshakeServerAsync(sharedKeyDB, verifierDB,
1018 certChain, privateKey, reqCert, sessionCache, settings,
1019 checker, reqCAs, tlsIntolerant):
1023 def handshakeServerAsync(self, sharedKeyDB=None, verifierDB=None,
1024 certChain=None, privateKey=None, reqCert=False,
1025 sessionCache=None, settings=None, checker=None,
1026 reqCAs=None, tlsIntolerant=0):
1027 """Start a server handshake operation on the TLS connection.
1029 This function returns a generator which behaves similarly to
1030 handshakeServer(). Successive invocations of the generator
1031 will return 0 if it is waiting to read from the socket, 1 if it is
1032 waiting to write to the socket, or it will raise StopIteration
1033 if the handshake operation is complete.
1036 @return: A generator; see above for details.
1038 handshaker = self._handshakeServerAsyncHelper(\
1039 sharedKeyDB=sharedKeyDB,
1040 verifierDB=verifierDB, certChain=certChain,
1041 privateKey=privateKey, reqCert=reqCert,
1042 sessionCache=sessionCache, settings=settings,
1044 tlsIntolerant=tlsIntolerant)
1045 for result in self._handshakeWrapperAsync(handshaker, checker):
1049 def _handshakeServerAsyncHelper(self, sharedKeyDB, verifierDB,
1050 certChain, privateKey, reqCert, sessionCache,
1051 settings, reqCAs, tlsIntolerant):
1053 self._handshakeStart(client=False)
1055 if (not sharedKeyDB) and (not verifierDB) and (not certChain):
1056 raise ValueError("Caller passed no authentication credentials")
1057 if certChain and not privateKey:
1058 raise ValueError("Caller passed a certChain but no privateKey")
1059 if privateKey and not certChain:
1060 raise ValueError("Caller passed a privateKey but no certChain")
1061 if reqCAs and not reqCert:
1062 raise ValueError("Caller passed reqCAs but not reqCert")
1065 settings = HandshakeSettings()
1066 settings = settings._filter()
1068 #Initialize acceptable cipher suites
1073 CipherSuite.getSrpRsaSuites(settings.cipherNames)
1074 cipherSuites += CipherSuite.getSrpSuites(settings.cipherNames)
1075 if sharedKeyDB or certChain:
1076 cipherSuites += CipherSuite.getRsaSuites(settings.cipherNames)
1078 #Initialize acceptable certificate type
1079 certificateType = None
1082 import cryptoIDlib.CertChain
1083 if isinstance(certChain, cryptoIDlib.CertChain.CertChain):
1084 certificateType = CertificateType.cryptoID
1087 if isinstance(certChain, X509CertChain):
1088 certificateType = CertificateType.x509
1089 if certificateType == None:
1090 raise ValueError("Unrecognized certificate type")
1093 clientCertChain = None
1094 serverCertChain = None #We may set certChain to this later
1095 postFinishedError = None
1096 doingChannelID = False
1098 #Tentatively set version to most-desirable version, so if an error
1099 #occurs parsing the ClientHello, this is what we'll use for the
1101 self.version = settings.maxVersion
1104 for result in self._getMsg(ContentType.handshake,
1105 HandshakeType.client_hello):
1110 clientHello = result
1112 #If client's version is too low, reject it
1113 if clientHello.client_version < settings.minVersion:
1114 self.version = settings.minVersion
1115 for result in self._sendError(\
1116 AlertDescription.protocol_version,
1117 "Too old version: %s" % str(clientHello.client_version)):
1120 #If tlsIntolerant is nonzero, reject certain TLS versions.
1121 #1: reject all TLS versions.
1122 #2: reject TLS 1.1 or higher.
1123 #3: reject TLS 1.2 or higher.
1124 if (tlsIntolerant == 1 and clientHello.client_version > (3, 0) or
1125 tlsIntolerant == 2 and clientHello.client_version > (3, 1) or
1126 tlsIntolerant == 3 and clientHello.client_version > (3, 2)):
1127 for result in self._sendError(\
1128 AlertDescription.handshake_failure):
1131 #If client's version is too high, propose my highest version
1132 elif clientHello.client_version > settings.maxVersion:
1133 self.version = settings.maxVersion
1136 #Set the version to the client's version
1137 self.version = clientHello.client_version
1139 #Get the client nonce; create server nonce
1140 clientRandom = clientHello.random
1141 serverRandom = getRandomBytes(32)
1143 #Calculate the first cipher suite intersection.
1144 #This is the 'privileged' ciphersuite. We'll use it if we're
1145 #doing a shared-key resumption or a new negotiation. In fact,
1146 #the only time we won't use it is if we're resuming a non-sharedkey
1147 #session, in which case we use the ciphersuite from the session.
1149 #Given the current ciphersuite ordering, this means we prefer SRP
1151 for cipherSuite in cipherSuites:
1152 if cipherSuite in clientHello.cipher_suites:
1155 for result in self._sendError(\
1156 AlertDescription.handshake_failure):
1159 #If resumption was requested...
1160 if clientHello.session_id and (sharedKeyDB or sessionCache):
1163 #Check in the sharedKeys container
1164 if sharedKeyDB and len(clientHello.session_id)==16:
1166 #Trim off zero padding, if any
1168 if clientHello.session_id[x]==0:
1170 self.allegedSharedKeyUsername = bytesToString(\
1171 clientHello.session_id[:x])
1172 session = sharedKeyDB[self.allegedSharedKeyUsername]
1173 if not session.sharedKey:
1174 raise AssertionError()
1175 #use privileged ciphersuite
1176 session.cipherSuite = cipherSuite
1180 #Then check in the session cache
1181 if sessionCache and not session:
1183 session = sessionCache[bytesToString(\
1184 clientHello.session_id)]
1185 if session.sharedKey:
1186 raise AssertionError()
1187 if not session.resumable:
1188 raise AssertionError()
1189 #Check for consistency with ClientHello
1190 if session.cipherSuite not in cipherSuites:
1191 for result in self._sendError(\
1192 AlertDescription.handshake_failure):
1194 if session.cipherSuite not in clientHello.cipher_suites:
1195 for result in self._sendError(\
1196 AlertDescription.handshake_failure):
1198 if clientHello.srp_username:
1199 if clientHello.srp_username != session.srpUsername:
1200 for result in self._sendError(\
1201 AlertDescription.handshake_failure):
1206 #If a session is found..
1209 self.session = session
1212 serverHello = ServerHello()
1213 serverHello.create(self.version, serverRandom,
1214 session.sessionID, session.cipherSuite,
1216 serverHello.channel_id = clientHello.channel_id
1217 doingChannelID = clientHello.channel_id
1218 for result in self._sendMsg(serverHello):
1221 #From here on, the client's messages must have the right version
1222 self._versionCheck = True
1224 #Calculate pending connection states
1225 self._calcPendingStates(clientRandom, serverRandom,
1226 settings.cipherImplementations)
1228 #Exchange ChangeCipherSpec and Finished messages
1229 for result in self._sendFinished():
1231 for result in self._getChangeCipherSpec():
1234 for result in self._getEncryptedExtensions():
1236 for result in self._getFinished():
1239 #Mark the connection as open
1240 self._handshakeDone(resumed=True)
1244 #If not a resumption...
1246 #TRICKY: we might have chosen an RSA suite that was only deemed
1247 #acceptable because of the shared-key resumption. If the shared-
1248 #key resumption failed, because the identifier wasn't recognized,
1249 #we might fall through to here, where we have an RSA suite
1250 #chosen, but no certificate.
1251 if cipherSuite in CipherSuite.rsaSuites and not certChain:
1252 for result in self._sendError(\
1253 AlertDescription.handshake_failure):
1256 #If an RSA suite is chosen, check for certificate type intersection
1257 #(We do this check down here because if the mismatch occurs but the
1258 # client is using a shared-key session, it's okay)
1259 if cipherSuite in CipherSuite.rsaSuites + \
1260 CipherSuite.srpRsaSuites:
1261 if certificateType not in clientHello.certificate_types:
1262 for result in self._sendError(\
1263 AlertDescription.handshake_failure,
1264 "the client doesn't support my certificate type"):
1267 #Move certChain -> serverCertChain, now that we're using it
1268 serverCertChain = certChain
1273 sessionID = getRandomBytes(32)
1275 sessionID = createByteArraySequence([])
1277 #If we've selected an SRP suite, exchange keys and calculate
1279 if cipherSuite in CipherSuite.srpSuites + CipherSuite.srpRsaSuites:
1281 #If there's no SRP username...
1282 if not clientHello.srp_username:
1284 #Ask the client to re-send ClientHello with one
1285 for result in self._sendMsg(Alert().create(\
1286 AlertDescription.missing_srp_username,
1287 AlertLevel.warning)):
1291 for result in self._getMsg(ContentType.handshake,
1292 HandshakeType.client_hello):
1297 clientHello = result
1300 #If client's version is too low, reject it (COPIED CODE; BAD!)
1301 if clientHello.client_version < settings.minVersion:
1302 self.version = settings.minVersion
1303 for result in self._sendError(\
1304 AlertDescription.protocol_version,
1305 "Too old version: %s" % str(clientHello.client_version)):
1308 #If client's version is too high, propose my highest version
1309 elif clientHello.client_version > settings.maxVersion:
1310 self.version = settings.maxVersion
1313 #Set the version to the client's version
1314 self.version = clientHello.client_version
1316 #Recalculate the privileged cipher suite, making sure to
1318 cipherSuites = [c for c in cipherSuites if c in \
1319 CipherSuite.srpSuites + \
1320 CipherSuite.srpRsaSuites]
1321 for cipherSuite in cipherSuites:
1322 if cipherSuite in clientHello.cipher_suites:
1325 for result in self._sendError(\
1326 AlertDescription.handshake_failure):
1329 #Get the client nonce; create server nonce
1330 clientRandom = clientHello.random
1331 serverRandom = getRandomBytes(32)
1333 #The username better be there, this time
1334 if not clientHello.srp_username:
1335 for result in self._sendError(\
1336 AlertDescription.illegal_parameter,
1337 "Client resent a hello, but without the SRP"\
1343 self.allegedSrpUsername = clientHello.srp_username
1345 #Get parameters from username
1347 entry = verifierDB[self.allegedSrpUsername]
1349 for result in self._sendError(\
1350 AlertDescription.unknown_srp_username):
1352 (N, g, s, v) = entry
1354 #Calculate server's ephemeral DH values (b, B)
1355 b = bytesToNumber(getRandomBytes(32))
1357 B = (powMod(g, b, N) + (k*v)) % N
1359 #Create ServerKeyExchange, signing it if necessary
1360 serverKeyExchange = ServerKeyExchange(cipherSuite)
1361 serverKeyExchange.createSRP(N, g, stringToBytes(s), B)
1362 if cipherSuite in CipherSuite.srpRsaSuites:
1363 hashBytes = serverKeyExchange.hash(clientRandom,
1365 serverKeyExchange.signature = privateKey.sign(hashBytes)
1367 #Send ServerHello[, Certificate], ServerKeyExchange,
1370 serverHello = ServerHello()
1371 serverHello.create(self.version, serverRandom, sessionID,
1372 cipherSuite, certificateType)
1373 msgs.append(serverHello)
1374 if cipherSuite in CipherSuite.srpRsaSuites:
1375 certificateMsg = Certificate(certificateType)
1376 certificateMsg.create(serverCertChain)
1377 msgs.append(certificateMsg)
1378 msgs.append(serverKeyExchange)
1379 msgs.append(ServerHelloDone())
1380 for result in self._sendMsgs(msgs):
1383 #From here on, the client's messages must have the right version
1384 self._versionCheck = True
1386 #Get and check ClientKeyExchange
1387 for result in self._getMsg(ContentType.handshake,
1388 HandshakeType.client_key_exchange,
1394 clientKeyExchange = result
1395 A = clientKeyExchange.srp_A
1397 postFinishedError = (AlertDescription.illegal_parameter,
1398 "Suspicious A value")
1402 #Calculate premaster secret
1403 S = powMod((A * powMod(v,u,N)) % N, b, N)
1404 premasterSecret = numberToBytes(S)
1407 #If we've selected an RSA suite, exchange keys and calculate
1409 elif cipherSuite in CipherSuite.rsaSuites:
1411 #Send ServerHello, Certificate[, CertificateRequest],
1414 serverHello = ServerHello().create(
1415 self.version, serverRandom,
1416 sessionID, cipherSuite, certificateType)
1417 serverHello.channel_id = clientHello.channel_id
1418 doingChannelID = clientHello.channel_id
1419 msgs.append(serverHello)
1420 msgs.append(Certificate(certificateType).create(serverCertChain))
1421 if reqCert and reqCAs:
1422 msgs.append(CertificateRequest().create([], reqCAs))
1424 msgs.append(CertificateRequest())
1425 msgs.append(ServerHelloDone())
1426 for result in self._sendMsgs(msgs):
1429 #From here on, the client's messages must have the right version
1430 self._versionCheck = True
1432 #Get [Certificate,] (if was requested)
1434 if self.version == (3,0):
1435 for result in self._getMsg((ContentType.handshake,
1437 HandshakeType.certificate,
1445 if isinstance(msg, Alert):
1446 #If it's not a no_certificate alert, re-raise
1448 if alert.description != \
1449 AlertDescription.no_certificate:
1450 self._shutdown(False)
1451 raise TLSRemoteAlert(alert)
1452 elif isinstance(msg, Certificate):
1453 clientCertificate = msg
1454 if clientCertificate.certChain and \
1455 clientCertificate.certChain.getNumCerts()!=0:
1456 clientCertChain = clientCertificate.certChain
1458 raise AssertionError()
1459 elif self.version in ((3,1), (3,2)):
1460 for result in self._getMsg(ContentType.handshake,
1461 HandshakeType.certificate,
1467 clientCertificate = result
1468 if clientCertificate.certChain and \
1469 clientCertificate.certChain.getNumCerts()!=0:
1470 clientCertChain = clientCertificate.certChain
1472 raise AssertionError()
1474 #Get ClientKeyExchange
1475 for result in self._getMsg(ContentType.handshake,
1476 HandshakeType.client_key_exchange,
1482 clientKeyExchange = result
1484 #Decrypt ClientKeyExchange
1485 premasterSecret = privateKey.decrypt(\
1486 clientKeyExchange.encryptedPreMasterSecret)
1488 randomPreMasterSecret = getRandomBytes(48)
1489 versionCheck = (premasterSecret[0], premasterSecret[1])
1490 if not premasterSecret:
1491 premasterSecret = randomPreMasterSecret
1492 elif len(premasterSecret)!=48:
1493 premasterSecret = randomPreMasterSecret
1494 elif versionCheck != clientHello.client_version:
1495 if versionCheck != self.version: #Tolerate buggy IE clients
1496 premasterSecret = randomPreMasterSecret
1498 #Get and check CertificateVerify, if relevant
1500 if self.version == (3,0):
1501 #Create a temporary session object, just for the purpose
1502 #of checking the CertificateVerify
1504 session._calcMasterSecret(self.version, premasterSecret,
1505 clientRandom, serverRandom)
1506 verifyBytes = self._calcSSLHandshakeHash(\
1507 session.masterSecret, "")
1508 elif self.version in ((3,1), (3,2)):
1509 verifyBytes = stringToBytes(self._handshake_md5.digest() +\
1510 self._handshake_sha.digest())
1511 for result in self._getMsg(ContentType.handshake,
1512 HandshakeType.certificate_verify):
1517 certificateVerify = result
1518 publicKey = clientCertChain.getEndEntityPublicKey()
1519 if len(publicKey) < settings.minKeySize:
1520 postFinishedError = (AlertDescription.handshake_failure,
1521 "Client's public key too small: %d" % len(publicKey))
1522 if len(publicKey) > settings.maxKeySize:
1523 postFinishedError = (AlertDescription.handshake_failure,
1524 "Client's public key too large: %d" % len(publicKey))
1526 if not publicKey.verify(certificateVerify.signature,
1528 postFinishedError = (AlertDescription.decrypt_error,
1529 "Signature failed to verify")
1532 #Create the session object
1533 self.session = Session()
1534 self.session._calcMasterSecret(self.version, premasterSecret,
1535 clientRandom, serverRandom)
1536 self.session.sessionID = sessionID
1537 self.session.cipherSuite = cipherSuite
1538 self.session.srpUsername = self.allegedSrpUsername
1539 self.session.clientCertChain = clientCertChain
1540 self.session.serverCertChain = serverCertChain
1542 #Calculate pending connection states
1543 self._calcPendingStates(clientRandom, serverRandom,
1544 settings.cipherImplementations)
1546 #Exchange ChangeCipherSpec and Finished messages
1547 for result in self._getChangeCipherSpec():
1550 for result in self._getEncryptedExtensions():
1552 for result in self._getFinished():
1555 #If we were holding a post-finished error until receiving the client
1556 #finished message, send it now. We delay the call until this point
1557 #because calling sendError() throws an exception, and our caller might
1558 #shut down the socket upon receiving the exception. If he did, and the
1559 #client was still sending its ChangeCipherSpec or Finished messages, it
1560 #would cause a socket error on the client side. This is a lot of
1561 #consideration to show to misbehaving clients, but this would also
1562 #cause problems with fault-testing.
1563 if postFinishedError:
1564 for result in self._sendError(*postFinishedError):
1567 for result in self._sendFinished():
1570 #Add the session object to the session cache
1571 if sessionCache and sessionID:
1572 sessionCache[bytesToString(sessionID)] = self.session
1574 #Mark the connection as open
1575 self.session._setResumable(True)
1576 self._handshakeDone(resumed=False)
1579 def _handshakeWrapperAsync(self, handshaker, checker):
1582 for result in handshaker:
1587 except TLSAuthenticationError:
1588 alert = Alert().create(AlertDescription.close_notify,
1590 for result in self._sendMsg(alert):
1594 self._shutdown(False)
1598 for result in handshaker:
1603 except TLSAuthenticationError:
1604 alert = Alert().create(AlertDescription.close_notify,
1606 for result in self._sendMsg(alert):
1609 except socket.error, e:
1610 raise TLSFaultError("socket error!")
1611 except TLSAbruptCloseError, e:
1612 raise TLSFaultError("abrupt close error!")
1613 except TLSAlert, alert:
1614 if alert.description not in Fault.faultAlerts[self.fault]:
1615 raise TLSFaultError(str(alert))
1619 self._shutdown(False)
1622 raise TLSFaultError("No error!")
1625 def _getKeyFromChain(self, certificate, settings):
1626 #Get and check cert chain from the Certificate message
1627 certChain = certificate.certChain
1628 if not certChain or certChain.getNumCerts() == 0:
1629 for result in self._sendError(AlertDescription.illegal_parameter,
1630 "Other party sent a Certificate message without "\
1634 #Get and check public key from the cert chain
1635 publicKey = certChain.getEndEntityPublicKey()
1636 if len(publicKey) < settings.minKeySize:
1637 for result in self._sendError(AlertDescription.handshake_failure,
1638 "Other party's public key too small: %d" % len(publicKey)):
1640 if len(publicKey) > settings.maxKeySize:
1641 for result in self._sendError(AlertDescription.handshake_failure,
1642 "Other party's public key too large: %d" % len(publicKey)):
1645 yield publicKey, certChain