[openssl-commits] [openssl] master update

Matt Caswell matt at openssl.org
Thu Mar 2 17:48:46 UTC 2017


The branch master has been updated
       via  83750d9b2b51bb622138d48fc82eb408b64d8057 (commit)
       via  cd9f7f624ee434606b084d77e6845f15f8c501bc (commit)
       via  09f288748266577cc38b77ca31c47b9e9f15890e (commit)
       via  0665b4edae3fec740ebe12fe2946d4cc9585ca86 (commit)
       via  f533fbd44a36daac9cc304ff648782e366391b00 (commit)
       via  ef466accdc196fe796301a06cdc6e94cb315ae9b (commit)
       via  ade1e88806461df5516525a8f36e707820167e01 (commit)
       via  3eaa4170956dc7ca2a0c9fc9414dc42cac7b426e (commit)
       via  5f9820380ff82fc07e93e430b97da516997d3771 (commit)
       via  f7e393be4725c33739d46a58de94a06ebdc6e49d (commit)
       via  d7f8783ff9e88ad34e010564d721a55a48c6d674 (commit)
       via  564547e482406c2d4c56a59e288b3a479dac2d74 (commit)
       via  4004ce5f6cd6540a07d6d1a4cef7138821d5e596 (commit)
       via  bc908c679b0d13ed5fdeb06d4c2eda8b0b5f5ce6 (commit)
       via  6437b802f19fb022da88f59cb3071ebdcd2838f6 (commit)
       via  0a5ece5bd20aac050d3c77c4f1fb760aa7892ab0 (commit)
       via  fd6c102520e3829a10fb273eaa62bbccf793e22b (commit)
       via  f5b519c416ad70f0bc0e9a5750be1367224eee5a (commit)
       via  46dcb9457edc1bcf224a36f9d559363507440fd7 (commit)
       via  fcc4757823a00ed21cd0b5fd90122eb4f249a10c (commit)
       via  7daf7156d8fb10e8ec18d806b653d425707c2c0d (commit)
       via  f637004037a11bc04682f54571e3ff11d48d8e36 (commit)
       via  a832b5ef7a6080a6a66d1135c80c9aaf5570fc02 (commit)
       via  38df5a452777b612f75796531c0b2629da6aa550 (commit)
       via  538bea6c8184670a8d1608ef288a4e1813dcefa6 (commit)
       via  329114f91f1a560bcf25ff2ebf5d608079e82272 (commit)
       via  2c604cb9af4a879ea43fd7fd84883a5e97ab0fe0 (commit)
       via  6746648c4270442fefc05ae25b0afcf326391b60 (commit)
       via  bfa9a9afe82e603339801da73ddbabd02d919888 (commit)
       via  70ef40a05e06d055a89c6c8f9309f047e7e834f1 (commit)
       via  67f78eadd00ce1c3a5bbde5e42530c1a61d363a2 (commit)
       via  10109364bf0f07c393bd4283470f1bf57f31cecb (commit)
       via  c117af6765928f3fc61585b01f5d722162914d80 (commit)
       via  576eb3958cbb18484680c0bbe7cbf2dce9af0f1b (commit)
       via  b2cc7f313ec1c8386ace3b351457c33af8861ce2 (commit)
       via  e0655186f9c520a7f3c15643081649f841c221ae (commit)
       via  fe5e20fd267bae655c37ba8d67d74c0db566e088 (commit)
       via  1ea4d09a3c049cd3b0748410e0c53b98082980cb (commit)
       via  d781d247d1ef9331983f456d616659108c857d0d (commit)
       via  6cb422654de11eb13f50b36d7d59e65fec029229 (commit)
       via  d49e23ec589e32e70f485fac379417097a831897 (commit)
       via  923ac8271b35eda36eb8fd9d8909671aee3ca022 (commit)
       via  0a87d0ac628685a1b420851f1614829a952cda5f (commit)
       via  a4f376af7e98161c7513614cf4a110724a5a65f5 (commit)
       via  49e7fe12eac1e84af726e0110ee29073699ed46b (commit)
       via  5d5b3fba1fc15e3a63876aa9c8deae351369781b (commit)
       via  29fac541b0af22fa1874c5594fabeff754c7dafe (commit)
       via  048b189336e5703f19e695245ae656513d5f2797 (commit)
       via  3fc8d856105e4716d3121348996ea3c61e7e4b7d (commit)
      from  73fb82b72c7544cf52d95ac29d4a45b253395715 (commit)


- Log -----------------------------------------------------------------
commit 83750d9b2b51bb622138d48fc82eb408b64d8057
Author: Matt Caswell <matt at openssl.org>
Date:   Thu Mar 2 17:40:43 2017 +0000

    More early data documentation updates following feedback
    
    Reviewed-by: Rich Salz <rsalz at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/2737)

commit cd9f7f624ee434606b084d77e6845f15f8c501bc
Author: Matt Caswell <matt at openssl.org>
Date:   Thu Mar 2 16:05:02 2017 +0000

    Update the API documentation for the latest early data changes
    
    Reviewed-by: Rich Salz <rsalz at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/2737)

commit 09f288748266577cc38b77ca31c47b9e9f15890e
Author: Matt Caswell <matt at openssl.org>
Date:   Thu Mar 2 15:49:33 2017 +0000

    Update early data API for writing to unauthenticated clients
    
    Change the early data API so that the server must use
    SSL_write_early_data() to write to an unauthenticated client.
    
    Reviewed-by: Rich Salz <rsalz at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/2737)

commit 0665b4edae3fec740ebe12fe2946d4cc9585ca86
Author: Matt Caswell <matt at openssl.org>
Date:   Thu Mar 2 15:05:36 2017 +0000

    Rename SSL_write_early() to SSL_write_early_data()
    
    This is for consistency with the rest of the API where all the functions
    are called *early_data*.
    
    Reviewed-by: Rich Salz <rsalz at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/2737)

commit f533fbd44a36daac9cc304ff648782e366391b00
Author: Matt Caswell <matt at openssl.org>
Date:   Thu Mar 2 14:42:55 2017 +0000

    Rename SSL_read_early() to SSL_read_early_data()
    
    This is for consistency with the rest of the API where all the functions
    are called *early_data*.
    
    Reviewed-by: Rich Salz <rsalz at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/2737)

commit ef466accdc196fe796301a06cdc6e94cb315ae9b
Author: Matt Caswell <matt at openssl.org>
Date:   Tue Feb 28 00:40:24 2017 +0000

    Updates to the early data documentation
    
    Following on from the latest API changes.
    
    Reviewed-by: Rich Salz <rsalz at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/2737)

commit ade1e88806461df5516525a8f36e707820167e01
Author: Matt Caswell <matt at openssl.org>
Date:   Mon Feb 27 20:55:04 2017 +0000

    Updates to s_server and s_client for the latest early_data API changes
    
    Reviewed-by: Rich Salz <rsalz at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/2737)

commit 3eaa4170956dc7ca2a0c9fc9414dc42cac7b426e
Author: Matt Caswell <matt at openssl.org>
Date:   Mon Feb 27 20:54:39 2017 +0000

    Make SSL_write_early_finish() an internal only function
    
    Reviewed-by: Rich Salz <rsalz at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/2737)

commit 5f9820380ff82fc07e93e430b97da516997d3771
Author: Matt Caswell <matt at openssl.org>
Date:   Mon Feb 27 11:20:22 2017 +0000

    Add early_data tests
    
    Reviewed-by: Rich Salz <rsalz at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/2737)

commit f7e393be4725c33739d46a58de94a06ebdc6e49d
Author: Matt Caswell <matt at openssl.org>
Date:   Mon Feb 27 11:19:57 2017 +0000

    Various fixes required to allow SSL_write/SSL_read during early data
    
    Reviewed-by: Rich Salz <rsalz at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/2737)

commit d7f8783ff9e88ad34e010564d721a55a48c6d674
Author: Matt Caswell <matt at openssl.org>
Date:   Sat Feb 25 15:59:44 2017 +0000

    Enable the server to call SSL_write() without stopping the ability to call SSL_read_early()
    
    Reviewed-by: Rich Salz <rsalz at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/2737)

commit 564547e482406c2d4c56a59e288b3a479dac2d74
Author: Matt Caswell <matt at openssl.org>
Date:   Sat Feb 25 15:34:07 2017 +0000

    Enable the client to call SSL_read() without stopping the ability to call SSL_write_early()
    
    Reviewed-by: Rich Salz <rsalz at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/2737)

commit 4004ce5f6cd6540a07d6d1a4cef7138821d5e596
Author: Matt Caswell <matt at openssl.org>
Date:   Sat Feb 25 00:06:49 2017 +0000

    Introduce a new early_data state in the state machine
    
    Also simplifies the state machine a bit.
    
    Reviewed-by: Rich Salz <rsalz at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/2737)

commit bc908c679b0d13ed5fdeb06d4c2eda8b0b5f5ce6
Author: Matt Caswell <matt at openssl.org>
Date:   Fri Feb 24 17:08:41 2017 +0000

    Improve the early data sanity check in SSL_do_handshake()
    
    Reviewed-by: Rich Salz <rsalz at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/2737)

commit 6437b802f19fb022da88f59cb3071ebdcd2838f6
Author: Matt Caswell <matt at openssl.org>
Date:   Fri Feb 24 16:17:00 2017 +0000

    Add documentation for the new s_client and s_server early_data options
    
    Reviewed-by: Rich Salz <rsalz at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/2737)

commit 0a5ece5bd20aac050d3c77c4f1fb760aa7892ab0
Author: Matt Caswell <matt at openssl.org>
Date:   Fri Feb 24 16:11:03 2017 +0000

    Tighten sanity checks when calling early data functions
    
    Reviewed-by: Rich Salz <rsalz at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/2737)

commit fd6c102520e3829a10fb273eaa62bbccf793e22b
Author: Matt Caswell <matt at openssl.org>
Date:   Fri Feb 24 15:38:38 2017 +0000

    Add documentation for the early data functions
    
    Reviewed-by: Rich Salz <rsalz at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/2737)

commit f5b519c416ad70f0bc0e9a5750be1367224eee5a
Author: Matt Caswell <matt at openssl.org>
Date:   Fri Feb 24 14:17:41 2017 +0000

    Make SSL_get_early_data_status() take a const
    
    Reviewed-by: Rich Salz <rsalz at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/2737)

commit 46dcb9457edc1bcf224a36f9d559363507440fd7
Author: Matt Caswell <matt at openssl.org>
Date:   Fri Feb 24 14:08:59 2017 +0000

    Make SSL_get_max_early_data() and SSL_CTX_get_max_early_data() take a const
    
    Reviewed-by: Rich Salz <rsalz at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/2737)

commit fcc4757823a00ed21cd0b5fd90122eb4f249a10c
Author: Matt Caswell <matt at openssl.org>
Date:   Fri Feb 24 14:08:06 2017 +0000

    Add a SSL_SESSION_get_max_early_data() function
    
    Reviewed-by: Rich Salz <rsalz at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/2737)

commit 7daf7156d8fb10e8ec18d806b653d425707c2c0d
Author: Matt Caswell <matt at openssl.org>
Date:   Fri Feb 24 13:51:04 2017 +0000

    Don't attempt to write more early_data than we know the server will accept
    
    Reviewed-by: Rich Salz <rsalz at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/2737)

commit f637004037a11bc04682f54571e3ff11d48d8e36
Author: Matt Caswell <matt at openssl.org>
Date:   Fri Feb 24 12:45:37 2017 +0000

    Only accept early_data if the negotiated ALPN is the same
    
    Reviewed-by: Rich Salz <rsalz at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/2737)

commit a832b5ef7a6080a6a66d1135c80c9aaf5570fc02
Author: Matt Caswell <matt at openssl.org>
Date:   Fri Feb 24 11:40:49 2017 +0000

    Skip early_data if appropriate after a HelloRetryRequest
    
    Reviewed-by: Rich Salz <rsalz at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/2737)

commit 38df5a452777b612f75796531c0b2629da6aa550
Author: Matt Caswell <matt at openssl.org>
Date:   Fri Feb 24 11:13:25 2017 +0000

    Don't accept early_data if we are going to issue a HelloRetryRequest
    
    Reviewed-by: Rich Salz <rsalz at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/2737)

commit 538bea6c8184670a8d1608ef288a4e1813dcefa6
Author: Matt Caswell <matt at openssl.org>
Date:   Fri Feb 24 10:29:20 2017 +0000

    Add extra validation parsing the server-to-client early_data extension
    
    Check that we actually resumed the session, and that we selected the first
    identity.
    
    Reviewed-by: Rich Salz <rsalz at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/2737)

commit 329114f91f1a560bcf25ff2ebf5d608079e82272
Author: Matt Caswell <matt at openssl.org>
Date:   Fri Feb 24 09:34:32 2017 +0000

    Remove some TLSv1.3 TODOs that are no longer relevant
    
    Reviewed-by: Rich Salz <rsalz at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/2737)

commit 2c604cb9af4a879ea43fd7fd84883a5e97ab0fe0
Author: Matt Caswell <matt at openssl.org>
Date:   Fri Feb 24 09:30:54 2017 +0000

    Validate the ticket age for resumed sessions
    
    If the ticket age calcualtions do not check out then we must not accept
    early data (it could be a replay).
    
    Reviewed-by: Rich Salz <rsalz at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/2737)

commit 6746648c4270442fefc05ae25b0afcf326391b60
Author: Matt Caswell <matt at openssl.org>
Date:   Thu Feb 23 16:54:11 2017 +0000

    Ensure the max_early_data option to s_server can be 0
    
    Reviewed-by: Rich Salz <rsalz at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/2737)

commit bfa9a9afe82e603339801da73ddbabd02d919888
Author: Matt Caswell <matt at openssl.org>
Date:   Thu Feb 23 16:41:15 2017 +0000

    Provide a default value for max_early_data
    
    Reviewed-by: Rich Salz <rsalz at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/2737)

commit 70ef40a05e06d055a89c6c8f9309f047e7e834f1
Author: Matt Caswell <matt at openssl.org>
Date:   Thu Feb 23 14:29:36 2017 +0000

    Check max_early_data against the amount of early data we actually receive
    
    Reviewed-by: Rich Salz <rsalz at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/2737)

commit 67f78eadd00ce1c3a5bbde5e42530c1a61d363a2
Author: Matt Caswell <matt at openssl.org>
Date:   Thu Feb 23 16:05:57 2017 +0000

    Make sure we reset the read sequence when skipping records
    
    Reviewed-by: Rich Salz <rsalz at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/2737)

commit 10109364bf0f07c393bd4283470f1bf57f31cecb
Author: Matt Caswell <matt at openssl.org>
Date:   Thu Feb 23 12:36:35 2017 +0000

    Disallow handshake messages in the middle of early_data
    
    Reviewed-by: Rich Salz <rsalz at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/2737)

commit c117af6765928f3fc61585b01f5d722162914d80
Author: Matt Caswell <matt at openssl.org>
Date:   Thu Feb 23 12:25:21 2017 +0000

    Fix seg fault when sending early_data using CCM ciphersuites
    
    Reviewed-by: Rich Salz <rsalz at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/2737)

commit 576eb3958cbb18484680c0bbe7cbf2dce9af0f1b
Author: Matt Caswell <matt at openssl.org>
Date:   Thu Feb 23 11:52:43 2017 +0000

    Get s_client to report on whether early data was accepted or not
    
    Reviewed-by: Rich Salz <rsalz at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/2737)

commit b2cc7f313ec1c8386ace3b351457c33af8861ce2
Author: Matt Caswell <matt at openssl.org>
Date:   Thu Feb 23 11:53:12 2017 +0000

    Implement client side parsing of the early_data extension
    
    Reviewed-by: Rich Salz <rsalz at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/2737)

commit e0655186f9c520a7f3c15643081649f841c221ae
Author: Matt Caswell <matt at openssl.org>
Date:   Wed Feb 22 15:24:11 2017 +0000

    Add a "-early_data" option to s_server
    
    Reviewed-by: Rich Salz <rsalz at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/2737)

commit fe5e20fd267bae655c37ba8d67d74c0db566e088
Author: Matt Caswell <matt at openssl.org>
Date:   Wed Feb 22 14:09:42 2017 +0000

    Fix changing of the cipher state when dealing with early data
    
    Reviewed-by: Rich Salz <rsalz at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/2737)

commit 1ea4d09a3c049cd3b0748410e0c53b98082980cb
Author: Matt Caswell <matt at openssl.org>
Date:   Wed Feb 22 13:01:48 2017 +0000

    Construct the server side early_data extension
    
    Reviewed-by: Rich Salz <rsalz at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/2737)

commit d781d247d1ef9331983f456d616659108c857d0d
Author: Matt Caswell <matt at openssl.org>
Date:   Tue Feb 21 17:14:42 2017 +0000

    Provide an SSL_read_early() function for reading early data
    
    Reviewed-by: Rich Salz <rsalz at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/2737)

commit 6cb422654de11eb13f50b36d7d59e65fec029229
Author: Matt Caswell <matt at openssl.org>
Date:   Tue Feb 21 16:40:16 2017 +0000

    Change the cipher state when sending early data
    
    Reviewed-by: Rich Salz <rsalz at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/2737)

commit d49e23ec589e32e70f485fac379417097a831897
Author: Matt Caswell <matt at openssl.org>
Date:   Tue Feb 21 16:39:43 2017 +0000

    Implement the early data changes required in tls13_change_cipher_state()
    
    Reviewed-by: Rich Salz <rsalz at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/2737)

commit 923ac8271b35eda36eb8fd9d8909671aee3ca022
Author: Matt Caswell <matt at openssl.org>
Date:   Mon Feb 20 16:00:20 2017 +0000

    Add an option to s_client to send early_data
    
    Reviewed-by: Rich Salz <rsalz at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/2737)

commit 0a87d0ac628685a1b420851f1614829a952cda5f
Author: Matt Caswell <matt at openssl.org>
Date:   Mon Feb 20 16:35:03 2017 +0000

    Parse the early_data extension
    
    We also skip any early_data that subsequently gets sent. Later commits will
    process it if we can.
    
    Reviewed-by: Rich Salz <rsalz at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/2737)

commit a4f376af7e98161c7513614cf4a110724a5a65f5
Author: Matt Caswell <matt at openssl.org>
Date:   Mon Feb 20 15:44:42 2017 +0000

    Construct the early_data extension
    
    Reviewed-by: Rich Salz <rsalz at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/2737)

commit 49e7fe12eac1e84af726e0110ee29073699ed46b
Author: Matt Caswell <matt at openssl.org>
Date:   Tue Feb 21 09:22:22 2017 +0000

    Provide functions to write early data
    
    We provide SSL_write_early() which *must* be called first on a connection
    (prior to any other IO function including SSL_connect()/SSL_do_handshake()).
    Also SSL_write_early_finish() which signals the end of early data.
    
    Reviewed-by: Rich Salz <rsalz at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/2737)

commit 5d5b3fba1fc15e3a63876aa9c8deae351369781b
Author: Matt Caswell <matt at openssl.org>
Date:   Mon Feb 20 14:56:51 2017 +0000

    Parse the ticket_early_data_info extension
    
    Reviewed-by: Rich Salz <rsalz at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/2737)

commit 29fac541b0af22fa1874c5594fabeff754c7dafe
Author: Matt Caswell <matt at openssl.org>
Date:   Fri Feb 17 17:41:46 2017 +0000

    Teach SSL_trace() about the early_data_info extension
    
    Reviewed-by: Rich Salz <rsalz at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/2737)

commit 048b189336e5703f19e695245ae656513d5f2797
Author: Matt Caswell <matt at openssl.org>
Date:   Fri Feb 17 17:01:16 2017 +0000

    Add a -max_early_data option to s_server
    
    Allows you to set the number of bytes that can be sent as early data
    
    Reviewed-by: Rich Salz <rsalz at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/2737)

commit 3fc8d856105e4716d3121348996ea3c61e7e4b7d
Author: Matt Caswell <matt at openssl.org>
Date:   Fri Feb 17 16:52:12 2017 +0000

    Construct the ticket_early_data_info extension
    
    Reviewed-by: Rich Salz <rsalz at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/2737)

-----------------------------------------------------------------------

Summary of changes:
 apps/s_client.c                  |  59 +++-
 apps/s_server.c                  |  87 +++++-
 doc/man1/s_client.pod            |  10 +-
 doc/man1/s_server.pod            |  13 +
 doc/man3/SSL_read_early_data.pod | 216 +++++++++++++
 include/openssl/ssl.h            |  37 ++-
 include/openssl/ssl3.h           |  13 +-
 include/openssl/tls1.h           |   3 +
 ssl/record/rec_layer_s3.c        |  48 ++-
 ssl/record/record_locl.h         |   1 +
 ssl/record/ssl3_record.c         |  85 ++++-
 ssl/record/ssl3_record_tls13.c   |  20 +-
 ssl/s3_msg.c                     |   5 +-
 ssl/ssl_asn1.c                   |  28 +-
 ssl/ssl_err.c                    |  16 +
 ssl/ssl_lib.c                    | 212 +++++++++++++
 ssl/ssl_locl.h                   |  76 ++++-
 ssl/ssl_sess.c                   |   6 +
 ssl/statem/extensions.c          |  43 +++
 ssl/statem/extensions_clnt.c     |  68 ++++
 ssl/statem/extensions_srvr.c     |  79 ++++-
 ssl/statem/statem.c              |  57 +++-
 ssl/statem/statem.h              |   3 +
 ssl/statem/statem_clnt.c         |  81 ++++-
 ssl/statem/statem_lib.c          |  24 ++
 ssl/statem/statem_locl.h         |  16 +
 ssl/statem/statem_srvr.c         |  79 +++--
 ssl/t1_enc.c                     |   8 +-
 ssl/t1_trce.c                    |  14 +-
 ssl/tls13_enc.c                  | 124 ++++++--
 test/sslapitest.c                | 655 +++++++++++++++++++++++++++++++++++++++
 test/tls13secretstest.c          |   9 +-
 util/libssl.num                  |   8 +
 33 files changed, 2084 insertions(+), 119 deletions(-)
 create mode 100644 doc/man3/SSL_read_early_data.pod

