Skip to content
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

TLS 1.3 #167

Closed
kazu-yamamoto opened this issue Nov 15, 2016 · 24 comments
Assignees
Labels

Comments

@kazu-yamamoto
Copy link
Collaborator

@kazu-yamamoto kazu-yamamoto commented Nov 15, 2016

Note

My implementation has been fully merged to this upstream. This contents are now outdated.

See #282.

Introduction

This is the current status of TLS 1.3 implementation in Haskell. This text is repeatedly updated if necessary.

If you are not Haskellers, please refer to this first.

If you want to use TLS 1.3 of the tls package in Haskell, you should track the tls13 branch of the kazu-yamamoto's fork:

% git clone https://github.com/kazu-yamamoto/hs-tls.git
% git checkout -t orign/tl13

All draft versions are available on this branch. See the commit logs.

On the tls13 branch, commits are frequently squashed, rebased and force-updated. So, you should do the following if necessary:

% git fetch
% git reset --hard origin/tls13

Supported

  • TLS 1.3 draft 18,19,20,21,22,23,24,25,26,27,28
  • Server: full negotiations, HRR, PSK, 0RTT
  • Client: full negotiations, HRR, PSK, 0RTT

Interoperability

TLS 1.3 draft 28 interoperability

Other clients to Haskell TLS server:

Full HRR PSK 0RTT
picotls OK OK OK OK
OpenSSL OK OK OK OK
NSS OK OK OK OK
BoringSSL OK OK OK OK
Firefox Nightly OK - - -
Chrome Canary OK - - -

Haskell client to other servers:

Full HRR PSK 0RTT
picotls OK OK OK OK
OpenSSL OK OK OK OK
NSS OK OK OK OK
BoringSSL OK OK OK OK
tris
www.tls13.facebook.com OK OK OK OK fizz
enabled.tls13.com OK OK OK OK BoringSSL
tls13.crypto.mozilla.org OK OK NG NG
  • BoringSSL server sends multiple NSTs in a single handshake

TLS 1.3 draft 23/24 interoperability

Other clients to Haskell TLS server:

Full HRR PSK 0RTT
picotls OK OK OK OK
OpenSSL OK OK OK OK
NSS OK OK OK OK
BoringSSL OK OK OK OK
Firefox Nightly OK - - -
Chrome Canary OK - - -

Haskell client to other servers:

Full HRR PSK 0RTT
picotls OK OK OK OK
OpenSSL OK OK OK OK
NSS OK OK OK OK
BoringSSL OK OK OK OK
tris
www.tls13.facebook.com OK OK OK OK fizz
enabled.tls13.com OK OK OK OK BoringSSL
tls13.crypto.mozilla.org OK OK NG NG

draft 22

Other clients to Haskell TLS server:

Full HRR PSK 0RTT
picotls OK OK OK OK
OpenSSL OK OK OK OK
NSS OK OK OK OK
BoringSSL OK OK OK OK

Haskell client to other servers:

Full HRR PSK 0RTT
picotls OK OK OK OK
OpenSSL OK OK OK OK
NSS OK OK OK OK
BoringSSL OK OK OK OK
tris OK NG OK OK
  • tris does not support HRR yet.

draft 21

Other clients to Haskell TLS server:

Full HRR PSK 0RTT
OpenSSL OK OK OK OK
NSS OK OK OK

Haskell client to other servers:

Full HRR PSK 0RTT
OpenSSL OK OK OK OK
NSS OK NG OK NG

draft 20

Other clients to Haskell TLS server:

Full HRR PSK 0RTT
OpenSSL OK OK OK OK
NSS OK OK OK

Haskell client to other servers:

Full HRR PSK 0RTT
OpenSSL OK OK OK OK
NSS OK

draft 19

The specification of draft 19 has a bug that EndOfEarlyData is not included in transcript calculation. Draft 19 implementators should include it.

I don't spend time for draft 19 anymore because of draft 20.

Other clients to Haskell TLS server:

Full HRR PSK 0RTT
picotls OK OK
OpenSSL OK OK OK

Haskell client to other servers:

Full HRR PSK 0RTT
OpenSSL OK OK OK OK

draft 18

Other clients to Haskell TLS server

Full HRR PSK 0RTT
Nightly OK OK OK
NSS OK OK OK
Canary OK OK OK *1
picotls OK OK OK OK
OpenSSL OK OK OK
  • *1 I don't know this browser supports 0RTT

Haskell client to other servers

Full HRR PSK 0RTT note
Tris OK *1 OK OK blog.cloudflare.com
NSS OK OK OK OK
BoringSSL OK OK OK OK tls.ctf.network
picotls OK OK OK OK
OpenSSL OK OK OK NG*2
  • *1 Not supported
  • *2 0RTT is not used. Instead, PSK is used.
  • Note: tls13.crypto.mozilla.org(NSS) is suffering from a mod_nss bug relating to session ticket

