1# Authors: 2# Trevor Perrin 3# Google - added reqCAs parameter 4# Google (adapted by Sam Rushing and Marcelo Fernandez) - NPN support 5# Dimitris Moraitis - Anon ciphersuites 6# Martin von Loewis - python 3 port 7# 8# See the LICENSE file for legal information regarding use of this file. 9 10""" 11MAIN CLASS FOR TLS LITE (START HERE!). 12""" 13 14import socket 15from .utils.compat import formatExceptionTrace 16from .tlsrecordlayer import TLSRecordLayer 17from .session import Session 18from .constants import * 19from .utils.cryptomath import getRandomBytes 20from .errors import * 21from .messages import * 22from .mathtls import * 23from .handshakesettings import HandshakeSettings 24from .utils.tackwrapper import * 25 26class KeyExchange(object): 27 def __init__(self, cipherSuite, clientHello, serverHello, privateKey): 28 """ 29 Initializes the KeyExchange. privateKey is the signing private key. 30 """ 31 self.cipherSuite = cipherSuite 32 self.clientHello = clientHello 33 self.serverHello = serverHello 34 self.privateKey = privateKey 35 36 def makeServerKeyExchange(): 37 """ 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. 41 """ 42 raise NotImplementedError() 43 44 def processClientKeyExchange(clientKeyExchange): 45 """ 46 Processes the client's ClientKeyExchange message and returns the 47 premaster secret. Raises TLSLocalAlert on error. 48 """ 49 raise NotImplementedError() 50 51class RSAKeyExchange(KeyExchange): 52 def makeServerKeyExchange(self): 53 return None 54 55 def processClientKeyExchange(self, clientKeyExchange): 56 premasterSecret = self.privateKey.decrypt(\ 57 clientKeyExchange.encryptedPreMasterSecret) 58 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 66 else: 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 73 74def _hexStringToNumber(s): 75 s = s.replace(" ", "").replace("\n", "") 76 if len(s) % 2 != 0: 77 raise ValueError("Length is not even") 78 return bytesToNumber(bytearray(s.decode("hex"))) 79 80class DHE_RSAKeyExchange(KeyExchange): 81 # 2048-bit MODP Group (RFC 3526, Section 3) 82 dh_p = _hexStringToNumber(""" 83FFFFFFFF FFFFFFFF C90FDAA2 2168C234 C4C6628B 80DC1CD1 8429024E08 8A67CC74 020BBEA6 3B139B22 514A0879 8E3404DD 85EF9519B3 CD3A431B 302B0A6D F25F1437 4FE1356D 6D51C245 86E485B576 625E7EC6 F44C42E9 A637ED6B 0BFF5CB6 F406B7ED 87EE386BFB 5A899FA5 AE9F2411 7C4B1FE6 49286651 ECE45B3D 88C2007CB8 A163BF05 98DA4836 1C55D39A 69163FA8 FD24CF5F 8983655D23 DCA3AD96 1C62F356 208552BB 9ED52907 7096966D 90670C354E 4ABC9804 F1746C08 CA18217C 32905E46 2E36CE3B 91E39E772C 180E8603 9B2783A2 EC07A28F B5C55DF0 6F4C52C9 92DE2BCBF6 95581718 3995497C EA956AE5 15D22618 98FA0510 9315728E5A 8AACAA68 FFFFFFFF FFFFFFFF""") 94 dh_g = 2 95 96 # RFC 3526, Section 8. 97 strength = 160 98 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) 104 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 111 112 def processClientKeyExchange(self, clientKeyExchange): 113 dh_Yc = clientKeyExchange.dh_Yc 114 115 # First half of RFC 2631, Section 2.1.5. Validate the client's public 116 # key. 117 if not 2 <= dh_Yc <= self.dh_p - 1: 118 raise TLSLocalAlert(AlertDescription.illegal_parameter, 119 "Invalid dh_Yc value") 120 121 S = powMod(dh_Yc, self.dh_Xs, self.dh_p) 122 return numberToByteArray(S) 123 124class TLSConnection(TLSRecordLayer): 125 """ 126 This class wraps a socket and provides TLS handshaking and data 127 transfer. 128 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. 134 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. 140 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 144 (see 145 L{tlslite.integration.tlsasyncdispatchermixin.TLSAsyncDispatcherMixIn}). 146 """ 147 148 def __init__(self, sock): 149 """Create a new TLSConnection instance. 150 151 @param sock: The socket data will be transmitted on. The 152 socket should already be connected. It may be in blocking or 153 non-blocking mode. 154 155 @type sock: L{socket.socket} 156 """ 157 TLSRecordLayer.__init__(self, sock) 158 159 #********************************************************* 160 # Client Handshake Functions 161 #********************************************************* 162 163 def handshakeClientAnonymous(self, session=None, settings=None, 164 checker=None, serverName="", 165 async=False): 166 """Perform an anonymous handshake in the role of client. 167 168 This function performs an SSL or TLS handshake using an 169 anonymous Diffie Hellman ciphersuite. 170 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. 174 175 If the function completes without raising an exception, the 176 TLS connection will be open and available for data transfer. 177 178 If an exception is raised, the connection will have been 179 automatically closed (if it was ever open). 180 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 184 performed. 185 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. 190 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. 195 196 @type serverName: string 197 @param serverName: The ServerNameIndication TLS Extension. 198 199 @type async: bool 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. 206 207 @rtype: None or an iterable 208 @return: If 'async' is True, a generator object will be 209 returned. 210 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. 217 """ 218 handshaker = self._handshakeClientAsync(anonParams=(True), 219 session=session, 220 settings=settings, 221 checker=checker, 222 serverName=serverName) 223 if async: 224 return handshaker 225 for result in handshaker: 226 pass 227 228 def handshakeClientSRP(self, username, password, session=None, 229 settings=None, checker=None, 230 reqTack=True, serverName="", 231 async=False): 232 """Perform an SRP handshake in the role of client. 233 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. 240 241 If the function completes without raising an exception, the 242 TLS connection will be open and available for data transfer. 243 244 If an exception is raised, the connection will have been 245 automatically closed (if it was ever open). 246 247 @type username: str 248 @param username: The SRP username. 249 250 @type password: str 251 @param password: The SRP password. 252 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. 258 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. 263 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. 268 269 @type reqTack: bool 270 @param reqTack: Whether or not to send a "tack" TLS Extension, 271 requesting the server return a TackExtension if it has one. 272 273 @type serverName: string 274 @param serverName: The ServerNameIndication TLS Extension. 275 276 @type async: bool 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. 283 284 @rtype: None or an iterable 285 @return: If 'async' is True, a generator object will be 286 returned. 287 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. 294 """ 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. 302 # 303 # If 'async' is True, the generator is returned to the caller, 304 # otherwise it is executed to completion here. 305 if async: 306 return handshaker 307 for result in handshaker: 308 pass 309 310 def handshakeClientCert(self, certChain=None, privateKey=None, 311 session=None, settings=None, checker=None, 312 nextProtos=None, reqTack=True, serverName="", 313 async=False): 314 """Perform a certificate-based handshake in the role of client. 315 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. 322 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. 329 330 If the function completes without raising an exception, the 331 TLS connection will be open and available for data transfer. 332 333 If an exception is raised, the connection will have been 334 automatically closed (if it was ever open). 335 336 @type certChain: L{tlslite.x509certchain.X509CertChain} 337 @param certChain: The certificate chain to be used if the 338 server requests client authentication. 339 340 @type privateKey: L{tlslite.utils.rsakey.RSAKey} 341 @param privateKey: The private key to be used if the server 342 requests client authentication. 343 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 347 performed. 348 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. 353 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. 358 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. 362 363 @type reqTack: bool 364 @param reqTack: Whether or not to send a "tack" TLS Extension, 365 requesting the server return a TackExtension if it has one. 366 367 @type serverName: string 368 @param serverName: The ServerNameIndication TLS Extension. 369 370 @type async: bool 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. 377 378 @rtype: None or an iterable 379 @return: If 'async' is True, a generator object will be 380 returned. 381 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. 388 """ 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. 397 # 398 # If 'async' is True, the generator is returned to the caller, 399 # otherwise it is executed to completion here. 400 if async: 401 return handshaker 402 for result in handshaker: 403 pass 404 405 406 def _handshakeClientAsync(self, srpParams=(), certParams=(), anonParams=(), 407 session=None, settings=None, checker=None, 408 nextProtos=None, serverName="", reqTack=True): 409 410 handshaker = self._handshakeClientAsyncHelper(srpParams=srpParams, 411 certParams=certParams, 412 anonParams=anonParams, 413 session=session, 414 settings=settings, 415 serverName=serverName, 416 nextProtos=nextProtos, 417 reqTack=reqTack) 418 for result in self._handshakeWrapperAsync(handshaker, checker): 419 yield result 420 421 422 def _handshakeClientAsyncHelper(self, srpParams, certParams, anonParams, 423 session, settings, serverName, nextProtos, reqTack): 424 425 self._handshakeStart(client=True) 426 427 #Unpack parameters 428 srpUsername = None # srpParams[0] 429 password = None # srpParams[1] 430 clientCertChain = None # certParams[0] 431 privateKey = None # certParams[1] 432 433 # Allow only one of (srpParams, certParams, anonParams) 434 if srpParams: 435 assert(not certParams) 436 assert(not anonParams) 437 srpUsername, password = srpParams 438 if certParams: 439 assert(not srpParams) 440 assert(not anonParams) 441 clientCertChain, privateKey = certParams 442 if anonParams: 443 assert(not srpParams) 444 assert(not certParams) 445 446 #Validate parameters 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") 455 if reqTack: 456 if not tackpyLoaded: 457 reqTack = False 458 if not settings or not settings.useExperimentalTackExtension: 459 reqTack = False 460 if nextProtos is not None: 461 if len(nextProtos) == 0: 462 raise ValueError("Caller passed no nextProtos") 463 464 # Validates the settings and filters out any unsupported ciphers 465 # or crypto libraries that were requested 466 if not settings: 467 settings = HandshakeSettings() 468 settings = settings._filter() 469 470 if clientCertChain: 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") 476 477 if session: 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") 487 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" 493 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 498 499 # OK Start sending messages! 500 # ***************************** 501 502 # Send the ClientHello. 503 for result in self._clientSendClientHello(settings, session, 504 srpUsername, srpParams, certParams, 505 anonParams, serverName, nextProtos, 506 reqTack): 507 if result in (0,1): yield result 508 else: break 509 clientHello = result 510 511 #Get the ServerHello. 512 for result in self._clientGetServerHello(settings, clientHello): 513 if result in (0,1): yield result 514 else: break 515 serverHello = result 516 cipherSuite = serverHello.cipher_suite 517 518 # Choose a matching Next Protocol from server list against ours 519 # (string or None) 520 nextProto = self._clientSelectNextProto(nextProtos, serverHello) 521 522 #If the server elected to resume the session, it is handled here. 523 for result in self._clientResume(session, serverHello, 524 clientHello.random, 525 settings.cipherImplementations, 526 nextProto): 527 if result in (0,1): yield result 528 else: break 529 if result == "resumed_and_finished": 530 self._handshakeDone(resumed=True) 531 return 532 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 543 else: break 544 (premasterSecret, serverCertChain, tackExt) = result 545 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 552 else: break 553 (premasterSecret, serverCertChain, tackExt) = result 554 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 560 #ClientKeyExchange. 561 else: 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 568 else: break 569 (premasterSecret, serverCertChain, clientCertChain, 570 tackExt) = result 571 572 #After having previously sent a ClientKeyExchange, the client now 573 #initiates an exchange of Finished messages. 574 for result in self._clientFinished(premasterSecret, 575 clientHello.random, 576 serverHello.random, 577 cipherSuite, settings.cipherImplementations, 578 nextProto): 579 if result in (0,1): yield result 580 else: break 581 masterSecret = result 582 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) 589 590 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] 596 if srpParams: 597 cipherSuites += CipherSuite.getSrpAllSuites(settings) 598 elif certParams: 599 cipherSuites += CipherSuite.getCertSuites(settings) 600 # TODO: Client DHE_RSA not supported. 601 # cipherSuites += CipherSuite.getDheCertSuites(settings) 602 elif anonParams: 603 cipherSuites += CipherSuite.getAnonSuites(settings) 604 else: 605 assert(False) 606 607 #Initialize acceptable certificate types 608 certificateTypes = settings._getCertificateTypes() 609 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 "\ 616 "with parameters") 617 else: 618 clientHello = ClientHello() 619 clientHello.create(settings.maxVersion, getRandomBytes(32), 620 session.sessionID, cipherSuites, 621 certificateTypes, 622 session.srpUsername, 623 reqTack, nextProtos is not None, 624 session.serverName) 625 626 #Or send ClientHello (without) 627 else: 628 clientHello = ClientHello() 629 clientHello.create(settings.maxVersion, getRandomBytes(32), 630 bytearray(0), cipherSuites, 631 certificateTypes, 632 srpUsername, 633 reqTack, nextProtos is not None, 634 serverName) 635 for result in self._sendMsg(clientHello): 636 yield result 637 yield clientHello 638 639 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 644 else: break 645 serverHello = result 646 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 650 651 #Future responses from server must use this version 652 self._versionCheck = True 653 654 #Check ServerHello 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)): 659 yield result 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)): 664 yield result 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"): 669 yield result 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"): 674 yield result 675 if serverHello.compression_method != 0: 676 for result in self._sendError(\ 677 AlertDescription.illegal_parameter, 678 "Server responded with incorrect compression method"): 679 yield result 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"): 685 yield result 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"): 690 yield result 691 if not serverHello.tackExt.verifySignatures(): 692 for result in self._sendError(\ 693 AlertDescription.decrypt_error, 694 "TackExtension contains an invalid signature"): 695 yield result 696 yield serverHello 697 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 701 # 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: 707 for p in nextProtos: 708 if bytearray(p) in serverHello.next_protos: 709 return bytearray(p) 710 else: 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]) 715 return None 716 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: 722 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"): 727 yield result 728 729 #Calculate pending connection states 730 self._calcPendingStates(session.cipherSuite, 731 session.masterSecret, 732 clientRandom, serverHello.random, 733 cipherImplementations) 734 735 #Exchange ChangeCipherSpec and Finished messages 736 for result in self._getFinished(session.masterSecret): 737 yield result 738 for result in self._sendFinished(session.masterSecret, nextProto): 739 yield result 740 741 #Set the session for this connection 742 self.session = session 743 yield "resumed_and_finished" 744 745 def _clientSRPKeyExchange(self, settings, cipherSuite, certificateType, 746 srpUsername, password, 747 clientRandom, serverRandom, tackExt): 748 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 755 else: break 756 serverCertificate = result 757 else: 758 serverCertificate = None 759 760 for result in self._getMsg(ContentType.handshake, 761 HandshakeType.server_key_exchange, cipherSuite): 762 if result in (0,1): yield result 763 else: break 764 serverKeyExchange = result 765 766 for result in self._getMsg(ContentType.handshake, 767 HandshakeType.server_hello_done): 768 if result in (0,1): yield result 769 else: break 770 serverHelloDone = result 771 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 778 779 if (g,N) not in goodGroupParameters: 780 for result in self._sendError(\ 781 AlertDescription.insufficient_security, 782 "Unknown group parameters"): 783 yield result 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)): 788 yield result 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)): 793 yield result 794 if B % N == 0: 795 for result in self._sendError(\ 796 AlertDescription.illegal_parameter, 797 "Suspicious B value"): 798 yield result 799 800 #Check the server's signature, if server chose an 801 #SRP+RSA suite 802 serverCertChain = None 803 if cipherSuite in CipherSuite.srpCertSuites: 804 #Hash ServerKeyExchange/ServerSRPParams 805 hashBytes = serverKeyExchange.hash(clientRandom, serverRandom) 806 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"): 814 yield result 815 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, 820 settings, tackExt): 821 if result in (0,1): yield result 822 else: break 823 publicKey, serverCertChain, tackExt = result 824 825 #Verify signature 826 if not publicKey.verify(sigBytes, hashBytes): 827 for result in self._sendError(\ 828 AlertDescription.decrypt_error, 829 "Signature failed to verify"): 830 yield result 831 832 #Calculate client's ephemeral DH values (a, A) 833 a = bytesToNumber(getRandomBytes(32)) 834 A = powMod(g, a, N) 835 836 #Calculate client's static DH values (x, v) 837 x = makeX(s, bytearray(srpUsername, "utf-8"), 838 bytearray(password, "utf-8")) 839 v = powMod(g, x, N) 840 841 #Calculate u 842 u = makeU(N, A, B) 843 844 #Calculate premaster secret 845 k = makeK(N, g) 846 S = powMod((B - (k*v)) % N, a+(u*x), N) 847 848 if self.fault == Fault.badA: 849 A = N 850 S = 0 851 852 premasterSecret = numberToByteArray(S) 853 854 #Send ClientKeyExchange 855 for result in self._sendMsg(\ 856 ClientKeyExchange(cipherSuite).createSRP(A)): 857 yield result 858 yield (premasterSecret, serverCertChain, tackExt) 859 860 861 def _clientRSAKeyExchange(self, settings, cipherSuite, 862 clientCertChain, privateKey, 863 certificateType, 864 clientRandom, serverRandom, 865 tackExt): 866 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 871 else: break 872 serverCertificate = result 873 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 879 else: break 880 msg = 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 888 else: break 889 serverHelloDone = result 890 elif isinstance(msg, ServerHelloDone): 891 serverHelloDone = msg 892 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, 897 settings, tackExt): 898 if result in (0,1): yield result 899 else: break 900 publicKey, serverCertChain, tackExt = result 901 902 #Calculate premaster secret 903 premasterSecret = getRandomBytes(48) 904 premasterSecret[0] = settings.maxVersion[0] 905 premasterSecret[1] = settings.maxVersion[1] 906 907 if self.fault == Fault.badPremasterPadding: 908 premasterSecret[0] = 5 909 if self.fault == Fault.shortPremasterSecret: 910 premasterSecret = premasterSecret[:-1] 911 912 #Encrypt premaster secret to server's public key 913 encryptedPreMasterSecret = publicKey.encrypt(premasterSecret) 914 915 #If client authentication was requested, send Certificate 916 #message, either with certificates or empty 917 if certificateRequest: 918 clientCertificate = Certificate(certificateType) 919 920 if clientCertChain: 921 #Check to make sure we have the same type of 922 #certificates the server requested 923 wrongType = False 924 if certificateType == CertificateType.x509: 925 if not isinstance(clientCertChain, X509CertChain): 926 wrongType = True 927 if wrongType: 928 for result in self._sendError(\ 929 AlertDescription.handshake_failure, 930 "Client certificate is of wrong type"): 931 yield result 932 933 clientCertificate.create(clientCertChain) 934 for result in self._sendMsg(clientCertificate): 935 yield result 936 else: 937 #The server didn't request client auth, so we 938 #zeroize these so the clientCertChain won't be 939 #stored in the session. 940 privateKey = None 941 clientCertChain = None 942 943 #Send ClientKeyExchange 944 clientKeyExchange = ClientKeyExchange(cipherSuite, 945 self.version) 946 clientKeyExchange.createRSA(encryptedPreMasterSecret) 947 for result in self._sendMsg(clientKeyExchange): 948 yield result 949 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, 955 premasterSecret, 956 clientRandom, 957 serverRandom) 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): 968 yield result 969 yield (premasterSecret, serverCertChain, clientCertChain, tackExt) 970 971 def _clientAnonKeyExchange(self, settings, cipherSuite, clientRandom, 972 serverRandom): 973 for result in self._getMsg(ContentType.handshake, 974 HandshakeType.server_key_exchange, cipherSuite): 975 if result in (0,1): yield result 976 else: break 977 serverKeyExchange = result 978 979 for result in self._getMsg(ContentType.handshake, 980 HandshakeType.server_hello_done): 981 if result in (0,1): yield result 982 else: break 983 serverHelloDone = result 984 985 #calculate Yc 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) 991 992 #Send ClientKeyExchange 993 for result in self._sendMsg(\ 994 ClientKeyExchange(cipherSuite, self.version).createDH(dh_Yc)): 995 yield result 996 997 #Calculate premaster secret 998 S = powMod(dh_Ys, dh_Xc, dh_p) 999 premasterSecret = numberToByteArray(S) 1000 1001 yield (premasterSecret, None, None) 1002 1003 def _clientFinished(self, premasterSecret, clientRandom, serverRandom, 1004 cipherSuite, cipherImplementations, nextProto): 1005 1006 masterSecret = calcMasterSecret(self.version, premasterSecret, 1007 clientRandom, serverRandom) 1008 self._calcPendingStates(cipherSuite, masterSecret, 1009 clientRandom, serverRandom, 1010 cipherImplementations) 1011 1012 #Exchange ChangeCipherSpec and Finished messages 1013 for result in self._sendFinished(masterSecret, nextProto): 1014 yield result 1015 for result in self._getFinished(masterSecret, nextProto=nextProto): 1016 yield result 1017 yield masterSecret 1018 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 "\ 1025 "certificates"): 1026 yield result 1027 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)): 1033 yield result 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)): 1037 yield result 1038 1039 # If there's no TLS Extension, look for a TACK cert 1040 if tackpyLoaded: 1041 if not tackExt: 1042 tackExt = certChain.getTackExt() 1043 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"): 1052 yield result 1053 1054 yield publicKey, certChain, tackExt 1055 1056 1057 #********************************************************* 1058 # Server Handshake Functions 1059 #********************************************************* 1060 1061 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 tlsIntolerant=None, signedCertTimestamps=None, 1069 fallbackSCSV=False, ocspResponse=None): 1070 """Perform a handshake in the role of server. 1071 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 1076 handshake. 1077 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. 1085 1086 If the function completes without raising an exception, the 1087 TLS connection will be open and available for data transfer. 1088 1089 If an exception is raised, the connection will have been 1090 automatically closed (if it was ever open). 1091 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. 1096 1097 @type certChain: L{tlslite.x509certchain.X509CertChain} 1098 @param certChain: The certificate chain to be used if the 1099 client requests server certificate authentication. 1100 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. 1104 1105 @type reqCert: bool 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. 1112 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 1117 added to the cache. 1118 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. 1122 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. 1127 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 1131 verification. 1132 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. 1136 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, 1140 if they support it. 1141 1142 @type tlsIntolerant: (int, int) or None 1143 @param tlsIntolerant: If tlsIntolerant is not None, the server will 1144 simulate TLS version intolerance by returning a fatal handshake_failure 1145 alert to all TLS versions tlsIntolerant or higher. 1146 1147 @type signedCertTimestamps: str 1148 @param signedCertTimestamps: A SignedCertificateTimestampList (as a 1149 binary 8-bit string) that will be sent as a TLS extension whenever 1150 the client announces support for the extension. 1151 1152 @type fallbackSCSV: bool 1153 @param fallbackSCSV: if true, the server will implement 1154 TLS_FALLBACK_SCSV and thus reject connections using less than the 1155 server's maximum TLS version that include this cipher suite. 1156 1157 @type ocspResponse: str 1158 @param ocspResponse: An OCSP response (as a binary 8-bit string) that 1159 will be sent stapled in the handshake whenever the client announces 1160 support for the status_request extension. 1161 Note that the response is sent independent of the ClientHello 1162 status_request extension contents, and is thus only meant for testing 1163 environments. Real OCSP stapling is more complicated as it requires 1164 choosing a suitable response based on the ClientHello status_request 1165 extension contents. 1166 1167 @raise socket.error: If a socket error occurs. 1168 @raise tlslite.errors.TLSAbruptCloseError: If the socket is closed 1169 without a preceding alert. 1170 @raise tlslite.errors.TLSAlert: If a TLS alert is signalled. 1171 @raise tlslite.errors.TLSAuthenticationError: If the checker 1172 doesn't like the other party's authentication credentials. 1173 """ 1174 for result in self.handshakeServerAsync(verifierDB, 1175 certChain, privateKey, reqCert, sessionCache, settings, 1176 checker, reqCAs, reqCertTypes, 1177 tacks=tacks, activationFlags=activationFlags, 1178 nextProtos=nextProtos, anon=anon, tlsIntolerant=tlsIntolerant, 1179 signedCertTimestamps=signedCertTimestamps, 1180 fallbackSCSV=fallbackSCSV, ocspResponse=ocspResponse): 1181 pass 1182 1183 1184 def handshakeServerAsync(self, verifierDB=None, 1185 certChain=None, privateKey=None, reqCert=False, 1186 sessionCache=None, settings=None, checker=None, 1187 reqCAs=None, reqCertTypes=None, 1188 tacks=None, activationFlags=0, 1189 nextProtos=None, anon=False, 1190 tlsIntolerant=None, 1191 signedCertTimestamps=None, 1192 fallbackSCSV=False, 1193 ocspResponse=None 1194 ): 1195 """Start a server handshake operation on the TLS connection. 1196 1197 This function returns a generator which behaves similarly to 1198 handshakeServer(). Successive invocations of the generator 1199 will return 0 if it is waiting to read from the socket, 1 if it is 1200 waiting to write to the socket, or it will raise StopIteration 1201 if the handshake operation is complete. 1202 1203 @rtype: iterable 1204 @return: A generator; see above for details. 1205 """ 1206 handshaker = self._handshakeServerAsyncHelper(\ 1207 verifierDB=verifierDB, certChain=certChain, 1208 privateKey=privateKey, reqCert=reqCert, 1209 sessionCache=sessionCache, settings=settings, 1210 reqCAs=reqCAs, reqCertTypes=reqCertTypes, 1211 tacks=tacks, activationFlags=activationFlags, 1212 nextProtos=nextProtos, anon=anon, 1213 tlsIntolerant=tlsIntolerant, 1214 signedCertTimestamps=signedCertTimestamps, 1215 fallbackSCSV=fallbackSCSV, 1216 ocspResponse=ocspResponse) 1217 for result in self._handshakeWrapperAsync(handshaker, checker): 1218 yield result 1219 1220 1221 def _handshakeServerAsyncHelper(self, verifierDB, 1222 certChain, privateKey, reqCert, sessionCache, 1223 settings, reqCAs, reqCertTypes, 1224 tacks, activationFlags, 1225 nextProtos, anon, 1226 tlsIntolerant, signedCertTimestamps, fallbackSCSV, 1227 ocspResponse): 1228 1229 self._handshakeStart(client=False) 1230 1231 if (not verifierDB) and (not certChain) and not anon: 1232 raise ValueError("Caller passed no authentication credentials") 1233 if certChain and not privateKey: 1234 raise ValueError("Caller passed a certChain but no privateKey") 1235 if privateKey and not certChain: 1236 raise ValueError("Caller passed a privateKey but no certChain") 1237 if reqCAs and not reqCert: 1238 raise ValueError("Caller passed reqCAs but not reqCert") 1239 if reqCertTypes and not reqCert: 1240 raise ValueError("Caller passed reqCertTypes but not reqCert") 1241 if certChain and not isinstance(certChain, X509CertChain): 1242 raise ValueError("Unrecognized certificate type") 1243 if activationFlags and not tacks: 1244 raise ValueError("Nonzero activationFlags requires tacks") 1245 if tacks: 1246 if not tackpyLoaded: 1247 raise ValueError("tackpy is not loaded") 1248 if not settings or not settings.useExperimentalTackExtension: 1249 raise ValueError("useExperimentalTackExtension not enabled") 1250 if signedCertTimestamps and not certChain: 1251 raise ValueError("Caller passed signedCertTimestamps but no " 1252 "certChain") 1253 1254 if not settings: 1255 settings = HandshakeSettings() 1256 settings = settings._filter() 1257 1258 # OK Start exchanging messages 1259 # ****************************** 1260 1261 # Handle ClientHello and resumption 1262 for result in self._serverGetClientHello(settings, certChain,\ 1263 verifierDB, sessionCache, 1264 anon, tlsIntolerant, fallbackSCSV): 1265 if result in (0,1): yield result 1266 elif result == None: 1267 self._handshakeDone(resumed=True) 1268 return # Handshake was resumed, we're done 1269 else: break 1270 (clientHello, cipherSuite) = result 1271 1272 #If not a resumption... 1273 1274 # Create the ServerHello message 1275 if sessionCache: 1276 sessionID = getRandomBytes(32) 1277 else: 1278 sessionID = bytearray(0) 1279 1280 if not clientHello.supports_npn: 1281 nextProtos = None 1282 1283 # If not doing a certificate-based suite, discard the TACK 1284 if not cipherSuite in CipherSuite.certAllSuites: 1285 tacks = None 1286 1287 # Prepare a TACK Extension if requested 1288 if clientHello.tack: 1289 tackExt = TackExtension.create(tacks, activationFlags) 1290 else: 1291 tackExt = None 1292 serverHello = ServerHello() 1293 serverHello.create(self.version, getRandomBytes(32), sessionID, \ 1294 cipherSuite, CertificateType.x509, tackExt, 1295 nextProtos) 1296 serverHello.channel_id = clientHello.channel_id 1297 if clientHello.support_signed_cert_timestamps: 1298 serverHello.signed_cert_timestamps = signedCertTimestamps 1299 if clientHello.status_request: 1300 serverHello.status_request = ocspResponse 1301 1302 # Perform the SRP key exchange 1303 clientCertChain = None 1304 if cipherSuite in CipherSuite.srpAllSuites: 1305 for result in self._serverSRPKeyExchange(clientHello, serverHello, 1306 verifierDB, cipherSuite, 1307 privateKey, certChain): 1308 if result in (0,1): yield result 1309 else: break 1310 premasterSecret = result 1311 1312 # Perform the RSA or DHE_RSA key exchange 1313 elif (cipherSuite in CipherSuite.certSuites or 1314 cipherSuite in CipherSuite.dheCertSuites): 1315 if cipherSuite in CipherSuite.certSuites: 1316 keyExchange = RSAKeyExchange(cipherSuite, 1317 clientHello, 1318 serverHello, 1319 privateKey) 1320 elif cipherSuite in CipherSuite.dheCertSuites: 1321 keyExchange = DHE_RSAKeyExchange(cipherSuite, 1322 clientHello, 1323 serverHello, 1324 privateKey) 1325 else: 1326 assert(False) 1327 for result in self._serverCertKeyExchange(clientHello, serverHello, 1328 certChain, keyExchange, 1329 reqCert, reqCAs, reqCertTypes, cipherSuite, 1330 settings, ocspResponse): 1331 if result in (0,1): yield result 1332 else: break 1333 (premasterSecret, clientCertChain) = result 1334 1335 # Perform anonymous Diffie Hellman key exchange 1336 elif cipherSuite in CipherSuite.anonSuites: 1337 for result in self._serverAnonKeyExchange(clientHello, serverHello, 1338 cipherSuite, settings): 1339 if result in (0,1): yield result 1340 else: break 1341 premasterSecret = result 1342 1343 else: 1344 assert(False) 1345 1346 # Exchange Finished messages 1347 for result in self._serverFinished(premasterSecret, 1348 clientHello.random, serverHello.random, 1349 cipherSuite, settings.cipherImplementations, 1350 nextProtos, clientHello.channel_id): 1351 if result in (0,1): yield result 1352 else: break 1353 masterSecret = result 1354 1355 #Create the session object 1356 self.session = Session() 1357 if cipherSuite in CipherSuite.certAllSuites: 1358 serverCertChain = certChain 1359 else: 1360 serverCertChain = None 1361 srpUsername = None 1362 serverName = None 1363 if clientHello.srp_username: 1364 srpUsername = clientHello.srp_username.decode("utf-8") 1365 if clientHello.server_name: 1366 serverName = clientHello.server_name.decode("utf-8") 1367 self.session.create(masterSecret, serverHello.session_id, cipherSuite, 1368 srpUsername, clientCertChain, serverCertChain, 1369 tackExt, serverHello.tackExt!=None, serverName) 1370 1371 #Add the session object to the session cache 1372 if sessionCache and sessionID: 1373 sessionCache[sessionID] = self.session 1374 1375 self._handshakeDone(resumed=False) 1376 1377 1378 def _serverGetClientHello(self, settings, certChain, verifierDB, 1379 sessionCache, anon, tlsIntolerant, fallbackSCSV): 1380 #Initialize acceptable cipher suites 1381 cipherSuites = [] 1382 if verifierDB: 1383 if certChain: 1384 cipherSuites += \ 1385 CipherSuite.getSrpCertSuites(settings) 1386 cipherSuites += CipherSuite.getSrpSuites(settings) 1387 elif certChain: 1388 cipherSuites += CipherSuite.getCertSuites(settings) 1389 cipherSuites += CipherSuite.getDheCertSuites(settings) 1390 elif anon: 1391 cipherSuites += CipherSuite.getAnonSuites(settings) 1392 else: 1393 assert(False) 1394 1395 #Tentatively set version to most-desirable version, so if an error 1396 #occurs parsing the ClientHello, this is what we'll use for the 1397 #error alert 1398 self.version = settings.maxVersion 1399 1400 #Get ClientHello 1401 for result in self._getMsg(ContentType.handshake, 1402 HandshakeType.client_hello): 1403 if result in (0,1): yield result 1404 else: break 1405 clientHello = result 1406 1407 #If client's version is too low, reject it 1408 if clientHello.client_version < settings.minVersion: 1409 self.version = settings.minVersion 1410 for result in self._sendError(\ 1411 AlertDescription.protocol_version, 1412 "Too old version: %s" % str(clientHello.client_version)): 1413 yield result 1414 1415 #If simulating TLS intolerance, reject certain TLS versions. 1416 elif (tlsIntolerant is not None and 1417 clientHello.client_version >= tlsIntolerant): 1418 for result in self._sendError(\ 1419 AlertDescription.handshake_failure): 1420 yield result 1421 1422 #If client's version is too high, propose my highest version 1423 elif clientHello.client_version > settings.maxVersion: 1424 self.version = settings.maxVersion 1425 1426 #Detect if the client performed an inappropriate fallback. 1427 elif fallbackSCSV and clientHello.client_version < settings.maxVersion: 1428 if CipherSuite.TLS_FALLBACK_SCSV in clientHello.cipher_suites: 1429 for result in self._sendError(\ 1430 AlertDescription.inappropriate_fallback): 1431 yield result 1432 1433 else: 1434 #Set the version to the client's version 1435 self.version = clientHello.client_version 1436 1437 #If resumption was requested and we have a session cache... 1438 if clientHello.session_id and sessionCache: 1439 session = None 1440 1441 #Check in the session cache 1442 if sessionCache and not session: 1443 try: 1444 session = sessionCache[clientHello.session_id] 1445 if not session.resumable: 1446 raise AssertionError() 1447 #Check for consistency with ClientHello 1448 if session.cipherSuite not in cipherSuites: 1449 for result in self._sendError(\ 1450 AlertDescription.handshake_failure): 1451 yield result 1452 if session.cipherSuite not in clientHello.cipher_suites: 1453 for result in self._sendError(\ 1454 AlertDescription.handshake_failure): 1455 yield result 1456 if clientHello.srp_username: 1457 if not session.srpUsername or \ 1458 clientHello.srp_username != bytearray(session.srpUsername, "utf-8"): 1459 for result in self._sendError(\ 1460 AlertDescription.handshake_failure): 1461 yield result 1462 if clientHello.server_name: 1463 if not session.serverName or \ 1464 clientHello.server_name != bytearray(session.serverName, "utf-8"): 1465 for result in self._sendError(\ 1466 AlertDescription.handshake_failure): 1467 yield result 1468 except KeyError: 1469 pass 1470 1471 #If a session is found.. 1472 if session: 1473 #Send ServerHello 1474 serverHello = ServerHello() 1475 serverHello.create(self.version, getRandomBytes(32), 1476 session.sessionID, session.cipherSuite, 1477 CertificateType.x509, None, None) 1478 for result in self._sendMsg(serverHello): 1479 yield result 1480 1481 #From here on, the client's messages must have right version 1482 self._versionCheck = True 1483 1484 #Calculate pending connection states 1485 self._calcPendingStates(session.cipherSuite, 1486 session.masterSecret, 1487 clientHello.random, 1488 serverHello.random, 1489 settings.cipherImplementations) 1490 1491 #Exchange ChangeCipherSpec and Finished messages 1492 for result in self._sendFinished(session.masterSecret): 1493 yield result 1494 for result in self._getFinished(session.masterSecret): 1495 yield result 1496 1497 #Set the session 1498 self.session = session 1499 1500 yield None # Handshake done! 1501 1502 #Calculate the first cipher suite intersection. 1503 #This is the 'privileged' ciphersuite. We'll use it if we're 1504 #doing a new negotiation. In fact, 1505 #the only time we won't use it is if we're resuming a 1506 #session, in which case we use the ciphersuite from the session. 1507 # 1508 #Use the client's preferences for now. 1509 for cipherSuite in clientHello.cipher_suites: 1510 if cipherSuite in cipherSuites: 1511 break 1512 else: 1513 for result in self._sendError(\ 1514 AlertDescription.handshake_failure, 1515 "No mutual ciphersuite"): 1516 yield result 1517 if cipherSuite in CipherSuite.srpAllSuites and \ 1518 not clientHello.srp_username: 1519 for result in self._sendError(\ 1520 AlertDescription.unknown_psk_identity, 1521 "Client sent a hello, but without the SRP username"): 1522 yield result 1523 1524 #If an RSA suite is chosen, check for certificate type intersection 1525 if cipherSuite in CipherSuite.certAllSuites and CertificateType.x509 \ 1526 not in clientHello.certificate_types: 1527 for result in self._sendError(\ 1528 AlertDescription.handshake_failure, 1529 "the client doesn't support my certificate type"): 1530 yield result 1531 1532 # If resumption was not requested, or 1533 # we have no session cache, or 1534 # the client's session_id was not found in cache: 1535 yield (clientHello, cipherSuite) 1536 1537 def _serverSRPKeyExchange(self, clientHello, serverHello, verifierDB, 1538 cipherSuite, privateKey, serverCertChain): 1539 1540 srpUsername = clientHello.srp_username.decode("utf-8") 1541 self.allegedSrpUsername = srpUsername 1542 #Get parameters from username 1543 try: 1544 entry = verifierDB[srpUsername] 1545 except KeyError: 1546 for result in self._sendError(\ 1547 AlertDescription.unknown_psk_identity): 1548 yield result 1549 (N, g, s, v) = entry 1550 1551 #Calculate server's ephemeral DH values (b, B) 1552 b = bytesToNumber(getRandomBytes(32)) 1553 k = makeK(N, g) 1554 B = (powMod(g, b, N) + (k*v)) % N 1555 1556 #Create ServerKeyExchange, signing it if necessary 1557 serverKeyExchange = ServerKeyExchange(cipherSuite) 1558 serverKeyExchange.createSRP(N, g, s, B) 1559 if cipherSuite in CipherSuite.srpCertSuites: 1560 hashBytes = serverKeyExchange.hash(clientHello.random, 1561 serverHello.random) 1562 serverKeyExchange.signature = privateKey.sign(hashBytes) 1563 1564 #Send ServerHello[, Certificate], ServerKeyExchange, 1565 #ServerHelloDone 1566 msgs = [] 1567 msgs.append(serverHello) 1568 if cipherSuite in CipherSuite.srpCertSuites: 1569 certificateMsg = Certificate(CertificateType.x509) 1570 certificateMsg.create(serverCertChain) 1571 msgs.append(certificateMsg) 1572 msgs.append(serverKeyExchange) 1573 msgs.append(ServerHelloDone()) 1574 for result in self._sendMsgs(msgs): 1575 yield result 1576 1577 #From here on, the client's messages must have the right version 1578 self._versionCheck = True 1579 1580 #Get and check ClientKeyExchange 1581 for result in self._getMsg(ContentType.handshake, 1582 HandshakeType.client_key_exchange, 1583 cipherSuite): 1584 if result in (0,1): yield result 1585 else: break 1586 clientKeyExchange = result 1587 A = clientKeyExchange.srp_A 1588 if A % N == 0: 1589 for result in self._sendError(AlertDescription.illegal_parameter, 1590 "Suspicious A value"): 1591 yield result 1592 assert(False) # Just to ensure we don't fall through somehow 1593 1594 #Calculate u 1595 u = makeU(N, A, B) 1596 1597 #Calculate premaster secret 1598 S = powMod((A * powMod(v,u,N)) % N, b, N) 1599 premasterSecret = numberToByteArray(S) 1600 1601 yield premasterSecret 1602 1603 1604 def _serverCertKeyExchange(self, clientHello, serverHello, 1605 serverCertChain, keyExchange, 1606 reqCert, reqCAs, reqCertTypes, cipherSuite, 1607 settings, ocspResponse): 1608 #Send ServerHello, Certificate[, ServerKeyExchange] 1609 #[, CertificateRequest], ServerHelloDone 1610 msgs = [] 1611 1612 # If we verify a client cert chain, return it 1613 clientCertChain = None 1614 1615 msgs.append(serverHello) 1616 msgs.append(Certificate(CertificateType.x509).create(serverCertChain)) 1617 if serverHello.status_request: 1618 msgs.append(CertificateStatus().create(ocspResponse)) 1619 serverKeyExchange = keyExchange.makeServerKeyExchange() 1620 if serverKeyExchange is not None: 1621 msgs.append(serverKeyExchange) 1622 if reqCert: 1623 reqCAs = reqCAs or [] 1624 #Apple's Secure Transport library rejects empty certificate_types, 1625 #so default to rsa_sign. 1626 reqCertTypes = reqCertTypes or [ClientCertificateType.rsa_sign] 1627 msgs.append(CertificateRequest().create(reqCertTypes, reqCAs)) 1628 msgs.append(ServerHelloDone()) 1629 for result in self._sendMsgs(msgs): 1630 yield result 1631 1632 #From here on, the client's messages must have the right version 1633 self._versionCheck = True 1634 1635 #Get [Certificate,] (if was requested) 1636 if reqCert: 1637 if self.version == (3,0): 1638 for result in self._getMsg((ContentType.handshake, 1639 ContentType.alert), 1640 HandshakeType.certificate, 1641 CertificateType.x509): 1642 if result in (0,1): yield result 1643 else: break 1644 msg = result 1645 1646 if isinstance(msg, Alert): 1647 #If it's not a no_certificate alert, re-raise 1648 alert = msg 1649 if alert.description != \ 1650 AlertDescription.no_certificate: 1651 self._shutdown(False) 1652 raise TLSRemoteAlert(alert) 1653 elif isinstance(msg, Certificate): 1654 clientCertificate = msg 1655 if clientCertificate.certChain and \ 1656 clientCertificate.certChain.getNumCerts()!=0: 1657 clientCertChain = clientCertificate.certChain 1658 else: 1659 raise AssertionError() 1660 elif self.version in ((3,1), (3,2)): 1661 for result in self._getMsg(ContentType.handshake, 1662 HandshakeType.certificate, 1663 CertificateType.x509): 1664 if result in (0,1): yield result 1665 else: break 1666 clientCertificate = result 1667 if clientCertificate.certChain and \ 1668 clientCertificate.certChain.getNumCerts()!=0: 1669 clientCertChain = clientCertificate.certChain 1670 else: 1671 raise AssertionError() 1672 1673 #Get ClientKeyExchange 1674 for result in self._getMsg(ContentType.handshake, 1675 HandshakeType.client_key_exchange, 1676 cipherSuite): 1677 if result in (0,1): yield result 1678 else: break 1679 clientKeyExchange = result 1680 1681 #Process ClientKeyExchange 1682 try: 1683 premasterSecret = \ 1684 keyExchange.processClientKeyExchange(clientKeyExchange) 1685 except TLSLocalAlert, alert: 1686 for result in self._sendError(alert.description, alert.message): 1687 yield result 1688 1689 #Get and check CertificateVerify, if relevant 1690 if clientCertChain: 1691 if self.version == (3,0): 1692 masterSecret = calcMasterSecret(self.version, premasterSecret, 1693 clientHello.random, serverHello.random) 1694 verifyBytes = self._calcSSLHandshakeHash(masterSecret, b"") 1695 elif self.version in ((3,1), (3,2)): 1696 verifyBytes = self._handshake_md5.digest() + \ 1697 self._handshake_sha.digest() 1698 for result in self._getMsg(ContentType.handshake, 1699 HandshakeType.certificate_verify): 1700 if result in (0,1): yield result 1701 else: break 1702 certificateVerify = result 1703 publicKey = clientCertChain.getEndEntityPublicKey() 1704 if len(publicKey) < settings.minKeySize: 1705 for result in self._sendError(\ 1706 AlertDescription.handshake_failure, 1707 "Client's public key too small: %d" % len(publicKey)): 1708 yield result 1709 1710 if len(publicKey) > settings.maxKeySize: 1711 for result in self._sendError(\ 1712 AlertDescription.handshake_failure, 1713 "Client's public key too large: %d" % len(publicKey)): 1714 yield result 1715 1716 if not publicKey.verify(certificateVerify.signature, verifyBytes): 1717 for result in self._sendError(\ 1718 AlertDescription.decrypt_error, 1719 "Signature failed to verify"): 1720 yield result 1721 yield (premasterSecret, clientCertChain) 1722 1723 1724 def _serverAnonKeyExchange(self, clientHello, serverHello, cipherSuite, 1725 settings): 1726 # Calculate DH p, g, Xs, Ys 1727 dh_p = getRandomSafePrime(32, False) 1728 dh_g = getRandomNumber(2, dh_p) 1729 dh_Xs = bytesToNumber(getRandomBytes(32)) 1730 dh_Ys = powMod(dh_g, dh_Xs, dh_p) 1731 1732 #Create ServerKeyExchange 1733 serverKeyExchange = ServerKeyExchange(cipherSuite) 1734 serverKeyExchange.createDH(dh_p, dh_g, dh_Ys) 1735 1736 #Send ServerHello[, Certificate], ServerKeyExchange, 1737 #ServerHelloDone 1738 msgs = [] 1739 msgs.append(serverHello) 1740 msgs.append(serverKeyExchange) 1741 msgs.append(ServerHelloDone()) 1742 for result in self._sendMsgs(msgs): 1743 yield result 1744 1745 #From here on, the client's messages must have the right version 1746 self._versionCheck = True 1747 1748 #Get and check ClientKeyExchange 1749 for result in self._getMsg(ContentType.handshake, 1750 HandshakeType.client_key_exchange, 1751 cipherSuite): 1752 if result in (0,1): 1753 yield result 1754 else: 1755 break 1756 clientKeyExchange = result 1757 dh_Yc = clientKeyExchange.dh_Yc 1758 1759 if dh_Yc % dh_p == 0: 1760 for result in self._sendError(AlertDescription.illegal_parameter, 1761 "Suspicious dh_Yc value"): 1762 yield result 1763 assert(False) # Just to ensure we don't fall through somehow 1764 1765 #Calculate premaster secre 1766 S = powMod(dh_Yc,dh_Xs,dh_p) 1767 premasterSecret = numberToByteArray(S) 1768 1769 yield premasterSecret 1770 1771 1772 def _serverFinished(self, premasterSecret, clientRandom, serverRandom, 1773 cipherSuite, cipherImplementations, nextProtos, 1774 doingChannelID): 1775 masterSecret = calcMasterSecret(self.version, premasterSecret, 1776 clientRandom, serverRandom) 1777 1778 #Calculate pending connection states 1779 self._calcPendingStates(cipherSuite, masterSecret, 1780 clientRandom, serverRandom, 1781 cipherImplementations) 1782 1783 #Exchange ChangeCipherSpec and Finished messages 1784 for result in self._getFinished(masterSecret, 1785 expect_next_protocol=nextProtos is not None, 1786 expect_channel_id=doingChannelID): 1787 yield result 1788 1789 for result in self._sendFinished(masterSecret): 1790 yield result 1791 1792 yield masterSecret 1793 1794 1795 #********************************************************* 1796 # Shared Handshake Functions 1797 #********************************************************* 1798 1799 1800 def _sendFinished(self, masterSecret, nextProto=None): 1801 #Send ChangeCipherSpec 1802 for result in self._sendMsg(ChangeCipherSpec()): 1803 yield result 1804 1805 #Switch to pending write state 1806 self._changeWriteState() 1807 1808 if nextProto is not None: 1809 nextProtoMsg = NextProtocol().create(nextProto) 1810 for result in self._sendMsg(nextProtoMsg): 1811 yield result 1812 1813 #Calculate verification data 1814 verifyData = self._calcFinished(masterSecret, True) 1815 if self.fault == Fault.badFinished: 1816 verifyData[0] = (verifyData[0]+1)%256 1817 1818 #Send Finished message under new state 1819 finished = Finished(self.version).create(verifyData) 1820 for result in self._sendMsg(finished): 1821 yield result 1822 1823 def _getFinished(self, masterSecret, expect_next_protocol=False, nextProto=None, 1824 expect_channel_id=False): 1825 #Get and check ChangeCipherSpec 1826 for result in self._getMsg(ContentType.change_cipher_spec): 1827 if result in (0,1): 1828 yield result 1829 changeCipherSpec = result 1830 1831 if changeCipherSpec.type != 1: 1832 for result in self._sendError(AlertDescription.illegal_parameter, 1833 "ChangeCipherSpec type incorrect"): 1834 yield result 1835 1836 #Switch to pending read state 1837 self._changeReadState() 1838 1839 #Server Finish - Are we waiting for a next protocol echo? 1840 if expect_next_protocol: 1841 for result in self._getMsg(ContentType.handshake, HandshakeType.next_protocol): 1842 if result in (0,1): 1843 yield result 1844 if result is None: 1845 for result in self._sendError(AlertDescription.unexpected_message, 1846 "Didn't get NextProtocol message"): 1847 yield result 1848 1849 self.next_proto = result.next_proto 1850 else: 1851 self.next_proto = None 1852 1853 #Client Finish - Only set the next_protocol selected in the connection 1854 if nextProto: 1855 self.next_proto = nextProto 1856 1857 #Server Finish - Are we waiting for a EncryptedExtensions? 1858 if expect_channel_id: 1859 for result in self._getMsg(ContentType.handshake, HandshakeType.encrypted_extensions): 1860 if result in (0,1): 1861 yield result 1862 if result is None: 1863 for result in self._sendError(AlertDescription.unexpected_message, 1864 "Didn't get EncryptedExtensions message"): 1865 yield result 1866 encrypted_extensions = result 1867 self.channel_id = result.channel_id_key 1868 else: 1869 self.channel_id = None 1870 1871 #Calculate verification data 1872 verifyData = self._calcFinished(masterSecret, False) 1873 1874 #Get and check Finished message under new state 1875 for result in self._getMsg(ContentType.handshake, 1876 HandshakeType.finished): 1877 if result in (0,1): 1878 yield result 1879 finished = result 1880 if finished.verify_data != verifyData: 1881 for result in self._sendError(AlertDescription.decrypt_error, 1882 "Finished message is incorrect"): 1883 yield result 1884 1885 def _calcFinished(self, masterSecret, send=True): 1886 if self.version == (3,0): 1887 if (self._client and send) or (not self._client and not send): 1888 senderStr = b"\x43\x4C\x4E\x54" 1889 else: 1890 senderStr = b"\x53\x52\x56\x52" 1891 1892 verifyData = self._calcSSLHandshakeHash(masterSecret, senderStr) 1893 return verifyData 1894 1895 elif self.version in ((3,1), (3,2)): 1896 if (self._client and send) or (not self._client and not send): 1897 label = b"client finished" 1898 else: 1899 label = b"server finished" 1900 1901 handshakeHashes = self._handshake_md5.digest() + \ 1902 self._handshake_sha.digest() 1903 verifyData = PRF(masterSecret, label, handshakeHashes, 12) 1904 return verifyData 1905 else: 1906 raise AssertionError() 1907 1908 1909 def _handshakeWrapperAsync(self, handshaker, checker): 1910 if not self.fault: 1911 try: 1912 for result in handshaker: 1913 yield result 1914 if checker: 1915 try: 1916 checker(self) 1917 except TLSAuthenticationError: 1918 alert = Alert().create(AlertDescription.close_notify, 1919 AlertLevel.fatal) 1920 for result in self._sendMsg(alert): 1921 yield result 1922 raise 1923 except GeneratorExit: 1924 raise 1925 except TLSAlert as alert: 1926 if not self.fault: 1927 raise 1928 if alert.description not in Fault.faultAlerts[self.fault]: 1929 raise TLSFaultError(str(alert)) 1930 else: 1931 pass 1932 except: 1933 self._shutdown(False) 1934 raise 1935