diff --git a/apps/s_client.c b/apps/s_client.c
index 351b5b9..b48c306 100644
--- a/apps/s_client.c
+++ b/apps/s_client.c
@@ -547,7 +547,7 @@ typedef enum OPTION_choice {
     OPT_SERVERINFO, OPT_STARTTLS, OPT_SERVERNAME,
     OPT_USE_SRTP, OPT_KEYMATEXPORT, OPT_KEYMATEXPORTLEN, OPT_SMTPHOST,
     OPT_ASYNC, OPT_SPLIT_SEND_FRAG, OPT_MAX_PIPELINES, OPT_READ_BUF,
-    OPT_KEYLOG_FILE,
+    OPT_KEYLOG_FILE, OPT_EARLY_DATA,
     OPT_V_ENUM,
     OPT_X_ENUM,
     OPT_S_ENUM,
@@ -732,6 +732,7 @@ const OPTIONS s_client_options[] = {
     {"ctlogfile", OPT_CTLOG_FILE, '<', "CT log list CONF file"},
 #endif
     {"keylogfile", OPT_KEYLOG_FILE, '>', "Write TLS secrets to file"},
+    {"early_data", OPT_EARLY_DATA, '<', "File to send as early data"},
     {NULL, OPT_EOF, 0x00, NULL}
 };
 
@@ -895,7 +896,7 @@ int s_client_main(int argc, char **argv)
     int c_status_req = 0;
 #endif
     BIO *bio_c_msg = NULL;
-    const char *keylog_file = NULL;
+    const char *keylog_file = NULL, *early_data_file = NULL;
 
     FD_ZERO(&readfds);
     FD_ZERO(&writefds);
@@ -1371,6 +1372,9 @@ int s_client_main(int argc, char **argv)
         case OPT_KEYLOG_FILE:
             keylog_file = opt_arg();
             break;
+        case OPT_EARLY_DATA:
+            early_data_file = opt_arg();
+            break;
         }
     }
     if (count4or6 >= 2) {
@@ -2355,6 +2359,40 @@ int s_client_main(int argc, char **argv)
         break;
     }
 
+    if (early_data_file != NULL
+            && SSL_get0_session(con) != NULL
+            && SSL_SESSION_get_max_early_data(SSL_get0_session(con)) > 0) {
+        BIO *edfile = BIO_new_file(early_data_file, "r");
+        size_t readbytes, writtenbytes;
+        int finish = 0;
+
+        if (edfile == NULL) {
+            BIO_printf(bio_err, "Cannot open early data file\n");
+            goto shut;
+        }
+
+        while (!finish) {
+            if (!BIO_read_ex(edfile, cbuf, BUFSIZZ, &readbytes))
+                finish = 1;
+
+            while (!SSL_write_early_data(con, cbuf, readbytes, &writtenbytes)) {
+                switch (SSL_get_error(con, 0)) {
+                case SSL_ERROR_WANT_WRITE:
+                case SSL_ERROR_WANT_ASYNC:
+                case SSL_ERROR_WANT_READ:
+                    /* Just keep trying - busy waiting */
+                    continue;
+                default:
+                    BIO_printf(bio_err, "Error writing early data\n");
+                    BIO_free(edfile);
+                    goto shut;
+                }
+            }
+        }
+
+        BIO_free(edfile);
+    }
+
     for (;;) {
         FD_ZERO(&readfds);
         FD_ZERO(&writefds);
@@ -2940,6 +2978,23 @@ static void print_stuff(BIO *bio, SSL *s, int full)
     }
 #endif
 
+    if (SSL_version(s) == TLS1_3_VERSION) {
+        switch (SSL_get_early_data_status(s)) {
+        case SSL_EARLY_DATA_NOT_SENT:
+            BIO_printf(bio, "Early data was not sent\n");
+            break;
+
+        case SSL_EARLY_DATA_REJECTED:
+            BIO_printf(bio, "Early data was rejected\n");
+            break;
+
+        case SSL_EARLY_DATA_ACCEPTED:
+            BIO_printf(bio, "Early data was accepted\n");
+            break;
+
+        }
+    }
+
     SSL_SESSION_print(bio, SSL_get_session(s));
     if (SSL_get_session(s) != NULL && keymatexportlabel != NULL) {
         BIO_printf(bio, "Keying material exporter:\n");
diff --git a/apps/s_server.c b/apps/s_server.c
index 6d35cb8..3190eab 100644
--- a/apps/s_server.c
+++ b/apps/s_server.c
@@ -104,6 +104,7 @@ static void free_sessions(void);
 #ifndef OPENSSL_NO_DH
 static DH *load_dh_param(const char *dhfile);
 #endif
+static void print_connection_info(SSL *con);
 
 /* static int load_CA(SSL_CTX *ctx, char *file);*/
 
@@ -147,6 +148,8 @@ static int dtlslisten = 0;
 static char *psk_identity = "Client_identity";
 char *psk_key = NULL;           /* by default PSK is not used */
 
+int early_data = 0;
+
 static unsigned int psk_server_cb(SSL *ssl, const char *identity,
                                   unsigned char *psk,
                                   unsigned int max_psk_len)
@@ -719,7 +722,7 @@ typedef enum OPTION_choice {
     OPT_ID_PREFIX, OPT_RAND, OPT_SERVERNAME, OPT_SERVERNAME_FATAL,
     OPT_CERT2, OPT_KEY2, OPT_NEXTPROTONEG, OPT_ALPN,
     OPT_SRTP_PROFILES, OPT_KEYMATEXPORT, OPT_KEYMATEXPORTLEN,
-    OPT_KEYLOG_FILE,
+    OPT_KEYLOG_FILE, OPT_MAX_EARLY, OPT_EARLY_DATA,
     OPT_S_ENUM,
     OPT_V_ENUM,
     OPT_X_ENUM
@@ -916,6 +919,9 @@ const OPTIONS s_server_options[] = {
     {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"},
 #endif
     {"keylogfile", OPT_KEYLOG_FILE, '>', "Write TLS secrets to file"},
+    {"max_early_data", OPT_MAX_EARLY, 'n',
+     "The maximum number of bytes of early data"},
+    {"early_data", OPT_EARLY_DATA, '-', "Attempt to read early data"},
     {NULL, OPT_EOF, 0, NULL}
 };
 
@@ -992,6 +998,7 @@ int s_server_main(int argc, char *argv[])
     unsigned int split_send_fragment = 0, max_pipelines = 0;
     const char *s_serverinfo_file = NULL;
     const char *keylog_file = NULL;
+    int max_early_data = -1;
 
     /* Init of few remaining global variables */
     local_argc = argc;
@@ -1500,7 +1507,16 @@ int s_server_main(int argc, char *argv[])
         case OPT_KEYLOG_FILE:
             keylog_file = opt_arg();
             break;
-
+        case OPT_MAX_EARLY:
+            max_early_data = atoi(opt_arg());
+            if (max_early_data < 0) {
+                BIO_printf(bio_err, "Invalid value for max_early_data\n");
+                goto end;
+            }
+            break;
+        case OPT_EARLY_DATA:
+            early_data = 1;
+            break;
         }
     }
     argc = opt_num_rest();
@@ -1991,6 +2007,9 @@ int s_server_main(int argc, char *argv[])
     if (set_keylog_file(ctx, keylog_file))
         goto end;
 
+    if (max_early_data >= 0)
+        SSL_CTX_set_max_early_data(ctx, max_early_data);
+
     BIO_printf(bio_s_out, "ACCEPT\n");
     (void)BIO_flush(bio_s_out);
     if (rev)
@@ -2191,6 +2210,45 @@ static int sv_body(int s, int stype, unsigned char *context)
         SSL_set_tlsext_debug_arg(con, bio_s_out);
     }
 
+    if (early_data) {
+        int write_header = 1, edret = SSL_READ_EARLY_DATA_ERROR;
+        size_t readbytes;
+
+        while (edret != SSL_READ_EARLY_DATA_FINISH) {
+            for (;;) {
+                edret = SSL_read_early_data(con, buf, bufsize, &readbytes);
+                if (edret != SSL_READ_EARLY_DATA_ERROR)
+                    break;
+
+                switch (SSL_get_error(con, 0)) {
+                case SSL_ERROR_WANT_WRITE:
+                case SSL_ERROR_WANT_ASYNC:
+                case SSL_ERROR_WANT_READ:
+                    /* Just keep trying - busy waiting */
+                    continue;
+                default:
+                    BIO_printf(bio_err, "Error reading early data\n");
+                    ERR_print_errors(bio_err);
+                    goto err;
+                }
+            }
+            if (readbytes > 0) {
+                if (write_header) {
+                    BIO_printf(bio_s_out, "Early data received:\n");
+                    write_header = 0;
+                }
+                raw_write_stdout(buf, (unsigned int)readbytes);
+                (void)BIO_flush(bio_s_out);
+            }
+        }
+        if (write_header)
+            BIO_printf(bio_s_out, "No early data received\n");
+        else
+            BIO_printf(bio_s_out, "\nEnd of early data\n");
+        if (SSL_is_init_finished(con))
+            print_connection_info(con);
+    }
+
     if (fileno_stdin() > s)
         width = fileno_stdin() + 1;
     else
@@ -2516,15 +2574,7 @@ static void close_accept_socket(void)
 static int init_ssl_connection(SSL *con)
 {
     int i;
-    const char *str;
-    X509 *peer;
     long verify_err;
-    char buf[BUFSIZ];
-#if !defined(OPENSSL_NO_NEXTPROTONEG)
-    const unsigned char *next_proto_neg;
-    unsigned next_proto_neg_len;
-#endif
-    unsigned char *exportedkeymat;
     int retry = 0;
 
 #ifndef OPENSSL_NO_DTLS
@@ -2618,6 +2668,22 @@ static int init_ssl_connection(SSL *con)
         return (0);
     }
 
+    print_connection_info(con);
+    return 1;
+}
+
+static void print_connection_info(SSL *con)
+{
+    const char *str;
+    X509 *peer;
+    char buf[BUFSIZ];
+#if !defined(OPENSSL_NO_NEXTPROTONEG)
+    const unsigned char *next_proto_neg;
+    unsigned next_proto_neg_len;
+#endif
+    unsigned char *exportedkeymat;
+    int i;
+
     if (s_brief)
         print_ssl_summary(con);
 
@@ -2688,7 +2754,6 @@ static int init_ssl_connection(SSL *con)
     }
 
     (void)BIO_flush(bio_s_out);
-    return (1);
 }
 
 #ifndef OPENSSL_NO_DH
diff --git a/doc/man1/s_client.pod b/doc/man1/s_client.pod
index 0c9329d..bbb86c2 100644
--- a/doc/man1/s_client.pod
+++ b/doc/man1/s_client.pod
@@ -105,6 +105,8 @@ B<openssl> B<s_client>
 [B<-nextprotoneg protocols>]
 [B<-ct|noct>]
 [B<-ctlogfile>]
+[B<-keylogfile file>]
+[B<-early_data file>]
 
 =head1 DESCRIPTION
 
@@ -528,11 +530,17 @@ for SCTs.
 A file containing a list of known Certificate Transparency logs. See
 L<SSL_CTX_set_ctlog_list_file(3)> for the expected file format.
 
-=item B<-keylogfile path>
+=item B<-keylogfile file>
 
 Appends TLS secrets to the specified keylog file such that external programs
 (like Wireshark) can decrypt TLS connections.
 
+=item B<-early_data file>
+
+Reads the contents of the specified file and attempts to send it as early data
+to the server. This will only work with resumed sessions that support early
+data and when the server accepts the early data.
+
 =back
 
 =head1 CONNECTED COMMANDS
diff --git a/doc/man1/s_server.pod b/doc/man1/s_server.pod
index 94289e8..c16b562 100644
--- a/doc/man1/s_server.pod
+++ b/doc/man1/s_server.pod
@@ -113,6 +113,8 @@ B<openssl> B<s_server>
 [B<-status_file file>]
 [B<-alpn protocols>]
 [B<-nextprotoneg protocols>]
+[B<-max_early_data>]
+[B<-early_data>]
 
 =head1 DESCRIPTION
 
@@ -527,6 +529,17 @@ The list should contain most wanted protocols first.
 Protocol names are printable ASCII strings, for example "http/1.1" or
 "spdy/3".
 
+=item B<-max_early_data arg>
+
+Change the default maximum early data bytes that are specified for new sessions
+and any incoming early data (when used in conjunction with the B<-early_data>
+flag). The default value is approximately 16k. The argument must be an integer
+greater than or equal to 0.
+
+=item B<-early_data>
+
+Accept early data where possible.
+
 =back
 
 =head1 CONNECTED COMMANDS
diff --git a/doc/man3/SSL_read_early_data.pod b/doc/man3/SSL_read_early_data.pod
new file mode 100644
index 0000000..4567de7
--- /dev/null
+++ b/doc/man3/SSL_read_early_data.pod
@@ -0,0 +1,216 @@
+=pod
+
+=head1 NAME
+
+SSL_set_max_early_data,
+SSL_CTX_set_max_early_data,
+SSL_get_max_early_data,
+SSL_CTX_get_max_early_data,
+SSL_SESSION_get_max_early_data,
+SSL_write_early_data,
+SSL_read_early_data,
+SSL_get_early_data_status
+- functions for sending and receiving early data
+
+=head1 SYNOPSIS
+
+ #include <openssl/ssl.h>
+
+ int SSL_CTX_set_max_early_data(SSL_CTX *ctx, uint32_t max_early_data);
+ uint32_t SSL_CTX_get_max_early_data(const SSL_CTX *ctx);
+ int SSL_set_max_early_data(SSL *s, uint32_t max_early_data);
+ uint32_t SSL_get_max_early_data(const SSL_CTX *s);
+ uint32_t SSL_SESSION_get_max_early_data(const SSL_SESSION *s);
+
+ int SSL_write_early_data(SSL *s, const void *buf, size_t num, size_t *written);
+
+ int SSL_read_early_data(SSL *s, void *buf, size_t num, size_t *readbytes);
+
+ int SSL_get_early_data_status(const SSL *s);
+
+=head1 DESCRIPTION
+
+These functions are used to send and recieve early data where TLSv1.3 has been
+negotiated. Early data can be sent by the client immediately after its initial
+ClientHello without having to wait for the server to complete the handshake.
+Early data can only be sent if a session has previously been established with
+the server, and the server is known to support it. Additionally these functions
+can be used to send data from the server to the client when the client has not
+yet completed the authentication stage of the handshake.
+
+Early data has weaker security properties than other data sent over an SSL/TLS
+connection. In particular the data does not have forward secrecy and there are
+no guarantees that the same early data was not replayed across multiple
+connections. For this reason extreme care should be exercised when using early
+data. For specific details, consult the TLS 1.3 specification.
+
+When a server receives early data it may opt to immediately respond by sending
+application data back to the client. Data sent by the server at this stage is
+done before the full handshake has been completed. Specifically the client's
+authentication messages have not yet been received, i.e. the client is
+unauthenticated at this point and care should be taken when using this
+capability.
+
+A server or client can determine whether the full handshake has been completed
+or not by calling L<SSL_is_init_finished(3)>.
+
+On the client side, the function SSL_SESSION_get_max_early_data() can be used to
+determine if a session established with a server can be used to send early data.
+If the session cannot be used then this function will return 0. Otherwise it
+will return the maximum number of early data bytes that can be sent.
+
+A client uses the function SSL_write_early_data() to send early data. This
+function is similar to the L<SSL_write_ex(3)> function, but with the following
+differences. See L<SSL_write_ex(3)> for information on how to write bytes to
+the underlying connection, and how to handle any errors that may arise. This 
+page describes the differences between SSL_write_early_data() and
+L<SSL_write_ex(3)>.
+
+When called by a client, SSL_write_early_data() must be the first IO function
+called on a new connection, i.e. it must occur before any calls to
+L<SSL_write_ex(3)>, L<SSL_read_ex(3)>, L<SSL_connect(3)>, L<SSL_do_handshake(3)>
+or other similar functions. It may be called multiple times to stream data to
+the server, but the total number of bytes written must not exceed the value
+returned from SSL_SESSION_get_max_early_data(). Once the initial
+SSL_write_early_data() call has completed successfully the client may interleave
+calls to L<SSL_read_ex(3)> and L<SSL_read(3)> with calls to
+SSL_write_early_data() as required.
+
+If SSL_write_early_data() fails you should call L<SSL_get_error(3)> to determine
+the correct course of action, as for L<SSL_write_ex(3)>.
+
+When the client no longer wishes to send any more early data then it should
+complete the handshake by calling a function such as L<SSL_connect(3)> or
+L<SSL_do_handshake(3)>. Alternatively you can call a standard write function
+such as L<SSL_write_ex(3)>, which will transparently complete the connection and
+write the requested data.
+
+A server may choose to ignore early data that has been sent to it. Once the
+connection has been completed you can determine whether the server accepted or
+rejected the early data by calling SSL_get_early_data_status(). This will return
+SSL_EARLY_DATA_ACCEPTED if the data was accepted, SSL_EARLY_DATA_REJECTED if it
+was rejected or SSL_EARLY_DATA_NOT_SENT if no early data was sent. This function
+may be called by either the client or the server.
+
+A server uses the SSL_read_early_data() function to receive early data on a
+connection. As for SSL_write_early_data() this must be the first IO function
+called on a connection, i.e. it must occur before any calls to
+L<SSL_write_ex(3)>, L<SSL_read_ex(3)>, L<SSL_accept(3)>, L<SSL_do_handshake(3)>,
+or other similar functions.
+
+SSL_read_early_data() is similar to L<SSL_read_ex(3)> with the following
+differences. Refer to L<SSL_read_ex(3)> for full details.
+
+SSL_read_early_data() may return 3 possible values:
+
+=over 4
+
+=item SSL_READ_EARLY_DATA_ERROR
+
+This indicates an IO or some other error occured. This should be treated in the
+same way as a 0 return value from L<SSL_read_ex(3)>.
+
+=item SSL_READ_EARLY_DATA_SUCCESS
+
+This indicates that early data was successfully read. This should be treated in
+the same way as a 1 return value from L<SSL_read_ex(3)>. You should continue to
+call SSL_read_early_data() to read more data.
+
+=item SSL_READ_EARLY_DATA_FINISH
+
+This indicates that no more early data can be read. It may be returned on the
+first call to SSL_read_early_data() if the client has not sent any early data,
+or if the early data was rejected.
+
+=back
+
+Once the initial SSL_read_early_data() call has completed successfully (i.e. it
+has returned SSL_READ_EARLY_DATA_SUCCESS or SSL_READ_EARLY_DATA_FINISH) then the
+server may choose to write data immediately to the unauthenticated client using
+SSL_write_early_data(). If SSL_read_early_data() returned
+SSL_READ_EARLY_DATA_FINISH then in some situations (e.g. if the client only
+supports TLSv1.2) the handshake may have already been completed and calls
+to SSL_write_early_data() are not allowed. Call L<SSL_is_init_finished(3)> to
+determine whether the handshake has completed or not. If the handshake is still
+in progress then the server may interleave calls to SSL_write_early_data() with
+calls to SSL_read_early_data() as required.
+
+Servers must not call L<SSL_read_ex(3)>, L<SSL_read(3)>, L<SSL_write_ex(3)> or
+L<SSL_write(3)>  until SSL_read_early_data() has returned with
+SSL_READ_EARLY_DATA_FINISH. Once it has done so the connection to the client
+still needs to be completed. Complete the connection by calling a function such
+as L<SSL_accept(3)> or L<SSL_do_handshake(3)>. Alternatively you can call a
+standard read function such as L<SSL_read_ex(3)>, which will transparently
+complete the connection and read the requested data. Note that it is an error to
+attempt to complete the connection before SSL_read_early_data() has returned
+SSL_READ_EARLY_DATA_FINISH.
+
+Only servers may call SSL_read_early_data().
+
+Calls to SSL_read_early_data() may, in certain circumstances, complete the
+connection immediately without further need to call a function such as
+L<SSL_accept(3)>. This can happen if the client is using a protocol version less
+than TLSv1.3. Applications can test for this by calling
+L<SSL_is_init_finished(3)>. Alternatively, applications may choose to call
+L<SSL_accept(3)> anway. Such a call will successfully return immediately with no
+further action taken.
+
+When a session is created between a server and a client the server will specify
+the maximum amount of any early data that it will accept on any future
+connection attempt. By default this is approximately 16k. A server may override
+this default value by calling SSL_CTX_set_max_early_data() or
+SSL_set_max_early_data() to set it for the whole SSL_CTX or an individual SSL
+object respectively. Similarly the SSL_CTX_get_max_early_data() and
+SSL_get_max_early_data() functions can be used to obtain the current maximum
+early data settings for the SSL_CTX and SSL objects respectively.
+
+In the event that the current maximum early data setting for the server is
+different to that originally specified in a session that a client is resuming
+with then the lower of the two values will apply.
+
+=head1 RETURN VALUES
+
+SSL_write_early_data() returns 1 for success or 0 for failure. In the event of a
+failure call L<SSL_get_error(3)> to determine the correct course of action.
+
+SSL_read_early_data() returns SSL_READ_EARLY_DATA_ERROR for failure,
+SSL_READ_EARLY_DATA_SUCCESS for success with more data to read and
+SSL_READ_EARLY_DATA_FINISH for success with no more to data be read. In the
+event of a failure call L<SSL_get_error(3)> to determine the correct course of
+action.
+
+SSL_get_max_early_data(), SSL_CTX_get_max_early_data() and
+SSL_SESSION_get_max_early_data() return the maximum number of early data bytes
+that may be sent.
+
+SSL_set_max_early_data() and SSL_CTX_set_max_early_data() return 1 for success
+or 0 for failure.
+
+SSL_get_early_data_status() returns SSL_EARLY_DATA_ACCEPTED if early data was
+accepted by the server, SSL_EARLY_DATA_REJECTED if early data was rejected by
+the server, or SSL_EARLY_DATA_NOT_SENT if no early data was sent.
+
+=head1 SEE ALSO
+
+L<SSL_get_error(3)>,
+L<SSL_write_ex(3)>,
+L<SSL_read_ex(3)>,
+L<SSL_connect(3)>,
+L<SSL_accept(3)>,
+L<SSL_do_handshake(3)>,
+L<ssl(7)>
+
+=head1 HISTORY
+
+All of the functions described above were added in OpenSSL 1.1.1.
+
+=head1 COPYRIGHT
+
+Copyright 2017 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the OpenSSL license (the "License").  You may not use
+this file except in compliance with the License.  You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/include/openssl/ssl.h b/include/openssl/ssl.h
index 9e87c6b..2b4464c 100644
--- a/include/openssl/ssl.h
+++ b/include/openssl/ssl.h
@@ -797,6 +797,11 @@ void SSL_CTX_set_keylog_callback(SSL_CTX *ctx, SSL_CTX_keylog_cb_func cb);
  */
 SSL_CTX_keylog_cb_func SSL_CTX_get_keylog_callback(const SSL_CTX *ctx);
 
+int SSL_CTX_set_max_early_data(SSL_CTX *ctx, uint32_t max_early_data);
+uint32_t SSL_CTX_get_max_early_data(const SSL_CTX *ctx);
+int SSL_set_max_early_data(SSL *s, uint32_t max_early_data);
+uint32_t SSL_get_max_early_data(const SSL_CTX *s);
+
 #ifdef __cplusplus
 }
 #endif