Things merged or fixed

Todo

  • Server: checking ticket age: absolute
  • Client: checking ticket age
  • Client: verifying certificate chain (cf --no-validate)
  • Client: Set 0RTTAccepted in ctx (checking EarlyData from a server)
  • Client authentication
  • Key update
  • Test cases

Todo but NOT motivated

  • DHE
@kazu-yamamoto

This comment has been minimized.

Copy link
Collaborator Author

@kazu-yamamoto kazu-yamamoto commented Nov 21, 2016

Usage of tls-simpleclient

tls-simpleclient takes a server name and optionally a port number then generates HTTP/1.1 GET.

  • -O : logging received HTML to the file
  • --http1.1: ensuring that HTTP/1.1 is used instead of HTTP/1.0
  • --no-valid: skipping verification of a server certificate

Full negotiation

Specify -g x25519 to not trigger HRR.

% stack exec tls-simpleclient -- --no-valid -O html-log.txt -g x25519 --http1.1 127.0.0.1 13443
groups = [X25519], keyshare = [X25519]
TLS 1.3: AES128GCM-SHA256 SHA256
NewSessionTicket received

HRR

The default value of -g is x448,x25519,p256. To trigger HRR, omit the -g option. The first value is only used for key-share.

% stack exec tls-simpleclient -- --no-valid -O html-log.txt --http1.1 127.0.0.1 13443
groups = [X448,X25519,P256], keyshare = [X448]
Retrying client hello...
groups = [X25519], keyshare = [X25519]
TLS 1.3: AES128GCM-SHA256 SHA256
NewSessionTicket received

PSK

Specify --session. The client stores a ticket in the memory and tries to make a new connection with the ticket. Note that a proper keyshare is selected on the second try to avoid HRR. "PSK[0] is used" indicates that PSK is succeeded.

% stack exec tls-simpleclient -- --no-valid -O html-log.txt --session --http1.1 127.0.0.1 13443
groups = [X448,X25519,P256], keyshare = [X448]
Retrying client hello...
groups = [X25519], keyshare = [X25519]
TLS 1.3: AES128GCM-SHA256 SHA256
NewSessionTicket received

Resuming the session...
groups = [X25519], keyshare = [X25519]
TLS 1.3: AES128GCM-SHA256 SHA256
PSK[0] is used
NewSessionTicket received

0RTT

Use -Z to specify a file containing early-data. "0RTT is accepted" indicates that 0RTT is succeded.

% cat early-data.txt 
GET / HTTP/1.1
Host: 127.0.0.1

% stack exec tls-simpleclient -- --no-valid -O html-log.txt -Z $SOMEWHERE/early-data.txt --session --http1.1 127.0.0.1 13443
groups = [X448,X25519,P256], keyshare = [X448]
Retrying client hello...
groups = [X25519], keyshare = [X25519]
TLS 1.3: AES128GCM-SHA256 SHA256
NewSessionTicket received

Resuming the session...
groups = [X25519], keyshare = [X25519]
Sending 0RTT request...
TLS 1.3: AES128GCM-SHA256 SHA256
PSK[0] is used
0RTT is accepted
NewSessionTicket received
@kazu-yamamoto

This comment has been minimized.

Copy link
Collaborator Author

@kazu-yamamoto kazu-yamamoto commented Nov 21, 2016

Using TLS 1.3 servers

Using Mighty

First, clone mighty:

% git clone https://github.com/kazu-yamamoto/mighttpd2
% cd mighttpd2
% git checkout -t origin/tls13

Then, clone the tls13 branches of warp-tls and wai:

% sh setup.sh

Build it (this takes a long time at the first time):

% stack setup
% stack build
% stack exec which mighty
/Users/kazu/work/mighttpd2/.stack-work/install/x86_64-osx/lts-9.14/8.0.2/bin/mighty

Create index.html and copy your certificate and private key files:

% echo '<html></html>' > /tmp/index.html
% cp $SOMEWHERE privkey.pem
% cp $SOMEWHERE cert.pem

And run:

% stack exec mighty -- conf/example.conf conf/example.route
HTTP service on port 8080 and HTTP/TLS service on port 13443.
28 Nov 2017 13:58:18: pid = 18974: Mighty started

Next time

% sh setup.sh
% stack build
% stack exec which mighty
/Users/kazu/work/mighttpd2/.stack-work/install/x86_64-osx/lts-9.14/8.0.2/bin/mighty
% stack exec mighty -- conf/example.conf conf/example.route

Public servers

tls-simpleserver

% cd hs-tls
% sh setup.sh
% stack build
% stack exec tls-simpleserver -- --key=$SOMEWHERE/key.pem --certificate=$SOMEWHERE/certificate.pem -v -Z 13443
@kazu-yamamoto

