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 |