@@ -894,7 +899,9 @@ typedef enum {
     TLS_ST_SW_KEY_UPDATE,
     TLS_ST_CW_KEY_UPDATE,
     TLS_ST_SR_KEY_UPDATE,
-    TLS_ST_CR_KEY_UPDATE
+    TLS_ST_CR_KEY_UPDATE,
+    TLS_ST_EARLY_DATA,
+    TLS_ST_PENDING_EARLY_DATA_END
 } OSSL_HANDSHAKE_STATE;
 
 /*
@@ -1020,6 +1027,7 @@ DECLARE_PEM_rw(SSL_SESSION, SSL_SESSION)
 # define SSL_AD_INTERNAL_ERROR           TLS1_AD_INTERNAL_ERROR
 # define SSL_AD_USER_CANCELLED           TLS1_AD_USER_CANCELLED
 # define SSL_AD_NO_RENEGOTIATION         TLS1_AD_NO_RENEGOTIATION
+# define SSL_AD_END_OF_EARLY_DATA        TLS13_AD_END_OF_EARLY_DATA
 # define SSL_AD_MISSING_EXTENSION        TLS13_AD_MISSING_EXTENSION
 # define SSL_AD_UNSUPPORTED_EXTENSION    TLS1_AD_UNSUPPORTED_EXTENSION
 # define SSL_AD_CERTIFICATE_UNOBTAINABLE TLS1_AD_CERTIFICATE_UNOBTAINABLE
@@ -1432,6 +1440,7 @@ __owur int SSL_SESSION_has_ticket(const SSL_SESSION *s);
 __owur unsigned long SSL_SESSION_get_ticket_lifetime_hint(const SSL_SESSION *s);
 void SSL_SESSION_get0_ticket(const SSL_SESSION *s, const unsigned char **tick,
                             size_t *len);
+__owur uint32_t SSL_SESSION_get_max_early_data(const SSL_SESSION *s);
 __owur int SSL_copy_session_id(SSL *to, const SSL *from);
 __owur X509 *SSL_SESSION_get0_peer(SSL_SESSION *s);
 __owur int SSL_SESSION_set1_id_context(SSL_SESSION *s, const unsigned char *sid_ctx,
@@ -1605,15 +1614,30 @@ __owur int SSL_accept(SSL *ssl);
 __owur int SSL_connect(SSL *ssl);
 __owur int SSL_read(SSL *ssl, void *buf, int num);
 __owur int SSL_read_ex(SSL *ssl, void *buf, size_t num, size_t *readbytes);
+
+# define SSL_READ_EARLY_DATA_ERROR   0
+# define SSL_READ_EARLY_DATA_SUCCESS 1
+# define SSL_READ_EARLY_DATA_FINISH  2
+
+__owur int SSL_read_early_data(SSL *s, void *buf, size_t num,
+                               size_t *readbytes);
 __owur int SSL_peek(SSL *ssl, void *buf, int num);
 __owur int SSL_peek_ex(SSL *ssl, void *buf, size_t num, size_t *readbytes);
 __owur int SSL_write(SSL *ssl, const void *buf, int num);
 __owur int SSL_write_ex(SSL *s, const void *buf, size_t num, size_t *written);
+__owur int SSL_write_early_data(SSL *s, const void *buf, size_t num,
+                                size_t *written);
 long SSL_ctrl(SSL *ssl, int cmd, long larg, void *parg);
 long SSL_callback_ctrl(SSL *, int, void (*)(void));
 long SSL_CTX_ctrl(SSL_CTX *ctx, int cmd, long larg, void *parg);
 long SSL_CTX_callback_ctrl(SSL_CTX *, int, void (*)(void));
 
+# define SSL_EARLY_DATA_NOT_SENT    0
+# define SSL_EARLY_DATA_REJECTED    1
+# define SSL_EARLY_DATA_ACCEPTED    2
+
+__owur int SSL_get_early_data_status(const SSL *s);
+
 __owur int SSL_get_error(const SSL *s, int ret_code);
 __owur const char *SSL_get_version(const SSL *s);
 
@@ -2133,6 +2157,7 @@ int ERR_load_SSL_strings(void);
 # define SSL_F_DTLS_CONSTRUCT_HELLO_VERIFY_REQUEST        385
 # define SSL_F_DTLS_GET_REASSEMBLED_MESSAGE               370
 # define SSL_F_DTLS_PROCESS_HELLO_VERIFY                  386
+# define SSL_F_EARLY_DATA_COUNT_OK                        532
 # define SSL_F_FINAL_EC_PT_FORMATS                        485
 # define SSL_F_FINAL_EMS                                  486
 # define SSL_F_FINAL_KEY_SHARE                            503
@@ -2246,6 +2271,7 @@ int ERR_load_SSL_strings(void);
 # define SSL_F_SSL_PEEK_EX                                432
 # define SSL_F_SSL_PEEK_INTERNAL                          522
 # define SSL_F_SSL_READ                                   223
+# define SSL_F_SSL_READ_EARLY_DATA                        529
 # define SSL_F_SSL_READ_EX                                434
 # define SSL_F_SSL_READ_INTERNAL                          523
 # define SSL_F_SSL_RENEGOTIATE                            516
@@ -2285,6 +2311,8 @@ int ERR_load_SSL_strings(void);
 # define SSL_F_SSL_VALIDATE_CT                            400
 # define SSL_F_SSL_VERIFY_CERT_CHAIN                      207
 # define SSL_F_SSL_WRITE                                  208
+# define SSL_F_SSL_WRITE_EARLY_DATA                       526
+# define SSL_F_SSL_WRITE_EARLY_FINISH                     527
 # define SSL_F_SSL_WRITE_EX                               433
 # define SSL_F_SSL_WRITE_INTERNAL                         524
 # define SSL_F_STATE_MACHINE                              353
@@ -2319,6 +2347,7 @@ int ERR_load_SSL_strings(void);
 # define SSL_F_TLS_CONSTRUCT_CLIENT_VERIFY                489
 # define SSL_F_TLS_CONSTRUCT_CTOS_ALPN                    466
 # define SSL_F_TLS_CONSTRUCT_CTOS_CERTIFICATE             355
+# define SSL_F_TLS_CONSTRUCT_CTOS_EARLY_DATA              530
 # define SSL_F_TLS_CONSTRUCT_CTOS_EC_PT_FORMATS           467
 # define SSL_F_TLS_CONSTRUCT_CTOS_EMS                     468
 # define SSL_F_TLS_CONSTRUCT_CTOS_ETM                     469
@@ -2355,6 +2384,8 @@ int ERR_load_SSL_strings(void);
 # define SSL_F_TLS_CONSTRUCT_STOC_CERTIFICATE             374
 # define SSL_F_TLS_CONSTRUCT_STOC_CRYPTOPRO_BUG           452
 # define SSL_F_TLS_CONSTRUCT_STOC_DONE                    375
+# define SSL_F_TLS_CONSTRUCT_STOC_EARLY_DATA              531
+# define SSL_F_TLS_CONSTRUCT_STOC_EARLY_DATA_INFO         525
 # define SSL_F_TLS_CONSTRUCT_STOC_EC_PT_FORMATS           453
 # define SSL_F_TLS_CONSTRUCT_STOC_EMS                     454
 # define SSL_F_TLS_CONSTRUCT_STOC_ETM                     455
@@ -2376,6 +2407,7 @@ int ERR_load_SSL_strings(void);
 # define SSL_F_TLS_PARSE_CTOS_PSK                         505
 # define SSL_F_TLS_PARSE_CTOS_RENEGOTIATE                 464
 # define SSL_F_TLS_PARSE_CTOS_USE_SRTP                    465
+# define SSL_F_TLS_PARSE_STOC_EARLY_DATA_INFO             528
 # define SSL_F_TLS_PARSE_STOC_KEY_SHARE                   445
 # define SSL_F_TLS_PARSE_STOC_PSK                         502
 # define SSL_F_TLS_PARSE_STOC_RENEGOTIATE                 448
@@ -2519,6 +2551,7 @@ int ERR_load_SSL_strings(void);
 # define SSL_R_INVALID_CONFIGURATION_NAME                 113
 # define SSL_R_INVALID_CT_VALIDATION_TYPE                 212
 # define SSL_R_INVALID_KEY_UPDATE_TYPE                    120
+# define SSL_R_INVALID_MAX_EARLY_DATA                     174
 # define SSL_R_INVALID_NULL_CMD_NAME                      385
 # define SSL_R_INVALID_SEQUENCE_NUMBER                    402
 # define SSL_R_INVALID_SERVERINFO_DATA                    388
@@ -2650,10 +2683,12 @@ int ERR_load_SSL_strings(void);
 # define SSL_R_TLS_INVALID_ECPOINTFORMAT_LIST             157
 # define SSL_R_TOO_MANY_KEY_UPDATES                       132
 # define SSL_R_TOO_MANY_WARN_ALERTS                       409
+# define SSL_R_TOO_MUCH_EARLY_DATA                        164
 # define SSL_R_UNABLE_TO_FIND_ECDH_PARAMETERS             314
 # define SSL_R_UNABLE_TO_FIND_PUBLIC_KEY_PARAMETERS       239
 # define SSL_R_UNABLE_TO_LOAD_SSL3_MD5_ROUTINES           242
 # define SSL_R_UNABLE_TO_LOAD_SSL3_SHA1_ROUTINES          243
+# define SSL_R_UNEXPECTED_END_OF_EARLY_DATA               178
 # define SSL_R_UNEXPECTED_MESSAGE                         244
 # define SSL_R_UNEXPECTED_RECORD                          245
 # define SSL_R_UNINITIALIZED                              276
diff --git a/include/openssl/ssl3.h b/include/openssl/ssl3.h
index 5948dfb..e6df97b 100644
--- a/include/openssl/ssl3.h
+++ b/include/openssl/ssl3.h
@@ -299,12 +299,13 @@ extern "C" {
 # define SSL3_MT_CCS                             1
 
 /* These are used when changing over to a new cipher */
-# define SSL3_CC_READ            0x01
-# define SSL3_CC_WRITE           0x02
-# define SSL3_CC_CLIENT          0x10
-# define SSL3_CC_SERVER          0x20
-# define SSL3_CC_HANDSHAKE       0x40
-# define SSL3_CC_APPLICATION     0x80
+# define SSL3_CC_READ            0x001
+# define SSL3_CC_WRITE           0x002
+# define SSL3_CC_CLIENT          0x010
+# define SSL3_CC_SERVER          0x020
+# define SSL3_CC_EARLY           0x040
+# define SSL3_CC_HANDSHAKE       0x080
+# define SSL3_CC_APPLICATION     0x100
 # define SSL3_CHANGE_CIPHER_CLIENT_WRITE (SSL3_CC_CLIENT|SSL3_CC_WRITE)
 # define SSL3_CHANGE_CIPHER_SERVER_READ  (SSL3_CC_SERVER|SSL3_CC_READ)
 # define SSL3_CHANGE_CIPHER_CLIENT_READ  (SSL3_CC_CLIENT|SSL3_CC_READ)
