haskell-tls / hs-tls

TLS/SSL implementation in haskell
Other
402 stars 87 forks source link

RFC 9266: Channel Bindings for TLS 1.3 support #462

Open Neustradamus opened 10 months ago

Neustradamus commented 10 months ago

Can you add the support of RFC 9266: Channel Bindings for TLS 1.3?

Little details, to know easily:

I think that you have seen the jabber.ru MITM and Channel Binding is the solution:

Thanks in advance.

Linked to:

kazu-yamamoto commented 9 months ago

I will probably spend time to improve tls for the next two months. First I need to understand this RFC.

Neustradamus commented 9 months ago

@kazu-yamamoto: Good :)

Please read the RFC5929 before:

It is important to support previous TLS versions and TLS 1.3.

For example, XMPP needs some XEPs in more the main RFC6120 with SCRAM-SHA-*-PLUS variants:

All SCRAM RFCs, I-Ds:

kazu-yamamoto commented 8 months ago

@Neustradamus Is it enough to revert 9b23d2ad5d1fb7f21b4d641a889bb00e00bf3890? Or should I provide a wrapper function to specify "EXPORTER-Channel-Binding", "" and 32 to it?

Neustradamus commented 8 months ago

@kazu-yamamoto: I am not sure about it, I am not an Haskell dev...

But there are 3 parts which must be possible:

Haskell devs from 2 XMPP projects:

kazu-yamamoto commented 8 months ago

@epoberezkin I guess that you have an opinion on this.

jappeace commented 8 months ago

afaik supercede dropped xmpp and that package is depracated.

kazu-yamamoto commented 8 months ago

8795ab6 implements getTLSExporter and add a document to `getFinished'. Let's close this.

Neustradamus commented 8 months ago

@kazu-yamamoto: Good job!

Now it supports 3 parts?

kazu-yamamoto commented 8 months ago

getFinished for (1) and getTLSExporter for (3) but no (2). Should I implement (2), too?

Neustradamus commented 8 months ago

Yes for tls-server-end-point, it is needed, it is in:

And it is in SASL2 I-D: Extensible Simple Authentication and Security Layer (SASL): https://datatracker.ietf.org/doc/html/draft-melnikov-sasl2

kazu-yamamoto commented 8 months ago

@epoberezkin I have implemented getTLSUnique which automatically selects the first Finished (see 1428994). getFinished and getPeerFinished are deprecated in tls v2.0

Neustradamus commented 8 months ago

@kazu-yamamoto: Thanks!

You will remove the support of TLS 1.2 in 2.0?

Important: "tls-server-end-point" is needed too: it is in several XEPs and it will be in next SASL2 IETF RFC, an RFC which will replace: https://datatracker.ietf.org/doc/html/rfc4422.

You can look in all links cited in my previous comment.

kazu-yamamoto commented 8 months ago

The last comment was to @epoberezkin which implemented getFinished. I'm now thinking how to implement "tls-server-end-point".

tls v2.0 supports both TLS 1.2 and TLS 1.3.

Neustradamus commented 8 months ago

@kazu-yamamoto: Ah sorry, too quick to read :)

Can you add comments in the code about "tls-unique" and RFC5929, "tls-server-end-point" and RFC5929, "tls-exporter" and RFC9266? It is easy to look in the code.

Example in GnuTLS code:

kazu-yamamoto commented 8 months ago

The old default for Extended Master Secret of TLS 1.2 was allowed. But I changed it to required in 4cabdf3 to prevent triple handshake attack to "tls-unique".

kazu-yamamoto commented 8 months ago

@Neustradamus About comments. The binding name were already there. I added RFC stuff in their comments.

Neustradamus commented 8 months ago

Thanks @kazu-yamamoto! All of this will not be added in a build before 2.0?

kazu-yamamoto commented 8 months ago

No. Haskell tls does not have long term support versions like other Haskell libraries. The Haskell community has a culture where libraries are very small and updated frequently.

kazu-yamamoto commented 8 months ago

I have implemented getTLSServerEndPoint. Both for TLS 1.2 and TLS 1.3, a channel binding is created with a certificate chain with the used hash.

kazu-yamamoto commented 8 months ago

What I'm not convinced yet:

Neustradamus commented 8 months ago

@kazu-yamamoto: I have sent you an email

kazu-yamamoto commented 8 months ago

@Neustradamus Yes. I have read the mail. Thank you. But I don't think the email answers to my questions above.

I tried to read the code of OpenSSL but I don't understand SSL_get_finished yet.

kazu-yamamoto commented 8 months ago

@epoberezkin Would you tell me whether or not getFinished is inter-operable with OpenSSL?

epoberezkin commented 8 months ago

@kazu-yamamoto sorry for slow replies!

tlsunique should be available for TLS 1.3 too - we use exactly that now. While it was defined for TLS 1.2 it can be used with some caveats for TLS 1.3 too - it's just a digest over client's handshake.

@epoberezkin I have implemented getTLSUnique which automatically selects the first Finished (see https://github.com/haskell-tls/hs-tls/commit/1428994477a3fd6831cbd9a16c3d743fbfee42ec). getFinished and getPeerFinished are deprecated in tls v2.0

You really need both to get tlsunique binding in both client and server, I believe they should not be deprecated, because which one to use depends on client/server role and in any case they can be useful for debugging.

I am not sure what "the first Finished" means, if you want to have tlsunique available to both sides via a single then it should be getPeerFinished in the server and getFinished in the client.

Also, I believe tlsunique should not be used when session resumption is allowed (that was the motivation to offer new bindings for TLS 1.3 spec) - just looked briefly at this commit, so maybe you can make the new function throw exception unless resumption is disabled.

Does the calculation of "tls-unique" exclude HandshakeType and the length of the Handshake struct?

tlsunique is client's Finished value, as it's defined in TLS handshake, it should not be calculated differently

@epoberezkin Would you tell me whether or not getFinished is inter-operable with OpenSSL?

Good question. We did not test that.

kazu-yamamoto commented 8 months ago

@epoberezkin

(1) tls-server-end-point

The problem is that the structure of TLS 1.3 certificate is different from that of TLS 1.2:

TLS 1.2:

struct {
    ASN.1Cert certificate_list<0..2^24-1>;
} Certificate;

TLS 1.3:

struct {
   opaque certificate_request_context<0..2^8-1>;
   Extension extensions<2..2^16-1>;
} CertificateRequest;

Some guys say "just use the entire of TLS 1.3 certificate" while others say "encode it into TLS 1.2 certificate".

(2) tls-unique

See the following figure to understand which is the first and which is the second.

      Client                                               Server

      ClientHello                  -------->
                                                      ServerHello
                                                     Certificate*
                                               ServerKeyExchange*
                                              CertificateRequest*
                                   <--------      ServerHelloDone
      Certificate*
      ClientKeyExchange
      CertificateVerify*
      [ChangeCipherSpec]
      Finished(1)                  -------->
                                               [ChangeCipherSpec]
                                   <--------             Finished(2)
      Application Data             <------->     Application Data

getTLSUnique returns the first Finished regardless of its role. getFinished and getPeerFinished are error-prone because users must take care of its role.

The TLS message is composed as follows:

TLS record header
Handshake message header
Finished (verify_data)

RFC 5929 says:

note: the Finished struct, not the TLS record layer message containing it

If the handshake message header is not included, the spec should say so explicitly.

Anyway, the current specifications look ambiguous to me. So, inter-operability test is important.