Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 # Authors: | 1 # Authors: |
| 2 # Trevor Perrin | 2 # Trevor Perrin |
| 3 # Google - added reqCAs parameter | 3 # Google - added reqCAs parameter |
| 4 # Google (adapted by Sam Rushing and Marcelo Fernandez) - NPN support | 4 # Google (adapted by Sam Rushing and Marcelo Fernandez) - NPN support |
| 5 # Dimitris Moraitis - Anon ciphersuites | 5 # Dimitris Moraitis - Anon ciphersuites |
| 6 # Martin von Loewis - python 3 port | 6 # Martin von Loewis - python 3 port |
| 7 # Yngve Pettersen (ported by Paul Sokolovsky) - TLS 1.2 | 7 # Yngve Pettersen (ported by Paul Sokolovsky) - TLS 1.2 |
| 8 # | 8 # |
| 9 # See the LICENSE file for legal information regarding use of this file. | 9 # See the LICENSE file for legal information regarding use of this file. |
| 10 | 10 |
| (...skipping 319 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 330 # | 330 # |
| 331 # If 'async' is True, the generator is returned to the caller, | 331 # If 'async' is True, the generator is returned to the caller, |
| 332 # otherwise it is executed to completion here. | 332 # otherwise it is executed to completion here. |
| 333 if async: | 333 if async: |
| 334 return handshaker | 334 return handshaker |
| 335 for result in handshaker: | 335 for result in handshaker: |
| 336 pass | 336 pass |
| 337 | 337 |
| 338 def handshakeClientCert(self, certChain=None, privateKey=None, | 338 def handshakeClientCert(self, certChain=None, privateKey=None, |
| 339 session=None, settings=None, checker=None, | 339 session=None, settings=None, checker=None, |
| 340 nextProtos=None, reqTack=True, serverName="", | 340 alpnProtos=None, nextProtos=None, reqTack=True, |
|
davidben
2016/08/03 23:34:22
Please do move this to the settings object. You wo
Bence
2016/08/04 18:41:45
Done. Also moved nextProtos so that they are toge
| |
| 341 async=False): | 341 serverName="", async=False): |
| 342 """Perform a certificate-based handshake in the role of client. | 342 """Perform a certificate-based handshake in the role of client. |
| 343 | 343 |
| 344 This function performs an SSL or TLS handshake. The server | 344 This function performs an SSL or TLS handshake. The server |
| 345 will authenticate itself using an X.509 certificate | 345 will authenticate itself using an X.509 certificate |
| 346 chain. If the handshake succeeds, the server's certificate | 346 chain. If the handshake succeeds, the server's certificate |
| 347 chain will be stored in the session's serverCertChain attribute. | 347 chain will be stored in the session's serverCertChain attribute. |
| 348 Unless a checker object is passed in, this function does no | 348 Unless a checker object is passed in, this function does no |
| 349 validation or checking of the server's certificate chain. | 349 validation or checking of the server's certificate chain. |
| 350 | 350 |
| 351 If the server requests client authentication, the | 351 If the server requests client authentication, the |
| (...skipping 24 matching lines...) Expand all Loading... | |
| 376 | 376 |
| 377 @type settings: L{tlslite.handshakesettings.HandshakeSettings} | 377 @type settings: L{tlslite.handshakesettings.HandshakeSettings} |
| 378 @param settings: Various settings which can be used to control | 378 @param settings: Various settings which can be used to control |
| 379 the ciphersuites, certificate types, and SSL/TLS versions | 379 the ciphersuites, certificate types, and SSL/TLS versions |
| 380 offered by the client. | 380 offered by the client. |
| 381 | 381 |
| 382 @type checker: L{tlslite.checker.Checker} | 382 @type checker: L{tlslite.checker.Checker} |
| 383 @param checker: A Checker instance. This instance will be | 383 @param checker: A Checker instance. This instance will be |
| 384 invoked to examine the other party's authentication | 384 invoked to examine the other party's authentication |
| 385 credentials, if the handshake completes succesfully. | 385 credentials, if the handshake completes succesfully. |
| 386 | |
| 387 @type alpnProtos: list of strings. | |
| 388 @param alpnProtos: A list of upper layer protocols ordered by | |
| 389 preference, to advertise in the Application-Layer Protocol Negotiation | |
| 390 Extension (RFC 7301). | |
| 386 | 391 |
| 387 @type nextProtos: list of strings. | 392 @type nextProtos: list of strings. |
| 388 @param nextProtos: A list of upper layer protocols ordered by | 393 @param nextProtos: A list of upper layer protocols ordered by |
| 389 preference, to use in the Next-Protocol Negotiation Extension. | 394 preference, to use in the Next-Protocol Negotiation Extension. |
| 390 | 395 |
| 391 @type reqTack: bool | 396 @type reqTack: bool |
| 392 @param reqTack: Whether or not to send a "tack" TLS Extension, | 397 @param reqTack: Whether or not to send a "tack" TLS Extension, |
| 393 requesting the server return a TackExtension if it has one. | 398 requesting the server return a TackExtension if it has one. |
| 394 | 399 |
| 395 @type serverName: string | 400 @type serverName: string |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 410 @raise socket.error: If a socket error occurs. | 415 @raise socket.error: If a socket error occurs. |
| 411 @raise tlslite.errors.TLSAbruptCloseError: If the socket is closed | 416 @raise tlslite.errors.TLSAbruptCloseError: If the socket is closed |
| 412 without a preceding alert. | 417 without a preceding alert. |
| 413 @raise tlslite.errors.TLSAlert: If a TLS alert is signalled. | 418 @raise tlslite.errors.TLSAlert: If a TLS alert is signalled. |
| 414 @raise tlslite.errors.TLSAuthenticationError: If the checker | 419 @raise tlslite.errors.TLSAuthenticationError: If the checker |
| 415 doesn't like the other party's authentication credentials. | 420 doesn't like the other party's authentication credentials. |
| 416 """ | 421 """ |
| 417 handshaker = self._handshakeClientAsync(certParams=(certChain, | 422 handshaker = self._handshakeClientAsync(certParams=(certChain, |
| 418 privateKey), session=session, settings=settings, | 423 privateKey), session=session, settings=settings, |
| 419 checker=checker, serverName=serverName, | 424 checker=checker, serverName=serverName, |
| 420 nextProtos=nextProtos, reqTack=reqTack) | 425 alpnProtos=alpnProtos, nextProtos=nextProtos, |
| 426 reqTack=reqTack) | |
| 421 # The handshaker is a Python Generator which executes the handshake. | 427 # The handshaker is a Python Generator which executes the handshake. |
| 422 # It allows the handshake to be run in a "piecewise", asynchronous | 428 # It allows the handshake to be run in a "piecewise", asynchronous |
| 423 # fashion, returning 1 when it is waiting to able to write, 0 when | 429 # fashion, returning 1 when it is waiting to able to write, 0 when |
| 424 # it is waiting to read. | 430 # it is waiting to read. |
| 425 # | 431 # |
| 426 # If 'async' is True, the generator is returned to the caller, | 432 # If 'async' is True, the generator is returned to the caller, |
| 427 # otherwise it is executed to completion here. | 433 # otherwise it is executed to completion here. |
| 428 if async: | 434 if async: |
| 429 return handshaker | 435 return handshaker |
| 430 for result in handshaker: | 436 for result in handshaker: |
| 431 pass | 437 pass |
| 432 | 438 |
| 433 | 439 |
| 434 def _handshakeClientAsync(self, srpParams=(), certParams=(), anonParams=(), | 440 def _handshakeClientAsync(self, srpParams=(), certParams=(), anonParams=(), |
| 435 session=None, settings=None, checker=None, | 441 session=None, settings=None, checker=None, |
| 436 nextProtos=None, serverName="", reqTack=True): | 442 alpnProtos=None, nextProtos=None, serverName="", |
| 443 reqTack=True): | |
| 437 | 444 |
| 438 handshaker = self._handshakeClientAsyncHelper(srpParams=srpParams, | 445 handshaker = self._handshakeClientAsyncHelper(srpParams=srpParams, |
| 439 certParams=certParams, | 446 certParams=certParams, |
| 440 anonParams=anonParams, | 447 anonParams=anonParams, |
| 441 session=session, | 448 session=session, |
| 442 settings=settings, | 449 settings=settings, |
| 443 serverName=serverName, | 450 serverName=serverName, |
| 451 alpnProtos=alpnProtos, | |
| 444 nextProtos=nextProtos, | 452 nextProtos=nextProtos, |
| 445 reqTack=reqTack) | 453 reqTack=reqTack) |
| 446 for result in self._handshakeWrapperAsync(handshaker, checker): | 454 for result in self._handshakeWrapperAsync(handshaker, checker): |
| 447 yield result | 455 yield result |
| 448 | 456 |
| 449 | 457 |
| 450 def _handshakeClientAsyncHelper(self, srpParams, certParams, anonParams, | 458 def _handshakeClientAsyncHelper(self, srpParams, certParams, anonParams, |
| 451 session, settings, serverName, nextProtos, reqTac k): | 459 session, settings, serverName, alpnProtos, |
| 460 nextProtos, reqTack): | |
| 452 | 461 |
| 453 self._handshakeStart(client=True) | 462 self._handshakeStart(client=True) |
| 454 | 463 |
| 455 #Unpack parameters | 464 #Unpack parameters |
| 456 srpUsername = None # srpParams[0] | 465 srpUsername = None # srpParams[0] |
| 457 password = None # srpParams[1] | 466 password = None # srpParams[1] |
| 458 clientCertChain = None # certParams[0] | 467 clientCertChain = None # certParams[0] |
| 459 privateKey = None # certParams[1] | 468 privateKey = None # certParams[1] |
| 460 | 469 |
| 461 # Allow only one of (srpParams, certParams, anonParams) | 470 # Allow only one of (srpParams, certParams, anonParams) |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 478 raise ValueError("Caller passed a password but no username") | 487 raise ValueError("Caller passed a password but no username") |
| 479 if clientCertChain and not privateKey: | 488 if clientCertChain and not privateKey: |
| 480 raise ValueError("Caller passed a certChain but no privateKey") | 489 raise ValueError("Caller passed a certChain but no privateKey") |
| 481 if privateKey and not clientCertChain: | 490 if privateKey and not clientCertChain: |
| 482 raise ValueError("Caller passed a privateKey but no certChain") | 491 raise ValueError("Caller passed a privateKey but no certChain") |
| 483 if reqTack: | 492 if reqTack: |
| 484 if not tackpyLoaded: | 493 if not tackpyLoaded: |
| 485 reqTack = False | 494 reqTack = False |
| 486 if not settings or not settings.useExperimentalTackExtension: | 495 if not settings or not settings.useExperimentalTackExtension: |
| 487 reqTack = False | 496 reqTack = False |
| 497 if alpnProtos is not None: | |
| 498 if len(alpnProtos) == 0: | |
| 499 raise ValueError("Caller passed no alpnProtos") | |
| 488 if nextProtos is not None: | 500 if nextProtos is not None: |
| 489 if len(nextProtos) == 0: | 501 if len(nextProtos) == 0: |
| 490 raise ValueError("Caller passed no nextProtos") | 502 raise ValueError("Caller passed no nextProtos") |
| 491 | 503 |
| 492 # Validates the settings and filters out any unsupported ciphers | 504 # Validates the settings and filters out any unsupported ciphers |
| 493 # or crypto libraries that were requested | 505 # or crypto libraries that were requested |
| 494 if not settings: | 506 if not settings: |
| 495 settings = HandshakeSettings() | 507 settings = HandshakeSettings() |
| 496 settings = settings._filter() | 508 settings = settings._filter() |
| 497 | 509 |
| (...skipping 25 matching lines...) Expand all Loading... | |
| 523 #We'll use this for the ClientHello, and if an error occurs | 535 #We'll use this for the ClientHello, and if an error occurs |
| 524 #parsing the Server Hello, we'll use this version for the response | 536 #parsing the Server Hello, we'll use this version for the response |
| 525 self.version = settings.maxVersion | 537 self.version = settings.maxVersion |
| 526 | 538 |
| 527 # OK Start sending messages! | 539 # OK Start sending messages! |
| 528 # ***************************** | 540 # ***************************** |
| 529 | 541 |
| 530 # Send the ClientHello. | 542 # Send the ClientHello. |
| 531 for result in self._clientSendClientHello(settings, session, | 543 for result in self._clientSendClientHello(settings, session, |
| 532 srpUsername, srpParams, certParams, | 544 srpUsername, srpParams, certParams, |
| 533 anonParams, serverName, nextProtos, | 545 anonParams, serverName, alpnProtos, |
| 534 reqTack): | 546 nextProtos, reqTack): |
| 535 if result in (0,1): yield result | 547 if result in (0,1): yield result |
| 536 else: break | 548 else: break |
| 537 clientHello = result | 549 clientHello = result |
| 538 | 550 |
| 539 #Get the ServerHello. | 551 #Get the ServerHello. |
| 540 for result in self._clientGetServerHello(settings, clientHello): | 552 for result in self._clientGetServerHello(settings, clientHello): |
| 541 if result in (0,1): yield result | 553 if result in (0,1): yield result |
| 542 else: break | 554 else: break |
| 543 serverHello = result | 555 serverHello = result |
| 544 cipherSuite = serverHello.cipher_suite | 556 cipherSuite = serverHello.cipher_suite |
| 545 | 557 |
| 546 # Choose a matching Next Protocol from server list against ours | 558 #Ignore NPN if server response has ALPN. |
|
davidben
2016/08/03 23:34:22
This isn't right. If the ServerHello contains both
Bence
2016/08/04 18:41:45
Done.
| |
| 547 # (string or None) | 559 if (serverHello.alpn_proto_selected): |
| 548 nextProto = self._clientSelectNextProto(nextProtos, serverHello) | 560 nextProto = None |
| 561 else: | |
| 562 nextProto = self._clientSelectNextProto(nextProtos, serverHello) | |
| 549 | 563 |
| 550 #If the server elected to resume the session, it is handled here. | 564 #If the server elected to resume the session, it is handled here. |
| 551 for result in self._clientResume(session, serverHello, | 565 for result in self._clientResume(session, serverHello, |
| 552 clientHello.random, | 566 clientHello.random, |
| 553 settings.cipherImplementations, | 567 settings.cipherImplementations, |
| 554 nextProto): | 568 nextProto): |
| 555 if result in (0,1): yield result | 569 if result in (0,1): yield result |
| 556 else: break | 570 else: break |
| 557 if result == "resumed_and_finished": | 571 if result == "resumed_and_finished": |
| 558 self._handshakeDone(resumed=True) | 572 self._handshakeDone(resumed=True) |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 614 # Create the session object which is used for resumptions | 628 # Create the session object which is used for resumptions |
| 615 self.session = Session() | 629 self.session = Session() |
| 616 self.session.create(masterSecret, serverHello.session_id, cipherSuite, | 630 self.session.create(masterSecret, serverHello.session_id, cipherSuite, |
| 617 srpUsername, clientCertChain, serverCertChain, | 631 srpUsername, clientCertChain, serverCertChain, |
| 618 tackExt, serverHello.tackExt!=None, serverName) | 632 tackExt, serverHello.tackExt!=None, serverName) |
| 619 self._handshakeDone(resumed=False) | 633 self._handshakeDone(resumed=False) |
| 620 | 634 |
| 621 | 635 |
| 622 def _clientSendClientHello(self, settings, session, srpUsername, | 636 def _clientSendClientHello(self, settings, session, srpUsername, |
| 623 srpParams, certParams, anonParams, | 637 srpParams, certParams, anonParams, |
| 624 serverName, nextProtos, reqTack): | 638 serverName, alpnProtos, nextProtos, reqTack): |
| 625 #Initialize acceptable ciphersuites | 639 #Initialize acceptable ciphersuites |
| 626 cipherSuites = [CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV] | 640 cipherSuites = [CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV] |
| 627 if srpParams: | 641 if srpParams: |
| 628 cipherSuites += CipherSuite.getSrpAllSuites(settings) | 642 cipherSuites += CipherSuite.getSrpAllSuites(settings) |
| 629 elif certParams: | 643 elif certParams: |
| 630 # TODO: Client DHE_RSA not supported. | 644 # TODO: Client DHE_RSA not supported. |
| 631 # cipherSuites += CipherSuite.getDheCertSuites(settings) | 645 # cipherSuites += CipherSuite.getDheCertSuites(settings) |
| 632 cipherSuites += CipherSuite.getCertSuites(settings) | 646 cipherSuites += CipherSuite.getCertSuites(settings) |
| 633 elif anonParams: | 647 elif anonParams: |
| 634 cipherSuites += CipherSuite.getAnonSuites(settings) | 648 cipherSuites += CipherSuite.getAnonSuites(settings) |
| 635 else: | 649 else: |
| 636 assert(False) | 650 assert(False) |
| 637 | 651 |
| 638 #Initialize acceptable certificate types | 652 #Initialize acceptable certificate types |
| 639 certificateTypes = settings._getCertificateTypes() | 653 certificateTypes = settings._getCertificateTypes() |
| 640 | 654 |
| 641 #Either send ClientHello (with a resumable session)... | 655 #Either send ClientHello (with a resumable session)... |
| 642 if session and session.sessionID: | 656 if session and session.sessionID: |
| 643 #If it's resumable, then its | 657 #If it's resumable, then its |
| 644 #ciphersuite must be one of the acceptable ciphersuites | 658 #ciphersuite must be one of the acceptable ciphersuites |
| 645 if session.cipherSuite not in cipherSuites: | 659 if session.cipherSuite not in cipherSuites: |
| 646 raise ValueError("Session's cipher suite not consistent "\ | 660 raise ValueError("Session's cipher suite not consistent "\ |
| 647 "with parameters") | 661 "with parameters") |
| 648 else: | 662 else: |
| 649 clientHello = ClientHello() | 663 clientHello = ClientHello() |
| 650 clientHello.create(settings.maxVersion, getRandomBytes(32), | 664 clientHello.create(settings.maxVersion, getRandomBytes(32), |
| 651 session.sessionID, cipherSuites, | 665 session.sessionID, cipherSuites, |
| 652 certificateTypes, | 666 certificateTypes, |
| 653 session.srpUsername, | 667 session.srpUsername, |
| 654 reqTack, nextProtos is not None, | 668 reqTack, alpnProtos, nextProtos is not None, |
| 655 session.serverName) | 669 session.serverName) |
| 656 | 670 |
| 657 #Or send ClientHello (without) | 671 #Or send ClientHello (without) |
| 658 else: | 672 else: |
| 659 clientHello = ClientHello() | 673 clientHello = ClientHello() |
| 660 clientHello.create(settings.maxVersion, getRandomBytes(32), | 674 clientHello.create(settings.maxVersion, getRandomBytes(32), |
| 661 bytearray(0), cipherSuites, | 675 bytearray(0), cipherSuites, |
| 662 certificateTypes, | 676 certificateTypes, |
| 663 srpUsername, | 677 srpUsername, |
| 664 reqTack, nextProtos is not None, | 678 reqTack, alpnProtos, nextProtos is not None, |
| 665 serverName) | 679 serverName) |
| 666 for result in self._sendMsg(clientHello): | 680 for result in self._sendMsg(clientHello): |
| 667 yield result | 681 yield result |
| 668 yield clientHello | 682 yield clientHello |
| 669 | 683 |
| 670 | 684 |
| 671 def _clientGetServerHello(self, settings, clientHello): | 685 def _clientGetServerHello(self, settings, clientHello): |
| 672 for result in self._getMsg(ContentType.handshake, | 686 for result in self._getMsg(ContentType.handshake, |
| 673 HandshakeType.server_hello): | 687 HandshakeType.server_hello): |
| 674 if result in (0,1): yield result | 688 if result in (0,1): yield result |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 707 for result in self._sendError(\ | 721 for result in self._sendError(\ |
| 708 AlertDescription.illegal_parameter, | 722 AlertDescription.illegal_parameter, |
| 709 "Server responded with incorrect compression method"): | 723 "Server responded with incorrect compression method"): |
| 710 yield result | 724 yield result |
| 711 if serverHello.tackExt: | 725 if serverHello.tackExt: |
| 712 if not clientHello.tack: | 726 if not clientHello.tack: |
| 713 for result in self._sendError(\ | 727 for result in self._sendError(\ |
| 714 AlertDescription.illegal_parameter, | 728 AlertDescription.illegal_parameter, |
| 715 "Server responded with unrequested Tack Extension"): | 729 "Server responded with unrequested Tack Extension"): |
| 716 yield result | 730 yield result |
| 731 if serverHello.alpn_proto_selected and not clientHello.alpn_protos_adver tised: | |
| 732 for result in self._sendError(\ | |
| 733 AlertDescription.illegal_parameter, | |
| 734 "Server responded with unrequested ALPN Extension"): | |
| 735 yield result | |
|
davidben
2016/08/03 23:34:22
Add a check that ALPN + NPN in a ServerHello is il
Bence
2016/08/04 18:41:45
Done.
| |
| 717 if serverHello.next_protos and not clientHello.supports_npn: | 736 if serverHello.next_protos and not clientHello.supports_npn: |
| 718 for result in self._sendError(\ | 737 for result in self._sendError(\ |
| 719 AlertDescription.illegal_parameter, | 738 AlertDescription.illegal_parameter, |
| 720 "Server responded with unrequested NPN Extension"): | 739 "Server responded with unrequested NPN Extension"): |
| 721 yield result | 740 yield result |
| 722 if not serverHello.tackExt.verifySignatures(): | 741 if not serverHello.tackExt.verifySignatures(): |
| 723 for result in self._sendError(\ | 742 for result in self._sendError(\ |
| 724 AlertDescription.decrypt_error, | 743 AlertDescription.decrypt_error, |
| 725 "TackExtension contains an invalid signature"): | 744 "TackExtension contains an invalid signature"): |
| 726 yield result | 745 yield result |
| (...skipping 368 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1095 #********************************************************* | 1114 #********************************************************* |
| 1096 # Server Handshake Functions | 1115 # Server Handshake Functions |
| 1097 #********************************************************* | 1116 #********************************************************* |
| 1098 | 1117 |
| 1099 | 1118 |
| 1100 def handshakeServer(self, verifierDB=None, | 1119 def handshakeServer(self, verifierDB=None, |
| 1101 certChain=None, privateKey=None, reqCert=False, | 1120 certChain=None, privateKey=None, reqCert=False, |
| 1102 sessionCache=None, settings=None, checker=None, | 1121 sessionCache=None, settings=None, checker=None, |
| 1103 reqCAs = None, reqCertTypes = None, | 1122 reqCAs = None, reqCertTypes = None, |
| 1104 tacks=None, activationFlags=0, | 1123 tacks=None, activationFlags=0, |
| 1105 nextProtos=None, anon=False, | 1124 alpnProtos=None, nextProtos=None, anon=False, |
| 1106 signedCertTimestamps=None, | 1125 signedCertTimestamps=None, |
| 1107 fallbackSCSV=False, ocspResponse=None): | 1126 fallbackSCSV=False, ocspResponse=None): |
| 1108 """Perform a handshake in the role of server. | 1127 """Perform a handshake in the role of server. |
| 1109 | 1128 |
| 1110 This function performs an SSL or TLS handshake. Depending on | 1129 This function performs an SSL or TLS handshake. Depending on |
| 1111 the arguments and the behavior of the client, this function can | 1130 the arguments and the behavior of the client, this function can |
| 1112 perform an SRP, or certificate-based handshake. It | 1131 perform an SRP, or certificate-based handshake. It |
| 1113 can also perform a combined SRP and server-certificate | 1132 can also perform a combined SRP and server-certificate |
| 1114 handshake. | 1133 handshake. |
| 1115 | 1134 |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1165 | 1184 |
| 1166 @type reqCAs: list of L{bytearray} of unsigned bytes | 1185 @type reqCAs: list of L{bytearray} of unsigned bytes |
| 1167 @param reqCAs: A collection of DER-encoded DistinguishedNames that | 1186 @param reqCAs: A collection of DER-encoded DistinguishedNames that |
| 1168 will be sent along with a certificate request. This does not affect | 1187 will be sent along with a certificate request. This does not affect |
| 1169 verification. | 1188 verification. |
| 1170 | 1189 |
| 1171 @type reqCertTypes: list of int | 1190 @type reqCertTypes: list of int |
| 1172 @param reqCertTypes: A list of certificate_type values to be sent | 1191 @param reqCertTypes: A list of certificate_type values to be sent |
| 1173 along with a certificate request. This does not affect verification. | 1192 along with a certificate request. This does not affect verification. |
| 1174 | 1193 |
| 1194 @type alpnProtos: list of strings. | |
| 1195 @param alpnProtos: A list of upper layer protocols with zero or one | |
| 1196 elements. If not empty, its single element is the protocol negotiated | |
| 1197 via the Application-Layer Protocol Negotiation Extension (RFC 7301). | |
| 1198 | |
| 1175 @type nextProtos: list of strings. | 1199 @type nextProtos: list of strings. |
| 1176 @param nextProtos: A list of upper layer protocols to expose to the | 1200 @param nextProtos: A list of upper layer protocols to expose to the |
| 1177 clients through the Next-Protocol Negotiation Extension, | 1201 clients through the Next-Protocol Negotiation Extension, |
| 1178 if they support it. | 1202 if they support it. |
| 1179 | 1203 |
| 1180 @type signedCertTimestamps: str | 1204 @type signedCertTimestamps: str |
| 1181 @param signedCertTimestamps: A SignedCertificateTimestampList (as a | 1205 @param signedCertTimestamps: A SignedCertificateTimestampList (as a |
| 1182 binary 8-bit string) that will be sent as a TLS extension whenever | 1206 binary 8-bit string) that will be sent as a TLS extension whenever |
| 1183 the client announces support for the extension. | 1207 the client announces support for the extension. |
| 1184 | 1208 |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 1201 @raise tlslite.errors.TLSAbruptCloseError: If the socket is closed | 1225 @raise tlslite.errors.TLSAbruptCloseError: If the socket is closed |
| 1202 without a preceding alert. | 1226 without a preceding alert. |
| 1203 @raise tlslite.errors.TLSAlert: If a TLS alert is signalled. | 1227 @raise tlslite.errors.TLSAlert: If a TLS alert is signalled. |
| 1204 @raise tlslite.errors.TLSAuthenticationError: If the checker | 1228 @raise tlslite.errors.TLSAuthenticationError: If the checker |
| 1205 doesn't like the other party's authentication credentials. | 1229 doesn't like the other party's authentication credentials. |
| 1206 """ | 1230 """ |
| 1207 for result in self.handshakeServerAsync(verifierDB, | 1231 for result in self.handshakeServerAsync(verifierDB, |
| 1208 certChain, privateKey, reqCert, sessionCache, settings, | 1232 certChain, privateKey, reqCert, sessionCache, settings, |
| 1209 checker, reqCAs, reqCertTypes, | 1233 checker, reqCAs, reqCertTypes, |
| 1210 tacks=tacks, activationFlags=activationFlags, | 1234 tacks=tacks, activationFlags=activationFlags, |
| 1211 nextProtos=nextProtos, anon=anon, | 1235 alpnProtos=alpnProtos, nextProtos=nextProtos, anon=anon, |
| 1212 signedCertTimestamps=signedCertTimestamps, | 1236 signedCertTimestamps=signedCertTimestamps, |
| 1213 fallbackSCSV=fallbackSCSV, ocspResponse=ocspResponse): | 1237 fallbackSCSV=fallbackSCSV, ocspResponse=ocspResponse): |
| 1214 pass | 1238 pass |
| 1215 | 1239 |
| 1216 | 1240 |
| 1217 def handshakeServerAsync(self, verifierDB=None, | 1241 def handshakeServerAsync(self, verifierDB=None, |
| 1218 certChain=None, privateKey=None, reqCert=False, | 1242 certChain=None, privateKey=None, reqCert=False, |
| 1219 sessionCache=None, settings=None, checker=None, | 1243 sessionCache=None, settings=None, checker=None, |
| 1220 reqCAs=None, reqCertTypes=None, | 1244 reqCAs=None, reqCertTypes=None, |
| 1221 tacks=None, activationFlags=0, | 1245 tacks=None, activationFlags=0, alpnProtos=None, |
| 1222 nextProtos=None, anon=False, | 1246 nextProtos=None, anon=False, |
| 1223 signedCertTimestamps=None, | 1247 signedCertTimestamps=None, |
| 1224 fallbackSCSV=False, | 1248 fallbackSCSV=False, |
| 1225 ocspResponse=None | 1249 ocspResponse=None |
| 1226 ): | 1250 ): |
| 1227 """Start a server handshake operation on the TLS connection. | 1251 """Start a server handshake operation on the TLS connection. |
| 1228 | 1252 |
| 1229 This function returns a generator which behaves similarly to | 1253 This function returns a generator which behaves similarly to |
| 1230 handshakeServer(). Successive invocations of the generator | 1254 handshakeServer(). Successive invocations of the generator |
| 1231 will return 0 if it is waiting to read from the socket, 1 if it is | 1255 will return 0 if it is waiting to read from the socket, 1 if it is |
| 1232 waiting to write to the socket, or it will raise StopIteration | 1256 waiting to write to the socket, or it will raise StopIteration |
| 1233 if the handshake operation is complete. | 1257 if the handshake operation is complete. |
| 1234 | 1258 |
| 1235 @rtype: iterable | 1259 @rtype: iterable |
| 1236 @return: A generator; see above for details. | 1260 @return: A generator; see above for details. |
| 1237 """ | 1261 """ |
| 1238 handshaker = self._handshakeServerAsyncHelper(\ | 1262 handshaker = self._handshakeServerAsyncHelper(\ |
| 1239 verifierDB=verifierDB, certChain=certChain, | 1263 verifierDB=verifierDB, certChain=certChain, |
| 1240 privateKey=privateKey, reqCert=reqCert, | 1264 privateKey=privateKey, reqCert=reqCert, |
| 1241 sessionCache=sessionCache, settings=settings, | 1265 sessionCache=sessionCache, settings=settings, |
| 1242 reqCAs=reqCAs, reqCertTypes=reqCertTypes, | 1266 reqCAs=reqCAs, reqCertTypes=reqCertTypes, |
| 1243 tacks=tacks, activationFlags=activationFlags, | 1267 tacks=tacks, activationFlags=activationFlags, alpnProtos=alpnProtos, |
| 1244 nextProtos=nextProtos, anon=anon, | 1268 nextProtos=nextProtos, anon=anon, |
| 1245 signedCertTimestamps=signedCertTimestamps, | 1269 signedCertTimestamps=signedCertTimestamps, |
| 1246 fallbackSCSV=fallbackSCSV, | 1270 fallbackSCSV=fallbackSCSV, |
| 1247 ocspResponse=ocspResponse) | 1271 ocspResponse=ocspResponse) |
| 1248 for result in self._handshakeWrapperAsync(handshaker, checker): | 1272 for result in self._handshakeWrapperAsync(handshaker, checker): |
| 1249 yield result | 1273 yield result |
| 1250 if settings and settings.alertAfterHandshake: | 1274 if settings and settings.alertAfterHandshake: |
| 1251 for result in self._sendError(AlertDescription.internal_error, | 1275 for result in self._sendError(AlertDescription.internal_error, |
| 1252 "Spurious alert"): | 1276 "Spurious alert"): |
| 1253 yield result | 1277 yield result |
| 1254 | 1278 |
| 1255 | 1279 |
| 1256 def _handshakeServerAsyncHelper(self, verifierDB, | 1280 def _handshakeServerAsyncHelper(self, verifierDB, |
| 1257 certChain, privateKey, reqCert, sessionCache, | 1281 certChain, privateKey, reqCert, sessionCache, |
| 1258 settings, reqCAs, reqCertTypes, | 1282 settings, reqCAs, reqCertTypes, |
| 1259 tacks, activationFlags, | 1283 tacks, activationFlags, |
| 1260 nextProtos, anon, | 1284 alpnProtos, nextProtos, anon, |
| 1261 signedCertTimestamps, fallbackSCSV, | 1285 signedCertTimestamps, fallbackSCSV, |
| 1262 ocspResponse): | 1286 ocspResponse): |
| 1263 | 1287 |
| 1264 self._handshakeStart(client=False) | 1288 self._handshakeStart(client=False) |
| 1265 | 1289 |
| 1266 if (not verifierDB) and (not certChain) and not anon: | 1290 if (not verifierDB) and (not certChain) and not anon: |
| 1267 raise ValueError("Caller passed no authentication credentials") | 1291 raise ValueError("Caller passed no authentication credentials") |
| 1268 if certChain and not privateKey: | 1292 if certChain and not privateKey: |
| 1269 raise ValueError("Caller passed a certChain but no privateKey") | 1293 raise ValueError("Caller passed a certChain but no privateKey") |
| 1270 if privateKey and not certChain: | 1294 if privateKey and not certChain: |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1307 # Save the ClientHello for external code to query. | 1331 # Save the ClientHello for external code to query. |
| 1308 self.clientHello = clientHello | 1332 self.clientHello = clientHello |
| 1309 | 1333 |
| 1310 #If not a resumption... | 1334 #If not a resumption... |
| 1311 | 1335 |
| 1312 # Create the ServerHello message | 1336 # Create the ServerHello message |
| 1313 if sessionCache: | 1337 if sessionCache: |
| 1314 sessionID = getRandomBytes(32) | 1338 sessionID = getRandomBytes(32) |
| 1315 else: | 1339 else: |
| 1316 sessionID = bytearray(0) | 1340 sessionID = bytearray(0) |
| 1317 | 1341 |
| 1342 alpn_proto_selected = None | |
| 1343 if clientHello.alpn_protos_advertised is not None: | |
| 1344 if alpnProtos is not None: | |
| 1345 for proto in alpnProtos: | |
| 1346 if proto in clientHello.alpn_protos_advertised: | |
| 1347 alpn_proto_selected = proto | |
| 1348 nextProtos = None | |
| 1349 break; | |
| 1350 | |
| 1318 if not clientHello.supports_npn: | 1351 if not clientHello.supports_npn: |
| 1319 nextProtos = None | 1352 nextProtos = None |
| 1320 | 1353 |
| 1321 # If not doing a certificate-based suite, discard the TACK | 1354 # If not doing a certificate-based suite, discard the TACK |
| 1322 if not cipherSuite in CipherSuite.certAllSuites: | 1355 if not cipherSuite in CipherSuite.certAllSuites: |
| 1323 tacks = None | 1356 tacks = None |
| 1324 | 1357 |
| 1325 # Prepare a TACK Extension if requested | 1358 # Prepare a TACK Extension if requested |
| 1326 if clientHello.tack: | 1359 if clientHello.tack: |
| 1327 tackExt = TackExtension.create(tacks, activationFlags) | 1360 tackExt = TackExtension.create(tacks, activationFlags) |
| 1328 else: | 1361 else: |
| 1329 tackExt = None | 1362 tackExt = None |
| 1330 serverHello = ServerHello() | 1363 serverHello = ServerHello() |
| 1331 serverHello.create(self.version, getRandomBytes(32), sessionID, \ | 1364 serverHello.create(self.version, getRandomBytes(32), sessionID, \ |
| 1332 cipherSuite, CertificateType.x509, tackExt, | 1365 cipherSuite, CertificateType.x509, tackExt, |
| 1333 nextProtos) | 1366 alpn_proto_selected, nextProtos) |
| 1334 serverHello.channel_id = \ | 1367 serverHello.channel_id = \ |
| 1335 clientHello.channel_id and settings.enableChannelID | 1368 clientHello.channel_id and settings.enableChannelID |
| 1336 serverHello.extended_master_secret = \ | 1369 serverHello.extended_master_secret = \ |
| 1337 clientHello.extended_master_secret and \ | 1370 clientHello.extended_master_secret and \ |
| 1338 settings.enableExtendedMasterSecret | 1371 settings.enableExtendedMasterSecret |
| 1339 for param in clientHello.tb_client_params: | 1372 for param in clientHello.tb_client_params: |
| 1340 if param in settings.supportedTokenBindingParams: | 1373 if param in settings.supportedTokenBindingParams: |
| 1341 serverHello.tb_params = param | 1374 serverHello.tb_params = param |
| 1342 break | 1375 break |
| 1343 if clientHello.support_signed_cert_timestamps: | 1376 if clientHello.support_signed_cert_timestamps: |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1390 else: break | 1423 else: break |
| 1391 premasterSecret = result | 1424 premasterSecret = result |
| 1392 | 1425 |
| 1393 else: | 1426 else: |
| 1394 assert(False) | 1427 assert(False) |
| 1395 | 1428 |
| 1396 # Exchange Finished messages | 1429 # Exchange Finished messages |
| 1397 for result in self._serverFinished(premasterSecret, | 1430 for result in self._serverFinished(premasterSecret, |
| 1398 clientHello.random, serverHello.random, | 1431 clientHello.random, serverHello.random, |
| 1399 cipherSuite, settings.cipherImplementations, | 1432 cipherSuite, settings.cipherImplementations, |
| 1400 nextProtos, serverHello.channel_id, | 1433 alpnProtos, nextProtos, serverHello.channel_id, |
| 1401 serverHello.extended_master_secret): | 1434 serverHello.extended_master_secret): |
| 1402 if result in (0,1): yield result | 1435 if result in (0,1): yield result |
| 1403 else: break | 1436 else: break |
| 1404 masterSecret = result | 1437 masterSecret = result |
| 1405 | 1438 |
| 1406 self.clientRandom = clientHello.random | 1439 self.clientRandom = clientHello.random |
| 1407 self.serverRandom = serverHello.random | 1440 self.serverRandom = serverHello.random |
| 1408 | 1441 |
| 1409 #Create the session object | 1442 #Create the session object |
| 1410 self.session = Session() | 1443 self.session = Session() |
| (...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1533 yield result | 1566 yield result |
| 1534 except KeyError: | 1567 except KeyError: |
| 1535 pass | 1568 pass |
| 1536 | 1569 |
| 1537 #If a session is found.. | 1570 #If a session is found.. |
| 1538 if session: | 1571 if session: |
| 1539 #Send ServerHello | 1572 #Send ServerHello |
| 1540 serverHello = ServerHello() | 1573 serverHello = ServerHello() |
| 1541 serverHello.create(self.version, getRandomBytes(32), | 1574 serverHello.create(self.version, getRandomBytes(32), |
| 1542 session.sessionID, session.cipherSuite, | 1575 session.sessionID, session.cipherSuite, |
| 1543 CertificateType.x509, None, None) | 1576 CertificateType.x509, None, None, None) |
|
davidben
2016/08/03 23:34:22
ALPN also should happen on session resumption.
Bence
2016/08/04 18:41:45
Done.
| |
| 1544 serverHello.extended_master_secret = \ | 1577 serverHello.extended_master_secret = \ |
| 1545 clientHello.extended_master_secret and \ | 1578 clientHello.extended_master_secret and \ |
| 1546 settings.enableExtendedMasterSecret | 1579 settings.enableExtendedMasterSecret |
| 1547 for param in clientHello.tb_client_params: | 1580 for param in clientHello.tb_client_params: |
| 1548 if param in settings.supportedTokenBindingParams: | 1581 if param in settings.supportedTokenBindingParams: |
| 1549 serverHello.tb_params = param | 1582 serverHello.tb_params = param |
| 1550 break | 1583 break |
| 1551 for result in self._sendMsg(serverHello): | 1584 for result in self._sendMsg(serverHello): |
| 1552 yield result | 1585 yield result |
| 1553 | 1586 |
| (...skipping 293 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1847 assert(False) # Just to ensure we don't fall through somehow | 1880 assert(False) # Just to ensure we don't fall through somehow |
| 1848 | 1881 |
| 1849 #Calculate premaster secre | 1882 #Calculate premaster secre |
| 1850 S = powMod(dh_Yc,dh_Xs,dh_p) | 1883 S = powMod(dh_Yc,dh_Xs,dh_p) |
| 1851 premasterSecret = numberToByteArray(S) | 1884 premasterSecret = numberToByteArray(S) |
| 1852 | 1885 |
| 1853 yield premasterSecret | 1886 yield premasterSecret |
| 1854 | 1887 |
| 1855 | 1888 |
| 1856 def _serverFinished(self, premasterSecret, clientRandom, serverRandom, | 1889 def _serverFinished(self, premasterSecret, clientRandom, serverRandom, |
| 1857 cipherSuite, cipherImplementations, nextProtos, | 1890 cipherSuite, cipherImplementations, alpnProtos, |
| 1858 doingChannelID, useExtendedMasterSecret): | 1891 nextProtos, doingChannelID, useExtendedMasterSecret): |
|
davidben
2016/08/03 23:34:22
(ALPN doesn't interact interestingly with the Fini
Bence
2016/08/04 18:41:44
Done.
| |
| 1859 masterSecret = calcMasterSecret(self.version, premasterSecret, | 1892 masterSecret = calcMasterSecret(self.version, premasterSecret, |
| 1860 clientRandom, serverRandom, | 1893 clientRandom, serverRandom, |
| 1861 self._ems_handshake_hash, | 1894 self._ems_handshake_hash, |
| 1862 useExtendedMasterSecret) | 1895 useExtendedMasterSecret) |
| 1863 | 1896 |
| 1864 #Calculate pending connection states | 1897 #Calculate pending connection states |
| 1865 self._calcPendingStates(cipherSuite, masterSecret, | 1898 self._calcPendingStates(cipherSuite, masterSecret, |
| 1866 clientRandom, serverRandom, | 1899 clientRandom, serverRandom, |
| 1867 cipherImplementations) | 1900 cipherImplementations) |
| 1868 | 1901 |
| (...skipping 170 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2039 seed += bytearray(2) | 2072 seed += bytearray(2) |
| 2040 seed[len(seed) - 2] = len(context) >> 8 | 2073 seed[len(seed) - 2] = len(context) >> 8 |
| 2041 seed[len(seed) - 1] = len(context) & 0xFF | 2074 seed[len(seed) - 1] = len(context) & 0xFF |
| 2042 seed += context | 2075 seed += context |
| 2043 if self.version in ((3,1), (3,2)): | 2076 if self.version in ((3,1), (3,2)): |
| 2044 return PRF(self.session.masterSecret, label, seed, length) | 2077 return PRF(self.session.masterSecret, label, seed, length) |
| 2045 elif self.version == (3,3): | 2078 elif self.version == (3,3): |
| 2046 return PRF_1_2(self.session.masterSecret, label, seed, length) | 2079 return PRF_1_2(self.session.masterSecret, label, seed, length) |
| 2047 else: | 2080 else: |
| 2048 raise AssertionError() | 2081 raise AssertionError() |
| OLD | NEW |