diff --git a/include/openssl/tls1.h b/include/openssl/tls1.h
index 6902f50..1054487 100644
--- a/include/openssl/tls1.h
+++ b/include/openssl/tls1.h
@@ -104,6 +104,7 @@ extern "C" {
 # define TLS1_AD_USER_CANCELLED          90
 # define TLS1_AD_NO_RENEGOTIATION        100
 /* TLSv1.3 alerts */
+# define TLS13_AD_END_OF_EARLY_DATA      1
 # define TLS13_AD_MISSING_EXTENSION      109 /* fatal */
 /* codes 110-114 are from RFC3546 */
 # define TLS1_AD_UNSUPPORTED_EXTENSION   110
@@ -178,8 +179,10 @@ extern "C" {
 /* As defined for TLS1.3 */
 # define TLSEXT_TYPE_key_share                   40
 # define TLSEXT_TYPE_psk                         41
+# define TLSEXT_TYPE_early_data                  42
 # define TLSEXT_TYPE_supported_versions          43
 # define TLSEXT_TYPE_psk_kex_modes               45
+# define TLSEXT_TYPE_early_data_info             46
 
 /* Temporary extension type */
 # define TLSEXT_TYPE_renegotiate                 0xff01
diff --git a/ssl/record/rec_layer_s3.c b/ssl/record/rec_layer_s3.c
index 5aea4b3..2cdc62d 100644
--- a/ssl/record/rec_layer_s3.c
+++ b/ssl/record/rec_layer_s3.c
@@ -348,6 +348,10 @@ int ssl3_write_bytes(SSL *s, int type, const void *buf_, size_t len,
         return -1;
     }
 
+    if (s->early_data_state == SSL_EARLY_DATA_WRITING
+            && !early_data_count_ok(s, len, 0, NULL))
+        return -1;
+
     s->rlayer.wnum = 0;
 
     if (SSL_in_init(s) && !ossl_statem_get_in_handshake(s)) {
@@ -745,7 +749,7 @@ int do_ssl3_write(SSL *s, int type, const unsigned char *buf,
     }
 
     /* Explicit IV length, block ciphers appropriate version flag */
-    if (s->enc_write_ctx && SSL_USE_EXPLICIT_IV(s)) {
+    if (s->enc_write_ctx && SSL_USE_EXPLICIT_IV(s) && !SSL_TREAT_AS_TLS13(s)) {
         int mode = EVP_CIPHER_CTX_mode(s->enc_write_ctx);
         if (mode == EVP_CIPH_CBC_MODE) {
             /* TODO(size_t): Convert me */
@@ -764,7 +768,7 @@ int do_ssl3_write(SSL *s, int type, const unsigned char *buf,
     /* Clear our SSL3_RECORD structures */
     memset(wr, 0, sizeof wr);
     for (j = 0; j < numpipes; j++) {
-        unsigned int version = SSL_IS_TLS13(s) ? TLS1_VERSION : s->version;
+        unsigned int version = SSL_TREAT_AS_TLS13(s) ? TLS1_VERSION : s->version;
         unsigned char *compressdata = NULL;
         size_t maxcomplen;
         unsigned int rectype;
@@ -777,7 +781,7 @@ int do_ssl3_write(SSL *s, int type, const unsigned char *buf,
          * In TLSv1.3, once encrypting, we always use application data for the
          * record type
          */
-        if (SSL_IS_TLS13(s) && s->enc_write_ctx != NULL)
+        if (SSL_TREAT_AS_TLS13(s) && s->enc_write_ctx != NULL)
             rectype = SSL3_RT_APPLICATION_DATA;
         else
             rectype = type;
@@ -835,7 +839,7 @@ int do_ssl3_write(SSL *s, int type, const unsigned char *buf,
             SSL3_RECORD_reset_input(&wr[j]);
         }
 
-        if (SSL_IS_TLS13(s) && s->enc_write_ctx != NULL) {
+        if (SSL_TREAT_AS_TLS13(s) && s->enc_write_ctx != NULL) {
             if (!WPACKET_put_bytes_u8(thispkt, type)) {
                 SSLerr(SSL_F_DO_SSL3_WRITE, ERR_R_INTERNAL_ERROR);
                 goto err;
@@ -887,8 +891,17 @@ int do_ssl3_write(SSL *s, int type, const unsigned char *buf,
         SSL3_RECORD_set_length(thiswr, len);
     }
 
-    if (s->method->ssl3_enc->enc(s, wr, numpipes, 1) < 1)
-        goto err;
+    if (s->early_data_state == SSL_EARLY_DATA_WRITING) {
+        /*
+         * We haven't actually negotiated the version yet, but we're trying to
+         * send early data - so we need to use the the tls13enc function.
+         */
+        if (tls13_enc(s, wr, numpipes, 1) < 1)
+            goto err;
+    } else {
+        if (s->method->ssl3_enc->enc(s, wr, numpipes, 1) < 1)
+            goto err;
+    }
 
     for (j = 0; j < numpipes; j++) {
         size_t origlen;
@@ -1428,6 +1441,14 @@ int ssl3_read_bytes(SSL *s, int type, int *recvd_type, unsigned char *buf,
                 al = SSL_AD_HANDSHAKE_FAILURE;
                 SSLerr(SSL_F_SSL3_READ_BYTES, SSL_R_NO_RENEGOTIATION);
                 goto f_err;
+            } else if (alert_descr == SSL_AD_END_OF_EARLY_DATA) {
+                if (!ssl_end_of_early_data_seen(s)) {
+                    al = SSL_AD_UNEXPECTED_MESSAGE;
+                    SSLerr(SSL_F_SSL3_READ_BYTES,
+                           SSL_R_UNEXPECTED_END_OF_EARLY_DATA);
+                    goto f_err;
+                }
+                return 0;
             }
         } else if (alert_level == SSL3_AL_FATAL) {
             char tmp[16];
@@ -1548,6 +1569,21 @@ int ssl3_read_bytes(SSL *s, int type, int *recvd_type, unsigned char *buf,
         if (ossl_statem_app_data_allowed(s)) {
             s->s3->in_read_app_data = 2;
             return -1;
+        } else if (ossl_statem_skip_early_data(s)) {
+            /*
+             * This can happen after a client sends a CH followed by early_data,
+             * but the server responds with a HelloRetryRequest. The server
+             * reads the next record from the client expecting to find a
+             * plaintext ClientHello but gets a record which appears to be
+             * application data. The trial decrypt "works" because null
+             * decryption was applied. We just skip it and move on to the next
+             * record.
+             */
+            if (!early_data_count_ok(s, rr->length,
+                                     EARLY_DATA_CIPHERTEXT_OVERHEAD, &al))
+                goto f_err;
+            SSL3_RECORD_set_read(rr);
+            goto start;
         } else {
             al = SSL_AD_UNEXPECTED_MESSAGE;
             SSLerr(SSL_F_SSL3_READ_BYTES, SSL_R_UNEXPECTED_RECORD);
diff --git a/ssl/record/record_locl.h b/ssl/record/record_locl.h
index 6394835..e249918 100644
--- a/ssl/record/record_locl.h
+++ b/ssl/record/record_locl.h
@@ -115,3 +115,4 @@ __owur int tls1_cbc_remove_padding(const SSL *s,
                                    size_t block_size, size_t mac_size);
 int dtls1_process_record(SSL *s, DTLS1_BITMAP *bitmap);
 __owur int dtls1_get_record(SSL *s);
+int early_data_count_ok(SSL *s, size_t length, size_t overhead, int *al);
diff --git a/ssl/record/ssl3_record.c b/ssl/record/ssl3_record.c
index 3868bb5..4149969 100644
--- a/ssl/record/ssl3_record.c
+++ b/ssl/record/ssl3_record.c
@@ -101,6 +101,40 @@ static int ssl3_record_app_data_waiting(SSL *s)
     return 1;
 }
 
+int early_data_count_ok(SSL *s, size_t length, size_t overhead, int *al)
+{
+    uint32_t max_early_data = s->max_early_data;
+
+    /*
+     * If we are a client then we always use the max_early_data from the
+     * session. Otherwise we go with the lowest out of the max early data set in
+     * the session and the configured max_early_data.
+     */
+    if (!s->server || (s->hit
+                       && s->session->ext.max_early_data < s->max_early_data))
+        max_early_data = s->session->ext.max_early_data;
+
+    if (max_early_data == 0) {
+        if (al != NULL)
+            *al = SSL_AD_UNEXPECTED_MESSAGE;
+        SSLerr(SSL_F_EARLY_DATA_COUNT_OK, SSL_R_TOO_MUCH_EARLY_DATA);
+        return 0;
+    }
+
+    /* If we are dealing with ciphertext we need to allow for the overhead */
+    max_early_data += overhead;
+
+    if (s->early_data_count + length > max_early_data) {
+        if (al != NULL)
+            *al = SSL_AD_UNEXPECTED_MESSAGE;
+        SSLerr(SSL_F_EARLY_DATA_COUNT_OK, SSL_R_TOO_MUCH_EARLY_DATA);
+        return 0;
+    }
+    s->early_data_count += length;
+
+    return 1;
+}
+
 /*
  * MAX_EMPTY_RECORDS defines the number of consecutive, empty records that
  * will be processed per call to ssl3_get_record. Without this limit an
@@ -139,6 +173,7 @@ int ssl3_get_record(SSL *s)
     int imac_size;
     size_t num_recs = 0, max_recs, j;
     PACKET pkt, sslv2pkt;
+    size_t first_rec_len;
 
     rr = RECORD_LAYER_get_rrec(&s->rlayer);
     rbuf = RECORD_LAYER_get_rbuf(&s->rlayer);
@@ -415,15 +450,35 @@ int ssl3_get_record(SSL *s)
         }
     }
 
+    first_rec_len = rr[0].length;
+
     enc_err = s->method->ssl3_enc->enc(s, rr, num_recs, 0);
 
     /*-
      * enc_err is:
-     *    0: (in non-constant time) if the record is publically invalid.
+     *    0: (in non-constant time) if the record is publicly invalid.
      *    1: if the padding is valid
      *    -1: if the padding is invalid
      */
     if (enc_err == 0) {
+        if (num_recs == 1 && ossl_statem_skip_early_data(s)) {
+            /*
+             * Valid early_data that we cannot decrypt might fail here as
+             * publicly invalid. We treat it like an empty record.
+             */
+
+            thisrr = &rr[0];
+
+            if (!early_data_count_ok(s, thisrr->length,
+                                     EARLY_DATA_CIPHERTEXT_OVERHEAD, &al))
+                goto f_err;
+
+            thisrr->length = 0;
+            thisrr->read = 1;
+            RECORD_LAYER_set_numrpipes(&s->rlayer, 1);
+            RECORD_LAYER_reset_read_sequence(&s->rlayer);
+            return 1;
+        }
         al = SSL_AD_DECRYPTION_FAILED;
         SSLerr(SSL_F_SSL3_GET_RECORD, SSL_R_BLOCK_CIPHER_PAD_IS_WRONG);
         goto f_err;
@@ -496,6 +551,27 @@ int ssl3_get_record(SSL *s)
     }
 
     if (enc_err < 0) {
+        if (num_recs == 1 && ossl_statem_skip_early_data(s)) {
+            /*
+             * We assume this is unreadable early_data - we treat it like an
+             * empty record
+             */
+
+            /*
+             * The record length may have been modified by the mac check above
+             * so we use the previously saved value
+             */
+            if (!early_data_count_ok(s, first_rec_len,
+                                     EARLY_DATA_CIPHERTEXT_OVERHEAD, &al))
+                goto f_err;
+
+            thisrr = &rr[0];
+            thisrr->length = 0;
+            thisrr->read = 1;
+            RECORD_LAYER_set_numrpipes(&s->rlayer, 1);
+            RECORD_LAYER_reset_read_sequence(&s->rlayer);
+            return 1;
+        }
         /*
          * A separate 'decryption_failed' alert was introduced with TLS 1.0,
          * SSL 3.0 only has 'bad_record_mac'.  But unless a decryption
@@ -580,6 +656,13 @@ int ssl3_get_record(SSL *s)
         }
     }
 
+    if (s->early_data_state == SSL_EARLY_DATA_READING) {
+        thisrr = &rr[0];
+        if (thisrr->type == SSL3_RT_APPLICATION_DATA
+                && !early_data_count_ok(s, thisrr->length, 0, &al))
+            goto f_err;
+    }
+
     RECORD_LAYER_set_numrpipes(&s->rlayer, num_recs);
     return 1;
 
diff --git a/ssl/record/ssl3_record_tls13.c b/ssl/record/ssl3_record_tls13.c
index d96a042..87041df 100644
--- a/ssl/record/ssl3_record_tls13.c
+++ b/ssl/record/ssl3_record_tls13.c
@@ -56,14 +56,18 @@ int tls13_enc(SSL *s, SSL3_RECORD *recs, size_t n_recs, int send)
 
     ivlen = EVP_CIPHER_CTX_iv_length(ctx);
 
-    /*
-     * To get here we must have selected a ciphersuite - otherwise ctx would
-     * be NULL
-     */
-    assert(s->s3->tmp.new_cipher != NULL);
-    if (s->s3->tmp.new_cipher == NULL)
-        return -1;
-    alg_enc = s->s3->tmp.new_cipher->algorithm_enc;
+    if (s->early_data_state == SSL_EARLY_DATA_WRITING) {
+        alg_enc = s->session->cipher->algorithm_enc;
+    } else {
+        /*
+         * To get here we must have selected a ciphersuite - otherwise ctx would
+         * be NULL
+         */
+        assert(s->s3->tmp.new_cipher != NULL);
+        if (s->s3->tmp.new_cipher == NULL)
+            return -1;
+        alg_enc = s->s3->tmp.new_cipher->algorithm_enc;
+    }
 
     if (alg_enc & SSL_AESCCM) {
         if (alg_enc & (SSL_AES128CCM8 | SSL_AES256CCM8))
diff --git a/ssl/s3_msg.c b/ssl/s3_msg.c
index 743a02b..7af2f99 100644
--- a/ssl/s3_msg.c
+++ b/ssl/s3_msg.c
@@ -63,7 +63,10 @@ int ssl3_do_change_cipher_spec(SSL *s)
 int ssl3_send_alert(SSL *s, int level, int desc)
 {
     /* Map tls/ssl alert value to correct one */
-    desc = s->method->ssl3_enc->alert_value(desc);
+    if (SSL_TREAT_AS_TLS13(s))
+        desc = tls13_alert_code(desc);
+    else
+        desc = s->method->ssl3_enc->alert_value(desc);
     if (s->version == SSL3_VERSION && desc == SSL_AD_PROTOCOL_VERSION)
         desc = SSL_AD_HANDSHAKE_FAILURE; /* SSL 3.0 does not have
                                           * protocol_version alerts */
diff --git a/ssl/ssl_asn1.c b/ssl/ssl_asn1.c
index 8141471..856db20 100644
--- a/ssl/ssl_asn1.c
+++ b/ssl/ssl_asn1.c
@@ -65,6 +65,8 @@ typedef struct {
     ASN1_OCTET_STRING *srp_username;
 #endif
     long flags;
+    uint32_t max_early_data;
+    ASN1_OCTET_STRING *alpn_selected;
 } SSL_SESSION_ASN1;
 
 ASN1_SEQUENCE(SSL_SESSION_ASN1) = {
@@ -91,7 +93,9 @@ ASN1_SEQUENCE(SSL_SESSION_ASN1) = {
     ASN1_EXP_OPT(SSL_SESSION_ASN1, srp_username, ASN1_OCTET_STRING, 12),
 #endif
     ASN1_EXP_OPT(SSL_SESSION_ASN1, flags, ZLONG, 13),
-    ASN1_EXP_OPT(SSL_SESSION_ASN1, tlsext_tick_age_add, ZLONG, 14)
+    ASN1_EXP_OPT(SSL_SESSION_ASN1, tlsext_tick_age_add, ZLONG, 14),
+    ASN1_EXP_OPT(SSL_SESSION_ASN1, max_early_data, ZLONG, 15),
+    ASN1_EXP_OPT(SSL_SESSION_ASN1, alpn_selected, ASN1_OCTET_STRING, 16)
 } static_ASN1_SEQUENCE_END(SSL_SESSION_ASN1)
 
 IMPLEMENT_STATIC_ASN1_ENCODE_FUNCTIONS(SSL_SESSION_ASN1)
@@ -132,16 +136,14 @@ int i2d_SSL_SESSION(SSL_SESSION *in, unsigned char **pp)
     ASN1_OCTET_STRING comp_id;
     unsigned char comp_id_data;
 #endif
-
     ASN1_OCTET_STRING tlsext_hostname, tlsext_tick;
-
 #ifndef OPENSSL_NO_SRP
     ASN1_OCTET_STRING srp_username;
 #endif
-
 #ifndef OPENSSL_NO_PSK
     ASN1_OCTET_STRING psk_identity, psk_identity_hint;
 #endif
+    ASN1_OCTET_STRING alpn_selected;
 
     long l;
 
@@ -203,6 +205,13 @@ int i2d_SSL_SESSION(SSL_SESSION *in, unsigned char **pp)
 #endif                          /* OPENSSL_NO_SRP */
 
     as.flags = in->flags;
+    as.max_early_data = in->ext.max_early_data;
+
+    if (in->ext.alpn_selected == NULL)
+        as.alpn_selected = NULL;
+    else
+        ssl_session_oinit(&as.alpn_selected, &alpn_selected,
+                          in->ext.alpn_selected, in->ext.alpn_selected_len);
 
     return i2d_SSL_SESSION_ASN1(&as, pp);
 
@@ -357,6 +366,17 @@ SSL_SESSION *d2i_SSL_SESSION(SSL_SESSION **a, const unsigned char **pp,
 #endif                          /* OPENSSL_NO_SRP */
     /* Flags defaults to zero which is fine */
     ret->flags = as->flags;
+    ret->ext.max_early_data = as->max_early_data;
+
+    if (as->alpn_selected != NULL) {
+        if (!ssl_session_strndup((char **)&ret->ext.alpn_selected,
+                                 as->alpn_selected))
+            goto err;
+        ret->ext.alpn_selected_len = as->alpn_selected->length;
+    } else {
+        ret->ext.alpn_selected = NULL;
+        ret->ext.alpn_selected_len = 0;
+    }
 
     M_ASN1_free_of(as, SSL_SESSION_ASN1);
 
diff --git a/ssl/ssl_err.c b/ssl/ssl_err.c
index 70764b3..6fe8e6e 100644
--- a/ssl/ssl_err.c
+++ b/ssl/ssl_err.c
@@ -52,6 +52,7 @@ static ERR_STRING_DATA SSL_str_functs[] = {
     {ERR_FUNC(SSL_F_DTLS_GET_REASSEMBLED_MESSAGE),
      "dtls_get_reassembled_message"},
     {ERR_FUNC(SSL_F_DTLS_PROCESS_HELLO_VERIFY), "dtls_process_hello_verify"},
+    {ERR_FUNC(SSL_F_EARLY_DATA_COUNT_OK), "early_data_count_ok"},
     {ERR_FUNC(SSL_F_FINAL_EC_PT_FORMATS), "final_ec_pt_formats"},
     {ERR_FUNC(SSL_F_FINAL_EMS), "final_ems"},
     {ERR_FUNC(SSL_F_FINAL_KEY_SHARE), "final_key_share"},
@@ -205,6 +206,7 @@ static ERR_STRING_DATA SSL_str_functs[] = {
     {ERR_FUNC(SSL_F_SSL_PEEK_EX), "SSL_peek_ex"},
     {ERR_FUNC(SSL_F_SSL_PEEK_INTERNAL), "ssl_peek_internal"},
     {ERR_FUNC(SSL_F_SSL_READ), "SSL_read"},
+    {ERR_FUNC(SSL_F_SSL_READ_EARLY_DATA), "SSL_read_early_data"},
     {ERR_FUNC(SSL_F_SSL_READ_EX), "SSL_read_ex"},
     {ERR_FUNC(SSL_F_SSL_READ_INTERNAL), "ssl_read_internal"},
     {ERR_FUNC(SSL_F_SSL_RENEGOTIATE), "SSL_renegotiate"},
@@ -253,6 +255,8 @@ static ERR_STRING_DATA SSL_str_functs[] = {
     {ERR_FUNC(SSL_F_SSL_VALIDATE_CT), "ssl_validate_ct"},
     {ERR_FUNC(SSL_F_SSL_VERIFY_CERT_CHAIN), "ssl_verify_cert_chain"},
     {ERR_FUNC(SSL_F_SSL_WRITE), "SSL_write"},
+    {ERR_FUNC(SSL_F_SSL_WRITE_EARLY_DATA), "SSL_write_early_data"},
+    {ERR_FUNC(SSL_F_SSL_WRITE_EARLY_FINISH), "SSL_write_early_finish"},
     {ERR_FUNC(SSL_F_SSL_WRITE_EX), "SSL_write_ex"},
     {ERR_FUNC(SSL_F_SSL_WRITE_INTERNAL), "ssl_write_internal"},
     {ERR_FUNC(SSL_F_STATE_MACHINE), "state_machine"},
@@ -299,6 +303,8 @@ static ERR_STRING_DATA SSL_str_functs[] = {
     {ERR_FUNC(SSL_F_TLS_CONSTRUCT_CTOS_ALPN), "tls_construct_ctos_alpn"},
     {ERR_FUNC(SSL_F_TLS_CONSTRUCT_CTOS_CERTIFICATE),
      "TLS_CONSTRUCT_CTOS_CERTIFICATE"},
+    {ERR_FUNC(SSL_F_TLS_CONSTRUCT_CTOS_EARLY_DATA),
+     "tls_construct_ctos_early_data"},
     {ERR_FUNC(SSL_F_TLS_CONSTRUCT_CTOS_EC_PT_FORMATS),
      "tls_construct_ctos_ec_pt_formats"},
     {ERR_FUNC(SSL_F_TLS_CONSTRUCT_CTOS_EMS), "tls_construct_ctos_ems"},
@@ -357,6 +363,10 @@ static ERR_STRING_DATA SSL_str_functs[] = {
     {ERR_FUNC(SSL_F_TLS_CONSTRUCT_STOC_CRYPTOPRO_BUG),
      "tls_construct_stoc_cryptopro_bug"},
     {ERR_FUNC(SSL_F_TLS_CONSTRUCT_STOC_DONE), "TLS_CONSTRUCT_STOC_DONE"},
+    {ERR_FUNC(SSL_F_TLS_CONSTRUCT_STOC_EARLY_DATA),
+     "tls_construct_stoc_early_data"},
+    {ERR_FUNC(SSL_F_TLS_CONSTRUCT_STOC_EARLY_DATA_INFO),
+     "tls_construct_stoc_early_data_info"},
     {ERR_FUNC(SSL_F_TLS_CONSTRUCT_STOC_EC_PT_FORMATS),
      "tls_construct_stoc_ec_pt_formats"},
     {ERR_FUNC(SSL_F_TLS_CONSTRUCT_STOC_EMS), "tls_construct_stoc_ems"},
@@ -390,6 +400,8 @@ static ERR_STRING_DATA SSL_str_functs[] = {
     {ERR_FUNC(SSL_F_TLS_PARSE_CTOS_RENEGOTIATE),
      "tls_parse_ctos_renegotiate"},
     {ERR_FUNC(SSL_F_TLS_PARSE_CTOS_USE_SRTP), "tls_parse_ctos_use_srtp"},
+    {ERR_FUNC(SSL_F_TLS_PARSE_STOC_EARLY_DATA_INFO),
+     "tls_parse_stoc_early_data_info"},
     {ERR_FUNC(SSL_F_TLS_PARSE_STOC_KEY_SHARE), "tls_parse_stoc_key_share"},
     {ERR_FUNC(SSL_F_TLS_PARSE_STOC_PSK), "tls_parse_stoc_psk"},
     {ERR_FUNC(SSL_F_TLS_PARSE_STOC_RENEGOTIATE),
@@ -585,6 +597,7 @@ static ERR_STRING_DATA SSL_str_reasons[] = {
     {ERR_REASON(SSL_R_INVALID_CT_VALIDATION_TYPE),
      "invalid ct validation type"},
     {ERR_REASON(SSL_R_INVALID_KEY_UPDATE_TYPE), "invalid key update type"},
+    {ERR_REASON(SSL_R_INVALID_MAX_EARLY_DATA), "invalid max early data"},
     {ERR_REASON(SSL_R_INVALID_NULL_CMD_NAME), "invalid null cmd name"},
     {ERR_REASON(SSL_R_INVALID_SEQUENCE_NUMBER), "invalid sequence number"},
     {ERR_REASON(SSL_R_INVALID_SERVERINFO_DATA), "invalid serverinfo data"},
@@ -776,6 +789,7 @@ static ERR_STRING_DATA SSL_str_reasons[] = {
      "tls invalid ecpointformat list"},
     {ERR_REASON(SSL_R_TOO_MANY_KEY_UPDATES), "too many key updates"},
     {ERR_REASON(SSL_R_TOO_MANY_WARN_ALERTS), "too many warn alerts"},
+    {ERR_REASON(SSL_R_TOO_MUCH_EARLY_DATA), "too much early data"},
     {ERR_REASON(SSL_R_UNABLE_TO_FIND_ECDH_PARAMETERS),
      "unable to find ecdh parameters"},
     {ERR_REASON(SSL_R_UNABLE_TO_FIND_PUBLIC_KEY_PARAMETERS),
@@ -784,6 +798,8 @@ static ERR_STRING_DATA SSL_str_reasons[] = {
      "unable to load ssl3 md5 routines"},
     {ERR_REASON(SSL_R_UNABLE_TO_LOAD_SSL3_SHA1_ROUTINES),
      "unable to load ssl3 sha1 routines"},
+    {ERR_REASON(SSL_R_UNEXPECTED_END_OF_EARLY_DATA),
+     "unexpected end of early data"},
     {ERR_REASON(SSL_R_UNEXPECTED_MESSAGE), "unexpected message"},
     {ERR_REASON(SSL_R_UNEXPECTED_RECORD), "unexpected record"},
     {ERR_REASON(SSL_R_UNINITIALIZED), "uninitialized"},
diff --git a/ssl/ssl_lib.c b/ssl/ssl_lib.c
index 39254f1..fcf4f4d 100644
--- a/ssl/ssl_lib.c
+++ b/ssl/ssl_lib.c
@@ -105,6 +105,8 @@ static const struct {
     },
 };
 
+static int ssl_write_early_finish(SSL *s);
+
 static int dane_ctx_enable(struct dane_ctx_st *dctx)
 {
     const EVP_MD **mdevp;
@@ -551,6 +553,7 @@ SSL *SSL_new(SSL_CTX *ctx)
     s->mode = ctx->mode;
     s->max_cert_list = ctx->max_cert_list;
     s->references = 1;
+    s->max_early_data = ctx->max_early_data;
 
     /*
      * Earlier library versions used to copy the pointer to the CERT, not
@@ -1544,6 +1547,17 @@ int ssl_read_internal(SSL *s, void *buf, size_t num, size_t *readbytes)
         return 0;
     }
 
+    if (s->early_data_state == SSL_EARLY_DATA_CONNECT_RETRY
+                || s->early_data_state == SSL_EARLY_DATA_ACCEPT_RETRY) {
+        SSLerr(SSL_F_SSL_READ_INTERNAL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+        return 0;
+    }
+    /*
+     * If we are a client and haven't received the ServerHello etc then we
+     * better do that
+     */
+    ossl_statem_check_finish_init(s, 0);
+
     if ((s->mode & SSL_MODE_ASYNC) && ASYNC_get_current_job() == NULL) {
         struct ssl_async_args args;
         int ret;
@@ -1593,6 +1607,78 @@ int SSL_read_ex(SSL *s, void *buf, size_t num, size_t *readbytes)
     return ret;
 }
 
+int SSL_read_early_data(SSL *s, void *buf, size_t num, size_t *readbytes)
+{
+    int ret;
+
+    if (!s->server) {
+        SSLerr(SSL_F_SSL_READ_EARLY_DATA, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+        return SSL_READ_EARLY_DATA_ERROR;
+    }
+
+    switch (s->early_data_state) {
+    case SSL_EARLY_DATA_NONE:
+        if (!SSL_in_before(s)) {
+            SSLerr(SSL_F_SSL_READ_EARLY_DATA,
+                   ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+            return SSL_READ_EARLY_DATA_ERROR;
+        }
+        /* fall through */
+
+    case SSL_EARLY_DATA_ACCEPT_RETRY:
+        s->early_data_state = SSL_EARLY_DATA_ACCEPTING;
+        ret = SSL_accept(s);
+        if (ret <= 0) {
+            /* NBIO or error */
+            s->early_data_state = SSL_EARLY_DATA_ACCEPT_RETRY;
+            return SSL_READ_EARLY_DATA_ERROR;
+        }
+        /* fall through */
+
+    case SSL_EARLY_DATA_READ_RETRY:
+        if (s->ext.early_data == SSL_EARLY_DATA_ACCEPTED) {
+            s->early_data_state = SSL_EARLY_DATA_READING;
+            ret = SSL_read_ex(s, buf, num, readbytes);
+            /*
+             * Record layer will call ssl_end_of_early_data_seen() if we see
+             * that alert - which updates the early_data_state to
+             * SSL_EARLY_DATA_FINISHED_READING
+             */
+            if (ret > 0 || (ret <= 0 && s->early_data_state
+                                        != SSL_EARLY_DATA_FINISHED_READING)) {
+                s->early_data_state = SSL_EARLY_DATA_READ_RETRY;
+                return ret > 0 ? SSL_READ_EARLY_DATA_SUCCESS
+                               : SSL_READ_EARLY_DATA_ERROR;
+            }
+        } else {
+            s->early_data_state = SSL_EARLY_DATA_FINISHED_READING;
+        }
+        *readbytes = 0;
+        return SSL_READ_EARLY_DATA_FINISH;
+
+    default:
+        SSLerr(SSL_F_SSL_READ_EARLY_DATA, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+        return SSL_READ_EARLY_DATA_ERROR;
+    }
+}
+
+int ssl_end_of_early_data_seen(SSL *s)
+{
+    if (s->early_data_state == SSL_EARLY_DATA_READING
+            || s->early_data_state == SSL_EARLY_DATA_READ_RETRY) {
+        s->early_data_state = SSL_EARLY_DATA_FINISHED_READING;
+        ossl_statem_finish_early_data(s);
+        return 1;
+    }
+
+    return 0;
+}
+
+int SSL_get_early_data_status(const SSL *s)
+{
+    return s->ext.early_data;
+}
+
 static int ssl_peek_internal(SSL *s, void *buf, size_t num, size_t *readbytes)
 {
     if (s->handshake_func == NULL) {
@@ -1666,6 +1752,22 @@ int ssl_write_internal(SSL *s, const void *buf, size_t num, size_t *written)
         return -1;
     }
 
+    if (s->early_data_state == SSL_EARLY_DATA_WRITE_RETRY) {
+        /*
+         * We're still writing early data. We need to stop that so we can write
+         * normal data
+         */
+        if (!ssl_write_early_finish(s))
+            return 0;
+    } else if (s->early_data_state == SSL_EARLY_DATA_CONNECT_RETRY
+                || s->early_data_state == SSL_EARLY_DATA_ACCEPT_RETRY
+                || s->early_data_state == SSL_EARLY_DATA_READ_RETRY) {
+        SSLerr(SSL_F_SSL_WRITE_INTERNAL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+        return 0;
+    }
+    /* If we are a client and haven't sent the Finished we better do that */
+    ossl_statem_check_finish_init(s, 1);
+
     if ((s->mode & SSL_MODE_ASYNC) && ASYNC_get_current_job() == NULL) {
         int ret;
         struct ssl_async_args args;
@@ -1715,6 +1817,77 @@ int SSL_write_ex(SSL *s, const void *buf, size_t num, size_t *written)
     return ret;
 }
 
+int SSL_write_early_data(SSL *s, const void *buf, size_t num, size_t *written)
+{
+    int ret;
+
+    switch (s->early_data_state) {
+    case SSL_EARLY_DATA_NONE:
+        if (s->server
+                || !SSL_in_before(s)
+                || s->session == NULL
+                || s->session->ext.max_early_data == 0) {
+            SSLerr(SSL_F_SSL_WRITE_EARLY_DATA,
+                   ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+            return 0;
+        }
+        /* fall through */
+
+    case SSL_EARLY_DATA_CONNECT_RETRY:
+        s->early_data_state = SSL_EARLY_DATA_CONNECTING;
+        ret = SSL_connect(s);
+        if (ret <= 0) {
+            /* NBIO or error */
+            s->early_data_state = SSL_EARLY_DATA_CONNECT_RETRY;
+            return 0;
+        }
+        /* fall through */
+
+    case SSL_EARLY_DATA_WRITE_RETRY:
+        s->early_data_state = SSL_EARLY_DATA_WRITING;
+        ret = SSL_write_ex(s, buf, num, written);
+        s->early_data_state = SSL_EARLY_DATA_WRITE_RETRY;
+        return ret;
+
+    case SSL_EARLY_DATA_READ_RETRY:
+        /* We are a server writing to an unauthenticated client */
+        s->early_data_state = SSL_EARLY_DATA_UNAUTH_WRITING;
+        ret = SSL_write_ex(s, buf, num, written);
+        s->early_data_state = SSL_EARLY_DATA_READ_RETRY;
+        return ret;
+
+    default:
+        SSLerr(SSL_F_SSL_WRITE_EARLY_DATA, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+        return 0;
+    }
+}
+
+static int ssl_write_early_finish(SSL *s)
+{
+    int ret;
+
+    if (s->early_data_state != SSL_EARLY_DATA_WRITE_RETRY) {
+        SSLerr(SSL_F_SSL_WRITE_EARLY_FINISH, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+        return 0;
+    }
+
+    s->early_data_state = SSL_EARLY_DATA_WRITING;
+    ret = ssl3_send_alert(s, SSL3_AL_WARNING, SSL_AD_END_OF_EARLY_DATA);
+    if (ret <= 0) {
+        s->early_data_state = SSL_EARLY_DATA_WRITE_RETRY;
+        return 0;
+    }
+    s->early_data_state = SSL_EARLY_DATA_FINISHED_WRITING;
+    /*
+     * We set the enc_write_ctx back to NULL because we may end up writing
+     * in cleartext again if we get a HelloRetryRequest from the server.
+     */
+    EVP_CIPHER_CTX_free(s->enc_write_ctx);
+    s->enc_write_ctx = NULL;
+    ossl_statem_set_in_init(s, 1);
+    return 1;
+}
+
 int SSL_shutdown(SSL *s)
 {
     /*
@@ -2622,6 +2795,12 @@ SSL_CTX *SSL_CTX_new(const SSL_METHOD *meth)
 
     ret->ext.status_type = TLSEXT_STATUSTYPE_nothing;
 
+    /*
+     * Default max early data is a fully loaded single record. Could be split
+     * across multiple records in practice
+     */
+    ret->max_early_data = SSL3_RT_MAX_PLAIN_LENGTH;
+
     return ret;
  err:
     SSLerr(SSL_F_SSL_CTX_NEW, ERR_R_MALLOC_FAILURE);
@@ -3072,6 +3251,15 @@ int SSL_do_handshake(SSL *s)
         return -1;
     }
 
+    if (s->early_data_state == SSL_EARLY_DATA_WRITE_RETRY) {
+        int edfin;
+
+        edfin = ssl_write_early_finish(s);
+        if (edfin <= 0)
+            return edfin;
+    }
+    ossl_statem_check_finish_init(s, -1);
+
     s->method->ssl_renegotiate_check(s, 0);
 
     if (SSL_in_init(s) || SSL_in_before(s)) {
@@ -4657,3 +4845,27 @@ int bytes_to_cipher_list(SSL *s, PACKET *cipher_suites,
     sk_SSL_CIPHER_free(scsvs);
     return 0;
 }
+
+int SSL_CTX_set_max_early_data(SSL_CTX *ctx, uint32_t max_early_data)
+{
+    ctx->max_early_data = max_early_data;
+
+    return 1;
+}
+
+uint32_t SSL_CTX_get_max_early_data(const SSL_CTX *ctx)
+{
+    return ctx->max_early_data;
+}
+
+int SSL_set_max_early_data(SSL *s, uint32_t max_early_data)
+{
+    s->max_early_data = max_early_data;
+
+    return 1;
+}
+
+uint32_t SSL_get_max_early_data(const SSL_CTX *s)
+{
+    return s->max_early_data;
+}
diff --git a/ssl/ssl_locl.h b/ssl/ssl_locl.h
index c253c99..6811b4f 100644
--- a/ssl/ssl_locl.h
+++ b/ssl/ssl_locl.h
@@ -349,6 +349,9 @@
                           && (s)->method->version >= TLS1_3_VERSION \
                           && (s)->method->version != TLS_ANY_VERSION)
 
+# define SSL_TREAT_AS_TLS13(s) \
+    (SSL_IS_TLS13(s) || (s)->early_data_state == SSL_EARLY_DATA_WRITING)
+
 # define SSL_IS_FIRST_HANDSHAKE(S) ((s)->s3->tmp.finish_md_len == 0)
 
 /* See if we need explicit IV */
@@ -575,6 +578,11 @@ struct ssl_session_st {
         unsigned long tick_lifetime_hint;
         uint32_t tick_age_add;
         int tick_identity;
+        /* Max number of bytes that can be sent as early data */
+        uint32_t max_early_data;
+        /* The ALPN protocol selected for this session */
+        unsigned char *alpn_selected;
+        size_t alpn_selected_len;
     } ext;
 # ifndef OPENSSL_NO_SRP
     char *srp_username;
@@ -607,6 +615,41 @@ typedef struct srp_ctx_st {
 
 # endif
 
+typedef enum {
+    SSL_EARLY_DATA_NONE = 0,
+    SSL_EARLY_DATA_CONNECT_RETRY,
+    SSL_EARLY_DATA_CONNECTING,
+    SSL_EARLY_DATA_WRITE_RETRY,
+    SSL_EARLY_DATA_WRITING,
+    SSL_EARLY_DATA_UNAUTH_WRITING,
+    SSL_EARLY_DATA_FINISHED_WRITING,
+    SSL_EARLY_DATA_ACCEPT_RETRY,
+    SSL_EARLY_DATA_ACCEPTING,
+    SSL_EARLY_DATA_READ_RETRY,
+    SSL_EARLY_DATA_READING,
+    SSL_EARLY_DATA_FINISHED_READING
+} SSL_EARLY_DATA_STATE;
+
+/*
+ * We check that the amount of unreadable early data doesn't exceed
+ * max_early_data. max_early_data is given in plaintext bytes. However if it is
+ * unreadable then we only know the number of ciphertext bytes. We also don't
+ * know how much the overhead should be because it depends on the ciphersuite.
+ * We make a small allowance. We assume 5 records of actual data plus the end
+ * of early data alert record. Each record has a tag and a content type byte.
+ * The longest tag length we know of is EVP_GCM_TLS_TAG_LEN. We don't count the
+ * content of the alert record either which is 2 bytes.
+ */
+# define EARLY_DATA_CIPHERTEXT_OVERHEAD ((6 * (EVP_GCM_TLS_TAG_LEN + 1)) + 2)
+
+/*
+ * The allowance we have between the client's calculated ticket age and our own.
+ * We allow for 10 seconds (units are in ms). If a ticket is presented and the
+ * client's age calculation is different by more than this than our own then we
+ * do not allow that ticket for early_data.
+ */
+# define TICKET_AGE_ALLOWANCE   (10 * 1000)
+
 #define MAX_COMPRESSIONS_SIZE   255
 
 struct ssl_comp_st {
@@ -922,6 +965,9 @@ struct ssl_ctx_st {
      * Wireshark. The callback should log `line` followed by a newline.
      */
     SSL_CTX_keylog_cb_func keylog_callback;
+
+    /* The maximum number of bytes that can be sent as early data */
+    uint32_t max_early_data;
 };
 
 struct ssl_st {
@@ -971,6 +1017,7 @@ struct ssl_st {
     int shutdown;
     /* where we are */
     OSSL_STATEM statem;
+    SSL_EARLY_DATA_STATE early_data_state;
     BUF_MEM *init_buf;          /* buffer used during init */
     void *init_msg;             /* pointer to handshake message body, set by
                                  * ssl3_get_message() */
@@ -1004,6 +1051,7 @@ struct ssl_st {
     unsigned char client_finished_secret[EVP_MAX_MD_SIZE];
     unsigned char server_finished_secret[EVP_MAX_MD_SIZE];
     unsigned char server_finished_hash[EVP_MAX_MD_SIZE];
+    unsigned char handshake_traffic_hash[EVP_MAX_MD_SIZE];
     unsigned char client_app_traffic_secret[EVP_MAX_MD_SIZE];
     unsigned char server_app_traffic_secret[EVP_MAX_MD_SIZE];
     EVP_CIPHER_CTX *enc_read_ctx; /* cryptographic state */
@@ -1158,6 +1206,11 @@ struct ssl_st {
 
         /* Set to one if we have negotiated ETM */
         int use_etm;
+
+        /* Are we expecting to receive early data? */
+        int early_data;
+        /* Is the session suitable for early data? */
+        int early_data_ok;
     } ext;
 
     /* Parsed form of the ClientHello, kept around across early_cb calls. */
@@ -1218,6 +1271,15 @@ struct ssl_st {
     ASYNC_WAIT_CTX *waitctx;
     size_t asyncrw;
 
+    /* The maximum number of plaintext bytes that can be sent as early data */
+    uint32_t max_early_data;
+    /*
+     * The number of bytes of early data received so far. If we accepted early
+     * data then this is a count of the plaintext bytes. If we rejected it then
+     * this is a count of the ciphertext bytes.
+     */
+    uint32_t early_data_count;
+
     CRYPTO_RWLOCK *lock;
 };
 
@@ -1724,6 +1786,7 @@ typedef enum tlsext_index_en {
     TLSEXT_IDX_renegotiate,
     TLSEXT_IDX_server_name,
     TLSEXT_IDX_srp,
+    TLSEXT_IDX_early_data_info,
     TLSEXT_IDX_ec_point_formats,
     TLSEXT_IDX_supported_groups,
     TLSEXT_IDX_session_ticket,
@@ -1739,6 +1802,7 @@ typedef enum tlsext_index_en {
     TLSEXT_IDX_psk_kex_modes,
     TLSEXT_IDX_key_share,
     TLSEXT_IDX_cryptopro_bug,
+    TLSEXT_IDX_early_data,
     TLSEXT_IDX_padding,
     TLSEXT_IDX_psk
 } TLSEXT_INDEX;
@@ -1961,6 +2025,7 @@ static ossl_inline int ssl_has_cert(const SSL *s, int idx)
 
 # ifndef OPENSSL_UNIT_TEST
 
+int ssl_end_of_early_data_seen(SSL *s);
 __owur int ssl_read_internal(SSL *s, void *buf, size_t num, size_t *readbytes);
 __owur int ssl_write_internal(SSL *s, const void *buf, size_t num, size_t *written);
 void ssl_clear_cipher_ctx(SSL *s);
@@ -2170,10 +2235,12 @@ __owur int tls13_hkdf_expand(SSL *s, const EVP_MD *md,
                              const unsigned char *label, size_t labellen,
                              const unsigned char *hash,
                              unsigned char *out, size_t outlen);
-__owur int tls13_derive_key(SSL *s, const unsigned char *secret,
-                            unsigned char *key, size_t keylen);
-__owur int tls13_derive_iv(SSL *s, const unsigned char *secret,
-                           unsigned char *iv, size_t ivlen);
+__owur int tls13_derive_key(SSL *s, const EVP_MD *md,
+                            const unsigned char *secret, unsigned char *key,
+                            size_t keylen);
+__owur int tls13_derive_iv(SSL *s, const EVP_MD *md,
+                           const unsigned char *secret, unsigned char *iv,
+                           size_t ivlen);
 __owur int tls13_derive_finishedkey(SSL *s, const EVP_MD *md,
                                     const unsigned char *secret,
                                     unsigned char *fin, size_t finlen);
@@ -2326,6 +2393,7 @@ __owur int ssl_log_secret(SSL *ssl, const char *label,
                           const uint8_t *secret, size_t secret_len);
 
 #define MASTER_SECRET_LABEL "CLIENT_RANDOM"
+#define CLIENT_EARLY_LABEL "CLIENT_EARLY_TRAFFIC_SECRET"
 #define CLIENT_HANDSHAKE_LABEL "CLIENT_HANDSHAKE_TRAFFIC_SECRET"
 #define SERVER_HANDSHAKE_LABEL "SERVER_HANDSHAKE_TRAFFIC_SECRET"
 #define CLIENT_APPLICATION_LABEL "CLIENT_TRAFFIC_SECRET_0"
diff --git a/ssl/ssl_sess.c b/ssl/ssl_sess.c
index be3c4c3..2e69176 100644
--- a/ssl/ssl_sess.c
+++ b/ssl/ssl_sess.c
@@ -791,6 +791,7 @@ void SSL_SESSION_free(SSL_SESSION *ss)
 #ifndef OPENSSL_NO_SRP
     OPENSSL_free(ss->srp_username);
 #endif
+    OPENSSL_free(ss->ext.alpn_selected);
     CRYPTO_THREAD_lock_free(ss->lock);
     OPENSSL_clear_free(ss, sizeof(*ss));
 }
@@ -901,6 +902,11 @@ void SSL_SESSION_get0_ticket(const SSL_SESSION *s, const unsigned char **tick,
         *tick = s->ext.tick;
 }
 
+uint32_t SSL_SESSION_get_max_early_data(const SSL_SESSION *s)
+{
+    return s->ext.max_early_data;
+}
+
 X509 *SSL_SESSION_get0_peer(SSL_SESSION *s)
 {
     return s->peer;
diff --git a/ssl/statem/extensions.c b/ssl/statem/extensions.c
index c011445..edcfe71 100644
--- a/ssl/statem/extensions.c
+++ b/ssl/statem/extensions.c
@@ -7,6 +7,7 @@
  * https://www.openssl.org/source/license.html
  */
 
+#include <string.h>
 #include "../ssl_locl.h"
 #include "statem_locl.h"
 
@@ -43,6 +44,7 @@ static int final_key_share(SSL *s, unsigned int context, int sent, int *al);
 static int init_srtp(SSL *s, unsigned int context);
 #endif
 static int final_sig_algs(SSL *s, unsigned int context, int sent, int *al);
+static int final_early_data(SSL *s, unsigned int context, int sent, int *al);
 
 /* Structure to define a built-in extension */
 typedef struct extensions_definition_st {
@@ -129,6 +131,12 @@ static const EXTENSION_DEFINITION ext_defs[] = {
 #else
     INVALID_EXTENSION,
 #endif
+    {
+        TLSEXT_TYPE_early_data_info,
+        EXT_TLS1_3_NEW_SESSION_TICKET,
+        NULL, NULL, tls_parse_stoc_early_data_info,
+        tls_construct_stoc_early_data_info, NULL, NULL
+    },
 #ifndef OPENSSL_NO_EC
     {
         TLSEXT_TYPE_ec_point_formats,
@@ -271,6 +279,13 @@ static const EXTENSION_DEFINITION ext_defs[] = {
         NULL, NULL, NULL, tls_construct_stoc_cryptopro_bug, NULL, NULL
     },
     {
+        TLSEXT_TYPE_early_data,
+        EXT_CLIENT_HELLO | EXT_TLS1_3_ENCRYPTED_EXTENSIONS,
+        NULL, tls_parse_ctos_early_data, tls_parse_stoc_early_data,
+        tls_construct_stoc_early_data, tls_construct_ctos_early_data,
+        final_early_data
+    },
+    {
         /* Must be immediately before pre_shared_key */
         /* TODO(TLS1.3): Fix me */
         TLSEXT_TYPE_padding,
@@ -1217,3 +1232,31 @@ int tls_psk_do_binder(SSL *s, const EVP_MD *md, const unsigned char *msgstart,
 
     return ret;
 }
+
+static int final_early_data(SSL *s, unsigned int context, int sent, int *al)
+{
+    if (!s->server || !sent)
+        return 1;
+
+    if (s->max_early_data == 0
+            || !s->hit
+            || s->session->ext.tick_identity != 0
+            || s->early_data_state != SSL_EARLY_DATA_ACCEPTING
+            || !s->ext.early_data_ok
+            || s->hello_retry_request
+            || s->s3->alpn_selected_len != s->session->ext.alpn_selected_len
+            || memcmp(s->s3->alpn_selected, s->session->ext.alpn_selected,
+                      s->s3->alpn_selected_len) != 0){
+        s->ext.early_data = SSL_EARLY_DATA_REJECTED;
+    } else {
+        s->ext.early_data = SSL_EARLY_DATA_ACCEPTED;
+
+        if (!tls13_change_cipher_state(s,
+                    SSL3_CC_EARLY | SSL3_CHANGE_CIPHER_SERVER_READ)) {
+            *al = SSL_AD_INTERNAL_ERROR;
+            return 0;
+        }
+    }
+
+    return 1;
+}
diff --git a/ssl/statem/extensions_clnt.c b/ssl/statem/extensions_clnt.c
index 09780a9..0af4d1b 100644
--- a/ssl/statem/extensions_clnt.c
+++ b/ssl/statem/extensions_clnt.c
@@ -636,6 +636,32 @@ int tls_construct_ctos_key_share(SSL *s, WPACKET *pkt, unsigned int context,
     return 1;
 }
 
+int tls_construct_ctos_early_data(SSL *s, WPACKET *pkt, unsigned int context,
+                                  X509 *x, size_t chainidx, int *al)
+{
+    if (s->early_data_state != SSL_EARLY_DATA_CONNECTING
+            || s->session->ext.max_early_data == 0) {
+        s->max_early_data = 0;
+        return 1;
+    }
+    s->max_early_data = s->session->ext.max_early_data;
+
+    if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_early_data)
+            || !WPACKET_start_sub_packet_u16(pkt)
+            || !WPACKET_close(pkt)) {
+        SSLerr(SSL_F_TLS_CONSTRUCT_CTOS_EARLY_DATA, ERR_R_INTERNAL_ERROR);
+        return 0;
+    }
+
+    /*
+     * We set this to rejected here. Later, if the server acknowledges the
+     * extension, we set it to accepted.
+     */
+    s->ext.early_data = SSL_EARLY_DATA_REJECTED;
+
+    return 1;
+}
+
 #define F5_WORKAROUND_MIN_MSG_LEN   0xff
 #define F5_WORKAROUND_MAX_MSG_LEN   0x200
 
@@ -879,6 +905,24 @@ int tls_parse_stoc_server_name(SSL *s, PACKET *pkt, unsigned int context,
     return 1;
 }
 
+int tls_parse_stoc_early_data_info(SSL *s, PACKET *pkt, unsigned int context,
+                                   X509 *x, size_t chainidx, int *al)
+{
+    unsigned long max_early_data;
+
+    if (!PACKET_get_net_4(pkt, &max_early_data)
+            || PACKET_remaining(pkt) != 0) {
+        SSLerr(SSL_F_TLS_PARSE_STOC_EARLY_DATA_INFO,
+               SSL_R_INVALID_MAX_EARLY_DATA);
+        *al = SSL_AD_DECODE_ERROR;
+        return 0;
+    }
+
+    s->session->ext.max_early_data = max_early_data;
+
+    return 1;
+}
+
 #ifndef OPENSSL_NO_EC
 int tls_parse_stoc_ec_pt_formats(SSL *s, PACKET *pkt, unsigned int context,
                                  X509 *x, size_t chainidx, int *al)
@@ -1294,6 +1338,30 @@ int tls_parse_stoc_key_share(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
     return 1;
 }
 
+int tls_parse_stoc_early_data(SSL *s, PACKET *pkt, unsigned int context,
+                              X509 *x, size_t chainidx, int *al)
+{
+    if (PACKET_remaining(pkt) != 0) {
+        *al = SSL_AD_DECODE_ERROR;
+        return 0;
+    }
+
+    if (s->ext.early_data != SSL_EARLY_DATA_REJECTED
+            || !s->hit
+            || s->session->ext.tick_identity != 0) {
+        /*
+         * If we get here then we didn't send early data, or we didn't resume
+         * using the first identity so the server should not be accepting it.
+         */
+        *al = SSL_AD_ILLEGAL_PARAMETER;
+        return 0;
+    }
+
+    s->ext.early_data = SSL_EARLY_DATA_ACCEPTED;
+
+    return 1;
+}
+
 int tls_parse_stoc_psk(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
                        size_t chainidx, int *al)
 {
diff --git a/ssl/statem/extensions_srvr.c b/ssl/statem/extensions_srvr.c
index ecfd00b..c613143 100644
--- a/ssl/statem/extensions_srvr.c
+++ b/ssl/statem/extensions_srvr.c
@@ -661,6 +661,18 @@ int tls_parse_ctos_ems(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
     return 1;
 }
 
+
+int tls_parse_ctos_early_data(SSL *s, PACKET *pkt, unsigned int context,
+                              X509 *x, size_t chainidx, int *al)
+{
+    if (PACKET_remaining(pkt) != 0) {
+        *al = SSL_AD_DECODE_ERROR;
+        return 0;
+    }
+
+    return 1;
+}
+
 int tls_parse_ctos_psk(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
                        size_t chainidx, int *al)
 {
@@ -669,6 +681,7 @@ int tls_parse_ctos_psk(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
     SSL_SESSION *sess = NULL;
     unsigned int id, i;
     const EVP_MD *md = NULL;
+    uint32_t ticket_age, now, agesec, agems;
 
     /*
      * If we have no PSK kex mode that we recognise then we can't resume so
@@ -685,16 +698,16 @@ int tls_parse_ctos_psk(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
 
     for (id = 0; PACKET_remaining(&identities) != 0; id++) {
         PACKET identity;
-        unsigned long ticket_age;
+        unsigned long ticket_agel;
         int ret;
 
         if (!PACKET_get_length_prefixed_2(&identities, &identity)
-                || !PACKET_get_net_4(&identities, &ticket_age)) {
+                || !PACKET_get_net_4(&identities, &ticket_agel)) {
             *al = SSL_AD_DECODE_ERROR;
             return 0;
         }
 
-        /* TODO(TLS1.3): Should we validate the ticket age? */
+        ticket_age = (uint32_t)ticket_agel;
 
         ret = tls_decrypt_ticket(s, PACKET_data(&identity),
                                  PACKET_remaining(&identity), NULL, 0, &sess);
@@ -753,6 +766,32 @@ int tls_parse_ctos_psk(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
     }
 
     sess->ext.tick_identity = id;
+
+    now = (uint32_t)time(NULL);
+    agesec = now - (uint32_t)sess->time;
+    agems = agesec * (uint32_t)1000;
+    ticket_age -= sess->ext.tick_age_add;
+
+
+    /*
+     * For simplicity we do our age calculations in seconds. If the client does
+     * it in ms then it could appear that their ticket age is longer than ours
+     * (our ticket age calculation should always be slightly longer than the
+     * client's due to the network latency). Therefore we add 1000ms to our age
+     * calculation to adjust for rounding errors.
+     */
+    if (sess->timeout >= agesec
+            && agems / (uint32_t)1000 == agesec
+            && ticket_age <= agems + 1000
+            && ticket_age + TICKET_AGE_ALLOWANCE >= agems + 1000) {
+        /*
+         * Ticket age is within tolerance and not expired. We allow it for early
+         * data
+         */
+        s->ext.early_data_ok = 1;
+    }
+
+
     SSL_SESSION_free(s->session);
     s->session = sess;
     return 1;
@@ -801,6 +840,24 @@ int tls_construct_stoc_server_name(SSL *s, WPACKET *pkt, unsigned int context,
     return 1;
 }
 
+int tls_construct_stoc_early_data_info(SSL *s, WPACKET *pkt,
+                                       unsigned int context, X509 *x,
+                                       size_t chainidx, int *al)
+{
+    if (s->max_early_data == 0)
+        return 1;
+
+    if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_early_data_info)
+            || !WPACKET_start_sub_packet_u16(pkt)
+            || !WPACKET_put_bytes_u32(pkt, s->max_early_data)
+            || !WPACKET_close(pkt)) {
+        SSLerr(SSL_F_TLS_CONSTRUCT_STOC_EARLY_DATA_INFO, ERR_R_INTERNAL_ERROR);
+        return 0;
+    }
+
+    return 1;
+}
+
 #ifndef OPENSSL_NO_EC
 int tls_construct_stoc_ec_pt_formats(SSL *s, WPACKET *pkt, unsigned int context,
                                      X509 *x, size_t chainidx, int *al)
@@ -1090,6 +1147,22 @@ int tls_construct_stoc_cryptopro_bug(SSL *s, WPACKET *pkt, unsigned int context,
     return 1;
 }
 
+int tls_construct_stoc_early_data(SSL *s, WPACKET *pkt, unsigned int context,
+                                  X509 *x, size_t chainidx, int *al)
+{
+    if (s->ext.early_data != SSL_EARLY_DATA_ACCEPTED)
+        return 1;
+
+    if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_early_data)
+            || !WPACKET_start_sub_packet_u16(pkt)
+            || !WPACKET_close(pkt)) {
+        SSLerr(SSL_F_TLS_CONSTRUCT_STOC_EARLY_DATA, ERR_R_INTERNAL_ERROR);
+        return 0;
+    }
+
+    return 1;
+}
+
 int tls_construct_stoc_psk(SSL *s, WPACKET *pkt, unsigned int context, X509 *x,
                            size_t chainidx, int *al)
 {
diff --git a/ssl/statem/statem.c b/ssl/statem/statem.c
index a1c5a21..11cbe55 100644
--- a/ssl/statem/statem.c
+++ b/ssl/statem/statem.c
@@ -151,6 +151,49 @@ void ossl_statem_set_in_handshake(SSL *s, int inhand)
         s->statem.in_handshake--;
 }
 
+/* Are we in a sensible state to skip over unreadable early data? */
+int ossl_statem_skip_early_data(SSL *s)
+{
+    if (s->ext.early_data != SSL_EARLY_DATA_REJECTED)
+        return 0;
+
+    if (s->hello_retry_request) {
+        if (s->statem.hand_state != TLS_ST_SW_HELLO_RETRY_REQUEST)
+            return 0;
+    } else {
+        if (!s->server || s->statem.hand_state != TLS_ST_EARLY_DATA)
+            return 0;
+    }
+
+    return 1;
+}
+
+/*
+ * Called when we are in SSL_read*(), SSL_write*(), or SSL_accept()
+ * /SSL_connect()/SSL_do_handshake(). Used to test whether we are in an early
+ * data state and whether we should attempt to move the handshake on if so.
+ * |send| is 1 if we are attempting to send data (SSL_write*()), 0 if we are
+ * attempting to read data (SSL_read*()), or -1 if we are in SSL_do_handshake()
+ * or similar.
+ */
+void ossl_statem_check_finish_init(SSL *s, int send)
+{
+    if (send == -1) {
+        if (s->statem.hand_state == TLS_ST_PENDING_EARLY_DATA_END
+                || s->statem.hand_state == TLS_ST_EARLY_DATA)
+            ossl_statem_set_in_init(s, 1);
+    } else if (!s->server) {
+        if ((send && s->statem.hand_state == TLS_ST_PENDING_EARLY_DATA_END
+                  && s->early_data_state != SSL_EARLY_DATA_WRITING)
+                || (!send && s->statem.hand_state == TLS_ST_EARLY_DATA))
+            ossl_statem_set_in_init(s, 1);
+    } else {
+        if (s->early_data_state == SSL_EARLY_DATA_FINISHED_READING
+                && s->statem.hand_state == TLS_ST_EARLY_DATA)
+            ossl_statem_set_in_init(s, 1);
+    }
+}
+
 void ossl_statem_set_hello_verify_done(SSL *s)
 {
     s->statem.state = MSG_FLOW_UNINITED;
@@ -313,7 +356,8 @@ static int state_machine(SSL *s, int server)
                 goto end;
             }
 
-        if (SSL_IS_FIRST_HANDSHAKE(s) || s->renegotiate) {
+        if ((SSL_in_before(s))
+                || s->renegotiate) {
             if (!tls_setup_handshake(s)) {
                 ossl_statem_set_error(s);
                 goto end;
@@ -717,8 +761,17 @@ static SUB_STATE_RETURN write_state_machine(SSL *s)
             case WORK_FINISHED_STOP:
                 return SUB_STATE_END_HANDSHAKE;
             }
+            if (!get_construct_message_f(s, &pkt, &confunc, &mt)) {
+                ossl_statem_set_error(s);
+                return SUB_STATE_ERROR;
+            }
+            if (mt == SSL3_MT_DUMMY) {
+                /* Skip construction and sending. This isn't a "real" state */
+                st->write_state = WRITE_STATE_POST_WORK;
+                st->write_state_work = WORK_MORE_A;
+                break;
+            }
             if (!WPACKET_init(&pkt, s->init_buf)
-                    || !get_construct_message_f(s, &pkt, &confunc, &mt)
                     || !ssl_set_handshake_header(s, &pkt, mt)
                     || (confunc != NULL && !confunc(s, &pkt))
                     || !ssl_close_construct_packet(s, &pkt, mt)
diff --git a/ssl/statem/statem.h b/ssl/statem/statem.h
index 906f2ec..56009b0 100644
--- a/ssl/statem/statem.h
+++ b/ssl/statem/statem.h
@@ -122,9 +122,12 @@ int ossl_statem_in_error(const SSL *s);
 void ossl_statem_set_in_init(SSL *s, int init);
 int ossl_statem_get_in_handshake(SSL *s);
 void ossl_statem_set_in_handshake(SSL *s, int inhand);
+__owur int ossl_statem_skip_early_data(SSL *s);
+void ossl_statem_check_finish_init(SSL *s, int send);
 void ossl_statem_set_hello_verify_done(SSL *s);
 __owur int ossl_statem_app_data_allowed(SSL *s);
 #ifndef OPENSSL_NO_SCTP
 void ossl_statem_set_sctp_read_sock(SSL *s, int read_sock);
 __owur int ossl_statem_in_sctp_read_sock(SSL *s);
 #endif
+int ossl_statem_finish_early_data(SSL *s);
diff --git a/ssl/statem/statem_clnt.c b/ssl/statem/statem_clnt.c
index abddc0a..b11cd19 100644
--- a/ssl/statem/statem_clnt.c
+++ b/ssl/statem/statem_clnt.c
@@ -124,11 +124,6 @@ static int ossl_statem_client13_read_transition(SSL *s, int mt)
     OSSL_STATEM *st = &s->statem;
 
     /*
-     * TODO(TLS1.3): This is still based on the TLSv1.2 state machine. Over time
-     * we will update this to look more like real TLSv1.3
-     */
-
-    /*
      * Note: There is no case for TLS_ST_CW_CLNT_HELLO, because we haven't
      * yet negotiated TLSv1.3 at that point so that is handled by
      * ossl_statem_client_read_transition()
@@ -258,6 +253,22 @@ int ossl_statem_client_read_transition(SSL *s, int mt)
         }
         break;
 
+    case TLS_ST_EARLY_DATA:
+        /*
+         * We've not actually selected TLSv1.3 yet, but we have sent early
+         * data. The only thing allowed now is a ServerHello or a
+         * HelloRetryRequest.
+         */
+        if (mt == SSL3_MT_SERVER_HELLO) {
+            st->hand_state = TLS_ST_CR_SRVR_HELLO;
+            return 1;
+        }
+        if (mt == SSL3_MT_HELLO_RETRY_REQUEST) {
+            st->hand_state = TLS_ST_CR_HELLO_RETRY_REQUEST;
+            return 1;
+        }
+        break;
+
     case TLS_ST_CR_SRVR_HELLO:
         if (s->hit) {
             if (s->ext.ticket_expected) {
@@ -424,6 +435,14 @@ static WRITE_TRAN ossl_statem_client13_write_transition(SSL *s)
         return WRITE_TRAN_CONTINUE;
 
     case TLS_ST_CR_FINISHED:
+        if (s->early_data_state == SSL_EARLY_DATA_WRITE_RETRY)
+            st->hand_state = TLS_ST_PENDING_EARLY_DATA_END;
+        else
+            st->hand_state = (s->s3->tmp.cert_req != 0) ? TLS_ST_CW_CERT
+                                                        : TLS_ST_CW_FINISHED;
+        return WRITE_TRAN_CONTINUE;
+
+    case TLS_ST_PENDING_EARLY_DATA_END:
         st->hand_state = (s->s3->tmp.cert_req != 0) ? TLS_ST_CW_CERT
                                                     : TLS_ST_CW_FINISHED;
         return WRITE_TRAN_CONTINUE;
@@ -449,7 +468,6 @@ static WRITE_TRAN ossl_statem_client13_write_transition(SSL *s)
     case TLS_ST_CR_SESSION_TICKET:
     case TLS_ST_CW_FINISHED:
         st->hand_state = TLS_ST_OK;
-        ossl_statem_set_in_init(s, 0);
         return WRITE_TRAN_CONTINUE;
 
     case TLS_ST_OK:
@@ -498,12 +516,23 @@ WRITE_TRAN ossl_statem_client_write_transition(SSL *s)
         return WRITE_TRAN_CONTINUE;
 
     case TLS_ST_CW_CLNT_HELLO:
+        if (s->early_data_state == SSL_EARLY_DATA_CONNECTING) {
+            /*
+             * We are assuming this is a TLSv1.3 connection, although we haven't
+             * actually selected a version yet.
+             */
+            st->hand_state = TLS_ST_EARLY_DATA;
+            return WRITE_TRAN_CONTINUE;
+        }
         /*
          * No transition at the end of writing because we don't know what
          * we will be sent
          */
         return WRITE_TRAN_FINISHED;
 
+    case TLS_ST_EARLY_DATA:
+        return WRITE_TRAN_FINISHED;
+
     case DTLS_ST_CR_HELLO_VERIFY_REQUEST:
         st->hand_state = TLS_ST_CW_CLNT_HELLO;
         return WRITE_TRAN_CONTINUE;
@@ -546,7 +575,8 @@ WRITE_TRAN ossl_statem_client_write_transition(SSL *s)
 
     case TLS_ST_CW_CHANGE:
 #if defined(OPENSSL_NO_NEXTPROTONEG)
-        st->hand_state = TLS_ST_CW_FINISHED;
+        st->
+        hand_state = TLS_ST_CW_FINISHED;
 #else
         if (!SSL_IS_DTLS(s) && s->s3->npn_seen)
             st->hand_state = TLS_ST_CW_NEXT_PROTO;
@@ -564,7 +594,6 @@ WRITE_TRAN ossl_statem_client_write_transition(SSL *s)
     case TLS_ST_CW_FINISHED:
         if (s->hit) {
             st->hand_state = TLS_ST_OK;
-            ossl_statem_set_in_init(s, 0);
             return WRITE_TRAN_CONTINUE;
         } else {
             return WRITE_TRAN_FINISHED;
@@ -576,7 +605,6 @@ WRITE_TRAN ossl_statem_client_write_transition(SSL *s)
             return WRITE_TRAN_CONTINUE;
         } else {
             st->hand_state = TLS_ST_OK;
-            ossl_statem_set_in_init(s, 0);
             return WRITE_TRAN_CONTINUE;
         }
 
@@ -594,7 +622,6 @@ WRITE_TRAN ossl_statem_client_write_transition(SSL *s)
             return WRITE_TRAN_CONTINUE;
         }
         st->hand_state = TLS_ST_OK;
-        ossl_statem_set_in_init(s, 0);
         return WRITE_TRAN_CONTINUE;
     }
 }
@@ -639,6 +666,8 @@ WORK_STATE ossl_statem_client_pre_work(SSL *s, WORK_STATE wst)
         }
         break;
 
+    case TLS_ST_EARLY_DATA:
+    case TLS_ST_PENDING_EARLY_DATA_END:
     case TLS_ST_OK:
         return tls_finish_handshake(s, wst, 1);
     }
@@ -669,6 +698,18 @@ WORK_STATE ossl_statem_client_post_work(SSL *s, WORK_STATE wst)
             /* Treat the next message as the first packet */
             s->first_packet = 1;
         }
+
+        if (s->early_data_state == SSL_EARLY_DATA_CONNECTING
+                && s->max_early_data > 0) {
+            /*
+             * We haven't selected TLSv1.3 yet so we don't call the change
+             * cipher state function associated with the SSL_METHOD. Instead
+             * we call tls13_change_cipher_state() directly.
+             */
+            if (!tls13_change_cipher_state(s,
+                        SSL3_CC_EARLY | SSL3_CHANGE_CIPHER_CLIENT_WRITE))
+                return WORK_ERROR;
+        }
         break;
 
     case TLS_ST_CW_KEY_EXCH:
@@ -999,9 +1040,6 @@ int tls_construct_client_hello(SSL *s, WPACKET *pkt)
     }
     /* else use the pre-loaded session */
 
-    /* This is a real handshake so make sure we clean it up at the end */
-    s->statem.cleanuphand = 1;
-
     p = s->s3->client_random;
 
     /*
@@ -1476,8 +1514,6 @@ MSG_PROCESS_RETURN tls_process_server_hello(SSL *s, PACKET *pkt)
     if (SSL_IS_TLS13(s)
             && (!s->method->ssl3_enc->setup_key_block(s)
                 || !s->method->ssl3_enc->change_cipher_state(s,
-                    SSL3_CC_HANDSHAKE | SSL3_CHANGE_CIPHER_CLIENT_WRITE)
-                || !s->method->ssl3_enc->change_cipher_state(s,
                     SSL3_CC_HANDSHAKE | SSL3_CHANGE_CIPHER_CLIENT_READ))) {
         al = SSL_AD_INTERNAL_ERROR;
         SSLerr(SSL_F_TLS_PROCESS_SERVER_HELLO, SSL_R_CANNOT_CHANGE_CIPHER);
@@ -3234,11 +3270,22 @@ int tls_construct_client_certificate(SSL *s, WPACKET *pkt)
                                                           : s->cert->key,
                                 &al)) {
         SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_CERTIFICATE, ERR_R_INTERNAL_ERROR);
-        ssl3_send_alert(s, SSL3_AL_FATAL, al);
-        return 0;
+        goto err;
+    }
+
+    if (SSL_IS_TLS13(s)
+            && SSL_IS_FIRST_HANDSHAKE(s)
+            && (!s->method->ssl3_enc->change_cipher_state(s,
+                    SSL3_CC_HANDSHAKE | SSL3_CHANGE_CIPHER_CLIENT_WRITE))) {
+        SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_CERTIFICATE,
+               SSL_R_CANNOT_CHANGE_CIPHER);
+        goto err;
     }
 
     return 1;
+ err:
+    ssl3_send_alert(s, SSL3_AL_FATAL, al);
+    return 0;
 }
 
 #define has_bits(i,m)   (((i)&(m)) == (m))
diff --git a/ssl/statem/statem_lib.c b/ssl/statem/statem_lib.c
index ed1ecce..32bcad4 100644
--- a/ssl/statem/statem_lib.c
+++ b/ssl/statem/statem_lib.c
@@ -442,6 +442,23 @@ int tls_construct_finished(SSL *s, WPACKET *pkt)
     const char *sender;
     size_t slen;
 
+    /* This is a real handshake so make sure we clean it up at the end */
+    if (!s->server)
+        s->statem.cleanuphand = 1;
+
+    /*
+     * We only change the keys if we didn't already do this when we sent the
+     * client certificate
+     */
+    if (SSL_IS_TLS13(s)
+            && !s->server
+            && s->s3->tmp.cert_req == 0
+            && (!s->method->ssl3_enc->change_cipher_state(s,
+                    SSL3_CC_HANDSHAKE | SSL3_CHANGE_CIPHER_CLIENT_WRITE))) {
+        SSLerr(SSL_F_TLS_CONSTRUCT_FINISHED, SSL_R_CANNOT_CHANGE_CIPHER);
+        goto err;
+    }
+
     if (s->server) {
         sender = s->method->ssl3_enc->server_finished_label;
         slen = s->method->ssl3_enc->server_finished_label_len;
@@ -654,6 +671,11 @@ MSG_PROCESS_RETURN tls_process_finished(SSL *s, PACKET *pkt)
     int al = SSL_AD_INTERNAL_ERROR;
     size_t md_len;
 
+
+    /* This is a real handshake so make sure we clean it up at the end */
+    if (s->server)
+        s->statem.cleanuphand = 1;
+
     /* If this occurs, we have missed a message */
     if (!SSL_IS_TLS13(s) && !s->s3->change_cipher_spec) {
         al = SSL_AD_UNEXPECTED_MESSAGE;
@@ -944,6 +966,7 @@ WORK_STATE tls_finish_handshake(SSL *s, WORK_STATE wst, int clearbufs)
             s->d1->next_handshake_write_seq = 0;
             dtls1_clear_received_buffer(s);
         }
+        s->early_data_state = SSL_EARLY_DATA_NONE;
     }
 
     /*
@@ -953,6 +976,7 @@ WORK_STATE tls_finish_handshake(SSL *s, WORK_STATE wst, int clearbufs)
     if (!clearbufs)
         return WORK_FINISHED_CONTINUE;
 
+    ossl_statem_set_in_init(s, 0);
     return WORK_FINISHED_STOP;
 }
 
diff --git a/ssl/statem/statem_locl.h b/ssl/statem/statem_locl.h
index 9230332..c52ce2b 100644
--- a/ssl/statem/statem_locl.h
+++ b/ssl/statem/statem_locl.h
@@ -53,6 +53,9 @@
 #define EXT_TLS1_3_CERTIFICATE              0x0800
 #define EXT_TLS1_3_NEW_SESSION_TICKET       0x1000
 
+/* Dummy message type */
+#define SSL3_MT_DUMMY   -1
+
 /* Message processing return codes */
 typedef enum {
     /* Something bad happened */
@@ -191,6 +194,8 @@ int tls_parse_ctos_server_name(SSL *s, PACKET *pkt, unsigned int context,
 int tls_parse_ctos_srp(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
                        size_t chainidx, int *al);
 #endif
+int tls_parse_ctos_early_data(SSL *s, PACKET *pkt, unsigned int context,
+                              X509 *x, size_t chainidx, int *al);
 #ifndef OPENSSL_NO_EC
 int tls_parse_ctos_ec_pt_formats(SSL *s, PACKET *pkt, unsigned int context,
                                  X509 *x, size_t chainidx, int *al);
@@ -230,6 +235,11 @@ int tls_construct_stoc_renegotiate(SSL *s, WPACKET *pkt, unsigned int context,
                                    X509 *x, size_t chainidx, int *al);
 int tls_construct_stoc_server_name(SSL *s, WPACKET *pkt, unsigned int context,
                                    X509 *x, size_t chainidx, int *al);
+int tls_construct_stoc_early_data_info(SSL *s, WPACKET *pkt,
+                                       unsigned int context, X509 *x,
+                                       size_t chainidx, int *al);
+int tls_construct_stoc_early_data(SSL *s, WPACKET *pkt, unsigned int context,
+                                  X509 *x, size_t chainidx, int *al);
 #ifndef OPENSSL_NO_EC
 int tls_construct_stoc_ec_pt_formats(SSL *s, WPACKET *pkt, unsigned int context,
                                      X509 *x, size_t chainidx, int *al);
@@ -285,6 +295,8 @@ int tls_construct_ctos_supported_groups(SSL *s, WPACKET *pkt,
                                         unsigned int context, X509 *x,
                                         size_t chainidx, int *al);
 #endif
+int tls_construct_ctos_early_data(SSL *s, WPACKET *pkt, unsigned int context,
+                                  X509 *x, size_t chainidx, int *al);
 int tls_construct_ctos_session_ticket(SSL *s, WPACKET *pkt,
                                       unsigned int context, X509 *x,
                                       size_t chainidx, int *al);
@@ -328,6 +340,10 @@ int tls_parse_stoc_renegotiate(SSL *s, PACKET *pkt, unsigned int context,
                                X509 *x, size_t chainidx, int *al);
 int tls_parse_stoc_server_name(SSL *s, PACKET *pkt, unsigned int context,
                                X509 *x, size_t chainidx, int *al);
+int tls_parse_stoc_early_data_info(SSL *s, PACKET *pkt, unsigned int context,
+                              X509 *x, size_t chainidx, int *al);
+int tls_parse_stoc_early_data(SSL *s, PACKET *pkt, unsigned int context,
+                              X509 *x, size_t chainidx, int *al);
 #ifndef OPENSSL_NO_EC
 int tls_parse_stoc_ec_pt_formats(SSL *s, PACKET *pkt, unsigned int context,
                                  X509 *x, size_t chainidx, int *al);
diff --git a/ssl/statem/statem_srvr.c b/ssl/statem/statem_srvr.c
index 39e0f59..7414c19 100644
--- a/ssl/statem/statem_srvr.c
+++ b/ssl/statem/statem_srvr.c
@@ -93,6 +93,7 @@ static int ossl_statem_server13_read_transition(SSL *s, int mt)
         }
         break;
 
+    case TLS_ST_EARLY_DATA:
     case TLS_ST_SW_FINISHED:
         if (s->s3->tmp.cert_request) {
             if (mt == SSL3_MT_CERTIFICATE) {
@@ -129,6 +130,12 @@ static int ossl_statem_server13_read_transition(SSL *s, int mt)
         break;
 
     case TLS_ST_OK:
+        /*
+         * Its never ok to start processing handshake messages in the middle of
+         * early data (i.e. before we've received the end of early data alert)
+         */
+        if (s->early_data_state == SSL_EARLY_DATA_READING)
+            break;
         if (mt == SSL3_MT_KEY_UPDATE) {
             st->hand_state = TLS_ST_SR_KEY_UPDATE;
             return 1;
@@ -450,6 +457,10 @@ static WRITE_TRAN ossl_statem_server13_write_transition(SSL *s)
         return WRITE_TRAN_CONTINUE;
 
     case TLS_ST_SW_FINISHED:
+        st->hand_state = TLS_ST_EARLY_DATA;
+        return WRITE_TRAN_CONTINUE;
+
+    case TLS_ST_EARLY_DATA:
         return WRITE_TRAN_FINISHED;
 
     case TLS_ST_SR_FINISHED:
@@ -474,7 +485,6 @@ static WRITE_TRAN ossl_statem_server13_write_transition(SSL *s)
     case TLS_ST_SW_KEY_UPDATE:
     case TLS_ST_SW_SESSION_TICKET:
         st->hand_state = TLS_ST_OK;
-        ossl_statem_set_in_init(s, 0);
         return WRITE_TRAN_CONTINUE;
     }
 }
@@ -520,7 +530,6 @@ WRITE_TRAN ossl_statem_server_write_transition(SSL *s)
 
     case TLS_ST_SW_HELLO_REQ:
         st->hand_state = TLS_ST_OK;
-        ossl_statem_set_in_init(s, 0);
         return WRITE_TRAN_CONTINUE;
 
     case TLS_ST_SR_CLNT_HELLO:
@@ -587,7 +596,6 @@ WRITE_TRAN ossl_statem_server_write_transition(SSL *s)
     case TLS_ST_SR_FINISHED:
         if (s->hit) {
             st->hand_state = TLS_ST_OK;
-            ossl_statem_set_in_init(s, 0);
             return WRITE_TRAN_CONTINUE;
         } else if (s->ext.ticket_expected) {
             st->hand_state = TLS_ST_SW_SESSION_TICKET;
@@ -609,7 +617,6 @@ WRITE_TRAN ossl_statem_server_write_transition(SSL *s)
             return WRITE_TRAN_FINISHED;
         }
         st->hand_state = TLS_ST_OK;
-        ossl_statem_set_in_init(s, 0);
         return WRITE_TRAN_CONTINUE;
     }
 }
@@ -693,6 +700,11 @@ WORK_STATE ossl_statem_server_pre_work(SSL *s, WORK_STATE wst)
         }
         return WORK_FINISHED_CONTINUE;
 
+    case TLS_ST_EARLY_DATA:
+        if (s->early_data_state != SSL_EARLY_DATA_ACCEPTING)
+            return WORK_FINISHED_CONTINUE;
+        /* Fall through */
+
     case TLS_ST_OK:
         return tls_finish_handshake(s, wst, 1);
     }
@@ -778,10 +790,13 @@ WORK_STATE ossl_statem_server_post_work(SSL *s, WORK_STATE wst)
         if (SSL_IS_TLS13(s)) {
             if (!s->method->ssl3_enc->setup_key_block(s)
                 || !s->method->ssl3_enc->change_cipher_state(s,
-                        SSL3_CC_HANDSHAKE | SSL3_CHANGE_CIPHER_SERVER_WRITE)
-                || !s->method->ssl3_enc->change_cipher_state(s,
+                        SSL3_CC_HANDSHAKE | SSL3_CHANGE_CIPHER_SERVER_WRITE))
+                return WORK_ERROR;
+
+            if (s->ext.early_data != SSL_EARLY_DATA_ACCEPTED
+                && !s->method->ssl3_enc->change_cipher_state(s,
                         SSL3_CC_HANDSHAKE |SSL3_CHANGE_CIPHER_SERVER_READ))
-            return WORK_ERROR;
+                return WORK_ERROR;
         }
         break;
 
@@ -934,6 +949,11 @@ int ossl_statem_server_construct_message(SSL *s, WPACKET *pkt,
         *mt = SSL3_MT_FINISHED;
         break;
 
+    case TLS_ST_EARLY_DATA:
+        *confunc = NULL;
+        *mt = SSL3_MT_DUMMY;
+        break;
+
     case TLS_ST_SW_ENCRYPTED_EXTENSIONS:
         *confunc = tls_construct_encrypted_extensions;
         *mt = SSL3_MT_ENCRYPTED_EXTENSIONS;
@@ -1095,6 +1115,15 @@ WORK_STATE ossl_statem_server_post_process_message(SSL *s, WORK_STATE wst)
     return WORK_FINISHED_CONTINUE;
 }
 
+int ossl_statem_finish_early_data(SSL *s)
+{
+    if (!s->method->ssl3_enc->change_cipher_state(s,
+                SSL3_CC_HANDSHAKE | SSL3_CHANGE_CIPHER_SERVER_READ))
+        return 0;
+
+    return 1;
+}
+
 #ifndef OPENSSL_NO_SRP
 static int ssl_check_srp_ext_ClientHello(SSL *s, int *al)
 {
@@ -1234,9 +1263,6 @@ MSG_PROCESS_RETURN tls_process_client_hello(SSL *s, PACKET *pkt)
         s->new_session = 1;
     }
 
-    /* This is a real handshake so make sure we clean it up at the end */
-    s->statem.cleanuphand = 1;
-
     /*
      * First, parse the raw ClientHello data into the CLIENTHELLO_MSG structure.
      */
@@ -3376,6 +3402,19 @@ int tls_construct_new_session_ticket(SSL *s, WPACKET *pkt)
         if (RAND_bytes(age_add_u.age_add_c, sizeof(age_add_u)) <= 0)
             goto err;
         s->session->ext.tick_age_add = age_add_u.age_add;
+        s->session->time = (long)time(NULL);
+        if (s->s3->alpn_selected != NULL) {
+            OPENSSL_free(s->session->ext.alpn_selected);
+            s->session->ext.alpn_selected =
+                OPENSSL_memdup(s->s3->alpn_selected, s->s3->alpn_selected_len);
+            if (s->session->ext.alpn_selected == NULL) {
+                SSLerr(SSL_F_TLS_CONSTRUCT_NEW_SESSION_TICKET,
+                       ERR_R_MALLOC_FAILURE);
+                goto err;
+            }
+            s->session->ext.alpn_selected_len = s->s3->alpn_selected_len;
+        }
+        s->session->ext.max_early_data = s->max_early_data;
     }
 
     /* get session encoding length */
@@ -3385,13 +3424,13 @@ int tls_construct_new_session_ticket(SSL *s, WPACKET *pkt)
      * long
      */
     if (slen_full == 0 || slen_full > 0xFF00) {
-        ossl_statem_set_error(s);
-        return 0;
+        SSLerr(SSL_F_TLS_CONSTRUCT_NEW_SESSION_TICKET, ERR_R_INTERNAL_ERROR);
+        goto err;
     }
     senc = OPENSSL_malloc(slen_full);
     if (senc == NULL) {
-        ossl_statem_set_error(s);
-        return 0;
+        SSLerr(SSL_F_TLS_CONSTRUCT_NEW_SESSION_TICKET, ERR_R_MALLOC_FAILURE);
+        goto err;
     }
 
     ctx = EVP_CIPHER_CTX_new();
@@ -3470,11 +3509,14 @@ int tls_construct_new_session_ticket(SSL *s, WPACKET *pkt)
     }
 
     /*
-     * Ticket lifetime hint (advisory only): We leave this unspecified
-     * for resumed session (for simplicity), and guess that tickets for
-     * new sessions will live as long as their sessions.
+     * Ticket lifetime hint: For TLSv1.2 this is advisory only and we leave this
+     * unspecified for resumed session (for simplicity).
+     * In TLSv1.3 we reset the "time" field above, and always specify the
+     * timeout.
      */
-    if (!WPACKET_put_bytes_u32(pkt, s->hit ? 0 : s->session->timeout)
+    if (!WPACKET_put_bytes_u32(pkt,
+                               (s->hit && !SSL_IS_TLS13(s))
+                               ? 0 : s->session->timeout)
             || (SSL_IS_TLS13(s)
                 && !WPACKET_put_bytes_u32(pkt, age_add_u.age_add))
                /* Now the actual ticket data */
@@ -3517,6 +3559,7 @@ int tls_construct_new_session_ticket(SSL *s, WPACKET *pkt)
 
     return 1;
  err:
+    ossl_statem_set_error(s);
     OPENSSL_free(senc);
     EVP_CIPHER_CTX_free(ctx);
     HMAC_CTX_free(hctx);
diff --git a/ssl/t1_enc.c b/ssl/t1_enc.c
index 4158548..2969b88 100644
--- a/ssl/t1_enc.c
+++ b/ssl/t1_enc.c
@@ -483,13 +483,7 @@ size_t tls1_final_finish_mac(SSL *s, const char *str, size_t slen,
 int tls1_generate_master_secret(SSL *s, unsigned char *out, unsigned char *p,
                                 size_t len, size_t *secret_size)
 {
-    /*
-     * TODO(TLS1.3): We haven't implemented TLS1.3 key derivation yet. For now
-     * we will just force no use of EMS (which adds complications around the
-     * handshake hash). This will need to be removed later
-     */
-    if ((s->session->flags & SSL_SESS_FLAG_EXTMS)
-            && !SSL_IS_TLS13(s)) {
+    if (s->session->flags & SSL_SESS_FLAG_EXTMS) {
         unsigned char hash[EVP_MAX_MD_SIZE * 2];
         size_t hashlen;
         /*
diff --git a/ssl/t1_trce.c b/ssl/t1_trce.c
index e99a2ce..5cfaacd 100644
--- a/ssl/t1_trce.c
+++ b/ssl/t1_trce.c
@@ -475,7 +475,9 @@ static ssl_trace_tbl ssl_exts_tbl[] = {
     {TLSEXT_TYPE_signed_certificate_timestamp, "signed_certificate_timestamps"},
     {TLSEXT_TYPE_padding, "padding"},
     {TLSEXT_TYPE_encrypt_then_mac, "encrypt_then_mac"},
-    {TLSEXT_TYPE_extended_master_secret, "extended_master_secret"}
+    {TLSEXT_TYPE_extended_master_secret, "extended_master_secret"},
+    {TLSEXT_TYPE_early_data_info, "ticket_early_data_info"},
+    {TLSEXT_TYPE_early_data, "early_data"}
 };
 
 static ssl_trace_tbl ssl_groups_tbl[] = {
@@ -680,6 +682,7 @@ static int ssl_print_extension(BIO *bio, int indent, int server,
 {
     size_t xlen, share_len;
     unsigned int sigalg;
+    uint32_t max_early_data;
 
     BIO_indent(bio, indent, 80);
     BIO_printf(bio, "extension_type=%s(%d), length=%d\n",
@@ -830,6 +833,15 @@ static int ssl_print_extension(BIO *bio, int indent, int server,
         return ssl_trace_list(bio, indent + 2, ext + 1, xlen, 1,
                               ssl_psk_kex_modes_tbl);
 
+    case TLSEXT_TYPE_early_data_info:
+        if (extlen != 4)
+            return 0;
+        max_early_data = (ext[0] << 24) | (ext[1] << 16) | (ext[2] << 8)
+                         | ext[3];
+        BIO_indent(bio, indent + 2, 80);
+        BIO_printf(bio, "max_early_data=%u\n", max_early_data);
+        break;
+
     default:
         BIO_dump_indent(bio, (const char *)ext, extlen, indent + 2);
     }
diff --git a/ssl/tls13_enc.c b/ssl/tls13_enc.c
index 6faa4e0..47d23bd 100644
--- a/ssl/tls13_enc.c
+++ b/ssl/tls13_enc.c
@@ -56,6 +56,7 @@ int tls13_hkdf_expand(SSL *s, const EVP_MD *md, const unsigned char *secret,
             || !WPACKET_sub_memcpy_u8(&pkt, hash, (hash == NULL) ? 0 : hashlen)
             || !WPACKET_get_total_written(&pkt, &hkdflabellen)
             || !WPACKET_finish(&pkt)) {
+        EVP_PKEY_CTX_free(pctx);
         WPACKET_cleanup(&pkt);
         return 0;
     }
@@ -77,26 +78,26 @@ int tls13_hkdf_expand(SSL *s, const EVP_MD *md, const unsigned char *secret,
  * Given a |secret| generate a |key| of length |keylen| bytes. Returns 1 on
  * success  0 on failure.
  */
-int tls13_derive_key(SSL *s, const unsigned char *secret, unsigned char *key,
-                     size_t keylen)
+int tls13_derive_key(SSL *s, const EVP_MD *md, const unsigned char *secret,
+                     unsigned char *key, size_t keylen)
 {
     static const unsigned char keylabel[] = "key";
 
-    return tls13_hkdf_expand(s, ssl_handshake_md(s), secret, keylabel,
-                             sizeof(keylabel) - 1, NULL, key, keylen);
+    return tls13_hkdf_expand(s, md, secret, keylabel, sizeof(keylabel) - 1,
+                             NULL, key, keylen);
 }
 
 /*
  * Given a |secret| generate an |iv| of length |ivlen| bytes. Returns 1 on
  * success  0 on failure.
  */
-int tls13_derive_iv(SSL *s, const unsigned char *secret, unsigned char *iv,
-                    size_t ivlen)
+int tls13_derive_iv(SSL *s, const EVP_MD *md, const unsigned char *secret,
+                    unsigned char *iv, size_t ivlen)
 {
     static const unsigned char ivlabel[] = "iv";
 
-    return tls13_hkdf_expand(s, ssl_handshake_md(s), secret, ivlabel,
-                             sizeof(ivlabel) - 1, NULL, iv, ivlen);
+    return tls13_hkdf_expand(s, md, secret, ivlabel, sizeof(ivlabel) - 1,
+                             NULL, iv, ivlen);
 }
 
 int tls13_derive_finishedkey(SSL *s, const EVP_MD *md,
@@ -242,7 +243,8 @@ int tls13_setup_key_block(SSL *s)
     return 1;
 }
 
-static int derive_secret_key_and_iv(SSL *s, int send,
+static int derive_secret_key_and_iv(SSL *s, int send, const EVP_MD *md,
+                                    const EVP_CIPHER *ciph,
                                     const unsigned char *insecret,
                                     const unsigned char *hash,
                                     const unsigned char *label,
@@ -251,9 +253,7 @@ static int derive_secret_key_and_iv(SSL *s, int send,
 {
     unsigned char key[EVP_MAX_KEY_LENGTH];
     size_t ivlen, keylen, taglen;
-    const EVP_MD *md = ssl_handshake_md(s);
     size_t hashlen = EVP_MD_size(md);
-    const EVP_CIPHER *ciph = s->s3->tmp.new_sym_enc;
 
     if (!tls13_hkdf_expand(s, md, insecret, label, labellen, hash, secret,
                            hashlen)) {
@@ -264,9 +264,16 @@ static int derive_secret_key_and_iv(SSL *s, int send,
     /* TODO(size_t): convert me */
     keylen = EVP_CIPHER_key_length(ciph);
     if (EVP_CIPHER_mode(ciph) == EVP_CIPH_CCM_MODE) {
+        uint32_t algenc;
+
         ivlen = EVP_CCM_TLS_IV_LEN;
-        if (s->s3->tmp.new_cipher->algorithm_enc
-                & (SSL_AES128CCM8 | SSL_AES256CCM8))
+        if (s->s3->tmp.new_cipher == NULL) {
+            /* We've not selected a cipher yet - we must be doing early data */
+            algenc = s->session->cipher->algorithm_enc;
+        } else {
+            algenc = s->s3->tmp.new_cipher->algorithm_enc;
+        }
+        if (algenc & (SSL_AES128CCM8 | SSL_AES256CCM8))
             taglen = EVP_CCM8_TLS_TAG_LEN;
          else
             taglen = EVP_CCM_TLS_TAG_LEN;
@@ -275,8 +282,8 @@ static int derive_secret_key_and_iv(SSL *s, int send,
         taglen = 0;
     }
 
-    if (!tls13_derive_key(s, secret, key, keylen)
-            || !tls13_derive_iv(s, secret, iv, ivlen)) {
+    if (!tls13_derive_key(s, md, secret, key, keylen)
+            || !tls13_derive_iv(s, md, secret, iv, ivlen)) {
         SSLerr(SSL_F_DERIVE_SECRET_KEY_AND_IV, ERR_R_INTERNAL_ERROR);
         goto err;
     }
@@ -312,6 +319,8 @@ static int derive_secret_key_and_iv(SSL *s, int send,
 
 int tls13_change_cipher_state(SSL *s, int which)
 {
+    static const unsigned char client_early_traffic[] =
+        "client early traffic secret";
     static const unsigned char client_handshake_traffic[] =
         "client handshake traffic secret";
     static const unsigned char client_application_traffic[] =
@@ -334,6 +343,8 @@ int tls13_change_cipher_state(SSL *s, int which)
     const unsigned char *label;
     size_t labellen, hashlen = 0;
     int ret = 0;
+    const EVP_MD *md;
+    const EVP_CIPHER *cipher;
 
     if (which & SSL3_CC_READ) {
         if (s->enc_read_ctx != NULL) {
@@ -367,13 +378,67 @@ int tls13_change_cipher_state(SSL *s, int which)
 
     if (((which & SSL3_CC_CLIENT) && (which & SSL3_CC_WRITE))
             || ((which & SSL3_CC_SERVER) && (which & SSL3_CC_READ))) {
-        if (which & SSL3_CC_HANDSHAKE) {
+        if (which & SSL3_CC_EARLY) {
+            EVP_MD_CTX *mdctx = NULL;
+            long handlen;
+            void *hdata;
+            unsigned int hashlenui;
+            const SSL_CIPHER *sslcipher = SSL_SESSION_get0_cipher(s->session);
+
+            insecret = s->early_secret;
+            label = client_early_traffic;
+            labellen = sizeof(client_early_traffic) - 1;
+            log_label = CLIENT_EARLY_LABEL;
+
+            handlen = BIO_get_mem_data(s->s3->handshake_buffer, &hdata);
+            if (handlen <= 0) {
+                SSLerr(SSL_F_TLS13_CHANGE_CIPHER_STATE,
+                       SSL_R_BAD_HANDSHAKE_LENGTH);
+                goto err;
+            }
+            if (sslcipher == NULL) {
+                SSLerr(SSL_F_TLS13_CHANGE_CIPHER_STATE, ERR_R_INTERNAL_ERROR);
+                goto err;
+            }
+
+            /*
+             * We need to calculate the handshake digest using the digest from
+             * the session. We haven't yet selected our ciphersuite so we can't
+             * use ssl_handshake_md().
+             */
+            mdctx = EVP_MD_CTX_new();
+            if (mdctx == NULL) {
+                SSLerr(SSL_F_TLS13_CHANGE_CIPHER_STATE, ERR_R_MALLOC_FAILURE);
+                goto err;
+            }
+            cipher = EVP_get_cipherbynid(SSL_CIPHER_get_cipher_nid(sslcipher));
+            md = ssl_md(sslcipher->algorithm2);
+            if (md == NULL || !EVP_DigestInit_ex(mdctx, md, NULL)
+                    || !EVP_DigestUpdate(mdctx, hdata, handlen)
+                    || !EVP_DigestFinal_ex(mdctx, hashval, &hashlenui)) {
+                SSLerr(SSL_F_TLS13_CHANGE_CIPHER_STATE, ERR_R_INTERNAL_ERROR);
+                EVP_MD_CTX_free(mdctx);
+                goto err;
+            }
+            hashlen = hashlenui;
+            EVP_MD_CTX_free(mdctx);
+        } else if (which & SSL3_CC_HANDSHAKE) {
             insecret = s->handshake_secret;
             finsecret = s->client_finished_secret;
             finsecretlen = EVP_MD_size(ssl_handshake_md(s));
             label = client_handshake_traffic;
             labellen = sizeof(client_handshake_traffic) - 1;
             log_label = CLIENT_HANDSHAKE_LABEL;
+            /*
+             * The hanshake hash used for the server read/client write handshake
+             * traffic secret is the same as the hash for the server
+             * write/client read handshake traffic secret. However, if we
+             * processed early data then we delay changing the server
+             * read/client write cipher state until later, and the handshake
+             * hashes have moved on. Therefore we use the value saved earlier
+             * when we did the server write/client read change cipher state.
+             */
+            hash = s->handshake_traffic_hash;
         } else {
             insecret = s->master_secret;
             label = client_application_traffic;
@@ -388,6 +453,7 @@ int tls13_change_cipher_state(SSL *s, int which)
             hash = s->server_finished_hash;
         }
     } else {
+        /* Early data never applies to client-read/server-write */
         if (which & SSL3_CC_HANDSHAKE) {
             insecret = s->handshake_secret;
             finsecret = s->server_finished_secret;
@@ -403,10 +469,14 @@ int tls13_change_cipher_state(SSL *s, int which)
         }
     }
 
-    if (!ssl3_digest_cached_records(s, 1)
-            || !ssl_handshake_hash(s, hashval, sizeof(hashval), &hashlen)) {
-        SSLerr(SSL_F_TLS13_CHANGE_CIPHER_STATE, ERR_R_INTERNAL_ERROR);
-        goto err;
+    if (!(which & SSL3_CC_EARLY)) {
+        md = ssl_handshake_md(s);
+        cipher = s->s3->tmp.new_sym_enc;
+        if (!ssl3_digest_cached_records(s, 1)
+                || !ssl_handshake_hash(s, hashval, sizeof(hashval), &hashlen)) {
+            SSLerr(SSL_F_TLS13_CHANGE_CIPHER_STATE, ERR_R_INTERNAL_ERROR);
+            goto err;
+        }
     }
 
     /*
@@ -416,6 +486,9 @@ int tls13_change_cipher_state(SSL *s, int which)
     if (label == server_application_traffic)
         memcpy(s->server_finished_hash, hashval, hashlen);
 
+    if (label == server_handshake_traffic)
+        memcpy(s->handshake_traffic_hash, hashval, hashlen);
+
     if (label == client_application_traffic) {
         /*
          * We also create the resumption master secret, but this time use the
@@ -431,8 +504,9 @@ int tls13_change_cipher_state(SSL *s, int which)
         s->session->master_key_length = hashlen;
     }
 
-    if (!derive_secret_key_and_iv(s, which & SSL3_CC_WRITE, insecret, hash,
-                                  label, labellen, secret, iv, ciph_ctx)) {
+    if (!derive_secret_key_and_iv(s, which & SSL3_CC_WRITE, md, cipher,
+                                  insecret, hash, label, labellen, secret, iv,
+                                  ciph_ctx)) {
         goto err;
     }
 
@@ -485,7 +559,9 @@ int tls13_update_key(SSL *s, int send)
         RECORD_LAYER_reset_read_sequence(&s->rlayer);
     }
 
-    if (!derive_secret_key_and_iv(s, send, insecret, NULL, application_traffic,
+    if (!derive_secret_key_and_iv(s, send, ssl_handshake_md(s),
+                                  s->s3->tmp.new_sym_enc, insecret, NULL,
+                                  application_traffic,
                                   sizeof(application_traffic) - 1, secret, iv,
                                   ciph_ctx))
         goto err;
@@ -500,7 +576,7 @@ int tls13_update_key(SSL *s, int send)
 
 int tls13_alert_code(int code)
 {
-    if (code == SSL_AD_MISSING_EXTENSION)
+    if (code == SSL_AD_MISSING_EXTENSION || code == SSL_AD_END_OF_EARLY_DATA)
         return code;
 
     return tls1_alert_code(code);
diff --git a/test/sslapitest.c b/test/sslapitest.c
index 4b5e8c0..1b96527 100644
--- a/test/sslapitest.c
+++ b/test/sslapitest.c
@@ -1537,6 +1537,652 @@ static int test_set_sigalgs(int idx)
     return testresult;
 }
 
+#ifndef OPENSSL_NO_TLS1_3
+
+#define MSG1    "Hello"
+#define MSG2    "World."
+#define MSG3    "This"
+#define MSG4    "is"
+#define MSG5    "a"
+#define MSG6    "test."
+
+/*
+ * Helper method to setup objects for early data test. Caller frees objects on
+ * error.
+ */
+static int setupearly_data_test(SSL_CTX **cctx, SSL_CTX **sctx, SSL **clientssl,
+                                SSL **serverssl, SSL_SESSION **sess)
+{
+    if (!create_ssl_ctx_pair(TLS_server_method(), TLS_client_method(), sctx,
+                             cctx, cert, privkey)) {
+        printf("Unable to create SSL_CTX pair\n");
+        return 0;
+    }
+
+    if (!create_ssl_objects(*sctx, *cctx, serverssl, clientssl, NULL, NULL)) {
+        printf("Unable to create SSL objects\n");
+        return 0;
+    }
+
+    if (!create_ssl_connection(*serverssl, *clientssl, SSL_ERROR_NONE)) {
+        printf("Unable to create SSL connection\n");
+        return 0;
+    }
+
+    *sess = SSL_get1_session(*clientssl);
+
+    SSL_shutdown(*clientssl);
+    SSL_shutdown(*serverssl);
+
+    SSL_free(*serverssl);
+    SSL_free(*clientssl);
+    *serverssl = *clientssl = NULL;
+
+    if (!create_ssl_objects(*sctx, *cctx, serverssl, clientssl, NULL, NULL)) {
+        printf("Unable to create SSL objects (2)\n");
+        return 0;
+    }
+
+    if (!SSL_set_session(*clientssl, *sess)) {
+        printf("Failed setting session\n");
+        return 0;
+    }
+
+    return 1;
+}
+
+static int test_early_data_read_write(void)
+{
+    SSL_CTX *cctx = NULL, *sctx = NULL;
+    SSL *clientssl = NULL, *serverssl = NULL;
+    int testresult = 0;
+    SSL_SESSION *sess = NULL;
+    unsigned char buf[20];
+    size_t readbytes, written;
+
+    if (!setupearly_data_test(&cctx, &sctx, &clientssl, &serverssl, &sess))
+        goto end;
+
+    /* Write and read some early data */
+    if (!SSL_write_early_data(clientssl, MSG1, strlen(MSG1), &written)
+            || written != strlen(MSG1)) {
+        printf("Failed writing early data message 1\n");
+        goto end;
+    }
+
+    if (SSL_read_early_data(serverssl, buf, sizeof(buf), &readbytes)
+                != SSL_READ_EARLY_DATA_SUCCESS
+            || readbytes != strlen(MSG1)
+            || memcmp(MSG1, buf, strlen(MSG1))) {
+        printf("Failed reading early data message 1\n");
+        goto end;
+    }
+
+    if (SSL_get_early_data_status(serverssl) != SSL_EARLY_DATA_ACCEPTED) {
+        printf("Unexpected early data status\n");
+        goto end;
+    }
+
+    /*
+     * Server should be able to write data, and client should be able to
+     * read it.
+     */
+    if (!SSL_write_early_data(serverssl, MSG2, strlen(MSG2), &written)
+            || written != strlen(MSG2)) {
+        printf("Failed writing message 2\n");
+        goto end;
+    }
+
+    if (!SSL_read_ex(clientssl, buf, sizeof(buf), &readbytes)
+            || readbytes != strlen(MSG2)
+            || memcmp(MSG2, buf, strlen(MSG2))) {
+        printf("Failed reading message 2\n");
+        goto end;
+    }
+
+    /* Even after reading normal data, client should be able write early data */
+    if (!SSL_write_early_data(clientssl, MSG3, strlen(MSG3), &written)
+            || written != strlen(MSG3)) {
+        printf("Failed writing early data message 3\n");
+        goto end;
+    }
+
+    /* Server should still be able read early data after writing data */
+    if (SSL_read_early_data(serverssl, buf, sizeof(buf), &readbytes)
+                != SSL_READ_EARLY_DATA_SUCCESS
+            || readbytes != strlen(MSG3)
+            || memcmp(MSG3, buf, strlen(MSG3))) {
+        printf("Failed reading early data message 3\n");
+        goto end;
+    }
+
+    /* Write more data from server and read it from client */
+    if (!SSL_write_early_data(serverssl, MSG4, strlen(MSG4), &written)
+            || written != strlen(MSG4)) {
+        printf("Failed writing message 4\n");
+        goto end;
+    }
+
+    if (!SSL_read_ex(clientssl, buf, sizeof(buf), &readbytes)
+            || readbytes != strlen(MSG4)
+            || memcmp(MSG4, buf, strlen(MSG4))) {
+        printf("Failed reading message 4\n");
+        goto end;
+    }
+
+    /*
+     * If client writes normal data it should mean writing early data is no
+     * longer possible.
+     */
+    if (!SSL_write_ex(clientssl, MSG5, strlen(MSG5), &written)
+            || written != strlen(MSG5)) {
+        printf("Failed writing message 5\n");
+        goto end;
+    }
+
+    if (SSL_get_early_data_status(clientssl) != SSL_EARLY_DATA_ACCEPTED) {
+        printf("Unexpected early data status(2)\n");
+        goto end;
+    }
+
+    /* Server should be told that there is no more early data */
+    if (SSL_read_early_data(serverssl, buf, sizeof(buf), &readbytes)
+                != SSL_READ_EARLY_DATA_FINISH
+            || readbytes != 0) {
+        printf("Failed finishing read of early data\n");
+        goto end;
+    }
+
+    /* Server should be able to read normal data */
+    if (!SSL_read_ex(serverssl, buf, sizeof(buf), &readbytes)
+            || readbytes != strlen(MSG5)) {
+        printf("Failed reading message 5\n");
+        goto end;
+    }
+
+    /* Client and server should not be able to write/read early data now */
+    if (SSL_write_early_data(clientssl, MSG6, strlen(MSG6), &written)) {
+        printf("Unexpected success writing early data\n");
+        goto end;
+    }
+    ERR_clear_error();
+
+    if (SSL_read_early_data(serverssl, buf, sizeof(buf), &readbytes)
+                != SSL_READ_EARLY_DATA_ERROR) {
+        printf("Unexpected success reading early data\n");
+        goto end;
+    }
+    ERR_clear_error();
+
+    /*
+     * Make sure we process the NewSessionTicket. This arrives post-handshake
+     * so we must make sure we attempt a read - even though we don't expect to
+     * actually get any application data.
+     */
+    if (SSL_read_ex(clientssl, buf, sizeof(buf), &readbytes)) {
+        printf("Unexpected success doing final client read\n");
+        goto end;
+    }
+
+    SSL_SESSION_free(sess);
+    sess = SSL_get1_session(clientssl);
+
+    SSL_shutdown(clientssl);
+    SSL_shutdown(serverssl);
+
+    SSL_free(serverssl);
+    SSL_free(clientssl);
+    serverssl = clientssl = NULL;
+
+    if (!create_ssl_objects(sctx, cctx, &serverssl, &clientssl, NULL, NULL)) {
+        printf("Unable to create SSL objects (3)\n");
+        goto end;
+    }
+
+    if (!SSL_set_session(clientssl, sess)) {
+        printf("Failed setting session (2)\n");
+        goto end;
+    }
+
+    /* Write and read some early data */
+    if (!SSL_write_early_data(clientssl, MSG1, strlen(MSG1), &written)
+            || written != strlen(MSG1)) {
+        printf("Failed writing early data message 1\n");
+        goto end;
+    }
+
+    if (SSL_read_early_data(serverssl, buf, sizeof(buf), &readbytes)
+                != SSL_READ_EARLY_DATA_SUCCESS
+            || readbytes != strlen(MSG1)
+            || memcmp(MSG1, buf, strlen(MSG1))) {
+        printf("Failed reading early data message 1\n");
+        goto end;
+    }
+
+    if (SSL_connect(clientssl) <= 0) {
+        printf("Unable to complete client handshake\n");
+        goto end;
+    }
+
+    /*
+     * We expect SSL_accept() to initially block as it handles the end of early
+     * data alert
+     */
+    if (SSL_accept(serverssl) > 0) {
+        printf("Unexpected success completing server handshake\n");
+        goto end;
+    }
+
+    if (SSL_accept(serverssl) <= 0) {
+        printf("Unable to complete server handshake\n");
+        goto end;
+    }
+
+    /* Client and server should not be able to write/read early data now */
+    if (SSL_write_early_data(clientssl, MSG6, strlen(MSG6), &written)) {
+        printf("Unexpected success writing early data (2)\n");
+        goto end;
+    }
+    ERR_clear_error();
+
+    if (SSL_read_early_data(serverssl, buf, sizeof(buf), &readbytes)
+                != SSL_READ_EARLY_DATA_ERROR) {
+        printf("Unexpected success reading early data (2)\n");
+        goto end;
+    }
+    ERR_clear_error();
+
+    /* Client and server should be able to write/read normal data */
+    if (!SSL_write_ex(clientssl, MSG5, strlen(MSG5), &written)
+            || written != strlen(MSG5)) {
+        printf("Failed writing message 5 (2)\n");
+        goto end;
+    }
+
+    if (!SSL_read_ex(serverssl, buf, sizeof(buf), &readbytes)
+            || readbytes != strlen(MSG5)) {
+        printf("Failed reading message 5 (2)\n");
+        goto end;
+    }
+
+    testresult = 1;
+
+ end:
+    if(!testresult)
+        ERR_print_errors_fp(stdout);
+    SSL_SESSION_free(sess);
+    SSL_free(serverssl);
+    SSL_free(clientssl);
+    SSL_CTX_free(sctx);
+    SSL_CTX_free(cctx);
+
+    return testresult;
+}
+
+static int test_early_data_skip(void)
+{
+    SSL_CTX *cctx = NULL, *sctx = NULL;
+    SSL *clientssl = NULL, *serverssl = NULL;
+    int testresult = 0;
+    SSL_SESSION *sess;
+    unsigned char buf[20];
+    size_t readbytes, written;
+
+    /*
+     * Test that a server attempting to read early data can handle a connection
+     * from a client where the early data is not acceptable.
+     */
+
+    if (!setupearly_data_test(&cctx, &sctx, &clientssl, &serverssl, &sess))
+        goto end;
+
+    /*
+     * Deliberately corrupt the creation time. We take 20 seconds off the time.
+     * It could be any value as long as it is not within tolerance. This should
+     * mean the ticket is rejected.
+     */
+    if (!SSL_SESSION_set_time(sess, time(NULL) - 20)) {
+        printf("Unexpected failure setting session creation time\n");
+        goto end;
+    }
+
+    /* Write some early data */
+    if (!SSL_write_early_data(clientssl, MSG1, strlen(MSG1), &written)
+            || written != strlen(MSG1)) {
+        printf("Failed writing early data message 1\n");
+        goto end;
+    }
+
+    /* Server should reject the early data and skip over it */
+    if (SSL_read_early_data(serverssl, buf, sizeof(buf), &readbytes)
+                != SSL_READ_EARLY_DATA_FINISH
+            || readbytes != 0) {
+        printf("Failed reading early data\n");
+        goto end;
+    }
+
+    if (SSL_get_early_data_status(serverssl) != SSL_EARLY_DATA_REJECTED) {
+        printf("Unexpected early data status\n");
+        goto end;
+    }
+
+    /*
+     * We should be able to send normal data despite rejection of early data
+     */
+    if (!SSL_write_ex(clientssl, MSG2, strlen(MSG2), &written)
+            || written != strlen(MSG2)) {
+        printf("Failed writing message 2\n");
+        goto end;
+    }
+
+    if (SSL_get_early_data_status(clientssl) != SSL_EARLY_DATA_REJECTED) {
+        printf("Unexpected early data status (2)\n");
+        goto end;
+    }
+
+    if (!SSL_read_ex(serverssl, buf, sizeof(buf), &readbytes)
+            || readbytes != strlen(MSG2)
+            || memcmp(MSG2, buf, strlen(MSG2))) {
+        printf("Failed reading message 2\n");
+        goto end;
+    }
+
+    testresult = 1;
+
+ end:
+    if(!testresult)
+        ERR_print_errors_fp(stdout);
+    SSL_SESSION_free(sess);
+    SSL_free(serverssl);
+    SSL_free(clientssl);
+    SSL_CTX_free(sctx);
+    SSL_CTX_free(cctx);
+
+    return testresult;
+}
+
+static int test_early_data_not_sent(void)
+{
+    SSL_CTX *cctx = NULL, *sctx = NULL;
+    SSL *clientssl = NULL, *serverssl = NULL;
+    int testresult = 0;
+    SSL_SESSION *sess;
+    unsigned char buf[20];
+    size_t readbytes, written;
+
+    /*
+     * Test that a server attempting to read early data can handle a connection
+     * from a client that doesn't send any.
+     */
+
+    if (!setupearly_data_test(&cctx, &sctx, &clientssl, &serverssl, &sess))
+        goto end;
+
+    /* Write some data - should block due to handshake with server */
+    SSL_set_connect_state(clientssl);
+    if (SSL_write_ex(clientssl, MSG1, strlen(MSG1), &written)) {
+        printf("Unexpected success writing message 1\n");
+        goto end;
+    }
+
+    /* Server should detect that early data has not been sent */
+    if (SSL_read_early_data(serverssl, buf, sizeof(buf), &readbytes)
+                != SSL_READ_EARLY_DATA_FINISH
+            || readbytes != 0) {
+        printf("Failed reading early data\n");
+        goto end;
+    }
+
+    if (SSL_get_early_data_status(serverssl) != SSL_EARLY_DATA_NOT_SENT) {
+        printf("Unexpected early data status\n");
+        goto end;
+    }
+
+    if (SSL_get_early_data_status(clientssl) != SSL_EARLY_DATA_NOT_SENT) {
+        printf("Unexpected early data status (2)\n");
+        goto end;
+    }
+
+    /* Continue writing the message we started earlier */
+    if (!SSL_write_ex(clientssl, MSG1, strlen(MSG1), &written)
+            || written != strlen(MSG1)) {
+        printf("Failed writing message 1\n");
+        goto end;
+    }
+
+    if (!SSL_read_ex(serverssl, buf, sizeof(buf), &readbytes)
+            || readbytes != strlen(MSG1)
+            || memcmp(MSG1, buf, strlen(MSG1))) {
+        printf("Failed reading message 1\n");
+        goto end;
+    }
+
+    if (!SSL_write_ex(serverssl, MSG2, strlen(MSG2), &written)
+            || written != strlen(MSG2)) {
+        printf("Failed writing message 2\n");
+        goto end;
+    }
+
+    /* Should block due to the NewSessionTicket arrival */
+    if (SSL_read_ex(clientssl, buf, sizeof(buf), &readbytes)) {
+        printf("Unexpected success reading message 2\n");
+        goto end;
+    }
+
+    if (!SSL_read_ex(clientssl, buf, sizeof(buf), &readbytes)
+            || readbytes != strlen(MSG2)
+            || memcmp(MSG2, buf, strlen(MSG2))) {
+        printf("Failed reading message 2\n");
+        goto end;
+    }
+
+    testresult = 1;
+
+ end:
+    if(!testresult)
+        ERR_print_errors_fp(stdout);
+    SSL_SESSION_free(sess);
+    SSL_free(serverssl);
+    SSL_free(clientssl);
+    SSL_CTX_free(sctx);
+    SSL_CTX_free(cctx);
+
+    return testresult;
+}
+
+static int test_early_data_not_expected(void)
+{
+    SSL_CTX *cctx = NULL, *sctx = NULL;
+    SSL *clientssl = NULL, *serverssl = NULL;
+    int testresult = 0;
+    SSL_SESSION *sess;
+    unsigned char buf[20];
+    size_t readbytes, written;
+
+    /*
+     * Test that a server that doesn't try to read early data can handle a
+     * client sending some.
+     */
+
+    if (!setupearly_data_test(&cctx, &sctx, &clientssl, &serverssl, &sess))
+        goto end;
+
+    /* Write some early data */
+    if (!SSL_write_early_data(clientssl, MSG1, strlen(MSG1), &written)) {
+        printf("Unexpected failure writing message 1\n");
+        goto end;
+    }
+
+    /*
+     * Server should skip over early data and then block waiting for client to
+     * continue handshake
+     */
+    if (SSL_accept(serverssl) > 0) {
+        printf("Unexpected success setting up server connection\n");
+        goto end;
+    }
+
+    if (SSL_connect(clientssl) <= 0) {
+        printf("Failed setting up client connection\n");
+        goto end;
+    }
+
+    if (SSL_get_early_data_status(serverssl) != SSL_EARLY_DATA_REJECTED) {
+        printf("Unexpected early data status\n");
+        goto end;
+    }
+
+    if (SSL_accept(serverssl) <= 0) {
+        printf("Failed setting up server connection\n");
+        goto end;
+    }
+
+    if (SSL_get_early_data_status(clientssl) != SSL_EARLY_DATA_REJECTED) {
+        printf("Unexpected early data status (2)\n");
+        goto end;
+    }
+
+    /* Send some normal data from client to server */
+    if (!SSL_write_ex(clientssl, MSG2, strlen(MSG2), &written)
+            || written != strlen(MSG2)) {
+        printf("Failed writing message 2\n");
+        goto end;
+    }
+
+    if (!SSL_read_ex(serverssl, buf, sizeof(buf), &readbytes)
+            || readbytes != strlen(MSG2)
+            || memcmp(MSG2, buf, strlen(MSG2))) {
+        printf("Failed reading message 2\n");
+        goto end;
+    }
+
+    testresult = 1;
+
+ end:
+    if(!testresult)
+        ERR_print_errors_fp(stdout);
+    SSL_SESSION_free(sess);
+    SSL_free(serverssl);
+    SSL_free(clientssl);
+    SSL_CTX_free(sctx);
+    SSL_CTX_free(cctx);
+
+    return testresult;
+}
+
+
+# ifndef OPENSSL_NO_TLS1_2
+static int test_early_data_tls1_2(void)
+{
+    SSL_CTX *cctx = NULL, *sctx = NULL;
+    SSL *clientssl = NULL, *serverssl = NULL;
+    int testresult = 0;
+    unsigned char buf[20];
+    size_t readbytes, written;
+
+    /*
+     * Test that a server attempting to read early data can handle a connection
+     * from a TLSv1.2 client.
+     */
+
+    if (!create_ssl_ctx_pair(TLS_server_method(), TLS_client_method(), &sctx,
+                             &cctx, cert, privkey)) {
+        printf("Unable to create SSL_CTX pair\n");
+        goto end;
+    }
+
+    if (!create_ssl_objects(sctx, cctx, &serverssl, &clientssl, NULL, NULL)) {
+        printf("Unable to create SSL objects\n");
+        goto end;
+    }
+
+    /* Write some data - should block due to handshake with server */
+    SSL_set_max_proto_version(clientssl, TLS1_2_VERSION);
+    SSL_set_connect_state(clientssl);
+    if (SSL_write_ex(clientssl, MSG1, strlen(MSG1), &written)) {
+        printf("Unexpected success writing message 1\n");
+        goto end;
+    }
+
+    /*
+     * Server should do TLSv1.2 handshake. First it will block waiting for more
+     * messages from client after ServerDone. Then SSL_read_early_data should
+     * finish and detect that early data has not been sent
+     */
+    if (SSL_read_early_data(serverssl, buf, sizeof(buf), &readbytes)
+                != SSL_READ_EARLY_DATA_ERROR) {
+        printf("Unexpected success reading early data\n");
+        goto end;
+    }
+
+    /*
+     * Continue writing the message we started earlier. Will still block waiting
+     * for the CCS/Finished from server
+     */
+    if (SSL_write_ex(clientssl, MSG1, strlen(MSG1), &written)) {
+        printf("Unexpected success writing message 1\n");
+        goto end;
+    }
+
+    if (SSL_read_early_data(serverssl, buf, sizeof(buf), &readbytes)
+                != SSL_READ_EARLY_DATA_FINISH
+            || readbytes != 0) {
+        printf("Failed reading early data\n");
+        goto end;
+    }
+
+    if (SSL_get_early_data_status(serverssl) != SSL_EARLY_DATA_NOT_SENT) {
+        printf("Unexpected early data status\n");
+        goto end;
+    }
+
+    /* Continue writing the message we started earlier */
+    if (!SSL_write_ex(clientssl, MSG1, strlen(MSG1), &written)
+            || written != strlen(MSG1)) {
+        printf("Failed writing message 1\n");
+        goto end;
+    }
+
+    if (SSL_get_early_data_status(clientssl) != SSL_EARLY_DATA_NOT_SENT) {
+        printf("Unexpected early data status (2)\n");
+        goto end;
+    }
+
+    if (!SSL_read_ex(serverssl, buf, sizeof(buf), &readbytes)
+            || readbytes != strlen(MSG1)
+            || memcmp(MSG1, buf, strlen(MSG1))) {
+        printf("Failed reading message 1\n");
+        goto end;
+    }
+
+    if (!SSL_write_ex(serverssl, MSG2, strlen(MSG2), &written)
+            || written != strlen(MSG2)) {
+        printf("Failed writing message 2\n");
+        goto end;
+    }
+
+    if (!SSL_read_ex(clientssl, buf, sizeof(buf), &readbytes)
+            || readbytes != strlen(MSG2)
+            || memcmp(MSG2, buf, strlen(MSG2))) {
+        printf("Failed reading message 2\n");
+        goto end;
+    }
+
+    testresult = 1;
+
+ end:
+    if(!testresult)
+        ERR_print_errors_fp(stdout);
+    SSL_free(serverssl);
+    SSL_free(clientssl);
+    SSL_CTX_free(sctx);
+    SSL_CTX_free(cctx);
+
+    return testresult;
+}
+# endif
+#endif
+
 int test_main(int argc, char *argv[])
 {
     int testresult = 1;
@@ -1573,6 +2219,15 @@ int test_main(int argc, char *argv[])
 #ifndef OPENSSL_NO_TLS1_2
     ADD_TEST(test_early_cb);
 #endif
+#ifndef OPENSSL_NO_TLS1_3
+    ADD_TEST(test_early_data_read_write);
+    ADD_TEST(test_early_data_skip);
+    ADD_TEST(test_early_data_not_sent);
+    ADD_TEST(test_early_data_not_expected);
+# ifndef OPENSSL_NO_TLS1_2
+    ADD_TEST(test_early_data_tls1_2);
+# endif
+#endif
 
     testresult = run_tests(argv[0]);
 
diff --git a/test/tls13secretstest.c b/test/tls13secretstest.c
index 7f177bf..55424b1 100644
--- a/test/tls13secretstest.c
+++ b/test/tls13secretstest.c
@@ -192,6 +192,11 @@ int ssl_log_secret(SSL *ssl,
     return 1;
 }
 
+const EVP_MD *ssl_md(int idx)
+{
+    return EVP_sha256();
+}
+
 /* End of mocked out code */
 
 static int test_secret(SSL *s, unsigned char *prk,
@@ -222,7 +227,7 @@ static int test_secret(SSL *s, unsigned char *prk,
         return 0;
     }
 
-    if (!tls13_derive_key(s, gensecret, key, KEYLEN)) {
+    if (!tls13_derive_key(s, md, gensecret, key, KEYLEN)) {
         fprintf(stderr, "Key generation failed\n");
         return 0;
     }
@@ -232,7 +237,7 @@ static int test_secret(SSL *s, unsigned char *prk,
         return 0;
     }
 
-    if (!tls13_derive_iv(s, gensecret, iv, IVLEN)) {
+    if (!tls13_derive_iv(s, md, gensecret, iv, IVLEN)) {
         fprintf(stderr, "IV generation failed\n");
         return 0;
     }
diff --git a/util/libssl.num b/util/libssl.num
index 20642ce..3c024e4 100644
--- a/util/libssl.num
+++ b/util/libssl.num
@@ -424,3 +424,11 @@ SSL_early_get0_random                   424	1_1_1	EXIST::FUNCTION:
 SSL_CTX_set_early_cb                    425	1_1_1	EXIST::FUNCTION:
 SSL_early_get0_legacy_version           426	1_1_1	EXIST::FUNCTION:
 SSL_early_isv2                          427	1_1_1	EXIST::FUNCTION:
+SSL_set_max_early_data                  428	1_1_1	EXIST::FUNCTION:
+SSL_CTX_set_max_early_data              429	1_1_1	EXIST::FUNCTION:
+SSL_get_max_early_data                  430	1_1_1	EXIST::FUNCTION:
+SSL_CTX_get_max_early_data              431	1_1_1	EXIST::FUNCTION:
+SSL_write_early_data                    432	1_1_1	EXIST::FUNCTION:
+SSL_read_early_data                     433	1_1_1	EXIST::FUNCTION:
+SSL_get_early_data_status               434	1_1_1	EXIST::FUNCTION:
+SSL_SESSION_get_max_early_data          435	1_1_1	EXIST::FUNCTION:


More information about the openssl-commits mailing list