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 477 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
488 if nextProtos is not None: | 488 if nextProtos is not None: |
489 if len(nextProtos) == 0: | 489 if len(nextProtos) == 0: |
490 raise ValueError("Caller passed no nextProtos") | 490 raise ValueError("Caller passed no nextProtos") |
491 | 491 |
492 # Validates the settings and filters out any unsupported ciphers | 492 # Validates the settings and filters out any unsupported ciphers |
493 # or crypto libraries that were requested | 493 # or crypto libraries that were requested |
494 if not settings: | 494 if not settings: |
495 settings = HandshakeSettings() | 495 settings = HandshakeSettings() |
496 settings = settings._filter() | 496 settings = settings._filter() |
497 | 497 |
| 498 if settings.alpnProtos is not None: |
| 499 if len(settings.alpnProtos) == 0: |
| 500 raise ValueError("Caller passed no alpnProtos") |
| 501 |
498 if clientCertChain: | 502 if clientCertChain: |
499 if not isinstance(clientCertChain, X509CertChain): | 503 if not isinstance(clientCertChain, X509CertChain): |
500 raise ValueError("Unrecognized certificate type") | 504 raise ValueError("Unrecognized certificate type") |
501 if "x509" not in settings.certificateTypes: | 505 if "x509" not in settings.certificateTypes: |
502 raise ValueError("Client certificate doesn't match "\ | 506 raise ValueError("Client certificate doesn't match "\ |
503 "Handshake Settings") | 507 "Handshake Settings") |
504 | 508 |
505 if session: | 509 if session: |
506 # session.valid() ensures session is resumable and has | 510 # session.valid() ensures session is resumable and has |
507 # non-empty sessionID | 511 # non-empty sessionID |
(...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
644 #ciphersuite must be one of the acceptable ciphersuites | 648 #ciphersuite must be one of the acceptable ciphersuites |
645 if session.cipherSuite not in cipherSuites: | 649 if session.cipherSuite not in cipherSuites: |
646 raise ValueError("Session's cipher suite not consistent "\ | 650 raise ValueError("Session's cipher suite not consistent "\ |
647 "with parameters") | 651 "with parameters") |
648 else: | 652 else: |
649 clientHello = ClientHello() | 653 clientHello = ClientHello() |
650 clientHello.create(settings.maxVersion, getRandomBytes(32), | 654 clientHello.create(settings.maxVersion, getRandomBytes(32), |
651 session.sessionID, cipherSuites, | 655 session.sessionID, cipherSuites, |
652 certificateTypes, | 656 certificateTypes, |
653 session.srpUsername, | 657 session.srpUsername, |
654 reqTack, nextProtos is not None, | 658 reqTack, settings.alpnProtos, |
| 659 nextProtos is not None, |
655 session.serverName) | 660 session.serverName) |
656 | 661 |
657 #Or send ClientHello (without) | 662 #Or send ClientHello (without) |
658 else: | 663 else: |
659 clientHello = ClientHello() | 664 clientHello = ClientHello() |
660 clientHello.create(settings.maxVersion, getRandomBytes(32), | 665 clientHello.create(settings.maxVersion, getRandomBytes(32), |
661 bytearray(0), cipherSuites, | 666 bytearray(0), cipherSuites, |
662 certificateTypes, | 667 certificateTypes, |
663 srpUsername, | 668 srpUsername, |
664 reqTack, nextProtos is not None, | 669 reqTack, settings.alpnProtos, |
| 670 nextProtos is not None, |
665 serverName) | 671 serverName) |
666 for result in self._sendMsg(clientHello): | 672 for result in self._sendMsg(clientHello): |
667 yield result | 673 yield result |
668 yield clientHello | 674 yield clientHello |
669 | 675 |
670 | 676 |
671 def _clientGetServerHello(self, settings, clientHello): | 677 def _clientGetServerHello(self, settings, clientHello): |
672 for result in self._getMsg(ContentType.handshake, | 678 for result in self._getMsg(ContentType.handshake, |
673 HandshakeType.server_hello): | 679 HandshakeType.server_hello): |
674 if result in (0,1): yield result | 680 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(\ | 713 for result in self._sendError(\ |
708 AlertDescription.illegal_parameter, | 714 AlertDescription.illegal_parameter, |
709 "Server responded with incorrect compression method"): | 715 "Server responded with incorrect compression method"): |
710 yield result | 716 yield result |
711 if serverHello.tackExt: | 717 if serverHello.tackExt: |
712 if not clientHello.tack: | 718 if not clientHello.tack: |
713 for result in self._sendError(\ | 719 for result in self._sendError(\ |
714 AlertDescription.illegal_parameter, | 720 AlertDescription.illegal_parameter, |
715 "Server responded with unrequested Tack Extension"): | 721 "Server responded with unrequested Tack Extension"): |
716 yield result | 722 yield result |
| 723 if serverHello.alpn_proto_selected and not clientHello.alpn_protos_adver
tised: |
| 724 for result in self._sendError(\ |
| 725 AlertDescription.illegal_parameter, |
| 726 "Server responded with unrequested ALPN Extension"): |
| 727 yield result |
| 728 if serverHello.alpn_proto_selected and serverHello.next_protos: |
| 729 for result in self._sendError(\ |
| 730 AlertDescription.illegal_parameter, |
| 731 "Server responded with both ALPN and NPN extension"): |
| 732 yield result |
717 if serverHello.next_protos and not clientHello.supports_npn: | 733 if serverHello.next_protos and not clientHello.supports_npn: |
718 for result in self._sendError(\ | 734 for result in self._sendError(\ |
719 AlertDescription.illegal_parameter, | 735 AlertDescription.illegal_parameter, |
720 "Server responded with unrequested NPN Extension"): | 736 "Server responded with unrequested NPN Extension"): |
721 yield result | 737 yield result |
722 if not serverHello.tackExt.verifySignatures(): | 738 if not serverHello.tackExt.verifySignatures(): |
723 for result in self._sendError(\ | 739 for result in self._sendError(\ |
724 AlertDescription.decrypt_error, | 740 AlertDescription.decrypt_error, |
725 "TackExtension contains an invalid signature"): | 741 "TackExtension contains an invalid signature"): |
726 yield result | 742 yield result |
(...skipping 581 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1308 self.clientHello = clientHello | 1324 self.clientHello = clientHello |
1309 | 1325 |
1310 #If not a resumption... | 1326 #If not a resumption... |
1311 | 1327 |
1312 # Create the ServerHello message | 1328 # Create the ServerHello message |
1313 if sessionCache: | 1329 if sessionCache: |
1314 sessionID = getRandomBytes(32) | 1330 sessionID = getRandomBytes(32) |
1315 else: | 1331 else: |
1316 sessionID = bytearray(0) | 1332 sessionID = bytearray(0) |
1317 | 1333 |
| 1334 alpn_proto_selected = None |
| 1335 if (clientHello.alpn_protos_advertised is not None |
| 1336 and settings.alpnProtos is not None): |
| 1337 for proto in settings.alpnProtos: |
| 1338 if proto in clientHello.alpn_protos_advertised: |
| 1339 alpn_proto_selected = proto |
| 1340 nextProtos = None |
| 1341 break; |
| 1342 |
1318 if not clientHello.supports_npn: | 1343 if not clientHello.supports_npn: |
1319 nextProtos = None | 1344 nextProtos = None |
1320 | 1345 |
1321 # If not doing a certificate-based suite, discard the TACK | 1346 # If not doing a certificate-based suite, discard the TACK |
1322 if not cipherSuite in CipherSuite.certAllSuites: | 1347 if not cipherSuite in CipherSuite.certAllSuites: |
1323 tacks = None | 1348 tacks = None |
1324 | 1349 |
1325 # Prepare a TACK Extension if requested | 1350 # Prepare a TACK Extension if requested |
1326 if clientHello.tack: | 1351 if clientHello.tack: |
1327 tackExt = TackExtension.create(tacks, activationFlags) | 1352 tackExt = TackExtension.create(tacks, activationFlags) |
1328 else: | 1353 else: |
1329 tackExt = None | 1354 tackExt = None |
1330 serverHello = ServerHello() | 1355 serverHello = ServerHello() |
1331 serverHello.create(self.version, getRandomBytes(32), sessionID, \ | 1356 serverHello.create(self.version, getRandomBytes(32), sessionID, \ |
1332 cipherSuite, CertificateType.x509, tackExt, | 1357 cipherSuite, CertificateType.x509, tackExt, |
| 1358 alpn_proto_selected, |
1333 nextProtos) | 1359 nextProtos) |
1334 serverHello.channel_id = \ | 1360 serverHello.channel_id = \ |
1335 clientHello.channel_id and settings.enableChannelID | 1361 clientHello.channel_id and settings.enableChannelID |
1336 serverHello.extended_master_secret = \ | 1362 serverHello.extended_master_secret = \ |
1337 clientHello.extended_master_secret and \ | 1363 clientHello.extended_master_secret and \ |
1338 settings.enableExtendedMasterSecret | 1364 settings.enableExtendedMasterSecret |
1339 for param in clientHello.tb_client_params: | 1365 for param in clientHello.tb_client_params: |
1340 if param in settings.supportedTokenBindingParams: | 1366 if param in settings.supportedTokenBindingParams: |
1341 serverHello.tb_params = param | 1367 serverHello.tb_params = param |
1342 break | 1368 break |
(...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1493 cipherSuites += CipherSuite.getSrpSuites(settings, self.version) | 1519 cipherSuites += CipherSuite.getSrpSuites(settings, self.version) |
1494 elif certChain: | 1520 elif certChain: |
1495 cipherSuites += CipherSuite.getEcdheCertSuites(settings, self.versio
n) | 1521 cipherSuites += CipherSuite.getEcdheCertSuites(settings, self.versio
n) |
1496 cipherSuites += CipherSuite.getDheCertSuites(settings, self.version) | 1522 cipherSuites += CipherSuite.getDheCertSuites(settings, self.version) |
1497 cipherSuites += CipherSuite.getCertSuites(settings, self.version) | 1523 cipherSuites += CipherSuite.getCertSuites(settings, self.version) |
1498 elif anon: | 1524 elif anon: |
1499 cipherSuites += CipherSuite.getAnonSuites(settings, self.version) | 1525 cipherSuites += CipherSuite.getAnonSuites(settings, self.version) |
1500 else: | 1526 else: |
1501 assert(False) | 1527 assert(False) |
1502 | 1528 |
| 1529 alpn_proto_selected = None |
| 1530 if (clientHello.alpn_protos_advertised is not None |
| 1531 and settings.alpnProtos is not None): |
| 1532 for proto in settings.alpnProtos: |
| 1533 if proto in clientHello.alpn_protos_advertised: |
| 1534 alpn_proto_selected = proto |
| 1535 break; |
| 1536 |
1503 #If resumption was requested and we have a session cache... | 1537 #If resumption was requested and we have a session cache... |
1504 if clientHello.session_id and sessionCache: | 1538 if clientHello.session_id and sessionCache: |
1505 session = None | 1539 session = None |
1506 | 1540 |
1507 #Check in the session cache | 1541 #Check in the session cache |
1508 if sessionCache and not session: | 1542 if sessionCache and not session: |
1509 try: | 1543 try: |
1510 session = sessionCache[clientHello.session_id] | 1544 session = sessionCache[clientHello.session_id] |
1511 if not session.resumable: | 1545 if not session.resumable: |
1512 raise AssertionError() | 1546 raise AssertionError() |
(...skipping 20 matching lines...) Expand all Loading... |
1533 yield result | 1567 yield result |
1534 except KeyError: | 1568 except KeyError: |
1535 pass | 1569 pass |
1536 | 1570 |
1537 #If a session is found.. | 1571 #If a session is found.. |
1538 if session: | 1572 if session: |
1539 #Send ServerHello | 1573 #Send ServerHello |
1540 serverHello = ServerHello() | 1574 serverHello = ServerHello() |
1541 serverHello.create(self.version, getRandomBytes(32), | 1575 serverHello.create(self.version, getRandomBytes(32), |
1542 session.sessionID, session.cipherSuite, | 1576 session.sessionID, session.cipherSuite, |
1543 CertificateType.x509, None, None) | 1577 CertificateType.x509, None, |
| 1578 alpn_proto_selected, None) |
1544 serverHello.extended_master_secret = \ | 1579 serverHello.extended_master_secret = \ |
1545 clientHello.extended_master_secret and \ | 1580 clientHello.extended_master_secret and \ |
1546 settings.enableExtendedMasterSecret | 1581 settings.enableExtendedMasterSecret |
1547 for param in clientHello.tb_client_params: | 1582 for param in clientHello.tb_client_params: |
1548 if param in settings.supportedTokenBindingParams: | 1583 if param in settings.supportedTokenBindingParams: |
1549 serverHello.tb_params = param | 1584 serverHello.tb_params = param |
1550 break | 1585 break |
1551 for result in self._sendMsg(serverHello): | 1586 for result in self._sendMsg(serverHello): |
1552 yield result | 1587 yield result |
1553 | 1588 |
(...skipping 485 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2039 seed += bytearray(2) | 2074 seed += bytearray(2) |
2040 seed[len(seed) - 2] = len(context) >> 8 | 2075 seed[len(seed) - 2] = len(context) >> 8 |
2041 seed[len(seed) - 1] = len(context) & 0xFF | 2076 seed[len(seed) - 1] = len(context) & 0xFF |
2042 seed += context | 2077 seed += context |
2043 if self.version in ((3,1), (3,2)): | 2078 if self.version in ((3,1), (3,2)): |
2044 return PRF(self.session.masterSecret, label, seed, length) | 2079 return PRF(self.session.masterSecret, label, seed, length) |
2045 elif self.version == (3,3): | 2080 elif self.version == (3,3): |
2046 return PRF_1_2(self.session.masterSecret, label, seed, length) | 2081 return PRF_1_2(self.session.masterSecret, label, seed, length) |
2047 else: | 2082 else: |
2048 raise AssertionError() | 2083 raise AssertionError() |
OLD | NEW |