This comment has been minimized.

Copy link
Collaborator Author

@kazu-yamamoto kazu-yamamoto commented Nov 30, 2016

How to use this package for non Haskellers

First time

You need GHC(Glasgow Haskell Compiler) to compile Haskell code. Recently, many Haskellers use stack as a package manager. stack kindly installs GHC! So, you should install stack first:

% curl -sSL https://get.haskellstack.org/ | sh
% which stack
/usr/local/bin/stack

Install GHC:

% stack setup

GHC is installed in ~/.stack/programs/x86_64-osx/ghc-8.0.2. Let's use the GHC interpreter via stack:

% stack ghci
> 1 + 2
3
> Ctr+D
%

Now, you should clone this repository:

% git clone https://github.com/kazu-yamamoto/hs-tls.git
% cd hs-tls
% git checkout -t origin/tls13

Let's build Haskell tls. At the first time, this takes a long time!

% sh setup.sh
% stack build

OK. tls-simpleclient and tls-simpleserver are created. Let's use tls-simpleclient via stack:

% stack exec tls-simpleclient -- --no-valid --http1.1 mew.org 13443

Next time

% sh setup.sh
% stack build
@kazu-yamamoto

This comment has been minimized.

Copy link
Collaborator Author

@kazu-yamamoto kazu-yamamoto commented Dec 20, 2016

Proposed APIs for 0RTT

  • Supported supportedEarlyData :: AcceptEarlyData Word32 for server and SendEarlyData ByteString for client
  • Information infoIsEarlyDataAccepted :: telling whether or not TLS 1.3 early data is accepted. If not, the client should resend the data
@kazu-yamamoto kazu-yamamoto self-assigned this Feb 22, 2017
@axman6

This comment has been minimized.

Copy link

@axman6 axman6 commented May 25, 2017

I was wondering if there's much progress on this in the last 5 months - it would be good to add a checklist of tasks done and yet to be done to the issue description above - would help people know if there's something they an help with too. Link for reference if you haven't used this feature before: https://github.com/blog/1375-task-lists-in-gfm-issues-pulls-comments

@kazu-yamamoto

This comment has been minimized.

Copy link
Collaborator Author

@kazu-yamamoto kazu-yamamoto commented May 25, 2017

I'm actively working:
https://github.com/kazu-yamamoto/hs-tls/commits/tls13-18
https://github.com/kazu-yamamoto/hs-tls/commits/tls13-19

The first commit of tls13-18 contains what's done and todo.
But I should copy them to here.

I will support TLS 1.3 ID20 soon. Some features of TLS 1.3 have already merged into the master.

@kazu-yamamoto

This comment has been minimized.

Copy link
Collaborator Author

@kazu-yamamoto kazu-yamamoto commented May 26, 2017

@axman6 I re-wrote the first text. I hope you like it.

@kazu-yamamoto

This comment has been minimized.

Copy link
Collaborator Author

@kazu-yamamoto kazu-yamamoto commented May 26, 2017

I also wrote usage of tls-simpleclient. See above.

@axman6

This comment has been minimized.

Copy link

@axman6 axman6 commented May 26, 2017

You've got one above and beyond Kazu, this is fantastic! Glad to see things are progressing so well. Do you have any comments on what an interface using the early data feature would look like? Wondering how easy it might be to use in general network code and also if it'll be accessible from say Wai.

@axman6

This comment has been minimized.

Copy link

@axman6 axman6 commented May 26, 2017

You've gone above and beyond*

@kazu-yamamoto

This comment has been minimized.

Copy link
Collaborator Author

@kazu-yamamoto kazu-yamamoto commented May 26, 2017

Client side:

You can set early data to ClientParams clientTLS13ZeroRttData and can tell whether or not it is accepted through Context (the later is still todo, see above).

Server side:

recvData simply returns early data. There is no way to tell whether or not it is early data at this moment.

kazu-yamamoto added a commit to kazu-yamamoto/hs-tls that referenced this issue May 26, 2017
@kazu-yamamoto

This comment has been minimized.

Copy link
Collaborator Author

@kazu-yamamoto kazu-yamamoto commented May 26, 2017

I also wrote how to use this lib in the server side. See above.

@kazu-yamamoto kazu-yamamoto referenced this issue May 26, 2017
kazu-yamamoto added a commit to kazu-yamamoto/hs-tls that referenced this issue May 26, 2017
See: vincenthz#167

This jumbo patch will be eventually divided into logical patches
after standardization of TLS 1.3 is finished and before a pull request
is sent. This patch is jumbo to observe the entire patch to make
difference minimum. This patch is repeatedly rebased and overridden
to clean up the TLS 1.3 code. Take care.
kazu-yamamoto added a commit to kazu-yamamoto/hs-tls that referenced this issue May 26, 2017
kazu-yamamoto added a commit to kazu-yamamoto/hs-tls that referenced this issue May 26, 2017
kazu-yamamoto added a commit to kazu-yamamoto/hs-tls that referenced this issue May 29, 2017
See: vincenthz#167

