-
Notifications
You must be signed in to change notification settings - Fork 82
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Mandatory parts of TLS 1.3 #174
Conversation
fafca3c
to
ef2cb66
Compare
8483965
to
1ae1280
Compare
6781e69
to
51f4e4e
Compare
982b4a7
to
608d7ba
Compare
876a1f7
to
c7f4251
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Reviewed 36edd15..23280e3
tlslite/handshakehelpers.py
Outdated
finished_key = HKDF_expand_label(binder_key, b"finished", b"", key_len, | ||
prf) | ||
binder = secureHMAC(finished_key, handshake_hash.digest(prf), prf) | ||
return binder | ||
|
||
@staticmethod | ||
def update_binders(client_hello, handshake_hashes, psk_configs): | ||
def calc_res_binder_psk(iden, resum_master_secret, tickets, ticket_hash): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The resum abbreviation in resum_master_secret looks to me a little bit awkward - I'd prefer res or rsmpt or resumpt. But certainly not a blocker.
tlslite/handshakehelpers.py
Outdated
while config[0] != iden.identity: | ||
# identities that are tickets don't carry PSK directly | ||
if iden.identity in ticket_idens: | ||
binder_hash = 'sha256' if len(resum_master_secret) == 32 else \ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If the hash used in resumption psk calculation really depends only on length of the master secret it might make sense to move this calculation to calc_res_binder_psk() and spare the ticket_hash argument.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it essentially does (the relation is other way round, but with just two hashes to choose from, there's no difference)
I was thinking about SHA-3, but we can cross that bridge when we get there
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it still needs to stay here for _calc_binder
below...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK
tlslite/handshakesettings.py
Outdated
"{0}".format(other.ticketCipher)) | ||
|
||
if any(len(i) not in set([16, 32]) for i in other.ticketKeys): | ||
raise ValueError("session ticket encryption keys must be 16 or 32" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: Should the "session ticket..." start with upper case? "Session ticket ...."
tlslite/handshakesettings.py
Outdated
"bytes long") | ||
|
||
if not 0 < other.ticketLifetime <= 7 * 24 * 60 * 60: | ||
raise ValueError("ticket lifetime must be a positive integer " |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Similarly as above "Ticket lifetime...."
tlslite/handshakesettings.py
Outdated
raise ValueError("Unknown MAC name: {0}".format(unknown)) | ||
|
||
unknown = not_matching(other.keyExchangeNames, KEY_EXCHANGE_NAMES) | ||
if unknown: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: You inconsistently renamed the unknownXyz variables here but the other ones kept the original name. Not sure if you want to change that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yeah, it's probably better to be consistent
add to the session object keying material necessary for TLS Exporter and session resumption to work
when sending the ticket we need to obfuscate the time, so we need to know when we received it
since the client saves session, not connection object keep the tickets inside session too since we're copying reference, the later updates to it will be reflected in the session object
fix the nits mentioned by codeclimate: - too long methods - similar code - whitespace issues - method complexity - redundant backslashes - bad line continuation
if client_hello is (3, 4) or greater, clamp it to (3, 3) i.e. TLS 1.2
compare the true highest advertised protocol version with the supported version for FALLBACK_SCSV if the client advertises TLS 1.2 (by sending some very high client_version, but no extension with protocol versions) and a FALLBACK_SCSV, that's an inappropriate fallback
draft-ietf-tls-tls13-25 calls for inclusion of Record Layer header as the associated data for the AEAD ciphers, update the code to do that
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I reviewed the last two commits. No real bugs spotted.
tlslite/recordlayer.py
Outdated
authData = bytearray(0) | ||
# this is essentially a Record Layer header | ||
authData = bytearray([recordType, 3, 3, | ||
len(buf) // 256, len(buf) % 256]) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I understand that this is probably easier to recreate the record layer header, but wouldn't it be more future-proof to carry it over from the actual data received?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this has the side-effect of enforcing them to those values, and I want to be strict on receiving
(on sending side I'm setting them to configured values as I want to be able to test this in other implementations)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But on the receiving side you then do not authenticate what was sent over the wire. I do not know whether there is any theoretical attack possible this way though. The enforcing to the expected values should be done explicitly I think.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed: 58a705e
@t8m Thanks! |
explicitly verify the record layer values for encrypted messages match the ones mandated by TLS 1.3 specification
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Reviewed
session.resumable = True | ||
|
||
print("Received {0} ticket[s]".format(len(connection.tickets))) | ||
assert connection.tickets is session.tickets |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note that this assertion triggers when connecting to nearly any HTTPS server on the internet.
$ tls.py client www.yahoo.com:443
Handshake success
Handshake time: 0.181 seconds
Version: TLS 1.2
Cipher: aes128gcm python
Ciphersuite: TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
No client certificate provided by peer
Server X.509 SHA1 fingerprint: 3914af80223c833f26df001cbf342eff8a31aba1
Key exchange signature: rsa_pkcs1_sha512
Group used for key exchange: secp256r1
SNI: www.yahoo.com
Next-Protocol Negotiated: None
Encrypt-then-MAC: False
Extended Master Secret: False
Received 0 ticket[s]
Traceback (most recent call last):
File "/usr/local/bin/tls.py", line 541, in
clientCmd(sys.argv[2:])
File "/usr/local/bin/tls.py", line 377, in clientCmd
assert connection.tickets is session.tickets
AssertionError
$ tls.py client www.amazon.com:443
Handshake success
Handshake time: 0.186 seconds
Version: TLS 1.2
Cipher: aes128gcm python
Ciphersuite: TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
No client certificate provided by peer
Server X.509 SHA1 fingerprint: 0e6bdcae568e3613c6d173c9b112c357ff5967b2
Key exchange signature: rsa_pkcs1_sha512
Group used for key exchange: secp256r1
SNI: www.amazon.com
Next-Protocol Negotiated: None
Encrypt-then-MAC: False
Extended Master Secret: False
Received 0 ticket[s]
Traceback (most recent call last):
File "/usr/local/bin/tls.py", line 541, in
clientCmd(sys.argv[2:])
File "/usr/local/bin/tls.py", line 377, in clientCmd
assert connection.tickets is session.tickets
AssertionError
$ tls.py client www.google.com:443
Handshake success
Handshake time: 0.068 seconds
Version: TLS 1.2
Cipher: chacha20-poly1305 python
Ciphersuite: TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256
No client certificate provided by peer
Server X.509 SHA1 fingerprint: 62231769ed0bf01ecce073c24a668578c5ffb66e
Key exchange signature: rsa_pss_rsae_sha256
Group used for key exchange: x25519
SNI: www.google.com
Next-Protocol Negotiated: None
Encrypt-then-MAC: False
Extended Master Secret: True
Received 0 ticket[s]
Traceback (most recent call last):
File "/usr/local/bin/tls.py", line 541, in
clientCmd(sys.argv[2:])
File "/usr/local/bin/tls.py", line 377, in clientCmd
assert connection.tickets is session.tickets
AssertionError
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
please file an issue
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ACK #317
Work in progress on TLS 1.3 support.
Includes:
messages themselves
documentation
test cases
general Client
general Server
Record Layer
Key Share extension
Supported Versions extension
Supported Groups extension from server
Encrypted Extensions message
Hello Retry Request message
Finished message
Certificate message
New Session Ticket message
Cookie extension
Sending supported groups in Encrypted Extensions
fake Change Cipher Spec
signature_algorithms_cert
Will fix #39 once ready
more clever ciphersuite selection (for external PSKs) will be handled in #213
This change is