This jumbo patch will be eventually divided into logical patches
after standardization of TLS 1.3 is finished and before a pull request
is sent. This patch is jumbo to observe the entire patch to make
difference minimum. This patch is repeatedly rebased and overridden
to clean up the TLS 1.3 code. Take care.
kazu-yamamoto added a commit to kazu-yamamoto/hs-tls that referenced this issue May 29, 2017
kazu-yamamoto added a commit to kazu-yamamoto/hs-tls that referenced this issue May 29, 2017
@ocheron

This comment has been minimized.

Copy link
Collaborator

@ocheron ocheron commented May 30, 2017

What is "isPointValid for draft 19" exactly?

@kazu-yamamoto

This comment has been minimized.

Copy link
Collaborator Author

@kazu-yamamoto kazu-yamamoto commented May 31, 2017

TLS 1.3 draft says:

For the curves secp256r1, secp384r1 and secp521r1, peers MUST
validate each other's public value Y by ensuring that the point is a
valid point on the elliptic curve. The appropriate validation
procedures are defined in Section 4.3.7 of [X962] and alternatively
in Section 5.6.2.6 of [KEYAGREEMENT]. This process consists of three
steps: (1) verify that Y is not the point at infinity (O), (2) verify
that for Y = (x, y) both integers are in the correct interval, (3)
ensure that (x, y) is a correct solution to the elliptic curve
equation. For these curves, implementers do not need to verify
membership in the correct subgroup.

For X25519 and X448, the contents of the public value are the byte
string inputs and outputs of the corresponding functions defined in
[RFC7748], 32 bytes for X25519 and 56 bytes for X448.

So, the EllipticCurve class or something should provide isPointValid.
But I have no idea on how to implement this for X25519 and X448.

@vincenthz

This comment has been minimized.

Copy link
Owner

@vincenthz vincenthz commented May 31, 2017

@kazu-yamamoto decodePoint already take care of validity checking by construction. ed25519 doesn't need "point-validation"

@ocheron

This comment has been minimized.

Copy link
Collaborator

@ocheron ocheron commented Jun 1, 2017

@kazu-yamamoto Thanks for the reference, I didn't find it.

This is mostly right, with the point format chosen for X25519 and X448 there is not much to validate.

One small exception though: RFC7748 mentions an optional all-zero result check after D-H.
This is actually already implemented in the C code cryptonite is based on, but not returned by the Haskell APIs.

This check becomes a MUST in draft-ietf-tls-rfc4492bis § 5.10 and 5.11.

@kazu-yamamoto

This comment has been minimized.

Copy link
Collaborator Author

@kazu-yamamoto kazu-yamamoto commented Jun 1, 2017

This is mostly right, with the point format chosen for X25519 and X448 there is not much to validate.

Check length but this is already implemented in cryptonite. :-)

One small exception though: RFC7748 mentions an optional all-zero result check after D-H.
This is actually already implemented in the C code cryptonite is based on, but not returned by the Haskell APIs.

We should implement it.

@ocheron

This comment has been minimized.

Copy link
Collaborator

@ocheron ocheron commented Jun 16, 2017

We should implement it.

We don't need to do anything special in tls if cryptonite has a check for point-at-infinity in ECIES, like described on the Wikipedia page or SEC 1 standard. All-zero value is identity element of X25519 and X448.

But this means ECIES functions deriveEncrypt and deriveDecrypt should have a CryptoFailable result. The API is only 6-month old, so maybe not to late to change.

@kazu-yamamoto

This comment has been minimized.

Copy link
Collaborator Author

@kazu-yamamoto kazu-yamamoto commented Jun 26, 2017

@ocheron Would you bring this issue to cryptonite repo?

@ocheron

This comment has been minimized.

Copy link
Collaborator

@ocheron ocheron commented Jun 26, 2017

Yes that's my plan.

@ocheron

This comment has been minimized.

Copy link
Collaborator

@ocheron ocheron commented Jun 29, 2017

Quick status update:

[EDIT: both now fixed in cryptonite-0.24]

@erikd

This comment has been minimized.

Copy link
Contributor

@erikd erikd commented Jun 23, 2018

Anything I can do to help move this along?

@kazu-yamamoto

This comment has been minimized.

Copy link
Collaborator Author

@kazu-yamamoto kazu-yamamoto commented Jun 25, 2018

I'm waiting for RFC8446 to be published. :-)
https://www.rfc-editor.org/auth48/rfc8446

@erikd

This comment has been minimized.

Copy link
Contributor

@erikd erikd commented Jun 25, 2018

Ah ok, that I cannot help you with :).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
5 participants
You can’t perform that action at this time.